From 693f4c70ffc8422bf053cae3e685d0f2620ddf7a Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 10 Feb 2021 08:29:46 -0500 Subject: [PATCH 0001/1519] Begin post-3.20 development --- .gitlab-ci.yml | 10 +++++----- Help/release/dev/0-sample-topic.rst | 7 +++++++ Help/release/index.rst | 2 ++ Source/CMakeVersion.cmake | 4 ++-- 4 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/0-sample-topic.rst diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a322aa69234..672df5ab625 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,7 @@ prep:doc-package: - .cmake_doc_artifacts - .run_only_for_package -.upload:source-package: +upload:source-package: extends: - .rsync_upload - .run_only_for_package @@ -199,7 +199,7 @@ build:linux-x86_64-package: needs: - prep:doc-package -.upload:linux-x86_64-package: +upload:linux-x86_64-package: extends: - .rsync_upload - .run_only_for_package @@ -223,7 +223,7 @@ build:linux-aarch64-package: needs: - prep:doc-package -.upload:linux-aarch64-package: +upload:linux-aarch64-package: extends: - .rsync_upload - .run_only_for_package @@ -298,7 +298,7 @@ build:macos-package: needs: - prep:doc-package -.upload:macos-package: +upload:macos-package: extends: - .rsync_upload - .run_only_for_package @@ -321,7 +321,7 @@ build:macos10.10-package: needs: - prep:doc-package -.upload:macos10.10-package: +upload:macos10.10-package: extends: - .rsync_upload - .run_only_for_package diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst new file mode 100644 index 00000000000..e4cc01e23fe --- /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/index.rst b/Help/release/index.rst index 95b41fb63b4..5dfca051be6 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -7,6 +7,8 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. +.. include:: dev.txt + Releases ======== diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d32de375724..b3b7d9421a9 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,8 +1,8 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 0) +set(CMake_VERSION_PATCH 20210210) +#set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 58ea0d12558b5607e81b1dfab1528bdf45393b3d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 10 Feb 2021 09:01:04 -0500 Subject: [PATCH 0002/1519] Add deprecation warnings for policies CMP0081 and below The OLD behaviors of all policies are deprecated, but only by documentation. Add an explicit deprecation diagnostic for policies introduced in CMake 3.13 and below to encourage projects to port away from setting policies to OLD. --- Source/cmMakefile.cxx | 2 +- .../CMP0080-COMMAND-OLD-stderr.txt | 9 +++++++ .../BundleUtilities/CMP0080-OLD-stderr.txt | 10 ++++++++ Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt | 1 - Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt | 10 ++++++++ Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt | 24 +++++++++++++++++++ Tests/RunCMake/option/CMP0077-OLD-stderr.txt | 10 ++++++++ .../CMP0079-iface-OLD-stderr.txt | 10 ++++++++ .../CMP0079-link-OLD-stderr.txt | 13 +++++++++- 9 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt create mode 100644 Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt delete mode 100644 Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt create mode 100644 Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt create mode 100644 Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt create mode 100644 Tests/RunCMake/option/CMP0077-OLD-stderr.txt create mode 100644 Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e4859864c6a..b3bab04a0fa 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4387,7 +4387,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0075 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. diff --git a/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt b/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt new file mode 100644 index 00000000000..31a0207fb80 --- /dev/null +++ b/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND-OLD-stderr.txt @@ -0,0 +1,9 @@ +^CMake Deprecation Warning at [^ +]*/Tests/RunCMake/BundleUtilities/CMP0080-COMMAND.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0080 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/BundleUtilities/CMP0080-OLD-stderr.txt b/Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt new file mode 100644 index 00000000000..2ff5d6035a7 --- /dev/null +++ b/Tests/RunCMake/BundleUtilities/CMP0080-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0080-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0080 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/CMP0081/CMP0081-OLD-result.txt b/Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt deleted file mode 100644 index 573541ac970..00000000000 --- a/Tests/RunCMake/CMP0081/CMP0081-OLD-result.txt +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt b/Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt new file mode 100644 index 00000000000..ff339fa04b1 --- /dev/null +++ b/Tests/RunCMake/CMP0081/CMP0081-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0081-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0081 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/UseSWIG/CMP0078-OLD-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt new file mode 100644 index 00000000000..e8eadedd518 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt @@ -0,0 +1,24 @@ +^CMake Deprecation Warning at CMP0078-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0078 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\) ++ +CMake Deprecation Warning at [^ +]*/Modules/UseSWIG.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0078 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\): + CMP0078-common.cmake:[0-9]+ \(include\) + CMP0078-OLD.cmake:[0-9]+ \(include\) + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/option/CMP0077-OLD-stderr.txt b/Tests/RunCMake/option/CMP0077-OLD-stderr.txt new file mode 100644 index 00000000000..9d963cba6ba --- /dev/null +++ b/Tests/RunCMake/option/CMP0077-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0077-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0077 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/target_link_libraries/CMP0079-iface-OLD-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt new file mode 100644 index 00000000000..c6645054f53 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0079-iface-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0079 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/target_link_libraries/CMP0079-link-OLD-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt index 0b4c4c6830b..14f47899683 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-OLD-stderr.txt @@ -1,4 +1,15 @@ -^CMake Error at CMP0079-link/CMakeLists.txt:[0-9]+ \(target_link_libraries\): +^CMake Deprecation Warning at CMP0079-link-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0079 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\) ++ +CMake Error at CMP0079-link/CMakeLists.txt:[0-9]+ \(target_link_libraries\): Attempt to add link library "foo" to target "top" which is not built in this directory. From 141dbf2c190b04e5a99776be4df590c46aaebc73 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 10 Feb 2021 09:02:49 -0500 Subject: [PATCH 0003/1519] export: Increase maximum policy version in exported files to 3.19 The files generatd by `install(EXPORT)` and `export()` commands are known to work with policies as of CMake 3.19, so enable them in sufficiently new CMake versions. --- Source/cmExportFileGenerator.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 7015a012980..0409f97cab7 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -924,13 +924,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.18 (this upper limit may be reviewed + // policy settings for up to CMake 3.19 (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. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.6...3.18)\n"; + << "cmake_policy(VERSION 2.6...3.19)\n"; /* clang-format on */ } From e517c1beb6354ebecc2923a9e0540901840ab880 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 10 Feb 2021 09:03:53 -0500 Subject: [PATCH 0004/1519] Configure CMake itself with policies through CMake 3.19 --- CMakeLists.txt | 2 +- Utilities/Doxygen/CMakeLists.txt | 2 +- Utilities/Sphinx/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a2fcf2e3727..045a283fa57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -cmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1...3.19 FATAL_ERROR) 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) diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt index a880f7a81b6..0ccb72124bf 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.1...3.18 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.19 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/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index f989907b405..69f85d9b3fa 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.1...3.18 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.19 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) From 5e33b1701754ea87522a3fa550ad031662b1f03f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 11 Feb 2021 00:01:16 -0500 Subject: [PATCH 0005/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b3b7d9421a9..d01d2574048 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210210) +set(CMake_VERSION_PATCH 20210211) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From de7f0aa6c0d3429342ce1b5aa94f9d2a43f85e12 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 11 Feb 2021 16:45:45 +0100 Subject: [PATCH 0006/1519] UseSWIG: avoid spurious policy warnings --- Modules/UseSWIG.cmake | 23 +++++++------------ Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt | 14 ----------- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 7d7f7377c5c..b1e05769784 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -338,20 +338,11 @@ as well as ``SWIG``: initialized with the value of this variable. #]=======================================================================] -cmake_policy(GET CMP0078 target_name_policy) -cmake_policy(GET CMP0086 module_name_policy) - -cmake_policy (VERSION 3.12) -if (target_name_policy) - # respect user choice regarding CMP0078 policy - cmake_policy(SET CMP0078 ${target_name_policy}) -endif() -if (module_name_policy) - # respect user choice regarding CMP0086 policy - cmake_policy(SET CMP0086 ${module_name_policy}) -endif() -unset(target_name_policy) -unset(module_name_policy) +cmake_policy(PUSH) +# numbers and boolean constants +cmake_policy (SET CMP0012 NEW) +# IN_LIST operator +cmake_policy (SET CMP0057 NEW) set(SWIG_CXX_EXTENSION "cxx") set(SWIG_EXTRA_LIBRARIES "") @@ -911,7 +902,7 @@ function(SWIG_ADD_LIBRARY name) if (APPLE) set_target_properties (${target_name} PROPERTIES SUFFIX ".jnilib") endif() - if ((WIN32 AND MINGW) OR CYGWIN OR CMAKE_SYSTEM_NAME STREQUAL MSYS) + if ((WIN32 AND MINGW) OR CYGWIN OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") set_target_properties(${target_name} PROPERTIES PREFIX "") endif() elseif (swig_lowercase_language STREQUAL "lua") @@ -1007,3 +998,5 @@ function(SWIG_LINK_LIBRARIES name) endif() endif() endfunction() + +cmake_policy(POP) diff --git a/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt index e8eadedd518..2afdc4f4928 100644 --- a/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt +++ b/Tests/RunCMake/UseSWIG/CMP0078-OLD-stderr.txt @@ -7,18 +7,4 @@ 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\) -+ -CMake Deprecation Warning at [^ -]*/Modules/UseSWIG.cmake:[0-9]+ \(cmake_policy\): - The OLD behavior for policy CMP0078 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\): - CMP0078-common.cmake:[0-9]+ \(include\) - CMP0078-OLD.cmake:[0-9]+ \(include\) CMakeLists.txt:[0-9]+ \(include\)$ From 04f5ffa1fdd8895b78ca107d1e61f5fc036d257b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 12 Feb 2021 00:01:17 -0500 Subject: [PATCH 0007/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d01d2574048..6c4fe079ae3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210211) +set(CMake_VERSION_PATCH 20210212) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 99e9167caa8fa65e72553fa38adb24071b51fd71 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 13 Feb 2021 00:01:15 -0500 Subject: [PATCH 0008/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6c4fe079ae3..bc4e0b90dc6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210212) +set(CMake_VERSION_PATCH 20210213) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e8f178a0016a545d33777d7e0b3717ef0ba718e3 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 14 Feb 2021 00:01:08 -0500 Subject: [PATCH 0009/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bc4e0b90dc6..267fc0994fe 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210213) +set(CMake_VERSION_PATCH 20210214) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 4620cf77f27a63163e0c101dbe28632039a3588a Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 14 Feb 2021 11:38:02 +0200 Subject: [PATCH 0010/1519] Clang: Remove unused CUDA implicit link variables We don't use/need implicit links for Clang with CUDA. --- Modules/Compiler/Clang-CUDA.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake index cafc7ddd1e6..37e5e9f7fd4 100644 --- a/Modules/Compiler/Clang-CUDA.cmake +++ b/Modules/Compiler/Clang-CUDA.cmake @@ -22,8 +22,8 @@ set(_CMAKE_CUDA_PTX_FLAG "--cuda-device-only -S") set(_CMAKE_CUDA_DEVICE_CODE "-fgpu-rdc -c") # RulePlaceholderExpander expands crosscompile variables like sysroot and target only for CMAKE__COMPILER. Override the default. -set(CMAKE_CUDA_LINK_EXECUTABLE " -o ${__IMPLICT_LINKS}") -set(CMAKE_CUDA_CREATE_SHARED_LIBRARY " -o ${__IMPLICT_LINKS}") +set(CMAKE_CUDA_LINK_EXECUTABLE " -o ") +set(CMAKE_CUDA_CREATE_SHARED_LIBRARY " -o ") set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "STATIC") set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static") From 4dc1c9e5251ec8c63bf19d074431a7662c742b55 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 14 Feb 2021 11:38:40 +0200 Subject: [PATCH 0011/1519] CUDA: Fix spelling __IMPLICT_ -> __IMPLICIT_ --- Modules/CMakeCUDAInformation.cmake | 32 +++++++++++----------- Modules/Platform/Apple-NVIDIA-CUDA.cmake | 12 ++++---- Modules/Platform/Windows-NVIDIA-CUDA.cmake | 32 +++++++++++----------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index cb03ef405be..2b7d7b2c4c2 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -9,15 +9,15 @@ endif() set(CMAKE_INCLUDE_FLAG_CUDA "-I") # Set implicit links early so compiler-specific modules can use them. -set(__IMPLICT_LINKS ) +set(__IMPLICIT_LINKS) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) - string(APPEND __IMPLICT_LINKS " -L\"${dir}\"") + string(APPEND __IMPLICIT_LINKS " -L\"${dir}\"") endforeach() foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}) if(${lib} MATCHES "/") - string(APPEND __IMPLICT_LINKS " \"${lib}\"") + string(APPEND __IMPLICIT_LINKS " \"${lib}\"") else() - string(APPEND __IMPLICT_LINKS " -l${lib}") + string(APPEND __IMPLICIT_LINKS " -l${lib}") endif() endforeach() @@ -117,7 +117,7 @@ endif() # create a shared library if(NOT CMAKE_CUDA_CREATE_SHARED_LIBRARY) set(CMAKE_CUDA_CREATE_SHARED_LIBRARY - " -o ${__IMPLICT_LINKS}") + " -o ${__IMPLICIT_LINKS}") endif() # create a shared module copy the shared library rule by default @@ -157,32 +157,32 @@ endif() # compile a cu file into an executable if(NOT CMAKE_CUDA_LINK_EXECUTABLE) set(CMAKE_CUDA_LINK_EXECUTABLE - " -o ${__IMPLICT_LINKS}") + " -o ${__IMPLICIT_LINKS}") endif() # Add implicit host link directories that contain device libraries # to the device link line. -set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) -if(__IMPLICT_DLINK_DIRS) - list(REMOVE_ITEM __IMPLICT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) +set(__IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +if(__IMPLICIT_DLINK_DIRS) + list(REMOVE_ITEM __IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) endif() -set(__IMPLICT_DLINK_FLAGS ) -foreach(dir ${__IMPLICT_DLINK_DIRS}) +set(__IMPLICIT_DLINK_FLAGS) +foreach(dir ${__IMPLICIT_DLINK_DIRS}) if(EXISTS "${dir}/libcurand_static.a") - string(APPEND __IMPLICT_DLINK_FLAGS " -L\"${dir}\"") + string(APPEND __IMPLICIT_DLINK_FLAGS " -L\"${dir}\"") endif() endforeach() -unset(__IMPLICT_DLINK_DIRS) +unset(__IMPLICIT_DLINK_DIRS) #These are used when linking relocatable (dc) cuda code if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - " ${_CMAKE_CUDA_EXTRA_FLAGS} ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o ${__IMPLICT_DLINK_FLAGS}") + " ${_CMAKE_CUDA_EXTRA_FLAGS} ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o ${__IMPLICIT_DLINK_FLAGS}") endif() if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE) set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - " ${_CMAKE_CUDA_EXTRA_FLAGS} ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o ${__IMPLICT_DLINK_FLAGS}") + " ${_CMAKE_CUDA_EXTRA_FLAGS} ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o ${__IMPLICIT_DLINK_FLAGS}") endif() # Used when device linking is handled by CMake. @@ -190,6 +190,6 @@ if(NOT CMAKE_CUDA_DEVICE_LINK_COMPILE) set(CMAKE_CUDA_DEVICE_LINK_COMPILE " ${_CMAKE_CUDA_EXTRA_FLAGS} -D__CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__ -D__NV_EXTRA_INITIALIZATION=\"\" -D__NV_EXTRA_FINALIZATION=\"\" -DREGISTERLINKBINARYFILE=\\\"\\\" -DFATBINFILE=\\\"\\\" ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c \"${CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT}/bin/crt/link.stub\" -o ") endif() -unset(__IMPLICT_DLINK_FLAGS) +unset(__IMPLICIT_DLINK_FLAGS) set(CMAKE_CUDA_INFORMATION_LOADED 1) diff --git a/Modules/Platform/Apple-NVIDIA-CUDA.cmake b/Modules/Platform/Apple-NVIDIA-CUDA.cmake index bec39483901..35e759a65cb 100644 --- a/Modules/Platform/Apple-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Apple-NVIDIA-CUDA.cmake @@ -1,19 +1,19 @@ include(Platform/Darwin) -set(__IMPLICT_LINKS ) +set(__IMPLICIT_LINKS) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) - string(APPEND __IMPLICT_LINKS " -L\"${dir}\"") + string(APPEND __IMPLICIT_LINKS " -L\"${dir}\"") endforeach() foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}) if(${lib} MATCHES "/") - string(APPEND __IMPLICT_LINKS " \"${lib}\"") + string(APPEND __IMPLICIT_LINKS " \"${lib}\"") else() - string(APPEND __IMPLICT_LINKS " -l${lib}") + string(APPEND __IMPLICIT_LINKS " -l${lib}") endif() endforeach() set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS "-shared -Wl,-headerpad_max_install_names") set(CMAKE_SHARED_MODULE_CREATE_CUDA_FLAGS "-shared -Wl,-headerpad_max_install_names") -set(CMAKE_CUDA_CREATE_SHARED_LIBRARY " -o ${__IMPLICT_LINKS}") -set(CMAKE_CUDA_CREATE_SHARED_MODULE " -o ${__IMPLICT_LINKS}") +set(CMAKE_CUDA_CREATE_SHARED_LIBRARY " -o ${__IMPLICIT_LINKS}") +set(CMAKE_CUDA_CREATE_SHARED_MODULE " -o ${__IMPLICIT_LINKS}") diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index a88f4bc4435..32cf7b86732 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -7,49 +7,49 @@ set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION " ${_CMAKE_CUDA_EXTRA_FLAGS} ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c -o -Xcompiler=-Fd,-FS") -set(__IMPLICT_LINKS ) +set(__IMPLICIT_LINKS) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) - string(APPEND __IMPLICT_LINKS " -LIBPATH:\"${dir}\"") + string(APPEND __IMPLICIT_LINKS " -LIBPATH:\"${dir}\"") endforeach() foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}) - string(APPEND __IMPLICT_LINKS " \"${lib}\"") + string(APPEND __IMPLICIT_LINKS " \"${lib}\"") endforeach() set(CMAKE_CUDA_LINK_EXECUTABLE - " /out: /implib: /pdb: /version:. ${__IMPLICT_LINKS}") + " /out: /implib: /pdb: /version:. ${__IMPLICIT_LINKS}") set(_CMAKE_VS_LINK_DLL " -E vs_link_dll --intdir= --rc= --mt= --manifests -- ") set(_CMAKE_VS_LINK_EXE " -E vs_link_exe --intdir= --rc= --mt= --manifests -- ") set(CMAKE_CUDA_CREATE_SHARED_LIBRARY - "${_CMAKE_VS_LINK_DLL} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /dll /version:.${_PLATFORM_LINK_FLAGS} ${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}") + "${_CMAKE_VS_LINK_DLL} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /dll /version:.${_PLATFORM_LINK_FLAGS} ${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}") set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY}) set(CMAKE_CUDA_CREATE_STATIC_LIBRARY " ${CMAKE_CL_NOLOGO} /out: ") set(CMAKE_CUDA_LINKER_SUPPORTS_PDB ON) set(CMAKE_CUDA_LINK_EXECUTABLE - "${_CMAKE_VS_LINK_EXE} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /version:.${_PLATFORM_LINK_FLAGS} ${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}") + "${_CMAKE_VS_LINK_EXE} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /version:.${_PLATFORM_LINK_FLAGS} ${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}") unset(_CMAKE_VS_LINK_EXE) unset(_CMAKE_VS_LINK_EXE) # Add implicit host link directories that contain device libraries # to the device link line. -set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) -if(__IMPLICT_DLINK_DIRS) - list(REMOVE_ITEM __IMPLICT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) +set(__IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +if(__IMPLICIT_DLINK_DIRS) + list(REMOVE_ITEM __IMPLICIT_DLINK_DIRS ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) endif() -set(__IMPLICT_DLINK_FLAGS ) -foreach(dir ${__IMPLICT_DLINK_DIRS}) +set(__IMPLICIT_DLINK_FLAGS) +foreach(dir ${__IMPLICIT_DLINK_DIRS}) if(EXISTS "${dir}/curand_static.lib") - string(APPEND __IMPLICT_DLINK_FLAGS " -L\"${dir}\"") + string(APPEND __IMPLICIT_DLINK_FLAGS " -L\"${dir}\"") endif() endforeach() -unset(__IMPLICT_DLINK_DIRS) +unset(__IMPLICIT_DLINK_DIRS) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - " ${_CMAKE_CUDA_EXTRA_FLAGS} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o -Xcompiler=-Fd,-FS${__IMPLICT_DLINK_FLAGS}") + " ${_CMAKE_CUDA_EXTRA_FLAGS} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o -Xcompiler=-Fd,-FS${__IMPLICIT_DLINK_FLAGS}") set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - " ${_CMAKE_CUDA_EXTRA_FLAGS} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o -Xcompiler=-Fd,-FS${__IMPLICT_DLINK_FLAGS}") -unset(__IMPLICT_DLINK_FLAGS) + " ${_CMAKE_CUDA_EXTRA_FLAGS} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o -Xcompiler=-Fd,-FS${__IMPLICIT_DLINK_FLAGS}") +unset(__IMPLICIT_DLINK_FLAGS) string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") From af38d5a1d43819d12b364308520cf9435fcc8ef2 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 14 Feb 2021 11:49:28 +0200 Subject: [PATCH 0012/1519] Platform/Windows-NVIDIA-CUDA: Remove duplicated code Some of the things are set in Platform/NVIDIA-CUDA and since we aren't setting them to different values there's no point in overriding them. Also fixed an unset() copy-paste error. --- Modules/Platform/Windows-NVIDIA-CUDA.cmake | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 32cf7b86732..b83932eddcf 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -27,7 +27,7 @@ set(CMAKE_CUDA_CREATE_STATIC_LIBRARY " ${CMAKE_CL_NOLOGO} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /version:.${_PLATFORM_LINK_FLAGS} ${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}") -unset(_CMAKE_VS_LINK_EXE) +unset(_CMAKE_VS_LINK_DLL) unset(_CMAKE_VS_LINK_EXE) @@ -69,14 +69,6 @@ else() endif() unset(_cmp0092) -set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static") -set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "cudadevrt;cudart") -set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_NONE "") - -if(UNIX) - list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl") -endif() - string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"${_W3}${_FLAGS_CXX}\"") string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}-Zi -Ob0 -Od ${_RTC1}\"") string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"${_MD}-O2 -Ob2\" -DNDEBUG") From 72de729bb35b2928b00065385b1471e7bcd13063 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 15 Feb 2021 00:01:18 -0500 Subject: [PATCH 0013/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 267fc0994fe..af9c6d720ab 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210214) +set(CMake_VERSION_PATCH 20210215) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 905d663961074c44201a99476933cf30f6778bcf Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 14 Feb 2021 12:07:50 +0200 Subject: [PATCH 0014/1519] Tests: Fake home directory even if not set In some cases ENV{HOME} might not be set, e.g. when run through a systemd service without User set. We should still to fake HOME in such cases as some tests (e.g. FindPackageTest) rely on it. We need only avoid setting ENV{CTEST_REAL_HOME} in such cases. Its possible absence seems to already be handled by tests. --- Tests/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 4ed902c8c51..5cb59af53c3 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -25,14 +25,14 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/CheckFortran.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/CheckSwift.cmake) # Fake a user home directory to avoid polluting the real one. -if(DEFINED ENV{HOME} AND NOT CTEST_NO_TEST_HOME) +if(NOT CTEST_NO_TEST_HOME AND (NOT WIN32 OR DEFINED ENV{HOME})) set(TEST_HOME "${CMake_BINARY_DIR}/Tests/CMakeFiles/TestHome") file(MAKE_DIRECTORY "${TEST_HOME}") file(WRITE "${TEST_HOME}/.cvspass" ":pserver:anoncvs@www.cmake.org:/cvsroot/KWSys A\n") set(TEST_HOME_ENV_CODE "# Fake a user home directory to avoid polluting the real one. # But provide original ENV{HOME} value in ENV{CTEST_REAL_HOME} for tests that # need access to the real HOME directory. -if(NOT DEFINED ENV{CTEST_REAL_HOME}) +if(DEFINED ENV{HOME} AND NOT DEFINED ENV{CTEST_REAL_HOME}) set(ENV{CTEST_REAL_HOME} \"\$ENV{HOME}\") endif() set(ENV{HOME} \"${TEST_HOME}\") From 4f577d9f3a3604038f5b942c51cbf96e4c94146d Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Thu, 11 Feb 2021 20:47:05 +0100 Subject: [PATCH 0015/1519] AUTOUIC: Fix missed ui files in Ninja deps This fixes the issue when two .ui files have the same name, but different locations. In this case, Ninja deps file only contains .ui file that was found first. So /xxx/yyy.ui and /yyy.ui were processed as a same file by AUTOUIC. --- Source/cmQtAutoMocUic.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 68d3c6cbc96..75611ac6474 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -1589,14 +1589,14 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi( }; // Vicinity of the source - if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) { - return true; - } if (!includePrefix.empty()) { if (findUi(cmStrCat(sourceDirPrefix, includePrefix, this->UiName))) { return true; } } + if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) { + return true; + } // Additional AUTOUIC search paths auto const& searchPaths = this->UicConst().SearchPaths; if (!searchPaths.empty()) { From 6e2e906365b695d0c9908ef9535527c74107adcf Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 16 Feb 2021 00:01:19 -0500 Subject: [PATCH 0016/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index af9c6d720ab..4bfc6fcf560 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210215) +set(CMake_VERSION_PATCH 20210216) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9934a97642f82f35380fca7b5b1b1867abbd9688 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 16 Feb 2021 10:11:02 -0500 Subject: [PATCH 0017/1519] cmListCommand: refactor out index argument parsing This is in preparation for detecting errors in index argument syntax. --- Source/cmListCommand.cxx | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index fdddb455697..edfaeeca765 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -36,6 +36,13 @@ namespace { +bool GetIndexArg(char const* arg, int* idx) +{ + *idx = atoi(arg); + // Ignore errors. + return true; +} + bool FilterRegex(std::vector const& args, bool includeMatches, std::string const& listName, std::vector& varArgsExpanded, @@ -154,7 +161,11 @@ bool HandleGetCommand(std::vector const& args, const char* sep = ""; size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size() - 1; cc++) { - int item = atoi(args[cc].c_str()); + int item; + if (!GetIndexArg(args[cc].c_str(), &item)) { + status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); + return false; + } value += sep; sep = ";"; if (item < 0) { @@ -362,7 +373,11 @@ bool HandleInsertCommand(std::vector const& args, const std::string& listName = args[1]; // expand the variable - int item = atoi(args[2].c_str()); + int item; + if (!GetIndexArg(args[2].c_str(), &item)) { + status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); + return false; + } std::vector varArgsExpanded; if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) || varArgsExpanded.empty()) && @@ -1282,8 +1297,16 @@ bool HandleSublistCommand(std::vector const& args, return true; } - const int start = atoi(args[2].c_str()); - const int length = atoi(args[3].c_str()); + int start; + int length; + if (!GetIndexArg(args[2].c_str(), &start)) { + status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); + return false; + } + if (!GetIndexArg(args[3].c_str(), &length)) { + status.SetError(cmStrCat("index: ", args[3], " is not a valid index")); + return false; + } using size_type = decltype(varArgsExpanded)::size_type; @@ -1338,7 +1361,11 @@ bool HandleRemoveAtCommand(std::vector const& args, std::vector removed; size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size(); ++cc) { - int item = atoi(args[cc].c_str()); + int item; + if (!GetIndexArg(args[cc].c_str(), &item)) { + status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); + return false; + } if (item < 0) { item = static_cast(nitem) + item; } From 0abf89bf225774c62ab79512defdb10be0bf6939 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 17 Feb 2021 00:01:14 -0500 Subject: [PATCH 0018/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4bfc6fcf560..ffbd6738f63 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210216) +set(CMake_VERSION_PATCH 20210217) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b6445ddeda9b4a608cd34d417f04aa2ee558ef76 Mon Sep 17 00:00:00 2001 From: Johan Andruejol Date: Mon, 15 Feb 2021 14:53:23 -0500 Subject: [PATCH 0019/1519] Help: Add SelectLibraryConfigurations example to cmake-developer(7) --- Help/manual/cmake-developer.7.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst index af9a8ab0d48..fe146de0f10 100644 --- a/Help/manual/cmake-developer.7.rst +++ b/Help/manual/cmake-developer.7.rst @@ -350,6 +350,24 @@ look. PATHS ${PC_Foo_LIBRARY_DIRS} ) +Alternatively, if the library is available with multiple configurations, you can +use :module:`SelectLibraryConfigurations` to automatically set the +``Foo_LIBRARY`` variable instead: + +.. code-block:: cmake + + find_library(Foo_LIBRARY_RELEASE + NAMES foo + PATHS ${PC_Foo_LIBRARY_DIRS}/Release + ) + find_library(Foo_LIBRARY_DEBUG + NAMES foo + PATHS ${PC_Foo_LIBRARY_DIRS}/Debug + ) + + include(SelectLibraryConfigurations) + select_library_configurations(Foo) + If you have a good way of getting the version (from a header file, for example), you can use that information to set ``Foo_VERSION`` (although note that find modules have traditionally used ``Foo_VERSION_STRING``, From b8762f31897e7b8fa5fa85bd20bc97f945098914 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 18 Feb 2021 00:01:15 -0500 Subject: [PATCH 0020/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ffbd6738f63..cec6293ef3e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210217) +set(CMake_VERSION_PATCH 20210218) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1f1fdff7fa9f51ccdc91232606a6ade20e02d83f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 16 Feb 2021 10:14:36 -0500 Subject: [PATCH 0021/1519] cmListCommand: prefer strtol to atoi This allows for detecting errors. --- Source/cmListCommand.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index edfaeeca765..42f94b6b6ce 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -4,9 +4,7 @@ #include #include -#include #include -#include // required for atoi #include #include #include @@ -38,8 +36,14 @@ namespace { bool GetIndexArg(char const* arg, int* idx) { - *idx = atoi(arg); - // Ignore errors. + long value; + if (!cmStrToLong(arg, &value)) { + // An error was detected. + } + + // Truncation is happening here, but it had always been happening here. + *idx = static_cast(value); + return true; } From 79eaa908dc2ad339d5f92b10a30c4244975ab21a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 16 Feb 2021 10:29:37 -0500 Subject: [PATCH 0022/1519] cmListCommand: add a policy for failing on invalid indicies --- Help/manual/cmake-policies.7.rst | 8 ++++ Help/policy/CMP0121.rst | 21 +++++++++++ Help/release/dev/list-index-arg-parsing.rst | 7 ++++ Source/cmListCommand.cxx | 37 +++++++++++++++---- Source/cmPolicies.h | 5 ++- .../CMP0121/CMP0121-ERANGE-Common.cmake | 8 ++++ .../CMP0121/CMP0121-ERANGE-NEW-result.txt | 1 + .../CMP0121/CMP0121-ERANGE-NEW-stderr.txt | 8 ++++ .../RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake | 2 + .../CMP0121/CMP0121-ERANGE-OLD-result.txt | 1 + .../CMP0121/CMP0121-ERANGE-OLD-stderr.txt | 8 ++++ .../RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake | 2 + .../CMP0121/CMP0121-ERANGE-WARN-result.txt | 1 + .../CMP0121/CMP0121-ERANGE-WARN-stderr.txt | 18 +++++++++ .../CMP0121/CMP0121-ERANGE-WARN.cmake | 2 + .../RunCMake/CMP0121/CMP0121-GET-Common.cmake | 4 ++ .../CMP0121/CMP0121-GET-NEW-result.txt | 1 + .../CMP0121/CMP0121-GET-NEW-stderr.txt | 8 ++++ Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake | 2 + .../CMP0121/CMP0121-GET-OLD-stderr.txt | 1 + Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake | 2 + .../CMP0121/CMP0121-GET-WARN-stderr.txt | 11 ++++++ Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake | 2 + .../CMP0121/CMP0121-INSERT-Common.cmake | 4 ++ .../CMP0121/CMP0121-INSERT-NEW-result.txt | 1 + .../CMP0121/CMP0121-INSERT-NEW-stderr.txt | 8 ++++ .../RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake | 2 + .../CMP0121/CMP0121-INSERT-OLD-stderr.txt | 1 + .../RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake | 2 + .../CMP0121/CMP0121-INSERT-WARN-stderr.txt | 11 ++++++ .../CMP0121/CMP0121-INSERT-WARN.cmake | 2 + .../CMP0121/CMP0121-REMOVE_AT-Common.cmake | 4 ++ .../CMP0121/CMP0121-REMOVE_AT-NEW-result.txt | 1 + .../CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt | 8 ++++ .../CMP0121/CMP0121-REMOVE_AT-NEW.cmake | 2 + .../CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt | 1 + .../CMP0121/CMP0121-REMOVE_AT-OLD.cmake | 2 + .../CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt | 11 ++++++ .../CMP0121/CMP0121-REMOVE_AT-WARN.cmake | 2 + .../CMP0121-SUBLIST-length-Common.cmake | 4 ++ .../CMP0121-SUBLIST-length-NEW-result.txt | 1 + .../CMP0121-SUBLIST-length-NEW-stderr.txt | 8 ++++ .../CMP0121/CMP0121-SUBLIST-length-NEW.cmake | 2 + .../CMP0121-SUBLIST-length-OLD-stderr.txt | 1 + .../CMP0121/CMP0121-SUBLIST-length-OLD.cmake | 2 + .../CMP0121-SUBLIST-length-WARN-stderr.txt | 11 ++++++ .../CMP0121/CMP0121-SUBLIST-length-WARN.cmake | 2 + .../CMP0121-SUBLIST-start-Common.cmake | 4 ++ .../CMP0121-SUBLIST-start-NEW-result.txt | 1 + .../CMP0121-SUBLIST-start-NEW-stderr.txt | 8 ++++ .../CMP0121/CMP0121-SUBLIST-start-NEW.cmake | 2 + .../CMP0121-SUBLIST-start-OLD-stderr.txt | 1 + .../CMP0121/CMP0121-SUBLIST-start-OLD.cmake | 2 + .../CMP0121-SUBLIST-start-WARN-stderr.txt | 11 ++++++ .../CMP0121/CMP0121-SUBLIST-start-WARN.cmake | 2 + Tests/RunCMake/CMP0121/CMakeLists.txt | 3 ++ Tests/RunCMake/CMP0121/RunCMakeTest.cmake | 7 ++++ Tests/RunCMake/CMakeLists.txt | 1 + 58 files changed, 287 insertions(+), 8 deletions(-) create mode 100644 Help/policy/CMP0121.rst create mode 100644 Help/release/dev/list-index-arg-parsing.rst create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake create mode 100644 Tests/RunCMake/CMP0121/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0121/RunCMakeTest.cmake diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index bd6b2f0ca9f..f103c5054a2 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.21 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0121: The list command detects invalid indicies + Policies Introduced by CMake 3.20 ================================= diff --git a/Help/policy/CMP0121.rst b/Help/policy/CMP0121.rst new file mode 100644 index 00000000000..5ef28569e26 --- /dev/null +++ b/Help/policy/CMP0121.rst @@ -0,0 +1,21 @@ +CMP0121 +------- + +.. versionadded:: 3.21 + +The :command:`list` command now detects invalid indicies. + +Prior to CMake version 3.21, the :command:`list` command's ``GET``, +``INSERT``, ``SUBLIST``, and ``REMOVE_AT`` subcommands did not detect invalid +index arguments. + +The ``OLD`` behavior of this policy is for invalid indicies to be treated as +their integer value (if any) at the start of the string. For example, +``2good4you`` is a ``2`` and ``not_an_integer`` is a ``0``. The ``NEW`` +behavior is for invalid indicies to trigger an error. + +This policy was introduced in CMake version 3.21. CMake version |release| +warns when the policy is not set and uses ``OLD`` behavior. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/list-index-arg-parsing.rst b/Help/release/dev/list-index-arg-parsing.rst new file mode 100644 index 00000000000..2ea525bc463 --- /dev/null +++ b/Help/release/dev/list-index-arg-parsing.rst @@ -0,0 +1,7 @@ +list-index-arg-parsing +---------------------- + +* The :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and + ``REMOVE_AT`` subcommands now error with invalid (i.e., non-integer) values + are given as any of their index arguments based on the setting of policy + :policy:`CMP0121`. diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 42f94b6b6ce..1bafdf799b4 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -34,11 +34,34 @@ namespace { -bool GetIndexArg(char const* arg, int* idx) +bool GetIndexArg(char const* arg, int* idx, cmMakefile& mf) { long value; if (!cmStrToLong(arg, &value)) { - // An error was detected. + switch (mf.GetPolicyStatus(cmPolicies::CMP0121)) { + case cmPolicies::WARN: { + // Default is to warn and use old behavior OLD behavior is to allow + // compatibility, so issue a warning and use the previous behavior. + std::string warn = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121), + " Invalid list index \"", arg, "\"."); + mf.IssueMessage(MessageType::AUTHOR_WARNING, warn); + break; + } + case cmPolicies::OLD: + // OLD behavior is to allow compatibility, so just ignore the + // situation. + break; + case cmPolicies::NEW: + return false; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + std::string msg = + cmStrCat(cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0121), + " Invalid list index \"", arg, "\"."); + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + break; + } } // Truncation is happening here, but it had always been happening here. @@ -166,7 +189,7 @@ bool HandleGetCommand(std::vector const& args, size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size() - 1; cc++) { int item; - if (!GetIndexArg(args[cc].c_str(), &item)) { + if (!GetIndexArg(args[cc].c_str(), &item, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); return false; } @@ -378,7 +401,7 @@ bool HandleInsertCommand(std::vector const& args, // expand the variable int item; - if (!GetIndexArg(args[2].c_str(), &item)) { + if (!GetIndexArg(args[2].c_str(), &item, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); return false; } @@ -1303,11 +1326,11 @@ bool HandleSublistCommand(std::vector const& args, int start; int length; - if (!GetIndexArg(args[2].c_str(), &start)) { + if (!GetIndexArg(args[2].c_str(), &start, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); return false; } - if (!GetIndexArg(args[3].c_str(), &length)) { + if (!GetIndexArg(args[3].c_str(), &length, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[3], " is not a valid index")); return false; } @@ -1366,7 +1389,7 @@ bool HandleRemoveAtCommand(std::vector const& args, size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size(); ++cc) { int item; - if (!GetIndexArg(args[cc].c_str(), &item)) { + if (!GetIndexArg(args[cc].c_str(), &item, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); return false; } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 2194b0f2906..9295a3fa4e6 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -359,7 +359,10 @@ class cmMakefile; 3, 20, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0120, \ "The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0121, \ + "The list() command now validates parsing of index arguments.", 3, \ + 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake new file mode 100644 index 00000000000..5594be811ab --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-Common.cmake @@ -0,0 +1,8 @@ +set(listvar a b c d e) + +list(GET listvar + 18446744073709551616 # 2^64 + 2147483648 # 2^31 + 4294967296 # 2^32; errors out-of-range as -2147483643 due to underflow + out) +message("ERANGE: -->${out}<--") diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt new file mode 100644 index 00000000000..0166e144434 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\): + list index: 18446744073709551616 is not a valid index +Call Stack \(most recent call first\): + CMP0121-ERANGE-NEW.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +ERANGE: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake new file mode 100644 index 00000000000..68e564d555c --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 NEW) +include(CMP0121-ERANGE-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt new file mode 100644 index 00000000000..5a035596e3a --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\): + list index: (-2147483643|2147483647) out of range \(-5, 4\) +Call Stack \(most recent call first\): + CMP0121-ERANGE-OLD.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +ERANGE: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake new file mode 100644 index 00000000000..32f0b5669a5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 OLD) +include(CMP0121-ERANGE-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt new file mode 100644 index 00000000000..1e7b1275716 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN-stderr.txt @@ -0,0 +1,18 @@ +CMake Warning \(dev\) at CMP0121-ERANGE-Common.cmake:3 \(list\): + Policy CMP0121 is not set: The list\(\) command now validates parsing of + index arguments. Run "cmake --help-policy CMP0121" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + Invalid list index "18446744073709551616". +Call Stack \(most recent call first\): + CMP0121-ERANGE-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\): + list index: (-2147483643|2147483647) out of range \(-5, 4\) +Call Stack \(most recent call first\): + CMP0121-ERANGE-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +ERANGE: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake new file mode 100644 index 00000000000..96552906a78 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-ERANGE-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0121-ERANGE-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake new file mode 100644 index 00000000000..e4986f02d0c --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-Common.cmake @@ -0,0 +1,4 @@ +set(listvar a b c d e) + +list(GET listvar 0 2junk out) +message("GET: -->${out}<--") diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt new file mode 100644 index 00000000000..d502b869a1a --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-GET-Common.cmake:3 \(list\): + list index: 2junk is not a valid index +Call Stack \(most recent call first\): + CMP0121-GET-NEW.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +GET: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake new file mode 100644 index 00000000000..1ab054de547 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 NEW) +include(CMP0121-GET-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt new file mode 100644 index 00000000000..96375e995de --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD-stderr.txt @@ -0,0 +1 @@ +GET: -->a;c<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake new file mode 100644 index 00000000000..ef4526f42bb --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 OLD) +include(CMP0121-GET-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt new file mode 100644 index 00000000000..ecfad2cab63 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at CMP0121-GET-Common.cmake:3 \(list\): + Policy CMP0121 is not set: The list\(\) command now validates parsing of + index arguments. Run "cmake --help-policy CMP0121" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + Invalid list index "2junk". +Call Stack \(most recent call first\): + CMP0121-GET-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +GET: -->a;c<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake new file mode 100644 index 00000000000..b08620b5bd9 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-GET-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0121-GET-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake new file mode 100644 index 00000000000..495088102fb --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-Common.cmake @@ -0,0 +1,4 @@ +set(listvar a b c d e) + +list(INSERT listvar junk2 new) +message("INSERT: -->${listvar}<--") diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt new file mode 100644 index 00000000000..22419627371 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-INSERT-Common.cmake:3 \(list\): + list index: junk2 is not a valid index +Call Stack \(most recent call first\): + CMP0121-INSERT-NEW.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +INSERT: -->a;b;c;d;e<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake new file mode 100644 index 00000000000..db627d13789 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 NEW) +include(CMP0121-INSERT-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt new file mode 100644 index 00000000000..52f34ad5d5c --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD-stderr.txt @@ -0,0 +1 @@ +INSERT: -->new;a;b;c;d;e<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake new file mode 100644 index 00000000000..60364d70ff9 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 OLD) +include(CMP0121-INSERT-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt new file mode 100644 index 00000000000..5fa7d17effe --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at CMP0121-INSERT-Common.cmake:3 \(list\): + Policy CMP0121 is not set: The list\(\) command now validates parsing of + index arguments. Run "cmake --help-policy CMP0121" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + Invalid list index "junk2". +Call Stack \(most recent call first\): + CMP0121-INSERT-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +INSERT: -->new;a;b;c;d;e<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake new file mode 100644 index 00000000000..55f13e22298 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-INSERT-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0121-INSERT-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake new file mode 100644 index 00000000000..ec923877464 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-Common.cmake @@ -0,0 +1,4 @@ +set(listvar a b c d e) + +list(REMOVE_AT listvar 0 invalid) +message("REMOVE_AT: -->${listvar}<--") diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt new file mode 100644 index 00000000000..f17bafd1981 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-REMOVE_AT-Common.cmake:3 \(list\): + list index: invalid is not a valid index +Call Stack \(most recent call first\): + CMP0121-REMOVE_AT-NEW.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +REMOVE_AT: -->a;b;c;d;e<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake new file mode 100644 index 00000000000..d1f09e374bf --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 NEW) +include(CMP0121-REMOVE_AT-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt new file mode 100644 index 00000000000..09af1ae53b5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD-stderr.txt @@ -0,0 +1 @@ +REMOVE_AT: -->b;c;d;e<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake new file mode 100644 index 00000000000..ac83226aafa --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 OLD) +include(CMP0121-REMOVE_AT-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt new file mode 100644 index 00000000000..e2d47af5885 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at CMP0121-REMOVE_AT-Common.cmake:3 \(list\): + Policy CMP0121 is not set: The list\(\) command now validates parsing of + index arguments. Run "cmake --help-policy CMP0121" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + Invalid list index "invalid". +Call Stack \(most recent call first\): + CMP0121-REMOVE_AT-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +REMOVE_AT: -->b;c;d;e<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake new file mode 100644 index 00000000000..2b4a8245adc --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-REMOVE_AT-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0121-REMOVE_AT-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake new file mode 100644 index 00000000000..93f46c5fc28 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-Common.cmake @@ -0,0 +1,4 @@ +set(listvar a b c d e) + +list(SUBLIST listvar 0 invalid out) +message("SUBLIST-length: -->${out}<--") diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt new file mode 100644 index 00000000000..28bd3621620 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-SUBLIST-length-Common.cmake:3 \(list\): + list index: invalid is not a valid index +Call Stack \(most recent call first\): + CMP0121-SUBLIST-length-NEW.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +SUBLIST-length: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake new file mode 100644 index 00000000000..c7875cb6c7d --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 NEW) +include(CMP0121-SUBLIST-length-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt new file mode 100644 index 00000000000..00fcf07fe04 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD-stderr.txt @@ -0,0 +1 @@ +SUBLIST-length: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake new file mode 100644 index 00000000000..e9b78eebdba --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 OLD) +include(CMP0121-SUBLIST-length-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt new file mode 100644 index 00000000000..bd06c2f701a --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at CMP0121-SUBLIST-length-Common.cmake:3 \(list\): + Policy CMP0121 is not set: The list\(\) command now validates parsing of + index arguments. Run "cmake --help-policy CMP0121" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + Invalid list index "invalid". +Call Stack \(most recent call first\): + CMP0121-SUBLIST-length-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +SUBLIST-length: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake new file mode 100644 index 00000000000..27318bfa9b6 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-length-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0121-SUBLIST-length-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake new file mode 100644 index 00000000000..33f57a33653 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-Common.cmake @@ -0,0 +1,4 @@ +set(listvar a b c d e) + +list(SUBLIST listvar invalid 2 out) +message("SUBLIST-start: -->${out}<--") diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt new file mode 100644 index 00000000000..9819f95e451 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at CMP0121-SUBLIST-start-Common.cmake:3 \(list\): + list index: invalid is not a valid index +Call Stack \(most recent call first\): + CMP0121-SUBLIST-start-NEW.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) + + +SUBLIST-start: --><-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake new file mode 100644 index 00000000000..3d676a3f3da --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 NEW) +include(CMP0121-SUBLIST-start-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt new file mode 100644 index 00000000000..8da2881d6e2 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD-stderr.txt @@ -0,0 +1 @@ +SUBLIST-start: -->a;b<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake new file mode 100644 index 00000000000..268f317e154 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0121 OLD) +include(CMP0121-SUBLIST-start-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt new file mode 100644 index 00000000000..39d0e0ee93a --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at CMP0121-SUBLIST-start-Common.cmake:3 \(list\): + Policy CMP0121 is not set: The list\(\) command now validates parsing of + index arguments. Run "cmake --help-policy CMP0121" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + Invalid list index "invalid". +Call Stack \(most recent call first\): + CMP0121-SUBLIST-start-WARN.cmake:2 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +SUBLIST-start: -->a;b<-- diff --git a/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake new file mode 100644 index 00000000000..a4078795690 --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMP0121-SUBLIST-start-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0121-SUBLIST-start-Common.cmake) diff --git a/Tests/RunCMake/CMP0121/CMakeLists.txt b/Tests/RunCMake/CMP0121/CMakeLists.txt new file mode 100644 index 00000000000..7cabeb68b2f --- /dev/null +++ b/Tests/RunCMake/CMP0121/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.20) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0121/RunCMakeTest.cmake b/Tests/RunCMake/CMP0121/RunCMakeTest.cmake new file mode 100644 index 00000000000..1ed5b1a5d14 --- /dev/null +++ b/Tests/RunCMake/CMP0121/RunCMakeTest.cmake @@ -0,0 +1,7 @@ +include(RunCMake) + +foreach (subcommand IN ITEMS ERANGE GET INSERT REMOVE_AT SUBLIST-length SUBLIST-start) + run_cmake(CMP0121-${subcommand}-WARN) + run_cmake(CMP0121-${subcommand}-OLD) + run_cmake(CMP0121-${subcommand}-NEW) +endforeach () diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 91fe6ca713f..c842574109e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -131,6 +131,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja") endif() add_RunCMake_test(CMP0118) add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) +add_RunCMake_test(CMP0121) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode From 15f0da341fb79298316dc42d04a4c81a300b0f3e Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 18 Feb 2021 08:30:17 -0500 Subject: [PATCH 0023/1519] ci: Enable IPO and FindOpenGL tests on Windows+MSVC+Ninja These are expected to work under a normal VS installation. --- .gitlab/ci/configure_windows_vs2019_x64_ninja.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab/ci/configure_windows_vs2019_x64_ninja.cmake b/.gitlab/ci/configure_windows_vs2019_x64_ninja.cmake index 9c30a4b7836..e1ae81e3d36 100644 --- a/.gitlab/ci/configure_windows_vs2019_x64_ninja.cmake +++ b/.gitlab/ci/configure_windows_vs2019_x64_ninja.cmake @@ -1,4 +1,7 @@ set(CMake_TEST_WIX_NO_VERIFY "ON" CACHE BOOL "") set(CMake_TEST_GUI "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "") +set(CMake_TEST_IPO_WORKS_C "ON" CACHE BOOL "") +set(CMake_TEST_IPO_WORKS_CXX "ON" CACHE BOOL "") include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_common.cmake") From 772c32831fa7b62fbb09fca7655d0b538926c5e4 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 19 Feb 2021 00:01:14 -0500 Subject: [PATCH 0024/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index cec6293ef3e..ed9117413e4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210218) +set(CMake_VERSION_PATCH 20210219) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 894e5548a899faf7dc7b1eadb6cf290505edaff0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 20 Feb 2021 00:01:14 -0500 Subject: [PATCH 0025/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ed9117413e4..1f110f1c8a5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210219) +set(CMake_VERSION_PATCH 20210220) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 7aad4df2ff3bb18817e480372d484f8977036033 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 21 Feb 2021 00:01:08 -0500 Subject: [PATCH 0026/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1f110f1c8a5..a9e15ebf65e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210220) +set(CMake_VERSION_PATCH 20210221) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9e1fe1f3587fa8e9b735ebc45677463c1b1d8101 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 22 Feb 2021 00:02:13 -0500 Subject: [PATCH 0027/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a9e15ebf65e..9711fbd0057 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210221) +set(CMake_VERSION_PATCH 20210222) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d7c80305410b728fce426ff0891ac9a28c4168e5 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 21 Feb 2021 18:04:28 +1100 Subject: [PATCH 0028/1519] FortranCInterface: Fix misuse of IS_NEWER_THAN in timestamp check When using a file system which only has second resolution timestamps, there is a reasonably high likelihood of timestamps being the same. The IS_NEWER_THAN test returns true when timestamps are the same, so don't redo detection when they match exactly. --- Modules/FortranCInterface/Detect.cmake | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 998faf1eccf..9e5726b03a0 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -6,14 +6,17 @@ configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in # Detect the Fortran/C interface on the first run or when the # configuration changes. -if(${FortranCInterface_BINARY_DIR}/Input.cmake - IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake - OR ${FortranCInterface_SOURCE_DIR}/Output.cmake.in - IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake - OR ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt - IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake - OR ${CMAKE_CURRENT_LIST_FILE} - IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake +if(NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake + OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Input.cmake + OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake.in + OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake + IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Input.cmake + OR NOT ${FortranCInterface_SOURCE_DIR}/Output.cmake + IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake.in + OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake + IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt + OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake + IS_NEWER_THAN ${CMAKE_CURRENT_LIST_FILE} ) message(CHECK_START "Detecting Fortran/C Interface") else() From 28501fca94f5bb54807f82ec5eb4e1885d6c7b11 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 21 Feb 2021 18:37:31 +1100 Subject: [PATCH 0029/1519] PCH PDB: Fix misuse of IS_NEWER_THAN in timestamp check When using a file system which only has second resolution timestamps, there is a reasonably high likelihood of timestamps being the same. The IS_NEWER_THAN test returns true when timestamps are the same, so don't retry copying the PCH PDB file when they match exactly. --- Source/cmLocalGenerator.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 34b9649cba7..fe31af1c01a 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2698,8 +2698,9 @@ void cmLocalGenerator::CopyPchCompilePdb( } file << "foreach(retry RANGE 1 30)\n"; - file << " if (EXISTS \"" << from_file << "\" AND \"" << from_file - << " \" IS_NEWER_THAN \"" << dest_file << "\")\n"; + file << " if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \"" + << dest_file << "\" OR NOT \"" << dest_file << " \" IS_NEWER_THAN \"" + << from_file << "\"))\n"; file << " execute_process(COMMAND ${CMAKE_COMMAND} -E copy"; file << " \"" << from_file << "\"" << " \"" << to_dir << "\" RESULT_VARIABLE result " From 8c93e3232f0db066ce613317db940a631f7d0d5e Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 21 Feb 2021 17:46:38 +1100 Subject: [PATCH 0030/1519] GoogleTest: Fix misuse of IS_NEWER_THAN in timestamp check When using a file system which only has second resolution timestamps, there is a reasonably high likelihood of timestamps being the same. The IS_NEWER_THAN test returns true when timestamps are the same, so don't redo test discovery when they match exactly. --- Modules/GoogleTest.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index 2ea9e742502..80d8e239715 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -504,7 +504,8 @@ function(gtest_discover_tests TARGET) string(CONCAT ctest_include_content "if(EXISTS \"$\")" "\n" - " if(\"$\" IS_NEWER_THAN \"${ctest_tests_file}\")" "\n" + " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n" + " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$\")" "\n" " include(\"${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}\")" "\n" " gtest_discover_tests_impl(" "\n" " TEST_EXECUTABLE" " [==[" "$" "]==]" "\n" From 8e8b99d01a6b2ce266a9401f760f4814a69e4853 Mon Sep 17 00:00:00 2001 From: Johnny Jazeix Date: Sun, 21 Feb 2021 16:29:11 +0100 Subject: [PATCH 0031/1519] CPack/NSIS: Add option for setting custom makensis executable It allows users to set a custom one without changing the PATH environment variable. Fixes: #21733 --- Help/cpack_gen/nsis.rst | 6 ++++++ Help/release/dev/cpack-nsis-executable-name.rst | 6 ++++++ Source/CPack/cmCPackNSISGenerator.cxx | 4 +++- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/cpack-nsis-executable-name.rst diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst index eaef8ae73ea..964f6296570 100644 --- a/Help/cpack_gen/nsis.rst +++ b/Help/cpack_gen/nsis.rst @@ -193,3 +193,9 @@ on Windows Nullsoft Scriptable Install System. .. versionadded:: 3.20 If set, trim down the size of the control to the size of the branding text string. + +.. variable:: CPACK_NSIS_EXECUTABLE + + .. versionadded:: 3.21 + + If set, specify the name of the NSIS executable. Default is ``makensis``. diff --git a/Help/release/dev/cpack-nsis-executable-name.rst b/Help/release/dev/cpack-nsis-executable-name.rst new file mode 100644 index 00000000000..a3818db192f --- /dev/null +++ b/Help/release/dev/cpack-nsis-executable-name.rst @@ -0,0 +1,6 @@ +cpack-nsis-executable-name +-------------------------- + +* The :cpack_gen:`CPack NSIS Generator` gained a new variable + :variable:`CPACK_NSIS_EXECUTABLE` to specify the makensis + executable to use instead of the default one. diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 263adfdf77d..9b007045e79 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -430,7 +430,9 @@ int cmCPackNSISGenerator::InitializeInternal() } #endif - nsisPath = cmSystemTools::FindProgram("makensis", path, false); + this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLE", "makensis"); + nsisPath = cmSystemTools::FindProgram( + this->GetOption("CPACK_NSIS_EXECUTABLE"), path, false); if (nsisPath.empty()) { cmCPackLogger( From bdf6a71c56803182adf6e8a39b3687f22c0704d6 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 23 Feb 2021 00:01:18 -0500 Subject: [PATCH 0032/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9711fbd0057..3e44916677d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210222) +set(CMake_VERSION_PATCH 20210223) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1265c65b330c3ba25136c6fa75fc93945c4ebec2 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Thu, 18 Feb 2021 16:02:46 +0100 Subject: [PATCH 0033/1519] AUTOUIC: Collect ui header files for Ninja generator The '_autogen/timestamp' target supposed to generate ui header files using the 'uic'. Ninja must have information about these header files as a result of generating. The fix collects .ui files of the user target and generates a list of the ui headers that need to be added to the generating results of the '_autogen/timestamp' target. The case when the .ui files are not specified and collected by AUTOUIC from the include directives of the project source files is not covered in this patch. Fixes: #16776 --- Source/cmQtAutoGenInitializer.cxx | 31 ++++++ Source/cmQtAutoGenInitializer.h | 2 + .../RerunUicOnFileChange/CMakeLists.txt | 102 ++++++++++++++++++ .../UicOnFileChange/CMakeLists.txt.in | 11 ++ .../UicOnFileChange/main.cpp | 9 ++ .../UicOnFileChange/mainwindow.ui.in | 7 ++ .../UicOnFileChange/mocwidget.h | 5 + Tests/QtAutogen/Tests.cmake | 1 + 8 files changed, 168 insertions(+) create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index bfe174c9e1f..1bcadafaa21 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -939,6 +939,30 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!uicOpts.empty()) { this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts)); } + + auto uiHeaderRelativePath = cmSystemTools::RelativePath( + this->LocalGen->GetCurrentSourceDirectory(), + cmSystemTools::GetFilenamePath(fullPath)); + + auto uiHeaderFilePath = cmStrCat( + '/', uiHeaderRelativePath, '/', "ui_"_s, + cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); + + ConfigString uiHeader; + uiHeader.Default = + cmStrCat(this->Dir.Build, "/include"_s, uiHeaderFilePath); + auto uiHeaderGenex = uiHeader.Default; + if (this->MultiConfig) { + uiHeaderGenex = cmStrCat(this->Dir.Build, "/include_$"_s, + uiHeaderFilePath); + for (std::string const& cfg : this->ConfigsList) { + uiHeader.Config[cfg] = cmStrCat(this->Dir.Build, "/include_"_s, + cfg, uiHeaderFilePath); + } + } + + this->Uic.UiHeaders.emplace_back( + std::make_pair(uiHeader, uiHeaderGenex)); } else { // Register skipped .ui file this->Uic.SkipUi.insert(fullPath); @@ -1092,6 +1116,13 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() autogenByproducts.push_back(this->Moc.CompilationFileGenex); } + if (this->Uic.Enabled) { + for (const auto& file : this->Uic.UiHeaders) { + this->AddGeneratedSource(file.first, this->Uic); + autogenByproducts.push_back(file.second); + } + } + // Compose target comment std::string autogenComment; { diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index f7e126d1009..fdb65d3df02 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -239,6 +239,8 @@ class cmQtAutoGenInitializer : public cmQtAutoGen std::vector UiFiles; ConfigStrings> Options; std::vector SearchPaths; + std::vector> + UiHeaders; } Uic; /** rcc variables. */ diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt new file mode 100644 index 00000000000..1f636af451f --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.17) +project(RerunUicOnFileChange) +include("../AutogenGuiTest.cmake") + +# Utility variables +set(testProjectTemplateDir "${CMAKE_CURRENT_SOURCE_DIR}/UicOnFileChange") +set(testProjectSrc "${CMAKE_CURRENT_BINARY_DIR}/UicOnFileChange") +set(testProjectBinDir "${CMAKE_CURRENT_BINARY_DIR}/UicOnFileChange-build") + +set(TEST_CONFIG "Release") + +macro(sleep) + message(STATUS "Sleeping for a few seconds.") + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) +endmacro() +macro(rebuild buildName) + message(STATUS "Starting build ${buildName}.") + execute_process(COMMAND "${CMAKE_COMMAND}" --build . --config "${TEST_CONFIG}" + WORKING_DIRECTORY "${testProjectBinDir}" RESULT_VARIABLE result + ) + if (result) + message(FATAL_ERROR "Build ${buildName} failed.") + else() + message(STATUS "Build ${buildName} finished.") + endif() +endmacro() + +configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY) +configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY) +configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY) + +set(Num 1) +configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) + +if(CMAKE_GENERATOR_INSTANCE) + set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}") +else() + set(_D_CMAKE_GENERATOR_INSTANCE "") +endif() + +get_property(is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(is_multi) + set(build_type_extra "-DCMAKE_CONFIGURATION_TYPES=${TEST_CONFIG}") + set(extra_bin_path "${TEST_CONFIG}/") +else() + set(build_type_extra "-DCMAKE_BUILD_TYPE=${TEST_CONFIG}") +endif() + +# Set the environment PATH/LD_LIBRARY_PATH variables to run the resulting executable +if(WIN32 AND TARGET ${QT_QTCORE_TARGET}) + get_target_property(qtcore_path ${QT_QTCORE_TARGET} LOCATION) + if(NOT qtcore_path) + get_target_property(qtcore_path ${QT_QTCORE_TARGET} IMPORTED_LOCATION) + endif() + get_filename_component(qtcore_path "${qtcore_path}" DIRECTORY) + set(ENV{PATH} "${qtcore_path};$ENV{PATH}") +endif() + +execute_process( + COMMAND "${CMAKE_COMMAND}" -B "${testProjectBinDir}" -S "${testProjectSrc}" + -G "${CMAKE_GENERATOR}" + -A "${CMAKE_GENERATOR_PLATFORM}" + -T "${CMAKE_GENERATOR_TOOLSET}" + ${_D_CMAKE_GENERATOR_INSTANCE} + "${build_type_extra}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + RESULT_VARIABLE exit_code + OUTPUT_VARIABLE output + ERROR_VARIABLE output +) +if(NOT exit_code EQUAL 0) + message(FATAL_ERROR "Initial configuration of UicOnFileChange failed. Output: ${output}") +endif() + +# Initial build +execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${testProjectBinDir}" --config "${TEST_CONFIG}" + RESULT_VARIABLE exit_code + OUTPUT_VARIABLE output + ERROR_VARIABLE output +) +if(NOT exit_code EQUAL 0) + message(FATAL_ERROR "Initial build of UicOnFileChange failed. Output: ${output}") +endif() + +execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result) +if(NOT result EQUAL "1") + message(FATAL_ERROR "Initial build of UicOnFileChange test result is: ${result}") +endif() + +sleep() + +set(Num 2) +configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) +rebuild(2) + +execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result) +if(NOT result EQUAL "0") + message(FATAL_ERROR "Rebuild of UicOnFileChange test result is: ${result}") +endif() diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in new file mode 100644 index 00000000000..fa9dd6bee32 --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.10) + +project(UicOnFileChange) +include("@CMAKE_CURRENT_LIST_DIR@/../AutogenGuiTest.cmake") + +# Enable CMAKE_AUTOUIC for all targets +set(CMAKE_AUTOUIC ON) + +add_executable(UicOnFileChange main.cpp mainwindow.ui) +target_include_directories(UicOnFileChange PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(UicOnFileChange ${QT_QTCORE_TARGET} ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp new file mode 100644 index 00000000000..fd810fa2472 --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp @@ -0,0 +1,9 @@ +#include "ui_mainwindow.h" + +int main(int argc, char* argv[]) +{ + MocWidget mw; + Ui::Widget mwUi; + mwUi.setupUi(&mw); + return mw.objectName() == "Widget2" ? 0 : 1; +} diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in new file mode 100644 index 00000000000..8f39e5514c2 --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.ui.in @@ -0,0 +1,7 @@ + + + Widget + + + + diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h new file mode 100644 index 00000000000..87fc177ddfb --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mocwidget.h @@ -0,0 +1,5 @@ +#include + +class MocWidget : public QObject +{ +}; diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake index b1337d6266c..d1edd72f4f3 100644 --- a/Tests/QtAutogen/Tests.cmake +++ b/Tests/QtAutogen/Tests.cmake @@ -24,6 +24,7 @@ ADD_AUTOGEN_TEST(RerunMocOnAddFile) ADD_AUTOGEN_TEST(RerunMocOnMissingDependency) ADD_AUTOGEN_TEST(RerunRccConfigChange) ADD_AUTOGEN_TEST(RerunRccDepends) +ADD_AUTOGEN_TEST(RerunUicOnFileChange) ADD_AUTOGEN_TEST(SameName sameName) ADD_AUTOGEN_TEST(StaticLibraryCycle slc) ADD_AUTOGEN_TEST(UicInclude uicInclude) From ca4a615118cfea8d977942012d0c0ae3566c4b80 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 24 Feb 2021 00:01:13 -0500 Subject: [PATCH 0034/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3e44916677d..4503c0b704e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210223) +set(CMake_VERSION_PATCH 20210224) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 23753be1cc2c3c363a9bc93182b53cb36cda129d Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Wed, 24 Feb 2021 15:21:54 +0200 Subject: [PATCH 0035/1519] Clang/CUDA: Restore needed references to implicit link variables In commit 4620cf77f2 (Clang: Remove unused CUDA implicit link variables, 2021-02-14) we removed some references. It turns out they are non-empty and necessary if using a non-scattered installation. Fixes: #21863 --- Modules/Compiler/Clang-CUDA.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake index 37e5e9f7fd4..0223081dad6 100644 --- a/Modules/Compiler/Clang-CUDA.cmake +++ b/Modules/Compiler/Clang-CUDA.cmake @@ -22,8 +22,8 @@ set(_CMAKE_CUDA_PTX_FLAG "--cuda-device-only -S") set(_CMAKE_CUDA_DEVICE_CODE "-fgpu-rdc -c") # RulePlaceholderExpander expands crosscompile variables like sysroot and target only for CMAKE__COMPILER. Override the default. -set(CMAKE_CUDA_LINK_EXECUTABLE " -o ") -set(CMAKE_CUDA_CREATE_SHARED_LIBRARY " -o ") +set(CMAKE_CUDA_LINK_EXECUTABLE " -o ${__IMPLICIT_LINKS}") +set(CMAKE_CUDA_CREATE_SHARED_LIBRARY " -o ${__IMPLICIT_LINKS}") set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "STATIC") set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static") From 136608dfec0552d5a49f4f414e6cafa920b53828 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 24 Feb 2021 12:21:57 -0500 Subject: [PATCH 0036/1519] cmCreateTestSourceList: avoid generating duplicate declarations This avoids warnings with `clang-tidy`'s `-readability-redundant-declaration` lint in generated source code. --- Source/cmCreateTestSourceList.cxx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index 3001ae09a9d..a2fac738c30 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -90,10 +90,15 @@ bool cmCreateTestSourceList(std::vector const& args, std::replace(func_name.begin(), func_name.end(), ' ', '_'); std::replace(func_name.begin(), func_name.end(), '/', '_'); std::replace(func_name.begin(), func_name.end(), ':', '_'); + bool already_declared = + std::find(tests_func_name.begin(), tests_func_name.end(), func_name) != + tests_func_name.end(); tests_func_name.push_back(func_name); - forwardDeclareCode += "int "; - forwardDeclareCode += func_name; - forwardDeclareCode += "(int, char*[]);\n"; + if (!already_declared) { + forwardDeclareCode += "int "; + forwardDeclareCode += func_name; + forwardDeclareCode += "(int, char*[]);\n"; + } } std::string functionMapCode; From d34d28e688c9ac5f1e5e446bb1131b3018721053 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 19 Feb 2021 09:27:48 -0500 Subject: [PATCH 0037/1519] Genex: Add TARGET_RUNTIME_DLLS genex Co-Authored-by: Brad King --- Help/manual/cmake-generator-expressions.7.rst | 23 +++++++++ Help/release/dev/runtime-dll-deps.rst | 4 ++ Source/cmComputeLinkInformation.cxx | 19 +++++++ Source/cmComputeLinkInformation.h | 6 +++ Source/cmGeneratorExpressionNode.cxx | 51 +++++++++++++++++++ Source/cmGeneratorTarget.cxx | 14 +++++ Source/cmGeneratorTarget.h | 5 ++ Tests/RunCMake/CMakeLists.txt | 1 + .../GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt | 3 ++ .../RunCMakeTest.cmake | 7 +++ .../TARGET_RUNTIME_DLLS-check.cmake | 15 ++++++ .../TARGET_RUNTIME_DLLS-static-result.txt | 1 + .../TARGET_RUNTIME_DLLS-static-stderr.txt | 9 ++++ .../TARGET_RUNTIME_DLLS-static.cmake | 9 ++++ ...LS-target_link_libraries-cycle1-result.txt | 1 + ...LS-target_link_libraries-cycle1-stderr.txt | 5 ++ ...ME_DLLS-target_link_libraries-cycle1.cmake | 4 ++ ...LS-target_link_libraries-cycle2-result.txt | 1 + ...LS-target_link_libraries-cycle2-stderr.txt | 5 ++ ...ME_DLLS-target_link_libraries-cycle2.cmake | 6 +++ ...T_RUNTIME_DLLS-target_link_libraries.cmake | 5 ++ .../TARGET_RUNTIME_DLLS.cmake | 37 ++++++++++++++ .../RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c | 12 +++++ .../RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c | 6 +++ .../RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c | 6 +++ .../RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c | 4 ++ .../GenEx-TARGET_RUNTIME_DLLS/static.c | 3 ++ 27 files changed, 262 insertions(+) create mode 100644 Help/release/dev/runtime-dll-deps.rst create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-check.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-result.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS.cmake create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c create mode 100644 Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index ca4ea3e0aa2..e7828168de5 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -938,6 +938,29 @@ which is just the string ``tgt``. :ref:`Target Usage Requirements` this is the consuming target rather than the target specifying the requirement. +.. genex:: $ + + List of DLLs that the target depends on at runtime. This is determined by + the locations of all the ``SHARED`` and ``MODULE`` targets in the target's + transitive dependencies. Using this generator expression on targets other + than executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error. + On non-DLL platforms, it evaluates to an empty string. + + This generator expression can be used to copy all of the DLLs that a target + depends on into its output directory in a ``POST_BUILD`` custom command. For + example: + + .. code-block:: cmake + + find_package(foo REQUIRED) + + add_executable(exe main.c) + target_link_libraries(exe PRIVATE foo::foo foo::bar) + add_custom_command(TARGET exe POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + COMMAND_EXPAND_LISTS + ) + .. genex:: $ Content of the install prefix when the target is exported via diff --git a/Help/release/dev/runtime-dll-deps.rst b/Help/release/dev/runtime-dll-deps.rst new file mode 100644 index 00000000000..831410f3bcc --- /dev/null +++ b/Help/release/dev/runtime-dll-deps.rst @@ -0,0 +1,4 @@ +runtime-dll-deps +---------------- + +* A new :genex:`TARGET_RUNTIME_DLLS` generator expression was added. diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 6225a4a9ed9..5473316daf9 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -701,6 +701,10 @@ void cmComputeLinkInformation::AddItem(BT const& item, this->AddTargetItem(lib, tgt); this->AddLibraryRuntimeInfo(lib.Value, tgt); + if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY && + this->Target->IsDLLPlatform()) { + this->AddRuntimeDLL(tgt); + } } } else { // This is not a CMake target. Use the name given. @@ -728,6 +732,13 @@ void cmComputeLinkInformation::AddItem(BT const& item, void cmComputeLinkInformation::AddSharedDepItem(BT const& item, const cmGeneratorTarget* tgt) { + // Record dependencies on DLLs. + if (tgt && tgt->GetType() == cmStateEnums::SHARED_LIBRARY && + this->Target->IsDLLPlatform() && + this->SharedDependencyMode != SharedDepModeLink) { + this->AddRuntimeDLL(tgt); + } + // If dropping shared library dependencies, ignore them. if (this->SharedDependencyMode == SharedDepModeNone) { return; @@ -799,6 +810,14 @@ void cmComputeLinkInformation::AddSharedDepItem(BT const& item, } } +void cmComputeLinkInformation::AddRuntimeDLL(cmGeneratorTarget const* tgt) +{ + if (std::find(this->RuntimeDLLs.begin(), this->RuntimeDLLs.end(), tgt) == + this->RuntimeDLLs.end()) { + this->RuntimeDLLs.emplace_back(tgt); + } +} + void cmComputeLinkInformation::ComputeLinkTypeInfo() { // Check whether archives may actually be shared libraries. diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 9fec7020652..4acb99f742a 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -64,6 +64,10 @@ class cmComputeLinkInformation std::string GetRPathString(bool for_install) const; std::string GetChrpathString() const; std::set const& GetSharedLibrariesLinked() const; + std::vector const& GetRuntimeDLLs() const + { + return this->RuntimeDLLs; + } std::string const& GetLibLinkFileFlag() const { @@ -81,6 +85,7 @@ class cmComputeLinkInformation void AddItem(BT const& item, const cmGeneratorTarget* tgt); void AddSharedDepItem(BT const& item, cmGeneratorTarget const* tgt); + void AddRuntimeDLL(cmGeneratorTarget const* tgt); // Output information. ItemVector Items; @@ -89,6 +94,7 @@ class cmComputeLinkInformation std::vector FrameworkPaths; std::vector RuntimeSearchPath; std::set SharedLibrariesLinked; + std::vector RuntimeDLLs; // Context information. cmGeneratorTarget const* const Target; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index e40316e1af2..da1a78e94fc 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include "cmsys/String.h" #include "cmAlgorithms.h" +#include "cmComputeLinkInformation.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" @@ -1687,6 +1689,54 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode } } targetObjectsNode; +static const struct TargetRuntimeDllsNode : public cmGeneratorExpressionNode +{ + TargetRuntimeDllsNode() {} // NOLINT(modernize-use-equals-default) + + std::string Evaluate( + const std::vector& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + std::string tgtName = parameters.front(); + cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName); + if (!gt) { + std::ostringstream e; + e << "Objects of target \"" << tgtName + << "\" referenced but no such target exists."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + cmStateEnums::TargetType type = gt->GetType(); + if (type != cmStateEnums::EXECUTABLE && + type != cmStateEnums::SHARED_LIBRARY && + type != cmStateEnums::MODULE_LIBRARY) { + std::ostringstream e; + e << "Objects of target \"" << tgtName + << "\" referenced but is not one of the allowed target types " + << "(EXECUTABLE, SHARED, MODULE)."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + + if (auto* cli = gt->GetLinkInformation(context->Config)) { + std::vector dllPaths; + auto const& dlls = cli->GetRuntimeDLLs(); + + for (auto const& dll : dlls) { + if (auto loc = dll->MaybeGetLocation(context->Config)) { + dllPaths.emplace_back(*loc); + } + } + + return cmJoin(dllPaths, ";"); + } + + return ""; + } +} targetRuntimeDllsNode; + static const struct CompileFeaturesNode : public cmGeneratorExpressionNode { CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default) @@ -2603,6 +2653,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "TARGET_EXISTS", &targetExistsNode }, { "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode }, { "TARGET_GENEX_EVAL", &targetGenexEvalNode }, + { "TARGET_RUNTIME_DLLS", &targetRuntimeDllsNode }, { "GENEX_EVAL", &genexEvalNode }, { "BUILD_INTERFACE", &buildInterfaceNode }, { "INSTALL_INTERFACE", &installInterfaceNode }, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d7e9952a2fe..d3c99596140 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1062,6 +1062,20 @@ const std::string& cmGeneratorTarget::GetLocation( return location; } +cm::optional cmGeneratorTarget::MaybeGetLocation( + std::string const& config) const +{ + cm::optional location; + if (cmGeneratorTarget::ImportInfo const* imp = this->GetImportInfo(config)) { + if (!imp->Location.empty()) { + location = imp->Location; + } + } else { + location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); + } + return location; +} + std::vector const& cmGeneratorTarget::GetPreBuildCommands() const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 8fe70abfc14..2935e0bce0c 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -14,6 +14,8 @@ #include #include +#include + #include "cmLinkItem.h" #include "cmListFileCache.h" #include "cmPolicies.h" @@ -50,6 +52,9 @@ class cmGeneratorTarget bool CanCompileSources() const; const std::string& GetLocation(const std::string& config) const; + /** Get the full path to the target's main artifact, if known. */ + cm::optional MaybeGetLocation(std::string const& config) const; + std::vector const& GetPreBuildCommands() const; std::vector const& GetPreLinkCommands() const; std::vector const& GetPostBuildCommands() const; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index c842574109e..fed084119d3 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -258,6 +258,7 @@ add_RunCMake_test(GenEx-HOST_LINK) add_RunCMake_test(GenEx-DEVICE_LINK) add_RunCMake_test(GenEx-TARGET_FILE -DLINKER_SUPPORTS_PDB=${LINKER_SUPPORTS_PDB}) add_RunCMake_test(GenEx-GENEX_EVAL) +add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS) add_RunCMake_test(GeneratorExpression) add_RunCMake_test(GeneratorInstance) add_RunCMake_test(GeneratorPlatform) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt new file mode 100644 index 00000000000..ab1a20c7ebc --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake new file mode 100644 index 00000000000..edc495c94cb --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake @@ -0,0 +1,7 @@ +include(RunCMake) + +run_cmake(TARGET_RUNTIME_DLLS) +run_cmake(TARGET_RUNTIME_DLLS-static) +run_cmake(TARGET_RUNTIME_DLLS-target_link_libraries) +run_cmake(TARGET_RUNTIME_DLLS-target_link_libraries-cycle1) +run_cmake(TARGET_RUNTIME_DLLS-target_link_libraries-cycle2) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-check.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-check.cmake new file mode 100644 index 00000000000..e19598e1445 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-check.cmake @@ -0,0 +1,15 @@ +function(check_genex expected actual) + if(NOT expected STREQUAL actual) + string(APPEND RunCMake_TEST_FAILED "Expected DLLs:\n") + foreach(dll IN LISTS expected) + string(APPEND RunCMake_TEST_FAILED " ${dll}\n") + endforeach() + string(APPEND RunCMake_TEST_FAILED "Actual DLLs:\n") + foreach(dll IN LISTS actual) + string(APPEND RunCMake_TEST_FAILED " ${dll}\n") + endforeach() + endif() + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +include("${RunCMake_TEST_BINARY_DIR}/dlls.cmake") diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt new file mode 100644 index 00000000000..7ce588a7421 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at TARGET_RUNTIME_DLLS-static\.cmake:[0-9]+ \(file\): + Error evaluating generator expression: + + \$ + + Objects of target "static" referenced but is not one of the allowed target + types \(EXECUTABLE, SHARED, MODULE\)\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static.cmake new file mode 100644 index 00000000000..dc900ddf190 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +add_library(static STATIC static.c) +set(condition) +get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(multi_config) + set(condition CONDITION "$") +endif() +file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/dlls.txt" CONTENT "$" ${condition}) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt new file mode 100644 index 00000000000..8cfcf7e41a1 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at TARGET_RUNTIME_DLLS-target_link_libraries-cycle1\.cmake:[0-9]+ \(add_library\): + The SOURCES of "lib1" use a generator expression that depends on the + SOURCES themselves\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake new file mode 100644 index 00000000000..f19e9e6a73b --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_library(lib1 SHARED lib1.c) +target_link_libraries(lib1 PRIVATE $) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt new file mode 100644 index 00000000000..bacbf63b7d4 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at TARGET_RUNTIME_DLLS-target_link_libraries-cycle2\.cmake:[0-9]+ \(add_library\): + The SOURCES of "(lib1|lib2)" use a generator expression that depends on the + SOURCES themselves\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake new file mode 100644 index 00000000000..7d035bd876f --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +add_library(lib1 SHARED lib1.c) +add_library(lib2 SHARED lib2.c) +target_link_libraries(lib1 PRIVATE $) +target_link_libraries(lib2 PRIVATE $) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries.cmake new file mode 100644 index 00000000000..f44dbf4b189 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries.cmake @@ -0,0 +1,5 @@ +enable_language(C) + +add_library(lib1 SHARED lib1.c) +add_library(lib2 SHARED lib2.c) +target_link_libraries(lib1 PRIVATE $) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS.cmake new file mode 100644 index 00000000000..806f0b60f20 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS.cmake @@ -0,0 +1,37 @@ +enable_language(C) + +add_executable(exe main.c) +add_library(lib1 SHARED lib1.c) +add_library(lib2 SHARED lib2.c) +add_library(lib3 SHARED lib3.c) +add_library(static STATIC static.c) +add_library(imported SHARED IMPORTED) +set_property(TARGET imported PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/imported.dll") +set_property(TARGET imported PROPERTY IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/imported.lib") +add_library(imported2 SHARED IMPORTED) +if(NOT WIN32 AND NOT CYGWIN) + set_property(TARGET imported2 PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/imported2.dll") +endif() +set_property(TARGET imported2 PROPERTY IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/imported2.lib") + +target_link_libraries(exe PRIVATE lib1 static imported imported2) +target_link_libraries(lib1 PRIVATE lib2) +target_link_libraries(lib1 INTERFACE lib3) + +set(expected_dlls "") +if(WIN32 OR CYGWIN) + set(expected_dlls + "$" + "$" + "$" + "$" + ) +endif() + +set(content "check_genex(\"${expected_dlls}\" \"$\")\n") +set(condition) +get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(multi_config) + set(condition CONDITION "$") +endif() +file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/dlls.cmake" CONTENT "${content}" ${condition}) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c new file mode 100644 index 00000000000..524b5b22fad --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib1.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void lib2(void); + +#ifdef _WIN32 +__declspec(dllexport) +#endif + void lib1(void) +{ + lib2(); +} diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c new file mode 100644 index 00000000000..e145117477b --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib2.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + void lib2(void) +{ +} diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c new file mode 100644 index 00000000000..5392f7a3c81 --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/lib3.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + void lib3(void) +{ +} diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c new file mode 100644 index 00000000000..8488f4e58fe --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c new file mode 100644 index 00000000000..7f5dab50a7b --- /dev/null +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.c @@ -0,0 +1,3 @@ +void static_func(void) +{ +} From f31e8d33ef5ca31ae7881157e660fc74dcde3ffa Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 24 Feb 2021 09:51:13 -0500 Subject: [PATCH 0038/1519] Genex: Fix grammatical error in TARGET_OBJECTS error message --- Source/cmGeneratorExpressionNode.cxx | 4 ++-- .../File_Generate/OutputNameMatchesObjects-stderr.txt | 4 ++-- Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt | 4 ++-- Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index da1a78e94fc..71251705a89 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1629,8 +1629,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode type != cmStateEnums::OBJECT_LIBRARY) { std::ostringstream e; e << "Objects of target \"" << tgtName - << "\" referenced but is not an allowed library types (EXECUTABLE, " - << "STATIC, SHARED, MODULE, OBJECT)."; + << "\" referenced but is not one of the allowed target types " + << "(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT)."; reportError(context, content->GetOriginalExpression(), e.str()); return std::string(); } diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt index 4c2e35fcc74..4d7370c472b 100644 --- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt +++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt @@ -3,7 +3,7 @@ CMake Error at OutputNameMatchesObjects.cmake:[0-9]+ \(file\): \$ - Objects of target "foo" referenced but is not an allowed library types - \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\). + Objects of target "foo" referenced but is not one of the allowed target + types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\). Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt index 4dbd8614420..6a7c17167b3 100644 --- a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt @@ -3,7 +3,7 @@ CMake Error at BadSourceExpression3.cmake:2 \(add_library\): \$ - Objects of target "NotObjLib" referenced but is not an allowed library - types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\). + Objects of target "NotObjLib" referenced but is not one of the allowed + target types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\). Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt index 77c4afd0816..9145a56e646 100644 --- a/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt +++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt @@ -3,7 +3,7 @@ CMake Error at NotObjlibTarget.cmake:[0-9]+ \(file\): \$ - Objects of target "IFaceLib" referenced but is not an allowed library types - \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\). + Objects of target "IFaceLib" referenced but is not one of the allowed + target types \(EXECUTABLE, STATIC, SHARED, MODULE, OBJECT\). Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) From 12cc87281f082fb6431368c69a42616188bf4dcf Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 25 Feb 2021 00:01:15 -0500 Subject: [PATCH 0039/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4503c0b704e..1db59d3c09e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210224) +set(CMake_VERSION_PATCH 20210225) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ebcb8896e31abfeb37422bf0ac6501b2f26ee3d0 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Thu, 25 Feb 2021 21:13:34 +1100 Subject: [PATCH 0040/1519] Help: Add missing MD5= for URL_HASH in FetchContent example Fixes: #21859 --- Modules/FetchContent.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 6a4cf388842..722490042b0 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -132,7 +132,7 @@ Declaring Content Details FetchContent_Declare( myCompanyIcons URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz - URL_HASH 5588a7b18261c20068beabfb4f530b87 + URL_HASH MD5=5588a7b18261c20068beabfb4f530b87 ) FetchContent_Declare( From 24b467c043a600c301f8e3037712fb18ed9a9ae4 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Fri, 19 Feb 2021 14:32:22 +0100 Subject: [PATCH 0041/1519] Help: Prefer commit hashes in FetchContent examples for security reasons Fixes: #21841 Co-Authored-By: Craig Scott --- Modules/FetchContent.cmake | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 722490042b0..297eec794f8 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -34,7 +34,7 @@ The following shows a typical example of declaring content details: FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.8.0 + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 ) For most typical cases, populating the content can then be done with a single @@ -126,7 +126,7 @@ Declaring Content Details FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.8.0 + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 ) FetchContent_Declare( @@ -141,6 +141,11 @@ Declaring Content Details SVN_REVISION -r12345 ) + Where contents are being fetched from a remote location and you do not + control that server, it is advisable to use a hash for ``GIT_TAG`` rather + than a branch or tag name. A commit hash is more secure and helps to + confirm that the downloaded contents are what you expected. + Populating The Content """""""""""""""""""""" @@ -456,12 +461,12 @@ frameworks are available to the main build: FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.8.0 + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 ) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v2.5.0 + GIT_TAG de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4 ) # After the following call, the CMake targets defined by googletest and @@ -480,7 +485,7 @@ it into the main build: FetchContent_Declare( protobuf GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git - GIT_TAG v3.12.0 + GIT_TAG ae50d9b9902526efd6c7a1907d09739f959c6297 # v3.15.0 SOURCE_SUBDIR cmake ) set(protobuf_BUILD_TESTS OFF) @@ -517,7 +522,7 @@ that all five projects are available on a company git server. The FetchContent_Declare( projE GIT_REPOSITORY git@mycompany.com:git/projE.git - GIT_TAG origin/release/2.3-rc1 + GIT_TAG v2.3-rc1 ) # Order is important, see notes in the discussion further below From 01e9922db5877bc8816f1efff5513f1cd01b70a2 Mon Sep 17 00:00:00 2001 From: Sibi Siddharthan Date: Tue, 23 Feb 2021 21:49:15 +0530 Subject: [PATCH 0042/1519] FindIconv: Add version support Issue: #21857 --- Help/release/dev/FindIconv-version.rst | 4 +++ Modules/FindIconv.cmake | 44 +++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/FindIconv-version.rst diff --git a/Help/release/dev/FindIconv-version.rst b/Help/release/dev/FindIconv-version.rst new file mode 100644 index 00000000000..3546d865111 --- /dev/null +++ b/Help/release/dev/FindIconv-version.rst @@ -0,0 +1,4 @@ +FindIconv-version +----------------- + +* The :module:`FindIconv` module now has version support. diff --git a/Modules/FindIconv.cmake b/Modules/FindIconv.cmake index 41b75509fa3..5ec12b2c7a6 100644 --- a/Modules/FindIconv.cmake +++ b/Modules/FindIconv.cmake @@ -25,6 +25,24 @@ The following variables are provided to indicate iconv support: The iconv libraries to be linked. +.. variable:: Iconv_VERSION + + .. versionadded:: 3.21 + + The version of iconv found (x.y) + +.. variable:: Iconv_VERSION_MAJOR + + .. versionadded:: 3.21 + + The major version of iconv + +.. variable:: Iconv_VERSION_MINOR + + .. versionadded:: 3.21 + + The minor version of iconv + .. variable:: Iconv_IS_BUILT_IN A variable indicating whether iconv support is stemming from the @@ -51,6 +69,10 @@ The following cache variables may also be set: On POSIX platforms, iconv might be part of the C library and the cache variables ``Iconv_INCLUDE_DIR`` and ``Iconv_LIBRARY`` might be empty. +.. note:: + Some libiconv implementations don't embed the version number in their header files. + In this case the variables ``Iconv_VERSION*`` will be empty. + #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) @@ -118,9 +140,29 @@ find_library(Iconv_LIBRARY mark_as_advanced(Iconv_INCLUDE_DIR) mark_as_advanced(Iconv_LIBRARY) +# NOTE: glibc's iconv.h does not define _LIBICONV_VERSION +if(Iconv_INCLUDE_DIR AND NOT Iconv_IS_BUILT_IN) + file(STRINGS ${Iconv_INCLUDE_DIR}/iconv.h Iconv_VERSION_DEFINE REGEX "_LIBICONV_VERSION (.*)") + + if(Iconv_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)") + set(Iconv_VERSION_NUMBER "${CMAKE_MATCH_1}") + # encoding -> version number: (major<<8) + minor + math(EXPR Iconv_VERSION_MAJOR "${Iconv_VERSION_NUMBER} >> 8" OUTPUT_FORMAT HEXADECIMAL) + math(EXPR Iconv_VERSION_MINOR "${Iconv_VERSION_NUMBER} - (${Iconv_VERSION_MAJOR} << 8)" OUTPUT_FORMAT HEXADECIMAL) + + math(EXPR Iconv_VERSION_MAJOR "${Iconv_VERSION_MAJOR}" OUTPUT_FORMAT DECIMAL) + math(EXPR Iconv_VERSION_MINOR "${Iconv_VERSION_MINOR}" OUTPUT_FORMAT DECIMAL) + set(Iconv_VERSION "${Iconv_VERSION_MAJOR}.${Iconv_VERSION_MINOR}") + endif() + + unset(Iconv_VERSION_DEFINE) + unset(Iconv_VERSION_NUMBER) +endif() + include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) if(NOT Iconv_IS_BUILT_IN) - find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR) + find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR + VERSION_VAR Iconv_VERSION) else() find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY) endif() From a9b11a06f56c79f13253c31c46c9e8405fdf6deb Mon Sep 17 00:00:00 2001 From: Sibi Siddharthan Date: Tue, 23 Feb 2021 21:50:24 +0530 Subject: [PATCH 0043/1519] FindIntl: Add version support Additional Changes: Rework the documentation of FindIntl NOTES: Reorder the REQUIRED_VARS arguments so find_package reports the library instead of the include directory. Handle Intl_LIBRARY in the same way how FindIconv handles it in case of glibc. If the VERSION_VAR argument is an empty string nothing happens. Fixes: #21857 --- Help/release/dev/FindIntl-version.rst | 4 + Modules/FindIntl.cmake | 117 +++++++++++++++++++++----- 2 files changed, 100 insertions(+), 21 deletions(-) create mode 100644 Help/release/dev/FindIntl-version.rst diff --git a/Help/release/dev/FindIntl-version.rst b/Help/release/dev/FindIntl-version.rst new file mode 100644 index 00000000000..5365cf1d9d7 --- /dev/null +++ b/Help/release/dev/FindIntl-version.rst @@ -0,0 +1,4 @@ +FindIntl-version +---------------- + +* The :module:`FindIntl` module now has version support. diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake index 686c8180103..a1dfed1180e 100644 --- a/Modules/FindIntl.cmake +++ b/Modules/FindIntl.cmake @@ -10,27 +10,75 @@ FindIntl Find the Gettext libintl headers and libraries. This module reports information about the Gettext libintl -installation in several variables. General variables:: +installation in several variables. - Intl_FOUND - true if the libintl headers and libraries were found - Intl_INCLUDE_DIRS - the directory containing the libintl headers - Intl_LIBRARIES - libintl libraries to be linked +.. variable:: Intl_FOUND + + True if libintl is found. + +.. variable:: Intl_INCLUDE_DIRS + + The directory containing the libintl headers. + +.. variable:: Intl_LIBRARIES + + The intl libraries to be linked. + +.. variable:: Intl_VERSION + + .. versionadded:: 3.21 + + The version of intl found (x.y.z) + +.. variable:: Intl_VERSION_MAJOR + + .. versionadded:: 3.21 + + The major version of intl + +.. variable:: Intl_VERSION_MINOR + + .. versionadded:: 3.21 + + The minor version of intl + +.. variable:: Intl_VERSION_PATCH + + .. versionadded:: 3.21 + + The patch version of intl .. versionadded:: 3.20 This module defines :prop_tgt:`IMPORTED` target ``Intl::Intl``. -The following cache variables may also be set:: +The following cache variables may also be set: - Intl_INCLUDE_DIR - the directory containing the libintl headers - Intl_LIBRARY - the libintl library (if any) - Intl_HAVE_GETTEXT_BUILTIN - check if gettext is in the C library - Intl_HAVE_DCGETTEXT_BUILTIN - check if dcgettext is in the C library - Intl_IS_BUILTIN - whether intl is a part of the C library determined - from the result of Intl_HAVE_GETTEXT_BUILTIN and Intl_HAVE_DCGETTEXT_BUILTIN +.. variable:: Intl_INCLUDE_DIR -.. versionadded:: 3.20 - Added the ``Intl_HAVE_GETTEXT_BUILTIN``, ``Intl_HAVE_DCGETTEXT_BUILTIN`` and - ``Intl_IS_BUILTIN`` variables. + The directory containing the libintl headers + +.. variable:: Intl_LIBRARY + + The libintl library (if any) + +.. variable:: Intl_HAVE_GETTEXT_BUILTIN + + .. versionadded:: 3.20 + + True if gettext is in the C library + +.. variable:: Intl_HAVE_DCGETTEXT_BUILTIN + + .. versionadded:: 3.20 + + True if dcgettext is in the C library + +.. variable:: Intl_IS_BUILTIN + + .. versionadded:: 3.20 + + whether intl is a part of the C library determined from the result of + Intl_HAVE_GETTEXT_BUILTIN and Intl_HAVE_DCGETTEXT_BUILTIN .. note:: On some platforms, such as Linux with GNU libc, the gettext @@ -38,6 +86,10 @@ The following cache variables may also be set:: is not required. ``Intl_LIBRARIES`` will be empty in this case. +.. note:: + Some libintl implementations don't embed the version number in their header files. + In this case the variables ``Intl_VERSION*`` will be empty. + .. note:: If you wish to use the Gettext tools (``msgmerge``, ``msgfmt``, etc.), use :module:`FindGettext`. @@ -69,20 +121,43 @@ find_path(Intl_INCLUDE_DIR mark_as_advanced(Intl_INCLUDE_DIR) # Find all Intl libraries -set(Intl_REQUIRED_VARS) if(NOT Intl_IS_BUILTIN) - find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR - DOC "libintl libraries (if not in the C library)") - mark_as_advanced(Intl_LIBRARY) - list(APPEND Intl_REQUIRED_VARS Intl_LIBRARY) + set(Intl_LIBRARY_NAMES "intl" "libintl") +else() + set(Intl_LIBRARY_NAMES "c") +endif() + +find_library(Intl_LIBRARY ${Intl_LIBRARY_NAMES} NAMES_PER_DIR + DOC "intl library (potentially the C library)") +mark_as_advanced(Intl_LIBRARY) + +# NOTE: glibc's libintl.h does not define LIBINTL_VERSION +if(Intl_INCLUDE_DIR AND NOT Intl_IS_BUILTIN) + file(STRINGS ${Intl_INCLUDE_DIR}/libintl.h Intl_VERSION_DEFINE REGEX "LIBINTL_VERSION (.*)") + + if(Intl_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)") + set(Intl_VERSION_NUMBER "${CMAKE_MATCH_1}") + # encoding -> version number: (major<<16) + (minor<<8) + patch + math(EXPR Intl_VERSION_MAJOR "${Intl_VERSION_NUMBER} >> 16" OUTPUT_FORMAT HEXADECIMAL) + math(EXPR Intl_VERSION_MINOR "(${Intl_VERSION_NUMBER} - (${Intl_VERSION_MAJOR} << 16)) >> 8" OUTPUT_FORMAT HEXADECIMAL) + math(EXPR Intl_VERSION_PATCH "${Intl_VERSION_NUMBER} - ((${Intl_VERSION_MAJOR} << 16) + (${Intl_VERSION_MINOR} << 8))" OUTPUT_FORMAT HEXADECIMAL) + + math(EXPR Intl_VERSION_MAJOR "${Intl_VERSION_MAJOR}" OUTPUT_FORMAT DECIMAL) + math(EXPR Intl_VERSION_MINOR "${Intl_VERSION_MINOR}" OUTPUT_FORMAT DECIMAL) + math(EXPR Intl_VERSION_PATCH "${Intl_VERSION_PATCH}" OUTPUT_FORMAT DECIMAL) + set(Intl_VERSION "${Intl_VERSION_MAJOR}.${Intl_VERSION_MINOR}.${Intl_VERSION_PATCH}") + endif() + + unset(Intl_VERSION_DEFINE) + unset(Intl_VERSION_NUMBER) endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl FOUND_VAR Intl_FOUND - REQUIRED_VARS Intl_INCLUDE_DIR ${Intl_REQUIRED_VARS} + REQUIRED_VARS Intl_LIBRARY Intl_INCLUDE_DIR + VERSION_VAR Intl_VERSION FAIL_MESSAGE "Failed to find Gettext libintl") -unset(Intl_REQUIRED_VARS) if(Intl_FOUND) set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}") From 7596d8b951e34c61b73e54a38cca86bdcf89dad8 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 7 Feb 2021 11:27:21 +0200 Subject: [PATCH 0044/1519] CMakeCCompilerId: Fix C standard detection in Clang MSVC mode Clang doesn't define __STDC__ if in MSVC compatibility mode, but does define __STDC_VERSION__. Avoid the fallback for this combination. --- Modules/CMakeCCompilerId.c.in | 5 ++--- Tests/RunCMake/CMakeLists.txt | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index 8ba6abc7da2..e6662b833af 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -33,9 +33,8 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; @CMAKE_C_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_C_COMPILER_ID_ERROR_FOR_TEST@ -#if !defined(__STDC__) -# if (defined(_MSC_VER) && !defined(__clang__)) \ - || (defined(__ibmxl__) || defined(__IBMC__)) +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) # define C_DIALECT "90" # else # define C_DIALECT diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index fed084119d3..5f8ff424ddf 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -417,6 +417,13 @@ function(add_RunCMake_test_try_compile) set(CMAKE_C_STANDARD_DEFAULT "") endif() endif() + if(CMAKE_VERSION VERSION_LESS 3.20.20210225 AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang") + # Older CMake versions do not know about Clang MSVC compatibility mode + # standards. Approximate the logic from Clang-C.cmake. + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5.2) + set(CMAKE_C_STANDARD_DEFAULT 11) + endif() + endif() foreach(var CMAKE_SYSTEM_NAME CMAKE_C_COMPILER_ID From f112450ea0d5d1784e24f6b4aae4212700f566c1 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 13 Feb 2021 10:12:12 +0200 Subject: [PATCH 0045/1519] Clang: C flags cleanup Don't need to set the options to empty strings if not supported. --- Modules/Compiler/Clang-C.cmake | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index 5609abf47ef..e9059096754 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -26,31 +26,29 @@ elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") endif() if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) + set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) + if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") - set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") - set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") - set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) else() # clang-cl doesn't have any of these set(CMAKE_C90_STANDARD_COMPILE_OPTION "") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") - set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C99_STANDARD_COMPILE_OPTION "") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "") - set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C11_STANDARD_COMPILE_OPTION "") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") - set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) endif() endif() From 356e83c156a37d5882685da11aa8d5be057cad33 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 13 Feb 2021 10:21:52 +0200 Subject: [PATCH 0046/1519] Clang: Correct C standards flags for ancient versions C89, C99 flags in LLVM commit ff43821d5380ee38aff421701f1d461242b524ee. C90 flag in LLVM commit 229ce60fc9983df5f7e83e25fa6b5c0ca4d2b135. C1x flag in LLVM commit a686b5f8bf7b5a2ab636c0c2de5ad4c174aa33e0. C11 flag in LLVM commit 6784aeb9ef96e5735850fa7226ed0cb45cb82e75. Mark C90, C99 full support since 2.1. Might've been possibly a little later, but source spelunking that much back is difficult. Mark C11 full support since 3.0, which added _Static_assert in LLVM commit 3d9cbdc3e66e274d5d3cb94ce81a65478d9baae0. --- Modules/Compiler/Clang-C.cmake | 37 ++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index e9059096754..220e009bb02 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -25,31 +25,38 @@ elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") endif() endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) - set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) - set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) - set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) - - if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") +if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") + endif() + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.1) set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") - else() - # clang-cl doesn't have any of these - set(CMAKE_C90_STANDARD_COMPILE_OPTION "") - set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") + elseif(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0) + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c1x") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") + endif() +else() + set(CMAKE_C90_STANDARD_COMPILE_OPTION "") + set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "") + set(CMAKE_C11_STANDARD_COMPILE_OPTION "") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") +endif() - set(CMAKE_C99_STANDARD_COMPILE_OPTION "") - set(CMAKE_C99_EXTENSION_COMPILE_OPTION "") +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1) + set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) +endif() - set(CMAKE_C11_STANDARD_COMPILE_OPTION "") - set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") - endif() +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0) + set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) endif() if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") From 58d9525233e4ffca1c7edc7a5978770a0e4ec36d Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 13 Feb 2021 10:56:37 +0200 Subject: [PATCH 0047/1519] Clang: Correct default C standards for ancient versions C11 was made default in LLVM commit ab506adf7d3ced6abcaf42f92de3d6cd15fa19e8, released in 3.5.2. C99 was made default in LLVM commit 17f76e04d244c80e70f1c81c94d4524b53d9772d, released in 2.1. It was flipped a few times between C89 and C99 during the 2.1 cycle, but the C89 default never made it into a release. --- Modules/Compiler/Clang-C.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index 220e009bb02..dc472d46470 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -60,7 +60,7 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0) endif() if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - __compiler_check_default_language_standard(C 3.4 99 3.6 11) + __compiler_check_default_language_standard(C 2.1 99 3.5.2 11) else() set(CMAKE_C_STANDARD_DEFAULT "") endif() From 93b7d3d29221f98388c7fa20568cd0b769a26774 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 6 Feb 2021 18:54:13 +0200 Subject: [PATCH 0048/1519] C17 support Implements #17755. --- Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst | 3 +++ Help/prop_tgt/C_STANDARD.rst | 2 +- Help/release/dev/c-std.rst | 6 ++++++ Modules/CMakeCCompiler.cmake.in | 1 + Modules/CMakeCCompilerId.c.in | 2 ++ Modules/CMakeDetermineCompileFeatures.cmake | 6 ++++++ Modules/Compiler/CMakeCommonCompilerMacros.cmake | 3 +++ Source/cmStandardLevelResolver.cxx | 5 +++-- Source/cmake.h | 1 + Tests/CompileFeatures/CMakeLists.txt | 1 + Tests/CompileFeatures/default_dialect.c | 6 +++++- 11 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/c-std.rst diff --git a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst index 7166381aa4d..9ea63faea24 100644 --- a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst @@ -24,6 +24,9 @@ The features known to this version of CMake are: ``c_std_11`` Compiler mode is at least C 11. +``c_std_17`` + Compiler mode is at least C 17. + ``c_function_prototypes`` Function prototypes, as defined in ``ISO/IEC 9899:1990``. diff --git a/Help/prop_tgt/C_STANDARD.rst b/Help/prop_tgt/C_STANDARD.rst index 3f0d242f497..4fbde3586bc 100644 --- a/Help/prop_tgt/C_STANDARD.rst +++ b/Help/prop_tgt/C_STANDARD.rst @@ -11,7 +11,7 @@ flag such as ``-std=gnu11`` to the compile line. For compilers that have no notion of a C standard level, such as Microsoft Visual C++ before VS 16.7, this property has no effect. -Supported values are ``90``, ``99`` and ``11``. +Supported values are ``90``, ``99``, ``11``, ``17``. If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This diff --git a/Help/release/dev/c-std.rst b/Help/release/dev/c-std.rst new file mode 100644 index 00000000000..475a4e49592 --- /dev/null +++ b/Help/release/dev/c-std.rst @@ -0,0 +1,6 @@ +c-std +----- + +* :prop_tgt:`C_STANDARD` and the + :manual:`Compile Features ` functionality gained + support for C17. diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 7f73891fafc..74487d1966e 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -9,6 +9,7 @@ set(CMAKE_C_COMPILE_FEATURES "@CMAKE_C_COMPILE_FEATURES@") set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@") set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@") set(CMAKE_C11_COMPILE_FEATURES "@CMAKE_C11_COMPILE_FEATURES@") +set(CMAKE_C17_COMPILE_FEATURES "@CMAKE_C17_COMPILE_FEATURES@") set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@") set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@") diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index e6662b833af..f1175f4e9f2 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -39,6 +39,8 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; # else # define C_DIALECT # endif +#elif __STDC_VERSION__ >= 201710L +# define C_DIALECT "17" #elif __STDC_VERSION__ >= 201000L # define C_DIALECT "11" #elif __STDC_VERSION__ >= 199901L diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake index c03a85fdbfd..49b8169f532 100644 --- a/Modules/CMakeDetermineCompileFeatures.cmake +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -10,6 +10,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_C90_COMPILE_FEATURES) set(CMAKE_C99_COMPILE_FEATURES) set(CMAKE_C11_COMPILE_FEATURES) + set(CMAKE_C17_COMPILE_FEATURES) include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") @@ -20,6 +21,9 @@ function(cmake_determine_compile_features lang) return() endif() + if (CMAKE_C11_COMPILE_FEATURES AND CMAKE_C17_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_C17_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES}) + endif() if (CMAKE_C99_COMPILE_FEATURES AND CMAKE_C11_COMPILE_FEATURES) list(REMOVE_ITEM CMAKE_C11_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES}) endif() @@ -32,6 +36,7 @@ function(cmake_determine_compile_features lang) ${CMAKE_C90_COMPILE_FEATURES} ${CMAKE_C99_COMPILE_FEATURES} ${CMAKE_C11_COMPILE_FEATURES} + ${CMAKE_C17_COMPILE_FEATURES} ) endif() @@ -39,6 +44,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_C90_COMPILE_FEATURES ${CMAKE_C90_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_C99_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_C11_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_C17_COMPILE_FEATURES ${CMAKE_C17_COMPILE_FEATURES} PARENT_SCOPE) message(CHECK_PASS "done") diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index cd897c527ef..ac20d5f6ebe 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -64,6 +64,9 @@ endmacro() # Define to allow compile features to be automatically determined macro(cmake_record_c_compile_features) set(_result 0) + if(_result EQUAL 0 AND DEFINED CMAKE_C17_STANDARD_COMPILE_OPTION) + _has_compiler_features_c(17) + endif() if(_result EQUAL 0 AND DEFINED CMAKE_C11_STANDARD_COMPILE_OPTION) if(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT) _has_compiler_features_c(11) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index bf6925e8748..e290663dfdc 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -308,8 +308,9 @@ struct StanardLevelComputer std::unordered_map StandardComputerMapping = { { "C", - StanardLevelComputer{ "C", std::vector{ 90, 99, 11 }, - std::vector{ "90", "99", "11" } } }, + StanardLevelComputer{ + "C", std::vector{ 90, 99, 11, 17 }, + std::vector{ "90", "99", "11", "17" } } }, { "CXX", StanardLevelComputer{ "CXX", std::vector{ 98, 11, 14, 17, 20, 23 }, diff --git a/Source/cmake.h b/Source/cmake.h index 82e028c31b0..95eb1136044 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -739,6 +739,7 @@ class cmake F(c_std_90) \ F(c_std_99) \ F(c_std_11) \ + F(c_std_17) \ FOR_EACH_C90_FEATURE(F) \ FOR_EACH_C99_FEATURE(F) \ FOR_EACH_C11_FEATURE(F) diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index cff98e3c50f..046b858c77d 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -237,6 +237,7 @@ if (C_expected_features) if (std_flag_idx EQUAL -1) add_executable(default_dialect_C default_dialect.c) target_compile_definitions(default_dialect_C PRIVATE + DEFAULT_C17=$ DEFAULT_C11=$ DEFAULT_C99=$ DEFAULT_C90=$ diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c index 6160c2f4413..e0900676f30 100644 --- a/Tests/CompileFeatures/default_dialect.c +++ b/Tests/CompileFeatures/default_dialect.c @@ -1,5 +1,9 @@ -#if DEFAULT_C11 +#if DEFAULT_C17 +# if __STDC_VERSION__ < 201710L +# error Unexpected value for __STDC_VERSION__. +# endif +#elif DEFAULT_C11 # if __STDC_VERSION__ < 201112L # error Unexpected value for __STDC_VERSION__. # endif From dcd599757f215fa8eba3b5e40d4b1c52eb5b3919 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 6 Feb 2021 18:59:23 +0200 Subject: [PATCH 0049/1519] C23 support --- Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst | 3 +++ Help/prop_tgt/C_STANDARD.rst | 2 +- Help/release/dev/c-std.rst | 2 +- Modules/CMakeCCompiler.cmake.in | 1 + Modules/CMakeCCompilerId.c.in | 2 ++ Modules/CMakeDetermineCompileFeatures.cmake | 6 ++++++ Modules/Compiler/CMakeCommonCompilerMacros.cmake | 3 +++ Source/cmStandardLevelResolver.cxx | 4 ++-- Source/cmake.h | 1 + Tests/CompileFeatures/CMakeLists.txt | 1 + Tests/CompileFeatures/default_dialect.c | 6 +++++- 11 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst index 9ea63faea24..2bd0febeaa0 100644 --- a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst @@ -27,6 +27,9 @@ The features known to this version of CMake are: ``c_std_17`` Compiler mode is at least C 17. +``c_std_23`` + Compiler mode is at least C 23. + ``c_function_prototypes`` Function prototypes, as defined in ``ISO/IEC 9899:1990``. diff --git a/Help/prop_tgt/C_STANDARD.rst b/Help/prop_tgt/C_STANDARD.rst index 4fbde3586bc..e22b775d13e 100644 --- a/Help/prop_tgt/C_STANDARD.rst +++ b/Help/prop_tgt/C_STANDARD.rst @@ -11,7 +11,7 @@ flag such as ``-std=gnu11`` to the compile line. For compilers that have no notion of a C standard level, such as Microsoft Visual C++ before VS 16.7, this property has no effect. -Supported values are ``90``, ``99``, ``11``, ``17``. +Supported values are ``90``, ``99``, ``11``, ``17``, ``23``. If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This diff --git a/Help/release/dev/c-std.rst b/Help/release/dev/c-std.rst index 475a4e49592..44daa85cd4a 100644 --- a/Help/release/dev/c-std.rst +++ b/Help/release/dev/c-std.rst @@ -3,4 +3,4 @@ c-std * :prop_tgt:`C_STANDARD` and the :manual:`Compile Features ` functionality gained - support for C17. + support for C17 and C23. diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 74487d1966e..754f235bae9 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -10,6 +10,7 @@ set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@") set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@") set(CMAKE_C11_COMPILE_FEATURES "@CMAKE_C11_COMPILE_FEATURES@") set(CMAKE_C17_COMPILE_FEATURES "@CMAKE_C17_COMPILE_FEATURES@") +set(CMAKE_C23_COMPILE_FEATURES "@CMAKE_C23_COMPILE_FEATURES@") set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@") set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@") diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index f1175f4e9f2..716b9757bc7 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -39,6 +39,8 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; # else # define C_DIALECT # endif +#elif __STDC_VERSION__ > 201710L +# define C_DIALECT "23" #elif __STDC_VERSION__ >= 201710L # define C_DIALECT "17" #elif __STDC_VERSION__ >= 201000L diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake index 49b8169f532..f767847936d 100644 --- a/Modules/CMakeDetermineCompileFeatures.cmake +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -11,6 +11,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_C99_COMPILE_FEATURES) set(CMAKE_C11_COMPILE_FEATURES) set(CMAKE_C17_COMPILE_FEATURES) + set(CMAKE_C23_COMPILE_FEATURES) include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") @@ -21,6 +22,9 @@ function(cmake_determine_compile_features lang) return() endif() + if (CMAKE_C17_COMPILE_FEATURES AND CMAKE_C23_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_C23_COMPILE_FEATURES ${CMAKE_C17_COMPILE_FEATURES}) + endif() if (CMAKE_C11_COMPILE_FEATURES AND CMAKE_C17_COMPILE_FEATURES) list(REMOVE_ITEM CMAKE_C17_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES}) endif() @@ -37,6 +41,7 @@ function(cmake_determine_compile_features lang) ${CMAKE_C99_COMPILE_FEATURES} ${CMAKE_C11_COMPILE_FEATURES} ${CMAKE_C17_COMPILE_FEATURES} + ${CMAKE_C23_COMPILE_FEATURES} ) endif() @@ -45,6 +50,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_C99_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_C11_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_C17_COMPILE_FEATURES ${CMAKE_C17_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_C23_COMPILE_FEATURES ${CMAKE_C23_COMPILE_FEATURES} PARENT_SCOPE) message(CHECK_PASS "done") diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index ac20d5f6ebe..29e673004c8 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -64,6 +64,9 @@ endmacro() # Define to allow compile features to be automatically determined macro(cmake_record_c_compile_features) set(_result 0) + if(_result EQUAL 0 AND DEFINED CMAKE_C23_STANDARD_COMPILE_OPTION) + _has_compiler_features_c(23) + endif() if(_result EQUAL 0 AND DEFINED CMAKE_C17_STANDARD_COMPILE_OPTION) _has_compiler_features_c(17) endif() diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index e290663dfdc..280e508d66e 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -309,8 +309,8 @@ std::unordered_map StandardComputerMapping = { { "C", StanardLevelComputer{ - "C", std::vector{ 90, 99, 11, 17 }, - std::vector{ "90", "99", "11", "17" } } }, + "C", std::vector{ 90, 99, 11, 17, 23 }, + std::vector{ "90", "99", "11", "17", "23" } } }, { "CXX", StanardLevelComputer{ "CXX", std::vector{ 98, 11, 14, 17, 20, 23 }, diff --git a/Source/cmake.h b/Source/cmake.h index 95eb1136044..d6d129ff164 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -740,6 +740,7 @@ class cmake F(c_std_99) \ F(c_std_11) \ F(c_std_17) \ + F(c_std_23) \ FOR_EACH_C90_FEATURE(F) \ FOR_EACH_C99_FEATURE(F) \ FOR_EACH_C11_FEATURE(F) diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 046b858c77d..7771967a120 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -237,6 +237,7 @@ if (C_expected_features) if (std_flag_idx EQUAL -1) add_executable(default_dialect_C default_dialect.c) target_compile_definitions(default_dialect_C PRIVATE + DEFAULT_C23=$ DEFAULT_C17=$ DEFAULT_C11=$ DEFAULT_C99=$ diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c index e0900676f30..b990e53258e 100644 --- a/Tests/CompileFeatures/default_dialect.c +++ b/Tests/CompileFeatures/default_dialect.c @@ -1,5 +1,9 @@ -#if DEFAULT_C17 +#if DEFAULT_C23 +# if __STDC_VERSION__ <= 201710L +# error Unexpected value for __STDC_VERSION__. +# endif +#elif DEFAULT_C17 # if __STDC_VERSION__ < 201710L # error Unexpected value for __STDC_VERSION__. # endif From 9024fb632eb236727d057f6d9f98e2b3b30df212 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 6 Feb 2021 18:20:19 +0200 Subject: [PATCH 0050/1519] Clang: C17 support Added in LLVM commit 5b6c0f75e01571851b767dc63a3229c962f464f1, available since Clang 6. Issue: #17755 --- Modules/Compiler/Clang-C.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index dc472d46470..e620d7cce4d 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -41,6 +41,11 @@ if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c1x") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() + + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") + endif() else() set(CMAKE_C90_STANDARD_COMPILE_OPTION "") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") @@ -48,6 +53,8 @@ else() set(CMAKE_C99_EXTENSION_COMPILE_OPTION "") set(CMAKE_C11_STANDARD_COMPILE_OPTION "") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") + set(CMAKE_C17_STANDARD_COMPILE_OPTION "") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "") endif() if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1) From 82239d43f8020cb50f03bf658e97c81afb611b9a Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 6 Feb 2021 18:25:47 +0200 Subject: [PATCH 0051/1519] Clang: C17 default version Switched in LLVM commit 91cdbd521a38495c66e30636943563ca70d3c022, released in Clang 11. Issue: #17755 --- Modules/Compiler/Clang-C.cmake | 2 +- Tests/RunCMake/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index e620d7cce4d..363a8c34e9f 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -67,7 +67,7 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0) endif() if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - __compiler_check_default_language_standard(C 2.1 99 3.5.2 11) + __compiler_check_default_language_standard(C 2.1 99 3.5.2 11 11.0 17) else() set(CMAKE_C_STANDARD_DEFAULT "") endif() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 5f8ff424ddf..354a04eca39 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -420,7 +420,9 @@ function(add_RunCMake_test_try_compile) if(CMAKE_VERSION VERSION_LESS 3.20.20210225 AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang") # Older CMake versions do not know about Clang MSVC compatibility mode # standards. Approximate the logic from Clang-C.cmake. - if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5.2) + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) + set(CMAKE_C_STANDARD_DEFAULT 17) + elseif(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5.2) set(CMAKE_C_STANDARD_DEFAULT 11) endif() endif() From 72f4984cdc0ed14a4c57e60a26d0710bc13f3723 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 7 Feb 2021 11:58:24 +0200 Subject: [PATCH 0052/1519] Clang: C23 support Added in LLVM commit d06f3917913d2558b771ccc48d838f8cd8993c01, released in Clang 9.0. --- Modules/Compiler/Clang-C.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index 363a8c34e9f..1b0b3ad4279 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -46,6 +46,11 @@ if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") endif() + + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9.0) + set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x") + set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x") + endif() else() set(CMAKE_C90_STANDARD_COMPILE_OPTION "") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") From 9f81591dbf5d8840f7193bb01ac0921fd5b2b687 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 6 Feb 2021 18:22:22 +0200 Subject: [PATCH 0053/1519] Clang: MSVC-style C flags Support added in LLVM commit d087d805acb664e885e9c31a916f6cfa5dbc2186, will be released in Clang 13. --- Modules/Compiler/Clang-C.cmake | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index 1b0b3ad4279..8f00a72e3d8 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -56,10 +56,20 @@ else() set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") set(CMAKE_C99_STANDARD_COMPILE_OPTION "") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "") - set(CMAKE_C11_STANDARD_COMPILE_OPTION "") - set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") - set(CMAKE_C17_STANDARD_COMPILE_OPTION "") - set(CMAKE_C17_EXTENSION_COMPILE_OPTION "") + + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + set(CMAKE_C11_STANDARD_COMPILE_OPTION "/std:c11") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "/std:c11") + + set(CMAKE_C17_STANDARD_COMPILE_OPTION "/std:c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "/std:c17") + else() + set(CMAKE_C11_STANDARD_COMPILE_OPTION "") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") + + set(CMAKE_C17_STANDARD_COMPILE_OPTION "") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "") + endif() endif() if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1) From 6c2e309a6667f0a6869becdeafcdc5e375116bda Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 6 Feb 2021 18:37:20 +0200 Subject: [PATCH 0054/1519] Clang: Set standard flags according to frontend variant They depend on the frontend not which compiler we're simulating. Fixes #21771. --- Modules/Compiler/Clang-C.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index 8f00a72e3d8..dc186072b39 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -25,7 +25,7 @@ elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") endif() endif() -if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") +if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 2.1) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") From 10a72c0f1c5e7e57ac61ff1f8a73acdd6e159c06 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 13 Feb 2021 10:40:12 +0200 Subject: [PATCH 0055/1519] Clang: Default C standard doesn't depend on compatibility mode MSVC compatibility mode doesn't affect the default standard. --- Modules/Compiler/Clang-C.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index dc186072b39..cf493d7200c 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -81,8 +81,4 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.0) set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) endif() -if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - __compiler_check_default_language_standard(C 2.1 99 3.5.2 11 11.0 17) -else() - set(CMAKE_C_STANDARD_DEFAULT "") -endif() +__compiler_check_default_language_standard(C 2.1 99 3.5.2 11 11.0 17) From c9f0613c2ace0714a48caf793889eedc605894ce Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 7 Feb 2021 12:08:16 +0200 Subject: [PATCH 0056/1519] GNU: C17 support Added in commit c76dc9c32d616eff1e0ae162042f1c0f8ca65fbf, released in 8.1. Set as default in the same commit. Issue: #17755 --- Modules/Compiler/GNU-C.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 86b4d83e546..4094717e85a 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -36,4 +36,9 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -__compiler_check_default_language_standard(C 3.4 90 5.0 11) +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1) + set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") +endif() + +__compiler_check_default_language_standard(C 3.4 90 5.0 11 8.1 17) From b9c3acac02b6202359e6964853521878e386ed06 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 7 Feb 2021 12:10:14 +0200 Subject: [PATCH 0057/1519] GNU: C23 support Added in commit 9f936c861383dc69e0053e34315d5d0262a19e8f, released in 9.1. --- Modules/Compiler/GNU-C.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 4094717e85a..39e9c72c442 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -41,4 +41,9 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1) set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") endif() +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9.1) + set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c23") + set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu23") +endif() + __compiler_check_default_language_standard(C 3.4 90 5.0 11 8.1 17) From 8211b4706f0ec1389fad073ef13937d99d6b13cc Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Thu, 18 Feb 2021 18:42:24 +0200 Subject: [PATCH 0058/1519] IntelLLVM: C17 support Issue: #17755 --- Modules/Compiler/IntelLLVM-C.cmake | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake index fce2971cacc..beb713242fc 100644 --- a/Modules/Compiler/IntelLLVM-C.cmake +++ b/Modules/Compiler/IntelLLVM-C.cmake @@ -37,6 +37,9 @@ if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") + + set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") else() # clang-cl doesn't have any of these set(CMAKE_C90_STANDARD_COMPILE_OPTION "") @@ -47,12 +50,13 @@ else() set(CMAKE_C11_STANDARD_COMPILE_OPTION "") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") + + set(CMAKE_C17_STANDARD_COMPILE_OPTION "") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "") endif() if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - # FIXME: The compiler actually defaults to C17, but - # CMake does not yet model or detect that standard. - __compiler_check_default_language_standard(C 2020 11) + __compiler_check_default_language_standard(C 2020 17) else() set(CMAKE_C_STANDARD_DEFAULT "") endif() From a133a583d484028f8b03bd791ebea8ba0cf96b84 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 24 Feb 2021 08:42:15 -0500 Subject: [PATCH 0059/1519] cmLocalGenerator: Clarify GetIncludeFlags signature Make the `config` argument non-optional so all callers must be explicit. Convert the path style argument to an enumeration to make its role clear at call sites. The path style argument is implemented by `ConvertToIncludeReference`, which was introduced with the Ninja generator by commit 5b114c9bee (Introduce a cmLocalGenerator::ConvertToIncludeReference function, 2011-09-07, v2.8.7~187^2~4). Its only purpose is to allow the Ninja generator to use relative paths in `-I` flags. Add a comment explaining this role. --- Source/cmExtraSublimeTextGenerator.cxx | 3 ++- Source/cmGlobalXCodeGenerator.cxx | 8 +++++-- Source/cmLocalGenerator.cxx | 12 +++++------ Source/cmLocalGenerator.h | 30 ++++++++++++++++---------- Source/cmLocalNinjaGenerator.cxx | 6 +++--- Source/cmLocalNinjaGenerator.h | 6 +++--- Source/cmMakefileTargetGenerator.cxx | 7 +++--- Source/cmNinjaTargetGenerator.cxx | 14 ++++++------ Source/cmake.cxx | 2 +- 9 files changed, 52 insertions(+), 36 deletions(-) diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index a92f6e32814..52965bb579b 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -435,7 +435,8 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes( lg->GetIncludeDirectories(includes, target, language, config); std::string includesString = - lg->GetIncludeFlags(includes, target, language, true, false, config); + lg->GetIncludeFlags(includes, target, language, config, false, + cmLocalGenerator::IncludePathStyle::Absolute); return includesString; } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8ecebae007b..37ef4fc08d3 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -991,7 +991,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), *sf); } - lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true)); + lg->AppendFlags( + flags, + lg->GetIncludeFlags(includes, gtgt, lang, std::string(), false, + cmLocalGenerator::IncludePathStyle::Absolute)); cmXCodeObject* buildFile = this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf); @@ -2695,7 +2698,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // GNU assembly files (#16449) for (auto const& language : languages) { std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags( - includes, gtgt, language, true, false, configName); + includes, gtgt, language, configName, false, + cmLocalGenerator::IncludePathStyle::Absolute); if (!includeFlags.empty()) { cflags[language] += " " + includeFlags; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 20d4df125ca..79d1de04e57 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -838,16 +838,16 @@ cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target, } std::string cmLocalGenerator::ConvertToIncludeReference( - std::string const& path, OutputFormat format, bool forceFullPaths) + std::string const& path, IncludePathStyle pathStyle, OutputFormat format) { - static_cast(forceFullPaths); + static_cast(pathStyle); return this->ConvertToOutputForExisting(path, format); } std::string cmLocalGenerator::GetIncludeFlags( - const std::vector& includeDirs, cmGeneratorTarget* target, - const std::string& lang, bool forceFullPaths, bool forResponseFile, - const std::string& config) + std::vector const& includeDirs, cmGeneratorTarget* target, + std::string const& lang, std::string const& config, bool forResponseFile, + IncludePathStyle pathStyle) { if (lang.empty()) { return ""; @@ -923,7 +923,7 @@ std::string cmLocalGenerator::GetIncludeFlags( flagUsed = true; } std::string includePath = - this->ConvertToIncludeReference(i, shellFormat, forceFullPaths); + this->ConvertToIncludeReference(i, pathStyle, shellFormat); if (quotePaths && !includePath.empty() && includePath.front() != '\"') { includeFlags << "\""; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index e48849a574b..f59712055bf 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -171,13 +171,19 @@ class cmLocalGenerator : public cmOutputConverter cmGeneratorTarget* target, const std::string& config, const std::string& lang); + + enum class IncludePathStyle + { + Default, + Absolute, + }; + //! Get the include flags for the current makefile and language - std::string GetIncludeFlags(const std::vector& includes, - cmGeneratorTarget* target, - const std::string& lang, - bool forceFullPaths = false, - bool forResponseFile = false, - const std::string& config = ""); + std::string GetIncludeFlags( + std::vector const& includes, cmGeneratorTarget* target, + std::string const& lang, std::string const& config, + bool forResponseFile = false, + IncludePathStyle pathStyle = IncludePathStyle::Default); using GeneratorTargetVector = std::vector>; @@ -256,11 +262,6 @@ class cmLocalGenerator : public cmOutputConverter bool GetRealDependency(const std::string& name, const std::string& config, std::string& dep); - virtual std::string ConvertToIncludeReference( - std::string const& path, - cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL, - bool forceFullPaths = false); - /** Called from command-line hook to clear dependencies. */ virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {} @@ -557,6 +558,13 @@ class cmLocalGenerator : public cmOutputConverter cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop); protected: + // The default implementation ignores the IncludePathStyle and always + // uses absolute paths. A generator may override this to use relative + // paths in some cases. + virtual std::string ConvertToIncludeReference( + std::string const& path, IncludePathStyle pathStyle, + cmOutputConverter::OutputFormat format); + //! put all the libraries for a target on into the given stream void OutputLinkLibraries(cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer, diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 8ed411a3ca5..64ff579dc2c 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -202,10 +202,10 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator() // Virtual protected methods. std::string cmLocalNinjaGenerator::ConvertToIncludeReference( - std::string const& path, cmOutputConverter::OutputFormat format, - bool forceFullPaths) + std::string const& path, IncludePathStyle pathStyle, + cmOutputConverter::OutputFormat format) { - if (forceFullPaths) { + if (pathStyle == IncludePathStyle::Absolute) { return this->ConvertToOutputFormat( cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()), format); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 5b850f3d09f..8b6824feea0 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -12,6 +12,7 @@ #include "cmListFileCache.h" #include "cmLocalCommonGenerator.h" +#include "cmLocalGenerator.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" @@ -91,9 +92,8 @@ class cmLocalNinjaGenerator : public cmLocalCommonGenerator protected: std::string ConvertToIncludeReference( - std::string const& path, - cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL, - bool forceFullPaths = false) override; + std::string const& path, IncludePathStyle pathStyle, + cmOutputConverter::OutputFormat format) override; private: cmGeneratedFileStream& GetImplFileStream(const std::string& config) const; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4918bf676a8..00bf891784e 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -854,7 +854,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.Defines = definesString.c_str(); std::string includesString = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, lang, true, false, config); + includes, this->GeneratorTarget, lang, config, false, + cmLocalGenerator::IncludePathStyle::Absolute); this->LocalGenerator->AppendFlags(includesString, "$(" + lang + "_INCLUDES)"); vars.Includes = includesString.c_str(); @@ -2195,8 +2196,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, lang, this->GetConfigName()); std::string includeFlags = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, lang, false, useResponseFile, - this->GetConfigName()); + includes, this->GeneratorTarget, lang, this->GetConfigName(), + useResponseFile, cmLocalGenerator::IncludePathStyle::Default); if (includeFlags.empty()) { return; } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 672b5797ed4..2e0ffdbdbe4 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -263,9 +263,10 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, language, config); // Add include directory flags. std::string includeFlags = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, language, - language == "RC", // full include paths for RC needed by cmcldeps - false, config); + includes, this->GeneratorTarget, language, config, false, + // full include paths for RC needed by cmcldeps + language == "RC" ? cmLocalGenerator::IncludePathStyle::Absolute + : cmLocalGenerator::IncludePathStyle::Default); if (this->GetGlobalGenerator()->IsGCCOnWindows()) { std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/'); } @@ -324,7 +325,8 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( } std::string includesString = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, language, true, false, config); + includes, this->GeneratorTarget, language, config, false, + cmLocalGenerator::IncludePathStyle::Absolute); this->LocalGenerator->AppendFlags(includesString, this->GetIncludes(language, config)); @@ -1379,8 +1381,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmSystemTools::GetParentDirectory(source->GetFullPath())); std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags( - sourceDirectory, this->GeneratorTarget, language, false, false, - config); + sourceDirectory, this->GeneratorTarget, language, config, false, + cmLocalGenerator::IncludePathStyle::Default); vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]); } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 4b573957279..7e6d5c31c07 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -649,7 +649,7 @@ bool cmake::FindPackage(const std::vector& args) this->GlobalGenerator->CreateGenerationObjects(); const auto& lg = this->GlobalGenerator->LocalGenerators[0]; std::string includeFlags = - lg->GetIncludeFlags(includeDirs, nullptr, language); + lg->GetIncludeFlags(includeDirs, nullptr, language, std::string()); std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); printf("%s %s\n", includeFlags.c_str(), definitions.c_str()); From 3e7dd3974777fc9af946d6b7db6ba72abfe4217c Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 24 Feb 2021 09:00:59 -0500 Subject: [PATCH 0060/1519] cmLocalGenerator: Simplify some GetIncludeFlag call sites The path style argument is meaningful only with the Ninja generator, so drop it from call sites in Makefile and Xcode generators. --- Source/cmGlobalXCodeGenerator.cxx | 9 +++------ Source/cmMakefileTargetGenerator.cxx | 5 ++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 37ef4fc08d3..cc075deeab1 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -991,10 +991,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), *sf); } - lg->AppendFlags( - flags, - lg->GetIncludeFlags(includes, gtgt, lang, std::string(), false, - cmLocalGenerator::IncludePathStyle::Absolute)); + lg->AppendFlags(flags, + lg->GetIncludeFlags(includes, gtgt, lang, std::string())); cmXCodeObject* buildFile = this->CreateXCodeBuildFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf); @@ -2698,8 +2696,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // GNU assembly files (#16449) for (auto const& language : languages) { std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags( - includes, gtgt, language, configName, false, - cmLocalGenerator::IncludePathStyle::Absolute); + includes, gtgt, language, configName); if (!includeFlags.empty()) { cflags[language] += " " + includeFlags; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 00bf891784e..fa469edac3b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -854,8 +854,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.Defines = definesString.c_str(); std::string includesString = this->LocalGenerator->GetIncludeFlags( - includes, this->GeneratorTarget, lang, config, false, - cmLocalGenerator::IncludePathStyle::Absolute); + includes, this->GeneratorTarget, lang, config); this->LocalGenerator->AppendFlags(includesString, "$(" + lang + "_INCLUDES)"); vars.Includes = includesString.c_str(); @@ -2197,7 +2196,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, lang, this->GetConfigName(), - useResponseFile, cmLocalGenerator::IncludePathStyle::Default); + useResponseFile); if (includeFlags.empty()) { return; } From 06bc2d065b7fecb40f22ed4c8ce72edf3ddebd3d Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 26 Feb 2021 00:01:16 -0500 Subject: [PATCH 0061/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1db59d3c09e..2c6b51355ef 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210225) +set(CMake_VERSION_PATCH 20210226) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9ff169d1a5b46b85571f44441f0b51e1ea183cde Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 27 Feb 2021 00:01:16 -0500 Subject: [PATCH 0062/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2c6b51355ef..b6e7ef2956c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210226) +set(CMake_VERSION_PATCH 20210227) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 79fa7529e027c5b341f08c804986453808275dd0 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 28 Feb 2021 11:34:05 +1100 Subject: [PATCH 0063/1519] FindDoxygen: Prevent CMP0054 policy warnings Fixes: #21871 --- Modules/FindDoxygen.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake index bbf941efb14..7fe5da137f8 100644 --- a/Modules/FindDoxygen.cmake +++ b/Modules/FindDoxygen.cmake @@ -395,6 +395,7 @@ Deprecated Hint Variables #]=======================================================================] cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # quoted if arguments cmake_policy(SET CMP0057 NEW) # if IN_LIST # For backwards compatibility support From 569547f0c4931c1ce163146d95375ead258c09d9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 28 Feb 2021 00:01:15 -0500 Subject: [PATCH 0064/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b6e7ef2956c..7738e10ffe5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210227) +set(CMake_VERSION_PATCH 20210228) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 653b871cb782dd30d1139e09a8285ba072518ae9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 1 Mar 2021 00:01:15 -0500 Subject: [PATCH 0065/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7738e10ffe5..1c0acc093f0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210228) +set(CMake_VERSION_PATCH 20210301) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 507710438d6033011cf980dc8a3c739b8bc1bb1c Mon Sep 17 00:00:00 2001 From: Tocic Date: Mon, 1 Mar 2021 11:51:19 +0000 Subject: [PATCH 0066/1519] FindBoost: Fix typo in documentation --- Modules/FindBoost.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index f8887ad2bec..3080062526b 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -189,7 +189,7 @@ This module defines the following :prop_tgt:`IMPORTED` targets: (adds ``-DBOOST_ALL_NO_LIB``). ``Boost::dynamic_linking`` - Interface target to enable dynamic linking linking with MSVC + Interface target to enable dynamic linking with MSVC (adds ``-DBOOST_ALL_DYN_LINK``). Implicit dependencies such as ``Boost::filesystem`` requiring From fcf16e9459044cc78db724998b7e69849b27b748 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Sun, 28 Feb 2021 16:33:54 +0100 Subject: [PATCH 0067/1519] ASM_NASM: Add depfile generation --- Modules/CMakeASM_NASMInformation.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/CMakeASM_NASMInformation.cmake b/Modules/CMakeASM_NASMInformation.cmake index 97cb4880fd8..f84ad559e8d 100644 --- a/Modules/CMakeASM_NASMInformation.cmake +++ b/Modules/CMakeASM_NASMInformation.cmake @@ -38,6 +38,8 @@ if(NOT CMAKE_ASM_NASM_COMPILE_OBJECT) set(CMAKE_ASM_NASM_COMPILE_OBJECT " -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o ") endif() +set(CMAKE_DEPFILE_FLAGS_ASM_NASM "-MD -MT ") + # Load the generic ASMInformation file: set(ASM_DIALECT "_NASM") include(CMakeASMInformation) From 5302073010eaf74fbc577cd53c62004545bc291e Mon Sep 17 00:00:00 2001 From: Henryk Paluch Date: Fri, 19 Feb 2021 12:39:28 +0000 Subject: [PATCH 0068/1519] Help: Add option to generate docs with latexpdf --- CMakeCPack.cmake | 3 ++ Utilities/Sphinx/CMakeLists.txt | 65 ++++++++++++++++++++++++--------- bootstrap | 8 ++++ 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index 31c2fe45611..9357804634a 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -133,6 +133,9 @@ if(CMake_INSTALL_COMPONENTS) if(SPHINX_QTHELP) list(APPEND _CPACK_IFW_COMPONENTS_ALL sphinx-qthelp) endif() + if(SPHINX_LATEXPDF) + list(APPEND _CPACK_IFW_COMPONENTS_ALL sphinx-latexpdf) + endif() if(CMake_BUILD_DEVELOPER_REFERENCE) if(CMake_BUILD_DEVELOPER_REFERENCE_HTML) list(APPEND _CPACK_IFW_COMPONENTS_ALL cmake-developer-reference-html) diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index 69f85d9b3fa..32efd4842bd 100644 --- a/Utilities/Sphinx/CMakeLists.txt +++ b/Utilities/Sphinx/CMakeLists.txt @@ -22,6 +22,7 @@ option(SPHINX_MAN "Build man pages with Sphinx" OFF) option(SPHINX_HTML "Build html help with Sphinx" OFF) option(SPHINX_SINGLEHTML "Build html single page help with Sphinx" OFF) option(SPHINX_QTHELP "Build Qt help with Sphinx" OFF) +option(SPHINX_LATEXPDF "Build PDF help with Sphinx using LaTeX" OFF) option(SPHINX_TEXT "Build text help with Sphinx (not installed)" OFF) find_program(SPHINX_EXECUTABLE NAMES sphinx-build @@ -33,7 +34,7 @@ separate_arguments(sphinx_flags UNIX_COMMAND "${SPHINX_FLAGS}") mark_as_advanced(SPHINX_TEXT) mark_as_advanced(SPHINX_FLAGS) -if(NOT SPHINX_INFO AND NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT) +if(NOT SPHINX_INFO AND NOT SPHINX_MAN AND NOT SPHINX_HTML AND NOT SPHINX_SINGLEHTML AND NOT SPHINX_QTHELP AND NOT SPHINX_TEXT AND NOT SPHINX_LATEXPDF) return() elseif(NOT SPHINX_EXECUTABLE) message(FATAL_ERROR "SPHINX_EXECUTABLE (sphinx-build) is not found!") @@ -117,28 +118,51 @@ if(SPHINX_QTHELP) ${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qhcp ) endif() - +if(SPHINX_LATEXPDF) + list(APPEND doc_formats latexpdf) +endif() set(doc_format_outputs "") set(doc_format_last "") foreach(format ${doc_formats}) set(doc_format_output "doc_format_${format}") set(doc_format_log "build-${format}.log") - add_custom_command( - OUTPUT ${doc_format_output} - COMMAND ${SPHINX_EXECUTABLE} - -c ${CMAKE_CURRENT_BINARY_DIR} - -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees - -b ${format} - ${sphinx_flags} - ${CMake_SOURCE_DIR}/Help - ${CMAKE_CURRENT_BINARY_DIR}/${format} - > ${doc_format_log} # log stdout, pass stderr - ${${format}_extra_commands} - DEPENDS ${doc_format_last} - COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}" - VERBATIM - ) + if(format STREQUAL "latexpdf") + # This format does not use builder (-b) but make_mode (-M) which expects + # arguments in peculiar order + add_custom_command( + OUTPUT ${doc_format_output} + COMMAND ${SPHINX_EXECUTABLE} + -M ${format} + ${CMake_SOURCE_DIR}/Help + ${CMAKE_CURRENT_BINARY_DIR}/${format} + -c ${CMAKE_CURRENT_BINARY_DIR} + -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees + ${sphinx_flags} + > ${doc_format_log} # log stdout, pass stderr + ${${format}_extra_commands} + DEPENDS ${doc_format_last} + COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}" + VERBATIM + ) + else() + # other formats use standard builder (-b) mode + add_custom_command( + OUTPUT ${doc_format_output} + COMMAND ${SPHINX_EXECUTABLE} + -c ${CMAKE_CURRENT_BINARY_DIR} + -d ${CMAKE_CURRENT_BINARY_DIR}/doctrees + -b ${format} + ${sphinx_flags} + ${CMake_SOURCE_DIR}/Help + ${CMAKE_CURRENT_BINARY_DIR}/${format} + > ${doc_format_log} # log stdout, pass stderr + ${${format}_extra_commands} + DEPENDS ${doc_format_last} + COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}" + VERBATIM + ) + endif() set_property(SOURCE ${doc_format_output} PROPERTY SYMBOLIC 1) list(APPEND doc_format_outputs ${doc_format_output}) set(doc_format_last ${doc_format_output}) @@ -219,3 +243,10 @@ if(SPHINX_QTHELP) DESTINATION ${CMAKE_DOC_DIR} ${COMPONENT} ) endif() + +if(SPHINX_LATEXPDF) + CMake_OPTIONAL_COMPONENT(sphinx-latexpdf) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/latexpdf/latex/CMake.pdf + DESTINATION ${CMAKE_DOC_DIR} ${COMPONENT} + ) +endif() diff --git a/bootstrap b/bootstrap index f85d57ee37d..768750da20d 100755 --- a/bootstrap +++ b/bootstrap @@ -84,6 +84,7 @@ cmake_sphinx_info="" cmake_sphinx_man="" cmake_sphinx_html="" cmake_sphinx_qthelp="" +cmake_sphinx_latexpdf="" cmake_sphinx_build="" cmake_sphinx_flags="" @@ -662,6 +663,7 @@ Configuration: --sphinx-man build man pages with Sphinx --sphinx-html build html help with Sphinx --sphinx-qthelp build qch help with Sphinx + --sphinx-latexpdf build PDF with Sphinx using LaTeX --sphinx-build= use as the sphinx-build executable --sphinx-flags= pass to sphinx-build executable @@ -926,6 +928,7 @@ while test $# != 0; do --sphinx-man) cmake_sphinx_man="1" ;; --sphinx-html) cmake_sphinx_html="1" ;; --sphinx-qthelp) cmake_sphinx_qthelp="1" ;; + --sphinx-latexpdf) cmake_sphinx_latexpdf="1" ;; --sphinx-build=*) cmake_sphinx_build=`cmake_arg "$1"` ;; --sphinx-flags=*) cmake_sphinx_flags=`cmake_arg "$1"` ;; --help) cmake_usage ;; @@ -1917,6 +1920,11 @@ if test "x${cmake_sphinx_qthelp}" != "x"; then set (SPHINX_QTHELP "'"${cmake_sphinx_qthelp}"'" CACHE BOOL "Build qch help with Sphinx" FORCE) ' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake" fi +if test "x${cmake_sphinx_latexpdf}" != "x"; then + echo ' +set (SPHINX_LATEXPDF "'"${cmake_sphinx_latexpdf}"'" CACHE BOOL "Build PDF help with Sphinx using LaTeX" FORCE) +' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake" +fi if test "x${cmake_sphinx_build}" != "x"; then echo ' set (SPHINX_EXECUTABLE "'"${cmake_sphinx_build}"'" CACHE FILEPATH "Location of Qt sphinx-build" FORCE) From e6ca675a297a3053489547b33fe5a33f6c95750d Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 2 Mar 2021 00:01:16 -0500 Subject: [PATCH 0069/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1c0acc093f0..8ecae5fb27f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210301) +set(CMake_VERSION_PATCH 20210302) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 48e74ec1e6d90a97a6d4ffd435c0135150f58602 Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Tue, 2 Mar 2021 12:27:47 +0100 Subject: [PATCH 0070/1519] ASM_NASM: generate depfiles for other makefiles --- Modules/CMakeASM_NASMInformation.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Modules/CMakeASM_NASMInformation.cmake b/Modules/CMakeASM_NASMInformation.cmake index f84ad559e8d..27b93ec0990 100644 --- a/Modules/CMakeASM_NASMInformation.cmake +++ b/Modules/CMakeASM_NASMInformation.cmake @@ -40,6 +40,13 @@ endif() set(CMAKE_DEPFILE_FLAGS_ASM_NASM "-MD -MT ") +if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake") + # dependencies are computed by the compiler itself + set(CMAKE_ASM_NASM_DEPFILE_FORMAT gcc) + set(CMAKE_ASM_NASM_DEPENDS_USE_COMPILER TRUE) +endif() + # Load the generic ASMInformation file: set(ASM_DIALECT "_NASM") include(CMakeASMInformation) From e3ac388738e7b2fb71593d49c70f22fd4c235da0 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Mon, 1 Mar 2021 21:04:54 -0800 Subject: [PATCH 0071/1519] cpack: add CPACK_DMG_FILESYSTEM Allow users to configure the filesystem format of the generated `.dmg` via the `CPACK_DMG_FILESYSTEM` option. Fixes: #21874 --- Help/cpack_gen/dmg.rst | 6 ++++++ Help/release/dev/cpack-dmg-filesystem.rst | 5 +++++ Source/CPack/cmCPackDragNDropGenerator.cxx | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/cpack-dmg-filesystem.rst diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst index 4c662a6f81e..ec2cf1e2d94 100644 --- a/Help/cpack_gen/dmg.rst +++ b/Help/cpack_gen/dmg.rst @@ -103,6 +103,12 @@ on macOS: - Default: ``CPACK_PACKAGE_FILE_NAME-`` +.. variable:: CPACK_DMG_FILESYSTEM + + The filesystem format. Common values are ``APFS`` and ``HFS+``. + See ``man hdiutil`` for a full list of supported formats. + Defaults to ``HFS+``. + .. variable:: CPACK_COMMAND_HDIUTIL Path to the ``hdiutil(1)`` command used to operate on disk image files on diff --git a/Help/release/dev/cpack-dmg-filesystem.rst b/Help/release/dev/cpack-dmg-filesystem.rst new file mode 100644 index 00000000000..e2a4742a258 --- /dev/null +++ b/Help/release/dev/cpack-dmg-filesystem.rst @@ -0,0 +1,5 @@ +cpack-dmg-filesystem +-------------------- + +* The :cpack_gen:`CPack DragNDrop Generator` gained option + :variable:`CPACK_DMG_FILESYSTEM` to control the ``.dmg`` filesystem. diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index cefb906bb66..0d56e5fd0e7 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -273,6 +273,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, ? this->GetOption("CPACK_DMG_FORMAT") : "UDZO"; + const std::string cpack_dmg_filesystem = + this->GetOption("CPACK_DMG_FILESYSTEM") + ? this->GetOption("CPACK_DMG_FILESYSTEM") + : "HFS+"; + // Get optional arguments ... std::string cpack_license_file = this->GetOption("CPACK_RESOURCE_FILE_LICENSE") @@ -418,7 +423,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, temp_image_command << " -ov"; temp_image_command << " -srcfolder \"" << staging.str() << "\""; temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\""; - temp_image_command << " -fs HFS+"; + temp_image_command << " -fs \"" << cpack_dmg_filesystem << "\""; temp_image_command << " -format " << temp_image_format; temp_image_command << " \"" << temp_image << "\""; From f63628b70423187a367a63216d5220f40e81eb16 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 3 Mar 2021 00:04:22 -0500 Subject: [PATCH 0072/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8ecae5fb27f..9f576b5deae 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210302) +set(CMake_VERSION_PATCH 20210303) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 42edf53ce2b201ca022d1f8170bb4323226c468a Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 3 Mar 2021 10:24:51 -0800 Subject: [PATCH 0073/1519] Tests: Generalize FindPackageModeMakefileTest extra flags var --- Tests/FindPackageModeMakefileTest/CMakeLists.txt | 13 +++++++------ Tests/FindPackageModeMakefileTest/Makefile.in | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Tests/FindPackageModeMakefileTest/CMakeLists.txt b/Tests/FindPackageModeMakefileTest/CMakeLists.txt index 8a87a8c97d0..909ba306747 100644 --- a/Tests/FindPackageModeMakefileTest/CMakeLists.txt +++ b/Tests/FindPackageModeMakefileTest/CMakeLists.txt @@ -19,12 +19,13 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Makefile" AND # configure a FindFoo.cmake so it knows where the library can be found configure_file(FindFoo.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FindFoo.cmake @ONLY) - # Need the -isysroot flag on recentish macOS after command line tools - # no longer provide headers in /usr/include - if(APPLE AND CMAKE_OSX_SYSROOT) - set(__EXTRA_OSX_SYSROOT_FLAGS "-isysroot ${CMAKE_OSX_SYSROOT}") - else() - set(__EXTRA_OSX_SYSROOT_FLAGS "") + set(EXTRA_FLAGS "") + if(APPLE) + # Need the -isysroot flag on recentish macOS after command line tools + # no longer provide headers in /usr/include + if(CMAKE_OSX_SYSROOT) + string(APPEND EXTRA_FLAGS " -isysroot ${CMAKE_OSX_SYSROOT}") + endif() endif() # now set up the test: diff --git a/Tests/FindPackageModeMakefileTest/Makefile.in b/Tests/FindPackageModeMakefileTest/Makefile.in index af9fa960988..695c64fe69a 100644 --- a/Tests/FindPackageModeMakefileTest/Makefile.in +++ b/Tests/FindPackageModeMakefileTest/Makefile.in @@ -5,7 +5,7 @@ CMAKE_CURRENT_BINARY_DIR = "@CMAKE_CURRENT_BINARY_DIR@" CMAKE_CXX_COMPILER = "@CMAKE_CXX_COMPILER@" CMAKE_CXX_COMPILER_ID = "@CMAKE_CXX_COMPILER_ID@" CMAKE_CXX_FLAGS = @CMAKE_CXX_FLAGS@ -__EXTRA_OSX_SYSROOT_FLAGS = @__EXTRA_OSX_SYSROOT_FLAGS@ +EXTRA_FLAGS = @EXTRA_FLAGS@ CMAKE_FOO = $(CMAKE) --find-package -DCMAKE_MODULE_PATH=$(CMAKE_CURRENT_BINARY_DIR) -DNAME=Foo -DLANGUAGE=CXX -DCOMPILER_ID=$(CMAKE_CXX_COMPILER_ID) @@ -16,7 +16,7 @@ all: pngtest main.o: clean main.cpp @$(CMAKE_FOO) -DMODE=COMPILE >$(tmp) @foo="`cat $(tmp)`"; \ - printf '"%s" %s %s %s -c main.cpp\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(__EXTRA_OSX_SYSROOT_FLAGS)" "$$foo" >$(tmp) + printf '"%s" %s %s %s -c main.cpp\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(EXTRA_FLAGS)" "$$foo" >$(tmp) @cat $(tmp) @sh $(tmp) @rm -f $(tmp) @@ -24,7 +24,7 @@ main.o: clean main.cpp pngtest: main.o @$(CMAKE_FOO) -DMODE=LINK >$(tmp) @foo="`cat $(tmp)`"; \ - printf '"%s" %s %s %s -o pngtest main.o %s\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(__EXTRA_OSX_SYSROOT_FLAGS)" "$(LDFLAGS)" "$$foo" >$(tmp) + printf '"%s" %s %s %s -o pngtest main.o %s\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(EXTRA_FLAGS)" "$(LDFLAGS)" "$$foo" >$(tmp) @cat $(tmp) @sh $(tmp) @rm -f $(tmp) From fd714dd2b83b86ad4ff5aaf0f7bbfec88525f08f Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 3 Mar 2021 10:29:06 -0800 Subject: [PATCH 0074/1519] Tests: Fix FindPackageModeMakefileTest with CMAKE_OSX_ARCHITECTURES --- Tests/FindPackageModeMakefileTest/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/FindPackageModeMakefileTest/CMakeLists.txt b/Tests/FindPackageModeMakefileTest/CMakeLists.txt index 909ba306747..0b15be8cf76 100644 --- a/Tests/FindPackageModeMakefileTest/CMakeLists.txt +++ b/Tests/FindPackageModeMakefileTest/CMakeLists.txt @@ -26,6 +26,9 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Makefile" AND if(CMAKE_OSX_SYSROOT) string(APPEND EXTRA_FLAGS " -isysroot ${CMAKE_OSX_SYSROOT}") endif() + foreach(arch ${CMAKE_OSX_ARCHITECTURES}) + string(APPEND EXTRA_FLAGS " -arch ${arch}") + endforeach() endif() # now set up the test: From adc351db8f89c3c41190df381c65800e7514e126 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 3 Mar 2021 16:35:16 -0500 Subject: [PATCH 0075/1519] Tests: Add RunCMake helper to run a plain script Many tests covering CMake scripting commands can work without initializing a full generator. --- Tests/RunCMake/RunCMake.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index a26f632e0d5..1a690594d45 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -214,6 +214,11 @@ function(run_cmake_command test) run_cmake(${test}) endfunction() +function(run_cmake_script test) + set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND} ${ARGN} -P ${RunCMake_SOURCE_DIR}/${test}.cmake) + run_cmake(${test}) +endfunction() + function(run_cmake_with_options test) set(RunCMake_TEST_OPTIONS "${ARGN}") run_cmake(${test}) From 1dde7e350a45638f2154430877a530968708448a Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 4 Mar 2021 00:01:19 -0500 Subject: [PATCH 0076/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9f576b5deae..67980a87ec6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210303) +set(CMake_VERSION_PATCH 20210304) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0c2dc345047135cac824ffc222bfb0c26f6c23be Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 3 Mar 2021 15:51:31 -0500 Subject: [PATCH 0077/1519] cmSystemTools: Add RenameFile signature to capture the error message --- Source/cmSystemTools.cxx | 43 +++++++++++++++++++++++++++++++++++++--- Source/cmSystemTools.h | 8 ++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 08075907709..eb0271222a0 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -149,6 +149,27 @@ static int cm_archive_read_open_file(struct archive* a, const char* file, # define environ (*_NSGetEnviron()) #endif +namespace { +void ReportError(std::string* err) +{ + if (!err) { + return; + } +#ifdef _WIN32 + LPSTR message = NULL; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, NULL); + *err = std::string(message, size); + LocalFree(message); +#else + *err = strerror(errno); +#endif +} +} + bool cmSystemTools::s_RunCommandHideConsole = false; bool cmSystemTools::s_DisableRunCommandOutput = false; bool cmSystemTools::s_ErrorOccured = false; @@ -966,6 +987,13 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname) bool cmSystemTools::RenameFile(const std::string& oldname, const std::string& newname) +{ + return cmSystemTools::RenameFile(oldname, newname, nullptr) == + RenameResult::Success; +} + +cmSystemTools::RenameResult cmSystemTools::RenameFile( + std::string const& oldname, std::string const& newname, std::string* err) { #ifdef _WIN32 # ifndef INVALID_FILE_ATTRIBUTES @@ -1004,7 +1032,8 @@ bool cmSystemTools::RenameFile(const std::string& oldname, // 3) Windows Explorer has an associated directory already opened. if (move_last_error != ERROR_ACCESS_DENIED && move_last_error != ERROR_SHARING_VIOLATION) { - return false; + ReportError(err); + return RenameResult::Failure; } DWORD const attrs = GetFileAttributesW(newname_wstr.c_str()); @@ -1028,10 +1057,18 @@ bool cmSystemTools::RenameFile(const std::string& oldname, save_restore_file_attributes.SetPath(newname_wstr); } SetLastError(move_last_error); - return retry.Count > 0; + if (retry.Count > 0) { + return RenameResult::Success; + } + ReportError(err); + return RenameResult::Failure; #else /* On UNIX we have an OS-provided call to do this atomically. */ - return rename(oldname.c_str(), newname.c_str()) == 0; + if (rename(oldname.c_str(), newname.c_str()) == 0) { + return RenameResult::Success; + } + ReportError(err); + return RenameResult::Failure; #endif } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 5bbbb0c7b6f..bb9013508e4 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -128,10 +128,18 @@ class cmSystemTools : public cmsys::SystemTools static bool SimpleGlob(const std::string& glob, std::vector& files, int type = 0); + enum class RenameResult + { + Success, + Failure, + }; + /** Rename a file or directory within a single disk volume (atomic if possible). */ static bool RenameFile(const std::string& oldname, const std::string& newname); + static RenameResult RenameFile(std::string const& oldname, + std::string const& newname, std::string* err); //! Rename a file if contents are different, delete the source otherwise static void MoveFileIfDifferent(const std::string& source, From c61292726cd3018ec502f8d59e62352c8dce62d3 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 3 Mar 2021 15:54:14 -0500 Subject: [PATCH 0078/1519] file(RENAME): Add option to capture error message on failure --- Help/command/file.rst | 11 ++++- Help/release/dev/file-RENAME.rst | 5 +++ Source/cmFileCommand.cxx | 41 +++++++++++++++---- .../file/RENAME-arg-missing-result.txt | 1 + .../file/RENAME-arg-missing-stderr.txt | 3 ++ Tests/RunCMake/file/RENAME-arg-missing.cmake | 1 + .../file/RENAME-arg-unknown-result.txt | 1 + .../file/RENAME-arg-unknown-stderr.txt | 5 +++ Tests/RunCMake/file/RENAME-arg-unknown.cmake | 1 + .../RENAME-file-to-dir-capture-stdout.txt | 1 + .../file/RENAME-file-to-dir-capture.cmake | 9 ++++ .../file/RENAME-file-to-dir-fail-result.txt | 1 + .../file/RENAME-file-to-dir-fail-stderr.txt | 13 ++++++ .../file/RENAME-file-to-dir-fail.cmake | 5 +++ Tests/RunCMake/file/RENAME-file-to-file.cmake | 10 +++++ Tests/RunCMake/file/RunCMakeTest.cmake | 6 +++ 16 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 Help/release/dev/file-RENAME.rst create mode 100644 Tests/RunCMake/file/RENAME-arg-missing-result.txt create mode 100644 Tests/RunCMake/file/RENAME-arg-missing-stderr.txt create mode 100644 Tests/RunCMake/file/RENAME-arg-missing.cmake create mode 100644 Tests/RunCMake/file/RENAME-arg-unknown-result.txt create mode 100644 Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt create mode 100644 Tests/RunCMake/file/RENAME-arg-unknown.cmake create mode 100644 Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt create mode 100644 Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake create mode 100644 Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt create mode 100644 Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt create mode 100644 Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake create mode 100644 Tests/RunCMake/file/RENAME-file-to-file.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index 3db605d6a8f..b28e206d04c 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -38,7 +38,7 @@ Synopsis `Filesystem`_ file({`GLOB`_ | `GLOB_RECURSE`_} [...] [...]) - file(`RENAME`_ ) + file(`RENAME`_ [...]) file({`REMOVE`_ | `REMOVE_RECURSE`_ } [...]) file(`MAKE_DIRECTORY`_ [...]) file({`COPY`_ | `INSTALL`_} ... DESTINATION [...]) @@ -665,11 +665,18 @@ Examples of recursive globbing include:: .. code-block:: cmake - file(RENAME ) + file(RENAME + [RESULT ]) Move a file or directory within a filesystem from ```` to ````, replacing the destination atomically. +The options are: + +``RESULT `` + Set ```` variable to ``0`` on success or an error message otherwise. + If ``RESULT`` is not specified and the operation fails, an error is emitted. + .. _REMOVE: .. _REMOVE_RECURSE: diff --git a/Help/release/dev/file-RENAME.rst b/Help/release/dev/file-RENAME.rst new file mode 100644 index 00000000000..6cde0363e0c --- /dev/null +++ b/Help/release/dev/file-RENAME.rst @@ -0,0 +1,5 @@ +file-RENAME +----------- + +* The :command:`file(RENAME)` command learned to optionally capture + failure in a result variable. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index f674833ea41..6243bb29b9c 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1313,8 +1313,9 @@ bool HandleRelativePathCommand(std::vector const& args, bool HandleRename(std::vector const& args, cmExecutionStatus& status) { - if (args.size() != 3) { - status.SetError("RENAME given incorrect number of arguments."); + if (args.size() < 3) { + status.SetError("RENAME must be called with at least two additional " + "arguments"); return false; } @@ -1330,13 +1331,39 @@ bool HandleRename(std::vector const& args, cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]); } - if (!cmSystemTools::RenameFile(oldname, newname)) { - std::string err = cmSystemTools::GetLastSystemError(); - status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, - "\nto\n ", newname, "\nbecause: ", err, "\n")); + struct Arguments + { + std::string Result; + }; + + static auto const parser = + cmArgumentParser{}.Bind("RESULT"_s, &Arguments::Result); + + std::vector unconsumedArgs; + Arguments const arguments = + parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs); + if (!unconsumedArgs.empty()) { + status.SetError("RENAME unknown argument:\n " + unconsumedArgs.front()); return false; } - return true; + + std::string err; + switch (cmSystemTools::RenameFile(oldname, newname, &err)) { + case cmSystemTools::RenameResult::Success: + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, "0"); + } + return true; + case cmSystemTools::RenameResult::Failure: + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, err); + return true; + } + break; + } + status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, "\nto\n ", + newname, "\nbecause: ", err, "\n")); + return false; } bool HandleRemoveImpl(std::vector const& args, bool recurse, diff --git a/Tests/RunCMake/file/RENAME-arg-missing-result.txt b/Tests/RunCMake/file/RENAME-arg-missing-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-missing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt b/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt new file mode 100644 index 00000000000..98d29614fa2 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-missing-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-arg-missing.cmake:1 \(file\): + file RENAME must be called with at least two additional arguments$ diff --git a/Tests/RunCMake/file/RENAME-arg-missing.cmake b/Tests/RunCMake/file/RENAME-arg-missing.cmake new file mode 100644 index 00000000000..2358ce982e4 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-missing.cmake @@ -0,0 +1 @@ +file(RENAME "old") diff --git a/Tests/RunCMake/file/RENAME-arg-unknown-result.txt b/Tests/RunCMake/file/RENAME-arg-unknown-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-unknown-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt b/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt new file mode 100644 index 00000000000..16edb2576b8 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-unknown-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-arg-unknown.cmake:1 \(file\): + file RENAME unknown argument: + + unknown$ diff --git a/Tests/RunCMake/file/RENAME-arg-unknown.cmake b/Tests/RunCMake/file/RENAME-arg-unknown.cmake new file mode 100644 index 00000000000..3110f70479e --- /dev/null +++ b/Tests/RunCMake/file/RENAME-arg-unknown.cmake @@ -0,0 +1 @@ +file(RENAME "old" "new" unknown) diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt b/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt new file mode 100644 index 00000000000..0276a5f898f --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-capture-stdout.txt @@ -0,0 +1 @@ +^-- file\(RENAME\) failed with result: [A-Za-z] diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake b/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake new file mode 100644 index 00000000000..4f817e8a686 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-capture.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(RENAME "${oldname}" "${newname}" RESULT result) +message(STATUS "file(RENAME) failed with result: ${result}") +if(NOT EXISTS "${oldname}") + message(FATAL_ERROR "The old name does not still exist:\n ${oldname}") +endif() diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt b/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt b/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt new file mode 100644 index 00000000000..e4dbc38e998 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail-stderr.txt @@ -0,0 +1,13 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake:[0-9] \(file\): + file RENAME failed to rename + + [^ +]*/Tests/RunCMake/file/RENAME-file-to-dir-fail-build/input + + to + + [^ +]*/Tests/RunCMake/file/RENAME-file-to-dir-fail-build/output + + because: [A-Za-z] diff --git a/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake b/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake new file mode 100644 index 00000000000..61fa644635e --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-dir-fail.cmake @@ -0,0 +1,5 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(RENAME "${oldname}" "${newname}") diff --git a/Tests/RunCMake/file/RENAME-file-to-file.cmake b/Tests/RunCMake/file/RENAME-file-to-file.cmake new file mode 100644 index 00000000000..dbc411be1a5 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-to-file.cmake @@ -0,0 +1,10 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(RENAME "${oldname}" "${newname}") +if(EXISTS "${oldname}") + message(FATAL_ERROR "The old name still exists:\n ${oldname}") +endif() +if(NOT EXISTS "${newname}") + message(FATAL_ERROR "The new name does not exist:\n ${newname}") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 22813eb1632..d9e4cfec313 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -50,6 +50,12 @@ run_cmake(SIZE-error-does-not-exist) run_cmake(REMOVE-empty) +run_cmake_script(RENAME-file-to-file) +run_cmake_script(RENAME-file-to-dir-capture) +run_cmake_script(RENAME-file-to-dir-fail) +run_cmake_script(RENAME-arg-missing) +run_cmake_script(RENAME-arg-unknown) + # tests are valid both for GLOB and GLOB_RECURSE run_cmake(GLOB-sort-dedup) run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean) From 3600c6cd8c09e501faa06be5f98465e994d51569 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 08:23:42 -0500 Subject: [PATCH 0079/1519] cmSystemTools: Add RenameFile option to not replace destination --- Source/cmFileCommand.cxx | 4 +++- Source/cmSystemTools.cxx | 38 ++++++++++++++++++++++++++++++-------- Source/cmSystemTools.h | 9 ++++++++- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 6243bb29b9c..ab954f215a1 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1348,12 +1348,14 @@ bool HandleRename(std::vector const& args, } std::string err; - switch (cmSystemTools::RenameFile(oldname, newname, &err)) { + switch (cmSystemTools::RenameFile(oldname, newname, + cmSystemTools::Replace::Yes, &err)) { case cmSystemTools::RenameResult::Success: if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, "0"); } return true; + case cmSystemTools::RenameResult::NoReplace: case cmSystemTools::RenameResult::Failure: if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, err); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index eb0271222a0..db5b1ac3342 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -973,14 +973,19 @@ void cmSystemTools::InitializeLibUV() #ifdef _WIN32 namespace { -bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname) +bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname, + cmSystemTools::Replace replace) { // Not only ignore any previous error, but clear any memory of it. SetLastError(0); - // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file. - return MoveFileExW(oldname.c_str(), newname.c_str(), - MOVEFILE_REPLACE_EXISTING); + DWORD flags = 0; + if (replace == cmSystemTools::Replace::Yes) { + // Use MOVEFILE_REPLACE_EXISTING to replace an existing destination file. + flags = flags | MOVEFILE_REPLACE_EXISTING; + } + + return MoveFileExW(oldname.c_str(), newname.c_str(), flags); } } #endif @@ -988,12 +993,13 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname) bool cmSystemTools::RenameFile(const std::string& oldname, const std::string& newname) { - return cmSystemTools::RenameFile(oldname, newname, nullptr) == + return cmSystemTools::RenameFile(oldname, newname, Replace::Yes) == RenameResult::Success; } cmSystemTools::RenameResult cmSystemTools::RenameFile( - std::string const& oldname, std::string const& newname, std::string* err) + std::string const& oldname, std::string const& newname, Replace replace, + std::string* err) { #ifdef _WIN32 # ifndef INVALID_FILE_ATTRIBUTES @@ -1016,7 +1022,7 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile( oldname_wstr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); DWORD move_last_error = 0; - while (!cmMoveFile(oldname_wstr, newname_wstr) && --retry.Count) { + while (!cmMoveFile(oldname_wstr, newname_wstr, replace) && --retry.Count) { move_last_error = GetLastError(); // There was no error ==> the operation is not yet complete. @@ -1032,6 +1038,9 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile( // 3) Windows Explorer has an associated directory already opened. if (move_last_error != ERROR_ACCESS_DENIED && move_last_error != ERROR_SHARING_VIOLATION) { + if (replace == Replace::No && move_last_error == ERROR_ALREADY_EXISTS) { + return RenameResult::NoReplace; + } ReportError(err); return RenameResult::Failure; } @@ -1060,10 +1069,23 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile( if (retry.Count > 0) { return RenameResult::Success; } + if (replace == Replace::No && GetLastError() == ERROR_ALREADY_EXISTS) { + return RenameResult::NoReplace; + } ReportError(err); return RenameResult::Failure; #else - /* On UNIX we have an OS-provided call to do this atomically. */ + // On UNIX we have OS-provided calls to create 'newname' atomically. + if (replace == Replace::No) { + if (link(oldname.c_str(), newname.c_str()) == 0) { + return RenameResult::Success; + } + if (errno == EEXIST) { + return RenameResult::NoReplace; + } + ReportError(err); + return RenameResult::Failure; + } if (rename(oldname.c_str(), newname.c_str()) == 0) { return RenameResult::Success; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index bb9013508e4..3cc032c5238 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -128,9 +128,15 @@ class cmSystemTools : public cmsys::SystemTools static bool SimpleGlob(const std::string& glob, std::vector& files, int type = 0); + enum class Replace + { + Yes, + No, + }; enum class RenameResult { Success, + NoReplace, Failure, }; @@ -139,7 +145,8 @@ class cmSystemTools : public cmsys::SystemTools static bool RenameFile(const std::string& oldname, const std::string& newname); static RenameResult RenameFile(std::string const& oldname, - std::string const& newname, std::string* err); + std::string const& newname, Replace replace, + std::string* err = nullptr); //! Rename a file if contents are different, delete the source otherwise static void MoveFileIfDifferent(const std::string& source, From 9bf40d8027ec9fb91ad995919f6db673c15558dc Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 08:13:16 -0500 Subject: [PATCH 0080/1519] file(RENAME): Add option to not replace existing path Add a `NO_REPLACE` option that prevents overwriting `` if it exists. --- Help/command/file.rst | 8 +++++++- Help/release/dev/file-RENAME.rst | 3 ++- Source/cmFileCommand.cxx | 17 ++++++++++++++--- .../RENAME-file-NO_REPLACE-capture-stdout.txt | 1 + .../file/RENAME-file-NO_REPLACE-capture.cmake | 9 +++++++++ .../file/RENAME-file-NO_REPLACE-fail-result.txt | 1 + .../file/RENAME-file-NO_REPLACE-fail-stderr.txt | 13 +++++++++++++ .../file/RENAME-file-NO_REPLACE-fail.cmake | 5 +++++ Tests/RunCMake/file/RENAME-file-replace.cmake | 9 +++++++++ Tests/RunCMake/file/RunCMakeTest.cmake | 3 +++ 10 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt create mode 100644 Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake create mode 100644 Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt create mode 100644 Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt create mode 100644 Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake create mode 100644 Tests/RunCMake/file/RENAME-file-replace.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index b28e206d04c..9cde90c64f1 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -666,7 +666,8 @@ Examples of recursive globbing include:: .. code-block:: cmake file(RENAME - [RESULT ]) + [RESULT ] + [NO_REPLACE]) Move a file or directory within a filesystem from ```` to ````, replacing the destination atomically. @@ -677,6 +678,11 @@ The options are: Set ```` variable to ``0`` on success or an error message otherwise. If ``RESULT`` is not specified and the operation fails, an error is emitted. +``NO_REPLACE`` + If the ```` path already exists, do not replace it. + If ``RESULT `` is used, the result variable will be + set to ``NO_REPLACE``. Otherwise, an error is emitted. + .. _REMOVE: .. _REMOVE_RECURSE: diff --git a/Help/release/dev/file-RENAME.rst b/Help/release/dev/file-RENAME.rst index 6cde0363e0c..6c1314d24f2 100644 --- a/Help/release/dev/file-RENAME.rst +++ b/Help/release/dev/file-RENAME.rst @@ -2,4 +2,5 @@ file-RENAME ----------- * The :command:`file(RENAME)` command learned to optionally capture - failure in a result variable. + failure in a result variable. It also gained a ``NO_REPLACE`` + option to fail if the destination exists. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index ab954f215a1..065b8459da2 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1333,11 +1333,13 @@ bool HandleRename(std::vector const& args, struct Arguments { + bool NoReplace = false; std::string Result; }; - static auto const parser = - cmArgumentParser{}.Bind("RESULT"_s, &Arguments::Result); + static auto const parser = cmArgumentParser{} + .Bind("NO_REPLACE"_s, &Arguments::NoReplace) + .Bind("RESULT"_s, &Arguments::Result); std::vector unconsumedArgs; Arguments const arguments = @@ -1349,13 +1351,22 @@ bool HandleRename(std::vector const& args, std::string err; switch (cmSystemTools::RenameFile(oldname, newname, - cmSystemTools::Replace::Yes, &err)) { + arguments.NoReplace + ? cmSystemTools::Replace::No + : cmSystemTools::Replace::Yes, + &err)) { case cmSystemTools::RenameResult::Success: if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, "0"); } return true; case cmSystemTools::RenameResult::NoReplace: + if (!arguments.Result.empty()) { + err = "NO_REPLACE"; + } else { + err = "path not replaced"; + } + CM_FALLTHROUGH; case cmSystemTools::RenameResult::Failure: if (!arguments.Result.empty()) { status.GetMakefile().AddDefinition(arguments.Result, err); diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt new file mode 100644 index 00000000000..a1163309569 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture-stdout.txt @@ -0,0 +1 @@ +^-- file\(RENAME\) failed with result: NO_REPLACE$ diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake new file mode 100644 index 00000000000..1ff41786f39 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-capture.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "a") +file(WRITE "${newname}" "b") +file(RENAME "${oldname}" "${newname}" NO_REPLACE RESULT result) +message(STATUS "file(RENAME) failed with result: ${result}") +if(NOT EXISTS "${oldname}") + message(FATAL_ERROR "The old name does not still exist:\n ${oldname}") +endif() diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt new file mode 100644 index 00000000000..dd7294cd594 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-stderr.txt @@ -0,0 +1,13 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake:[0-9] \(file\): + file RENAME failed to rename + + [^ +]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-build/input + + to + + [^ +]*/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail-build/output + + because: path not replaced$ diff --git a/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake new file mode 100644 index 00000000000..c05dd6359b4 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-NO_REPLACE-fail.cmake @@ -0,0 +1,5 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "a") +file(WRITE "${newname}" "b") +file(RENAME "${oldname}" "${newname}" NO_REPLACE) diff --git a/Tests/RunCMake/file/RENAME-file-replace.cmake b/Tests/RunCMake/file/RENAME-file-replace.cmake new file mode 100644 index 00000000000..efbfaed1120 --- /dev/null +++ b/Tests/RunCMake/file/RENAME-file-replace.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "a") +file(WRITE "${newname}" "b") +file(RENAME "${oldname}" "${newname}") +file(READ "${newname}" new) +if(NOT "${new}" STREQUAL "a") + message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index d9e4cfec313..f74832c55b7 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -50,9 +50,12 @@ run_cmake(SIZE-error-does-not-exist) run_cmake(REMOVE-empty) +run_cmake_script(RENAME-file-replace) run_cmake_script(RENAME-file-to-file) run_cmake_script(RENAME-file-to-dir-capture) run_cmake_script(RENAME-file-to-dir-fail) +run_cmake_script(RENAME-file-NO_REPLACE-capture) +run_cmake_script(RENAME-file-NO_REPLACE-fail) run_cmake_script(RENAME-arg-missing) run_cmake_script(RENAME-arg-unknown) From 38140713ad24576f1c4e6253a1de91ff217dd475 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 22 Feb 2021 11:52:14 -0500 Subject: [PATCH 0081/1519] cmake: add support for --install-prefix command argument Fixes: #21781 --- Help/manual/OPTIONS_BUILD.txt | 3 +++ .../dev/cmake-install-prefix-command.rst | 5 +++++ Source/cmake.cxx | 17 +++++++++++++++++ Source/cmake.h | 2 ++ Tests/ExternalProjectLocal/CMakeLists.txt | 6 +++--- Tests/RunCMake/CMP0041/RunCMakeTest.cmake | 4 ++++ Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 3 +++ Tests/RunCMake/IfacePaths/RunCMakeTest.cmake | 8 +++++--- 8 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/cmake-install-prefix-command.rst diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index 0947e41cbf6..251672e7792 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -76,6 +76,9 @@ native build system to choose a compiler or SDK. See the :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. +``--install-prefix `` + Specify the installation prefix, :variable:`CMAKE_INSTALL_PREFIX`. + ``-Wno-dev`` Suppress developer warnings. diff --git a/Help/release/dev/cmake-install-prefix-command.rst b/Help/release/dev/cmake-install-prefix-command.rst new file mode 100644 index 00000000000..a5b140a37aa --- /dev/null +++ b/Help/release/dev/cmake-install-prefix-command.rst @@ -0,0 +1,5 @@ +cmake-install-prefix-command +---------------------------- + +* The :manual:`cmake(1)` command gained the ``--install-prefix `` + command line option to specify the location of the install prefix. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 7e6d5c31c07..f96badda31b 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -493,6 +493,16 @@ bool cmake::SetCacheArgs(const std::vector& args) return true; }; + auto PrefixLambda = [&](std::string const& path, cmake* state) -> bool { + const std::string var = "CMAKE_INSTALL_PREFIX"; + cmStateEnums::CacheEntryType type = cmStateEnums::PATH; +#ifndef CMAKE_BOOTSTRAP + state->UnprocessedPresetVariables.erase(var); +#endif + state->ProcessCacheArg(var, path, type); + return true; + }; + std::vector arguments = { CommandArgument{ "-D", "-D must be followed with VAR=VALUE.", CommandArgument::Values::One, DefineLambda }, @@ -511,8 +521,12 @@ bool cmake::SetCacheArgs(const std::vector& args) state->ReadListFile(args, path); return true; } }, + CommandArgument{ "-P", "-P must be followed by a file name.", CommandArgument::Values::One, ScriptLambda }, + CommandArgument{ "--install-prefix", + "No install directory specified for --install-prefix", + CommandArgument::Values::One, PrefixLambda }, CommandArgument{ "--find-package", CommandArgument::Values::Zero, [&](std::string const&, cmake*) -> bool { findPackageMode = true; @@ -815,6 +829,9 @@ void cmake::SetArgs(const std::vector& args) CommandArgument::Values::One, PlatformLambda }, CommandArgument{ "-T", "No toolset specified for -T", CommandArgument::Values::One, ToolsetLamda }, + CommandArgument{ "--install-prefix", + "No install directory specified for --install-prefix", + CommandArgument::Values::One, IgnoreAndTrueLambda }, CommandArgument{ "--check-build-system", CommandArgument::Values::Two, [](std::string const& value, cmake* state) -> bool { diff --git a/Source/cmake.h b/Source/cmake.h index d6d129ff164..ab2ed21a9c6 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -712,6 +712,8 @@ class cmake "Specify toolset name if supported by generator." }, \ { "-A ", \ "Specify platform name if supported by generator." }, \ + { "--install-prefix ", \ + "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \ { "-Wdev", "Enable developer warnings." }, \ { "-Wno-dev", "Suppress developer warnings." }, \ { "-Werror=dev", "Make developer warnings errors." }, \ diff --git a/Tests/ExternalProjectLocal/CMakeLists.txt b/Tests/ExternalProjectLocal/CMakeLists.txt index 9a0241c2723..57e81052bfa 100644 --- a/Tests/ExternalProjectLocal/CMakeLists.txt +++ b/Tests/ExternalProjectLocal/CMakeLists.txt @@ -41,7 +41,7 @@ set(TutorialStep5_install_dir ${install_dir}) set(proj TutorialStep5-Local-TestAfterInstall) ExternalProject_Add(${proj} URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5" -CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -G ${CMAKE_GENERATOR} +CMAKE_ARGS --install-prefix= -G ${CMAKE_GENERATOR} CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF TEST_AFTER_INSTALL 1 LOG_TEST 1 @@ -51,7 +51,7 @@ set_property(TARGET ${proj} PROPERTY FOLDER "Local") set(proj TutorialStep5-Local-TestExcludeFromMainBefore) ExternalProject_Add(${proj} URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5" -CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -G ${CMAKE_GENERATOR} +CMAKE_ARGS --install-prefix= -G ${CMAKE_GENERATOR} CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF TEST_BEFORE_INSTALL 1 TEST_EXCLUDE_FROM_MAIN 1 @@ -63,7 +63,7 @@ set_property(TARGET ${proj} PROPERTY FOLDER "Local") set(proj TutorialStep5-Local-TestExcludeFromMainAfter) ExternalProject_Add(${proj} URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5" -CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -G ${CMAKE_GENERATOR} +CMAKE_ARGS --install-prefix= -G ${CMAKE_GENERATOR} CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF TEST_AFTER_INSTALL 1 TEST_EXCLUDE_FROM_MAIN 1 diff --git a/Tests/RunCMake/CMP0041/RunCMakeTest.cmake b/Tests/RunCMake/CMP0041/RunCMakeTest.cmake index e7f27a1a289..f47bb2ee314 100644 --- a/Tests/RunCMake/CMP0041/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMP0041/RunCMakeTest.cmake @@ -6,6 +6,10 @@ set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/NotDefa run_cmake(CMP0041-OLD) run_cmake(CMP0041-NEW) run_cmake(CMP0041-WARN) + +# Protect tests from running inside the default install prefix. +set(RunCMake_TEST_OPTIONS "--install-prefix ${RunCMake_BINARY_DIR}/NotDefaultPrefix") + run_cmake(CMP0041-tid-OLD) run_cmake(CMP0041-tid-NEW) run_cmake(CMP0041-tid-WARN) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 51754fc6165..a2b2044bed9 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -61,6 +61,9 @@ run_cmake_command(build-bad-dir run_cmake_command(build-bad-generator ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator) + +run_cmake_command(install-prefix-no-arg ${CMAKE_COMMAND} -B DummyBuildDir --install-prefix) + run_cmake_command(install-no-dir ${CMAKE_COMMAND} --install) run_cmake_command(install-bad-dir diff --git a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake index 066c83e63df..6530aeeb768 100644 --- a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake +++ b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake @@ -18,6 +18,9 @@ run_cmake(BinaryDirectoryInInterface) set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/DirInInstallPrefix/prefix") run_cmake(DirInInstallPrefix) +set(RunCMake_TEST_OPTIONS "--install-prefix=${RunCMake_BINARY_DIR}/DirInInstallPrefix/prefix") +run_cmake(DirInInstallPrefix) + configure_file( "${RunCMake_SOURCE_DIR}/CMakeLists.txt" "${RunCMake_BINARY_DIR}/copy/CMakeLists.txt" @@ -34,14 +37,13 @@ configure_file( COPYONLY ) set(RunCMake_TEST_OPTIONS - "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface/prefix" + "--install-prefix=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface/prefix" "-DTEST_FILE=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface.cmake" ) set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/copy") run_cmake(InstallInSrcDir) unset(RunCMake_TEST_SOURCE_DIR) -set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/InstallInBinDir-build/prefix") set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/InstallInBinDir-build/prefix" "-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake" @@ -77,7 +79,7 @@ foreach(policyStatus NEW OLD "") set(policySuffix -CMP0052-${policyStatus}) endif() set(RunCMake_TEST_OPTIONS - "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/prefix" ${policyOption} + "--install-prefix=${RunCMake_BINARY_DIR}/prefix" ${policyOption} "-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake" ) # Set the RunCMake_TEST_SOURCE_DIR here to the copy too. This is needed to run From 9dfa7981d54b32067b7a797ab68ac52055b47e2b Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 4 Mar 2021 20:43:34 +0100 Subject: [PATCH 0082/1519] Makefiles: Escape SONAME on linker command line If the shared object name contains spaces, they need to be properly escaped, or link command will fail. --- Source/cmMakefileLibraryTargetGenerator.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index ce64e2cfa6e..5e4f03d0c71 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -780,9 +780,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); + std::string targetOutSOName; if (this->GeneratorTarget->HasSOName(this->GetConfigName())) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); - vars.TargetSOName = this->TargetNames.SharedObject.c_str(); + targetOutSOName = this->LocalGenerator->ConvertToOutputFormat( + this->TargetNames.SharedObject.c_str(), cmOutputConverter::SHELL); + vars.TargetSOName = targetOutSOName.c_str(); } vars.LinkFlags = linkFlags.c_str(); From c0a33174970c7d0adb2d49287b0aab5aa9432e4e Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 4 Mar 2021 20:33:07 +0100 Subject: [PATCH 0083/1519] Ninja: Escape SONAME on linker command line If the shared object name contains spaces, they need to be properly escaped, or link command will fail. This was already done for soname symlink creation in commit 13c92b4a30 (Ninja: Fix creation of library symlinks in folders with spaces, 2019-05-20, v3.15.0-rc1~87^2). Fixes: #20331 --- Source/cmNinjaNormalTargetGenerator.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 49e5e4cc65f..1d511f21e4a 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -868,7 +868,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement( if (genTarget->HasSOName(config)) { vars["SONAME_FLAG"] = this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config)); - vars["SONAME"] = tgtNames.SharedObject; + vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject, + cmOutputConverter::SHELL); if (genTarget->GetType() == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config); @@ -1176,7 +1177,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( } if (gt->HasSOName(config)) { vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config)); - vars["SONAME"] = tgtNames.SharedObject; + vars["SONAME"] = localGen.ConvertToOutputFormat(tgtNames.SharedObject, + cmOutputConverter::SHELL); if (targetType == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = gt->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { From 96ee96c6d5bceeabb166ad6ebb6198f6663fdeac Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 5 Mar 2021 00:01:17 -0500 Subject: [PATCH 0084/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 67980a87ec6..406174b91e8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210304) +set(CMake_VERSION_PATCH 20210305) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From c456b0951370f900615e354ef724a153f607e837 Mon Sep 17 00:00:00 2001 From: Olivier Iffrig Date: Thu, 4 Mar 2021 17:04:56 +0000 Subject: [PATCH 0085/1519] CPack: Fix symbolic link detection for directories In the case where the current path is a symlink to a directory, a trailing slash causes the link to be dereferenced, which means that any subsequent `FileIsSymlink` on it will return false. Fixes: #21886 --- Source/CPack/cmCPackGenerator.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 3db4162c92e..c512a361584 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -384,7 +384,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( for (std::string const& gf : this->files) { bool skip = false; std::string inFile = gf; - if (cmSystemTools::FileIsDirectory(gf)) { + if (cmSystemTools::FileIsDirectory(gf) && + !cmSystemTools::FileIsSymlink(gf)) { inFile += '/'; } for (cmsys::RegularExpression& reg : ignoreFilesRegex) { From fe17685722f7c4af3664409f1728f7c3e9e4e9da Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 13:10:53 -0500 Subject: [PATCH 0086/1519] cmGlobalVisualStudio10Generator: Adopt flag table name methods Migrate them from `cmVisualStudio10ToolsetOptions`. --- Source/CMakeLists.txt | 2 - Source/cmGlobalVisualStudio10Generator.cxx | 188 ++++++++++++++++++--- Source/cmGlobalVisualStudio10Generator.h | 17 +- Source/cmVisualStudio10ToolsetOptions.cxx | 143 ---------------- Source/cmVisualStudio10ToolsetOptions.h | 31 ---- 5 files changed, 177 insertions(+), 204 deletions(-) delete mode 100644 Source/cmVisualStudio10ToolsetOptions.cxx delete mode 100644 Source/cmVisualStudio10ToolsetOptions.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6adc9cf6a86..d7828908e06 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -785,8 +785,6 @@ if (WIN32) cmVisualStudioGeneratorOptions.cxx cmVisualStudio10TargetGenerator.h cmVisualStudio10TargetGenerator.cxx - cmVisualStudio10ToolsetOptions.h - cmVisualStudio10ToolsetOptions.cxx cmLocalVisualStudio10Generator.cxx cmLocalVisualStudio10Generator.h cmGlobalVisualStudio10Generator.h diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 7794df3fa07..8ad6f5ddd84 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1400,65 +1400,65 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetClFlagTableName( + std::string optionsName = this->GetClFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultCLFlagTableName); + std::string defaultName = this->GetToolsetName(this->GetPlatformName(), + this->DefaultCLFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName( + std::string optionsName = this->GetCSharpFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultCSharpFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetRcFlagTableName( + std::string optionsName = this->GetRcFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( - this->GetPlatformName(), this->DefaultRCFlagTableName); + std::string defaultName = this->GetToolsetName(this->GetPlatformName(), + this->DefaultRCFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetLibFlagTableName( + std::string optionsName = this->GetLibFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultLibFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName( + std::string optionsName = this->GetLinkFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultLinkFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultCudaFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "Cuda"); } @@ -1466,29 +1466,165 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultCudaHostFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName( + std::string optionsName = this->GetMasmFlagTableName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultMasmFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - std::string toolsetName = this->ToolsetOptions.GetToolsetName( + std::string toolsetName = this->GetToolsetName( this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->ToolsetOptions.GetToolsetName( + std::string defaultName = this->GetToolsetName( this->GetPlatformName(), this->DefaultNasmFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "NASM"); } + +std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( + std::string const& name, std::string const& toolset) const +{ + std::string const useToolset = this->GetToolsetName(name, toolset); + + if (toolset == "v142") { + return "v142"; + } else if (toolset == "v141") { + return "v141"; + } else if (useToolset == "v140") { + return "v140"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( + std::string const& name, std::string const& toolset) const +{ + std::string const useToolset = this->GetToolsetName(name, toolset); + + if (useToolset == "v142") { + return "v142"; + } else if (useToolset == "v141") { + return "v141"; + } else if (useToolset == "v140") { + return "v140"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( + std::string const& name, std::string const& toolset) const +{ + std::string const useToolset = this->GetToolsetName(name, toolset); + + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( + std::string const& name, std::string const& toolset) const +{ + std::string const useToolset = this->GetToolsetName(name, toolset); + + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( + std::string const& name, std::string const& toolset) const +{ + std::string const useToolset = this->GetToolsetName(name, toolset); + + if (useToolset == "v142") { + return "v142"; + } else if (useToolset == "v141") { + return "v141"; + } else if (useToolset == "v140") { + return "v140"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName( + std::string const& name, std::string const& toolset) const +{ + std::string const useToolset = this->GetToolsetName(name, toolset); + + if ((useToolset == "v140") || (useToolset == "v141") || + (useToolset == "v142")) { + return "v14"; + } else if (useToolset == "v120") { + return "v12"; + } else if (useToolset == "v110") { + return "v11"; + } else if (useToolset == "v100") { + return "v10"; + } else { + return ""; + } +} + +std::string cmGlobalVisualStudio10Generator::GetToolsetName( + std::string const& name, std::string const& toolset) const +{ + static_cast(name); + std::size_t length = toolset.length(); + + if (cmHasLiteralSuffix(toolset, "_xp")) { + length -= 3; + } + + return toolset.substr(0, length); +} diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 65ea33fc9d1..64a7b959f84 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -6,7 +6,6 @@ #include #include "cmGlobalVisualStudio8Generator.h" -#include "cmVisualStudio10ToolsetOptions.h" /** \class cmGlobalVisualStudio10Generator * \brief Write a Unix makefiles. @@ -224,7 +223,6 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string MSBuildCommand; bool MSBuildCommandInitialized; - cmVisualStudio10ToolsetOptions ToolsetOptions; std::set AndroidExecutableWarnings; virtual std::string FindMSBuildCommand(); std::string FindDevEnvCommand() override; @@ -234,6 +232,21 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string GetClFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetCSharpFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetRcFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetLibFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetLinkFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetMasmFlagTableName(std::string const& name, + std::string const& toolset) const; + std::string GetToolsetName(std::string const& name, + std::string const& toolset) const; + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx deleted file mode 100644 index 7fc33e63eab..00000000000 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ /dev/null @@ -1,143 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmVisualStudio10ToolsetOptions.h" - -#include "cmAlgorithms.h" -#include "cmIDEFlagTable.h" -#include "cmVisualStudioGeneratorOptions.h" - -std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if (toolset == "v142") { - return "v142"; - } else if (toolset == "v141") { - return "v141"; - } else if (useToolset == "v140") { - return "v140"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if (useToolset == "v142") { - return "v142"; - } else if (useToolset == "v141") { - return "v141"; - } else if (useToolset == "v140") { - return "v140"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if ((useToolset == "v140") || (useToolset == "v141") || - (useToolset == "v142")) { - return "v14"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if ((useToolset == "v140") || (useToolset == "v141") || - (useToolset == "v142")) { - return "v14"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if (useToolset == "v142") { - return "v142"; - } else if (useToolset == "v141") { - return "v141"; - } else if (useToolset == "v140") { - return "v140"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName( - std::string const& name, std::string const& toolset) const -{ - std::string const useToolset = this->GetToolsetName(name, toolset); - - if ((useToolset == "v140") || (useToolset == "v141") || - (useToolset == "v142")) { - return "v14"; - } else if (useToolset == "v120") { - return "v12"; - } else if (useToolset == "v110") { - return "v11"; - } else if (useToolset == "v100") { - return "v10"; - } else { - return ""; - } -} - -std::string cmVisualStudio10ToolsetOptions::GetToolsetName( - std::string const& name, std::string const& toolset) const -{ - static_cast(name); - std::size_t length = toolset.length(); - - if (cmHasLiteralSuffix(toolset, "_xp")) { - length -= 3; - } - - return toolset.substr(0, length); -} diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h deleted file mode 100644 index 85cc2b6b2dd..00000000000 --- a/Source/cmVisualStudio10ToolsetOptions.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#pragma once - -#include "cmConfigure.h" // IWYU pragma: keep - -#include - -/** \class cmVisualStudio10ToolsetOptions - * \brief Retrieves toolset options for MSBuild. - * - * cmVisualStudio10ToolsetOptions manages toolsets within MSBuild - */ -class cmVisualStudio10ToolsetOptions -{ -public: - std::string GetClFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetCSharpFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetRcFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetLibFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetLinkFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetMasmFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetToolsetName(std::string const& name, - std::string const& toolset) const; -}; From e562e8987ca0d569e19034ec97141a009999536b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 13:36:53 -0500 Subject: [PATCH 0087/1519] cmGlobalVisualStudio10Generator: Remove unused flag table method argument --- Source/cmGlobalVisualStudio10Generator.cxx | 121 ++++++++++----------- Source/cmGlobalVisualStudio10Generator.h | 21 ++-- 2 files changed, 66 insertions(+), 76 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 8ad6f5ddd84..e3eadf67b84 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1400,103 +1400,101 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - std::string optionsName = this->GetClFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName(this->GetPlatformName(), - this->DefaultCLFlagTableName); + std::string optionsName = + this->GetClFlagTableName(this->GetPlatformToolsetString()); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = this->GetToolsetName(this->DefaultCLFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - std::string optionsName = this->GetCSharpFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultCSharpFlagTableName); + std::string optionsName = + this->GetCSharpFlagTableName(this->GetPlatformToolsetString()); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultCSharpFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - std::string optionsName = this->GetRcFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName(this->GetPlatformName(), - this->DefaultRCFlagTableName); + std::string optionsName = + this->GetRcFlagTableName(this->GetPlatformToolsetString()); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = this->GetToolsetName(this->DefaultRCFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - std::string optionsName = this->GetLibFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultLibFlagTableName); + std::string optionsName = + this->GetLibFlagTableName(this->GetPlatformToolsetString()); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultLibFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - std::string optionsName = this->GetLinkFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultLinkFlagTableName); + std::string optionsName = + this->GetLinkFlagTableName(this->GetPlatformToolsetString()); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultLinkFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultCudaFlagTableName); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultCudaFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultCudaHostFlagTableName); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultCudaHostFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - std::string optionsName = this->GetMasmFlagTableName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultMasmFlagTableName); + std::string optionsName = + this->GetMasmFlagTableName(this->GetPlatformToolsetString()); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultMasmFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - std::string toolsetName = this->GetToolsetName( - this->GetPlatformName(), this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName( - this->GetPlatformName(), this->DefaultNasmFlagTableName); + std::string toolsetName = + this->GetToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->GetToolsetName(this->DefaultNasmFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "NASM"); } std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(name, toolset); + std::string const useToolset = this->GetToolsetName(toolset); if (toolset == "v142") { return "v142"; @@ -1516,9 +1514,9 @@ std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( } std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(name, toolset); + std::string const useToolset = this->GetToolsetName(toolset); if (useToolset == "v142") { return "v142"; @@ -1538,9 +1536,9 @@ std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( } std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(name, toolset); + std::string const useToolset = this->GetToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || (useToolset == "v142")) { @@ -1557,9 +1555,9 @@ std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( } std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(name, toolset); + std::string const useToolset = this->GetToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || (useToolset == "v142")) { @@ -1576,9 +1574,9 @@ std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( } std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(name, toolset); + std::string const useToolset = this->GetToolsetName(toolset); if (useToolset == "v142") { return "v142"; @@ -1598,9 +1596,9 @@ std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( } std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(name, toolset); + std::string const useToolset = this->GetToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || (useToolset == "v142")) { @@ -1617,9 +1615,8 @@ std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName( } std::string cmGlobalVisualStudio10Generator::GetToolsetName( - std::string const& name, std::string const& toolset) const + std::string const& toolset) const { - static_cast(name); std::size_t length = toolset.length(); if (cmHasLiteralSuffix(toolset, "_xp")) { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 64a7b959f84..5057572f47c 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -232,20 +232,13 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); - std::string GetClFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetCSharpFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetRcFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetLibFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetLinkFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetMasmFlagTableName(std::string const& name, - std::string const& toolset) const; - std::string GetToolsetName(std::string const& name, - std::string const& toolset) const; + std::string GetClFlagTableName(std::string const& toolset) const; + std::string GetCSharpFlagTableName(std::string const& toolset) const; + std::string GetRcFlagTableName(std::string const& toolset) const; + std::string GetLibFlagTableName(std::string const& toolset) const; + std::string GetLinkFlagTableName(std::string const& toolset) const; + std::string GetMasmFlagTableName(std::string const& toolset) const; + std::string GetToolsetName(std::string const& toolset) const; std::string CustomVCTargetsPath; std::string VCTargetsPath; From a1c0758ea0c26eb1f5003cca431f3326e1e2495b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 13:42:52 -0500 Subject: [PATCH 0088/1519] cmGlobalVisualStudio10Generator: Clarify method name --- Source/cmGlobalVisualStudio10Generator.cxx | 52 +++++++++++----------- Source/cmGlobalVisualStudio10Generator.h | 2 +- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index e3eadf67b84..a8207b50d3e 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1403,8 +1403,9 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const std::string optionsName = this->GetClFlagTableName(this->GetPlatformToolsetString()); std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName(this->DefaultCLFlagTableName); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->CanonicalToolsetName(this->DefaultCLFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); } @@ -1414,9 +1415,9 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() std::string optionsName = this->GetCSharpFlagTableName(this->GetPlatformToolsetString()); std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultCSharpFlagTableName); + this->CanonicalToolsetName(this->DefaultCSharpFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); } @@ -1425,8 +1426,9 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const std::string optionsName = this->GetRcFlagTableName(this->GetPlatformToolsetString()); std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); - std::string defaultName = this->GetToolsetName(this->DefaultRCFlagTableName); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); + std::string defaultName = + this->CanonicalToolsetName(this->DefaultRCFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); } @@ -1435,9 +1437,9 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const std::string optionsName = this->GetLibFlagTableName(this->GetPlatformToolsetString()); std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultLibFlagTableName); + this->CanonicalToolsetName(this->DefaultLibFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); } @@ -1446,18 +1448,18 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const std::string optionsName = this->GetLinkFlagTableName(this->GetPlatformToolsetString()); std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultLinkFlagTableName); + this->CanonicalToolsetName(this->DefaultLinkFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultCudaFlagTableName); + this->CanonicalToolsetName(this->DefaultCudaFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "Cuda"); } @@ -1465,9 +1467,9 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultCudaHostFlagTableName); + this->CanonicalToolsetName(this->DefaultCudaHostFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); } @@ -1476,25 +1478,25 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const std::string optionsName = this->GetMasmFlagTableName(this->GetPlatformToolsetString()); std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultMasmFlagTableName); + this->CanonicalToolsetName(this->DefaultMasmFlagTableName); return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { std::string toolsetName = - this->GetToolsetName(this->GetPlatformToolsetString()); + this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = - this->GetToolsetName(this->DefaultNasmFlagTableName); + this->CanonicalToolsetName(this->DefaultNasmFlagTableName); return LoadFlagTable("", toolsetName, defaultName, "NASM"); } std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(toolset); + std::string const useToolset = this->CanonicalToolsetName(toolset); if (toolset == "v142") { return "v142"; @@ -1516,7 +1518,7 @@ std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(toolset); + std::string const useToolset = this->CanonicalToolsetName(toolset); if (useToolset == "v142") { return "v142"; @@ -1538,7 +1540,7 @@ std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(toolset); + std::string const useToolset = this->CanonicalToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || (useToolset == "v142")) { @@ -1557,7 +1559,7 @@ std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(toolset); + std::string const useToolset = this->CanonicalToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || (useToolset == "v142")) { @@ -1576,7 +1578,7 @@ std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(toolset); + std::string const useToolset = this->CanonicalToolsetName(toolset); if (useToolset == "v142") { return "v142"; @@ -1598,7 +1600,7 @@ std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName( std::string const& toolset) const { - std::string const useToolset = this->GetToolsetName(toolset); + std::string const useToolset = this->CanonicalToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || (useToolset == "v142")) { @@ -1614,7 +1616,7 @@ std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName( } } -std::string cmGlobalVisualStudio10Generator::GetToolsetName( +std::string cmGlobalVisualStudio10Generator::CanonicalToolsetName( std::string const& toolset) const { std::size_t length = toolset.length(); diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 5057572f47c..6736e17a86b 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -238,7 +238,7 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string GetLibFlagTableName(std::string const& toolset) const; std::string GetLinkFlagTableName(std::string const& toolset) const; std::string GetMasmFlagTableName(std::string const& toolset) const; - std::string GetToolsetName(std::string const& toolset) const; + std::string CanonicalToolsetName(std::string const& toolset) const; std::string CustomVCTargetsPath; std::string VCTargetsPath; From 1b774e18fbf98b1e5b3b046e621e36f2e7d145f5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 13:50:43 -0500 Subject: [PATCH 0089/1519] cmGlobalVisualStudio10Generator: Remove redundant arguments --- Source/cmGlobalVisualStudio10Generator.cxx | 42 ++++++++++------------ Source/cmGlobalVisualStudio10Generator.h | 12 +++---- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index a8207b50d3e..a155d7dfc63 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1400,8 +1400,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - std::string optionsName = - this->GetClFlagTableName(this->GetPlatformToolsetString()); + std::string optionsName = this->GetClFlagTableName(); std::string toolsetName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = @@ -1412,8 +1411,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - std::string optionsName = - this->GetCSharpFlagTableName(this->GetPlatformToolsetString()); + std::string optionsName = this->GetCSharpFlagTableName(); std::string toolsetName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = @@ -1423,8 +1421,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - std::string optionsName = - this->GetRcFlagTableName(this->GetPlatformToolsetString()); + std::string optionsName = this->GetRcFlagTableName(); std::string toolsetName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = @@ -1434,8 +1431,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - std::string optionsName = - this->GetLibFlagTableName(this->GetPlatformToolsetString()); + std::string optionsName = this->GetLibFlagTableName(); std::string toolsetName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = @@ -1445,8 +1441,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - std::string optionsName = - this->GetLinkFlagTableName(this->GetPlatformToolsetString()); + std::string optionsName = this->GetLinkFlagTableName(); std::string toolsetName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = @@ -1475,8 +1470,7 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - std::string optionsName = - this->GetMasmFlagTableName(this->GetPlatformToolsetString()); + std::string optionsName = this->GetMasmFlagTableName(); std::string toolsetName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = @@ -1493,9 +1487,9 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const return LoadFlagTable("", toolsetName, defaultName, "NASM"); } -std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( - std::string const& toolset) const +std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const { + std::string const& toolset = this->GetPlatformToolsetString(); std::string const useToolset = this->CanonicalToolsetName(toolset); if (toolset == "v142") { @@ -1515,9 +1509,9 @@ std::string cmGlobalVisualStudio10Generator::GetClFlagTableName( } } -std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( - std::string const& toolset) const +std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName() const { + std::string const& toolset = this->GetPlatformToolsetString(); std::string const useToolset = this->CanonicalToolsetName(toolset); if (useToolset == "v142") { @@ -1537,9 +1531,9 @@ std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName( } } -std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( - std::string const& toolset) const +std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName() const { + std::string const& toolset = this->GetPlatformToolsetString(); std::string const useToolset = this->CanonicalToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || @@ -1556,9 +1550,9 @@ std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName( } } -std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( - std::string const& toolset) const +std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName() const { + std::string const& toolset = this->GetPlatformToolsetString(); std::string const useToolset = this->CanonicalToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || @@ -1575,9 +1569,9 @@ std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName( } } -std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( - std::string const& toolset) const +std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName() const { + std::string const& toolset = this->GetPlatformToolsetString(); std::string const useToolset = this->CanonicalToolsetName(toolset); if (useToolset == "v142") { @@ -1597,9 +1591,9 @@ std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName( } } -std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName( - std::string const& toolset) const +std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName() const { + std::string const& toolset = this->GetPlatformToolsetString(); std::string const useToolset = this->CanonicalToolsetName(toolset); if ((useToolset == "v140") || (useToolset == "v141") || diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 6736e17a86b..d683c37edc9 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -232,12 +232,12 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); - std::string GetClFlagTableName(std::string const& toolset) const; - std::string GetCSharpFlagTableName(std::string const& toolset) const; - std::string GetRcFlagTableName(std::string const& toolset) const; - std::string GetLibFlagTableName(std::string const& toolset) const; - std::string GetLinkFlagTableName(std::string const& toolset) const; - std::string GetMasmFlagTableName(std::string const& toolset) const; + std::string GetClFlagTableName() const; + std::string GetCSharpFlagTableName() const; + std::string GetRcFlagTableName() const; + std::string GetLibFlagTableName() const; + std::string GetLinkFlagTableName() const; + std::string GetMasmFlagTableName() const; std::string CanonicalToolsetName(std::string const& toolset) const; std::string CustomVCTargetsPath; From 99f6f1b3b9df00f0221a0603fca12c4388f3c596 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 13:50:43 -0500 Subject: [PATCH 0090/1519] cmGlobalVisualStudio10Generator: Remove redundant arguments --- Source/cmGlobalVisualStudio10Generator.cxx | 42 +++++++--------------- Source/cmGlobalVisualStudio10Generator.h | 1 - 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index a155d7dfc63..6b7a972c938 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1366,8 +1366,8 @@ static std::string cmGetFlagTableName(std::string const& toolsetName, } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( - std::string const& optionsName, std::string const& toolsetName, - std::string const& defaultName, std::string const& table) const + std::string const& optionsName, std::string const& defaultName, + std::string const& table) const { cmIDEFlagTable const* ret = nullptr; @@ -1376,6 +1376,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( filename = cmGetFlagTableName(optionsName, table); ret = cmLoadFlagTableJson(filename); } else { + std::string const& toolsetName = + this->CanonicalToolsetName(this->GetPlatformToolsetString()); filename = cmGetFlagTableName(toolsetName, table); if (cmSystemTools::FileExists(filename)) { ret = cmLoadFlagTableJson(filename); @@ -1401,90 +1403,72 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { std::string optionsName = this->GetClFlagTableName(); - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultCLFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "CL"); + return LoadFlagTable(optionsName, defaultName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { std::string optionsName = this->GetCSharpFlagTableName(); - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultCSharpFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp"); + return LoadFlagTable(optionsName, defaultName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { std::string optionsName = this->GetRcFlagTableName(); - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultRCFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "RC"); + return LoadFlagTable(optionsName, defaultName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { std::string optionsName = this->GetLibFlagTableName(); - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultLibFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB"); + return LoadFlagTable(optionsName, defaultName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { std::string optionsName = this->GetLinkFlagTableName(); - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultLinkFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "Link"); + return LoadFlagTable(optionsName, defaultName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultCudaFlagTableName); - return LoadFlagTable("", toolsetName, defaultName, "Cuda"); + return LoadFlagTable("", defaultName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultCudaHostFlagTableName); - return LoadFlagTable("", toolsetName, defaultName, "CudaHost"); + return LoadFlagTable("", defaultName, "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { std::string optionsName = this->GetMasmFlagTableName(); - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultMasmFlagTableName); - return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM"); + return LoadFlagTable(optionsName, defaultName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - std::string toolsetName = - this->CanonicalToolsetName(this->GetPlatformToolsetString()); std::string defaultName = this->CanonicalToolsetName(this->DefaultNasmFlagTableName); - return LoadFlagTable("", toolsetName, defaultName, "NASM"); + return LoadFlagTable("", defaultName, "NASM"); } std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index d683c37edc9..5160f2914d0 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -170,7 +170,6 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string const& GetMSBuildCommand(); cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName, - std::string const& toolsetName, std::string const& defaultName, std::string const& table) const; From d5522f096da4a04669e49bebfb63887ca1b0fdde Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 15:25:01 -0500 Subject: [PATCH 0091/1519] cmGlobalVisualStudio10Generator: Drop default toolset name canonicalization The default toolset names are always canonical. --- Source/cmGlobalVisualStudio10Generator.cxx | 37 ++++++---------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 6b7a972c938..101ddc052bb 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1403,72 +1403,55 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { std::string optionsName = this->GetClFlagTableName(); - std::string defaultName = - this->CanonicalToolsetName(this->DefaultCLFlagTableName); - return LoadFlagTable(optionsName, defaultName, "CL"); + return LoadFlagTable(optionsName, this->DefaultCLFlagTableName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { std::string optionsName = this->GetCSharpFlagTableName(); - std::string defaultName = - this->CanonicalToolsetName(this->DefaultCSharpFlagTableName); - return LoadFlagTable(optionsName, defaultName, "CSharp"); + return LoadFlagTable(optionsName, this->DefaultCSharpFlagTableName, + "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { std::string optionsName = this->GetRcFlagTableName(); - std::string defaultName = - this->CanonicalToolsetName(this->DefaultRCFlagTableName); - return LoadFlagTable(optionsName, defaultName, "RC"); + return LoadFlagTable(optionsName, this->DefaultRCFlagTableName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { std::string optionsName = this->GetLibFlagTableName(); - std::string defaultName = - this->CanonicalToolsetName(this->DefaultLibFlagTableName); - return LoadFlagTable(optionsName, defaultName, "LIB"); + return LoadFlagTable(optionsName, this->DefaultLibFlagTableName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { std::string optionsName = this->GetLinkFlagTableName(); - std::string defaultName = - this->CanonicalToolsetName(this->DefaultLinkFlagTableName); - return LoadFlagTable(optionsName, defaultName, "Link"); + return LoadFlagTable(optionsName, this->DefaultLinkFlagTableName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - std::string defaultName = - this->CanonicalToolsetName(this->DefaultCudaFlagTableName); - return LoadFlagTable("", defaultName, "Cuda"); + return LoadFlagTable("", this->DefaultCudaFlagTableName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - std::string defaultName = - this->CanonicalToolsetName(this->DefaultCudaHostFlagTableName); - return LoadFlagTable("", defaultName, "CudaHost"); + return LoadFlagTable("", this->DefaultCudaHostFlagTableName, "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { std::string optionsName = this->GetMasmFlagTableName(); - std::string defaultName = - this->CanonicalToolsetName(this->DefaultMasmFlagTableName); - return LoadFlagTable(optionsName, defaultName, "MASM"); + return LoadFlagTable(optionsName, this->DefaultMasmFlagTableName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - std::string defaultName = - this->CanonicalToolsetName(this->DefaultNasmFlagTableName); - return LoadFlagTable("", defaultName, "NASM"); + return LoadFlagTable("", this->DefaultNasmFlagTableName, "NASM"); } std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const From cbba9f26a891d477851fac1cf1515d69c25d41a9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 15:29:08 -0500 Subject: [PATCH 0092/1519] cmGlobalVisualStudio10Generator: Drop unnecessary temporaries --- Source/cmGlobalVisualStudio10Generator.cxx | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 101ddc052bb..0c7f1c49b79 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1402,56 +1402,56 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const { - std::string optionsName = this->GetClFlagTableName(); - return LoadFlagTable(optionsName, this->DefaultCLFlagTableName, "CL"); + return LoadFlagTable(this->GetClFlagTableName(), + this->DefaultCLFlagTableName, "CL"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable() const { - std::string optionsName = this->GetCSharpFlagTableName(); - return LoadFlagTable(optionsName, this->DefaultCSharpFlagTableName, - "CSharp"); + return LoadFlagTable(this->GetCSharpFlagTableName(), + this->DefaultCSharpFlagTableName, "CSharp"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const { - std::string optionsName = this->GetRcFlagTableName(); - return LoadFlagTable(optionsName, this->DefaultRCFlagTableName, "RC"); + return LoadFlagTable(this->GetRcFlagTableName(), + this->DefaultRCFlagTableName, "RC"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const { - std::string optionsName = this->GetLibFlagTableName(); - return LoadFlagTable(optionsName, this->DefaultLibFlagTableName, "LIB"); + return LoadFlagTable(this->GetLibFlagTableName(), + this->DefaultLibFlagTableName, "LIB"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const { - std::string optionsName = this->GetLinkFlagTableName(); - return LoadFlagTable(optionsName, this->DefaultLinkFlagTableName, "Link"); + return LoadFlagTable(this->GetLinkFlagTableName(), + this->DefaultLinkFlagTableName, "Link"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const { - return LoadFlagTable("", this->DefaultCudaFlagTableName, "Cuda"); + return LoadFlagTable(std::string(), this->DefaultCudaFlagTableName, "Cuda"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() const { - return LoadFlagTable("", this->DefaultCudaHostFlagTableName, "CudaHost"); + return LoadFlagTable(std::string(), this->DefaultCudaHostFlagTableName, + "CudaHost"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { - std::string optionsName = this->GetMasmFlagTableName(); - return LoadFlagTable(optionsName, this->DefaultMasmFlagTableName, "MASM"); + return LoadFlagTable(this->GetMasmFlagTableName(), + this->DefaultMasmFlagTableName, "MASM"); } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const { - return LoadFlagTable("", this->DefaultNasmFlagTableName, "NASM"); + return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM"); } std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const From 414b5e0119a99de401e1d7aea61428ec2c9311d5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 15:34:34 -0500 Subject: [PATCH 0093/1519] cmGlobalVisualStudio10Generator: Clarify LoadFlagTable argument name --- Source/cmGlobalVisualStudio10Generator.cxx | 10 +++++----- Source/cmGlobalVisualStudio10Generator.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 0c7f1c49b79..40e30d59c63 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1366,19 +1366,19 @@ static std::string cmGetFlagTableName(std::string const& toolsetName, } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( - std::string const& optionsName, std::string const& defaultName, + std::string const& toolSpecificName, std::string const& defaultName, std::string const& table) const { cmIDEFlagTable const* ret = nullptr; std::string filename; - if (!optionsName.empty()) { - filename = cmGetFlagTableName(optionsName, table); + if (!toolSpecificName.empty()) { + filename = cmGetFlagTableName(toolSpecificName, table); ret = cmLoadFlagTableJson(filename); } else { - std::string const& toolsetName = + std::string const& genericName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); - filename = cmGetFlagTableName(toolsetName, table); + filename = cmGetFlagTableName(genericName, table); if (cmSystemTools::FileExists(filename)) { ret = cmLoadFlagTableJson(filename); } else { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 5160f2914d0..e8f5ab59cd1 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -169,7 +169,7 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string const& GetMSBuildCommand(); - cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName, + cmIDEFlagTable const* LoadFlagTable(std::string const& toolSpecificName, std::string const& defaultName, std::string const& table) const; From 1b33150f7eff42df9d3f926b078de44681755a1d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 16:23:52 -0500 Subject: [PATCH 0094/1519] cmGlobalVisualStudio10Generator: Generalize flag table lookup interface --- Source/cmGlobalVisualStudio10Generator.cxx | 59 ++++++++++++++-------- Source/cmGlobalVisualStudio10Generator.h | 6 +++ 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 40e30d59c63..8d68bf6b4e9 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1358,46 +1358,61 @@ static cmIDEFlagTable const* cmLoadFlagTableJson( return ret; } -static std::string cmGetFlagTableName(std::string const& toolsetName, - std::string const& table) +cm::optional cmGlobalVisualStudio10Generator::FindFlagTable( + cm::string_view toolsetName, cm::string_view table) const { - return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" + - toolsetName + "_" + table + ".json"; + std::string fullPath = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/MSBuild/FlagTables/", + toolsetName, '_', table, ".json"); + if (cmSystemTools::FileExists(fullPath)) { + return fullPath; + } + return {}; } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( std::string const& toolSpecificName, std::string const& defaultName, std::string const& table) const { - cmIDEFlagTable const* ret = nullptr; + cmMakefile* mf = this->GetCurrentMakefile(); std::string filename; if (!toolSpecificName.empty()) { - filename = cmGetFlagTableName(toolSpecificName, table); - ret = cmLoadFlagTableJson(filename); + if (cm::optional found = + this->FindFlagTable(toolSpecificName, table)) { + filename = std::move(*found); + } else { + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("JSON flag table for ", table, + " not found for toolset ", toolSpecificName)); + return nullptr; + } } else { std::string const& genericName = this->CanonicalToolsetName(this->GetPlatformToolsetString()); - filename = cmGetFlagTableName(genericName, table); - if (cmSystemTools::FileExists(filename)) { - ret = cmLoadFlagTableJson(filename); + cm::optional found = this->FindFlagTable(genericName, table); + if (!found) { + found = this->FindFlagTable(defaultName, table); + } + if (found) { + filename = std::move(*found); } else { - filename = cmGetFlagTableName(defaultName, table); - ret = cmLoadFlagTableJson(filename); + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("JSON flag table for ", table, + " not found for toolset ", genericName, " ", + defaultName)); + return nullptr; } } - if (!ret) { - cmMakefile* mf = this->GetCurrentMakefile(); - - std::ostringstream e; - /* clang-format off */ - e << "JSON flag table \"" << filename << - "\" could not be loaded.\n"; - /* clang-format on */ - mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename)) { + return ret; } - return ret; + + mf->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("JSON flag table could not be loaded:\n ", filename)); + return nullptr; } cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index e8f5ab59cd1..df79ad7675e 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -5,6 +5,9 @@ #include #include +#include +#include + #include "cmGlobalVisualStudio8Generator.h" /** \class cmGlobalVisualStudio10Generator @@ -239,6 +242,9 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string GetMasmFlagTableName() const; std::string CanonicalToolsetName(std::string const& toolset) const; + cm::optional FindFlagTable(cm::string_view toolsetName, + cm::string_view table) const; + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); From 934861e3549b54b9c91c0d501f7e75901d8fa57e Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Fri, 5 Mar 2021 09:59:39 -0500 Subject: [PATCH 0095/1519] Find: Document that first argument to PATHS and HINTS can be ENV{} --- Help/command/FIND_XXX.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index 97eecfca36e..aae1c382877 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -11,8 +11,8 @@ The general signature is: |FIND_XXX| ( name | |NAMES| - [HINTS path1 [path2 ... ENV var]] - [PATHS path1 [path2 ... ENV var]] + [HINTS [path | ENV var]... ] + [PATHS [path | ENV var]... ] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [REQUIRED] From fdfbf89f0c650a9886ffa91e4f3fda08080702b9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 09:06:34 -0500 Subject: [PATCH 0096/1519] ExternalData: Avoid replacing a concurrently-created object If more than one content link references the same object, the build system may launch multiple download processes for the same object concurrently. Use whichever one finishes first, and discard the others. Without this, we replace the objects and use the last finisher instead of the first. This is okay on non-Windows platforms where `rename(2)` gives reliable atomic replacement. However, on Windows platforms and NTFS this is less reliable. I've observed `MoveFileEx` somehow cause another process to get `ERROR_SHARING_VIOLATION` when attempting to read the destination file. We may be able to improve the `file(RENAME)` implementation on modern Windows 10 versions, but for ExternalData's use case it is simpler to just not replace existing objects. --- Modules/ExternalData.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index d6fbae9aaf1..b439636f5c4 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -1101,7 +1101,14 @@ function(_ExternalData_download_object name hash algo var_obj var_success var_er set(success 1) if(found) - file(RENAME "${tmp}" "${obj}") + # Atomically create the object. If we lose a race with another process, + # do not replace it. Content-addressing ensures it has what we expect. + file(RENAME "${tmp}" "${obj}" NO_REPLACE RESULT result) + if (result STREQUAL "NO_REPLACE") + file(REMOVE "${tmp}") + elseif (result) + message(FATAL_ERROR "Failed to rename:\n \"${tmp}\"\nto:\n \"${obj}\"\nwith error:\n ${result}") + endif() message(STATUS "Downloaded object: \"${obj}\"") elseif(EXISTS "${staged}") set(obj "${staged}") From 31be23dd1d61db80656159adbcf915a609b8692f Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Mar 2021 10:58:54 -0500 Subject: [PATCH 0097/1519] ci: Restore the Module.ExternalData test on Windows In commit a58e3c7e8b (ci: Skip the Module.ExternalData test on Windows, 2020-10-01, v3.19.0-rc1~59^2) the test was dropped pending further investigation. We've now (hopefully) resolved the underlying problem, so we can restore the test. --- .gitlab/ci/ctest_exclusions.cmake | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.gitlab/ci/ctest_exclusions.cmake b/.gitlab/ci/ctest_exclusions.cmake index a68a693bf4c..b885a6a5e78 100644 --- a/.gitlab/ci/ctest_exclusions.cmake +++ b/.gitlab/ci/ctest_exclusions.cmake @@ -13,15 +13,6 @@ if (CTEST_CMAKE_GENERATOR MATCHES "Visual Studio") "^ExternalProjectUpdateSetup$") endif () -if (CMAKE_HOST_WIN32) - list(APPEND test_exclusions - # This test often fails with an undiagnosed subtle race due to the test - # re-using the same objects for many files. Some copy operations fail - # to open their input with ERROR_SHARING_VIOLATION. - "^Module.ExternalData$" - ) -endif() - string(REPLACE ";" "|" test_exclusions "${test_exclusions}") if (test_exclusions) set(test_exclusions "(${test_exclusions})") From 425ac4c3b3eb4c7eba9eb3b9f17f19b26e4d22e8 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 6 Mar 2021 00:01:19 -0500 Subject: [PATCH 0098/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 406174b91e8..27075b32906 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210305) +set(CMake_VERSION_PATCH 20210306) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b72c7f856dc99b3e437ad79201586db32cb65da1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 7 Mar 2021 00:01:08 -0500 Subject: [PATCH 0099/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 27075b32906..a8e47d25105 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210306) +set(CMake_VERSION_PATCH 20210307) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ae791686e7de6c0e80b6120bf2a8949ad5fe4ee5 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 8 Mar 2021 00:03:15 -0500 Subject: [PATCH 0100/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a8e47d25105..f98c0efad40 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210307) +set(CMake_VERSION_PATCH 20210308) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 388eb83c098400cb63493896e12b05d685040147 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 8 Mar 2021 13:02:36 -0500 Subject: [PATCH 0101/1519] Tests: Enable MAKE_SUPPORTS_SPACES tests with Ninja generators --- Tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 987f54d0419..c3652fe67ed 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -96,7 +96,7 @@ if(BUILD_TESTING) # some old versions of make simply cannot handle spaces in paths if (MAKE_IS_GNU OR CMAKE_MAKE_PROGRAM MATCHES "nmake|gmake|wmake" OR - CMAKE_GENERATOR MATCHES "Visual Studio|Xcode|Borland") + CMAKE_GENERATOR MATCHES "Visual Studio|Xcode|Borland|Ninja") set(MAKE_SUPPORTS_SPACES 1) else() set(MAKE_SUPPORTS_SPACES 0) From 7621861f30992bdaddb66a7f3e5dce6eec4545bd Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 15:50:16 -0500 Subject: [PATCH 0102/1519] Tests: Update LibName to cover spaces in shared library name --- Tests/CMakeLists.txt | 2 ++ Tests/LibName/CMakeLists.txt | 8 ++++++++ Tests/LibName/use_ver_space.c | 9 +++++++++ Tests/LibName/ver_space.c | 7 +++++++ 4 files changed, 26 insertions(+) create mode 100644 Tests/LibName/use_ver_space.c create mode 100644 Tests/LibName/ver_space.c diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index c3652fe67ed..3a05317c19a 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -828,6 +828,8 @@ if(BUILD_TESTING) ${build_generator_args} --build-project LibName --build-exe-dir "${CMake_BINARY_DIR}/Tests/LibName/lib" + --build-options + -DMAKE_SUPPORTS_SPACES=${MAKE_SUPPORTS_SPACES} --test-command foobar ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LibName") diff --git a/Tests/LibName/CMakeLists.txt b/Tests/LibName/CMakeLists.txt index 3ac125fb975..b8f08909275 100644 --- a/Tests/LibName/CMakeLists.txt +++ b/Tests/LibName/CMakeLists.txt @@ -24,3 +24,11 @@ set_target_properties(verFoo PROPERTIES VERSION 3.1.4 SOVERSION 3) add_executable(verFoobar foobar.c) target_link_libraries(verFoobar verFoo) + +if(MAKE_SUPPORTS_SPACES AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake") + # check with lib version and space + add_library(ver_space SHARED ver_space.c) + set_target_properties(ver_space PROPERTIES VERSION 3.1.4 SOVERSION 3 OUTPUT_NAME "ver space") + add_executable(use_ver_space use_ver_space.c) + target_link_libraries(use_ver_space ver_space) +endif() diff --git a/Tests/LibName/use_ver_space.c b/Tests/LibName/use_ver_space.c new file mode 100644 index 00000000000..a6a733df577 --- /dev/null +++ b/Tests/LibName/use_ver_space.c @@ -0,0 +1,9 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + int ver_space(void); + +int main(void) +{ + return ver_space(); +} diff --git a/Tests/LibName/ver_space.c b/Tests/LibName/ver_space.c new file mode 100644 index 00000000000..669a3b52848 --- /dev/null +++ b/Tests/LibName/ver_space.c @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + int ver_space(void) +{ + return 0; +} From 9e556829c8fd2e78860e798f454f90dc1160dd20 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Mon, 8 Mar 2021 13:32:05 -0500 Subject: [PATCH 0103/1519] KWSys 2021-03-08 (5bfba5e1) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 5bfba5e1a988e16df833e86062d61f4b70d83645 (master). Upstream Shortlog ----------------- Ben Boeckel (4): f69c5cb7 Directory: return a bool literal on Windows 2a118b34 SystemTools: use nullptr in Windows-only code 7ee0dbee Directory: capture the error message dd703ac6 SystemTools: make file copying mechanisms public Sean McBride (1): 3ba8a6de Glob: Change deleted ctor and operator= from private to public --- Directory.cxx | 30 +++++++++++++++++++++++++++++- Glob.hxx.in | 7 +++---- SystemTools.cxx | 17 +++++++---------- SystemTools.hxx.in | 11 +++++++++++ 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/Directory.cxx b/Directory.cxx index 0c2190aee53..e70d4e86882 100644 --- a/Directory.cxx +++ b/Directory.cxx @@ -121,7 +121,21 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) delete[] buf; if (srchHandle == -1) { - return 0; + if (errorMessage) { + if (unsigned int errorId = GetLastError()) { + LPSTR message = nullptr; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, nullptr); + *errorMessage = std::string(message, size); + LocalFree(message); + } else { + *errorMessage = "Unknown error."; + } + } + return false; } // Loop through names @@ -152,6 +166,20 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, delete[] buf; if (srchHandle == -1) { + if (errorMessage) { + if (unsigned int errorId = GetLastError()) { + LPSTR message = nullptr; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, nullptr); + *errorMessage = std::string(message, size); + LocalFree(message); + } else { + *errorMessage = "Unknown error."; + } + } return 0; } diff --git a/Glob.hxx.in b/Glob.hxx.in index e8474e20015..fd39775417c 100644 --- a/Glob.hxx.in +++ b/Glob.hxx.in @@ -54,6 +54,9 @@ public: Glob(); ~Glob(); + Glob(const Glob&) = delete; + void operator=(const Glob&) = delete; + //! Find all files that match the pattern. bool FindFiles(const std::string& inexpr, GlobMessages* messages = nullptr); @@ -124,10 +127,6 @@ protected: std::vector VisitedSymlinks; bool ListDirs; bool RecurseListDirs; - -private: - Glob(const Glob&) = delete; - void operator=(const Glob&) = delete; }; } // namespace @KWSYS_NAMESPACE@ diff --git a/SystemTools.cxx b/SystemTools.cxx index 6144d9c04dd..cf04799776d 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -244,7 +244,7 @@ inline int Chdir(const std::string& dir) return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); } inline void Realpath(const std::string& path, std::string& resolved_path, - std::string* errorMessage = 0) + std::string* errorMessage = nullptr) { std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path); wchar_t* ptemp; @@ -2273,11 +2273,8 @@ bool SystemTools::TextFilesDiffer(const std::string& path1, return false; } -/** - * Blockwise copy source to destination file - */ -static bool CopyFileContentBlockwise(const std::string& source, - const std::string& destination) +bool SystemTools::CopyFileContentBlockwise(const std::string& source, + const std::string& destination) { // Open files kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); @@ -2341,8 +2338,8 @@ static bool CopyFileContentBlockwise(const std::string& source, * - The underlying filesystem does not support file cloning * - An unspecified error occurred */ -static bool CloneFileContent(const std::string& source, - const std::string& destination) +bool SystemTools::CloneFileContent(const std::string& source, + const std::string& destination) { #if defined(__linux) && defined(FICLONE) int in = open(source.c_str(), O_RDONLY); @@ -2410,9 +2407,9 @@ bool SystemTools::CopyFileAlways(const std::string& source, SystemTools::MakeDirectory(destination_dir); - if (!CloneFileContent(source, real_destination)) { + if (!SystemTools::CloneFileContent(source, real_destination)) { // if cloning did not succeed, fall back to blockwise copy - if (!CopyFileContentBlockwise(source, real_destination)) { + if (!SystemTools::CopyFileContentBlockwise(source, real_destination)) { return false; } } diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index 74dc1765143..a7b1288733e 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -577,6 +577,17 @@ public: static bool TextFilesDiffer(const std::string& path1, const std::string& path2); + /** + * Blockwise copy source to destination file + */ + static bool CopyFileContentBlockwise(const std::string& source, + const std::string& destination); + /** + * Clone the source file to the destination file + */ + static bool CloneFileContent(const std::string& source, + const std::string& destination); + /** * Return true if the two files are the same file */ From a8954cc3c47a1a9459ddbe10f5b288e466872076 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 9 Mar 2021 00:01:16 -0500 Subject: [PATCH 0104/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f98c0efad40..ee17d4005ef 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210308) +set(CMake_VERSION_PATCH 20210309) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6fd7e8c53f83ed5b38dd7a5ca9383b22dc6739cf Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 9 Mar 2021 07:34:17 -0500 Subject: [PATCH 0105/1519] Tests: Make RunCMake.Generator{Platform,Toolset} two-flag cases explicit Do not rely on the RunCMake infrastructure to pass `-T` or `-A`. --- Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake | 4 ++-- Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index 27ede066ec0..83e63f91853 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -11,9 +11,9 @@ else() run_cmake(BadPlatform) endif() -set(RunCMake_GENERATOR_TOOLSET "") +set(RunCMake_GENERATOR_PLATFORM "") -set(RunCMake_TEST_OPTIONS -A "Extra Platform") +set(RunCMake_TEST_OPTIONS -A "Test Platform" -A "Extra Platform") run_cmake(TwoPlatforms) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index 5f12d799a1b..75ed677be9b 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -76,7 +76,7 @@ endif() set(RunCMake_GENERATOR_TOOLSET "") -set(RunCMake_TEST_OPTIONS -T "Extra Toolset") +set(RunCMake_TEST_OPTIONS -T "Test Toolset" -T "Extra Toolset") run_cmake(TwoToolsets) unset(RunCMake_TEST_OPTIONS) From f4d154755ac751541a084415d669deb11e8da76c Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 9 Mar 2021 06:52:53 -0500 Subject: [PATCH 0106/1519] Tests: Reverse RunCMake code path order --- Tests/RunCMake/RunCMake.cmake | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 1a690594d45..c1023f0ca9d 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -91,21 +91,7 @@ function(run_cmake test) else() set(maybe_input_file "") endif() - if(RunCMake_TEST_COMMAND) - if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY) - set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") - endif() - execute_process( - COMMAND ${RunCMake_TEST_COMMAND} - WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}" - OUTPUT_VARIABLE actual_stdout - ERROR_VARIABLE ${actual_stderr_var} - RESULT_VARIABLE actual_result - ENCODING UTF8 - ${maybe_timeout} - ${maybe_input_file} - ) - else() + if(NOT RunCMake_TEST_COMMAND) if(RunCMake_GENERATOR_INSTANCE) set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}") else() @@ -134,6 +120,20 @@ function(run_cmake test) ${maybe_timeout} ${maybe_input_file} ) + else() + if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY) + set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + endif() + execute_process( + COMMAND ${RunCMake_TEST_COMMAND} + WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}" + OUTPUT_VARIABLE actual_stdout + ERROR_VARIABLE ${actual_stderr_var} + RESULT_VARIABLE actual_result + ENCODING UTF8 + ${maybe_timeout} + ${maybe_input_file} + ) endif() set(msg "") if(NOT "${actual_result}" MATCHES "${expect_result}") From 5f03744e3661f07e9c59d6e62ceec9ce3b45c404 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 9 Mar 2021 07:11:36 -0500 Subject: [PATCH 0107/1519] Tests: Move RunCMake option construction closer to use --- Tests/RunCMake/RunCMake.cmake | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index c1023f0ca9d..a690f4e7f9a 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -64,15 +64,6 @@ function(run_cmake test) else() include(${top_src}/${test}-prep.cmake OPTIONAL) endif() - if(NOT DEFINED RunCMake_TEST_OPTIONS) - set(RunCMake_TEST_OPTIONS "") - endif() - if(APPLE) - list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW) - endif() - if(RunCMake_MAKE_PROGRAM) - list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}") - endif() if(RunCMake_TEST_OUTPUT_MERGE) set(actual_stderr_var actual_stdout) set(actual_stderr "") @@ -92,6 +83,15 @@ function(run_cmake test) set(maybe_input_file "") endif() if(NOT RunCMake_TEST_COMMAND) + if(NOT DEFINED RunCMake_TEST_OPTIONS) + set(RunCMake_TEST_OPTIONS "") + endif() + if(APPLE) + list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW) + endif() + if(RunCMake_MAKE_PROGRAM) + list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}") + endif() if(RunCMake_GENERATOR_INSTANCE) set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}") else() From e8065554a8de34decaa1cd4a9df7865da85daf52 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 9 Mar 2021 07:12:09 -0500 Subject: [PATCH 0108/1519] Tests: Teach RunCMake to always print the command on failure Previously we only printed explicit `RunCMake_TEST_COMMAND` cases on failure. Refactor the RunCMake infrastructure so that we always define `RunCMake_TEST_COMMAND` internally, and print it on failure. --- Tests/RunCMake/RunCMake.cmake | 76 +++++++++++++++++------------------ 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index a690f4e7f9a..5e2f647b8ec 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -92,49 +92,41 @@ function(run_cmake test) if(RunCMake_MAKE_PROGRAM) list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}") endif() - if(RunCMake_GENERATOR_INSTANCE) - set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}") - else() - set(_D_CMAKE_GENERATOR_INSTANCE "") - endif() + set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND}) if(NOT RunCMake_TEST_NO_SOURCE_DIR) - set(maybe_source_dir "${RunCMake_TEST_SOURCE_DIR}") - else() - set(maybe_source_dir "") + list(APPEND RunCMake_TEST_COMMAND "${RunCMake_TEST_SOURCE_DIR}") endif() - execute_process( - COMMAND ${CMAKE_COMMAND} - ${maybe_source_dir} - -G "${RunCMake_GENERATOR}" - -A "${RunCMake_GENERATOR_PLATFORM}" - -T "${RunCMake_GENERATOR_TOOLSET}" - ${_D_CMAKE_GENERATOR_INSTANCE} - -DRunCMake_TEST=${test} - --no-warn-unused-cli - ${RunCMake_TEST_OPTIONS} - WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}" - OUTPUT_VARIABLE actual_stdout - ERROR_VARIABLE ${actual_stderr_var} - RESULT_VARIABLE actual_result - ENCODING UTF8 - ${maybe_timeout} - ${maybe_input_file} - ) - else() - if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY) - set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + list(APPEND RunCMake_TEST_COMMAND -G "${RunCMake_GENERATOR}") + if(RunCMake_GENERATOR_PLATFORM) + list(APPEND RunCMake_TEST_COMMAND -A "${RunCMake_GENERATOR_PLATFORM}") + endif() + if(RunCMake_GENERATOR_TOOLSET) + list(APPEND RunCMake_TEST_COMMAND -T "${RunCMake_GENERATOR_TOOLSET}") endif() - execute_process( - COMMAND ${RunCMake_TEST_COMMAND} - WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}" - OUTPUT_VARIABLE actual_stdout - ERROR_VARIABLE ${actual_stderr_var} - RESULT_VARIABLE actual_result - ENCODING UTF8 - ${maybe_timeout} - ${maybe_input_file} + if(RunCMake_GENERATOR_INSTANCE) + list(APPEND RunCMake_TEST_COMMAND "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}") + endif() + list(APPEND RunCMake_TEST_COMMAND + -DRunCMake_TEST=${test} + --no-warn-unused-cli ) - endif() + else() + set(RunCMake_TEST_OPTIONS "") + endif() + if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY) + set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + endif() + execute_process( + COMMAND ${RunCMake_TEST_COMMAND} + ${RunCMake_TEST_OPTIONS} + WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}" + OUTPUT_VARIABLE actual_stdout + ERROR_VARIABLE ${actual_stderr_var} + RESULT_VARIABLE actual_result + ENCODING UTF8 + ${maybe_timeout} + ${maybe_input_file} + ) set(msg "") if(NOT "${actual_result}" MATCHES "${expect_result}") string(APPEND msg "Result is [${actual_result}], not [${expect_result}].\n") @@ -190,8 +182,12 @@ function(run_cmake test) if(RunCMake_TEST_FAILED) set(msg "${RunCMake_TEST_FAILED}\n${msg}") endif() - if(msg AND RunCMake_TEST_COMMAND) + if(msg) string(REPLACE ";" "\" \"" command "\"${RunCMake_TEST_COMMAND}\"") + if(RunCMake_TEST_OPTIONS) + string(REPLACE ";" "\" \"" options "\"${RunCMake_TEST_OPTIONS}\"") + string(APPEND command " ${options}") + endif() string(APPEND msg "Command was:\n command> ${command}\n") endif() if(msg) From 7b0ab0439d58b72617e6cbcb9d357a388da83f2b Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 9 Mar 2021 06:22:45 -0500 Subject: [PATCH 0109/1519] Tests: Fix FortranModules test with Intel compiler on Windows The test regularly fails updating the `vc*.pdb` compiler-generated PDB file. Add the `/Z7` flag as the compiler suggests for this. --- Tests/FortranModules/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/FortranModules/CMakeLists.txt b/Tests/FortranModules/CMakeLists.txt index b7a6f68325c..94f59390801 100644 --- a/Tests/FortranModules/CMakeLists.txt +++ b/Tests/FortranModules/CMakeLists.txt @@ -1,6 +1,11 @@ cmake_minimum_required (VERSION 3.9) project(FortranModules Fortran) +if("${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" MATCHES "^Intel(LLVM)?;MSVC$") + string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -Z7") + string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO " -Z7") +endif() + if(NOT DEFINED CMake_TEST_NESTED_MAKE_PROGRAM AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") set(CMake_TEST_NESTED_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM}") endif() From 100016e9cb31aad7b642a9733409c7294cd6652f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 4 Mar 2021 11:51:03 -0500 Subject: [PATCH 0110/1519] cmSystemTools: add utilities to copy a file with error handling --- Source/cmSystemTools.cxx | 46 ++++++++++++++++++++++++++++++++++++++++ Source/cmSystemTools.h | 18 ++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index db5b1ac3342..87ba1525854 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -87,6 +87,7 @@ # include # include +# include #endif #if defined(_WIN32) && \ @@ -990,6 +991,51 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname, } #endif +bool cmSystemTools::CopySingleFile(const std::string& oldname, + const std::string& newname) +{ + return cmSystemTools::CopySingleFile(oldname, newname, CopyWhen::Always) == + CopyResult::Success; +} + +cmSystemTools::CopyResult cmSystemTools::CopySingleFile( + std::string const& oldname, std::string const& newname, CopyWhen when, + std::string* err) +{ + switch (when) { + case CopyWhen::Always: + break; + case CopyWhen::OnlyIfDifferent: + if (!FilesDiffer(oldname, newname)) { + return CopyResult::Success; + } + break; + } + + mode_t perm = 0; + bool perms = SystemTools::GetPermissions(oldname, perm); + + // If files are the same do not copy + if (SystemTools::SameFile(oldname, newname)) { + return CopyResult::Success; + } + + if (!cmsys::SystemTools::CloneFileContent(oldname, newname)) { + // if cloning did not succeed, fall back to blockwise copy + if (!cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname)) { + ReportError(err); + return CopyResult::Failure; + } + } + if (perms) { + if (!SystemTools::SetPermissions(newname, perm)) { + ReportError(err); + return CopyResult::Failure; + } + } + return CopyResult::Success; +} + bool cmSystemTools::RenameFile(const std::string& oldname, const std::string& newname) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 3cc032c5238..2ff4c5dd601 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -128,6 +128,24 @@ class cmSystemTools : public cmsys::SystemTools static bool SimpleGlob(const std::string& glob, std::vector& files, int type = 0); + enum class CopyWhen + { + Always, + OnlyIfDifferent, + }; + enum class CopyResult + { + Success, + Failure, + }; + + /** Copy a file. */ + static bool CopySingleFile(const std::string& oldname, + const std::string& newname); + static CopyResult CopySingleFile(std::string const& oldname, + std::string const& newname, CopyWhen when, + std::string* err = nullptr); + enum class Replace { Yes, From 9af6e2e7b2940d5ba4d138f0df5950a675ec41c0 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 26 Feb 2021 11:49:50 -0500 Subject: [PATCH 0111/1519] Ninja: Use new wincodepage tool to determine encoding Ninja 1.11 and later uses UTF-8 on Windows when possible, and includes a tool that reports the code page in use. Use this tool to determine what encoding to write the Ninja files in. Fixes: #21866 --- Source/cmGlobalNinjaGenerator.cxx | 65 +++++++++++++++++++++++++++---- Source/cmGlobalNinjaGenerator.h | 5 +++ Source/cmLocalNinjaGenerator.cxx | 5 ++- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 7eac16929f8..36be45cac92 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -503,14 +504,7 @@ std::unique_ptr cmGlobalNinjaGenerator::CreateLocalGenerator( codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const { -#ifdef _WIN32 - // Ninja on Windows does not support non-ANSI characters. - // https://github.com/ninja-build/ninja/issues/1195 - return codecvt::ANSI; -#else - // No encoding conversion needed on other platforms. - return codecvt::None; -#endif + return this->NinjaExpectedEncoding; } void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry) @@ -731,6 +725,61 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() this->NinjaSupportsMetadataOnRegeneration = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), RequiredNinjaVersionForMetadataOnRegeneration().c_str()); +#ifdef _WIN32 + this->NinjaSupportsCodePage = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForCodePage().c_str()); + if (this->NinjaSupportsCodePage) { + this->CheckNinjaCodePage(); + } else { + this->NinjaExpectedEncoding = codecvt::ANSI; + } +#endif +} + +void cmGlobalNinjaGenerator::CheckNinjaCodePage() +{ + std::vector command{ this->NinjaCommand, "-t", "wincodepage" }; + std::string output; + std::string error; + int result; + if (!cmSystemTools::RunSingleCommand(command, &output, &error, &result, + nullptr, cmSystemTools::OUTPUT_NONE)) { + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Running\n '", + cmJoin(command, "' '"), + "'\n" + "failed with:\n ", + error)); + cmSystemTools::SetFatalErrorOccured(); + } else if (result == 0) { + std::istringstream outputStream(output); + std::string line; + bool found = false; + while (cmSystemTools::GetLineFromStream(outputStream, line)) { + if (cmHasLiteralPrefix(line, "Build file encoding: ")) { + cm::string_view lineView(line); + cm::string_view encoding = + lineView.substr(cmStrLen("Build file encoding: ")); + if (encoding == "UTF-8") { + // Ninja expects UTF-8. We use that internally. No conversion needed. + this->NinjaExpectedEncoding = codecvt::None; + } else { + this->NinjaExpectedEncoding = codecvt::ANSI; + } + found = true; + break; + } + } + if (!found) { + this->GetCMakeInstance()->IssueMessage( + MessageType::WARNING, + "Could not determine Ninja's code page, defaulting to UTF-8"); + this->NinjaExpectedEncoding = codecvt::None; + } + } else { + this->NinjaExpectedEncoding = codecvt::ANSI; + } } bool cmGlobalNinjaGenerator::CheckLanguages( diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 0c919ef1d87..9f317087474 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -388,6 +388,7 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator { return "1.10.2"; } + static std::string RequiredNinjaVersionForCodePage() { return "1.11"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -474,6 +475,7 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; void CheckNinjaFeatures(); + void CheckNinjaCodePage(); bool CheckLanguages(std::vector const& languages, cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; @@ -568,6 +570,9 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator bool NinjaSupportsUnconditionalRecompactTool = false; bool NinjaSupportsMultipleOutputs = false; bool NinjaSupportsMetadataOnRegeneration = false; + bool NinjaSupportsCodePage = false; + + codecvt::Encoding NinjaExpectedEncoding = codecvt::None; bool DiagnosedCxxModuleSupport = false; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 8ed411a3ca5..050c907b0c3 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -97,9 +97,12 @@ void cmLocalNinjaGenerator::Generate() // contains any non-ASCII characters and dependency checking will fail. // As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though // the rest of the file is ANSI encoded. - if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8) { + if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8 && + this->GetGlobalGenerator()->GetMakefileEncoding() != codecvt::None) { this->GetRulesFileStream().WriteRaw(showIncludesPrefix); } else { + // Ninja 1.11 and above uses the UTF-8 code page if it's supported, so + // in that case we can write it normally without using raw bytes. this->GetRulesFileStream() << showIncludesPrefix; } #else From b227a9565eb06dcc6e59bfa31e6939edf1ddbaad Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 22 Feb 2021 11:58:52 -0500 Subject: [PATCH 0112/1519] cmake: configure preset add support for --install-prefix mapping --- Help/manual/OPTIONS_BUILD.txt | 3 +- Help/manual/cmake-presets.7.rst | 6 ++ Help/manual/presets/schema.json | 94 ++++++++++++++++++- .../dev/cmake-install-prefix-command.rst | 3 + Source/cmCMakePresetsFile.cxx | 25 ++++- Source/cmCMakePresetsFile.h | 2 + Source/cmake.cxx | 20 +++- .../FuturePresetInstallDirField-result.txt | 1 + .../FuturePresetInstallDirField-stderr.txt | 2 + .../FuturePresetInstallDirField.json.in | 11 +++ .../RunCMake/CMakePresets/GoodInstall.json.in | 30 ++++++ .../CMakePresets/GoodInstallCommandLine.cmake | 3 + .../CMakePresets/GoodInstallDefault.cmake | 3 + .../CMakePresets/GoodInstallInherit.cmake | 3 + .../CMakePresets/GoodInstallOverride.cmake | 3 + .../RunCMake/CMakePresets/RunCMakeTest.cmake | 8 ++ .../install-prefix-no-arg-result.txt | 1 + .../install-prefix-no-arg-stderr.txt | 1 + Tests/RunCMake/IfacePaths/RunCMakeTest.cmake | 2 +- 19 files changed, 212 insertions(+), 9 deletions(-) create mode 100644 Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt create mode 100644 Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in create mode 100644 Tests/RunCMake/CMakePresets/GoodInstall.json.in create mode 100644 Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake create mode 100644 Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake create mode 100644 Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake create mode 100644 Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake create mode 100644 Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt create mode 100644 Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index 251672e7792..c4f9be8a98c 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -77,7 +77,8 @@ :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. ``--install-prefix `` - Specify the installation prefix, :variable:`CMAKE_INSTALL_PREFIX`. + Specify the installation directory, used by the + :variable:`CMAKE_INSTALL_PREFIX` variable. Must be an absolute path. ``-Wno-dev`` Suppress developer warnings. diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 467818dfa67..3d2ada88d4c 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -183,6 +183,12 @@ that may contain the following fields: specified, it must be inherited from the ``inherits`` preset (unless this preset is ``hidden``). +``installDir`` + + An optional string representing the path to the installation directory. + This field supports `macro expansion`_. If a relative path is specified, + it is calculated relative to the source directory. + ``cmakeExecutable`` An optional string representing the path to the CMake executable to use diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index ffbd7feb3e4..a5025bb6a1e 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -11,7 +11,7 @@ }, "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, "vendor": { "$ref": "#/definitions/vendor" }, - "configurePresets": { "$ref": "#/definitions/configurePresets"} + "configurePresets": { "$ref": "#/definitions/configurePresetsV1"} }, "additionalProperties": false }, @@ -19,11 +19,25 @@ "properties": { "version": { "const": 2, + "description": "A requVired integer representing the version of the JSON schema." + }, + "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, + "vendor": { "$ref": "#/definitions/vendor" }, + "configurePresets": { "$ref": "#/definitions/configurePresetsV1"}, + "buildPresets": { "$ref": "#/definitions/buildPresets"}, + "testPresets": { "$ref": "#/definitions/testPresets"} + }, + "additionalProperties": false + }, + { + "properties": { + "version": { + "const": 3, "description": "A required integer representing the version of the JSON schema." }, "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, "vendor": { "$ref": "#/definitions/vendor" }, - "configurePresets": { "$ref": "#/definitions/configurePresets"}, + "configurePresets": { "$ref": "#/definitions/configurePresetsV3"}, "buildPresets": { "$ref": "#/definitions/buildPresets"}, "testPresets": { "$ref": "#/definitions/testPresets"} }, @@ -58,7 +72,21 @@ "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": { + "configurePresetsItemsV3": { + "type": "array", + "description": "A configure preset object.", + "items": { + "type": "object", + "description": "A configure preset object.", + "properties": { + "installDir": { + "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)." + } + } + } + }, + "configurePresetsItemsV1": { "type": "array", "description": "An optional array of configure preset objects.", "items": { @@ -302,6 +330,66 @@ }, "additionalProperties": false } + } + } + }, + "configurePresetsV3": { + "type": "array", + "description": "An optional array of configure preset objects.", + "allOf": [ + { "$ref": "#/definitions/configurePresetsItemsV1" }, + { "$ref": "#/definitions/configurePresetsItemsV3" } + ], + "items": { + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "generator": {}, + "architecture": {}, + "toolset": {}, + "binaryDir": {}, + "installDir": {}, + "cmakeExecutable": {}, + "cacheVariables": {}, + "environment": {}, + "warnings": {}, + "errors": {}, + "debug": {} + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "configurePresetsV1": { + "type": "array", + "description": "An optional array of configure preset objects.", + "allOf": [ + { "$ref": "#/definitions/configurePresetsItemsV1" } + ], + "items": { + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "generator": {}, + "architecture": {}, + "toolset": {}, + "binaryDir": {}, + "cmakeExecutable": {}, + "cacheVariables": {}, + "environment": {}, + "warnings": {}, + "errors": {}, + "debug": {} }, "required": [ "name" diff --git a/Help/release/dev/cmake-install-prefix-command.rst b/Help/release/dev/cmake-install-prefix-command.rst index a5b140a37aa..2de5d918549 100644 --- a/Help/release/dev/cmake-install-prefix-command.rst +++ b/Help/release/dev/cmake-install-prefix-command.rst @@ -3,3 +3,6 @@ cmake-install-prefix-command * The :manual:`cmake(1)` command gained the ``--install-prefix `` command line option to specify the location of the install prefix. + +* :manual:`cmake-presets(7)` configure preset gained support for specifying + the install prefix. diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index c8d69b8f73f..e9e8c4cb397 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -57,7 +57,7 @@ using TestPreset = cmCMakePresetsFile::TestPreset; using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy; constexpr int MIN_VERSION = 1; -constexpr int MAX_VERSION = 2; +constexpr int MAX_VERSION = 3; struct CMakeVersion { @@ -327,6 +327,8 @@ auto const ConfigurePresetHelper = .Bind("toolset"_s, ToolsetHelper, false) .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper, false) + .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper, + false) .Bind("cmakeExecutable"_s, nullptr, PresetStringHelper, false) .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables, VariablesHelper, false) @@ -872,6 +874,17 @@ bool ExpandMacros(const cmCMakePresetsFile& file, out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir); cmSystemTools::ConvertToUnixSlashes(out->BinaryDir); + if (!preset.InstallDir.empty()) { + std::string installDir = preset.InstallDir; + CHECK_EXPAND(out, installDir, macroExpanders) + + if (!cmSystemTools::FileIsFullPath(installDir)) { + installDir = cmStrCat(file.SourceDir, '/', installDir); + } + out->InstallDir = cmSystemTools::CollapseFullPath(installDir); + cmSystemTools::ConvertToUnixSlashes(out->InstallDir); + } + for (auto& variable : out->CacheVariables) { if (variable.second) { CHECK_EXPAND(out, variable.second->Value, macroExpanders) @@ -1174,6 +1187,7 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit( preset.ToolsetStrategy = parent.ToolsetStrategy; } InheritString(preset.BinaryDir, parent.BinaryDir); + InheritString(preset.InstallDir, parent.InstallDir); InheritOptionalValue(preset.WarnDev, parent.WarnDev); InheritOptionalValue(preset.ErrorDev, parent.ErrorDev); InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated); @@ -1502,6 +1516,9 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result) case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED: return "File version must be 2 or higher for build and test preset " "support."; + case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED: + return "File version must be 3 or higher for installDir preset " + "support."; } return "Unknown error"; @@ -1571,6 +1588,12 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( .second) { return ReadFileResult::DUPLICATE_PRESETS; } + + // Support for installDir presets added in version 3. + if (v < 3 && !preset.InstallDir.empty()) { + return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED; + } + this->ConfigurePresetOrder.push_back(preset.Name); } diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index e92c86b509b..517215d2332 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -32,6 +32,7 @@ class cmCMakePresetsFile USER_PRESET_INHERITANCE, INVALID_MACRO_EXPANSION, BUILD_TEST_PRESETS_UNSUPPORTED, + INSTALL_PREFIX_UNSUPPORTED, }; enum class ArchToolsetStrategy @@ -102,6 +103,7 @@ class cmCMakePresetsFile std::string Toolset; cm::optional ToolsetStrategy; std::string BinaryDir; + std::string InstallDir; std::map> CacheVariables; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f96badda31b..b12eeee7f31 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -28,6 +28,7 @@ #include "cm_sys_stat.h" +#include "cmCMakePath.h" #include "cmCMakePresetsFile.h" #include "cmCommandLineArgument.h" #include "cmCommands.h" @@ -496,11 +497,16 @@ bool cmake::SetCacheArgs(const std::vector& args) auto PrefixLambda = [&](std::string const& path, cmake* state) -> bool { const std::string var = "CMAKE_INSTALL_PREFIX"; cmStateEnums::CacheEntryType type = cmStateEnums::PATH; + cmCMakePath absolutePath(path); + if (absolutePath.IsAbsolute()) { #ifndef CMAKE_BOOTSTRAP - state->UnprocessedPresetVariables.erase(var); + state->UnprocessedPresetVariables.erase(var); #endif - state->ProcessCacheArg(var, path, type); - return true; + state->ProcessCacheArg(var, path, type); + return true; + } + cmSystemTools::Error("Absolute paths are required for --install-prefix"); + return false; }; std::vector arguments = { @@ -1224,6 +1230,14 @@ void cmake::SetArgs(const std::vector& args) this->UnprocessedPresetVariables = expandedPreset->CacheVariables; this->UnprocessedPresetEnvironment = expandedPreset->Environment; + if (!expandedPreset->InstallDir.empty() && + this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX") == + nullptr) { + this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = { + "PATH", expandedPreset->InstallDir + }; + } + if (!expandedPreset->ArchitectureStrategy || expandedPreset->ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set) { diff --git a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt new file mode 100644 index 00000000000..36123bdacaa --- /dev/null +++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField: File version must be 3 or higher for installDir preset support.$ diff --git a/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in new file mode 100644 index 00000000000..2e5f7d51972 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/FuturePresetInstallDirField.json.in @@ -0,0 +1,11 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "FuturePresetInstallDirField", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "installDir": "${sourceDir}/install" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/GoodInstall.json.in b/Tests/RunCMake/CMakePresets/GoodInstall.json.in new file mode 100644 index 00000000000..6287c65809d --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodInstall.json.in @@ -0,0 +1,30 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "GoodInstallDefault", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build/${presetName}", + "installDir": "${sourceDir}/build/install_dir1" + }, + { + "name": "GoodInstallInherit", + "inherits": "GoodInstallDefault", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": { + "type": "PATH", + "value": "${sourceDir}/build/bad_path" + } + } + }, + { + "name": "GoodInstallOverride", + "inherits": "GoodInstallInherit", + "installDir": "${sourceDir}/build/install_dir2" + }, + { + "name": "GoodInstallCommandLine", + "inherits": "GoodInstallOverride" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake b/Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake new file mode 100644 index 00000000000..a4f61786e0c --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodInstallCommandLine.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${RunCMake_SOURCE_DIR}/path/passed/on/command_line") diff --git a/Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake b/Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake new file mode 100644 index 00000000000..656fda0b95b --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodInstallDefault.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${CMAKE_SOURCE_DIR}/build/install_dir1") diff --git a/Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake b/Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake new file mode 100644 index 00000000000..656fda0b95b --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodInstallInherit.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${CMAKE_SOURCE_DIR}/build/install_dir1") diff --git a/Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake b/Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake new file mode 100644 index 00000000000..3d12b07eda7 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodInstallOverride.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_INSTALL_PREFIX" "PATH" "${CMAKE_SOURCE_DIR}/build/install_dir2") diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index dfc56eeb741..ee211306106 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -94,6 +94,7 @@ run_cmake_presets(InvalidVariableValue) run_cmake_presets(ExtraRootField) run_cmake_presets(ExtraPresetField) run_cmake_presets(ExtraVariableField) +run_cmake_presets(FuturePresetInstallDirField) run_cmake_presets(InvalidPresetVendor) set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) run_cmake_presets(DuplicatePresets) @@ -181,6 +182,13 @@ run_cmake_presets(GoodInheritanceMulti) run_cmake_presets(GoodInheritanceMultiSecond) run_cmake_presets(GoodInheritanceMacro) +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/GoodInstall.json.in") +run_cmake_presets(GoodInstallDefault) +run_cmake_presets(GoodInstallInherit) +run_cmake_presets(GoodInstallOverride) +run_cmake_presets(GoodInstallCommandLine "--install-prefix=${RunCMake_SOURCE_DIR}/path/passed/on/command_line") + +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/CMakePresets.json.in") # Test bad preset arguments run_cmake_presets(VendorMacro) run_cmake_presets(InvalidGenerator) diff --git a/Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt b/Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-prefix-no-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt new file mode 100644 index 00000000000..a464c700080 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-prefix-no-arg-stderr.txt @@ -0,0 +1 @@ +^CMake Error: No install directory specified for --install-prefix diff --git a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake index 6530aeeb768..c84e95e00a8 100644 --- a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake +++ b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake @@ -79,7 +79,7 @@ foreach(policyStatus NEW OLD "") set(policySuffix -CMP0052-${policyStatus}) endif() set(RunCMake_TEST_OPTIONS - "--install-prefix=${RunCMake_BINARY_DIR}/prefix" ${policyOption} + "--install-prefix ${RunCMake_BINARY_DIR}/prefix" ${policyOption} "-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake" ) # Set the RunCMake_TEST_SOURCE_DIR here to the copy too. This is needed to run From 400536c3179ddbfedd28dc4739d1b1cd785d02b4 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 9 Mar 2021 14:35:49 -0500 Subject: [PATCH 0113/1519] cmCommandLineArgument: trim leading empty spaces --- Source/cmCommandLineArgument.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index cbedf0a9c0c..6b75da04e83 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -110,6 +110,10 @@ struct cmCommandLineArgument } } if (parseState == ParseMode::Valid) { + if (possible_value[0] == ' ') { + possible_value.remove_prefix(1); + } + parseState = this->StoreCall(std::string(possible_value), std::forward(state)...) ? ParseMode::Valid From bef1cc77effd833c75f6fb526055cba3df115059 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 10 Mar 2021 00:01:13 -0500 Subject: [PATCH 0114/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ee17d4005ef..c93283a4e22 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210309) +set(CMake_VERSION_PATCH 20210310) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 00ecddd9ebcbfc0cc4c2bd4e49ae56db59b465ea Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 10 Mar 2021 10:04:05 -0500 Subject: [PATCH 0115/1519] Tests: Enable Framework test case with spaces everywhere possible --- Tests/CMakeLists.txt | 1 + Tests/Framework/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 3a05317c19a..0430afb77fc 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -804,6 +804,7 @@ if(BUILD_TESTING) ${build_generator_args} --build-project Framework --build-options + -DMAKE_SUPPORTS_SPACES=${MAKE_SUPPORTS_SPACES} "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/Framework/Install" --test-command bar) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Framework") diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt index aabf6b419f9..6e82f868b31 100644 --- a/Tests/Framework/CMakeLists.txt +++ b/Tests/Framework/CMakeLists.txt @@ -83,7 +83,7 @@ if(NOT XCODE OR NOT XCODE_VERSION VERSION_LESS 5) target_link_libraries(barStatic fooStatic) endif() -if(XCODE) +if(MAKE_SUPPORTS_SPACES AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake") add_library(space SHARED space.c) set_target_properties(space PROPERTIES FRAMEWORK TRUE From 088444211e942a3587f4af5ef76c3654f2562364 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 4 Mar 2021 11:50:10 -0500 Subject: [PATCH 0116/1519] file: add `COPY_FILE` subcommand The `file(COPY)` subcommand is overloaded and busy for such a simple operation. Instead, make a simpler subcommand with error handling support. --- Help/command/file.rst | 23 +++++ Help/release/dev/file-COPY_FILE.rst | 4 + Source/cmFileCommand.cxx | 92 +++++++++++++++++++ .../file/COPY_FILE-arg-missing-result.txt | 1 + .../file/COPY_FILE-arg-missing-stderr.txt | 3 + .../RunCMake/file/COPY_FILE-arg-missing.cmake | 1 + .../file/COPY_FILE-arg-unknown-result.txt | 1 + .../file/COPY_FILE-arg-unknown-stderr.txt | 5 + .../RunCMake/file/COPY_FILE-arg-unknown.cmake | 1 + .../COPY_FILE-dir-to-file-capture-stdout.txt | 1 + .../file/COPY_FILE-dir-to-file-capture.cmake | 8 ++ .../COPY_FILE-dir-to-file-fail-result.txt | 1 + .../COPY_FILE-dir-to-file-fail-stderr.txt | 6 ++ .../file/COPY_FILE-dir-to-file-fail.cmake | 4 + ...PY_FILE-dirlink-to-file-capture-stdout.txt | 1 + .../COPY_FILE-dirlink-to-file-capture.cmake | 8 ++ .../COPY_FILE-dirlink-to-file-fail-result.txt | 1 + .../COPY_FILE-dirlink-to-file-fail-stderr.txt | 6 ++ .../file/COPY_FILE-dirlink-to-file-fail.cmake | 4 + ..._FILE-file-ONLY_IF_DIFFERENT-capture.cmake | 9 ++ ...ILE-file-ONLY_IF_DIFFERENT-fail-result.txt | 1 + ...ILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt | 6 ++ ...OPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake | 5 + ...-file-ONLY_IF_DIFFERENT-no-overwrite.cmake | 12 +++ .../file/COPY_FILE-file-replace.cmake | 9 ++ .../COPY_FILE-file-to-dir-capture-stdout.txt | 1 + .../file/COPY_FILE-file-to-dir-capture.cmake | 9 ++ .../COPY_FILE-file-to-dir-fail-result.txt | 1 + .../COPY_FILE-file-to-dir-fail-stderr.txt | 6 ++ .../file/COPY_FILE-file-to-dir-fail.cmake | 5 + .../file/COPY_FILE-file-to-file.cmake | 10 ++ .../file/COPY_FILE-link-to-file.cmake | 10 ++ Tests/RunCMake/file/RunCMakeTest.cmake | 15 +++ 33 files changed, 270 insertions(+) create mode 100644 Help/release/dev/file-COPY_FILE.rst create mode 100644 Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-arg-missing.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-replace.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt create mode 100644 Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-file-to-file.cmake create mode 100644 Tests/RunCMake/file/COPY_FILE-link-to-file.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index 9cde90c64f1..445a408332d 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -39,6 +39,7 @@ Synopsis `Filesystem`_ file({`GLOB`_ | `GLOB_RECURSE`_} [...] [...]) file(`RENAME`_ [...]) + file(`COPY_FILE`_ [...]) file({`REMOVE`_ | `REMOVE_RECURSE`_ } [...]) file(`MAKE_DIRECTORY`_ [...]) file({`COPY`_ | `INSTALL`_} ... DESTINATION [...]) @@ -683,6 +684,28 @@ The options are: If ``RESULT `` is used, the result variable will be set to ``NO_REPLACE``. Otherwise, an error is emitted. +.. _COPY_FILE: + +.. code-block:: cmake + + file(COPY_FILE + [RESULT ] + [ONLY_IF_DIFFERENT]) + +Copy a file from ```` to ````. Directories are not +supported. Symlinks are ignored and ````'s content is read and +written to ```` as a new file. + +The options are: + +``RESULT `` + Set ```` variable to ``0`` on success or an error message otherwise. + If ``RESULT`` is not specified and the operation fails, an error is emitted. + +``ONLY_IF_DIFFERENT`` + If the ```` path already exists, do not replace it if it is the + same as ````. Otherwise, an error is emitted. + .. _REMOVE: .. _REMOVE_RECURSE: diff --git a/Help/release/dev/file-COPY_FILE.rst b/Help/release/dev/file-COPY_FILE.rst new file mode 100644 index 00000000000..2f0cdf009c4 --- /dev/null +++ b/Help/release/dev/file-COPY_FILE.rst @@ -0,0 +1,4 @@ +file-COPY_ONLY +-------------- + +* The :command:`file(COPY_FILE)` command was added to copy a file to another. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 065b8459da2..1c73d0d381d 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1379,6 +1379,97 @@ bool HandleRename(std::vector const& args, return false; } +bool HandleCopyFile(std::vector const& args, + cmExecutionStatus& status) +{ + if (args.size() < 3) { + status.SetError("COPY_FILE must be called with at least two additional " + "arguments"); + return false; + } + + // Compute full path for old and new names. + std::string oldname = args[1]; + if (!cmsys::SystemTools::FileIsFullPath(oldname)) { + oldname = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]); + } + std::string newname = args[2]; + if (!cmsys::SystemTools::FileIsFullPath(newname)) { + newname = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]); + } + + struct Arguments + { + bool OnlyIfDifferent = false; + std::string Result; + }; + + static auto const parser = + cmArgumentParser{} + .Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent) + .Bind("RESULT"_s, &Arguments::Result); + + std::vector unconsumedArgs; + Arguments const arguments = + parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs); + if (!unconsumedArgs.empty()) { + status.SetError("COPY_FILE unknown argument:\n " + + unconsumedArgs.front()); + return false; + } + + bool result = true; + if (cmsys::SystemTools::FileIsDirectory(oldname)) { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, + "cannot copy a directory"); + } else { + status.SetError( + cmStrCat("COPY_FILE cannot copy a directory\n ", oldname)); + result = false; + } + return result; + } + if (cmsys::SystemTools::FileIsDirectory(newname)) { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, + "cannot copy to a directory"); + } else { + status.SetError( + cmStrCat("COPY_FILE cannot copy to a directory\n ", newname)); + result = false; + } + return result; + } + + cmSystemTools::CopyWhen when; + if (arguments.OnlyIfDifferent) { + when = cmSystemTools::CopyWhen::OnlyIfDifferent; + } else { + when = cmSystemTools::CopyWhen::Always; + } + + std::string err; + if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) == + cmSystemTools::CopyResult::Success) { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, "0"); + } + } else { + if (!arguments.Result.empty()) { + status.GetMakefile().AddDefinition(arguments.Result, err); + } else { + status.SetError(cmStrCat("COPY_FILE failed to copy\n ", oldname, + "\nto\n ", newname, "\nbecause: ", err, "\n")); + result = false; + } + } + + return result; +} + bool HandleRemoveImpl(std::vector const& args, bool recurse, cmExecutionStatus& status) { @@ -3609,6 +3700,7 @@ bool cmFileCommand(std::vector const& args, { "GLOB_RECURSE"_s, HandleGlobRecurseCommand }, { "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand }, { "RENAME"_s, HandleRename }, + { "COPY_FILE"_s, HandleCopyFile }, { "REMOVE"_s, HandleRemove }, { "REMOVE_RECURSE"_s, HandleRemoveRecurse }, { "COPY"_s, HandleCopyCommand }, diff --git a/Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt b/Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-arg-missing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt b/Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt new file mode 100644 index 00000000000..2ba38b66a30 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-arg-missing-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake:1 \(file\): + file COPY_FILE must be called with at least two additional arguments diff --git a/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake b/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake new file mode 100644 index 00000000000..0e56c3894e2 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-arg-missing.cmake @@ -0,0 +1 @@ +file(COPY_FILE "old") diff --git a/Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt b/Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-arg-unknown-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt b/Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt new file mode 100644 index 00000000000..e5ccd331c20 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-arg-unknown-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake:1 \(file\): + file COPY_FILE unknown argument: + + unknown$ diff --git a/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake b/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake new file mode 100644 index 00000000000..835f39e1149 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-arg-unknown.cmake @@ -0,0 +1 @@ +file(COPY_FILE "old" "new" unknown) diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt new file mode 100644 index 00000000000..45b3d27ea26 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture-stdout.txt @@ -0,0 +1 @@ +^-- file\(COPY_FILE\) failed with result: cannot copy a directory diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake new file mode 100644 index 00000000000..acec05ab373 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-capture.cmake @@ -0,0 +1,8 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(MAKE_DIRECTORY "${oldname}") +file(COPY_FILE "${oldname}" "${newname}" RESULT result) +message(STATUS "file(COPY_FILE) failed with result: ${result}") +if(EXISTS "${newname}") + message(FATAL_ERROR "The new name exists:\n ${newname}") +endif() diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt new file mode 100644 index 00000000000..2fe8bec569b --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake:[0-9] \(file\): + file COPY_FILE cannot copy a directory + + [^ +]*/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail-build/input diff --git a/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake new file mode 100644 index 00000000000..a86ba8d393e --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dir-to-file-fail.cmake @@ -0,0 +1,4 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(MAKE_DIRECTORY "${oldname}") +file(COPY_FILE "${oldname}" "${newname}") diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt new file mode 100644 index 00000000000..45b3d27ea26 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture-stdout.txt @@ -0,0 +1 @@ +^-- file\(COPY_FILE\) failed with result: cannot copy a directory diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake new file mode 100644 index 00000000000..acec05ab373 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-capture.cmake @@ -0,0 +1,8 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(MAKE_DIRECTORY "${oldname}") +file(COPY_FILE "${oldname}" "${newname}" RESULT result) +message(STATUS "file(COPY_FILE) failed with result: ${result}") +if(EXISTS "${newname}") + message(FATAL_ERROR "The new name exists:\n ${newname}") +endif() diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt new file mode 100644 index 00000000000..c58dc2c12ef --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake:[0-9] \(file\): + file COPY_FILE cannot copy a directory + + [^ +]*/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail-build/input diff --git a/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake new file mode 100644 index 00000000000..a86ba8d393e --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-dirlink-to-file-fail.cmake @@ -0,0 +1,4 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(MAKE_DIRECTORY "${oldname}") +file(COPY_FILE "${oldname}" "${newname}") diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake new file mode 100644 index 00000000000..028220e9671 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-capture.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(COPY_FILE "${oldname}" "${newname}" RESULT result ONLY_IF_DIFFERENT) +message(STATUS "file(COPY_FILE) failed with result: ${result}") +if(NOT EXISTS "${oldname}") + message(FATAL_ERROR "The old name still does not exist:\n ${oldname}") +endif() diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt new file mode 100644 index 00000000000..fd5ceeed982 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake:[0-9] \(file\): + file COPY_FILE cannot copy to a directory + + [^ +]*/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail-build/output diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake new file mode 100644 index 00000000000..a56b4e75e3d --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-fail.cmake @@ -0,0 +1,5 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(COPY_FILE "${oldname}" "${newname}" ONLY_IF_DIFFERENT) diff --git a/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake new file mode 100644 index 00000000000..059a308acf0 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite.cmake @@ -0,0 +1,12 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +execute_process(COMMAND "${CMAKE_COMMAND} -E sleep 1") +file(WRITE "${newname}" "") +file(TIMESTAMP "${newname}" before_copy UTC) +file(COPY_FILE "${oldname}" "${newname}" RESULT result ONLY_IF_DIFFERENT) +file(TIMESTAMP "${newname}" after_copy UTC) +if (NOT before_copy STREQUAL after_copy) + message(FATAL_ERROR + "${newname} was modified even though ONLY_IF_DIFFERENT was specified") +endif () diff --git a/Tests/RunCMake/file/COPY_FILE-file-replace.cmake b/Tests/RunCMake/file/COPY_FILE-file-replace.cmake new file mode 100644 index 00000000000..40e42905a69 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-replace.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "a") +file(WRITE "${newname}" "b") +file(COPY_FILE "${oldname}" "${newname}") +file(READ "${newname}" new) +if(NOT "${new}" STREQUAL "a") + message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.") +endif() diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt new file mode 100644 index 00000000000..24f969f057e --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture-stdout.txt @@ -0,0 +1 @@ +^-- file\(COPY_FILE\) failed with result: cannot copy to a directory diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake new file mode 100644 index 00000000000..98621c6e18e --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-capture.cmake @@ -0,0 +1,9 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(COPY_FILE "${oldname}" "${newname}" RESULT result) +message(STATUS "file(COPY_FILE) failed with result: ${result}") +if(NOT EXISTS "${oldname}") + message(FATAL_ERROR "The old name does not exist:\n ${oldname}") +endif() diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt new file mode 100644 index 00000000000..ba2a0276cc2 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake:[0-9] \(file\): + file COPY_FILE cannot copy to a directory + + [^ +]*/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail-build/output diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake new file mode 100644 index 00000000000..c2628dd3e88 --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-to-dir-fail.cmake @@ -0,0 +1,5 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(MAKE_DIRECTORY "${newname}") +file(COPY_FILE "${oldname}" "${newname}") diff --git a/Tests/RunCMake/file/COPY_FILE-file-to-file.cmake b/Tests/RunCMake/file/COPY_FILE-file-to-file.cmake new file mode 100644 index 00000000000..26b702a8a5e --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-file-to-file.cmake @@ -0,0 +1,10 @@ +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${oldname}" "") +file(COPY_FILE "${oldname}" "${newname}") +if(NOT EXISTS "${oldname}") + message(FATAL_ERROR "The old name does not exist:\n ${oldname}") +endif() +if(NOT EXISTS "${newname}") + message(FATAL_ERROR "The new name does not exist:\n ${newname}") +endif() diff --git a/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake b/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake new file mode 100644 index 00000000000..93a02043edd --- /dev/null +++ b/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake @@ -0,0 +1,10 @@ +set(lnkname "${CMAKE_CURRENT_BINARY_DIR}/link") +set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input") +set(newname "${CMAKE_CURRENT_BINARY_DIR}/output") +file(WRITE "${lnkname}" "a") +file(CREATE_LINK "${lnkname}" "${oldname}") +file(COPY_FILE "${oldname}" "${newname}") +file(READ "${newname}" new) +if(NOT "${new}" STREQUAL "a") + message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index f74832c55b7..b4ea9bac309 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -50,6 +50,21 @@ run_cmake(SIZE-error-does-not-exist) run_cmake(REMOVE-empty) +run_cmake_script(COPY_FILE-file-replace) +run_cmake_script(COPY_FILE-dir-to-file-capture) +run_cmake_script(COPY_FILE-dir-to-file-fail) +run_cmake_script(COPY_FILE-dirlink-to-file-capture) +run_cmake_script(COPY_FILE-dirlink-to-file-fail) +run_cmake_script(COPY_FILE-file-to-file) +run_cmake_script(COPY_FILE-file-to-dir-capture) +run_cmake_script(COPY_FILE-file-to-dir-fail) +run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-capture) +run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-fail) +run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite) +run_cmake_script(COPY_FILE-link-to-file) +run_cmake_script(COPY_FILE-arg-missing) +run_cmake_script(COPY_FILE-arg-unknown) + run_cmake_script(RENAME-file-replace) run_cmake_script(RENAME-file-to-file) run_cmake_script(RENAME-file-to-dir-capture) From f42b048b9ca35d8637de6caa2bc6dad8904793dc Mon Sep 17 00:00:00 2001 From: Olivier Iffrig Date: Fri, 5 Mar 2021 18:41:23 +0000 Subject: [PATCH 0117/1519] Tests: Check symlinks to directories in RunCMake.CPackSymlinks Regression test for issue #21886 --- .../RunCMake/CPackSymlinks/RunCMakeTest.cmake | 1 + .../CPackSymlinks/SrcSymlinksCheck.cmake | 21 ++++++++++++++++++ .../CPackSymlinks/SrcSymlinksTar-stdout.txt | 7 +++--- Tests/RunCMake/CPackSymlinks/testcpacksym.tar | Bin 10240 -> 20480 bytes 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake diff --git a/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake b/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake index 439d95e6179..5a8b7a08cb1 100644 --- a/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPackSymlinks/RunCMakeTest.cmake @@ -15,6 +15,7 @@ function(run_cpack_symlink_test) run_cmake_command(SrcSymlinksCPack ${CMAKE_CPACK_COMMAND} --config CPackSourceConfig.cmake ) + run_cmake_script(SrcSymlinksCheck) endfunction() run_cpack_symlink_test() diff --git a/Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake b/Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake new file mode 100644 index 00000000000..0041c9249f9 --- /dev/null +++ b/Tests/RunCMake/CPackSymlinks/SrcSymlinksCheck.cmake @@ -0,0 +1,21 @@ +set(dir ${CMAKE_CURRENT_SOURCE_DIR}) + +set(tarball ${dir}/SrcSymlinks-0.1-Source.tar.gz) +set(extrdir ${dir}/SrcSymlinks-0.1-Source) + +message(STATUS "Extracting ${tarball} in ${dir}...") +execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ${tarball} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE output + WORKING_DIRECTORY ${dir}) +message(STATUS "result='${result}'") +message(STATUS "output='${output}'") + +if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "Cannot unpack source tarball") +endif() + +if(NOT EXISTS ${extrdir}/dirlink/src.h) + message(FATAL_ERROR "${extrdir}/dirlink/src.h not found") +endif() diff --git a/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt b/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt index 24ad1247202..8b1ae5746a6 100644 --- a/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt +++ b/Tests/RunCMake/CPackSymlinks/SrcSymlinksTar-stdout.txt @@ -1,7 +1,6 @@ -^x CMakeLists.txt -x cygwin/ -x cygwin/build.sh -x cygwin/setup.patch +^x build.sh +x CMakeLists.txt +x dirlink x include/ x include/src.h x link.h diff --git a/Tests/RunCMake/CPackSymlinks/testcpacksym.tar b/Tests/RunCMake/CPackSymlinks/testcpacksym.tar index a44c656e899de1b7730f1baab9e3d64e6b185e58..c24af48a24ec5bf44dd2b98032c9fe9d18b44b3d 100644 GIT binary patch literal 20480 zcmeHOO>f#j5cQc~;ii}5V)lFC&;vqgJ%YsCX-$aQ+no>kKDzy-K$)|1=3>d+Ljp z-|^k_e(|sM$t)7CY*AMK8*TXfseBcU%gGIL`i)ws*l7ip|F8e(-G--8GD(8T!^Fk6 z8(uu;|0$y$6@)Pm2T2(Ce=eX2{l5$FH;e&JezfG|wFtPXP*yeme`#x=(k@N8vbP3l zSCuk>GO_{iH`eW*?e+p^{9o_?8SDj?`7dC@fd1b`(tS&R1Zv+MMdN5R9d+aI?=*_T z!ST;VyYua=<@11@l1`<&JwAN}~)|!ou-#TkGPD)8Q zIj*1A>fgJav&(k9(QP(bjdtzgtnD9NG=CkPl%jEeI30v=SFeA2f|}vpuG@}i`~N`{ z8xwCkz!vvy>;I{yOmSu6eg-vZf}-?Hrgi6B)GR4QC3nfL!ffRh)35~lP1|FMf# zkjpQ($v#JL&vtwEhW|Q^``5((5H=hCzu-TI2hj6b68G)V9Jd^J{BP_3+&4Rfd6WJx z^1l=^Lp0TY#xeeLXo9sv<$}Dqk~1=k|DNW5XI+vJfkEC{INx2zobBZzC!Xs6bNOGR z|7rc_k^f2&&zD6`DjWO2^*^(Jz6uDgH*i$~+)4k_`X8qh?2q-o>>(}geWm_ON_d+8 zTdDsX>wm@BW8WiZ{CCOs{2EgI-?abF^grdlgbFn5|AU|m^D-}IT9lugci{SO@BdBm z$1U7D>Ay7fAF37Pe^LLfr`37GO8pmt@HGEp>%V{koyH`Ob344&fbQ9DuVg3vPx;S< zkf8r@*c-Z)B71VE|GD#j?m^#0{~0&u|3LpS|8GC51+=Wze?>T5ljPTgDb)W0Eb%%+ zx@Wt+jv4>g*Z<+X&tv{)#(y~f3;K`e|7w7HAZngi{1Sz% z1pklqpQ0_}dB*-l)_%+iw%30+T*TpbVsQRTg8ec7SG@gK>wlHlhrH+YfAiZN)c@iQ zv!`z`{D)VeS+W>1tpET3 literal 10240 zcmeHMU2mH(6y-U;f@yn5UcfdGKc|#!s0oQ6>9i+AfHo|FWqfF>rv3L_C#_1eEMY3H z)M28?G1pwoIX?GZ9CH$^<8e}yg;M?~B`yboW2oyAG?*Hw-ZB%?ks)DXAZlQwVX#BT zFeDjqnazRIswjh8mZf!)-7XJo_3k-)ee5gx9j3s)pC(z7R;i!I->M{!qyDw!diK`WbN&@1AyZ_Y;Mm2ZCj@X2=k*=TNl^qs}z!g6K& z*8%VCu_eFzX--C0mTxXx*K+2*H(j`<-Yep(?Wx`a-L~5&{+Pxo2pXEB`iJv-{UZ$0 zC!l|Hk#y_Za^nO`sv@U(>0m|JomvLuGYh+;dDj{wd`32K66Qh`>M4PbHZsiVE{$Uv6`gI$r;=w>f^` z?pMt}@o%vDpAZcCCwUxfcu%h5{J#XmjQ^AQAIRR<{}>SvKE!{FK>uR@=Q&Zg*|kN) zJ~uZ}AzlEQA@+ZbV)>Q#6Yb)Eqx~Ov|EFyK7Yzv#^&f9un1Al|72M-&{IAvjM1%hc qFg95IFXI18tN?Kjfq+0jARrJB2nYlO0s;YnfIvVXAQ0#R0>1$bB`aM3 From 8dacf533a90a89c6812e9081c3632c9f60158bc0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 11 Mar 2021 00:01:17 -0500 Subject: [PATCH 0118/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c93283a4e22..b0ed132a00b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210310) +set(CMake_VERSION_PATCH 20210311) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 01cc8bf93084d91d0a1e2258a3b7307ef5ec5852 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 2 Mar 2021 15:05:32 -0500 Subject: [PATCH 0119/1519] ExternalData: use `file(COPY_FILE)` instead of forking CMake --- Modules/ExternalData.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index b439636f5c4..032e423c098 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -944,7 +944,7 @@ function(_ExternalData_link_or_copy src dst) execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${tgt}" "${tmp}" RESULT_VARIABLE result) else() # Create a copy. - execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${src}" "${tmp}" RESULT_VARIABLE result) + file(COPY_FILE "${src}" "${tmp}" RESULT result) endif() if(result) file(REMOVE "${tmp}") From b6c022eaa27abcc265a5961b22e5e0c44df88752 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 2 Mar 2021 14:51:22 -0500 Subject: [PATCH 0120/1519] ExternalData: use `file(CREATE_LINK)` This avoids spawning a new CMake command which isn't necessary. --- Modules/ExternalData.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 032e423c098..1850e746252 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -941,7 +941,8 @@ function(_ExternalData_link_or_copy src dst) file(RELATIVE_PATH tgt "${dst_dir}" "${src}") endif() endif() - execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${tgt}" "${tmp}" RESULT_VARIABLE result) + # 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) From bb9a701a2b90f002c87c01b4a9f8019f2c7f8385 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 11 Mar 2021 08:55:05 -0500 Subject: [PATCH 0121/1519] CMakePrintHelpers: Work around CACHE argument of set() Fixes: #21919 --- Modules/CMakePrintHelpers.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index d652ffa5c9e..8c25a737f7c 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -101,7 +101,10 @@ function(cmake_print_properties) if(CPP_CACHE_ENTRIES) set(items ${CPP_CACHE_ENTRIES}) set(mode ${mode} CACHE_ENTRIES) - set(keyword CACHE) + # This is a workaround for the fact that passing `CACHE` as an argument to + # set() causes a cache variable to be set. + set(keyword "") + string(APPEND keyword CACHE) endif() if(NOT mode) From 887e0c6c7b2ea0d3489b72afb5c60b93e402a23f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 12 Mar 2021 00:01:17 -0500 Subject: [PATCH 0122/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b0ed132a00b..e5a0bec6780 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210311) +set(CMake_VERSION_PATCH 20210312) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 74eda8ab1f21ad7ba37dd1fa4f21e158f01d7f1c Mon Sep 17 00:00:00 2001 From: Yauheni Khnykin Date: Mon, 8 Mar 2021 17:57:35 +0100 Subject: [PATCH 0123/1519] Tests: Add XCTest cases to cover output directory selection Fixes: #21800 --- .../RunCMake/XcodeProject/RunCMakeTest.cmake | 26 +++++++++++++++++++ .../XcodeProject/XCTestAddBundle.cmake | 17 ++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 8b032165704..c8b75ebe7fe 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -387,4 +387,30 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 8) XcodeRemoveExcessiveISystemSDK(iphoneos) XcodeRemoveExcessiveISystemSDK(iphonesimulator) endif() + +if (XCODE_VERSION VERSION_GREATER_EQUAL 7.3) + function(xctest_add_bundle_test SystemName SDK BuildSystemVersion ExpectedOutputDir) + set(RunCMake_TEST_BINARY_DIR + ${RunCMake_BINARY_DIR}/DeploymentTarget-${SystemName}-${SDK}-${BuildSystemVersion}-build) + set(RunCMake_TEST_OPTIONS + "-DCMAKE_SYSTEM_NAME=${SystemName}" + "-DCMAKE_OSX_SYSROOT=${SDK}" + "-DTEST_EXPECTED_OUTPUT_DIR=${ExpectedOutputDir}") + unset(RunCMake_GENERATOR_TOOLSET) + if(BuildSystemVersion) + set(RunCMake_GENERATOR_TOOLSET "buildsystem=${BuildSystemVersion}") + endif() + run_cmake(XCTestAddBundle) + endfunction() + + if(XCODE_VERSION VERSION_GREATER_EQUAL 12) + xctest_add_bundle_test(Darwin macosx "1" "$/PlugIns") + xctest_add_bundle_test(Darwin macosx "12" "$/PlugIns") + xctest_add_bundle_test(iOS iphoneos "1" "$/PlugIns") + xctest_add_bundle_test(iOS iphoneos "12" "$") + else() + xctest_add_bundle_test(Darwin macosx "" "$/PlugIns") + xctest_add_bundle_test(iOS iphoneos "" "$/PlugIns") + endif() +endif() # Please add macOS-only tests above before the device-specific tests. diff --git a/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake b/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake new file mode 100644 index 00000000000..444c730bbe6 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake @@ -0,0 +1,17 @@ +enable_language(Swift) +find_package(XCTest REQUIRED) + +add_executable(TestedApp MACOSX_BUNDLE EXCLUDE_FROM_ALL foo.swift) + +xctest_add_bundle(TestingAppBundle TestedApp foo.swift) + +get_target_property(_lib_output_dir TestingAppBundle LIBRARY_OUTPUT_DIRECTORY) + +if (NOT DEFINED TEST_EXPECTED_OUTPUT_DIR) + message(FATAL_ERROR "Testing variable TEST_EXPECTED_OUTPUT_DIR is not set") +endif() + +if (NOT _lib_output_dir STREQUAL TEST_EXPECTED_OUTPUT_DIR) + message(SEND_ERROR "Property LIBRARY_OUTPUT_DIRECTORY is expected to be ${TEST_EXPECTED_OUTPUT_DIR} " + "but was ${_lib_output_dir}") +endif() From 982f7bb5063453d3c0be102c917bb660ec21978b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 13 Mar 2021 00:01:18 -0500 Subject: [PATCH 0124/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e5a0bec6780..46a7dee6c9f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210312) +set(CMake_VERSION_PATCH 20210313) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 12624ebd7ee1380b5e5aa0bc3bcbb03c4d9aec73 Mon Sep 17 00:00:00 2001 From: vvs31415 Date: Sat, 13 Mar 2021 07:00:00 -0500 Subject: [PATCH 0125/1519] Source: Reduce c_str() usage --- .../cmCTestEmptyBinaryDirectoryCommand.cxx | 2 +- Source/CTest/cmCTestRunScriptCommand.cxx | 4 ++-- Source/CTest/cmCTestScriptHandler.cxx | 23 ++++++++----------- Source/CTest/cmCTestScriptHandler.h | 12 ++++++---- Source/CTest/cmCTestTestHandler.cxx | 10 ++++---- Source/cmCTest.cxx | 6 ++--- Source/cmFindLibraryCommand.cxx | 2 +- Source/cmListCommand.cxx | 12 +++++----- Source/cmOrderDirectories.cxx | 2 +- Source/cmStringCommand.cxx | 4 ++-- Source/cmcmd.cxx | 20 ++++++++-------- 11 files changed, 47 insertions(+), 50 deletions(-) diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx index 051c117ca9f..af495bb5636 100644 --- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx +++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx @@ -16,7 +16,7 @@ bool cmCTestEmptyBinaryDirectoryCommand::InitialPass( return false; } - if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0].c_str())) { + if (!cmCTestScriptHandler::EmptyBinaryDirectory(args[0])) { std::ostringstream ostr; ostr << "problem removing the binary directory: " << args[0]; this->SetError(ostr.str()); diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx index f59ca57dedf..7661d4dd642 100644 --- a/Source/CTest/cmCTestRunScriptCommand.cxx +++ b/Source/CTest/cmCTestRunScriptCommand.cxx @@ -37,8 +37,8 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector const& args, ++i; } else { int ret; - cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, - args[i].c_str(), !np, &ret); + cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, args[i], + !np, &ret); this->Makefile->AddDefinition(returnVariable, std::to_string(ret)); } } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 4808c36aa34..ff0b179a6da 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -91,7 +90,7 @@ void cmCTestScriptHandler::Initialize() cmCTestScriptHandler::~cmCTestScriptHandler() = default; // just adds an argument to the vector -void cmCTestScriptHandler::AddConfigurationScript(const char* script, +void cmCTestScriptHandler::AddConfigurationScript(const std::string& script, bool pscope) { this->ConfigurationScripts.emplace_back(script); @@ -676,7 +675,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() // clear the binary directory? if (this->EmptyBinDir) { - if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir.c_str())) { + if (!cmCTestScriptHandler::EmptyBinaryDirectory(this->BinaryDir)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem removing the binary directory" << std::endl); } @@ -724,8 +723,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard() // put the initial cache into the bin dir if (!this->InitialCache.empty()) { - if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir.c_str(), - this->InitialCache.c_str())) { + if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir, + this->InitialCache)) { this->RestoreBackupDirectories(); return 9; } @@ -812,8 +811,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard() return 0; } -bool cmCTestScriptHandler::WriteInitialCache(const char* directory, - const char* text) +bool cmCTestScriptHandler::WriteInitialCache(const std::string& directory, + const std::string& text) { std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt"); cmGeneratedFileStream fout(cacheFile); @@ -821,9 +820,7 @@ bool cmCTestScriptHandler::WriteInitialCache(const char* directory, return false; } - if (text != nullptr) { - fout.write(text, strlen(text)); - } + fout.write(text.data(), text.size()); // Make sure the operating system has finished writing the file // before closing it. This will ensure the file is finished before @@ -852,7 +849,7 @@ void cmCTestScriptHandler::RestoreBackupDirectories() } bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, - const char* sname, bool InProcess, + const std::string& sname, bool InProcess, int* returnValue) { auto sh = cm::make_unique(); @@ -866,10 +863,10 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf, return true; } -bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname) +bool cmCTestScriptHandler::EmptyBinaryDirectory(const std::string& sname) { // try to avoid deleting root - if (!sname || strlen(sname) < 2) { + if (sname.size() < 2) { return false; } diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index 8eb96582bbf..b7764b2a7c5 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -62,7 +62,7 @@ class cmCTestScriptHandler : public cmCTestGenericHandler /** * Add a script to run, and if is should run in the current process */ - void AddConfigurationScript(const char*, bool pscope); + void AddConfigurationScript(const std::string&, bool pscope); /** * Run a dashboard using a specified confiuration script @@ -72,19 +72,21 @@ class cmCTestScriptHandler : public cmCTestGenericHandler /* * Run a script */ - static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script, - bool InProcess, int* returnValue); + static bool RunScript(cmCTest* ctest, cmMakefile* mf, + const std::string& script, bool InProcess, + int* returnValue); int RunCurrentScript(); /* * Empty Binary Directory */ - static bool EmptyBinaryDirectory(const char* dir); + static bool EmptyBinaryDirectory(const std::string& dir); /* * Write an initial CMakeCache.txt from the given contents. */ - static bool WriteInitialCache(const char* directory, const char* text); + static bool WriteInitialCache(const std::string& directory, + const std::string& text); /* * Some elapsed time handling functions diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 1cb5d009028..42c4d5e06f0 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1705,18 +1705,16 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty( bool cmCTestTestHandler::GetListOfTests() { if (!this->IncludeLabelRegExp.empty()) { - this->IncludeLabelRegularExpression.compile( - this->IncludeLabelRegExp.c_str()); + this->IncludeLabelRegularExpression.compile(this->IncludeLabelRegExp); } if (!this->ExcludeLabelRegExp.empty()) { - this->ExcludeLabelRegularExpression.compile( - this->ExcludeLabelRegExp.c_str()); + this->ExcludeLabelRegularExpression.compile(this->ExcludeLabelRegExp); } if (!this->IncludeRegExp.empty()) { - this->IncludeTestsRegularExpression.compile(this->IncludeRegExp.c_str()); + this->IncludeTestsRegularExpression.compile(this->IncludeRegExp); } if (!this->ExcludeRegExp.empty()) { - this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp.c_str()); + this->ExcludeTestsRegularExpression.compile(this->ExcludeRegExp); } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl, this->Quiet); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 620ba197988..77b44417c4c 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2221,7 +2221,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector& args, cmCTestScriptHandler* ch = this->GetScriptHandler(); // -SR is an internal argument, -SP should be ignored when it is passed if (!SRArgumentSpecified) { - ch->AddConfigurationScript(args[i].c_str(), false); + ch->AddConfigurationScript(args[i], false); } } @@ -2231,7 +2231,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector& args, this->Impl->RunConfigurationScript = true; i++; cmCTestScriptHandler* ch = this->GetScriptHandler(); - ch->AddConfigurationScript(args[i].c_str(), true); + ch->AddConfigurationScript(args[i], true); } if (this->CheckArgument(arg, "-S"_s, "--script") && i < args.size() - 1) { @@ -2240,7 +2240,7 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector& args, cmCTestScriptHandler* ch = this->GetScriptHandler(); // -SR is an internal argument, -S should be ignored when it is passed if (!SRArgumentSpecified) { - ch->AddConfigurationScript(args[i].c_str(), true); + ch->AddConfigurationScript(args[i], true); } } } diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 49b1bd74b3c..d85ba8fd9f6 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -374,7 +374,7 @@ void cmFindLibraryHelper::AddName(std::string const& name) regex += "(\\.[0-9]+\\.[0-9]+)?"; } regex += "$"; - entry.Regex.compile(regex.c_str()); + entry.Regex.compile(regex); this->Names.push_back(std::move(entry)); } diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 1bafdf799b4..09cd88e08f5 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -34,7 +34,7 @@ namespace { -bool GetIndexArg(char const* arg, int* idx, cmMakefile& mf) +bool GetIndexArg(const std::string& arg, int* idx, cmMakefile& mf) { long value; if (!cmStrToLong(arg, &value)) { @@ -189,7 +189,7 @@ bool HandleGetCommand(std::vector const& args, size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size() - 1; cc++) { int item; - if (!GetIndexArg(args[cc].c_str(), &item, status.GetMakefile())) { + if (!GetIndexArg(args[cc], &item, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); return false; } @@ -401,7 +401,7 @@ bool HandleInsertCommand(std::vector const& args, // expand the variable int item; - if (!GetIndexArg(args[2].c_str(), &item, status.GetMakefile())) { + if (!GetIndexArg(args[2], &item, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); return false; } @@ -1326,11 +1326,11 @@ bool HandleSublistCommand(std::vector const& args, int start; int length; - if (!GetIndexArg(args[2].c_str(), &start, status.GetMakefile())) { + if (!GetIndexArg(args[2], &start, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); return false; } - if (!GetIndexArg(args[3].c_str(), &length, status.GetMakefile())) { + if (!GetIndexArg(args[3], &length, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[3], " is not a valid index")); return false; } @@ -1389,7 +1389,7 @@ bool HandleRemoveAtCommand(std::vector const& args, size_t nitem = varArgsExpanded.size(); for (cc = 2; cc < args.size(); ++cc) { int item; - if (!GetIndexArg(args[cc].c_str(), &item, status.GetMakefile())) { + if (!GetIndexArg(args[cc], &item, status.GetMakefile())) { status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); return false; } diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 0369af00217..68f40a9631d 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -359,7 +359,7 @@ void cmOrderDirectories::SetLinkExtensionInfo( std::string const& removeExtRegex) { this->LinkExtensions = linkExtensions; - this->RemoveLibraryExtension.compile(removeExtRegex.c_str()); + this->RemoveLibraryExtension.compile(removeExtRegex); } void cmOrderDirectories::CollectOriginalDirectories() diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 23fc3e0f60c..5fa309df379 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -241,7 +241,7 @@ bool RegexMatch(std::vector const& args, status.GetMakefile().ClearMatches(); // Compile the regular expression. cmsys::RegularExpression re; - if (!re.compile(regex.c_str())) { + if (!re.compile(regex)) { std::string e = "sub-command REGEX, mode MATCH failed to compile regex \"" + regex + "\"."; @@ -283,7 +283,7 @@ bool RegexMatchAll(std::vector const& args, status.GetMakefile().ClearMatches(); // Compile the regular expression. cmsys::RegularExpression re; - if (!re.compile(regex.c_str())) { + if (!re.compile(regex)) { std::string e = "sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex + "\"."; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 6713cc35822..9ba4b93de76 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -74,7 +74,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, std::vector::const_iterator argEnd); namespace { -void CMakeCommandUsage(const char* program) +void CMakeCommandUsage(std::string const& program) { std::ostringstream errorStream; @@ -704,7 +704,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, } else if (args[2] == "--ignore-eol") { filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]); } else { - CMakeCommandUsage(args[0].c_str()); + CMakeCommandUsage(args[0]); return 2; } @@ -1085,7 +1085,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, std::string const& directory = args[2]; if (!cmSystemTools::FileExists(directory)) { cmSystemTools::Error("Directory does not exist for chdir command: " + - args[2]); + directory); return 1; } @@ -1152,7 +1152,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, << "\n"; return 1; } - if (!cmSystemTools::CreateSymlink(args[2], args[3])) { + if (!cmSystemTools::CreateSymlink(args[2], destinationFileName)) { return 1; } return 0; @@ -1161,12 +1161,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, // Command to create a hard link. Fails on platforms not // supporting them. if (args[1] == "create_hardlink" && args.size() == 4) { - const char* SouceFileName = args[2].c_str(); - const char* destinationFileName = args[3].c_str(); + std::string const& sourceFileName = args[2]; + std::string const& destinationFileName = args[3]; - if (!cmSystemTools::FileExists(SouceFileName)) { + if (!cmSystemTools::FileExists(sourceFileName)) { std::cerr << "failed to create hard link because source path '" - << SouceFileName << "' does not exist \n"; + << sourceFileName << "' does not exist \n"; return 1; } @@ -1180,7 +1180,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, return 1; } - if (!cmSystemTools::CreateLink(args[2], args[3])) { + if (!cmSystemTools::CreateLink(sourceFileName, destinationFileName)) { return 1; } return 0; @@ -1560,7 +1560,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, } } - CMakeCommandUsage(args[0].c_str()); + CMakeCommandUsage(args[0]); return 1; } From d4053aabce9c10a83dc3522a599ae12846689050 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 14 Mar 2021 00:01:09 -0500 Subject: [PATCH 0126/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 46a7dee6c9f..ed4368d05ed 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210313) +set(CMake_VERSION_PATCH 20210314) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 948b379e26a4d64490ceea894649d907b4fa2fef Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 15 Mar 2021 00:01:19 -0400 Subject: [PATCH 0127/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ed4368d05ed..ff82f8f0551 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210314) +set(CMake_VERSION_PATCH 20210315) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From c13f75982f784cc85f6c0a88c6efe917fe3b72c7 Mon Sep 17 00:00:00 2001 From: Elsie Hupp <9206310+elsiehupp@users.noreply.github.com> Date: Sun, 14 Mar 2021 17:35:20 -0400 Subject: [PATCH 0128/1519] Help: Clarify configure_file #cmakedefine01 syntax and behavior Fixes: #21935 --- Help/command/configure_file.rst | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst index 63ea84d1b35..8f082e859a8 100644 --- a/Help/command/configure_file.rst +++ b/Help/command/configure_file.rst @@ -36,8 +36,30 @@ or depending on whether ``VAR`` is set in CMake to any value not considered a false constant by the :command:`if` command. The "..." content on the line after the variable name, if any, is processed as above. -Input file lines of the form ``#cmakedefine01 VAR`` will be replaced with -either ``#define VAR 1`` or ``#define VAR 0`` similarly. + +Unlike lines of the form ``#cmakedefine VAR ...``, in lines of the form +``#cmakedefine01 VAR``, ``VAR`` itself will expand to ``VAR 0`` or ``VAR 1`` +rather than being assigned the value ``...``. Therefore, input lines of the form + +.. code-block:: c + + #cmakedefine01 VAR + +will be replaced with either + +.. code-block:: c + + #define VAR 0 + +or + +.. code-block:: c + + #define VAR 1 + +Input lines of the form ``#cmakedefine01 VAR ...`` will expand +as ``#cmakedefine01 VAR ... 0`` or ``#cmakedefine01 VAR ... 0``, +which may lead to undefined behavior. .. versionadded:: 3.10 The result lines (with the exception of the ``#undef`` comments) can be From ad19da011d5702da3407a17bf45f3d39ec651639 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 11 Mar 2021 12:02:13 -0500 Subject: [PATCH 0129/1519] Refactor: Add cmSystemTools::GetSystemName() And use it for CMAKE_HOST_SYSTEM_NAME and CMAKE_SYSTEM_NAME. --- .../release/dev/cmake-system-name-version.rst | 10 ++++ Modules/CMakeDetermineSystem.cmake | 39 +++---------- Source/cmStateSnapshot.cxx | 55 +++++++------------ Source/cmSystemTools.cxx | 47 ++++++++++++++++ Source/cmSystemTools.h | 3 + 5 files changed, 88 insertions(+), 66 deletions(-) create mode 100644 Help/release/dev/cmake-system-name-version.rst diff --git a/Help/release/dev/cmake-system-name-version.rst b/Help/release/dev/cmake-system-name-version.rst new file mode 100644 index 00000000000..9cfe4013286 --- /dev/null +++ b/Help/release/dev/cmake-system-name-version.rst @@ -0,0 +1,10 @@ +cmake-system-name-version +------------------------- + +* :variable:`CMAKE_HOST_SYSTEM_NAME`'s undocumented version-stripping behavior + has been moved earlier, before :command:`project` or + :command:`enable_language` is called. +* :variable:`CMAKE_SYSTEM_NAME`'s undocumented version-stripping behavior has + been removed entirely. If it is set by a ``-D`` flag or by a + :manual:`toolchain file `, it is left unaltered, even if + it still contains a version number. diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index bae270dec15..c3f2b740058 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -158,37 +158,14 @@ endif() include(Platform/${CMAKE_SYSTEM_NAME}-Determine OPTIONAL) -macro(ADJUST_CMAKE_SYSTEM_VARIABLES _PREFIX) - if(NOT ${_PREFIX}_NAME) - set(${_PREFIX}_NAME "UnknownOS") - endif() - - # fix for BSD/OS , remove the / - if(${_PREFIX}_NAME MATCHES BSD.OS) - set(${_PREFIX}_NAME BSDOS) - endif() - - # fix for GNU/kFreeBSD, remove the GNU/ - if(${_PREFIX}_NAME MATCHES kFreeBSD) - set(${_PREFIX}_NAME kFreeBSD) - endif() - - # fix for CYGWIN which has windows version in it - if(${_PREFIX}_NAME MATCHES CYGWIN) - set(${_PREFIX}_NAME CYGWIN) - endif() - - # set CMAKE_SYSTEM to the CMAKE_SYSTEM_NAME - set(${_PREFIX} ${${_PREFIX}_NAME}) - # if there is a CMAKE_SYSTEM_VERSION then add a -${CMAKE_SYSTEM_VERSION} - if(${_PREFIX}_VERSION) - set(${_PREFIX} ${${_PREFIX}}-${${_PREFIX}_VERSION}) - endif() - -endmacro() - -ADJUST_CMAKE_SYSTEM_VARIABLES(CMAKE_SYSTEM) -ADJUST_CMAKE_SYSTEM_VARIABLES(CMAKE_HOST_SYSTEM) +set(CMAKE_SYSTEM ${CMAKE_SYSTEM_NAME}) +if(CMAKE_SYSTEM_VERSION) + string(APPEND CMAKE_SYSTEM -${CMAKE_SYSTEM_VERSION}) +endif() +set(CMAKE_HOST_SYSTEM ${CMAKE_HOST_SYSTEM_NAME}) +if(CMAKE_HOST_SYSTEM_VERSION) + string(APPEND CMAKE_HOST_SYSTEM -${CMAKE_HOST_SYSTEM_VERSION}) +endif() # this file is also executed from cpack, then we don't need to generate these files # in this case there is no CMAKE_BINARY_DIR diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 1e20abb2579..fbf47ef68c3 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -16,16 +16,9 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStatePrivate.h" +#include "cmSystemTools.h" #include "cmVersion.h" -#if !defined(_WIN32) -# include -#endif - -#if defined(__CYGWIN__) -# include "cmSystemTools.h" -#endif - cmStateSnapshot::cmStateSnapshot(cmState* state) : State(state) { @@ -292,34 +285,26 @@ void InitializeContentFromParent(T& parentContent, T& thisContent, void cmStateSnapshot::SetDefaultDefinitions() { -/* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set. - With CMake must separate between target and host platform. In most cases - the tests for WIN32, UNIX and APPLE will be for the target system, so an - additional set of variables for the host system is required -> - CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE. - WIN32, UNIX and APPLE are now set in the platform files in - Modules/Platforms/. - To keep cmake scripts (-P) and custom language and compiler modules - working, these variables are still also set here in this place, but they - will be reset in CMakeSystemSpecificInformation.cmake before the platform - files are executed. */ -#if defined(_WIN32) - this->SetDefinition("WIN32", "1"); - this->SetDefinition("CMAKE_HOST_WIN32", "1"); - this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows"); -#else - this->SetDefinition("UNIX", "1"); - this->SetDefinition("CMAKE_HOST_UNIX", "1"); - -# if defined(__ANDROID__) - this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android"); -# else - struct utsname uts_name; - if (uname(&uts_name) >= 0) { - this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); + /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set. + With CMake must separate between target and host platform. In most cases + the tests for WIN32, UNIX and APPLE will be for the target system, so an + additional set of variables for the host system is required -> + CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE. + WIN32, UNIX and APPLE are now set in the platform files in + Modules/Platforms/. + To keep cmake scripts (-P) and custom language and compiler modules + working, these variables are still also set here in this place, but they + will be reset in CMakeSystemSpecificInformation.cmake before the platform + files are executed. */ + cm::string_view hostSystemName = cmSystemTools::GetSystemName(); + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName); + if (hostSystemName == "Windows") { + this->SetDefinition("WIN32", "1"); + this->SetDefinition("CMAKE_HOST_WIN32", "1"); + } else { + this->SetDefinition("UNIX", "1"); + this->SetDefinition("CMAKE_HOST_UNIX", "1"); } -# endif -#endif #if defined(__CYGWIN__) std::string legacy; if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) && diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 87ba1525854..e8e1018c0f6 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -103,6 +103,10 @@ # include /* for malloc/free on QNX */ #endif +#if !defined(_WIN32) && !defined(__ANDROID__) +# include +#endif + namespace { cmSystemTools::InterruptCallback s_InterruptCallback; @@ -3207,3 +3211,46 @@ bool cmSystemTools::CreateLink(const std::string& origName, return true; } + +cm::string_view cmSystemTools::GetSystemName() +{ +#if defined(_WIN32) + return "Windows"; +#elif defined(__ANDROID__) + return "Android"; +#else + static struct utsname uts_name; + static bool initialized = false; + static cm::string_view systemName; + if (initialized) { + return systemName; + } + if (uname(&uts_name) >= 0) { + initialized = true; + systemName = uts_name.sysname; + + if (cmIsOff(systemName)) { + systemName = "UnknownOS"; + } + + // fix for BSD/OS, remove the / + static const cmsys::RegularExpression bsdOsRegex("BSD.OS"); + cmsys::RegularExpressionMatch match; + if (bsdOsRegex.find(uts_name.sysname, match)) { + systemName = "BSDOS"; + } + + // fix for GNU/kFreeBSD, remove the GNU/ + if (systemName.find("kFreeBSD") != cm::string_view::npos) { + systemName = "kFreeBSD"; + } + + // fix for CYGWIN which has windows version in it + if (systemName.find("CYGWIN") != cm::string_view::npos) { + systemName = "CYGWIN"; + } + return systemName; + } + return ""; +#endif +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 2ff4c5dd601..562089973af 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -498,6 +498,9 @@ class cmSystemTools : public cmsys::SystemTools const std::string& newName, std::string* errorMessage = nullptr); + /** Get the system name. */ + static cm::string_view GetSystemName(); + private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; From 69527a1979093a5fb103c1940f0f0b17d97b45e2 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 10 Mar 2021 16:30:19 -0500 Subject: [PATCH 0130/1519] Refactor: Pass CMakePresets.json version to ExpandMacros() functions --- Source/cmCMakePresetsFile.cxx | 100 +++++++++++++++++++++------------- Source/cmCMakePresetsFile.h | 7 +++ 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index e9e8c4cb397..e9caecdb9d9 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -28,9 +28,9 @@ return _result; \ } -#define CHECK_EXPAND(out, field, expanders) \ +#define CHECK_EXPAND(out, field, expanders, version) \ { \ - switch (ExpandMacros(field, expanders)) { \ + switch (ExpandMacros(field, expanders, version)) { \ case ExpandMacroResult::Error: \ return false; \ case ExpandMacroResult::Ignore: \ @@ -849,16 +849,19 @@ enum class ExpandMacroResult }; using MacroExpander = std::function; + const std::string&, const std::string&, std::string&, int version)>; ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, - const std::vector& macroExpanders); + const std::vector& macroExpanders, + int version); ExpandMacroResult ExpandMacros( - std::string& out, const std::vector& macroExpanders); -ExpandMacroResult ExpandMacro( - std::string& out, const std::string& macroNamespace, - const std::string& macroName, - const std::vector& macroExpanders); + std::string& out, const std::vector& macroExpanders, + int version); +ExpandMacroResult ExpandMacro(std::string& out, + const std::string& macroNamespace, + const std::string& macroName, + const std::vector& macroExpanders, + int version); bool ExpandMacros(const cmCMakePresetsFile& file, const ConfigurePreset& preset, @@ -866,7 +869,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const std::vector& macroExpanders) { std::string binaryDir = preset.BinaryDir; - CHECK_EXPAND(out, binaryDir, macroExpanders) + CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset)) if (!cmSystemTools::FileIsFullPath(binaryDir)) { binaryDir = cmStrCat(file.SourceDir, '/', binaryDir); @@ -876,7 +879,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, if (!preset.InstallDir.empty()) { std::string installDir = preset.InstallDir; - CHECK_EXPAND(out, installDir, macroExpanders) + CHECK_EXPAND(out, installDir, macroExpanders, file.GetVersion(preset)) if (!cmSystemTools::FileIsFullPath(installDir)) { installDir = cmStrCat(file.SourceDir, '/', installDir); @@ -887,67 +890,76 @@ bool ExpandMacros(const cmCMakePresetsFile& file, for (auto& variable : out->CacheVariables) { if (variable.second) { - CHECK_EXPAND(out, variable.second->Value, macroExpanders) + CHECK_EXPAND(out, variable.second->Value, macroExpanders, + file.GetVersion(preset)) } } return true; } -bool ExpandMacros(const cmCMakePresetsFile&, const BuildPreset&, +bool ExpandMacros(const cmCMakePresetsFile& file, const BuildPreset& preset, cm::optional& out, const std::vector& macroExpanders) { for (auto& target : out->Targets) { - CHECK_EXPAND(out, target, macroExpanders) + CHECK_EXPAND(out, target, macroExpanders, file.GetVersion(preset)) } for (auto& nativeToolOption : out->NativeToolOptions) { - CHECK_EXPAND(out, nativeToolOption, macroExpanders) + CHECK_EXPAND(out, nativeToolOption, macroExpanders, + file.GetVersion(preset)) } return true; } -bool ExpandMacros(const cmCMakePresetsFile&, const TestPreset&, +bool ExpandMacros(const cmCMakePresetsFile& file, const TestPreset& preset, cm::optional& out, const std::vector& macroExpanders) { for (auto& overwrite : out->OverwriteConfigurationFile) { - CHECK_EXPAND(out, overwrite, macroExpanders); + CHECK_EXPAND(out, overwrite, macroExpanders, file.GetVersion(preset)); } if (out->Output) { - CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders) + CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders, + file.GetVersion(preset)) } if (out->Filter) { if (out->Filter->Include) { - CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders) - CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders) + CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders, + file.GetVersion(preset)) + CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders, + file.GetVersion(preset)) if (out->Filter->Include->Index) { CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile, - macroExpanders); + macroExpanders, file.GetVersion(preset)); } } if (out->Filter->Exclude) { - CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders) - CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders) + CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders, + file.GetVersion(preset)) + CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders, + file.GetVersion(preset)) if (out->Filter->Exclude->Fixtures) { - CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders) + CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders, + file.GetVersion(preset)) CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup, - macroExpanders) + macroExpanders, file.GetVersion(preset)) CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup, - macroExpanders) + macroExpanders, file.GetVersion(preset)) } } } if (out->Execution) { - CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders) + CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders, + file.GetVersion(preset)) } return true; @@ -968,8 +980,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, MacroExpander defaultMacroExpander = [&file, &preset](const std::string& macroNamespace, - const std::string& macroName, - std::string& macroOut) -> ExpandMacroResult { + const std::string& macroName, std::string& macroOut, + int /*version*/) -> ExpandMacroResult { if (macroNamespace.empty()) { if (macroName == "sourceDir") { macroOut += file.SourceDir; @@ -1006,11 +1018,12 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, MacroExpander environmentMacroExpander = [¯oExpanders, &out, &envCycles]( const std::string& macroNamespace, const std::string& macroName, - std::string& result) -> ExpandMacroResult { + std::string& result, int version) -> ExpandMacroResult { if (macroNamespace == "env" && !macroName.empty() && out) { auto v = out->Environment.find(macroName); if (v != out->Environment.end() && v->second) { - auto e = VisitEnv(*v->second, envCycles[macroName], macroExpanders); + auto e = + VisitEnv(*v->second, envCycles[macroName], macroExpanders, version); if (e != ExpandMacroResult::Ok) { return e; } @@ -1038,7 +1051,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, for (auto& v : out->Environment) { if (v.second) { - switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders)) { + switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders, + file.GetVersion(preset))) { case ExpandMacroResult::Error: return false; case ExpandMacroResult::Ignore: @@ -1054,7 +1068,8 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, } ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, - const std::vector& macroExpanders) + const std::vector& macroExpanders, + int version) { if (status == CycleStatus::Verified) { return ExpandMacroResult::Ok; @@ -1064,7 +1079,7 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, } status = CycleStatus::InProgress; - auto e = ExpandMacros(value, macroExpanders); + auto e = ExpandMacros(value, macroExpanders, version); if (e != ExpandMacroResult::Ok) { return e; } @@ -1073,7 +1088,8 @@ ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, } ExpandMacroResult ExpandMacros( - std::string& out, const std::vector& macroExpanders) + std::string& out, const std::vector& macroExpanders, + int version) { std::string result; std::string macroNamespace; @@ -1120,8 +1136,8 @@ ExpandMacroResult ExpandMacros( case State::MacroName: if (c == '}') { - auto e = - ExpandMacro(result, macroNamespace, macroName, macroExpanders); + auto e = ExpandMacro(result, macroNamespace, macroName, + macroExpanders, version); if (e != ExpandMacroResult::Ok) { return e; } @@ -1153,10 +1169,11 @@ ExpandMacroResult ExpandMacros( ExpandMacroResult ExpandMacro(std::string& out, const std::string& macroNamespace, const std::string& macroName, - const std::vector& macroExpanders) + const std::vector& macroExpanders, + int version) { for (auto const& macroExpander : macroExpanders) { - auto result = macroExpander(macroNamespace, macroName, out); + auto result = macroExpander(macroNamespace, macroName, out, version); if (result != ExpandMacroResult::Ignore) { return result; } @@ -1549,6 +1566,11 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( if (v < MIN_VERSION || v > MAX_VERSION) { return ReadFileResult::UNRECOGNIZED_VERSION; } + if (user) { + this->UserVersion = v; + } else { + this->Version = v; + } // Support for build and test presets added in version 2. if (v < 2 && diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index 517215d2332..eed0eabff71 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -294,6 +294,13 @@ class cmCMakePresetsFile std::vector TestPresetOrder; std::string SourceDir; + int Version; + int UserVersion; + + int GetVersion(const Preset& preset) const + { + return preset.User ? this->UserVersion : this->Version; + } static std::string GetFilename(const std::string& sourceDir); static std::string GetUserFilename(const std::string& sourceDir); From 79d03ab5055da1397c525c31d8cb13c30965a911 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 11 Mar 2021 09:22:37 -0500 Subject: [PATCH 0131/1519] Help: Fix version numbers in CMakePresets.json documentation --- Help/manual/cmake-presets.7.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 3d2ada88d4c..60d047322f0 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -39,7 +39,7 @@ The root object recognizes the following fields: ``version`` A required integer representing the version of the JSON schema. - The supported versions are ``1`` and ``2``. + The supported versions are ``1``, ``2``, and ``3``. ``cmakeMinimumRequired`` @@ -70,17 +70,17 @@ The root object recognizes the following fields: ``configurePresets`` An optional array of `Configure Preset`_ objects. - This is allowed in preset files specifying version 1 or above. + 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. + 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. + This is allowed in preset files specifying version ``2`` or above. Configure Preset ^^^^^^^^^^^^^^^^ @@ -187,7 +187,8 @@ that may contain the following fields: An optional string representing the path to the installation directory. This field supports `macro expansion`_. If a relative path is specified, - it is calculated relative to the source directory. + it is calculated relative to the source directory. This is allowed in + preset files specifying version ``3`` or above. ``cmakeExecutable`` From 0d497e159b5854ed050d9eb8c4e965976a03de11 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 10 Mar 2021 16:46:20 -0500 Subject: [PATCH 0132/1519] CMakePresets.json: Add ${hostSystemName} macro --- Help/manual/cmake-presets.7.rst | 6 ++++++ Help/release/dev/cmake-presets-host-system-name.rst | 5 +++++ Source/cmCMakePresetsFile.cxx | 10 +++++++++- Tests/RunCMake/CMakePresets/HostSystemName.cmake | 3 +++ Tests/RunCMake/CMakePresets/HostSystemName.json.in | 13 +++++++++++++ .../CMakePresets/HostSystemNameFuture-result.txt | 1 + .../CMakePresets/HostSystemNameFuture-stderr.txt | 2 ++ .../CMakePresets/HostSystemNameFuture.json.in | 13 +++++++++++++ Tests/RunCMake/CMakePresets/RunCMakeTest.cmake | 6 ++++++ 9 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/cmake-presets-host-system-name.rst create mode 100644 Tests/RunCMake/CMakePresets/HostSystemName.cmake create mode 100644 Tests/RunCMake/CMakePresets/HostSystemName.json.in create mode 100644 Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt create mode 100644 Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 60d047322f0..527323678b7 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -830,6 +830,12 @@ Recognized macros include: test presets, this will evaluate to the generator specified by ``configurePreset``. +``${hostSystemName}`` + + 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. + ``${dollar}`` A literal dollar sign (``$``). diff --git a/Help/release/dev/cmake-presets-host-system-name.rst b/Help/release/dev/cmake-presets-host-system-name.rst new file mode 100644 index 00000000000..803693965a1 --- /dev/null +++ b/Help/release/dev/cmake-presets-host-system-name.rst @@ -0,0 +1,5 @@ +cmake-presets-host-system-name +------------------------------ + +* :manual:`cmake-presets(7)` gained support for a new ``${hostSystemName}`` + macro. diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index e9caecdb9d9..7726927bb60 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -981,7 +982,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, MacroExpander defaultMacroExpander = [&file, &preset](const std::string& macroNamespace, const std::string& macroName, std::string& macroOut, - int /*version*/) -> ExpandMacroResult { + int version) -> ExpandMacroResult { if (macroNamespace.empty()) { if (macroName == "sourceDir") { macroOut += file.SourceDir; @@ -1010,6 +1011,13 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, macroOut += '$'; return ExpandMacroResult::Ok; } + if (macroName == "hostSystemName") { + if (version < 3) { + return ExpandMacroResult::Error; + } + macroOut += cmSystemTools::GetSystemName(); + return ExpandMacroResult::Ok; + } } return ExpandMacroResult::Ignore; diff --git a/Tests/RunCMake/CMakePresets/HostSystemName.cmake b/Tests/RunCMake/CMakePresets/HostSystemName.cmake new file mode 100644 index 00000000000..dc0998aa357 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/HostSystemName.cmake @@ -0,0 +1,3 @@ +include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake) + +test_variable(TEST_HOST_SYSTEM_NAME "" "${CMAKE_HOST_SYSTEM_NAME}") diff --git a/Tests/RunCMake/CMakePresets/HostSystemName.json.in b/Tests/RunCMake/CMakePresets/HostSystemName.json.in new file mode 100644 index 00000000000..7fcd8c8362b --- /dev/null +++ b/Tests/RunCMake/CMakePresets/HostSystemName.json.in @@ -0,0 +1,13 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "HostSystemName", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "TEST_HOST_SYSTEM_NAME": "${hostSystemName}" + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt new file mode 100644 index 00000000000..7f4bb9a2433 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/HostSystemNameFuture: Invalid macro expansion$ diff --git a/Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in b/Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in new file mode 100644 index 00000000000..7a2f0aa1f0c --- /dev/null +++ b/Tests/RunCMake/CMakePresets/HostSystemNameFuture.json.in @@ -0,0 +1,13 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "HostSystemNameFuture", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "TEST_HOST_SYSTEM_NAME": "${hostSystemName}" + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index ee211306106..24ac0e985e7 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -261,6 +261,12 @@ set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Debug.json.in") run_cmake_presets(NoDebug) run_cmake_presets(Debug) +# Test ${hostSystemName} macro +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/HostSystemName.json.in") +run_cmake_presets(HostSystemName) +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/HostSystemNameFuture.json.in") +run_cmake_presets(HostSystemNameFuture) + # Test the example from the documentation file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example) string(REPLACE "\"generator\": \"Ninja\"" "\"generator\": \"@RunCMake_GENERATOR@\"" _example "${_example}") From 55233eee424816843bb0a5c820d3d4ebbdf3da27 Mon Sep 17 00:00:00 2001 From: Tobias Ribizel Date: Wed, 10 Mar 2021 14:55:43 +0100 Subject: [PATCH 0133/1519] CUDA: Add support for finding nvcc in CUDA_PATH Previously, nvcc needed to be present in PATH or specified by CUDACXX. On Windows with vcpkg, the PATH is heavily modified, which lead to nvcc not being found with the Ninja generator. --- Modules/CMakeDetermineCUDACompiler.cmake | 2 ++ Modules/CMakeDetermineCompiler.cmake | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 1ba537a3eb0..0f507eaa174 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -31,7 +31,9 @@ else() set(CMAKE_CUDA_COMPILER_LIST nvcc) endif() + set(_CMAKE_CUDA_COMPILER_PATHS "$ENV{CUDA_PATH}/bin") _cmake_find_compiler(CUDA) + unset(_CMAKE_CUDA_COMPILER_PATHS) else() _cmake_find_compiler_path(CUDA) endif() diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake index 2780399dcc4..6430793baa0 100644 --- a/Modules/CMakeDetermineCompiler.cmake +++ b/Modules/CMakeDetermineCompiler.cmake @@ -68,6 +68,16 @@ macro(_cmake_find_compiler lang) ) endif() find_program(CMAKE_${lang}_COMPILER NAMES ${CMAKE_${lang}_COMPILER_LIST} DOC "${lang} compiler") + if(_CMAKE_${lang}_COMPILER_PATHS) + # As a last fall-back, search in language-specific paths + find_program(CMAKE_${lang}_COMPILER + NAMES ${CMAKE_${lang}_COMPILER_LIST} + NAMES_PER_DIR + PATHS ${_CMAKE_${lang}_COMPILER_PATHS} + DOC "${lang} compiler" + NO_DEFAULT_PATH + ) + endif() if(CMAKE_${lang}_COMPILER_INIT AND NOT CMAKE_${lang}_COMPILER) set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${CMAKE_${lang}_COMPILER_INIT}") endif() From 0cf1b5c5adca7061f5d65eef602eca180c8fecb7 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 16 Mar 2021 00:01:17 -0400 Subject: [PATCH 0134/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ff82f8f0551..7c6d2847ce7 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210315) +set(CMake_VERSION_PATCH 20210316) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ea430582f96a085e1b4d7c5125d5ca8a2266e48b Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Mar 2021 11:40:22 -0500 Subject: [PATCH 0135/1519] cmInstallTargetGenerator: Drop unused GetNamelinkMode method --- Source/cmInstallTargetGenerator.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 8c5d4441013..b94c2a6805a 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -39,7 +39,6 @@ class cmInstallTargetGenerator : public cmInstallGenerator NamelinkModeSkip }; void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; } - NamelinkModeType GetNamelinkMode() const { return this->NamelinkMode; } std::string GetInstallFilename(const std::string& config) const; From f73b6879e9f93157bc3bec26ee319cf67e6b026a Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Mar 2021 11:41:06 -0500 Subject: [PATCH 0136/1519] cmInstallTargetGenerator: Report namelink mode with list of files --- Source/cmInstallTargetGenerator.cxx | 1 + Source/cmInstallTargetGenerator.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index bef785d0b3a..eb214fa1c74 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -338,6 +338,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles( // Add the names based on the current namelink mode. if (haveNamelink) { + files.NamelinkMode = this->NamelinkMode; // With a namelink we need to check the mode. if (this->NamelinkMode == NamelinkModeOnly) { // Install the namelink only. diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index b94c2a6805a..84fce4231b3 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -81,6 +81,7 @@ class cmInstallTargetGenerator : public cmInstallGenerator // Prefix for all files in To. std::string ToDir; + NamelinkModeType NamelinkMode = NamelinkModeNone; bool NoTweak = false; bool UseSourcePermissions = false; cmInstallType Type = cmInstallType(); From 415ead81533ead72fca8a495c3cbc17e2bf4e400 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 11 Jan 2021 10:19:38 -0500 Subject: [PATCH 0137/1519] cmFileAPICodemodel: Build map from each target to its index --- Source/cmFileAPICodemodel.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 90611092bad..596edd15974 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -46,6 +46,9 @@ namespace { +using TargetIndexMapType = + std::unordered_map; + class Codemodel { cmFileAPI& FileAPI; @@ -94,6 +97,8 @@ class CodemodelConfig ProjectMap; std::vector Projects; + TargetIndexMapType TargetIndexMap; + void ProcessDirectories(); Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg); @@ -663,6 +668,8 @@ Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt, target["projectIndex"] = pi; this->Projects[pi].TargetIndexes.append(ti); + this->TargetIndexMap[gt] = ti; + return target; } From fd30bd93e6f4334a9cd317a1e5eb8181fffa7a42 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 11 Jan 2021 09:17:05 -0500 Subject: [PATCH 0138/1519] fileapi: Re-organize backtrace infrastructure Make it available to more parts of the codemodel object. --- Help/manual/cmake-file-api.7.rst | 76 +++++---- Source/cmFileAPICodemodel.cxx | 168 +++++++++---------- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 5 +- 3 files changed, 128 insertions(+), 121 deletions(-) diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 89739b7d55b..133282ddc50 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -964,40 +964,48 @@ with members: with forward slashes. ``backtraceGraph`` - A JSON object describing the graph of backtraces whose nodes are - referenced from ``backtrace`` members elsewhere. The members are: - - ``nodes`` - A JSON array listing nodes in the backtrace graph. Each entry - is a JSON object with members: - - ``file`` - An unsigned integer 0-based index into the backtrace ``files`` array. - - ``line`` - An optional member present when the node represents a line within - the file. The value is an unsigned integer 1-based line number. - - ``command`` - An optional member present when the node represents a command - invocation within the file. The value is an unsigned integer - 0-based index into the backtrace ``commands`` array. - - ``parent`` - An optional member present when the node is not the bottom of - the call stack. The value is an unsigned integer 0-based index - of another entry in the backtrace ``nodes`` array. - - ``commands`` - A JSON array listing command names referenced by backtrace nodes. - Each entry is a string specifying a command name. - - ``files`` - A JSON array listing CMake language files referenced by backtrace nodes. - Each entry is a string specifying the path to a file, represented - with forward slashes. If the file is inside the top-level source - directory then the path is specified relative to that directory. - Otherwise the path is absolute. + A `"codemodel" version 2 "backtrace graph"`_ whose nodes are referenced + from ``backtrace`` members elsewhere in this "target" object. + +"codemodel" version 2 "backtrace graph" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``backtraceGraph`` member of a `"codemodel" version 2 "target" object`_ +is a JSON object describing a graph of backtraces. Its nodes are referenced +from ``backtrace`` members elsewhere in the containing object. +The backtrace graph object members are: + +``nodes`` + A JSON array listing nodes in the backtrace graph. Each entry + is a JSON object with members: + + ``file`` + An unsigned integer 0-based index into the backtrace ``files`` array. + + ``line`` + An optional member present when the node represents a line within + the file. The value is an unsigned integer 1-based line number. + + ``command`` + An optional member present when the node represents a command + invocation within the file. The value is an unsigned integer + 0-based index into the backtrace ``commands`` array. + + ``parent`` + An optional member present when the node is not the bottom of + the call stack. The value is an unsigned integer 0-based index + of another entry in the backtrace ``nodes`` array. + +``commands`` + A JSON array listing command names referenced by backtrace nodes. + Each entry is a string specifying a command name. + +``files`` + A JSON array listing CMake language files referenced by backtrace nodes. + Each entry is a string specifying the path to a file, represented + with forward slashes. If the file is inside the top-level source + directory then the path is specified relative to that directory. + Otherwise the path is absolute. Object Kind "cache" ------------------- diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 596edd15974..ed6ac8e7b0c 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -49,80 +49,6 @@ namespace { using TargetIndexMapType = std::unordered_map; -class Codemodel -{ - cmFileAPI& FileAPI; - unsigned long Version; - - Json::Value DumpPaths(); - Json::Value DumpConfigurations(); - Json::Value DumpConfiguration(std::string const& config); - -public: - Codemodel(cmFileAPI& fileAPI, unsigned long version); - Json::Value Dump(); -}; - -class CodemodelConfig -{ - cmFileAPI& FileAPI; - unsigned long Version; - std::string const& Config; - std::string TopSource; - std::string TopBuild; - - struct Directory - { - cmStateSnapshot Snapshot; - cmLocalGenerator const* LocalGenerator = nullptr; - Json::Value TargetIndexes = Json::arrayValue; - Json::ArrayIndex ProjectIndex; - bool HasInstallRule = false; - }; - std::map - DirectoryMap; - std::vector Directories; - - struct Project - { - cmStateSnapshot Snapshot; - static const Json::ArrayIndex NoParentIndex = - static_cast(-1); - Json::ArrayIndex ParentIndex = NoParentIndex; - Json::Value ChildIndexes = Json::arrayValue; - Json::Value DirectoryIndexes = Json::arrayValue; - Json::Value TargetIndexes = Json::arrayValue; - }; - std::map - ProjectMap; - std::vector Projects; - - TargetIndexMapType TargetIndexMap; - - void ProcessDirectories(); - - Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg); - Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s); - - Json::ArrayIndex AddProject(cmStateSnapshot s); - - Json::Value DumpTargets(); - Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti); - - Json::Value DumpDirectories(); - Json::Value DumpDirectory(Directory& d); - - Json::Value DumpProjects(); - Json::Value DumpProject(Project& p); - - Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s); - -public: - CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, - std::string const& config); - Json::Value Dump(); -}; - std::string RelativeIfUnder(std::string const& top, std::string const& in) { std::string out; @@ -136,16 +62,6 @@ std::string RelativeIfUnder(std::string const& top, std::string const& in) return out; } -std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) -{ - cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256); - std::string path = RelativeIfUnder( - topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory()); - std::string hash = hasher.HashString(path); - hash.resize(20, '0'); - return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; -} - class JBTIndex { public: @@ -295,6 +211,90 @@ Json::Value BacktraceData::Dump() return backtraceGraph; } +class Codemodel +{ + cmFileAPI& FileAPI; + unsigned long Version; + + Json::Value DumpPaths(); + Json::Value DumpConfigurations(); + Json::Value DumpConfiguration(std::string const& config); + +public: + Codemodel(cmFileAPI& fileAPI, unsigned long version); + Json::Value Dump(); +}; + +class CodemodelConfig +{ + cmFileAPI& FileAPI; + unsigned long Version; + std::string const& Config; + std::string TopSource; + std::string TopBuild; + + struct Directory + { + cmStateSnapshot Snapshot; + cmLocalGenerator const* LocalGenerator = nullptr; + Json::Value TargetIndexes = Json::arrayValue; + Json::ArrayIndex ProjectIndex; + bool HasInstallRule = false; + }; + std::map + DirectoryMap; + std::vector Directories; + + struct Project + { + cmStateSnapshot Snapshot; + static const Json::ArrayIndex NoParentIndex = + static_cast(-1); + Json::ArrayIndex ParentIndex = NoParentIndex; + Json::Value ChildIndexes = Json::arrayValue; + Json::Value DirectoryIndexes = Json::arrayValue; + Json::Value TargetIndexes = Json::arrayValue; + }; + std::map + ProjectMap; + std::vector Projects; + + TargetIndexMapType TargetIndexMap; + + void ProcessDirectories(); + + Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg); + Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s); + + Json::ArrayIndex AddProject(cmStateSnapshot s); + + Json::Value DumpTargets(); + Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti); + + Json::Value DumpDirectories(); + Json::Value DumpDirectory(Directory& d); + + Json::Value DumpProjects(); + Json::Value DumpProject(Project& p); + + Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s); + +public: + CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, + std::string const& config); + Json::Value Dump(); +}; + +std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) +{ + cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256); + std::string path = RelativeIfUnder( + topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory()); + std::string hash = hasher.HashString(path); + hash.resize(20, '0'); + return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; +} + struct CompileData { struct IncludeEntry diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index df2410a4166..e1550374a4d 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -94,8 +94,7 @@ def _check(actual, expected): return _check -def check_target_backtrace_graph(t): - btg = t["backtraceGraph"] +def check_backtrace_graph(btg): assert is_dict(btg) assert sorted(btg.keys()) == ["commands", "files", "nodes"] assert is_list(btg["commands"]) @@ -148,7 +147,7 @@ def _check(actual, expected): assert is_string(obj["name"], expected["name"]) assert matches(obj["id"], expected["id"]) assert is_string(obj["type"], expected["type"]) - check_target_backtrace_graph(obj) + check_backtrace_graph(obj["backtraceGraph"]) assert is_dict(obj["paths"]) assert sorted(obj["paths"].keys()) == ["build", "source"] From a12d7f70b1b97f74293d9861a1827c88ef46ec39 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 14 Jan 2021 15:10:49 -0500 Subject: [PATCH 0139/1519] fileapi: Add a "directory" object to codemodel-v2 This object will contain more detailed directory-level information. Co-Authored-by: Kyle Edwards --- Help/manual/cmake-file-api.7.rst | 37 ++++++- .../dev/fileapi-codemodel-directory.rst | 8 ++ Source/cmFileAPI.cxx | 2 +- Source/cmFileAPICodemodel.cxx | 72 ++++++++++++- .../CommandLine/E_capabilities-stdout.txt | 2 +- .../codemodel-v2-ClientStateful-check.cmake | 1 + .../codemodel-v2-ClientStateless-check.cmake | 1 + .../codemodel-v2-SharedStateless-check.cmake | 1 + Tests/RunCMake/FileAPI/codemodel-v2-check.py | 22 +++- .../directories/external.json | 2 +- .../targets/c_shared_lib.json | 101 +++++++++++++++++- .../targets/cxx_shared_lib.json | 95 +++++++++++++++- Tests/RunCMake/FileAPI/codemodel-v2.cmake | 17 ++- Tests/RunCMake/FileAPI/cxx/CMakeLists.txt | 2 +- .../FileAPIExternalSource/CMakeLists.txt | 3 + 15 files changed, 351 insertions(+), 15 deletions(-) create mode 100644 Help/release/dev/fileapi-codemodel-directory.rst diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 133282ddc50..7c34d517f56 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -443,7 +443,8 @@ Version 1 does not exist to avoid confusion with that from "hasInstallRule": true, "minimumCMakeVersion": { "string": "3.14" - } + }, + "jsonFile": "" }, { "source": "sub", @@ -453,7 +454,8 @@ Version 1 does not exist to avoid confusion with that from "targetIndexes": [ 1 ], "minimumCMakeVersion": { "string": "3.14" - } + }, + "jsonFile": "" } ], "projects": [ @@ -569,6 +571,13 @@ The members specific to ``codemodel`` objects are: :command:`install` rules, i.e. whether a ``make install`` or equivalent rule is available. + ``jsonFile`` + A JSON string specifying a path relative to the codemodel file + to another JSON file containing a + `"codemodel" version 2 "directory" object`_. + + This field was added in codemodel version 2.3. + ``projects`` A JSON array of entries corresponding to the top-level project and sub-projects defined in the build system. Each (sub-)project @@ -633,6 +642,30 @@ The members specific to ``codemodel`` objects are: to another JSON file containing a `"codemodel" version 2 "target" object`_. +"codemodel" version 2 "directory" object +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A codemodel "directory" object is referenced by a `"codemodel" version 2`_ +object's ``directories`` array. Each "directory" object is a JSON object +with members: + +``paths`` + A JSON object containing members: + + ``source`` + A string specifying the path to the source directory, represented + with forward slashes. If the directory is inside the top-level + source directory then the path is specified relative to that + directory (with ``.`` for the top-level source directory itself). + Otherwise the path is absolute. + + ``build`` + A string specifying the path to the build directory, represented + with forward slashes. If the directory is inside the top-level + build directory then the path is specified relative to that + directory (with ``.`` for the top-level build directory itself). + Otherwise the path is absolute. + "codemodel" version 2 "target" object ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/fileapi-codemodel-directory.rst b/Help/release/dev/fileapi-codemodel-directory.rst new file mode 100644 index 00000000000..7dffb96fef8 --- /dev/null +++ b/Help/release/dev/fileapi-codemodel-directory.rst @@ -0,0 +1,8 @@ +fileapi-codemodel-directory +--------------------------- + +* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has + component been updated to 2.3. + +* The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a + new "directory" object containing directory-level information. diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index d2a9becf45f..d529f5268e5 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -686,7 +686,7 @@ std::string cmFileAPI::NoSupportedVersion( // The "codemodel" object kind. -static unsigned int const CodeModelV2Minor = 2; +static unsigned int const CodeModelV2Minor = 3; void cmFileAPI::BuildClientRequestCodeModel( ClientRequest& r, std::vector const& versions) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index ed6ac8e7b0c..2f36db2d844 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -273,6 +273,7 @@ class CodemodelConfig Json::Value DumpDirectories(); Json::Value DumpDirectory(Directory& d); + Json::Value DumpDirectoryObject(Directory& d); Json::Value DumpProjects(); Json::Value DumpProject(Project& p); @@ -372,6 +373,20 @@ struct hash } // namespace std namespace { +class DirectoryObject +{ + cmLocalGenerator const* LG = nullptr; + std::string const& Config; + std::string TopSource; + std::string TopBuild; + + Json::Value DumpPaths(); + +public: + DirectoryObject(cmLocalGenerator const* lg, std::string const& config); + Json::Value Dump(); +}; + class Target { cmGeneratorTarget* GT; @@ -684,7 +699,7 @@ Json::Value CodemodelConfig::DumpDirectories() Json::Value CodemodelConfig::DumpDirectory(Directory& d) { - Json::Value directory = Json::objectValue; + Json::Value directory = this->DumpDirectoryObject(d); std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource(); directory["source"] = RelativeIfUnder(this->TopSource, sourceDir); @@ -724,6 +739,31 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d) return directory; } +Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d) +{ + std::string prefix = "directory"; + std::string sourceDirRel = RelativeIfUnder( + this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource()); + std::string buildDirRel = RelativeIfUnder( + this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary()); + if (!cmSystemTools::FileIsFullPath(buildDirRel)) { + prefix = cmStrCat(prefix, '-', buildDirRel); + } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) { + prefix = cmStrCat(prefix, '-', sourceDirRel); + } + for (char& c : prefix) { + if (c == '/' || c == '\\') { + c = '.'; + } + } + if (!this->Config.empty()) { + prefix += "-" + this->Config; + } + + DirectoryObject dir(d.LocalGenerator, this->Config); + return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix); +} + Json::Value CodemodelConfig::DumpProjects() { Json::Value projects = Json::arrayValue; @@ -767,6 +807,36 @@ Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) return minimumCMakeVersion; } +DirectoryObject::DirectoryObject(cmLocalGenerator const* lg, + std::string const& config) + : LG(lg) + , Config(config) + , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory()) + , TopBuild( + lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory()) +{ +} + +Json::Value DirectoryObject::Dump() +{ + Json::Value directoryObject = Json::objectValue; + directoryObject["paths"] = this->DumpPaths(); + return directoryObject; +} + +Json::Value DirectoryObject::DumpPaths() +{ + Json::Value paths = Json::objectValue; + + std::string const& sourceDir = this->LG->GetCurrentSourceDirectory(); + paths["source"] = RelativeIfUnder(this->TopSource, sourceDir); + + std::string const& buildDir = this->LG->GetCurrentBinaryDirectory(); + paths["build"] = RelativeIfUnder(this->TopBuild, buildDir); + + return paths; +} + Target::Target(cmGeneratorTarget* gt, std::string const& config) : GT(gt) , Config(config) diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt index c76c92d9e22..3df3e523d63 100644 --- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt +++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt @@ -1 +1 @@ -^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":2}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"version":{.*}}$ +^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":3}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"version":{.*}}$ diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake index fb78e8789e6..91cdf7ca19a 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake @@ -4,6 +4,7 @@ set(expect query/client-foo/query.json reply reply/codemodel-v2-[0-9a-f]+\\.json + .* reply/index-[0-9.T-]+\\.json .* ) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake index 7c6a35ab557..9aa9e4a2a17 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake @@ -4,6 +4,7 @@ set(expect query/client-foo/codemodel-v2 reply reply/codemodel-v2-[0-9a-f]+\\.json + .* reply/index-[0-9.T-]+\\.json .* ) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake index cc2f31b9488..43d1a0b4e1f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake @@ -3,6 +3,7 @@ set(expect query/codemodel-v2 reply reply/codemodel-v2-[0-9a-f]+\\.json + .* reply/index-[0-9.T-]+\\.json .* ) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index e1550374a4d..0e5b3b96e85 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -12,7 +12,7 @@ def read_codemodel_json_data(filename): def check_objects(o, g): assert is_list(o) assert len(o) == 1 - check_index_object(o[0], "codemodel", 2, 2, check_object_codemodel(g)) + check_index_object(o[0], "codemodel", 2, 3, check_object_codemodel(g)) def check_backtrace(t, b, backtrace): btg = t["backtraceGraph"] @@ -55,7 +55,7 @@ def check_backtraces(t, actual, expected): def check_directory(c): def _check(actual, expected): assert is_dict(actual) - expected_keys = ["build", "source", "projectIndex"] + expected_keys = ["build", "jsonFile", "source", "projectIndex"] assert matches(actual["build"], expected["build"]) assert is_int(actual["projectIndex"]) @@ -92,6 +92,17 @@ def _check(actual, expected): assert sorted(actual.keys()) == sorted(expected_keys) + assert is_string(actual["jsonFile"]) + filepath = os.path.join(reply_dir, actual["jsonFile"]) + with open(filepath) as f: + d = json.load(f) + + assert is_dict(d) + assert sorted(d.keys()) == ["paths"] + + assert is_string(d["paths"]["source"], actual["source"]) + assert is_string(d["paths"]["build"], actual["build"]) + return _check def check_backtrace_graph(btg): @@ -704,6 +715,13 @@ def gen_check_targets(c, g, inSource): if sys.platform not in ("win32", "cygwin", "msys"): for e in expected: e["artifacts"] = filter_list(lambda a: not a["_dllExtra"], e["artifacts"]) + if e["install"] is not None: + e["install"]["destinations"] = filter_list(lambda d: "_dllExtra" not in d or not d["_dllExtra"], e["install"]["destinations"]) + + else: + for e in expected: + if e["install"] is not None: + e["install"]["destinations"] = filter_list(lambda d: "_namelink" not in d or not d["_namelink"], e["install"]["destinations"]) if "aix" not in sys.platform: for e in expected: diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json index 521e3c70d80..0d3161c16a3 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json @@ -10,5 +10,5 @@ ], "projectName": "External", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": true } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json index 176a8575bd4..5588bd53d2f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json @@ -90,10 +90,10 @@ } ], "folder": null, - "nameOnDisk": "^(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$", + "nameOnDisk": "^(lib|cyg)?c_shared_lib(-1)?\\.(so|dylib|dll)$", "artifacts": [ { - "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$", + "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib(-1)?\\.(so|dylib|dll)$", "_dllExtra": false }, { @@ -101,13 +101,106 @@ "_dllExtra": true }, { - "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.pdb$", + "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib(-1)?\\.pdb$", "_dllExtra": true } ], "build": "^\\.$", "source": "^\\.$", - "install": null, + "install": { + "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$", + "destinations": [ + { + "path": "lib", + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "path": "lib", + "_dllExtra": true, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "path": "lib", + "_namelink": true, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 46, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] + }, "link": { "language": "C", "lto": true, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json index 171a4f5c1b0..e5e1d0de244 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json @@ -83,7 +83,100 @@ ], "build": "^cxx$", "source": "^cxx$", - "install": null, + "install": { + "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$", + "destinations": [ + { + "path": "lib", + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "path": "lib", + "_dllExtra": true, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "path": "lib", + "_namelink": true, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 46, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] + }, "link": { "language": "CXX", "lto": null, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake index 2405954429b..528f07546d1 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake @@ -35,4 +35,19 @@ if(_ipo) file(WRITE "${CMAKE_BINARY_DIR}/ipo_enabled.txt" "") endif() -install(TARGETS cxx_exe) +install(TARGETS cxx_exe COMPONENT Tools EXPORT FooTargets) + +set_target_properties(c_shared_lib PROPERTIES VERSION 1.2.3 SOVERSION 1) +install(TARGETS c_shared_lib cxx_shared_lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION lib + LIBRARY DESTINATION lib NAMELINK_SKIP + ) +install(TARGETS c_shared_lib cxx_shared_lib LIBRARY NAMELINK_ONLY) + +install(FILES empty.h TYPE INCLUDE RENAME empty-renamed.h OPTIONAL) +install(FILES codemodel-v2.cmake empty.h DESTINATION include) +install(DIRECTORY . dir cxx/ OPTIONAL DESTINATION dir1) +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}/cxx/" DESTINATION dir2) +install(EXPORT FooTargets DESTINATION lib/cmake/foo) +install(SCRIPT InstallScript.cmake) diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt index 76235f5c5a4..95c803fb65c 100644 --- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt @@ -16,7 +16,7 @@ target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib) target_compile_options(cxx_exe PUBLIC TargetCompileOptions) target_link_options(cxx_exe PUBLIC TargetLinkOptions) -target_link_directories(cxx_exe PUBLIC "${CMAKE_BINARY_DIR}/TargetLinkDir") +target_link_directories(cxx_exe PUBLIC "$") target_precompile_headers(cxx_exe PUBLIC ../empty.h) diff --git a/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt b/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt index b3ca6607510..2865864a3cf 100644 --- a/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt +++ b/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt @@ -11,3 +11,6 @@ set_property(SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY target_include_directories(generated_exe SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_compile_definitions(generated_exe PRIVATE GENERATED_EXE=1 -DTGT_DUMMY) set_source_files_properties(empty.c PROPERTIES COMPILE_OPTIONS SRC_COMPILE_OPTIONS_DUMMY) + +install(DIRECTORY . DESTINATION dir3) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} EXCLUDE_FROM_ALL DESTINATION dir4) From eae2256a529250e4fda639a79a9edddef6604f12 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 14 Jan 2021 16:17:56 -0500 Subject: [PATCH 0140/1519] fileapi: Add backtraceGraph to codemodel-v2 "directory" object Co-Authored-by: Kyle Edwards --- Help/manual/cmake-file-api.7.rst | 12 ++++++++---- Source/cmFileAPICodemodel.cxx | 13 +++++++++++++ Tests/RunCMake/FileAPI/codemodel-v2-check.py | 4 +++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 7c34d517f56..088ec2e625d 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -666,6 +666,10 @@ with members: directory (with ``.`` for the top-level build directory itself). Otherwise the path is absolute. +``backtraceGraph`` + A `"codemodel" version 2 "backtrace graph"`_ whose nodes are referenced + from ``backtrace`` members elsewhere in this "directory" object. + "codemodel" version 2 "target" object ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1003,10 +1007,10 @@ with members: "codemodel" version 2 "backtrace graph" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The ``backtraceGraph`` member of a `"codemodel" version 2 "target" object`_ -is a JSON object describing a graph of backtraces. Its nodes are referenced -from ``backtrace`` members elsewhere in the containing object. -The backtrace graph object members are: +The ``backtraceGraph`` member of a `"codemodel" version 2 "directory" object`_, +or `"codemodel" version 2 "target" object`_ is a JSON object describing a +graph of backtraces. Its nodes are referenced from ``backtrace`` members +elsewhere in the containing object. The backtrace graph object members are: ``nodes`` A JSON array listing nodes in the backtrace graph. Each entry diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 2f36db2d844..e7bfc6164a0 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -379,6 +379,9 @@ class DirectoryObject std::string const& Config; std::string TopSource; std::string TopBuild; + BacktraceData Backtraces; + + void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt); Json::Value DumpPaths(); @@ -814,6 +817,7 @@ DirectoryObject::DirectoryObject(cmLocalGenerator const* lg, , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory()) , TopBuild( lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory()) + , Backtraces(this->TopSource) { } @@ -821,9 +825,18 @@ Json::Value DirectoryObject::Dump() { Json::Value directoryObject = Json::objectValue; directoryObject["paths"] = this->DumpPaths(); + directoryObject["backtraceGraph"] = this->Backtraces.Dump(); return directoryObject; } +void DirectoryObject::AddBacktrace(Json::Value& object, + cmListFileBacktrace const& bt) +{ + if (JBTIndex backtrace = this->Backtraces.Add(bt)) { + object["backtrace"] = backtrace.Index; + } +} + Json::Value DirectoryObject::DumpPaths() { Json::Value paths = Json::objectValue; diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 0e5b3b96e85..900faf9c3fb 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -98,11 +98,13 @@ def _check(actual, expected): d = json.load(f) assert is_dict(d) - assert sorted(d.keys()) == ["paths"] + assert sorted(d.keys()) == ["backtraceGraph", "paths"] assert is_string(d["paths"]["source"], actual["source"]) assert is_string(d["paths"]["build"], actual["build"]) + check_backtrace_graph(d["backtraceGraph"]) + return _check def check_backtrace_graph(btg): From 049bf98f63f386bdc174c3872c7ef1c658041cf4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 21 Jan 2021 13:17:19 -0500 Subject: [PATCH 0141/1519] fileapi: Add installers to codemodel-v2 "directory" object Co-Authored-by: Kyle Edwards --- Help/manual/cmake-file-api.7.rst | 148 +++++ .../dev/fileapi-codemodel-directory.rst | 2 + Source/cmFileAPICodemodel.cxx | 220 ++++++- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 93 ++- .../codemodel-v2-data/directories/alias.json | 3 +- .../codemodel-v2-data/directories/custom.json | 3 +- .../codemodel-v2-data/directories/cxx.json | 3 +- .../codemodel-v2-data/directories/dir.json | 3 +- .../directories/dir_dir.json | 3 +- .../directories/external.json | 66 ++- .../directories/imported.json | 3 +- .../directories/interface.json | 3 +- .../codemodel-v2-data/directories/object.json | 66 ++- .../codemodel-v2-data/directories/top.json | 546 +++++++++++++++++- 14 files changed, 1148 insertions(+), 14 deletions(-) diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 088ec2e625d..cbc3d6dc673 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -666,6 +666,154 @@ with members: directory (with ``.`` for the top-level build directory itself). Otherwise the path is absolute. +``installers`` + A JSON array of entries corresponding to :command:`install` rules. + Each entry is a JSON object containing members: + + ``component`` + A string specifying the component selected by the corresponding + :command:`install` command invocation. + + ``destination`` + Optional member that is present for specific ``type`` values below. + The value is a string specifying the install destination path. + The path may be absolute or relative to the install prefix. + + ``paths`` + Optional member that is present for specific ``type`` values below. + The value is a JSON array of entries corresponding to the paths + (files or directories) to be installed. Each entry is one of: + + * A string specifying the path from which a file or directory + is to be installed. The portion of the path not preceded by + a ``/`` also specifies the path (name) to which the file + or directory is to be installed under the destination. + + * A JSON object with members: + + ``from`` + A string specifying the path from which a file or directory + is to be installed. + + ``to`` + A string specifying the path to which the file or directory + is to be installed under the destination. + + In both cases the paths are represented with forward slashes. If + the "from" path is inside the top-level directory documented by the + corresponding ``type`` value, then the path is specified relative + to that directory. Otherwise the path is absolute. + + ``type`` + A string specifying the type of installation rule. The value is one + of the following, with some variants providing additional members: + + ``file`` + An :command:`install(FILES)` or :command:`install(PROGRAMS)` call. + The ``destination`` and ``paths`` members are populated, with paths + under the top-level *source* directory expressed relative to it. + The ``isOptional`` member may exist. + This type has no additional members. + + ``directory`` + An :command:`install(DIRECTORY)` call. + The ``destination`` and ``paths`` members are populated, with paths + under the top-level *source* directory expressed relative to it. + The ``isOptional`` member may exist. + This type has no additional members. + + ``target`` + An :command:`install(TARGETS)` call. + The ``destination`` and ``paths`` members are populated, with paths + under the top-level *build* directory expressed relative to it. + The ``isOptional`` member may exist. + This type has additional members ``targetId``, ``targetIndex``, + ``targetIsImportLibrary``, and ``targetInstallNamelink``. + + ``export`` + An :command:`install(EXPORT)` call. + The ``destination`` and ``paths`` members are populated, with paths + under the top-level *build* directory expressed relative to it. + The ``paths`` entries refer to files generated automatically by + CMake for installation, and their actual values are considered + private implementation details. + This type has additional members ``exportName`` and ``exportTargets``. + + ``script`` + An :command:`install(SCRIPT)` call. + This type has additional member ``scriptFile``. + + ``code`` + An :command:`install(CODE)` call. + This type has no additional members. + + ``isExcludeFromAll`` + Optional member that is present with boolean value ``true`` when + :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option. + + ``isOptional`` + Optional member that is present with boolean value ``true`` when + :command:`install` is called with the ``OPTIONAL`` option. + This is allowed when ``type`` is ``file``, ``directory``, or ``target``. + + ``targetId`` + Optional member that is present when ``type`` is ``target``. + The value is a string uniquely identifying the target to be installed. + This matches the ``id`` member of the target in the main + "codemodel" object's ``targets`` array. + + ``targetIndex`` + Optional member that is present when ``type`` is ``target``. + The value is an unsigned integer 0-based index into the main "codemodel" + object's ``targets`` array for the target to be installed. + + ``targetIsImportLibrary`` + Optional member that is present when ``type`` is ``target`` and + the installer is for a Windows DLL import library file or for an + AIX linker import file. If present, it has boolean value ``true``. + + ``targetInstallNamelink`` + Optional member that is present when ``type`` is ``target`` and + the installer corresponds to a target that may use symbolic links + to implement the :prop_tgt:`VERSION` and :prop_tgt:`SOVERSION` + target properties. + The value is a string indicating how the installer is supposed to + handle the symlinks: ``skip`` means the installer should skip the + symlinks and install only the real file, and ``only`` means the + installer should install only the symlinks and not the real file. + In all cases the ``paths`` member lists what it actually installs. + + ``exportName`` + Optional member that is present when ``type`` is ``export``. + The value is a string specifying the name of the export. + + ``exportTargets`` + Optional member that is present when ``type`` is ``export``. + The value is a JSON array of entries corresponding to the targets + included in the export. Each entry is a JSON object with members: + + ``id`` + A string uniquely identifying the target. This matches + the ``id`` member of the target in the main "codemodel" + object's ``targets`` array. + + ``index`` + An unsigned integer 0-based index into the main "codemodel" + object's ``targets`` array for the target. + + ``scriptFile`` + Optional member that is present when ``type`` is ``script``. + The value is a string specifying the path to the script file on disk, + represented with forward slashes. If the file is inside the top-level + source directory then the path is specified relative to that directory. + Otherwise the path is absolute. + + ``backtrace`` + Optional member that is present when a CMake language backtrace to + the :command:`install` or other command invocation that added this + installer is available. The value is an unsigned integer 0-based + index into the ``backtraceGraph`` member's ``nodes`` array. + ``backtraceGraph`` A `"codemodel" version 2 "backtrace graph"`_ whose nodes are referenced from ``backtrace`` members elsewhere in this "directory" object. diff --git a/Help/release/dev/fileapi-codemodel-directory.rst b/Help/release/dev/fileapi-codemodel-directory.rst index 7dffb96fef8..f6515fd17c3 100644 --- a/Help/release/dev/fileapi-codemodel-directory.rst +++ b/Help/release/dev/fileapi-codemodel-directory.rst @@ -6,3 +6,5 @@ fileapi-codemodel-directory * The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a new "directory" object containing directory-level information. + This includes a list of installers generated by the :command:`install` + command. diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index e7bfc6164a0..6b8757c4164 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -20,11 +20,16 @@ #include #include "cmCryptoHash.h" +#include "cmExportSet.h" #include "cmFileAPI.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmInstallDirectoryGenerator.h" +#include "cmInstallExportGenerator.h" +#include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallScriptGenerator.h" #include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" @@ -42,6 +47,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" +#include "cmTargetExport.h" #include "cmake.h" namespace { @@ -377,6 +383,7 @@ class DirectoryObject { cmLocalGenerator const* LG = nullptr; std::string const& Config; + TargetIndexMapType& TargetIndexMap; std::string TopSource; std::string TopBuild; BacktraceData Backtraces; @@ -384,9 +391,16 @@ class DirectoryObject void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt); Json::Value DumpPaths(); + Json::Value DumpInstallers(); + Json::Value DumpInstaller(cmInstallGenerator* gen); + Json::Value DumpInstallerExportTargets(cmExportSet* exp); + Json::Value DumpInstallerPath(std::string const& top, + std::string const& fromPathIn, + std::string const& toPath); public: - DirectoryObject(cmLocalGenerator const* lg, std::string const& config); + DirectoryObject(cmLocalGenerator const* lg, std::string const& config, + TargetIndexMapType& targetIndexMap); Json::Value Dump(); }; @@ -763,7 +777,7 @@ Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d) prefix += "-" + this->Config; } - DirectoryObject dir(d.LocalGenerator, this->Config); + DirectoryObject dir(d.LocalGenerator, this->Config, this->TargetIndexMap); return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix); } @@ -811,9 +825,11 @@ Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) } DirectoryObject::DirectoryObject(cmLocalGenerator const* lg, - std::string const& config) + std::string const& config, + TargetIndexMapType& targetIndexMap) : LG(lg) , Config(config) + , TargetIndexMap(targetIndexMap) , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory()) , TopBuild( lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory()) @@ -825,6 +841,7 @@ Json::Value DirectoryObject::Dump() { Json::Value directoryObject = Json::objectValue; directoryObject["paths"] = this->DumpPaths(); + directoryObject["installers"] = this->DumpInstallers(); directoryObject["backtraceGraph"] = this->Backtraces.Dump(); return directoryObject; } @@ -850,6 +867,203 @@ Json::Value DirectoryObject::DumpPaths() return paths; } +Json::Value DirectoryObject::DumpInstallers() +{ + Json::Value installers = Json::arrayValue; + for (const auto& gen : this->LG->GetMakefile()->GetInstallGenerators()) { + Json::Value installer = this->DumpInstaller(gen.get()); + if (!installer.empty()) { + installers.append(std::move(installer)); // NOLINT(*) + } + } + return installers; +} + +Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) +{ + Json::Value installer = Json::objectValue; + + // Exclude subdirectory installers. They are implementation details. + if (dynamic_cast(gen)) { + return installer; + } + + // Exclude installers not used in this configuration. + if (!gen->InstallsForConfig(this->Config)) { + return installer; + } + + // Add fields specific to each kind of install generator. + if (auto* installTarget = dynamic_cast(gen)) { + cmInstallTargetGenerator::Files const& files = + installTarget->GetFiles(this->Config); + if (files.From.empty()) { + return installer; + } + + installer["type"] = "target"; + installer["destination"] = installTarget->GetDestination(this->Config); + installer["targetId"] = + TargetId(installTarget->GetTarget(), this->TopBuild); + installer["targetIndex"] = + this->TargetIndexMap[installTarget->GetTarget()]; + + std::string fromDir = files.FromDir; + if (!fromDir.empty()) { + fromDir.push_back('/'); + } + + std::string toDir = files.ToDir; + if (!toDir.empty()) { + toDir.push_back('/'); + } + + Json::Value paths = Json::arrayValue; + for (size_t i = 0; i < files.From.size(); ++i) { + std::string const& fromPath = cmStrCat(fromDir, files.From[i]); + std::string const& toPath = cmStrCat(toDir, files.To[i]); + paths.append(this->DumpInstallerPath(this->TopBuild, fromPath, toPath)); + } + installer["paths"] = std::move(paths); + + if (installTarget->GetOptional()) { + installer["isOptional"] = true; + } + + if (installTarget->IsImportLibrary()) { + installer["targetIsImportLibrary"] = true; + } + + switch (files.NamelinkMode) { + case cmInstallTargetGenerator::NamelinkModeNone: + break; + case cmInstallTargetGenerator::NamelinkModeOnly: + installer["targetInstallNamelink"] = "only"; + break; + case cmInstallTargetGenerator::NamelinkModeSkip: + installer["targetInstallNamelink"] = "skip"; + break; + } + + // FIXME: Parse FilePermissions to provide structured information. + // FIXME: Thread EXPORT name through from install() call. + } else if (auto* installFiles = + dynamic_cast(gen)) { + std::vector const& files = + installFiles->GetFiles(this->Config); + if (files.empty()) { + return installer; + } + + installer["type"] = "file"; + installer["destination"] = installFiles->GetDestination(this->Config); + Json::Value paths = Json::arrayValue; + std::string const& rename = installFiles->GetRename(this->Config); + if (!rename.empty() && files.size() == 1) { + paths.append(this->DumpInstallerPath(this->TopSource, files[0], rename)); + } else { + for (std::string const& file : installFiles->GetFiles(this->Config)) { + paths.append(RelativeIfUnder(this->TopSource, file)); + } + } + installer["paths"] = std::move(paths); + if (installFiles->GetOptional()) { + installer["isOptional"] = true; + } + // FIXME: Parse FilePermissions to provide structured information. + } else if (auto* installDir = + dynamic_cast(gen)) { + std::vector const& dirs = + installDir->GetDirectories(this->Config); + if (dirs.empty()) { + return installer; + } + + installer["type"] = "directory"; + installer["destination"] = installDir->GetDestination(this->Config); + Json::Value paths = Json::arrayValue; + for (std::string const& dir : dirs) { + if (cmHasLiteralSuffix(dir, "/")) { + paths.append(this->DumpInstallerPath( + this->TopSource, dir.substr(0, dir.size() - 1), ".")); + } else { + paths.append(this->DumpInstallerPath( + this->TopSource, dir, cmSystemTools::GetFilenameName(dir))); + } + } + installer["paths"] = std::move(paths); + if (installDir->GetOptional()) { + installer["isOptional"] = true; + } + // FIXME: Parse FilePermissions, DirPermissions, and LiteralArguments. + // to provide structured information. + } else if (auto* installExport = + dynamic_cast(gen)) { + installer["type"] = "export"; + installer["destination"] = installExport->GetDestination(); + cmExportSet* exportSet = installExport->GetExportSet(); + installer["exportName"] = exportSet->GetName(); + installer["exportTargets"] = this->DumpInstallerExportTargets(exportSet); + Json::Value paths = Json::arrayValue; + paths.append( + RelativeIfUnder(this->TopBuild, installExport->GetMainImportFile())); + installer["paths"] = std::move(paths); + } else if (auto* installScript = + dynamic_cast(gen)) { + if (installScript->IsCode()) { + installer["type"] = "code"; + } else { + installer["type"] = "script"; + installer["scriptFile"] = RelativeIfUnder( + this->TopSource, installScript->GetScript(this->Config)); + } + } + + // Add fields common to all install generators. + installer["component"] = gen->GetComponent(); + if (gen->GetExcludeFromAll()) { + installer["isExcludeFromAll"] = true; + } + this->AddBacktrace(installer, gen->GetBacktrace()); + + return installer; +} + +Json::Value DirectoryObject::DumpInstallerExportTargets(cmExportSet* exp) +{ + Json::Value targets = Json::arrayValue; + for (auto const& targetExport : exp->GetTargetExports()) { + Json::Value target = Json::objectValue; + target["id"] = TargetId(targetExport->Target, this->TopBuild); + target["index"] = this->TargetIndexMap[targetExport->Target]; + targets.append(std::move(target)); // NOLINT(*) + } + return targets; +} + +Json::Value DirectoryObject::DumpInstallerPath(std::string const& top, + std::string const& fromPathIn, + std::string const& toPath) +{ + Json::Value installPath; + + std::string fromPath = RelativeIfUnder(top, fromPathIn); + + // If toPath is the last component of fromPath, use just fromPath. + if (toPath.find_first_of('/') == std::string::npos && + cmHasSuffix(fromPath, toPath) && + (fromPath.size() == toPath.size() || + fromPath[fromPath.size() - toPath.size() - 1] == '/')) { + installPath = fromPath; + } else { + installPath = Json::objectValue; + installPath["from"] = fromPath; + installPath["to"] = toPath; + } + + return installPath; +} + Target::Target(cmGeneratorTarget* gt, std::string const& config) : GT(gt) , Config(config) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 900faf9c3fb..0d718a4e7c0 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -98,13 +98,90 @@ def _check(actual, expected): d = json.load(f) assert is_dict(d) - assert sorted(d.keys()) == ["backtraceGraph", "paths"] + assert sorted(d.keys()) == ["backtraceGraph", "installers", "paths"] assert is_string(d["paths"]["source"], actual["source"]) assert is_string(d["paths"]["build"], actual["build"]) check_backtrace_graph(d["backtraceGraph"]) + assert is_list(d["installers"]) + assert len(d["installers"]) == len(expected["installers"]) + for a, e in zip(d["installers"], expected["installers"]): + assert is_dict(a) + expected_keys = ["component", "type"] + + assert is_string(a["component"], e["component"]) + assert is_string(a["type"], e["type"]) + + if e["destination"] is not None: + expected_keys.append("destination") + assert is_string(a["destination"], e["destination"]) + + if e["paths"] is not None: + expected_keys.append("paths") + assert is_list(a["paths"]) + assert len(a["paths"]) == len(e["paths"]) + + for ap, ep in zip(a["paths"], e["paths"]): + if is_string(ep): + assert matches(ap, ep) + else: + assert is_dict(ap) + assert sorted(ap.keys()) == ["from", "to"] + assert matches(ap["from"], ep["from"]) + assert matches(ap["to"], ep["to"]) + + if e["isExcludeFromAll"] is not None: + expected_keys.append("isExcludeFromAll") + assert is_bool(a["isExcludeFromAll"], e["isExcludeFromAll"]) + + if e["isOptional"] is not None: + expected_keys.append("isOptional") + assert is_bool(a["isOptional"], e["isOptional"]) + + if e["targetId"] is not None: + expected_keys.append("targetId") + assert matches(a["targetId"], e["targetId"]) + + if e["targetIndex"] is not None: + expected_keys.append("targetIndex") + assert is_int(a["targetIndex"]) + assert c["targets"][a["targetIndex"]]["name"] == e["targetIndex"] + + if e["targetIsImportLibrary"] is not None: + expected_keys.append("targetIsImportLibrary") + assert is_bool(a["targetIsImportLibrary"], e["targetIsImportLibrary"]) + + if e["targetInstallNamelink"] is not None: + expected_keys.append("targetInstallNamelink") + assert is_string(a["targetInstallNamelink"], e["targetInstallNamelink"]) + + if e["exportName"] is not None: + expected_keys.append("exportName") + assert is_string(a["exportName"], e["exportName"]) + + if e["exportTargets"] is not None: + expected_keys.append("exportTargets") + assert is_list(a["exportTargets"]) + assert len(a["exportTargets"]) == len(e["exportTargets"]) + for at, et in zip(a["exportTargets"], e["exportTargets"]): + assert is_dict(at) + assert sorted(at.keys()) == ["id", "index"] + assert matches(at["id"], et["id"]) + assert is_int(at["index"]) + assert c["targets"][at["index"]]["name"] == et["index"] + + if e["scriptFile"] is not None: + expected_keys.append("scriptFile") + assert is_string(a["scriptFile"], e["scriptFile"]) + + if e["backtrace"] is not None: + expected_keys.append("backtrace") + check_backtrace(d, a["backtrace"], e["backtrace"]) + + assert sorted(a.keys()) == sorted(expected_keys) + return _check def check_backtrace_graph(btg): @@ -555,6 +632,20 @@ def gen_check_directories(c, g): for e in expected: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(ALL_BUILD|ZERO_CHECK)"), e["targetIds"]) + if sys.platform in ("win32", "cygwin", "msys") or "aix" in sys.platform: + for e in expected: + e["installers"] = list(filter(lambda i: i["targetInstallNamelink"] is None or i["targetInstallNamelink"] == "skip", e["installers"])) + for i in e["installers"]: + i["targetInstallNamelink"] = None + + if sys.platform not in ("win32", "cygwin", "msys"): + for e in expected: + e["installers"] = list(filter(lambda i: "_dllExtra" not in i or not i["_dllExtra"], e["installers"])) + if "aix" not in sys.platform: + for i in e["installers"]: + if "pathsNamelink" in i: + i["paths"] = i["pathsNamelink"] + return expected def check_directories(c, g): diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json index 9f0c48a0173..6514910a81e 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json @@ -11,5 +11,6 @@ ], "projectName": "Alias", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json index afd41f328ac..c89e4f9dd95 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json @@ -11,5 +11,6 @@ ], "projectName": "Custom", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json index a51b6eb8d67..7168306d320 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json @@ -17,5 +17,6 @@ ], "projectName": "Cxx", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json index afbd43a3e3b..8509f084c33 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json @@ -8,5 +8,6 @@ "targetIds": null, "projectName": "codemodel-v2", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json index 3737ad5febd..27184cd5e8c 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json @@ -6,5 +6,6 @@ "targetIds": null, "projectName": "codemodel-v2", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json index 0d3161c16a3..55dd57327e5 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json @@ -10,5 +10,69 @@ ], "projectName": "External", "minimumCMakeVersion": "3.12", - "hasInstallRule": true + "hasInstallRule": true, + "installers": [ + { + "component": "Unspecified", + "type": "directory", + "destination": "dir3", + "paths": [ + "^.*/Tests/RunCMake/FileAPIExternalSource/\\.$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": 15, + "command": "install", + "hasParent": true + }, + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "directory", + "destination": "dir4", + "paths": [ + "^.*/Tests/RunCMake/FileAPIExternalSource$" + ], + "isExcludeFromAll": true, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": 16, + "command": "install", + "hasParent": true + }, + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json index a41b79b5176..d1272740974 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json @@ -14,5 +14,6 @@ ], "projectName": "Imported", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json index b10d496059b..90664dc72e3 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json @@ -10,5 +10,6 @@ ], "projectName": "Interface", "minimumCMakeVersion": "3.12", - "hasInstallRule": null + "hasInstallRule": null, + "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json index 1e647ad1b35..ef2dd0b61bb 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json @@ -13,5 +13,69 @@ ], "projectName": "Object", "minimumCMakeVersion": "3.13", - "hasInstallRule": true + "hasInstallRule": true, + "installers": [ + { + "component": "Unspecified", + "type": "target", + "destination": "bin", + "paths": [ + "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?c_object_exe(\\.exe)?$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^c_object_exe::@5ed5358f70faf8d8af7a$", + "targetIndex": "c_object_exe", + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^object/CMakeLists\\.txt$", + "line": 13, + "command": "install", + "hasParent": true + }, + { + "file": "^object/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "target", + "destination": "bin", + "paths": [ + "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_object_exe(\\.exe)?$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^cxx_object_exe::@5ed5358f70faf8d8af7a$", + "targetIndex": "cxx_object_exe", + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^object/CMakeLists\\.txt$", + "line": 13, + "command": "install", + "hasParent": true + }, + { + "file": "^object/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json index 736d1f5a394..ce459472414 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json @@ -25,5 +25,549 @@ ], "projectName": "codemodel-v2", "minimumCMakeVersion": "3.12", - "hasInstallRule": true + "hasInstallRule": true, + "installers": [ + { + "component": "Tools", + "type": "target", + "destination": "bin", + "paths": [ + "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^cxx_exe::@a56b12a3f5c0529fb296$", + "targetIndex": "cxx_exe", + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 38, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "target", + "destination": "lib", + "paths": [ + "^((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(lib|dll\\.a)$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$", + "targetIndex": "c_shared_lib", + "targetIsImportLibrary": true, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "_dllExtra": true, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "target", + "destination": "lib", + "paths": [ + "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg)?c_shared_lib(-1)?\\.(dll|so)$" + ], + "pathsNamelink": [ + "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1\\.2\\.3|1\\.2\\.3\\.dylib)$", + "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1|1\\.dylib)$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$", + "targetIndex": "c_shared_lib", + "targetIsImportLibrary": null, + "targetInstallNamelink": "skip", + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "target", + "destination": "lib", + "paths": [ + "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?cxx_shared_lib\\.(lib|dll\\.a)$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$", + "targetIndex": "cxx_shared_lib", + "targetIsImportLibrary": true, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "_dllExtra": true, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "target", + "destination": "lib", + "paths": [ + "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg)?cxx_shared_lib\\.(dll|so|dylib)$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$", + "targetIndex": "cxx_shared_lib", + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 41, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "target", + "destination": "lib", + "paths": [ + "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(dll|so|dylib)$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$", + "targetIndex": "c_shared_lib", + "targetIsImportLibrary": null, + "targetInstallNamelink": "only", + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 46, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "file", + "destination": "include", + "paths": [ + { + "from": "^empty\\.h$", + "to": "^empty-renamed\\.h$" + } + ], + "isExcludeFromAll": null, + "isOptional": true, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 48, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "file", + "destination": "include", + "paths": [ + "^codemodel-v2\\.cmake$", + "^empty\\.h$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 49, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "directory", + "destination": "dir1", + "paths": [ + "^\\.$", + "^dir$", + { + "from": "^cxx$", + "to": "^\\.$" + } + ], + "isExcludeFromAll": null, + "isOptional": true, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 50, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "directory", + "destination": "dir2", + "paths": [ + { + "from": "^\\.$", + "to": "^FileAPI$" + }, + "^dir$", + { + "from": "^cxx$", + "to": "^\\.$" + } + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 51, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "export", + "destination": "lib/cmake/foo", + "paths": [ + "^CMakeFiles/Export/lib/cmake/foo/FooTargets\\.cmake$" + ], + "isExcludeFromAll": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": "FooTargets", + "exportTargets": [ + { + "id": "^cxx_exe::@a56b12a3f5c0529fb296$", + "index": "cxx_exe" + } + ], + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 52, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "script", + "destination": null, + "paths": null, + "isExcludeFromAll": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": "InstallScript.cmake", + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 53, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] } From ac4f83d98fd1c55e94736999d88effd50d2c0b64 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 17 Mar 2021 00:01:19 -0400 Subject: [PATCH 0142/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7c6d2847ce7..bea8efd2ec8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210316) +set(CMake_VERSION_PATCH 20210317) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 95c50da8af070999f5302ed19d807b59451d8c85 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Tue, 16 Mar 2021 13:19:21 +0000 Subject: [PATCH 0143/1519] Help: Document that CMAKE__FLAGS[_INIT] are strings Issue: #21944 --- Help/variable/CMAKE_LANG_FLAGS.rst | 3 +++ Help/variable/CMAKE_LANG_FLAGS_INIT.rst | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Help/variable/CMAKE_LANG_FLAGS.rst b/Help/variable/CMAKE_LANG_FLAGS.rst index 14b2694ef37..11864f8e7c0 100644 --- a/Help/variable/CMAKE_LANG_FLAGS.rst +++ b/Help/variable/CMAKE_LANG_FLAGS.rst @@ -15,3 +15,6 @@ This is initialized for each language from environment variables: Initialized by the :envvar:`CUDAFLAGS` environment variable. * ``CMAKE_Fortran_FLAGS``: Initialized by the :envvar:`FFLAGS` environment variable. + +This value is a command-line string fragment. Therefore, multiple options +should be separated by spaces, and options with spaces should be quoted. diff --git a/Help/variable/CMAKE_LANG_FLAGS_INIT.rst b/Help/variable/CMAKE_LANG_FLAGS_INIT.rst index 67ff2cb3eb0..ca13a29a059 100644 --- a/Help/variable/CMAKE_LANG_FLAGS_INIT.rst +++ b/Help/variable/CMAKE_LANG_FLAGS_INIT.rst @@ -12,6 +12,8 @@ the contents of a ``xxxFLAGS`` environment variable will be prepended, where ``xxx`` will be language-specific but not necessarily the same as ```` (e.g. :envvar:`CXXFLAGS` for ``CXX``, :envvar:`FFLAGS` for ``Fortran``, and so on). +This value is a command-line string fragment. Therefore, multiple options +should be separated by spaces, and options with spaces should be quoted. See also the configuration-specific :variable:`CMAKE__FLAGS__INIT` variable. From 256c320fb6aea90f6544bcefe8dbde497b40351f Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 12 Mar 2021 13:01:45 -0500 Subject: [PATCH 0144/1519] gitlab-ci: add variable for job to control its ctest build name --- .gitlab/ci/gitlab_ci.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab/ci/gitlab_ci.cmake b/.gitlab/ci/gitlab_ci.cmake index f863a279ce3..f1662158045 100644 --- a/.gitlab/ci/gitlab_ci.cmake +++ b/.gitlab/ci/gitlab_ci.cmake @@ -17,7 +17,11 @@ if ("$ENV{CMAKE_CONFIGURATION}" STREQUAL "") endif () # Set the build metadata. -set(CTEST_BUILD_NAME "$ENV{CI_PROJECT_NAME}-$ENV{CMAKE_CONFIGURATION}") +if(NOT "$ENV{CMAKE_CI_BUILD_NAME}" STREQUAL "") + set(CTEST_BUILD_NAME "$ENV{CI_PROJECT_NAME}-$ENV{CMAKE_CI_BUILD_NAME}") +else() + set(CTEST_BUILD_NAME "$ENV{CI_PROJECT_NAME}-$ENV{CMAKE_CONFIGURATION}") +endif() set(CTEST_SITE "gitlab-ci") set(ctest_model "Experimental") From 747940157f897bfaf875a85d30dad1f1902094b9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 12 Mar 2021 13:02:43 -0500 Subject: [PATCH 0145/1519] gitlab-ci: init environment with per-CMAKE_CONFIGURATION shell scripts --- .gitlab/ci/env.sh | 14 ++++++++++++++ .gitlab/os-linux.yml | 2 ++ 2 files changed, 16 insertions(+) create mode 100644 .gitlab/ci/env.sh diff --git a/.gitlab/ci/env.sh b/.gitlab/ci/env.sh new file mode 100644 index 00000000000..7634f5deeed --- /dev/null +++ b/.gitlab/ci/env.sh @@ -0,0 +1,14 @@ +quietly() { + readonly log="/tmp/quietly-$RANDOM.log" + if ! "$@" >"$log" 2>&1; then + ret=$? + cat "$log" + rm -f "$log" + exit $ret + fi + rm -f "$log" +} + +if test -r ".gitlab/ci/env_${CMAKE_CONFIGURATION}.sh"; then + source ".gitlab/ci/env_${CMAKE_CONFIGURATION}.sh" +fi diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index e40760e2668..7496e9e6da7 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -195,6 +195,7 @@ ## Linux-specific scripts .before_script_linux: &before_script_linux + - source .gitlab/ci/env.sh - .gitlab/ci/cmake.sh - .gitlab/ci/ninja.sh - export PATH=$PWD/.gitlab:$PWD/.gitlab/cmake/bin:$PATH @@ -251,6 +252,7 @@ stage: build script: + - source .gitlab/ci/env.sh # Bootstrap. - mkdir -p build/ # Exclude documentation. A job dependency provides it for packaging. From 402518904f08c2eb9b4bbcc58c70a2bc9884fb4b Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 15 Mar 2021 13:27:53 -0400 Subject: [PATCH 0146/1519] gitlab-ci: add rules to enable jobs only in a nightly pipeline schedule --- .gitlab/rules.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitlab/rules.yml b/.gitlab/rules.yml index b3e5342694b..568546398bf 100644 --- a/.gitlab/rules.yml +++ b/.gitlab/rules.yml @@ -6,6 +6,8 @@ when: never - if: '$CMAKE_CI_NIGHTLY == "true"' when: on_success + - if: '$CMAKE_CI_JOB_NIGHTLY == "true"' + when: never - if: '($CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != "" && $CI_COMMIT_BRANCH == $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH && $CMAKE_CI_JOB_CONTINUOUS == "true")' when: delayed start_in: 5 minutes @@ -24,6 +26,8 @@ when: never - if: '$CMAKE_CI_NIGHTLY == "true"' when: on_success + - if: '$CMAKE_CI_JOB_NIGHTLY == "true"' + when: never - if: '($CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != "" && $CI_COMMIT_BRANCH == $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH && $CMAKE_CI_JOB_CONTINUOUS == "true")' when: on_success - if: '($CMAKE_CI_NO_MR == "true" && $CI_MERGE_REQUEST_ID)' @@ -42,6 +46,8 @@ when: always - if: '$CMAKE_CI_NIGHTLY == "true"' when: on_success + - if: '$CMAKE_CI_JOB_NIGHTLY == "true"' + when: never - if: '($CMAKE_CI_NO_MR == "true" && $CI_MERGE_REQUEST_ID)' when: never - if: '$CI_MERGE_REQUEST_ID' From 5ea928d9d25cfd2bfea946bdd7c3ad3c92a63168 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 15 Mar 2021 13:34:16 -0400 Subject: [PATCH 0147/1519] gitlab-ci: factor out job dependencies on release-style binaries --- .gitlab-ci.yml | 20 ++++---------------- .gitlab/os-linux.yml | 12 ++++++++++++ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8e76e41d66e..e2e8331b0d1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -115,10 +115,7 @@ test:debian10-ninja: - .cmake_test_linux_release - .linux_builder_tags_qt - .run_dependent - dependencies: - - build:centos6-x86_64 - needs: - - build:centos6-x86_64 + - .needs_centos6_x86_64 test:debian10-aarch64-ninja: extends: @@ -126,10 +123,7 @@ test:debian10-aarch64-ninja: - .cmake_test_linux_release - .linux_builder_tags_aarch64_qt - .run_dependent - dependencies: - - build:centos7-aarch64 - needs: - - build:centos7-aarch64 + - .needs_centos7_aarch64 variables: CMAKE_CI_NO_MR: "true" @@ -139,10 +133,7 @@ test:fedora33-makefiles: - .cmake_test_linux_release - .linux_builder_tags_qt - .run_dependent - dependencies: - - build:centos6-x86_64 - needs: - - build:centos6-x86_64 + - .needs_centos6_x86_64 test:cuda10.2-nvidia: extends: @@ -150,10 +141,7 @@ test:cuda10.2-nvidia: - .cmake_test_linux_release - .linux_builder_tags_cuda - .run_dependent - dependencies: - - build:centos6-x86_64 - needs: - - build:centos6-x86_64 + - .needs_centos6_x86_64 build:fedora33-ninja: extends: diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 7496e9e6da7..786e2935246 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -30,6 +30,18 @@ variables: BOOTSTRAP_ARGS: '-- "-DCMake_DOC_ARTIFACT_PREFIX=$CI_PROJECT_DIR/build/install-doc"' +.needs_centos6_x86_64: + dependencies: + - build:centos6-x86_64 + needs: + - build:centos6-x86_64 + +.needs_centos7_aarch64: + dependencies: + - build:centos7-aarch64 + needs: + - build:centos7-aarch64 + ### Debian .debian10: From c07683331052bf5bd29788a73563930dd5ff2349 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 15 Mar 2021 13:37:23 -0400 Subject: [PATCH 0148/1519] gitlab-ci: add jobs testing Intel Classic compilers on Linux --- .gitlab-ci.yml | 189 ++++++++++++++++++ .../ci/configure_intelclassic_makefiles.cmake | 1 + .gitlab/ci/env_intelclassic_common.sh | 9 + .gitlab/ci/env_intelclassic_makefiles.sh | 1 + .gitlab/ci/env_intelcompiler_license.sh | 8 + .gitlab/os-linux.yml | 25 +++ 6 files changed, 233 insertions(+) create mode 100644 .gitlab/ci/configure_intelclassic_makefiles.cmake create mode 100644 .gitlab/ci/env_intelclassic_common.sh create mode 100644 .gitlab/ci/env_intelclassic_makefiles.sh create mode 100644 .gitlab/ci/env_intelcompiler_license.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e2e8331b0d1..b5e3fb0cc8c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -174,6 +174,195 @@ test:fedora33-ninja-multi: needs: - test:fedora33-ninja +test:intel2016-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2016_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016-centos7 + +test:intel2016u1-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2016u1_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u1-centos7 + +test:intel2016u2-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2016u2_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u2-centos7 + +test:intel2017-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017-centos7 + +test:intel2017u1-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u1_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u1-centos7 + +test:intel2017u2-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u2_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u2-centos7 + +test:intel2017u3-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u3_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u3-centos7 + +test:intel2017u4-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u4_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u4-centos7 + +test:intel2017u5-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u5_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u5-centos7 + +test:intel2017u6-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u6_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u6-centos7 + +test:intel2017u7-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u7_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u7-centos7 + +test:intel2017u8-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2017u8_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u8-centos7 + +test:intel2018-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2018_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018-centos7 + +test:intel2018u1-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2018u1_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u1-centos7 + +test:intel2018u2-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2018u2_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u2-centos7 + +test:intel2018u3-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2018u3_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u3-centos7 + +test:intel2018u4-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2018u4_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u4-centos7 + +test:intel2019-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2019_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019-centos7 + +test:intel2019u1-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2019u1_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u1-centos7 + +test:intel2019u2-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2019u2_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u2-centos7 + +test:intel2019u3-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2019u3_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u3-centos7 + +test:intel2019u4-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2019u4_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u4-centos7 + +test:intel2020-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2020_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020-rhel8 + +test:intel2020u2-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2020u2_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u2-rhel8 + +test:intel2020u4-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2020u4_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u4-rhel8 + +test: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-rhel8 + +test: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-rhel8 + build:linux-x86_64-package: extends: - .linux_package diff --git a/.gitlab/ci/configure_intelclassic_makefiles.cmake b/.gitlab/ci/configure_intelclassic_makefiles.cmake new file mode 100644 index 00000000000..20863a2fb08 --- /dev/null +++ b/.gitlab/ci/configure_intelclassic_makefiles.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/env_intelclassic_common.sh b/.gitlab/ci/env_intelclassic_common.sh new file mode 100644 index 00000000000..22b1d03ba3e --- /dev/null +++ b/.gitlab/ci/env_intelclassic_common.sh @@ -0,0 +1,9 @@ +source .gitlab/ci/env_intelcompiler_license.sh + +if test -r /opt/intel/oneapi/setvars.sh; then + source /opt/intel/oneapi/setvars.sh +elif test -r /opt/intel/bin/compilervars.sh; then + source /opt/intel/bin/compilervars.sh intel64 +fi + +export CC=icc CXX=icpc FC=ifort diff --git a/.gitlab/ci/env_intelclassic_makefiles.sh b/.gitlab/ci/env_intelclassic_makefiles.sh new file mode 100644 index 00000000000..d1ff85e0c54 --- /dev/null +++ b/.gitlab/ci/env_intelclassic_makefiles.sh @@ -0,0 +1 @@ +source .gitlab/ci/env_intelclassic_common.sh diff --git a/.gitlab/ci/env_intelcompiler_license.sh b/.gitlab/ci/env_intelcompiler_license.sh new file mode 100644 index 00000000000..54743b28e2e --- /dev/null +++ b/.gitlab/ci/env_intelcompiler_license.sh @@ -0,0 +1,8 @@ +if test -n "$CMAKE_CI_INTELCOMPILER_LICENSE"; then + if test -d /opt/intel/licenses; then + mv "$CMAKE_CI_INTELCOMPILER_LICENSE" /opt/intel/licenses/ci.lic + else + rm "$CMAKE_CI_INTELCOMPILER_LICENSE" + fi + unset CMAKE_CI_INTELCOMPILER_LICENSE +fi diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 786e2935246..158f1078ea3 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -140,6 +140,21 @@ CTEST_NO_WARNINGS_ALLOWED: 1 CMAKE_GENERATOR: "Unix Makefiles" +### Intel Compiler + +.intelcompiler: + image: "kitware/intelcompiler:$CMAKE_CI_INTELCOMPILER_IMAGE_TAG" + environment: + name: intel-compiler + variables: + CMAKE_ARCH: x86_64 + +.intelclassic_makefiles: + extends: .intelcompiler + variables: + CMAKE_CONFIGURATION: intelclassic_makefiles + CMAKE_GENERATOR: "Unix Makefiles" + ### CUDA builds .cuda10.2: @@ -327,3 +342,13 @@ - sccache --show-stats interruptible: true + +.cmake_test_linux_intelclassic_makefiles: + extends: + - .intelclassic_makefiles + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_manually + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" From 1610c0f0345959e388a7b106969e972889815ec6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 15 Mar 2021 14:52:25 -0400 Subject: [PATCH 0149/1519] gitlab-ci: add jobs testing Intel oneAPI compilers on Linux --- .gitlab-ci.yml | 14 ++++++++++++++ .gitlab/ci/configure_inteloneapi_makefiles.cmake | 1 + .gitlab/ci/env_inteloneapi_common.sh | 7 +++++++ .gitlab/ci/env_inteloneapi_makefiles.sh | 1 + .gitlab/os-linux.yml | 16 ++++++++++++++++ 5 files changed, 39 insertions(+) create mode 100644 .gitlab/ci/configure_inteloneapi_makefiles.cmake create mode 100644 .gitlab/ci/env_inteloneapi_common.sh create mode 100644 .gitlab/ci/env_inteloneapi_makefiles.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b5e3fb0cc8c..9f996e8772b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -363,6 +363,20 @@ test:intel2021.1.2-makefiles: CMAKE_CI_BUILD_NAME: intel2021.1.2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-rhel8 +test: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-rhel8 + +test: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-rhel8 + build:linux-x86_64-package: extends: - .linux_package diff --git a/.gitlab/ci/configure_inteloneapi_makefiles.cmake b/.gitlab/ci/configure_inteloneapi_makefiles.cmake new file mode 100644 index 00000000000..20863a2fb08 --- /dev/null +++ b/.gitlab/ci/configure_inteloneapi_makefiles.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/env_inteloneapi_common.sh b/.gitlab/ci/env_inteloneapi_common.sh new file mode 100644 index 00000000000..beaf3feee9d --- /dev/null +++ b/.gitlab/ci/env_inteloneapi_common.sh @@ -0,0 +1,7 @@ +source .gitlab/ci/env_intelcompiler_license.sh + +if test -r /opt/intel/oneapi/setvars.sh; then + source /opt/intel/oneapi/setvars.sh +fi + +export CC=icx CXX=icpx FC=ifx diff --git a/.gitlab/ci/env_inteloneapi_makefiles.sh b/.gitlab/ci/env_inteloneapi_makefiles.sh new file mode 100644 index 00000000000..eefcddaeddc --- /dev/null +++ b/.gitlab/ci/env_inteloneapi_makefiles.sh @@ -0,0 +1 @@ +source .gitlab/ci/env_inteloneapi_common.sh diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 158f1078ea3..0229bc03dc7 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -155,6 +155,12 @@ CMAKE_CONFIGURATION: intelclassic_makefiles CMAKE_GENERATOR: "Unix Makefiles" +.inteloneapi_makefiles: + extends: .intelcompiler + variables: + CMAKE_CONFIGURATION: inteloneapi_makefiles + CMAKE_GENERATOR: "Unix Makefiles" + ### CUDA builds .cuda10.2: @@ -352,3 +358,13 @@ - .needs_centos6_x86_64 variables: CMAKE_CI_JOB_NIGHTLY: "true" + +.cmake_test_linux_inteloneapi_makefiles: + extends: + - .inteloneapi_makefiles + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_manually + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" From 56c759b000ab5041aff9a92d51a6cc471e7d34a4 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 13 Mar 2021 15:37:19 +0200 Subject: [PATCH 0150/1519] Per-language Win32/Console flags Allows using different compilers with different flags for different languages. For example Clang with GNU-like commandline for CXX and MSVC as host compiler for CUDA. Should help with #21914. --- Modules/Platform/CYGWIN-GNU.cmake | 2 +- Modules/Platform/Windows-Clang.cmake | 4 ++-- Modules/Platform/Windows-Embarcadero.cmake | 8 +++----- Modules/Platform/Windows-GNU.cmake | 2 +- Modules/Platform/Windows-MSVC.cmake | 12 ++++++++---- Modules/Platform/Windows-OpenWatcom-C.cmake | 1 + Modules/Platform/Windows-OpenWatcom-CXX.cmake | 1 + Modules/Platform/Windows-OpenWatcom.cmake | 7 +++++-- Modules/Platform/Windows-df.cmake | 4 ++-- Source/cmLocalGenerator.cxx | 8 ++++---- Source/cmMakefileExecutableTargetGenerator.cxx | 7 +++++-- Tests/Fortran/CMakeLists.txt | 2 +- 12 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake index 4fa14cea6e0..b81bd4d2be7 100644 --- a/Modules/Platform/CYGWIN-GNU.cmake +++ b/Modules/Platform/CYGWIN-GNU.cmake @@ -10,7 +10,6 @@ set(__CYGWIN_COMPILER_GNU 1) # TODO: Is -Wl,--enable-auto-import now always default? string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,--enable-auto-import") -set(CMAKE_CREATE_WIN32_EXE "-mwindows") set(CMAKE_GNULD_IMAGE_VERSION "-Wl,--major-image-version,,--minor-image-version,") @@ -23,6 +22,7 @@ macro(__cygwin_compiler_gnu lang) " -o -Wl,--out-implib, ${CMAKE_GNULD_IMAGE_VERSION} ") set(CMAKE_${lang}_LINK_EXECUTABLE " -o -Wl,--out-implib, ${CMAKE_GNULD_IMAGE_VERSION} ") + set(CMAKE_${lang}_CREATE_WIN32_EXE "-mwindows") # No -fPIC on cygwin set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "") diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index c508ac1a590..7365ff58971 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -71,8 +71,8 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_LINK_EXECUTABLE " -fuse-ld=lld-link -nostartfiles -nostdlib -o -Xlinker /implib: -Xlinker /pdb: -Xlinker /version:. ${CMAKE_GNULD_IMAGE_VERSION} ") - set(CMAKE_CREATE_WIN32_EXE "-Xlinker /subsystem:windows") - set(CMAKE_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console") + set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows") + set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console") if(NOT "${lang}" STREQUAL "ASM") set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -Xclang -flto-visibility-public-std -D_MT -Xclang --dependent-lib=libcmt) diff --git a/Modules/Platform/Windows-Embarcadero.cmake b/Modules/Platform/Windows-Embarcadero.cmake index 8f1d02430ac..4ecc2c2c973 100644 --- a/Modules/Platform/Windows-Embarcadero.cmake +++ b/Modules/Platform/Windows-Embarcadero.cmake @@ -51,11 +51,6 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES "-bcc.lib" ".lib") # Borland cannot handle + in the file name, so mangle object file name set (CMAKE_MANGLE_OBJECT_FILE_NAMES "ON") -# extra flags for a win32 exe -set(CMAKE_CREATE_WIN32_EXE "${_tW}" ) -# extra flags for a console app -set(CMAKE_CREATE_CONSOLE_EXE "${_tC}" ) - set (CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel.") @@ -124,6 +119,9 @@ macro(__embarcadero_language lang) "tlib ${CMAKE_START_TEMP_FILE}/p512 /a ${CMAKE_END_TEMP_FILE}" ) + set(CMAKE_${lang}_CREATE_WIN32_EXE "${_tW}") + set(CMAKE_${lang}_CREATE_CONSOLE_EXE "${_tC}") + # Precompile Headers if (EMBARCADERO) set(CMAKE_PCH_EXTENSION .pch) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index a2e3811dd8e..e50c2150805 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -35,7 +35,6 @@ set(CMAKE_LIBRARY_PATH_FLAG "-L") set(CMAKE_LINK_LIBRARY_FLAG "-l") set(CMAKE_LINK_DEF_FILE_FLAG "") # Empty string: passing the file is enough set(CMAKE_LINK_LIBRARY_SUFFIX "") -set(CMAKE_CREATE_WIN32_EXE "-mwindows") set(CMAKE_GNULD_IMAGE_VERSION "-Wl,--major-image-version,,--minor-image-version,") @@ -105,6 +104,7 @@ macro(__windows_compiler_gnu lang) " -o -Wl,--out-implib, ${CMAKE_GNULD_IMAGE_VERSION} ") set(CMAKE_${lang}_LINK_EXECUTABLE " -o -Wl,--out-implib, ${CMAKE_GNULD_IMAGE_VERSION} ") + set(CMAKE_${lang}_CREATE_WIN32_EXE "-mwindows") list(APPEND CMAKE_${lang}_ABI_FILES "Platform/Windows-GNU-${lang}-ABI") diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index e384af4565c..4223bde8cfd 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -27,12 +27,8 @@ else() endif() if(CMAKE_SYSTEM_NAME STREQUAL "WindowsCE") - set(CMAKE_CREATE_WIN32_EXE "/entry:WinMainCRTStartup") - set(CMAKE_CREATE_CONSOLE_EXE "/entry:mainACRTStartup") set(_PLATFORM_LINK_FLAGS " /subsystem:windowsce") else() - set(CMAKE_CREATE_WIN32_EXE "/subsystem:windows") - set(CMAKE_CREATE_CONSOLE_EXE "/subsystem:console") set(_PLATFORM_LINK_FLAGS "") endif() @@ -351,6 +347,14 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_LINK_EXECUTABLE "${_CMAKE_VS_LINK_EXE} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /version:.${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}") + if(CMAKE_SYSTEM_NAME STREQUAL "WindowsCE") + set(CMAKE_${lang}_CREATE_WIN32_EXE "/entry:WinMainCRTStartup") + set(CMAKE_${lang}_CREATE_CONSOLE_EXE "/entry:mainACRTStartup") + else() + set(CMAKE_${lang}_CREATE_WIN32_EXE "/subsystem:windows") + set(CMAKE_${lang}_CREATE_CONSOLE_EXE "/subsystem:console") + endif() + set(CMAKE_PCH_EXTENSION .pch) set(CMAKE_LINK_PCH ON) if (CMAKE_${lang}_COMPILER_ID STREQUAL "Clang") diff --git a/Modules/Platform/Windows-OpenWatcom-C.cmake b/Modules/Platform/Windows-OpenWatcom-C.cmake index ce9bc453299..b82a4cb2361 100644 --- a/Modules/Platform/Windows-OpenWatcom-C.cmake +++ b/Modules/Platform/Windows-OpenWatcom-C.cmake @@ -1 +1,2 @@ include(Platform/Windows-OpenWatcom) +__windows_open_watcom(C) diff --git a/Modules/Platform/Windows-OpenWatcom-CXX.cmake b/Modules/Platform/Windows-OpenWatcom-CXX.cmake index ce9bc453299..ac90d280bc6 100644 --- a/Modules/Platform/Windows-OpenWatcom-CXX.cmake +++ b/Modules/Platform/Windows-OpenWatcom-CXX.cmake @@ -1 +1,2 @@ include(Platform/Windows-OpenWatcom) +__windows_open_watcom(CXX) diff --git a/Modules/Platform/Windows-OpenWatcom.cmake b/Modules/Platform/Windows-OpenWatcom.cmake index 70055da95ec..19bcb97076b 100644 --- a/Modules/Platform/Windows-OpenWatcom.cmake +++ b/Modules/Platform/Windows-OpenWatcom.cmake @@ -6,8 +6,6 @@ include_guard() set(CMAKE_BUILD_TYPE_INIT Debug) -set(CMAKE_CREATE_WIN32_EXE "system nt_win" ) -set(CMAKE_CREATE_CONSOLE_EXE "system nt" ) string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " system nt_dll") string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " system nt_dll") @@ -30,3 +28,8 @@ if(CMAKE_CROSSCOMPILING) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES $ENV{WATCOM}/h $ENV{WATCOM}/h/nt) endif() endif() + +macro(__windows_open_watcom lang) + set(CMAKE_${lang}_CREATE_WIN32_EXE "system nt_win") + set(CMAKE_${lang}_CREATE_CONSOLE_EXE "system nt") +endmacro() diff --git a/Modules/Platform/Windows-df.cmake b/Modules/Platform/Windows-df.cmake index 8b824bc45db..c823423a095 100644 --- a/Modules/Platform/Windows-df.cmake +++ b/Modules/Platform/Windows-df.cmake @@ -27,8 +27,8 @@ set(CMAKE_Fortran_COMPILE_OBJECT set(CMAKE_Fortran_LINK_EXECUTABLE " ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /exe: /link ${CMAKE_END_TEMP_FILE}") -set(CMAKE_CREATE_WIN32_EXE /winapp) -set(CMAKE_CREATE_CONSOLE_EXE ) +set(CMAKE_Fortran_CREATE_WIN32_EXE /winapp) +set(CMAKE_Fortran_CREATE_CONSOLE_EXE ) # does the compiler support pdbtype and is it the newer compiler diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 79d1de04e57..b301c6e94a0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1527,12 +1527,12 @@ void cmLocalGenerator::GetTargetFlags( } if (target->IsWin32Executable(config)) { - exeFlags += - this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); + exeFlags += this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE")); exeFlags += " "; } else { - exeFlags += - this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"); + exeFlags += this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE")); exeFlags += " "; } diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 1750e37addc..6783341095d 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -384,11 +384,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) if (this->GeneratorTarget->IsWin32Executable( this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) { this->LocalGenerator->AppendFlags( - linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE")); + linkFlags, + this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE"))); } else { this->LocalGenerator->AppendFlags( linkFlags, - this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE")); + this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_CREATE_CONSOLE_EXE"))); } // Add symbol export flags if necessary. diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt index 18688923fb0..c1476be3883 100644 --- a/Tests/Fortran/CMakeLists.txt +++ b/Tests/Fortran/CMakeLists.txt @@ -131,7 +131,7 @@ else() # as a language, cmake needs language specific versions # of these variables.... if(WIN32 AND CMAKE_Fortran_COMPILER_ID MATCHES "GNU") - set(CMAKE_CREATE_CONSOLE_EXE ) + set(CMAKE_Fortran_CREATE_CONSOLE_EXE ) set(CMAKE_LIBRARY_PATH_FLAG "-L") set(CMAKE_LINK_LIBRARY_FLAG "-l") set(CMAKE_LINK_LIBRARY_SUFFIX ) From dd952f28e9e2a3687dc9b666886d0fea0c764bbb Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 18 Mar 2021 00:01:15 -0400 Subject: [PATCH 0151/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bea8efd2ec8..163224cd597 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210317) +set(CMake_VERSION_PATCH 20210318) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From fae7910268ca132c3eee28f8fbae9eb29516b5cc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Mar 2021 01:04:02 +0100 Subject: [PATCH 0152/1519] Help: Fix typos in presets schema field descriptions --- Help/manual/presets/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index c29d6865273..e2b1d95c48a 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -19,7 +19,7 @@ "properties": { "version": { "const": 2, - "description": "A requVired integer representing the version of the JSON schema." + "description": "A required integer representing the version of the JSON schema." }, "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, "vendor": { "$ref": "#/definitions/vendor" }, From 52d3d1bdc5c099209d02e44130d352df55ffc9a0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 18 Mar 2021 10:39:41 -0400 Subject: [PATCH 0153/1519] FindDevIL: Format documentation of provided variables --- Modules/FindDevIL.cmake | 43 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake index 998494365b4..e01cdcd15b1 100644 --- a/Modules/FindDevIL.cmake +++ b/Modules/FindDevIL.cmake @@ -12,24 +12,31 @@ http://openil.sourceforge.net/ This module sets: -:: - - IL_LIBRARIES - the name of the IL library. These include the full path to - the core DevIL library. This one has to be linked into the - application. - ILU_LIBRARIES - the name of the ILU library. Again, the full path. This - library is for filters and effects, not actual loading. It - doesn't have to be linked if the functionality it provides - is not used. - ILUT_LIBRARIES - the name of the ILUT library. Full path. This part of the - library interfaces with OpenGL. It is not strictly needed - in applications. - IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files. - DevIL_FOUND - this is set to TRUE if all the above variables were set. - This will be set to false if ILU or ILUT are not found, - even if they are not needed. In most systems, if one - library is found all the others are as well. That's the - way the DevIL developers release it. +``IL_LIBRARIES`` + The name of the IL library. These include the full path to + the core DevIL library. This one has to be linked into the + application. + +``ILU_LIBRARIES`` + The name of the ILU library. Again, the full path. This + library is for filters and effects, not actual loading. It + doesn't have to be linked if the functionality it provides + is not used. + +``ILUT_LIBRARIES`` + The name of the ILUT library. Full path. This part of the + library interfaces with OpenGL. It is not strictly needed + in applications. + +``IL_INCLUDE_DIR`` + where to find the il.h, ilu.h and ilut.h files. + +``DevIL_FOUND`` + This is set to TRUE if all the above variables were set. + This will be set to false if ILU or ILUT are not found, + even if they are not needed. In most systems, if one + library is found all the others are as well. That's the + way the DevIL developers release it. #]=======================================================================] # TODO: Add version support. From 73b27f6ae8c9599c9cfea13d8b3413837355ec8a Mon Sep 17 00:00:00 2001 From: Alex <10857-leha-bot@users.noreply.gitlab.kitware.com> Date: Mon, 8 Mar 2021 21:11:09 +0300 Subject: [PATCH 0154/1519] FindDevIL: add imported targets and tests Fixes: #21900 --- .../dev/FindDevIL-imported-targets.rst | 4 ++ Modules/FindDevIL.cmake | 57 +++++++++++++++++++ Tests/CMakeLists.txt | 1 + Tests/FindDevIL/CMakeLists.txt | 10 ++++ Tests/FindDevIL/Test/CMakeLists.txt | 29 ++++++++++ Tests/FindDevIL/Test/main.c | 10 ++++ Tests/FindDevIL/Test/main_ilu.c | 8 +++ 7 files changed, 119 insertions(+) create mode 100644 Help/release/dev/FindDevIL-imported-targets.rst create mode 100644 Tests/FindDevIL/CMakeLists.txt create mode 100644 Tests/FindDevIL/Test/CMakeLists.txt create mode 100644 Tests/FindDevIL/Test/main.c create mode 100644 Tests/FindDevIL/Test/main_ilu.c diff --git a/Help/release/dev/FindDevIL-imported-targets.rst b/Help/release/dev/FindDevIL-imported-targets.rst new file mode 100644 index 00000000000..aa0929ea0fa --- /dev/null +++ b/Help/release/dev/FindDevIL-imported-targets.rst @@ -0,0 +1,4 @@ +FindDevIL +--------- + +* The :module:`FindDevIL` module now provides imported targets. diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake index e01cdcd15b1..c8e5e315492 100644 --- a/Modules/FindDevIL.cmake +++ b/Modules/FindDevIL.cmake @@ -10,6 +10,25 @@ FindDevIL This module locates the developer's image library. http://openil.sourceforge.net/ +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.21 + +This module defines the :prop_tgt:`IMPORTED` targets: + +``DevIL::IL`` + Defined if the system has DevIL. + +``DevIL::ILU`` + Defined if the system has DevIL Utilities. + +``DevIL::ILUT`` + Defined if the system has DevIL Utility Toolkit. + +Result Variables +^^^^^^^^^^^^^^^^ + This module sets: ``IL_LIBRARIES`` @@ -37,6 +56,11 @@ This module sets: even if they are not needed. In most systems, if one library is found all the others are as well. That's the way the DevIL developers release it. + +``DevIL_ILUT_FOUND`` + .. versionadded:: 3.21 + + This is set to TRUE if the ILUT library is found. #]=======================================================================] # TODO: Add version support. @@ -80,3 +104,36 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(DevIL DEFAULT_MSG IL_INCLUDE_DIR) # provide legacy variable for compatibility set(IL_FOUND ${DevIL_FOUND}) + +# create imported targets ONLY if we found DevIL. +if(DevIL_FOUND) + # Report the ILUT found if ILUT_LIBRARIES contains valid path. + if (ILUT_LIBRARIES) + set(DevIL_ILUT_FOUND TRUE) + else() + set(DevIL_ILUT_FOUND FALSE) + endif() + + if(NOT TARGET DevIL::IL) + add_library(DevIL::IL UNKNOWN IMPORTED) + set_target_properties(DevIL::IL PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${IL_INCLUDE_DIR}" + IMPORTED_LOCATION "${IL_LIBRARIES}") + endif() + + # DevIL Utilities target + if(NOT TARGET DevIL::ILU) + add_library(DevIL::ILU UNKNOWN IMPORTED) + set_target_properties(DevIL::ILU PROPERTIES + IMPORTED_LOCATION "${ILU_LIBRARIES}") + target_link_libraries(DevIL::ILU INTERFACE DevIL::IL) + endif() + + # ILUT (if found) + if(NOT TARGET DevIL::ILUT AND DevIL_ILUT_FOUND) + add_library(DevIL::ILUT UNKNOWN IMPORTED) + set_target_properties(DevIL::ILUT PROPERTIES + IMPORTED_LOCATION "${ILUT_LIBRARIES}") + target_link_libraries(DevIL::ILUT INTERFACE DevIL::ILU) + endif() +endif() diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 0430afb77fc..e532acef3ac 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1424,6 +1424,7 @@ if(BUILD_TESTING) CURL Cups Doxygen + DevIL EnvModules EXPAT Fontconfig diff --git a/Tests/FindDevIL/CMakeLists.txt b/Tests/FindDevIL/CMakeLists.txt new file mode 100644 index 00000000000..d37d50faf57 --- /dev/null +++ b/Tests/FindDevIL/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindDevIL.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindDevIL/Test" + "${CMake_BINARY_DIR}/Tests/FindDevIL/Test" + ${build_generator_args} + --build-project TestFindDevIL + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/FindDevIL/Test/CMakeLists.txt b/Tests/FindDevIL/Test/CMakeLists.txt new file mode 100644 index 00000000000..c2c132223e6 --- /dev/null +++ b/Tests/FindDevIL/Test/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.1) +project(TestFindDevIL C) +include(CTest) + +find_package(DevIL) + +#FIXME: check version too. +# add_definitions( +# -DCMAKE_EXPECTED_SDL_VERSION_MAJOR=${SDL_VERSION_MAJOR} +# -DCMAKE_EXPECTED_SDL_VERSION_MINOR=${SDL_VERSION_MINOR} +# -DCMAKE_EXPECTED_SDL_VERSION_PATCH=${SDL_VERSION_PATCH}) + +add_executable(test_devil_var main.c) +target_include_directories(test_devil_var PRIVATE ${IL_INCLUDE_DIRS}) +target_link_libraries(test_devil_var PRIVATE ${IL_LIBRARIES}) +add_test(NAME test_devil_var COMMAND test_devil_var) + +add_executable(test_devil_il_tgt main.c) +target_link_libraries(test_devil_il_tgt DevIL::IL) +add_test(NAME test_devil_il_tgt COMMAND test_devil_il_tgt) + +add_executable(test_devil_ilu_tgt main_ilu.c) +target_link_libraries(test_devil_ilu_tgt DevIL::ILU) + +add_executable(test_devil_ilu_var main_ilu.c) +target_include_directories(test_devil_ilu_var PRIVATE ${IL_INCLUDE_DIRS} ${ILU_INCLUDE_DIRS}) +target_link_libraries(test_devil_ilu_var ${IL_LIBRARIES} ${ILU_LIBRARIES}) + +#FIXME: Check DevIL::ILUT target diff --git a/Tests/FindDevIL/Test/main.c b/Tests/FindDevIL/Test/main.c new file mode 100644 index 00000000000..4a070872007 --- /dev/null +++ b/Tests/FindDevIL/Test/main.c @@ -0,0 +1,10 @@ +#include + +int main() +{ + // Test 1 requires to link to the library. + ilInit(); + + ilShutDown(); + return 0; +} diff --git a/Tests/FindDevIL/Test/main_ilu.c b/Tests/FindDevIL/Test/main_ilu.c new file mode 100644 index 00000000000..a9e7819ba62 --- /dev/null +++ b/Tests/FindDevIL/Test/main_ilu.c @@ -0,0 +1,8 @@ +#include + +int main() +{ + // IL Utilities requires only initialization. + // Unlike main DevIL there are no shutdown function. + iluInit(); +} From c73b847b0311a0eff0eeaa113991bce0149532a7 Mon Sep 17 00:00:00 2001 From: Marcel Ritzschke Date: Sun, 14 Mar 2021 18:14:19 +0100 Subject: [PATCH 0155/1519] VS: switch to new folder structure while keeping the old one working Fixes: #21170 --- ...KE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst | 13 +++++---- Modules/CMakeDetermineCompilerId.cmake | 16 ++++++++--- Source/cmGlobalVisualStudio10Generator.cxx | 27 +++++++++++++++++-- Source/cmGlobalVisualStudio10Generator.h | 9 +++++++ Source/cmVisualStudio10TargetGenerator.cxx | 12 +++++---- .../GeneratorToolset/RunCMakeTest.cmake | 6 ++++- .../TestToolsetCudaPathOnly-stderr.txt | 4 +-- ...estToolsetCudaPathOnlyOldLayout-result.txt | 1 + ...estToolsetCudaPathOnlyOldLayout-stderr.txt | 12 +++++++++ .../TestToolsetCudaPathOnlyOldLayout.cmake | 1 + 10 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst index 74db6b143f0..a19e7e148d8 100644 --- a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst +++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR.rst @@ -9,10 +9,9 @@ The :ref:`Visual Studio Generators` for VS 2010 and above support using a standalone (non-installed) NVIDIA CUDA toolkit. The path may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of the form ``cuda=C:\path\to\cuda``. The given directory must at least -contain a folder ``.\nvcc`` and must provide Visual Studio integration -files in path ``.\CUDAVisualStudioIntegration\extras\ -visual_studio_integration\MSBuildExtensions\``. One can create a standalone -CUDA toolkit directory by either opening a installer with 7zip or -copying the files that are extracted by the running installer. -The value may be empty if no path to a standalone CUDA Toolkit was -specified. +contain the nvcc compiler in path ``.\bin`` and must provide Visual Studio +integration files in path ``.\extras\visual_studio_integration\ +MSBuildExtensions\``. One can create a standalone CUDA toolkit directory by +either opening a installer with 7zip or copying the files that are extracted +by the running installer. The value may be empty if no path to a standalone +CUDA Toolkit was specified. diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 1595cfd73ce..f406e5ae005 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -452,9 +452,19 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} set(id_ItemDefinitionGroup_entry "${cuda_target}%(AdditionalOptions)-v${cuda_codegen}") set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]]) if(CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR) - set(id_CudaToolkitCustomDir "${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc") - string(CONCAT id_Import_props "") - string(CONCAT id_Import_targets "") + # check for legacy cuda custom toolkit folder structure + if(EXISTS ${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc) + set(id_CudaToolkitCustomDir "${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}nvcc") + else() + set(id_CudaToolkitCustomDir "${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}") + endif() + if(EXISTS ${CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR}CUDAVisualStudioIntegration) + string(CONCAT id_Import_props "") + string(CONCAT id_Import_targets "") + else() + string(CONCAT id_Import_props "") + string(CONCAT id_Import_targets "") + endif() else() string(CONCAT id_Import_props [[]]) string(CONCAT id_Import_targets [[]]) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 74d813554bb..d33c763a558 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -263,8 +263,8 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( bcDir = this->VCTargetsPath + "/BuildCustomizations"; } else { bcDir = this->GetPlatformToolsetCudaCustomDirString() + - "CUDAVisualStudioIntegration\\extras\\" - "visual_studio_integration\\MSBuildExtensions"; + this->GetPlatformToolsetCudaVSIntegrationSubdirString() + + "extras\\visual_studio_integration\\MSBuildExtensions"; cmSystemTools::ConvertToUnixSlashes(bcDir); } cmsys::Glob gl; @@ -470,6 +470,17 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( if (this->GeneratorToolsetCudaCustomDir.back() != '\\') { this->GeneratorToolsetCudaCustomDir.push_back('\\'); } + /* check for legacy toolkit folder structure */ + if (cmsys::SystemTools::FileIsDirectory( + cmStrCat(this->GeneratorToolsetCudaCustomDir, "nvcc"))) { + this->GeneratorToolsetCudaNvccSubdir = "nvcc\\"; + } + if (cmsys::SystemTools::FileIsDirectory( + cmStrCat(this->GeneratorToolsetCudaCustomDir, + "CUDAVisualStudioIntegration"))) { + this->GeneratorToolsetCudaVSIntegrationSubdir = + "CUDAVisualStudioIntegration\\"; + } } else { this->GeneratorToolsetCuda = value; } @@ -787,6 +798,18 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const return this->GeneratorToolsetCudaCustomDir; } +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaNvccSubdirString() const +{ + return this->GeneratorToolsetCudaNvccSubdir; +} + +std::string const& cmGlobalVisualStudio10Generator:: + GetPlatformToolsetCudaVSIntegrationSubdirString() const +{ + return this->GeneratorToolsetCudaVSIntegrationSubdir; +} + cmGlobalVisualStudio10Generator::AuxToolset cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&, std::string&) const diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 5e42c1728d9..e221d4c1e0d 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -78,6 +78,13 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator const char* GetPlatformToolsetCudaCustomDir() const; std::string const& GetPlatformToolsetCudaCustomDirString() const; + /** The nvcc subdirectory of a custom cuda install directory */ + std::string const& GetPlatformToolsetCudaNvccSubdirString() const; + + /** The visual studio integration subdirectory of a custom cuda install + * directory */ + std::string const& GetPlatformToolsetCudaVSIntegrationSubdirString() const; + /** Return whether we need to use No/Debug instead of false/true for GenerateDebugInformation. */ bool GetPlatformToolsetNeedsDebugEnum() const @@ -188,6 +195,8 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string GeneratorToolsetCustomVCTargetsDir; std::string GeneratorToolsetCuda; std::string GeneratorToolsetCudaCustomDir; + std::string GeneratorToolsetCudaNvccSubdir; + std::string GeneratorToolsetCudaVSIntegrationSubdir; std::string DefaultPlatformToolset; std::string DefaultPlatformToolsetHostArchitecture; std::string DefaultAndroidToolset; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 965ac3eeec7..0255d60cf40 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -545,7 +545,7 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element( "CudaToolkitCustomDir", this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() + - "nvcc"); + this->GlobalGenerator->GetPlatformToolsetCudaNvccSubdirString()); } } @@ -654,8 +654,9 @@ void cmVisualStudio10TargetGenerator::Generate() std::string cudaPath = customDir.empty() ? "$(VCTargetsPath)\\BuildCustomizations\\" : customDir + - "CUDAVisualStudioIntegration\\extras\\" - "visual_studio_integration\\MSBuildExtensions\\"; + this->GlobalGenerator + ->GetPlatformToolsetCudaVSIntegrationSubdirString() + + "extras\\visual_studio_integration\\MSBuildExtensions\\"; Elem(e1, "Import") .Attribute("Project", std::move(cudaPath) + "CUDA " + @@ -747,8 +748,9 @@ void cmVisualStudio10TargetGenerator::Generate() std::string cudaPath = customDir.empty() ? "$(VCTargetsPath)\\BuildCustomizations\\" : customDir + - "CUDAVisualStudioIntegration\\extras\\" - "visual_studio_integration\\MSBuildExtensions\\"; + this->GlobalGenerator + ->GetPlatformToolsetCudaVSIntegrationSubdirString() + + "extras\\visual_studio_integration\\MSBuildExtensions\\"; Elem(e1, "Import") .Attribute("Project", std::move(cudaPath) + "CUDA " + diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index 75ed677be9b..3aa791d52a9 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -12,8 +12,12 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") run_cmake(TestToolsetCudaVersionOnly) set(RunCMake_GENERATOR_TOOLSET "cuda=0.0") run_cmake(TestToolsetCudaVersionOnly) - set(RunCMake_GENERATOR_TOOLSET "cuda=C:\\dummy\\cuda") + set(RunCMake_GENERATOR_TOOLSET "cuda=${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset") run_cmake(TestToolsetCudaPathOnly) + set(RunCMake_GENERATOR_TOOLSET "cuda=${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset") + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset/CUDAVisualStudioIntegration") + run_cmake(TestToolsetCudaPathOnlyOldLayout) + file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset") if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[2456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt index b17745f9ab1..52367879be2 100644 --- a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnly-stderr.txt @@ -5,8 +5,8 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\): given toolset - cuda=C:\\dummy\\cuda\\ + cuda=.*/Tests/RunCMake/CudaStandaloneToolset\\ cannot detect Visual Studio integration files in path - C:/dummy/cuda/CUDAVisualStudioIntegration/extras/visual_studio_integration/MSBuildExtensions + .*/Tests/RunCMake/CudaStandaloneToolset/extras/visual_studio_integration/MSBuildExtensions diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt new file mode 100644 index 00000000000..3ce79f8300c --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout-stderr.txt @@ -0,0 +1,12 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio .* + + given toolset + + cuda=.*/Tests/RunCMake/CudaStandaloneToolset\\ + + cannot detect Visual Studio integration files in path + + .*/Tests/RunCMake/CudaStandaloneToolset/CUDAVisualStudioIntegration/extras/visual_studio_integration/MSBuildExtensions diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake new file mode 100644 index 00000000000..2fc38e5c597 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaPathOnlyOldLayout.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") From 87cd4f3ba0de7353b98d81cf7a677c619ec8b03b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 19 Mar 2021 00:01:17 -0400 Subject: [PATCH 0156/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 163224cd597..88c163163d6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210318) +set(CMake_VERSION_PATCH 20210319) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ebbd475e54e0ce66dbb1b07a129a11b05cdf3dbb Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 19 Mar 2021 10:25:50 -0400 Subject: [PATCH 0157/1519] Refactor: Move cmCMakePresetsFile::ReadJSON into a separate file Some compilers complain about translation units that are too large. In order to prepare for upcoming additions to cmCMakePresetsFile, split ReadJSON into a separate file. --- Source/CMakeLists.txt | 1 + Source/cmCMakePresetsFile.cxx | 787 ------------------------- Source/cmCMakePresetsFileReadJSON.cxx | 803 ++++++++++++++++++++++++++ 3 files changed, 804 insertions(+), 787 deletions(-) create mode 100644 Source/cmCMakePresetsFileReadJSON.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index d7828908e06..8b11a537e74 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -198,6 +198,7 @@ set(SRCS cmCMakePath.cxx cmCMakePresetsFile.cxx cmCMakePresetsFile.h + cmCMakePresetsFileReadJSON.cxx cmCommandArgumentParserHelper.cxx cmCommonTargetGenerator.cxx cmCommonTargetGenerator.h diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index c73ca9aeade..1d959538fd2 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -9,18 +9,8 @@ #include #include -#include -#include - -#include -#include - -#include "cmsys/FStream.hxx" - -#include "cmJSONHelpers.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include "cmVersion.h" #define CHECK_OK(expr) \ { \ @@ -51,675 +41,9 @@ enum class CycleStatus }; using ReadFileResult = cmCMakePresetsFile::ReadFileResult; -using CacheVariable = cmCMakePresetsFile::CacheVariable; using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset; using BuildPreset = cmCMakePresetsFile::BuildPreset; using TestPreset = cmCMakePresetsFile::TestPreset; -using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy; - -constexpr int MIN_VERSION = 1; -constexpr int MAX_VERSION = 3; - -struct CMakeVersion -{ - unsigned int Major = 0; - unsigned int Minor = 0; - unsigned int Patch = 0; -}; - -struct RootPresets -{ - CMakeVersion CMakeMinimumRequired; - std::vector ConfigurePresets; - std::vector BuildPresets; - std::vector TestPresets; -}; - -cmJSONHelper VendorHelper(ReadFileResult error) -{ - return [error](std::nullptr_t& /*out*/, - const Json::Value* value) -> ReadFileResult { - if (!value) { - return ReadFileResult::READ_OK; - } - - if (!value->isObject()) { - return error; - } - - return ReadFileResult::READ_OK; - }; -} - -auto const VersionIntHelper = cmJSONIntHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); - -auto const VersionHelper = cmJSONRequiredHelper( - ReadFileResult::NO_VERSION, VersionIntHelper); - -auto const RootVersionHelper = - cmJSONObjectHelper(ReadFileResult::READ_OK, - ReadFileResult::INVALID_ROOT) - .Bind("version"_s, VersionHelper, false); - -auto const VariableStringHelper = cmJSONStringHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); - -ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) -{ - if (!value) { - out.clear(); - return ReadFileResult::READ_OK; - } - - if (value->isBool()) { - out = value->asBool() ? "TRUE" : "FALSE"; - return ReadFileResult::READ_OK; - } - - return VariableStringHelper(out, value); -} - -auto const VariableObjectHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false) - .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false) - .Bind("value"_s, &CacheVariable::Value, VariableValueHelper); - -ReadFileResult VariableHelper(cm::optional& out, - const Json::Value* value) -{ - if (value->isBool()) { - out = CacheVariable{ - /*Type=*/"BOOL", - /*Value=*/value->asBool() ? "TRUE" : "FALSE", - }; - return ReadFileResult::READ_OK; - } - if (value->isString()) { - out = CacheVariable{ - /*Type=*/"", - /*Value=*/value->asString(), - }; - return ReadFileResult::READ_OK; - } - if (value->isObject()) { - out.emplace(); - return VariableObjectHelper(*out, value); - } - if (value->isNull()) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - return ReadFileResult::INVALID_VARIABLE; -} - -auto const VariablesHelper = - cmJSONMapHelper, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); - -auto const PresetStringHelper = cmJSONStringHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - -ReadFileResult EnvironmentHelper(cm::optional& out, - const Json::Value* value) -{ - if (!value || value->isNull()) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - if (value->isString()) { - out = value->asString(); - return ReadFileResult::READ_OK; - } - return ReadFileResult::INVALID_PRESET; -} - -auto const EnvironmentMapHelper = - cmJSONMapHelper, ReadFileResult>( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - EnvironmentHelper); - -auto const PresetVectorStringHelper = - cmJSONVectorHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, - PresetStringHelper); - -ReadFileResult PresetInheritsHelper(std::vector& out, - const Json::Value* value) -{ - out.clear(); - if (!value) { - return ReadFileResult::READ_OK; - } - - if (value->isString()) { - out.push_back(value->asString()); - return ReadFileResult::READ_OK; - } - - return PresetVectorStringHelper(out, value); -} - -auto const PresetBoolHelper = cmJSONBoolHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - -auto const PresetOptionalBoolHelper = - cmJSONOptionalHelper(ReadFileResult::READ_OK, - PresetBoolHelper); - -auto const PresetIntHelper = cmJSONIntHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); - -auto const PresetOptionalIntHelper = cmJSONOptionalHelper( - ReadFileResult::READ_OK, PresetIntHelper); - -auto const PresetVectorIntHelper = cmJSONVectorHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); - -auto const PresetWarningsHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false) - .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated, - PresetOptionalBoolHelper, false) - .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized, - PresetOptionalBoolHelper, false) - .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli, - PresetOptionalBoolHelper, false) - .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars, - PresetOptionalBoolHelper, false); - -auto const PresetErrorsHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false) - .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated, - PresetOptionalBoolHelper, false); - -auto const PresetDebugHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper, - false) - .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile, - PresetOptionalBoolHelper, false) - .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper, - false); - -ReadFileResult ArchToolsetStrategyHelper( - cm::optional& out, const Json::Value* value) -{ - if (!value) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "set") { - out = ArchToolsetStrategy::Set; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "external") { - out = ArchToolsetStrategy::External; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -std::function -ArchToolsetHelper( - std::string ConfigurePreset::*valueField, - cm::optional ConfigurePreset::*strategyField) -{ - auto const objectHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("value", valueField, PresetStringHelper, false) - .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false); - return [valueField, strategyField, objectHelper]( - ConfigurePreset& out, const Json::Value* value) -> ReadFileResult { - if (!value) { - (out.*valueField).clear(); - out.*strategyField = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (value->isString()) { - out.*valueField = value->asString(); - out.*strategyField = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (value->isObject()) { - return objectHelper(out, value); - } - - return ReadFileResult::INVALID_PRESET; - }; -} - -auto const ArchitectureHelper = ArchToolsetHelper( - &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy); -auto const ToolsetHelper = ArchToolsetHelper( - &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy); - -auto const ConfigurePresetHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper) - .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper, - false) - .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false) - .Bind("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_PRESET), false) - .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper, - false) - .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper, - false) - .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper, - false) - .Bind("architecture"_s, ArchitectureHelper, false) - .Bind("toolset"_s, ToolsetHelper, false) - .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper, - false) - .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper, - false) - .Bind("cmakeExecutable"_s, nullptr, PresetStringHelper, false) - .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables, - VariablesHelper, false) - .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper, - false) - .Bind("warnings"_s, PresetWarningsHelper, false) - .Bind("errors"_s, PresetErrorsHelper, false) - .Bind("debug"_s, PresetDebugHelper, false); - -auto const BuildPresetHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("name"_s, &BuildPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false) - .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false) - .Bind("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_PRESET), false) - .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper, - false) - .Bind("description"_s, &BuildPreset::Description, PresetStringHelper, - false) - .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper, - false) - .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset, - PresetStringHelper, false) - .Bind("inheritConfigureEnvironment"_s, - &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, - false) - .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false) - .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false) - .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper, - false) - .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper, - false) - .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false) - .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions, - PresetVectorStringHelper, false); - -ReadFileResult TestPresetOutputVerbosityHelper( - TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) -{ - if (!value) { - out = TestPreset::OutputOptions::VerbosityEnum::Default; - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "default") { - out = TestPreset::OutputOptions::VerbosityEnum::Default; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "verbose") { - out = TestPreset::OutputOptions::VerbosityEnum::Verbose; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "extra") { - out = TestPreset::OutputOptions::VerbosityEnum::Extra; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalOutputVerbosityHelper = - cmJSONOptionalHelper(ReadFileResult::READ_OK, - TestPresetOutputVerbosityHelper); - -auto const TestPresetOptionalOutputHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress, - PresetOptionalBoolHelper, false) - .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity, - TestPresetOptionalOutputVerbosityHelper, false) - .Bind("debug"_s, &TestPreset::OutputOptions::Debug, - PresetOptionalBoolHelper, false) - .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure, - PresetOptionalBoolHelper, false) - .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet, - PresetOptionalBoolHelper, false) - .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile, - PresetStringHelper, false) - .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary, - PresetOptionalBoolHelper, false) - .Bind("subprojectSummary"_s, - &TestPreset::OutputOptions::SubprojectSummary, - PresetOptionalBoolHelper, false) - .Bind("maxPassedTestOutputSize"_s, - &TestPreset::OutputOptions::MaxPassedTestOutputSize, - PresetOptionalIntHelper, false) - .Bind("maxFailedTestOutputSize"_s, - &TestPreset::OutputOptions::MaxFailedTestOutputSize, - PresetOptionalIntHelper, false) - .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth, - PresetOptionalIntHelper, false)); - -auto const TestPresetOptionalFilterIncludeIndexObjectHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) - .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start, - PresetOptionalIntHelper, false) - .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End, - PresetOptionalIntHelper, false) - .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride, - PresetOptionalIntHelper, false) - .Bind("specificTests"_s, - &TestPreset::IncludeOptions::IndexOptions::SpecificTests, - PresetVectorIntHelper, false)); - -ReadFileResult TestPresetOptionalFilterIncludeIndexHelper( - cm::optional& out, - const Json::Value* value) -{ - if (!value) { - out = cm::nullopt; - return ReadFileResult::READ_OK; - } - - if (value->isString()) { - out.emplace(); - out->IndexFile = value->asString(); - return ReadFileResult::READ_OK; - } - - if (value->isObject()) { - return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value); - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalFilterIncludeHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper, - false) - .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper, - false) - .Bind("index"_s, &TestPreset::IncludeOptions::Index, - TestPresetOptionalFilterIncludeIndexHelper, false) - .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion, - PresetOptionalBoolHelper, false)); - -auto const TestPresetOptionalFilterExcludeFixturesHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) - .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any, - PresetStringHelper, false) - .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup, - PresetStringHelper, false) - .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup, - PresetStringHelper, false)); - -auto const TestPresetOptionalFilterExcludeHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper, - false) - .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper, - false) - .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures, - TestPresetOptionalFilterExcludeFixturesHelper, false)); - -ReadFileResult TestPresetExecutionShowOnlyHelper( - TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value) -{ - if (!value || !value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "human") { - out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "json-v1") { - out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalExecutionShowOnlyHelper = - cmJSONOptionalHelper(ReadFileResult::READ_OK, - TestPresetExecutionShowOnlyHelper); - -ReadFileResult TestPresetExecutionModeHelper( - TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out, - const Json::Value* value) -{ - if (!value) { - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "until-fail") { - out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "until-pass") { - out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "after-timeout") { - out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalExecutionRepeatHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper(ReadFileResult::READ_OK, - ReadFileResult::INVALID_PRESET) - .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode, - TestPresetExecutionModeHelper, true) - .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count, - PresetIntHelper, true)); - -ReadFileResult TestPresetExecutionNoTestsActionHelper( - TestPreset::ExecutionOptions::NoTestsActionEnum& out, - const Json::Value* value) -{ - if (!value) { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; - return ReadFileResult::READ_OK; - } - - if (!value->isString()) { - return ReadFileResult::INVALID_PRESET; - } - - if (value->asString() == "default") { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "error") { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error; - return ReadFileResult::READ_OK; - } - - if (value->asString() == "ignore") { - out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore; - return ReadFileResult::READ_OK; - } - - return ReadFileResult::INVALID_PRESET; -} - -auto const TestPresetOptionalExecutionNoTestsActionHelper = - cmJSONOptionalHelper(ReadFileResult::READ_OK, - TestPresetExecutionNoTestsActionHelper); - -auto const TestPresetExecutionHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure, - PresetOptionalBoolHelper, false) - .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover, - PresetOptionalBoolHelper, false) - .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs, - PresetOptionalIntHelper, false) - .Bind("resourceSpecFile"_s, - &TestPreset::ExecutionOptions::ResourceSpecFile, - PresetStringHelper, false) - .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad, - PresetOptionalIntHelper, false) - .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly, - TestPresetOptionalExecutionShowOnlyHelper, false) - .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat, - TestPresetOptionalExecutionRepeatHelper, false) - .Bind("interactiveDebugging"_s, - &TestPreset::ExecutionOptions::InteractiveDebugging, - PresetOptionalBoolHelper, false) - .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom, - PresetOptionalBoolHelper, false) - .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout, - PresetOptionalIntHelper, false) - .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction, - TestPresetOptionalExecutionNoTestsActionHelper, false)); - -auto const TestPresetFilterHelper = - cmJSONOptionalHelper( - ReadFileResult::READ_OK, - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) - .Bind("include"_s, &TestPreset::FilterOptions::Include, - TestPresetOptionalFilterIncludeHelper, false) - .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude, - TestPresetOptionalFilterExcludeHelper, false)); - -auto const TestPresetHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) - .Bind("name"_s, &TestPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false) - .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false) - .Bind("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_PRESET), false) - .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false) - .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false) - .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper, - false) - .Bind("configurePreset"_s, &TestPreset::ConfigurePreset, - PresetStringHelper, false) - .Bind("inheritConfigureEnvironment"_s, - &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, - false) - .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper, - false) - .Bind("overwriteConfigurationFile"_s, - &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper, - false) - .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper, - false) - .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false) - .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper, - false); - -auto const ConfigurePresetsHelper = - cmJSONVectorHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - ConfigurePresetHelper); - -auto const BuildPresetsHelper = - cmJSONVectorHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, - BuildPresetHelper); - -auto const TestPresetsHelper = cmJSONVectorHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper); - -auto const CMakeVersionUIntHelper = cmJSONUIntHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); - -auto const CMakeVersionHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) - .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) - .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) - .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); - -auto const RootPresetsHelper = - cmJSONObjectHelper( - ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false) - .Bind("version"_s, nullptr, VersionHelper) - .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, - ConfigurePresetsHelper, false) - .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper, - false) - .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false) - .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired, - CMakeVersionHelper, false) - .Bind("vendor"_s, nullptr, - VendorHelper(ReadFileResult::INVALID_ROOT), false); void InheritString(std::string& child, const std::string& parent) { @@ -1557,117 +881,6 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result) return "Unknown error"; } -cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( - const std::string& filename, bool user) -{ - cmsys::ifstream fin(filename.c_str()); - if (!fin) { - return ReadFileResult::FILE_NOT_FOUND; - } - // If there's a BOM, toss it. - cmsys::FStream::ReadBOM(fin); - - Json::Value root; - Json::CharReaderBuilder builder; - Json::CharReaderBuilder::strictMode(&builder.settings_); - if (!Json::parseFromStream(builder, fin, &root, nullptr)) { - return ReadFileResult::JSON_PARSE_ERROR; - } - - int v = 0; - auto result = RootVersionHelper(v, &root); - if (result != ReadFileResult::READ_OK) { - return result; - } - if (v < MIN_VERSION || v > MAX_VERSION) { - return ReadFileResult::UNRECOGNIZED_VERSION; - } - if (user) { - this->UserVersion = v; - } else { - this->Version = v; - } - - // Support for build and test presets added in version 2. - if (v < 2 && - (root.isMember("buildPresets") || root.isMember("testPresets"))) { - return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED; - } - - RootPresets presets; - if ((result = RootPresetsHelper(presets, &root)) != - ReadFileResult::READ_OK) { - return result; - } - - unsigned int currentMajor = cmVersion::GetMajorVersion(); - unsigned int currentMinor = cmVersion::GetMinorVersion(); - unsigned int currentPatch = cmVersion::GetPatchVersion(); - auto const& required = presets.CMakeMinimumRequired; - if (required.Major > currentMajor || - (required.Major == currentMajor && - (required.Minor > currentMinor || - (required.Minor == currentMinor && - (required.Patch > currentPatch))))) { - return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION; - } - - for (auto& preset : presets.ConfigurePresets) { - preset.User = user; - if (preset.Name.empty()) { - return ReadFileResult::INVALID_PRESET; - } - - PresetPair presetPair; - presetPair.Unexpanded = preset; - presetPair.Expanded = cm::nullopt; - if (!this->ConfigurePresets - .emplace(std::make_pair(preset.Name, presetPair)) - .second) { - return ReadFileResult::DUPLICATE_PRESETS; - } - - // Support for installDir presets added in version 3. - if (v < 3 && !preset.InstallDir.empty()) { - return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED; - } - - this->ConfigurePresetOrder.push_back(preset.Name); - } - - for (auto& preset : presets.BuildPresets) { - preset.User = user; - if (preset.Name.empty()) { - return ReadFileResult::INVALID_PRESET; - } - - PresetPair presetPair; - presetPair.Unexpanded = preset; - presetPair.Expanded = cm::nullopt; - if (!this->BuildPresets.emplace(preset.Name, presetPair).second) { - return ReadFileResult::DUPLICATE_PRESETS; - } - this->BuildPresetOrder.push_back(preset.Name); - } - - for (auto& preset : presets.TestPresets) { - preset.User = user; - if (preset.Name.empty()) { - return ReadFileResult::INVALID_PRESET; - } - - PresetPair presetPair; - presetPair.Unexpanded = preset; - presetPair.Expanded = cm::nullopt; - if (!this->TestPresets.emplace(preset.Name, presetPair).second) { - return ReadFileResult::DUPLICATE_PRESETS; - } - this->TestPresetOrder.push_back(preset.Name); - } - - return ReadFileResult::READ_OK; -} - void cmCMakePresetsFile::ClearPresets() { this->ConfigurePresets.clear(); diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx new file mode 100644 index 00000000000..b71b17602eb --- /dev/null +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -0,0 +1,803 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "cmsys/FStream.hxx" + +#include "cmCMakePresetsFile.h" +#include "cmJSONHelpers.h" +#include "cmVersion.h" + +namespace { +using ReadFileResult = cmCMakePresetsFile::ReadFileResult; +using CacheVariable = cmCMakePresetsFile::CacheVariable; +using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset; +using BuildPreset = cmCMakePresetsFile::BuildPreset; +using TestPreset = cmCMakePresetsFile::TestPreset; +using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy; + +constexpr int MIN_VERSION = 1; +constexpr int MAX_VERSION = 3; + +struct CMakeVersion +{ + unsigned int Major = 0; + unsigned int Minor = 0; + unsigned int Patch = 0; +}; + +struct RootPresets +{ + CMakeVersion CMakeMinimumRequired; + std::vector ConfigurePresets; + std::vector BuildPresets; + std::vector TestPresets; +}; + +cmJSONHelper VendorHelper(ReadFileResult error) +{ + return [error](std::nullptr_t& /*out*/, + const Json::Value* value) -> ReadFileResult { + if (!value) { + return ReadFileResult::READ_OK; + } + + if (!value->isObject()) { + return error; + } + + return ReadFileResult::READ_OK; + }; +} + +auto const VersionIntHelper = cmJSONIntHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); + +auto const VersionHelper = cmJSONRequiredHelper( + ReadFileResult::NO_VERSION, VersionIntHelper); + +auto const RootVersionHelper = + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_ROOT) + .Bind("version"_s, VersionHelper, false); + +auto const VariableStringHelper = cmJSONStringHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); + +ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value) +{ + if (!value) { + out.clear(); + return ReadFileResult::READ_OK; + } + + if (value->isBool()) { + out = value->asBool() ? "TRUE" : "FALSE"; + return ReadFileResult::READ_OK; + } + + return VariableStringHelper(out, value); +} + +auto const VariableObjectHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false) + .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false) + .Bind("value"_s, &CacheVariable::Value, VariableValueHelper); + +ReadFileResult VariableHelper(cm::optional& out, + const Json::Value* value) +{ + if (value->isBool()) { + out = CacheVariable{ + /*Type=*/"BOOL", + /*Value=*/value->asBool() ? "TRUE" : "FALSE", + }; + return ReadFileResult::READ_OK; + } + if (value->isString()) { + out = CacheVariable{ + /*Type=*/"", + /*Value=*/value->asString(), + }; + return ReadFileResult::READ_OK; + } + if (value->isObject()) { + out.emplace(); + return VariableObjectHelper(*out, value); + } + if (value->isNull()) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + return ReadFileResult::INVALID_VARIABLE; +} + +auto const VariablesHelper = + cmJSONMapHelper, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); + +auto const PresetStringHelper = cmJSONStringHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); + +ReadFileResult EnvironmentHelper(cm::optional& out, + const Json::Value* value) +{ + if (!value || value->isNull()) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + if (value->isString()) { + out = value->asString(); + return ReadFileResult::READ_OK; + } + return ReadFileResult::INVALID_PRESET; +} + +auto const EnvironmentMapHelper = + cmJSONMapHelper, ReadFileResult>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + EnvironmentHelper); + +auto const PresetVectorStringHelper = + cmJSONVectorHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + PresetStringHelper); + +ReadFileResult PresetInheritsHelper(std::vector& out, + const Json::Value* value) +{ + out.clear(); + if (!value) { + return ReadFileResult::READ_OK; + } + + if (value->isString()) { + out.push_back(value->asString()); + return ReadFileResult::READ_OK; + } + + return PresetVectorStringHelper(out, value); +} + +auto const PresetBoolHelper = cmJSONBoolHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); + +auto const PresetOptionalBoolHelper = + cmJSONOptionalHelper(ReadFileResult::READ_OK, + PresetBoolHelper); + +auto const PresetIntHelper = cmJSONIntHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET); + +auto const PresetOptionalIntHelper = cmJSONOptionalHelper( + ReadFileResult::READ_OK, PresetIntHelper); + +auto const PresetVectorIntHelper = cmJSONVectorHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper); + +auto const PresetWarningsHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false) + .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated, + PresetOptionalBoolHelper, false) + .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized, + PresetOptionalBoolHelper, false) + .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli, + PresetOptionalBoolHelper, false) + .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars, + PresetOptionalBoolHelper, false); + +auto const PresetErrorsHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false) + .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated, + PresetOptionalBoolHelper, false); + +auto const PresetDebugHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper, + false) + .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile, + PresetOptionalBoolHelper, false) + .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper, + false); + +ReadFileResult ArchToolsetStrategyHelper( + cm::optional& out, const Json::Value* value) +{ + if (!value) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "set") { + out = ArchToolsetStrategy::Set; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "external") { + out = ArchToolsetStrategy::External; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +std::function +ArchToolsetHelper( + std::string ConfigurePreset::*valueField, + cm::optional ConfigurePreset::*strategyField) +{ + auto const objectHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("value", valueField, PresetStringHelper, false) + .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false); + return [valueField, strategyField, objectHelper]( + ConfigurePreset& out, const Json::Value* value) -> ReadFileResult { + if (!value) { + (out.*valueField).clear(); + out.*strategyField = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (value->isString()) { + out.*valueField = value->asString(); + out.*strategyField = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (value->isObject()) { + return objectHelper(out, value); + } + + return ReadFileResult::INVALID_PRESET; + }; +} + +auto const ArchitectureHelper = ArchToolsetHelper( + &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy); +auto const ToolsetHelper = ArchToolsetHelper( + &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy); + +auto const ConfigurePresetHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper) + .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper, + false) + .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false) + .Bind("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_PRESET), false) + .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper, + false) + .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper, + false) + .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper, + false) + .Bind("architecture"_s, ArchitectureHelper, false) + .Bind("toolset"_s, ToolsetHelper, false) + .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper, + false) + .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper, + false) + .Bind("cmakeExecutable"_s, nullptr, PresetStringHelper, false) + .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables, + VariablesHelper, false) + .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper, + false) + .Bind("warnings"_s, PresetWarningsHelper, false) + .Bind("errors"_s, PresetErrorsHelper, false) + .Bind("debug"_s, PresetDebugHelper, false); + +auto const BuildPresetHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &BuildPreset::Name, PresetStringHelper) + .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false) + .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false) + .Bind("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_PRESET), false) + .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper, + false) + .Bind("description"_s, &BuildPreset::Description, PresetStringHelper, + false) + .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper, + false) + .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset, + PresetStringHelper, false) + .Bind("inheritConfigureEnvironment"_s, + &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, + false) + .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false) + .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false) + .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper, + false) + .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper, + false) + .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false) + .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions, + PresetVectorStringHelper, false); + +ReadFileResult TestPresetOutputVerbosityHelper( + TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) +{ + if (!value) { + out = TestPreset::OutputOptions::VerbosityEnum::Default; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "default") { + out = TestPreset::OutputOptions::VerbosityEnum::Default; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "verbose") { + out = TestPreset::OutputOptions::VerbosityEnum::Verbose; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "extra") { + out = TestPreset::OutputOptions::VerbosityEnum::Extra; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalOutputVerbosityHelper = + cmJSONOptionalHelper(ReadFileResult::READ_OK, + TestPresetOutputVerbosityHelper); + +auto const TestPresetOptionalOutputHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress, + PresetOptionalBoolHelper, false) + .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity, + TestPresetOptionalOutputVerbosityHelper, false) + .Bind("debug"_s, &TestPreset::OutputOptions::Debug, + PresetOptionalBoolHelper, false) + .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure, + PresetOptionalBoolHelper, false) + .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet, + PresetOptionalBoolHelper, false) + .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile, + PresetStringHelper, false) + .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary, + PresetOptionalBoolHelper, false) + .Bind("subprojectSummary"_s, + &TestPreset::OutputOptions::SubprojectSummary, + PresetOptionalBoolHelper, false) + .Bind("maxPassedTestOutputSize"_s, + &TestPreset::OutputOptions::MaxPassedTestOutputSize, + PresetOptionalIntHelper, false) + .Bind("maxFailedTestOutputSize"_s, + &TestPreset::OutputOptions::MaxFailedTestOutputSize, + PresetOptionalIntHelper, false) + .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth, + PresetOptionalIntHelper, false)); + +auto const TestPresetOptionalFilterIncludeIndexObjectHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET) + .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start, + PresetOptionalIntHelper, false) + .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End, + PresetOptionalIntHelper, false) + .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride, + PresetOptionalIntHelper, false) + .Bind("specificTests"_s, + &TestPreset::IncludeOptions::IndexOptions::SpecificTests, + PresetVectorIntHelper, false)); + +ReadFileResult TestPresetOptionalFilterIncludeIndexHelper( + cm::optional& out, + const Json::Value* value) +{ + if (!value) { + out = cm::nullopt; + return ReadFileResult::READ_OK; + } + + if (value->isString()) { + out.emplace(); + out->IndexFile = value->asString(); + return ReadFileResult::READ_OK; + } + + if (value->isObject()) { + return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value); + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalFilterIncludeHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper, + false) + .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper, + false) + .Bind("index"_s, &TestPreset::IncludeOptions::Index, + TestPresetOptionalFilterIncludeIndexHelper, false) + .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion, + PresetOptionalBoolHelper, false)); + +auto const TestPresetOptionalFilterExcludeFixturesHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET) + .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any, + PresetStringHelper, false) + .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup, + PresetStringHelper, false) + .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup, + PresetStringHelper, false)); + +auto const TestPresetOptionalFilterExcludeHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper, + false) + .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper, + false) + .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures, + TestPresetOptionalFilterExcludeFixturesHelper, false)); + +ReadFileResult TestPresetExecutionShowOnlyHelper( + TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value) +{ + if (!value || !value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "human") { + out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "json-v1") { + out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalExecutionShowOnlyHelper = + cmJSONOptionalHelper(ReadFileResult::READ_OK, + TestPresetExecutionShowOnlyHelper); + +ReadFileResult TestPresetExecutionModeHelper( + TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out, + const Json::Value* value) +{ + if (!value) { + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "until-fail") { + out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "until-pass") { + out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "after-timeout") { + out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalExecutionRepeatHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_PRESET) + .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode, + TestPresetExecutionModeHelper, true) + .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count, + PresetIntHelper, true)); + +ReadFileResult TestPresetExecutionNoTestsActionHelper( + TestPreset::ExecutionOptions::NoTestsActionEnum& out, + const Json::Value* value) +{ + if (!value) { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; + return ReadFileResult::READ_OK; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "default") { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "error") { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "ignore") { + out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const TestPresetOptionalExecutionNoTestsActionHelper = + cmJSONOptionalHelper(ReadFileResult::READ_OK, + TestPresetExecutionNoTestsActionHelper); + +auto const TestPresetExecutionHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure, + PresetOptionalBoolHelper, false) + .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover, + PresetOptionalBoolHelper, false) + .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs, + PresetOptionalIntHelper, false) + .Bind("resourceSpecFile"_s, + &TestPreset::ExecutionOptions::ResourceSpecFile, + PresetStringHelper, false) + .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad, + PresetOptionalIntHelper, false) + .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly, + TestPresetOptionalExecutionShowOnlyHelper, false) + .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat, + TestPresetOptionalExecutionRepeatHelper, false) + .Bind("interactiveDebugging"_s, + &TestPreset::ExecutionOptions::InteractiveDebugging, + PresetOptionalBoolHelper, false) + .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom, + PresetOptionalBoolHelper, false) + .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout, + PresetOptionalIntHelper, false) + .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction, + TestPresetOptionalExecutionNoTestsActionHelper, false)); + +auto const TestPresetFilterHelper = + cmJSONOptionalHelper( + ReadFileResult::READ_OK, + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET) + .Bind("include"_s, &TestPreset::FilterOptions::Include, + TestPresetOptionalFilterIncludeHelper, false) + .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude, + TestPresetOptionalFilterExcludeHelper, false)); + +auto const TestPresetHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &TestPreset::Name, PresetStringHelper) + .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false) + .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false) + .Bind("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_PRESET), false) + .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false) + .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false) + .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper, + false) + .Bind("configurePreset"_s, &TestPreset::ConfigurePreset, + PresetStringHelper, false) + .Bind("inheritConfigureEnvironment"_s, + &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, + false) + .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper, + false) + .Bind("overwriteConfigurationFile"_s, + &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper, + false) + .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper, + false) + .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false) + .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper, + false); + +auto const ConfigurePresetsHelper = + cmJSONVectorHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + ConfigurePresetHelper); + +auto const BuildPresetsHelper = + cmJSONVectorHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + BuildPresetHelper); + +auto const TestPresetsHelper = cmJSONVectorHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper); + +auto const CMakeVersionUIntHelper = cmJSONUIntHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION); + +auto const CMakeVersionHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false) + .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) + .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) + .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); + +auto const RootPresetsHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false) + .Bind("version"_s, nullptr, VersionHelper) + .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, + ConfigurePresetsHelper, false) + .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper, + false) + .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false) + .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired, + CMakeVersionHelper, false) + .Bind("vendor"_s, nullptr, + VendorHelper(ReadFileResult::INVALID_ROOT), false); +} + +cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( + const std::string& filename, bool user) +{ + cmsys::ifstream fin(filename.c_str()); + if (!fin) { + return ReadFileResult::FILE_NOT_FOUND; + } + // If there's a BOM, toss it. + cmsys::FStream::ReadBOM(fin); + + Json::Value root; + Json::CharReaderBuilder builder; + Json::CharReaderBuilder::strictMode(&builder.settings_); + if (!Json::parseFromStream(builder, fin, &root, nullptr)) { + return ReadFileResult::JSON_PARSE_ERROR; + } + + int v = 0; + auto result = RootVersionHelper(v, &root); + if (result != ReadFileResult::READ_OK) { + return result; + } + if (v < MIN_VERSION || v > MAX_VERSION) { + return ReadFileResult::UNRECOGNIZED_VERSION; + } + if (user) { + this->UserVersion = v; + } else { + this->Version = v; + } + + // Support for build and test presets added in version 2. + if (v < 2 && + (root.isMember("buildPresets") || root.isMember("testPresets"))) { + return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED; + } + + RootPresets presets; + if ((result = RootPresetsHelper(presets, &root)) != + ReadFileResult::READ_OK) { + return result; + } + + unsigned int currentMajor = cmVersion::GetMajorVersion(); + unsigned int currentMinor = cmVersion::GetMinorVersion(); + unsigned int currentPatch = cmVersion::GetPatchVersion(); + auto const& required = presets.CMakeMinimumRequired; + if (required.Major > currentMajor || + (required.Major == currentMajor && + (required.Minor > currentMinor || + (required.Minor == currentMinor && + (required.Patch > currentPatch))))) { + return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION; + } + + for (auto& preset : presets.ConfigurePresets) { + preset.User = user; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->ConfigurePresets + .emplace(std::make_pair(preset.Name, presetPair)) + .second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + + // Support for installDir presets added in version 3. + if (v < 3 && !preset.InstallDir.empty()) { + return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED; + } + + this->ConfigurePresetOrder.push_back(preset.Name); + } + + for (auto& preset : presets.BuildPresets) { + preset.User = user; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->BuildPresets.emplace(preset.Name, presetPair).second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + this->BuildPresetOrder.push_back(preset.Name); + } + + for (auto& preset : presets.TestPresets) { + preset.User = user; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->TestPresets.emplace(preset.Name, presetPair).second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + this->TestPresetOrder.push_back(preset.Name); + } + + return ReadFileResult::READ_OK; +} From ce6ea7c927b9f80f219a7783ce725bea4c24091f Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 19 Mar 2021 10:40:03 -0400 Subject: [PATCH 0158/1519] Refactor: Move some common code into separate file This code is going to be needed by both cmCMakePresetsFile and cmCMakePresetsFileReadJSON when the upcoming condition types are created. Move it into a header file. --- Source/CMakeLists.txt | 1 + Source/cmCMakePresetsFile.cxx | 20 +++----------------- Source/cmCMakePresetsFileInternal.h | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 Source/cmCMakePresetsFileInternal.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8b11a537e74..938745c489f 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -198,6 +198,7 @@ set(SRCS cmCMakePath.cxx cmCMakePresetsFile.cxx cmCMakePresetsFile.h + cmCMakePresetsFileInternal.h cmCMakePresetsFileReadJSON.cxx cmCommandArgumentParserHelper.cxx cmCommonTargetGenerator.cxx diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index 1d959538fd2..c0b09817c4f 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -9,16 +9,10 @@ #include #include +#include "cmCMakePresetsFileInternal.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#define CHECK_OK(expr) \ - { \ - auto _result = expr; \ - if (_result != ReadFileResult::READ_OK) \ - return _result; \ - } - #define CHECK_EXPAND(out, field, expanders, version) \ { \ switch (ExpandMacros(field, expanders, version)) { \ @@ -44,6 +38,8 @@ using ReadFileResult = cmCMakePresetsFile::ReadFileResult; using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset; using BuildPreset = cmCMakePresetsFile::BuildPreset; using TestPreset = cmCMakePresetsFile::TestPreset; +using ExpandMacroResult = cmCMakePresetsFileInternal::ExpandMacroResult; +using MacroExpander = cmCMakePresetsFileInternal::MacroExpander; void InheritString(std::string& child, const std::string& parent) { @@ -166,16 +162,6 @@ bool IsValidMacroNamespace(const std::string& str) [&str](const char* prefix) -> bool { return str == prefix; }); } -enum class ExpandMacroResult -{ - Ok, - Ignore, - Error, -}; - -using MacroExpander = std::function; - ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status, const std::vector& macroExpanders, int version); diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h new file mode 100644 index 00000000000..f05b8ce4a14 --- /dev/null +++ b/Source/cmCMakePresetsFileInternal.h @@ -0,0 +1,22 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCMakePresetsFile.h" + +#define CHECK_OK(expr) \ + { \ + auto _result = expr; \ + if (_result != ReadFileResult::READ_OK) \ + return _result; \ + } + +namespace cmCMakePresetsFileInternal { +enum class ExpandMacroResult +{ + Ok, + Ignore, + Error, +}; + +using MacroExpander = std::function; +} From 26cf661b6495610aab1dee176666b9b6dc8fd77b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 18 Mar 2021 09:24:52 -0400 Subject: [PATCH 0159/1519] Help/guide: use GNUInstallDirs in importing-exporting example This allows the example to also show how to work on systems with different libdir settings (e.g., Debian multiarch or Red Hat multilib) rather than a regular `lib` directory. --- .../MathFunctions/CMakeLists.txt | 21 +++++++++++-------- .../Addition/CMakeLists.txt | 14 ++++++------- .../MathFunctionsComponents/CMakeLists.txt | 7 +++++-- .../SquareRoot/CMakeLists.txt | 14 ++++++------- Help/guide/importing-exporting/index.rst | 4 ++++ 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt index 9a9e40ee23c..d277b541904 100644 --- a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt +++ b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.15) project(MathFunctions) +# make cache variables for install destinations +include(GNUInstallDirs) + # specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) @@ -12,26 +15,26 @@ add_library(MathFunctions STATIC MathFunctions.cxx) target_include_directories(MathFunctions PUBLIC "$" - "$" + "$" ) # install the target and create export-set install(TARGETS MathFunctions EXPORT MathFunctionsTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # install header file -install(FILES MathFunctions.h DESTINATION include) +install(FILES MathFunctions.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # generate and install export file install(EXPORT MathFunctionsTargets FILE MathFunctionsTargets.cmake NAMESPACE MathFunctions:: - DESTINATION lib/cmake/MathFunctions + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions ) # include CMakePackageConfigHelpers macro @@ -58,14 +61,14 @@ write_basic_package_version_file( # create config file configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" - INSTALL_DESTINATION lib/cmake/MathFunctions + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions ) # install config files install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" - DESTINATION lib/cmake/MathFunctions + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions ) # generate the export targets for the build tree diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt index 17ad95210b4..9de935eea97 100644 --- a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt +++ b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt @@ -7,24 +7,24 @@ add_library(MathFunctions::Addition ALIAS Addition) target_include_directories(Addition PUBLIC "$" - $ + $ ) # install the target and create export-set install(TARGETS Addition EXPORT AdditionTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # install header file -install(FILES Addition.h DESTINATION include) +install(FILES Addition.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # generate and install export file install(EXPORT AdditionTargets FILE MathFunctionsAdditionTargets.cmake NAMESPACE MathFunctions:: - DESTINATION lib/cmake/MathFunctions + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions ) diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt index fd95e28df03..90ee89f0f67 100644 --- a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt +++ b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.15) project(MathFunctionsComponents) +# make cache variables for install destinations +include(GNUInstallDirs) + # specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) @@ -24,7 +27,7 @@ write_basic_package_version_file( # create config file configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" - INSTALL_DESTINATION lib/cmake/MathFunctions + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions NO_CHECK_REQUIRED_COMPONENTS_MACRO ) @@ -32,5 +35,5 @@ configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" - DESTINATION lib/cmake/MathFunctions + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions ) diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt index be5ae65d1cf..517c5e26a90 100644 --- a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt +++ b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt @@ -7,24 +7,24 @@ add_library(MathFunctions::SquareRoot ALIAS SquareRoot) target_include_directories(SquareRoot PUBLIC "$" - "$" + "$" ) # install the target and create export-set install(TARGETS SquareRoot EXPORT SquareRootTargets - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # install header file -install(FILES SquareRoot.h DESTINATION include) +install(FILES SquareRoot.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # generate and install export file install(EXPORT SquareRootTargets FILE MathFunctionsSquareRootTargets.cmake NAMESPACE MathFunctions:: - DESTINATION lib/cmake/MathFunctions + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions ) diff --git a/Help/guide/importing-exporting/index.rst b/Help/guide/importing-exporting/index.rst index 2e6e06da4ed..3e602508ff3 100644 --- a/Help/guide/importing-exporting/index.rst +++ b/Help/guide/importing-exporting/index.rst @@ -202,6 +202,10 @@ project. Start by specifying the :command:`cmake_minimum_required` version and :language: cmake :end-before: # create library +The :module:`GNUInstallDirs` module is included in order to provide the +project with the flexibility to install into different platform layouts by +making the directories available as cache variables. + Create a library called ``MathFunctions`` with the :command:`add_library` command: From e2aa44ba049e1a4f2f44c042cf34231c5bb073f0 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 18 Mar 2021 10:36:32 -0400 Subject: [PATCH 0160/1519] Tests: set CMAKE_PREFIX_PATH to the installation prefix As it is documented to be. --- Tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e532acef3ac..d6a20bc3e99 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1697,7 +1697,7 @@ if(BUILD_TESTING) ${build_generator_args} --build-project ${import_name} --build-options - "-DCMAKE_PREFIX_PATH:PATH=${install_dir}/lib/cmake") + "-DCMAKE_PREFIX_PATH:PATH=${install_dir}") set_tests_properties(${import_test_name} PROPERTIES DEPENDS ${export_test_name}) list(APPEND TEST_BUILD_DIRS "${import_build_dir}") endfunction() From 9b4390e76be7e46f2031563642f0a1cae5dbf4e8 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 20 Mar 2021 00:01:15 -0400 Subject: [PATCH 0161/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 88c163163d6..530c2caa34c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210319) +set(CMake_VERSION_PATCH 20210320) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 8f0cbaf2e03d3809f55ad674dbe5543636c0ebc6 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 21 Mar 2021 00:03:25 -0400 Subject: [PATCH 0162/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 530c2caa34c..a11fd8c2fb6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210320) +set(CMake_VERSION_PATCH 20210321) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6d4cbf7416f8ab4d001ca08ca4e108615ea5dfb1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 22 Mar 2021 00:01:18 -0400 Subject: [PATCH 0163/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a11fd8c2fb6..17f26a876ed 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210321) +set(CMake_VERSION_PATCH 20210322) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 7c4c4f1406f1b4a3d84248e87ce1786ee7a5d0f5 Mon Sep 17 00:00:00 2001 From: Andrew Gilewsky Date: Sun, 21 Mar 2021 18:10:57 +0300 Subject: [PATCH 0164/1519] Treat '.ixx' and '.cppm' files as C++ sources These extensions are used by convention for C++ modules and interface units with MSVC. --- Help/release/dev/cxx-module-extensions.rst | 4 ++++ Modules/CMakeCXXCompiler.cmake.in | 2 +- Source/cmMakefile.cxx | 2 +- Source/cmSourceFile.h | 2 +- Source/cmake.cxx | 6 +++--- 5 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/cxx-module-extensions.rst diff --git a/Help/release/dev/cxx-module-extensions.rst b/Help/release/dev/cxx-module-extensions.rst new file mode 100644 index 00000000000..b9d0a8a1544 --- /dev/null +++ b/Help/release/dev/cxx-module-extensions.rst @@ -0,0 +1,4 @@ +cxx-module-extensions +--------------------- + +* Source file extensions ``.ixx`` and ``.cppm`` are now treated as C++. diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 45acfe732b0..d0ce77a7ee7 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -44,7 +44,7 @@ if(CMAKE_COMPILER_IS_MINGW) set(MINGW 1) endif() set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) foreach (lang C OBJC OBJCXX) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e156625f463..40a67a399d2 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1222,7 +1222,7 @@ void cmMakefile::AddCustomCommandOldStyle( // Each output must get its own copy of this rule. cmsys::RegularExpression sourceFiles( - "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|cu|m|mm|" + "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|ixx|cppm|cu|m|mm|" "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|" "hm|hpp|hxx|in|txx|inl)$"); diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 76a5ded89dd..32ed68715fe 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -175,7 +175,7 @@ class cmSourceFile #define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$" #define CM_SOURCE_REGEX \ - "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \ + "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|ixx|cppm|cu|f|f90|for|fpp|ftn|m|mm|" \ "rc|def|r|odl|idl|hpj|bat)$" #define CM_PCH_REGEX "cmake_pch(_[^.]+)?\\.(h|hxx)$" diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b12eeee7f31..55a7feb9fb8 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -209,9 +209,9 @@ cmake::cmake(Role role, cmState::Mode mode) }; // The "c" extension MUST precede the "C" extension. - setupExts( - this->CLikeSourceFileExtensions, - { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", "mm" }); + setupExts(this->CLikeSourceFileExtensions, + { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", + "mm", "ixx", "cppm" }); setupExts(this->HeaderFileExtensions, { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); setupExts(this->CudaFileExtensions, { "cu" }); From 8dd8d6366576c09a44dc19d6609209ff74cd0dde Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 22 Mar 2021 13:26:00 -0400 Subject: [PATCH 0165/1519] Tests: Add RunCMake hook to describe test variants --- Tests/RunCMake/RunCMake.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 5e2f647b8ec..3ea4ae504a1 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -193,7 +193,7 @@ function(run_cmake test) if(msg) string(REGEX REPLACE "\n" "\n actual-out> " actual_out " actual-out> ${actual_stdout}") string(REGEX REPLACE "\n" "\n actual-err> " actual_err " actual-err> ${actual_stderr}") - message(SEND_ERROR "${test} - FAILED:\n" + message(SEND_ERROR "${test}${RunCMake_TEST_VARIANT_DESCRIPTION} - FAILED:\n" "${msg}" "${expect_out}" "Actual stdout:\n${actual_out}\n" @@ -201,7 +201,7 @@ function(run_cmake test) "Actual stderr:\n${actual_err}\n" ) else() - message(STATUS "${test} - PASSED") + message(STATUS "${test}${RunCMake_TEST_VARIANT_DESCRIPTION} - PASSED") endif() endfunction() From 608ef8a6fcbdd3d1a8419ff774109b8f9e5ebafb Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Mar 2021 16:47:49 -0500 Subject: [PATCH 0166/1519] VS: Add a mostly-undocumented hook to load custom JSON flag tables The names and formats of our VS flag tables are internal implementation details. However, some institutions need to maintain support for non-public VS platforms and toolsets. Provide a hook that their projects can use to load custom flag table files. This helps avoid distributing a custom CMake package within such institutions. Document the hook itself, but explicitly specify that the files the hook loads are not considered a stable interface. --- Help/variable/CMAKE_GENERATOR_TOOLSET.rst | 24 +++++++++++++ Source/cmGlobalVisualStudio10Generator.cxx | 36 +++++++++++++++++++ Source/cmGlobalVisualStudio10Generator.h | 2 ++ .../BadToolsetCustomFlagTableDir-result.txt | 1 + .../BadToolsetCustomFlagTableDir-stderr.txt | 11 ++++++ .../BadToolsetCustomFlagTableDir.cmake | 1 + .../GeneratorToolset/RunCMakeTest.cmake | 25 +++++++++++++ .../TestToolsetCustomFlagTableDir-check.cmake | 24 +++++++++++++ .../TestToolsetCustomFlagTableDir.cmake | 3 ++ .../GeneratorToolset/VsNormal-stdout.txt | 2 ++ .../RunCMake/GeneratorToolset/VsNormal.cmake | 6 ++++ Tests/RunCMake/GeneratorToolset/main.c | 4 +++ 12 files changed, 139 insertions(+) create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/VsNormal.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/main.c diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index 53ad2f3e760..45f2d3236b2 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -63,3 +63,27 @@ Supported pairs are: Specify an alternative ``VCTargetsPath`` value for Visual Studio project files. This allows use of VS platform extension configuration files (``.props`` and ``.targets``) that are not installed with VS. + +Visual Studio Toolset Customization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**These are unstable interfaces with no compatibility guarantees** +because they hook into undocumented internal CMake implementation details. +Institutions may use these to internally maintain support for non-public +Visual Studio platforms and toolsets, but must accept responsibility to +make updates as changes are made to CMake. + +Additional ``key=value`` pairs are available: + +``customFlagTableDir=`` + .. versionadded:: 3.21 + + Specify the absolute path to a directory from which to load custom + flag tables stored as JSON documents with file names of the form + ``__.json`` or ``_.json``, + where ```` is the :variable:`CMAKE_VS_PLATFORM_NAME`, + ```` is the :variable:`CMAKE_VS_PLATFORM_TOOLSET`, + and ```` is the tool for which the flag table is meant. + **This naming pattern is an internal CMake implementation detail.** + The ```` names are undocumented. The format of the ``.json`` + flag table files is undocumented. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index d33c763a558..93fbe37d6bc 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -231,6 +231,23 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( return false; } + if (!this->CustomFlagTableDir.empty() && + !(cmSystemTools::FileIsFullPath(this->CustomFlagTableDir) && + cmSystemTools::FileIsDirectory(this->CustomFlagTableDir))) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset\n" + " customFlagTableDir=" << this->CustomFlagTableDir << "\n" + "that is not an absolute path to an existing directory."; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) { // The GenerateDebugInformation link setting for the v140 toolset // in VS 2015 was originally an enum with "No" and "Debug" values, @@ -486,6 +503,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( } return true; } + if (key == "customFlagTableDir") { + this->CustomFlagTableDir = value; + cmSystemTools::ConvertToUnixSlashes(this->CustomFlagTableDir); + return true; + } if (key == "version") { this->GeneratorToolsetVersion = value; return true; @@ -1375,6 +1397,20 @@ static cmIDEFlagTable const* cmLoadFlagTableJson( cm::optional cmGlobalVisualStudio10Generator::FindFlagTable( cm::string_view toolsetName, cm::string_view table) const { + if (!this->CustomFlagTableDir.empty()) { + std::string customFlagTableFile = + cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_', + toolsetName, '_', table, ".json"); + if (cmSystemTools::FileExists(customFlagTableFile)) { + return customFlagTableFile; + } + customFlagTableFile = + cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_', + table, ".json"); + if (cmSystemTools::FileExists(customFlagTableFile)) { + return customFlagTableFile; + } + } std::string fullPath = cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/MSBuild/FlagTables/", toolsetName, '_', table, ".json"); diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index e221d4c1e0d..25967204af5 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -262,6 +262,8 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator cm::optional FindFlagTable(cm::string_view toolsetName, cm::string_view table) const; + std::string CustomFlagTableDir; + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt new file mode 100644 index 00000000000..d8b6c5eab0c --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Visual Studio [^ +]* + + given toolset + + customFlagTableDir=does_not_exist + + that is not an absolute path to an existing directory.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake new file mode 100644 index 00000000000..2fc38e5c597 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetCustomFlagTableDir.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index 3aa791d52a9..faed8f7d4d8 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -1,5 +1,11 @@ include(RunCMake) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") + run_cmake(VsNormal) + include("${RunCMake_BINARY_DIR}/VsNormal-build/defaults.cmake" OPTIONAL) + message(STATUS "VsNormal: platform='${VsNormal_Platform}' toolset='${VsNormal_Toolset}'") +endif() + set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) @@ -18,6 +24,25 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset/CUDAVisualStudioIntegration") run_cmake(TestToolsetCudaPathOnlyOldLayout) file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/CudaStandaloneToolset") + if (VsNormal_Platform MATCHES "^(x64|Win32)$" AND + EXISTS "${CMAKE_ROOT}/Templates/MSBuild/FlagTables/${VsNormal_Toolset}_CL.json") + set(flagTableDir "${RunCMake_BINARY_DIR}/FlagTables") + file(READ "${CMAKE_ROOT}/Templates/MSBuild/FlagTables/${VsNormal_Toolset}_CL.json" flagTableContent) + string(REPLACE [["WX-"]] [["TESTWX-"]] flagTableContent "${flagTableContent}") + file(REMOVE_RECURSE "${flagTableDir}") + file(WRITE "${flagTableDir}/${VsNormal_Platform}_${VsNormal_Toolset}_CL.json" "${flagTableContent}") + set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=${flagTableDir}") + set(RunCMake_TEST_VARIANT_DESCRIPTION ":${VsNormal_Platform}_${VsNormal_Toolset}_CL.json") + run_cmake(TestToolsetCustomFlagTableDir) + file(REMOVE_RECURSE "${flagTableDir}") + file(WRITE "${flagTableDir}/${VsNormal_Platform}_CL.json" "${flagTableContent}") + set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=${flagTableDir}") + set(RunCMake_TEST_VARIANT_DESCRIPTION ":${VsNormal_Platform}_CL.json") + run_cmake(TestToolsetCustomFlagTableDir) + unset(RunCMake_TEST_VARIANT_DESCRIPTION) + set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=does_not_exist") + run_cmake(BadToolsetCustomFlagTableDir) + endif() if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[2456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake new file mode 100644 index 00000000000..79752b1f23a --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake @@ -0,0 +1,24 @@ +set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/main.vcxproj") +if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file\n ${vcProjectFile}\ndoes not exist.") + return() +endif() + +set(TreatWarningAsError_FOUND FALSE) +file(STRINGS "${vcProjectFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES "^ *([^<>]*)$") + set(TreatWarningAsError_FOUND TRUE) + set(expectedValue "false") + set(actualValue "${CMAKE_MATCH_1}") + if(NOT (${actualValue} STREQUAL ${expectedValue})) + set(RunCMake_TEST_FAILED "TreatWarningAsError \"${actualValue}\" differs from expected value \"${expectedValue}\".") + return() + endif() + endif() +endforeach() + +if(NOT TreatWarningAsError_FOUND) + set(RunCMake_TEST_FAILED "Property TreatWarningAsError not found in project file:\n ${vcProjectFile}.") + return() +endif() diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake new file mode 100644 index 00000000000..91c6b443736 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir.cmake @@ -0,0 +1,3 @@ +enable_language(C) +string(APPEND CMAKE_C_FLAGS " -TESTWX-") +add_executable(main main.c) diff --git a/Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt b/Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt new file mode 100644 index 00000000000..25fa3bfbf85 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/VsNormal-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_NAME='[^']+' +-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+' diff --git a/Tests/RunCMake/GeneratorToolset/VsNormal.cmake b/Tests/RunCMake/GeneratorToolset/VsNormal.cmake new file mode 100644 index 00000000000..e891708d751 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/VsNormal.cmake @@ -0,0 +1,6 @@ +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/defaults.cmake" "# VS Defaults +set(VsNormal_Platform [[${CMAKE_VS_PLATFORM_NAME}]]) +set(VsNormal_Toolset [[${CMAKE_VS_PLATFORM_TOOLSET}]]) +") +message(STATUS "CMAKE_VS_PLATFORM_NAME='${CMAKE_VS_PLATFORM_NAME}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") diff --git a/Tests/RunCMake/GeneratorToolset/main.c b/Tests/RunCMake/GeneratorToolset/main.c new file mode 100644 index 00000000000..8488f4e58fe --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} From 8bc5c8961e552a15091b7f4d2c205ce90b8f764f Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 10 Mar 2021 14:59:14 -0500 Subject: [PATCH 0167/1519] CMakePresets.json: Add the ability to conditionally disable presets --- Help/manual/cmake-presets.7.rst | 96 +++++ Help/manual/presets/example.json | 13 +- Help/manual/presets/schema.json | 356 +++++++++++++++++- Help/release/dev/cmake-presets-condition.rst | 4 + Source/QtDialog/QCMake.cxx | 2 +- Source/cmCMakePresetsFile.cxx | 109 +++++- Source/cmCMakePresetsFile.h | 10 + Source/cmCMakePresetsFileInternal.h | 80 ++++ Source/cmCMakePresetsFileReadJSON.cxx | 205 +++++++++- Source/cmCTest.cxx | 7 + Source/cmJSONHelpers.h | 2 +- Source/cmake.cxx | 13 + .../CMakePresets/ConditionFuture-result.txt | 1 + .../CMakePresets/ConditionFuture-stderr.txt | 2 + .../CMakePresets/ConditionFuture.json.in | 11 + .../RunCMake/CMakePresets/Conditions.json.in | 349 +++++++++++++++++ .../CMakePresets/ListConditions-stdout.txt | 22 ++ .../RunCMake/CMakePresets/RunCMakeTest.cmake | 8 + .../CMakePresets/SimpleFalse-result.txt | 1 + .../CMakePresets/SimpleFalse-stderr.txt | 1 + Tests/RunCMake/CMakePresets/SimpleTrue.cmake | 0 .../CMakePresets/SubConditionNull-result.txt | 1 + .../CMakePresets/SubConditionNull-stderr.txt | 2 + .../CMakePresets/SubConditionNull.json.in | 14 + .../Condition-build-disabled-result.txt | 1 + .../Condition-build-disabled-stderr.txt | 2 + .../CMakePresetsBuild/Condition.cmake | 0 .../CMakePresetsBuild/Condition.json.in | 22 ++ ...ionFuture-build-conditionFuture-result.txt | 1 + ...ionFuture-build-conditionFuture-stderr.txt | 2 + .../CMakePresetsBuild/ConditionFuture.json.in | 17 + .../ListPresets-build-x-stdout.txt | 3 +- .../CMakePresetsBuild/ListPresets.json.in | 12 +- .../CMakePresetsBuild/RunCMakeTest.cmake | 2 + .../CMakePresetsTest/Condition.json.in | 22 ++ .../ConditionFuture-test-x-result.txt | 1 + .../ConditionFuture-test-x-stderr.txt | 2 + .../CMakePresetsTest/ConditionFuture.json.in | 17 + .../ConditionListPresets-test-x-stdout.txt | 3 + ...ConditionRunTests-test-disabled-result.txt | 1 + ...ConditionRunTests-test-disabled-stderr.txt | 2 + .../CMakePresetsTest/ConditionRunTests.cmake | 2 + .../CMakePresetsTest/RunCMakeTest.cmake | 7 + Utilities/IWYU/mapping.imp | 1 + 44 files changed, 1410 insertions(+), 19 deletions(-) create mode 100644 Help/release/dev/cmake-presets-condition.rst create mode 100644 Tests/RunCMake/CMakePresets/ConditionFuture-result.txt create mode 100644 Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/ConditionFuture.json.in create mode 100644 Tests/RunCMake/CMakePresets/Conditions.json.in create mode 100644 Tests/RunCMake/CMakePresets/ListConditions-stdout.txt create mode 100644 Tests/RunCMake/CMakePresets/SimpleFalse-result.txt create mode 100644 Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/SimpleTrue.cmake create mode 100644 Tests/RunCMake/CMakePresets/SubConditionNull-result.txt create mode 100644 Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/SubConditionNull.json.in create mode 100644 Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt create mode 100644 Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsBuild/Condition.cmake create mode 100644 Tests/RunCMake/CMakePresetsBuild/Condition.json.in create mode 100644 Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt create mode 100644 Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in create mode 100644 Tests/RunCMake/CMakePresetsTest/Condition.json.in create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 527323678b7..cc726032036 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -119,6 +119,11 @@ that may contain the following fields: This field can also be a string, which is equivalent to an array containing one string. +``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 @@ -345,6 +350,11 @@ that may contain the following fields: This field can also be a string, which is equivalent to an array containing one string. +``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 @@ -464,6 +474,11 @@ that may contain the following fields: This field can also be a string, which is equivalent to an array containing one string. +``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 @@ -789,6 +804,87 @@ that may contain the following fields: Equivalent to passing ``--no-tests=ignore`` on the command line. +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: + +``type`` + + A required string with one of the following values: + + ``"const"`` + + Indicates that the condition is constant. This is equivalent to using a + boolean in place of the object. The condition object will have the + following additional fields: + + ``value`` + + A required boolean which provides a constant value for the condition's + evaluation. + + ``"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: + + ``lhs`` + + First string to compare. This field supports macro expansion. + + ``rhs`` + + Second string to compare. This field supports macro expansion. + + ``"inList"`` + + ``"notInList"`` + + Indicates that the condition searches for a string in a list of strings. + The condition object will have the following additional fields: + + ``string`` + + A required string to search for. This field supports macro expansion. + + ``list`` + + A required list of strings to search. This field supports macro + expansion, and uses short-circuit evaluation. + + ``"anyOf"`` + + ``"allOf"`` + + Indicates that the condition is an aggregation of zero or more nested + conditions. The condition object will have the following additional fields: + + ``conditions`` + + A required array of condition objects. These conditions use short-circuit + evaluation. + + ``"not"`` + + Indicates that the condition is an inversion of another condition. The + condition object will have the following additional fields: + + ``condition`` + + A required condition object. + Macro Expansion ^^^^^^^^^^^^^^^ diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json index dfc2910a2c4..346f3425126 100644 --- a/Help/manual/presets/example.json +++ b/Help/manual/presets/example.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "cmakeMinimumRequired": { "major": 3, "minor": 20, @@ -35,6 +35,17 @@ "displayName": "Ninja Multi-Config", "description": "Default build using Ninja Multi-Config generator", "generator": "Ninja Multi-Config" + }, + { + "name": "windows-only", + "inherits": "default", + "displayName": "Windows-only configuration", + "description": "This build is only available on Windows", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } } ], "buildPresets": [ diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index a5025bb6a1e..dbcead5a70a 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -24,8 +24,8 @@ "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, "vendor": { "$ref": "#/definitions/vendor" }, "configurePresets": { "$ref": "#/definitions/configurePresetsV1"}, - "buildPresets": { "$ref": "#/definitions/buildPresets"}, - "testPresets": { "$ref": "#/definitions/testPresets"} + "buildPresets": { "$ref": "#/definitions/buildPresetsV2"}, + "testPresets": { "$ref": "#/definitions/testPresetsV2"} }, "additionalProperties": false }, @@ -38,8 +38,8 @@ "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, "vendor": { "$ref": "#/definitions/vendor" }, "configurePresets": { "$ref": "#/definitions/configurePresetsV3"}, - "buildPresets": { "$ref": "#/definitions/buildPresets"}, - "testPresets": { "$ref": "#/definitions/testPresets"} + "buildPresets": { "$ref": "#/definitions/buildPresetsV3"}, + "testPresets": { "$ref": "#/definitions/testPresetsV3"} }, "additionalProperties": false } @@ -82,7 +82,8 @@ "installDir": { "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)." - } + }, + "condition": { "$ref": "#/definitions/topCondition" } } } }, @@ -358,7 +359,8 @@ "environment": {}, "warnings": {}, "errors": {}, - "debug": {} + "debug": {}, + "condition": {} }, "required": [ "name" @@ -397,7 +399,17 @@ "additionalProperties": false } }, - "buildPresets": { + "buildPresetsItemsV3": { + "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", + "properties": { + "condition": { "$ref": "#/definitions/topCondition" } + } + } + }, + "buildPresetsItemsV2": { "type": "array", "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.", "items": { @@ -513,13 +525,86 @@ } } }, + "required": [ + "name" + ] + } + }, + "buildPresetsV3": { + "type": "array", + "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.", + "allOf": [ + { "$ref": "#/definitions/buildPresetsItemsV3" }, + { "$ref": "#/definitions/buildPresetsItemsV2" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "configurePreset": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "inheritConfigureEnvironment": {}, + "environment": {}, + "jobs": {}, + "targets": {}, + "configuration": {}, + "cleanFirst": {}, + "verbose": {}, + "nativeToolOptions": {}, + "condition": {} + }, "required": [ "name" ], "additionalProperties": false } }, - "testPresets": { + "buildPresetsV2": { + "type": "array", + "description": "An optional array of build preset objects. Used to specify arguments to cmake --build. Available in version 2 and higher.", + "allOf": [ + { "$ref": "#/definitions/buildPresetsItemsV2" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "configurePreset": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "inheritConfigureEnvironment": {}, + "environment": {}, + "jobs": {}, + "targets": {}, + "configuration": {}, + "cleanFirst": {}, + "verbose": {}, + "nativeToolOptions": {} + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "testPresetsItemsV3": { + "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", + "properties": { + "condition": { "$ref": "#/definitions/topCondition" } + } + } + }, + "testPresetsItemsV2": { "type": "array", "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.", "items": { @@ -829,11 +914,266 @@ "additionalProperties": false } }, + "required": [ + "name" + ] + } + }, + "testPresetsV3": { + "type": "array", + "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.", + "allOf": [ + { "$ref": "#/definitions/testPresetsItemsV2" }, + { "$ref": "#/definitions/testPresetsItemsV3" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "configurePreset": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "inheritConfigureEnvironment": {}, + "environment": {}, + "configuration": {}, + "overwriteConfigurationFile": {}, + "output": {}, + "filter": {}, + "execution": {}, + "condition": {} + }, "required": [ "name" ], "additionalProperties": false } + }, + "testPresetsV2": { + "type": "array", + "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 2 and higher.", + "allOf": [ + { "$ref": "#/definitions/testPresetsItemsV2" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "configurePreset": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "inheritConfigureEnvironment": {}, + "environment": {}, + "configuration": {}, + "overwriteConfigurationFile": {}, + "output": {}, + "filter": {}, + "execution": {} + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "condition": { + "anyOf": [ + { + "type": "boolean", + "description": "A boolean which provides a constant value for the condition's evaluation." + }, + { + "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" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "equals" + }, + "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" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "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" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "inList" + }, + "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" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "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" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "anyOf" + }, + "conditions": { + "type": "array", + "description": "A required array of condition objects. These conditions use short-circuit evaluation.", + "items": { "$ref": "#/definitions/condition" } + } + }, + "required": [ + "type", + "conditions" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "allOf" + }, + "conditions": { + "type": "array", + "description": "A required array of condition objects. These conditions use short-circuit evaluation.", + "items": { "$ref": "#/definitions/condition" } + } + }, + "required": [ + "type", + "conditions" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "not" + }, + "condition": { "$ref": "#/definitions/condition" } + }, + "required": [ + "type", + "condition" + ], + "additionalProperties": false + } + ] + }, + "topCondition": { + "anyOf": [ + { "$ref": "#/definitions/condition" }, + { + "type": "null", + "description": "Null indicates that the condition always evaluates to true and is not inherited." + } + ] } } } diff --git a/Help/release/dev/cmake-presets-condition.rst b/Help/release/dev/cmake-presets-condition.rst new file mode 100644 index 00000000000..aa01bc19a9d --- /dev/null +++ b/Help/release/dev/cmake-presets-condition.rst @@ -0,0 +1,4 @@ +cmake-presets-condition +----------------------- + +* :manual:`cmake-presets(7)` now support conditional enabling of presets. diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index f593f83583e..7d037e34dbc 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -557,7 +557,7 @@ void QCMake::loadPresets() preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data())); preset.setToolset = !p.ToolsetStrategy || p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set; - preset.enabled = it.Expanded && + preset.enabled = it.Expanded && it.Expanded->ConditionResult && std::find_if(this->AvailableGenerators.begin(), this->AvailableGenerators.end(), [&p](const cmake::GeneratorInfo& g) { diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index c0b09817c4f..fbe9fe59d5d 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -9,6 +9,8 @@ #include #include +#include + #include "cmCMakePresetsFileInternal.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -114,6 +116,14 @@ ReadFileResult VisitPreset( for (auto const& v : parentPreset.Environment) { preset.Environment.insert(v); } + + if (!preset.ConditionEvaluator) { + preset.ConditionEvaluator = parentPreset.ConditionEvaluator; + } + } + + if (preset.ConditionEvaluator && preset.ConditionEvaluator->IsNull()) { + preset.ConditionEvaluator.reset(); } CHECK_OK(preset.VisitPresetAfterInherit()) @@ -382,6 +392,19 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset, } } + if (preset.ConditionEvaluator) { + cm::optional result; + if (!preset.ConditionEvaluator->Evaluate( + macroExpanders, file.GetVersion(preset), result)) { + return false; + } + if (!result) { + out.reset(); + return true; + } + out->ConditionResult = *result; + } + return ExpandMacros(file, preset, out, macroExpanders); } @@ -505,6 +528,80 @@ ExpandMacroResult ExpandMacro(std::string& out, } } +bool cmCMakePresetsFileInternal::EqualsCondition::Evaluate( + const std::vector& expanders, int version, + cm::optional& out) const +{ + std::string lhs = this->Lhs; + CHECK_EXPAND(out, lhs, expanders, version); + + std::string rhs = this->Rhs; + CHECK_EXPAND(out, rhs, expanders, version); + + out = (lhs == rhs); + return true; +} + +bool cmCMakePresetsFileInternal::InListCondition::Evaluate( + const std::vector& expanders, int version, + cm::optional& out) const +{ + std::string str = this->String; + CHECK_EXPAND(out, str, expanders, version); + + for (auto item : this->List) { + CHECK_EXPAND(out, item, expanders, version); + if (str == item) { + out = true; + return true; + } + } + + out = false; + return true; +} + +bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate( + const std::vector& expanders, int version, + cm::optional& out) const +{ + for (auto const& condition : this->Conditions) { + cm::optional result; + if (!condition->Evaluate(expanders, version, result)) { + out.reset(); + return false; + } + + if (!result) { + out.reset(); + return true; + } + + if (result == this->StopValue) { + out = result; + return true; + } + } + + out = !this->StopValue; + return true; +} + +bool cmCMakePresetsFileInternal::NotCondition::Evaluate( + const std::vector& expanders, int version, + cm::optional& out) const +{ + out.reset(); + if (!this->SubCondition->Evaluate(expanders, version, out)) { + out.reset(); + return false; + } + if (out) { + *out = !*out; + } + return true; +} + cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit( const cmCMakePresetsFile::Preset& parentPreset) @@ -862,6 +959,10 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result) case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED: return "File version must be 3 or higher for installDir preset " "support."; + case ReadFileResult::INVALID_CONDITION: + return "Invalid preset condition"; + case ReadFileResult::CONDITION_UNSUPPORTED: + return "File version must be 3 or higher for condition support"; } return "Unknown error"; @@ -918,7 +1019,7 @@ void cmCMakePresetsFile::PrintConfigurePresetList( for (auto const& p : this->ConfigurePresetOrder) { auto const& preset = this->ConfigurePresets.at(p); if (!preset.Unexpanded.Hidden && preset.Expanded && - filter(preset.Unexpanded)) { + preset.Expanded->ConditionResult && filter(preset.Unexpanded)) { presets.push_back( static_cast(&preset.Unexpanded)); } @@ -935,7 +1036,8 @@ void cmCMakePresetsFile::PrintBuildPresetList() const std::vector presets; for (auto const& p : this->BuildPresetOrder) { auto const& preset = this->BuildPresets.at(p); - if (!preset.Unexpanded.Hidden && preset.Expanded) { + if (!preset.Unexpanded.Hidden && preset.Expanded && + preset.Expanded->ConditionResult) { presets.push_back( static_cast(&preset.Unexpanded)); } @@ -952,7 +1054,8 @@ void cmCMakePresetsFile::PrintTestPresetList() const std::vector presets; for (auto const& p : this->TestPresetOrder) { auto const& preset = this->TestPresets.at(p); - if (!preset.Unexpanded.Hidden && preset.Expanded) { + if (!preset.Unexpanded.Hidden && preset.Expanded && + preset.Expanded->ConditionResult) { presets.push_back( static_cast(&preset.Unexpanded)); } diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index 02e6a321d7b..0999d5a1a59 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -2,8 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include "cmConfigure.h" // IWYU pragma: keep + #include #include +#include #include #include #include @@ -34,6 +37,8 @@ class cmCMakePresetsFile BUILD_TEST_PRESETS_UNSUPPORTED, INVALID_CONFIGURE_PRESET, INSTALL_PREFIX_UNSUPPORTED, + INVALID_CONDITION, + CONDITION_UNSUPPORTED, }; enum class ArchToolsetStrategy @@ -49,6 +54,8 @@ class cmCMakePresetsFile std::string Value; }; + class Condition; + class Preset { public: @@ -71,6 +78,9 @@ class cmCMakePresetsFile std::string DisplayName; std::string Description; + std::shared_ptr ConditionEvaluator; + bool ConditionResult = true; + std::map> Environment; virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0; diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h index f05b8ce4a14..ffb6ce93a6c 100644 --- a/Source/cmCMakePresetsFileInternal.h +++ b/Source/cmCMakePresetsFileInternal.h @@ -1,5 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#include + #include "cmCMakePresetsFile.h" #define CHECK_OK(expr) \ @@ -20,3 +22,81 @@ enum class ExpandMacroResult using MacroExpander = std::function; } + +class cmCMakePresetsFile::Condition +{ +public: + virtual ~Condition() = default; + + virtual bool Evaluate( + const std::vector& expanders, + int version, cm::optional& out) const = 0; + virtual bool IsNull() const { return false; } +}; + +namespace cmCMakePresetsFileInternal { + +class NullCondition : public cmCMakePresetsFile::Condition +{ + bool Evaluate(const std::vector& /*expanders*/, + int /*version*/, cm::optional& out) const override + { + out = true; + return true; + } + + bool IsNull() const override { return true; } +}; + +class ConstCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector& /*expanders*/, + int /*version*/, cm::optional& out) const override + { + out = this->Value; + return true; + } + + bool Value; +}; + +class EqualsCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector& expanders, int version, + cm::optional& out) const override; + + std::string Lhs; + std::string Rhs; +}; + +class InListCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector& expanders, int version, + cm::optional& out) const override; + + std::string String; + std::vector List; +}; + +class AnyAllOfCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector& expanders, int version, + cm::optional& out) const override; + + std::vector> Conditions; + bool StopValue; +}; + +class NotCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector& expanders, int version, + cm::optional& out) const override; + + std::unique_ptr SubCondition; +}; +} diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx index b71b17602eb..e26e7b47e70 100644 --- a/Source/cmCMakePresetsFileReadJSON.cxx +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -15,6 +16,7 @@ #include "cmsys/FStream.hxx" #include "cmCMakePresetsFile.h" +#include "cmCMakePresetsFileInternal.h" #include "cmJSONHelpers.h" #include "cmVersion.h" @@ -44,6 +46,180 @@ struct RootPresets std::vector TestPresets; }; +std::unique_ptr InvertCondition( + std::unique_ptr condition) +{ + auto retval = cm::make_unique(); + retval->SubCondition = std::move(condition); + return retval; +} + +auto const ConditionStringHelper = cmJSONStringHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); + +auto const ConditionBoolHelper = cmJSONBoolHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION); + +auto const ConditionStringListHelper = + cmJSONVectorHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, + ConditionStringHelper); + +auto const ConstConditionHelper = + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind("type"_s, nullptr, ConditionStringHelper, true) + .Bind("value"_s, &cmCMakePresetsFileInternal::ConstCondition::Value, + ConditionBoolHelper, true); + +auto const EqualsConditionHelper = + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind("type"_s, nullptr, ConditionStringHelper, true) + .Bind("lhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Lhs, + ConditionStringHelper, true) + .Bind("rhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Rhs, + ConditionStringHelper, true); + +auto const InListConditionHelper = + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind("type"_s, nullptr, ConditionStringHelper, true) + .Bind("string"_s, &cmCMakePresetsFileInternal::InListCondition::String, + ConditionStringHelper, true) + .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List, + ConditionStringListHelper, true); + +ReadFileResult SubConditionHelper( + std::unique_ptr& out, + const Json::Value* value); + +auto const ListConditionVectorHelper = + cmJSONVectorHelper, + ReadFileResult>(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, + SubConditionHelper); +auto const AnyAllOfConditionHelper = + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind("type"_s, nullptr, ConditionStringHelper, true) + .Bind("conditions"_s, + &cmCMakePresetsFileInternal::AnyAllOfCondition::Conditions, + ListConditionVectorHelper); + +auto const NotConditionHelper = + cmJSONObjectHelper( + ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false) + .Bind("type"_s, nullptr, ConditionStringHelper, true) + .Bind("condition"_s, + &cmCMakePresetsFileInternal::NotCondition::SubCondition, + SubConditionHelper); + +ReadFileResult ConditionHelper( + std::unique_ptr& out, + const Json::Value* value) +{ + if (!value) { + out.reset(); + return ReadFileResult::READ_OK; + } + + if (value->isBool()) { + auto c = cm::make_unique(); + c->Value = value->asBool(); + out = std::move(c); + return ReadFileResult::READ_OK; + } + + if (value->isNull()) { + out = cm::make_unique(); + return ReadFileResult::READ_OK; + } + + if (value->isObject()) { + if (!value->isMember("type")) { + return ReadFileResult::INVALID_CONDITION; + } + + if (!(*value)["type"].isString()) { + return ReadFileResult::INVALID_CONDITION; + } + auto type = (*value)["type"].asString(); + + if (type == "const") { + auto c = cm::make_unique(); + CHECK_OK(ConstConditionHelper(*c, value)); + out = std::move(c); + return ReadFileResult::READ_OK; + } + + if (type == "equals" || type == "notEquals") { + auto c = cm::make_unique(); + CHECK_OK(EqualsConditionHelper(*c, value)); + out = std::move(c); + if (type == "notEquals") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + + if (type == "inList" || type == "notInList") { + auto c = cm::make_unique(); + CHECK_OK(InListConditionHelper(*c, value)); + out = std::move(c); + if (type == "notInList") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + + if (type == "anyOf" || type == "allOf") { + auto c = + cm::make_unique(); + c->StopValue = (type == "anyOf"); + CHECK_OK(AnyAllOfConditionHelper(*c, value)); + out = std::move(c); + return ReadFileResult::READ_OK; + } + + if (type == "not") { + auto c = cm::make_unique(); + CHECK_OK(NotConditionHelper(*c, value)); + out = std::move(c); + return ReadFileResult::READ_OK; + } + } + + return ReadFileResult::INVALID_CONDITION; +} + +ReadFileResult PresetConditionHelper( + std::shared_ptr& out, + const Json::Value* value) +{ + std::unique_ptr ptr; + auto result = ConditionHelper(ptr, value); + out = std::move(ptr); + return result; +} + +ReadFileResult SubConditionHelper( + std::unique_ptr& out, + const Json::Value* value) +{ + std::unique_ptr ptr; + auto result = ConditionHelper(ptr, value); + if (ptr && ptr->IsNull()) { + return ReadFileResult::INVALID_CONDITION; + } + out = std::move(ptr); + return result; +} + cmJSONHelper VendorHelper(ReadFileResult error) { return [error](std::nullptr_t& /*out*/, @@ -306,7 +482,9 @@ auto const ConfigurePresetHelper = false) .Bind("warnings"_s, PresetWarningsHelper, false) .Bind("errors"_s, PresetErrorsHelper, false) - .Bind("debug"_s, PresetDebugHelper, false); + .Bind("debug"_s, PresetDebugHelper, false) + .Bind("condition"_s, &ConfigurePreset::ConditionEvaluator, + PresetConditionHelper, false); auto const BuildPresetHelper = cmJSONObjectHelper( @@ -335,7 +513,9 @@ auto const BuildPresetHelper = false) .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false) .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions, - PresetVectorStringHelper, false); + PresetVectorStringHelper, false) + .Bind("condition"_s, &BuildPreset::ConditionEvaluator, + PresetConditionHelper, false); ReadFileResult TestPresetOutputVerbosityHelper( TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value) @@ -651,7 +831,9 @@ auto const TestPresetHelper = false) .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false) .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper, - false); + false) + .Bind("condition"_s, &TestPreset::ConditionEvaluator, + PresetConditionHelper, false); auto const ConfigurePresetsHelper = cmJSONVectorHelper( @@ -766,6 +948,11 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED; } + // Support for conditions added in version 3. + if (v < 3 && preset.ConditionEvaluator) { + return ReadFileResult::CONDITION_UNSUPPORTED; + } + this->ConfigurePresetOrder.push_back(preset.Name); } @@ -781,6 +968,12 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( if (!this->BuildPresets.emplace(preset.Name, presetPair).second) { return ReadFileResult::DUPLICATE_PRESETS; } + + // Support for conditions added in version 3. + if (v < 3 && preset.ConditionEvaluator) { + return ReadFileResult::CONDITION_UNSUPPORTED; + } + this->BuildPresetOrder.push_back(preset.Name); } @@ -796,6 +989,12 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( if (!this->TestPresets.emplace(preset.Name, presetPair).second) { return ReadFileResult::DUPLICATE_PRESETS; } + + // Support for conditions added in version 3. + if (v < 3 && preset.ConditionEvaluator) { + return ReadFileResult::CONDITION_UNSUPPORTED; + } + this->TestPresetOrder.push_back(preset.Name); } diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 77b44417c4c..4228d307e8c 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2310,6 +2310,13 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, return false; } + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled test preset in ", + workingDirectory, ": \"", presetName, '"')); + settingsFile.PrintTestPresetList(); + return false; + } + auto configurePresetPair = settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset); if (configurePresetPair == settingsFile.ConfigurePresets.end()) { diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h index a63347d6541..6690aef848b 100644 --- a/Source/cmJSONHelpers.h +++ b/Source/cmJSONHelpers.h @@ -239,7 +239,7 @@ cmJSONHelper, E> cmJSONVectorFilterHelper(E success, E fail, if (!filter(t)) { continue; } - out.push_back(t); + out.push_back(std::move(t)); } return success; }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b12eeee7f31..61ce154a7b2 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1217,6 +1217,11 @@ void cmake::SetArgs(const std::vector& args) "\": 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) { this->SetHomeOutputDirectory(expandedPreset->BinaryDir); @@ -3164,6 +3169,14 @@ int cmake::Build(int jobs, std::string dir, std::vector targets, return 1; } + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled build preset in ", + this->GetHomeDirectory(), ": \"", + presetName, '"')); + settingsFile.PrintBuildPresetList(); + return 1; + } + auto configurePresetPair = settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset); if (configurePresetPair == settingsFile.ConfigurePresets.end()) { diff --git a/Tests/RunCMake/CMakePresets/ConditionFuture-result.txt b/Tests/RunCMake/CMakePresets/ConditionFuture-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ConditionFuture-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt b/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt new file mode 100644 index 00000000000..ea5f47f653a --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ConditionFuture-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/ConditionFuture: File version must be 3 or higher for condition support$ diff --git a/Tests/RunCMake/CMakePresets/ConditionFuture.json.in b/Tests/RunCMake/CMakePresets/ConditionFuture.json.in new file mode 100644 index 00000000000..9d4798b58b9 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ConditionFuture.json.in @@ -0,0 +1,11 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "ConditionFuture", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "condition": true + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/Conditions.json.in b/Tests/RunCMake/CMakePresets/Conditions.json.in new file mode 100644 index 00000000000..9a01e2f0385 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/Conditions.json.in @@ -0,0 +1,349 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "Base", + "hidden": true, + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + }, + { + "name": "SimpleTrue", + "inherits": "Base", + "condition": true + }, + { + "name": "SimpleFalse", + "inherits": "Base", + "condition": false + }, + { + "name": "Null", + "inherits": "Base", + "condition": null + }, + { + "name": "ConstTrue", + "inherits": "Base", + "condition": { + "type": "const", + "value": true + } + }, + { + "name": "ConstFalse", + "inherits": "Base", + "condition": { + "type": "const", + "value": false + } + }, + { + "name": "EqualsTrue", + "inherits": "Base", + "condition": { + "type": "equals", + "lhs": "abc", + "rhs": "abc" + } + }, + { + "name": "EqualsFalse", + "inherits": "Base", + "condition": { + "type": "equals", + "lhs": "abc", + "rhs": "abcd" + } + }, + { + "name": "EqualsMacroLeft", + "inherits": "Base", + "condition": { + "type": "equals", + "lhs": "${presetName}", + "rhs": "EqualsMacroLeft" + } + }, + { + "name": "EqualsMacroRight", + "inherits": "Base", + "condition": { + "type": "equals", + "lhs": "EqualsMacroRight", + "rhs": "${presetName}" + } + }, + { + "name": "NotEqualsTrue", + "inherits": "Base", + "condition": { + "type": "notEquals", + "lhs": "abc", + "rhs": "abcd" + } + }, + { + "name": "NotEqualsFalse", + "inherits": "Base", + "condition": { + "type": "notEquals", + "lhs": "abc", + "rhs": "abc" + } + }, + { + "name": "InListTrue", + "inherits": "Base", + "condition": { + "type": "inList", + "string": "b", + "list": [ + "a", + "b", + "c" + ] + } + }, + { + "name": "InListFalse", + "inherits": "Base", + "condition": { + "type": "inList", + "string": "d", + "list": [ + "a", + "b", + "c" + ] + } + }, + { + "name": "InListMacroString", + "inherits": "Base", + "condition": { + "type": "inList", + "string": "${presetName}", + "list": [ + "InListMacroString", + "AnotherString" + ] + } + }, + { + "name": "InListMacroList", + "inherits": "Base", + "condition": { + "type": "inList", + "string": "InListMacroList", + "list": [ + "${presetName}", + "AnotherString" + ] + } + }, + { + "name": "InListShortCircuit", + "inherits": "Base", + "condition": { + "type": "inList", + "string": "a", + "list": [ + "a", + "${invalidMacro}" + ] + } + }, + { + "name": "NotInListTrue", + "inherits": "Base", + "condition": { + "type": "notInList", + "string": "d", + "list": [ + "a", + "b", + "c" + ] + } + }, + { + "name": "NotInListFalse", + "inherits": "Base", + "condition": { + "type": "notInList", + "string": "a", + "list": [ + "a", + "b", + "c" + ] + } + }, + { + "name": "AnyOfTrue1", + "inherits": "Base", + "condition": { + "type": "anyOf", + "conditions": [ + true, + false + ] + } + }, + { + "name": "AnyOfTrue2", + "inherits": "Base", + "condition": { + "type": "anyOf", + "conditions": [ + false, + true + ] + } + }, + { + "name": "AnyOfFalse", + "inherits": "Base", + "condition": { + "type": "anyOf", + "conditions": [ + false, + { + "type": "equals", + "lhs": "abc", + "rhs": "abcd" + } + ] + } + }, + { + "name": "AnyOfShortCircuit", + "inherits": "Base", + "condition": { + "type": "anyOf", + "conditions": [ + true, + { + "type": "equals", + "lhs": "${invalidMacro}", + "rhs": "" + } + ] + } + }, + { + "name": "AnyOfEmpty", + "inherits": "Base", + "condition": { + "type": "anyOf", + "conditions": [] + } + }, + { + "name": "AllOfTrue", + "inherits": "Base", + "condition": { + "type": "allOf", + "conditions": [ + true, + { + "type": "equals", + "lhs": "abc", + "rhs": "abc" + } + ] + } + }, + { + "name": "AllOfFalse1", + "inherits": "Base", + "condition": { + "type": "allOf", + "conditions": [ + false, + true + ] + } + }, + { + "name": "AllOfFalse2", + "inherits": "Base", + "condition": { + "type": "allOf", + "conditions": [ + true, + false + ] + } + }, + { + "name": "AllOfShortCircuit", + "inherits": "Base", + "condition": { + "type": "allOf", + "conditions": [ + false, + { + "type": "equals", + "lhs": "${invalidMacro}", + "rhs": "" + } + ] + } + }, + { + "name": "AllOfEmpty", + "inherits": "Base", + "condition": { + "type": "allOf", + "conditions": [] + } + }, + { + "name": "NotTrue", + "inherits": "Base", + "condition": { + "type": "not", + "condition": true + } + }, + { + "name": "NotFalse", + "inherits": "Base", + "condition": { + "type": "not", + "condition": false + } + }, + { + "name": "InheritanceBase", + "inherits": "Base", + "hidden": true, + "condition": { + "type": "equals", + "lhs": "${presetName}", + "rhs": "InheritanceChildTrue" + } + }, + { + "name": "InheritanceChildTrue", + "inherits": "InheritanceBase" + }, + { + "name": "InheritanceChildFalse", + "inherits": "InheritanceBase" + }, + { + "name": "InheritanceNull", + "inherits": "Null" + }, + { + "name": "InheritanceNullFalse", + "inherits": [ + "Null", + "SimpleFalse" + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt new file mode 100644 index 00000000000..19f91d4e835 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt @@ -0,0 +1,22 @@ +Available configure presets: + + "SimpleTrue" + "Null" + "ConstTrue" + "EqualsTrue" + "EqualsMacroLeft" + "EqualsMacroRight" + "NotEqualsTrue" + "InListTrue" + "InListMacroString" + "InListMacroList" + "InListShortCircuit" + "NotInListTrue" + "AnyOfTrue1" + "AnyOfTrue2" + "AnyOfShortCircuit" + "AllOfTrue" + "AllOfEmpty" + "NotFalse" + "InheritanceChildTrue" + "InheritanceNull"$ diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 24ac0e985e7..22425b24aab 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -118,6 +118,8 @@ run_cmake_presets(EnvCycle) run_cmake_presets(EmptyEnv) run_cmake_presets(EmptyPenv) set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) +run_cmake_presets(ConditionFuture) +run_cmake_presets(SubConditionNull) # Test cmakeMinimumRequired field run_cmake_presets(MinimumRequiredInvalid) @@ -267,6 +269,12 @@ run_cmake_presets(HostSystemName) set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/HostSystemNameFuture.json.in") run_cmake_presets(HostSystemNameFuture) +# Test conditions +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Conditions.json.in") +run_cmake_presets(ListConditions --list-presets) +run_cmake_presets(SimpleTrue) +run_cmake_presets(SimpleFalse) + # Test the example from the documentation file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example) string(REPLACE "\"generator\": \"Ninja\"" "\"generator\": \"@RunCMake_GENERATOR@\"" _example "${_example}") diff --git a/Tests/RunCMake/CMakePresets/SimpleFalse-result.txt b/Tests/RunCMake/CMakePresets/SimpleFalse-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/SimpleFalse-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt b/Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt new file mode 100644 index 00000000000..6a9a7dea2a5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/SimpleFalse-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Could not use disabled preset "SimpleFalse"$ diff --git a/Tests/RunCMake/CMakePresets/SimpleTrue.cmake b/Tests/RunCMake/CMakePresets/SimpleTrue.cmake new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/CMakePresets/SubConditionNull-result.txt b/Tests/RunCMake/CMakePresets/SubConditionNull-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/SubConditionNull-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt b/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt new file mode 100644 index 00000000000..42b74d61771 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/SubConditionNull-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/SubConditionNull: Invalid preset condition$ diff --git a/Tests/RunCMake/CMakePresets/SubConditionNull.json.in b/Tests/RunCMake/CMakePresets/SubConditionNull.json.in new file mode 100644 index 00000000000..eed3da689bc --- /dev/null +++ b/Tests/RunCMake/CMakePresets/SubConditionNull.json.in @@ -0,0 +1,14 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "SubConditionNull", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "condition": { + "type": "not", + "condition": null + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt new file mode 100644 index 00000000000..c35f5d7d83b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/Condition-build-disabled-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Cannot use disabled build preset in [^ +]*/Tests/RunCMake/CMakePresetsBuild/Condition: "disabled"$ diff --git a/Tests/RunCMake/CMakePresetsBuild/Condition.cmake b/Tests/RunCMake/CMakePresetsBuild/Condition.cmake new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/CMakePresetsBuild/Condition.json.in b/Tests/RunCMake/CMakePresetsBuild/Condition.json.in new file mode 100644 index 00000000000..aaee96a8deb --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/Condition.json.in @@ -0,0 +1,22 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "buildPresets": [ + { + "name": "enabled", + "configurePreset": "default", + "condition": true + }, + { + "name": "disabled", + "configurePreset": "default", + "condition": false + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt new file mode 100644 index 00000000000..f08f4c11bae --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture-build-conditionFuture-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsBuild/ConditionFuture: File version must be 3 or higher for condition support$ diff --git a/Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in new file mode 100644 index 00000000000..2f3f7d8513f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/ConditionFuture.json.in @@ -0,0 +1,17 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "buildPresets": [ + { + "name": "conditionFuture", + "configurePreset": "default", + "condition": true + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt b/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt index 4d30707d416..2d362d4f502 100644 --- a/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt +++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt @@ -1,5 +1,6 @@ -Available build presets: +^Available build presets: "build-default" - build-default displayName "empty" "display" - display displayName + "true"$ diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in b/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in index 3f5e02c25c3..26504d309f5 100644 --- a/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in +++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in @@ -1,5 +1,5 @@ { - "version": 2, + "version": 3, "configurePresets": [ { "name": "default", @@ -26,6 +26,16 @@ { "name": "hidden", "hidden": true + }, + { + "name": "true", + "inherits": "build-default", + "condition": true + }, + { + "name": "false", + "inherits": "build-default", + "condition": false } ] } diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake index 2559b12a791..afa22eb715f 100644 --- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake @@ -64,6 +64,7 @@ set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject") run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset") +run_cmake_build_presets(Condition "default" "enabled;disabled") set(CMakePresetsBuild_BUILD_ONLY 1) run_cmake_build_presets(ListPresets "x" "x" "--list-presets") @@ -72,5 +73,6 @@ run_cmake_build_presets(Invalid "x" "hidden;vendorMacro") set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) run_cmake_build_presets(PresetsUnsupported "x" "x") +run_cmake_build_presets(ConditionFuture "x" "conditionFuture") set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) set(CMakePresetsBuild_BUILD_ONLY 0) diff --git a/Tests/RunCMake/CMakePresetsTest/Condition.json.in b/Tests/RunCMake/CMakePresetsTest/Condition.json.in new file mode 100644 index 00000000000..0baf17613e7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Condition.json.in @@ -0,0 +1,22 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "testPresets": [ + { + "name": "enabled", + "configurePreset": "default", + "condition": true + }, + { + "name": "disabled", + "configurePreset": "default", + "condition": false + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt new file mode 100644 index 00000000000..b814bbb94b7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture-test-x-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsTest/ConditionFuture: File version must be 3 or higher for condition support$ diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in b/Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in new file mode 100644 index 00000000000..4b9f33f66ee --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionFuture.json.in @@ -0,0 +1,17 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "testPresets": [ + { + "name": "conditionFuture", + "configurePreset": "default", + "condition": true + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt b/Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt new file mode 100644 index 00000000000..11918e51907 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionListPresets-test-x-stdout.txt @@ -0,0 +1,3 @@ +^Available test presets: + + "enabled"$ diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt new file mode 100644 index 00000000000..5db3b77e670 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests-test-disabled-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Cannot use disabled test preset in [^ +]*/Tests/RunCMake/CMakePresetsTest/ConditionRunTests: "disabled"$ diff --git a/Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake new file mode 100644 index 00000000000..b29161edfa7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/ConditionRunTests.cmake @@ -0,0 +1,2 @@ +enable_testing() +add_test(true ${CMAKE_COMMAND} -E true) diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake index c93dff36f5a..70d25d4ec14 100644 --- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake @@ -90,6 +90,12 @@ run_cmake_test_presets(InvalidConfigurePreset "default" "" "badConfigurePreset") set(CMakePresetsTest_NO_CONFIGURE 1) set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Good.json.in") run_cmake_test_presets(ListPresets "" "" "x" "--list-presets") + +set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Condition.json.in") +run_cmake_test_presets(ConditionListPresets "" "" "x" "--list-presets") +unset(CMakePresetsTest_NO_CONFIGURE) +run_cmake_test_presets(ConditionRunTests "default" "" "enabled;disabled") +set(CMakePresetsTest_NO_CONFIGURE 1) unset(CMakePresetsTest_FILE) run_cmake_test_presets(NoConfigurePreset "" "" "noConfigurePreset") @@ -98,6 +104,7 @@ run_cmake_test_presets(Invalid "" "" "hidden;vendorMacro") set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) run_cmake_test_presets(PresetsUnsupported "" "" "x") +run_cmake_test_presets(ConditionFuture "" "" "x") set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) set(CMakePresetsTest_NO_CONFIGURE 0) diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index c2aced594c9..f2aef3ecac7 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -96,6 +96,7 @@ { symbol: [ "std::enable_if > >::type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::enable_if > >::type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::enable_if > >::type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "__gnu_cxx::__enable_if::__type", private, "\"cmConfigure.h\"", public ] }, # Wrappers for 3rd-party libraries { include: [ "@<.*curl/curlver.h>", private, "", public ] }, From 6e7ff52af74cfbff15ded5c3aba7097499dffd32 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 23 Mar 2021 00:01:09 -0400 Subject: [PATCH 0168/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 17f26a876ed..d106195dc5c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210322) +set(CMake_VERSION_PATCH 20210323) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 88060f471766222c54a080900f73abf29586a6f4 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 24 Mar 2021 00:01:16 -0400 Subject: [PATCH 0169/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d106195dc5c..d86d725d53d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210323) +set(CMake_VERSION_PATCH 20210324) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f536e6f3fb588e2cb8ab86a1f4eab75db011cefa Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Wed, 24 Mar 2021 18:22:38 +1100 Subject: [PATCH 0170/1519] CPackIFW: Remove redundant variable assignment This was showing up in cppcheck results. --- Source/CPack/IFW/cmCPackIFWPackage.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index c4bd7f115b8..5191c96e30b 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -31,7 +31,7 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct( const std::string& dependence) { // Search compare section - size_t pos = std::string::npos; + size_t pos; if ((pos = dependence.find("<=")) != std::string::npos) { this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; this->Compare.Value = dependence.substr(pos + 2); From d1b23dd4680fb39cd315980bbfd720e8cc39cafc Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 24 Mar 2021 12:35:35 -0400 Subject: [PATCH 0171/1519] gitlab-ci: update Intel Compiler base image tag naming convention --- .gitlab-ci.yml | 58 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f996e8772b..465dc2caa82 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -179,203 +179,203 @@ test:intel2016-makefiles: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2016_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016-el7 test:intel2016u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2016u1_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u1-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u1-el7 test:intel2016u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2016u2_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u2-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u2-el7 test:intel2017-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017-el7 test:intel2017u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u1_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u1-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u1-el7 test:intel2017u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u2_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u2-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u2-el7 test:intel2017u3-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u3_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u3-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u3-el7 test:intel2017u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u4_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u4-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u4-el7 test:intel2017u5-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u5_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u5-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u5-el7 test:intel2017u6-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u6_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u6-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u6-el7 test:intel2017u7-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u7_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u7-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u7-el7 test:intel2017u8-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u8_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u8-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u8-el7 test:intel2018-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018-el7 test:intel2018u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u1_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u1-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u1-el7 test:intel2018u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u2_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u2-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u2-el7 test:intel2018u3-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u3_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u3-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u3-el7 test:intel2018u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u4_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u4-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u4-el7 test:intel2019-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019-el7 test:intel2019u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u1_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u1-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u1-el7 test:intel2019u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u2_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u2-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u2-el7 test:intel2019u3-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u3_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u3-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u3-el7 test:intel2019u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u4_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u4-centos7 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u4-el7 test:intel2020-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2020_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020-el8 test:intel2020u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2020u2_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u2-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u2-el8 test:intel2020u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2020u4_makefiles - CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u4-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u4-el8 test: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-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.1-el8 test: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-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8 test: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-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.1-el8 test: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-rhel8 + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8 build:linux-x86_64-package: extends: From c0aa4244f5b1900c280b54a5453cc881dc7d3d95 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 25 Mar 2021 00:01:17 -0400 Subject: [PATCH 0172/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d86d725d53d..dd9f4cbf579 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210324) +set(CMake_VERSION_PATCH 20210325) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 238c2b6cb7e96a6024108b3657f7d8bec6fa07f2 Mon Sep 17 00:00:00 2001 From: Pedro Luis Castedo Cepeda Date: Thu, 25 Mar 2021 20:17:28 +0100 Subject: [PATCH 0173/1519] FindRuby: Consider ruby names with full nodot version suffixes --- Modules/FindRuby.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index ee07f83451f..759f57c22d9 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -435,7 +435,7 @@ endif() # Determine the list of possible names for the ruby library -set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION}) +set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby${_Ruby_NODOT_VERSION} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION}) if(WIN32) set(_Ruby_POSSIBLE_MSVC_RUNTIMES "msvcrt;vcruntime140;vcruntime140_1") From 2fe39dc30614f8fd7d0c37a68e8e7e3eb20f445a Mon Sep 17 00:00:00 2001 From: Matt Jaeger Date: Thu, 25 Mar 2021 11:56:36 -0700 Subject: [PATCH 0174/1519] cmake: Fix loading CMake sources from long paths on Windows Pass a Windows extended path to the lexer so it can open long paths. --- Source/cmListFileCache.cxx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 1464a14cc58..5c3a0344dc3 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -7,6 +7,10 @@ #include #include +#ifdef _WIN32 +# include +#endif + #include "cmListFileLexer.h" #include "cmMessageType.h" #include "cmMessenger.h" @@ -83,9 +87,15 @@ bool cmListFileParser::ParseFile(const char* filename) { this->FileName = filename; +#ifdef _WIN32 + std::string expandedFileName = cmsys::Encoding::ToNarrow( + cmSystemTools::ConvertToWindowsExtendedPath(filename)); + filename = expandedFileName.c_str(); +#endif + // Open the file. cmListFileLexer_BOM bom; - if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) { + if (!cmListFileLexer_SetFileName(this->Lexer, filename, &bom)) { this->IssueFileOpenError("cmListFileCache: error can not open file."); return false; } From 739446a9a1975367b2c9a6b105b3fde1656c725b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 25 Mar 2021 16:54:08 -0400 Subject: [PATCH 0175/1519] FindDoxygen: clarify the CMake variable naming scheme --- Modules/FindDoxygen.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake index 7fe5da137f8..4a16e316a61 100644 --- a/Modules/FindDoxygen.cmake +++ b/Modules/FindDoxygen.cmake @@ -223,7 +223,8 @@ them to be separated by whitespace. CMake variables hold lists as a string with items separated by semi-colons, so a conversion needs to be performed. The ``doxygen_add_docs()`` command specifically checks the following Doxygen config options and will convert their associated CMake variable's contents into the -required form if set. +required form if set. CMake variables are named ``DOXYGEN_`` for the +Doxygen settings specified here. :: From 61fd90b90c9dfec154aee7fb4d97574921e651d1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 26 Mar 2021 00:01:21 -0400 Subject: [PATCH 0176/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index dd9f4cbf579..fa9d567d79c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210325) +set(CMake_VERSION_PATCH 20210326) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3706e9c97cef2ad8097adfd4ed2f04ff08398787 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 26 Mar 2021 09:34:18 -0400 Subject: [PATCH 0177/1519] Help: Convert project() directory variables to a definition list --- Help/command/project.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Help/command/project.rst b/Help/command/project.rst index 6c931b692ae..a726cbba6f0 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -20,12 +20,13 @@ Sets the name of the project, and stores it in the variable ``CMakeLists.txt`` also stores the project name in the variable :variable:`CMAKE_PROJECT_NAME`. -Also sets the variables +Also sets the variables: -* :variable:`PROJECT_SOURCE_DIR`, - :variable:`_SOURCE_DIR` -* :variable:`PROJECT_BINARY_DIR`, - :variable:`_BINARY_DIR` +:variable:`PROJECT_SOURCE_DIR`, :variable:`_SOURCE_DIR` + Absolute path to the source directory for the project. + +:variable:`PROJECT_BINARY_DIR`, :variable:`_BINARY_DIR` + Absolute path to the binary directory for the project. Further variables are set by the optional arguments described in the following. If any of these arguments is not used, then the corresponding variables are From 96a704010713833e9ec17fa78495df3e0852bbf5 Mon Sep 17 00:00:00 2001 From: friendlyanon Date: Wed, 24 Mar 2021 19:59:14 +0000 Subject: [PATCH 0178/1519] project: Define variables indicating whether project is top level Define `PROJECT_IS_TOP_LEVEL` and `_IS_TOP_LEVEL`. The latter is a STATIC cache entry just like other `_*` variables so that it is globally scoped. Issue: #20310 Fixes: #21961 --- Help/command/project.rst | 5 +++++ Help/manual/cmake-variables.7.rst | 2 ++ Help/release/dev/project-is-top-level.rst | 6 ++++++ Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst | 11 ++++++++++ Help/variable/PROJECT_IS_TOP_LEVEL.rst | 21 +++++++++++++++++++ Source/cmProjectCommand.cxx | 5 +++++ .../project/ProjectIsTopLevel-stdout.txt | 2 ++ .../RunCMake/project/ProjectIsTopLevel.cmake | 9 ++++++++ .../ProjectIsTopLevelMultiple-stdout.txt | 3 +++ .../project/ProjectIsTopLevelMultiple.cmake | 14 +++++++++++++ .../ProjectIsTopLevelSubdirectory-stdout.txt | 6 ++++++ .../ProjectIsTopLevelSubdirectory.cmake | 8 +++++++ .../CMakeLists.txt | 5 +++++ Tests/RunCMake/project/RunCMakeTest.cmake | 3 +++ 14 files changed, 100 insertions(+) create mode 100644 Help/release/dev/project-is-top-level.rst create mode 100644 Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst create mode 100644 Help/variable/PROJECT_IS_TOP_LEVEL.rst create mode 100644 Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt create mode 100644 Tests/RunCMake/project/ProjectIsTopLevel.cmake create mode 100644 Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt create mode 100644 Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake create mode 100644 Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt create mode 100644 Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake create mode 100644 Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt diff --git a/Help/command/project.rst b/Help/command/project.rst index a726cbba6f0..8a6bc1e548d 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -28,6 +28,11 @@ Also sets the variables: :variable:`PROJECT_BINARY_DIR`, :variable:`_BINARY_DIR` Absolute path to the binary directory for the project. +:variable:`PROJECT_IS_TOP_LEVEL`, :variable:`_IS_TOP_LEVEL` + .. versionadded:: 3.21 + + Boolean value indicating whether the project is top-level. + Further variables are set by the optional arguments described in the following. If any of these arguments is not used, then the corresponding variables are set to the empty string. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 4317dd40719..37ef053db41 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -130,6 +130,7 @@ Variables that Provide Information /variable/PROJECT-NAME_BINARY_DIR /variable/PROJECT-NAME_DESCRIPTION /variable/PROJECT-NAME_HOMEPAGE_URL + /variable/PROJECT-NAME_IS_TOP_LEVEL /variable/PROJECT-NAME_SOURCE_DIR /variable/PROJECT-NAME_VERSION /variable/PROJECT-NAME_VERSION_MAJOR @@ -139,6 +140,7 @@ Variables that Provide Information /variable/PROJECT_BINARY_DIR /variable/PROJECT_DESCRIPTION /variable/PROJECT_HOMEPAGE_URL + /variable/PROJECT_IS_TOP_LEVEL /variable/PROJECT_NAME /variable/PROJECT_SOURCE_DIR /variable/PROJECT_VERSION diff --git a/Help/release/dev/project-is-top-level.rst b/Help/release/dev/project-is-top-level.rst new file mode 100644 index 00000000000..568afe02c36 --- /dev/null +++ b/Help/release/dev/project-is-top-level.rst @@ -0,0 +1,6 @@ +project-is-top-level +-------------------- + +* :command:`project` now sets variables :variable:`PROJECT_IS_TOP_LEVEL` and + :variable:`_IS_TOP_LEVEL` to indicate whether it was called + in a top level ``CMakeLists.txt`` file. diff --git a/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst b/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst new file mode 100644 index 00000000000..953e9783fd5 --- /dev/null +++ b/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst @@ -0,0 +1,11 @@ +_IS_TOP_LEVEL +--------------------------- + +.. versionadded:: 3.21 + +A boolean variable indicating whether the named project was called in a top +level ``CMakeLists.txt`` file. + +To obtain the value from the most recent call to :command:`project` in +the current directory scope or above, see the +:variable:`PROJECT_IS_TOP_LEVEL` variable. diff --git a/Help/variable/PROJECT_IS_TOP_LEVEL.rst b/Help/variable/PROJECT_IS_TOP_LEVEL.rst new file mode 100644 index 00000000000..e5eb6c1231e --- /dev/null +++ b/Help/variable/PROJECT_IS_TOP_LEVEL.rst @@ -0,0 +1,21 @@ +PROJECT_IS_TOP_LEVEL +-------------------- + +.. versionadded:: 3.21 + +A boolean variable indicating whether :command:`project` was called in a top +level ``CMakeLists.txt`` file. + +Some modules should only be included as part of the top level +``CMakeLists.txt`` file to not cause unintended side effects in the build +tree, and this variable can be used to conditionally execute such code. For +example, consider the :module:`CTest` module, which creates targets and +options: + +.. code-block:: cmake + + project(MyProject) + ... + if(PROJECT_IS_TOP_LEVEL) + include(CTest) + endif() diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index ed32de9f3d0..acdb09f3361 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -59,6 +59,11 @@ bool cmProjectCommand(std::vector const& args, mf.AddDefinition("PROJECT_NAME", projectName); + mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile()); + mf.AddCacheDefinition(projectName + "_IS_TOP_LEVEL", + mf.IsRootMakefile() ? "ON" : "OFF", + "Value Computed by CMake", cmStateEnums::STATIC); + // Set the CMAKE_PROJECT_NAME variable to be the highest-level // project name in the tree. If there are two project commands // in the same CMakeLists.txt file, and it is the top level diff --git a/Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt b/Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt new file mode 100644 index 00000000000..af8abfdfdf3 --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevel-stdout.txt @@ -0,0 +1,2 @@ +-- PROJECT_IS_TOP_LEVEL=ON +-- ProjectIsTopLevel_IS_TOP_LEVEL=ON diff --git a/Tests/RunCMake/project/ProjectIsTopLevel.cmake b/Tests/RunCMake/project/ProjectIsTopLevel.cmake new file mode 100644 index 00000000000..5a0af0aaa11 --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevel.cmake @@ -0,0 +1,9 @@ +# no project() call, includer already calls project(${RunCMake_TEST} NONE) +if(NOT DEFINED PROJECT_IS_TOP_LEVEL) + message(FATAL_ERROR "PROJECT_IS_TOP_LEVEL is not defined") +endif() +if(NOT DEFINED "CACHE{${RunCMake_TEST}_IS_TOP_LEVEL}") + message(FATAL_ERROR "IsTopLevel_IS_TOP_LEVEL is not defined") +endif() +message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}") +message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}") diff --git a/Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt b/Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt new file mode 100644 index 00000000000..75d787f9ef6 --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevelMultiple-stdout.txt @@ -0,0 +1,3 @@ +-- PROJECT_IS_TOP_LEVEL=ON +-- ProjectIsTopLevelMultiple_IS_TOP_LEVEL=ON +-- IsTopLevel_IS_TOP_LEVEL=ON diff --git a/Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake b/Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake new file mode 100644 index 00000000000..98ba55bc186 --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevelMultiple.cmake @@ -0,0 +1,14 @@ +# only one project() call, includer already calls project(${RunCMake_TEST} NONE) +project(IsTopLevel NONE) +if(NOT DEFINED PROJECT_IS_TOP_LEVEL) + message(FATAL_ERROR "PROJECT_IS_TOP_LEVEL is not defined") +endif() +if(NOT DEFINED "CACHE{${RunCMake_TEST}_IS_TOP_LEVEL}") + message(FATAL_ERROR "${RunCMake_TEST}_IS_TOP_LEVEL is not defined") +endif() +if(NOT DEFINED CACHE{IsTopLevel_IS_TOP_LEVEL}) + message(FATAL_ERROR "IsTopLevel_IS_TOP_LEVEL is not defined") +endif() +message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}") +message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}") +message(STATUS "IsTopLevel_IS_TOP_LEVEL=${IsTopLevel_IS_TOP_LEVEL}") diff --git a/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt new file mode 100644 index 00000000000..d9e15ff8d7e --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory-stdout.txt @@ -0,0 +1,6 @@ +-- PROJECT_IS_TOP_LEVEL=ON +-- PROJECT_IS_TOP_LEVEL=ON +-- PROJECT_IS_TOP_LEVEL=OFF +-- PROJECT_IS_TOP_LEVEL=ON +-- ProjectIsTopLevelSubdirectory_IS_TOP_LEVEL=ON +-- NotTopLevel_IS_TOP_LEVEL=OFF diff --git a/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake new file mode 100644 index 00000000000..b5df84b2f71 --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory.cmake @@ -0,0 +1,8 @@ +# no project() call, includer already calls project(${RunCMake_TEST} NONE) +message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}") + +add_subdirectory(ProjectIsTopLevelSubdirectory) + +message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}") +message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}") +message(STATUS "NotTopLevel_IS_TOP_LEVEL=${NotTopLevel_IS_TOP_LEVEL}") diff --git a/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt new file mode 100644 index 00000000000..d2f16ea4c60 --- /dev/null +++ b/Tests/RunCMake/project/ProjectIsTopLevelSubdirectory/CMakeLists.txt @@ -0,0 +1,5 @@ +message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}") + +project(NotTopLevel NONE) + +message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}") diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake index 69146993bda..349e8ac41a0 100644 --- a/Tests/RunCMake/project/RunCMakeTest.cmake +++ b/Tests/RunCMake/project/RunCMakeTest.cmake @@ -15,6 +15,9 @@ run_cmake(ProjectDescriptionNoArg2) run_cmake(ProjectHomepage) run_cmake(ProjectHomepage2) run_cmake(ProjectHomepageNoArg) +run_cmake(ProjectIsTopLevel) +run_cmake(ProjectIsTopLevelMultiple) +run_cmake(ProjectIsTopLevelSubdirectory) run_cmake(ProjectTwice) run_cmake(VersionAndLanguagesEmpty) run_cmake(VersionEmpty) From 8e342a6637d7d3d63549bfa6ae98efe6deee8390 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 26 Mar 2021 10:52:30 -0400 Subject: [PATCH 0179/1519] FindIntl: Fix detection of intl built in to C library Since commit c30d06b7e6 (FindIntl: Add imported target, 2020-10-06, v3.20.0-rc1~687^2) we use `check_symbol_exists` to check whether the `intl` library is built in to the C library. On some platforms the tested symbols are provided as macros so the check passes without linking any symbol. Instead, check whether a sample source file both compiles and links. Fixes: #21979 --- Modules/FindIntl.cmake | 101 +++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake index eaeefef944a..038f4dacf1e 100644 --- a/Modules/FindIntl.cmake +++ b/Modules/FindIntl.cmake @@ -61,24 +61,11 @@ The following cache variables may also be set: The libintl library (if any) -.. variable:: Intl_HAVE_GETTEXT_BUILTIN +.. variable:: Intl_IS_BUILT_IN .. versionadded:: 3.20 - True if gettext is in the C library - -.. variable:: Intl_HAVE_DCGETTEXT_BUILTIN - - .. versionadded:: 3.20 - - True if dcgettext is in the C library - -.. variable:: Intl_IS_BUILTIN - - .. versionadded:: 3.20 - - whether intl is a part of the C library determined from the result of - Intl_HAVE_GETTEXT_BUILTIN and Intl_HAVE_DCGETTEXT_BUILTIN + whether ``intl`` is a part of the C library. .. note:: On some platforms, such as Linux with GNU libc, the gettext @@ -96,40 +83,59 @@ The following cache variables may also be set: #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake) - -# Check if we have libintl is a part of libc -cmake_push_check_state(RESET) -set(CMAKE_REQUIRED_QUIET TRUE) -check_symbol_exists(gettext libintl.h Intl_HAVE_GETTEXT_BUILTIN) -check_symbol_exists(dcgettext libintl.h Intl_HAVE_DCGETTEXT_BUILTIN) # redundant check -cmake_pop_check_state() - -if(Intl_HAVE_GETTEXT_BUILTIN AND Intl_HAVE_DCGETTEXT_BUILTIN) - set(Intl_IS_BUILTIN TRUE) +if(CMAKE_C_COMPILER_LOADED) + include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake) +elseif(CMAKE_CXX_COMPILER_LOADED) + include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXSourceCompiles.cmake) else() - set(Intl_IS_BUILTIN FALSE) + # If neither C nor CXX are loaded, implicit intl makes no sense. + set(Intl_IS_BUILT_IN FALSE) endif() -# Find include directory -find_path(Intl_INCLUDE_DIR - NAMES "libintl.h" - DOC "libintl include directory") -mark_as_advanced(Intl_INCLUDE_DIR) +# Check if Intl is built in to the C library. +if(NOT DEFINED Intl_IS_BUILT_IN) + if(NOT DEFINED Intl_INCLUDE_DIR AND NOT DEFINED Intl_LIBRARY) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_QUIET TRUE) + set(Intl_IMPLICIT_TEST_CODE [[ +#include +int main(void) { + gettext(""); + dgettext("", ""); + dcgettext("", "", 0); + return 0; +} +]]) + if(CMAKE_C_COMPILER_LOADED) + check_c_source_compiles("${Intl_IMPLICIT_TEST_CODE}" Intl_IS_BUILT_IN) + else() + check_cxx_source_compiles("${Intl_IMPLICIT_TEST_CODE}" Intl_IS_BUILT_IN) + endif() + cmake_pop_check_state() + else() + set(Intl_IS_BUILT_IN FALSE) + endif() +endif() -# Find all Intl libraries -if(NOT Intl_IS_BUILTIN) - set(Intl_LIBRARY_NAMES "intl" "libintl") +set(_Intl_REQUIRED_VARS) +if(Intl_IS_BUILT_IN) + set(_Intl_REQUIRED_VARS _Intl_IS_BUILT_IN_MSG) + set(_Intl_IS_BUILT_IN_MSG "built in to C library") else() - set(Intl_LIBRARY_NAMES "c") -endif() + set(_Intl_REQUIRED_VARS Intl_LIBRARY Intl_INCLUDE_DIR) + + find_path(Intl_INCLUDE_DIR + NAMES "libintl.h" + DOC "libintl include directory") + mark_as_advanced(Intl_INCLUDE_DIR) -find_library(Intl_LIBRARY ${Intl_LIBRARY_NAMES} NAMES_PER_DIR - DOC "intl library (potentially the C library)") -mark_as_advanced(Intl_LIBRARY) + find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR + DOC "libintl libraries (if not in the C library)") + mark_as_advanced(Intl_LIBRARY) +endif() # NOTE: glibc's libintl.h does not define LIBINTL_VERSION -if(Intl_INCLUDE_DIR AND NOT Intl_IS_BUILTIN) +if(Intl_INCLUDE_DIR AND EXISTS "${Intl_INCLUDE_DIR}/libintl.h") file(STRINGS ${Intl_INCLUDE_DIR}/libintl.h Intl_VERSION_DEFINE REGEX "LIBINTL_VERSION (.*)") if(Intl_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)") @@ -152,13 +158,20 @@ endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl FOUND_VAR Intl_FOUND - REQUIRED_VARS Intl_LIBRARY Intl_INCLUDE_DIR + REQUIRED_VARS ${_Intl_REQUIRED_VARS} VERSION_VAR Intl_VERSION FAIL_MESSAGE "Failed to find Gettext libintl") +unset(_Intl_REQUIRED_VARS) +unset(_Intl_IS_BUILT_IN_MSG) if(Intl_FOUND) - set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}") - set(Intl_LIBRARIES "${Intl_LIBRARY}") + if(Intl_IS_BUILT_IN) + set(Intl_INCLUDE_DIRS "") + set(Intl_LIBRARIES "") + else() + set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}") + set(Intl_LIBRARIES "${Intl_LIBRARY}") + endif() if(NOT TARGET Intl::Intl) add_library(Intl::Intl INTERFACE IMPORTED) set_target_properties(Intl::Intl PROPERTIES From 1d8e3a1e770ae4aed921eefffaceb70b1fd73701 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 26 Mar 2021 16:27:18 +0100 Subject: [PATCH 0180/1519] UseSWIG: Use standard library name conventions for csharp language Fixes: #21542 --- Help/manual/cmake-policies.7.rst | 3 ++- Help/policy/CMP0122.rst | 17 +++++++++++++++++ Help/release/dev/UseSWIG-csharp.rst | 5 +++++ Modules/UseSWIG.cmake | 19 ++++++++++++++++++- Source/cmPolicies.h | 6 +++++- .../RunCMake/UseSWIG/CMP0122-NEW-check.cmake | 10 ++++++++++ Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake | 2 ++ .../RunCMake/UseSWIG/CMP0122-OLD-check.cmake | 10 ++++++++++ Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake | 2 ++ .../RunCMake/UseSWIG/CMP0122-WARN-stderr.txt | 10 ++++++++++ Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake | 1 + Tests/RunCMake/UseSWIG/CMP0122-common.cmake | 12 ++++++++++++ Tests/RunCMake/UseSWIG/RunCMakeTest.cmake | 4 ++++ 13 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 Help/policy/CMP0122.rst create mode 100644 Help/release/dev/UseSWIG-csharp.rst create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake create mode 100644 Tests/RunCMake/UseSWIG/CMP0122-common.cmake diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index f103c5054a2..5dfa89492fd 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,7 +57,8 @@ Policies Introduced by CMake 3.21 .. toctree:: :maxdepth: 1 - CMP0121: The list command detects invalid indicies + CMP0122: UseSWIG use standard library name conventions for csharp language. + CMP0121: The list command detects invalid indicies. Policies Introduced by CMake 3.20 ================================= diff --git a/Help/policy/CMP0122.rst b/Help/policy/CMP0122.rst new file mode 100644 index 00000000000..1ff8c48621e --- /dev/null +++ b/Help/policy/CMP0122.rst @@ -0,0 +1,17 @@ +CMP0122 +------- + +.. versionadded:: 3.21 + +:module:`UseSWIG` use library name conventions for ``CSharp`` language. + +Starting with CMake 3.21, :module:`UseSWIG` generates now a library using +default naming conventions. This policy provides compatibility with projects +that expect the legacy behavior. + +This policy was introduced in CMake version 3.21. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/UseSWIG-csharp.rst b/Help/release/dev/UseSWIG-csharp.rst new file mode 100644 index 00000000000..dbbeaf16ac5 --- /dev/null +++ b/Help/release/dev/UseSWIG-csharp.rst @@ -0,0 +1,5 @@ +UseSWIG-csharp +-------------- + +* The :module:`UseSWIG` module use now standard library name conventions for + ``CSharp`` language. See policy :policy:`CMP0122`. diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index b1e05769784..c7d8346335a 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -38,7 +38,13 @@ Defines the following command for use with ``SWIG``: .. versionchanged:: 3.15 Alternate library name (set with the :prop_tgt:`OUTPUT_NAME` property, - for example) will be passed on to Python and CSharp wrapper libraries. + for example) will be passed on to ``Python`` and ``CSharp`` wrapper + libraries. + + .. versionchanged:: 3.21 + Generated library use standard naming conventions for ``CSharp`` language + when policy :policy:`CMP0122` is set to ``NEW``. Otherwise, the legacy + behavior is applied. .. note:: @@ -950,6 +956,17 @@ function(SWIG_ADD_LIBRARY name) endif () elseif (swig_lowercase_language STREQUAL "fortran") # Do *not* override the target's library prefix + elseif (swig_lowercase_language STREQUAL "csharp") + cmake_policy(GET CMP0122 csharp_naming_policy) + if (csharp_naming_policy STREQUAL "NEW") + # Do *not* override the target's library prefix + else() + if (NOT csharp_naming_policy) + cmake_policy(GET_WARNING CMP0122 _cmp0122_warning) + message(AUTHOR_WARNING "${_cmp0122_warning}\n") + endif() + set_target_properties (${target_name} PROPERTIES PREFIX "") + endif() else() # assume empty prefix because we expect the module to be dynamically loaded set_target_properties (${target_name} PROPERTIES PREFIX "") diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 9295a3fa4e6..d546b6e937a 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -362,7 +362,11 @@ class cmMakefile; cmPolicies::WARN) \ SELECT(POLICY, CMP0121, \ "The list() command now validates parsing of index arguments.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0122, \ + "UseSWIG use standard library name conventions for csharp language.", 3, \ + 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake b/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake new file mode 100644 index 00000000000..a26c27842be --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-NEW-check.cmake @@ -0,0 +1,10 @@ + +cmake_policy(VERSION 3.1) + +file(STRINGS "${RunCMake_TEST_BINARY_DIR}/CMP0122-library-name.txt" prefixes) + +list(GET prefixes 0 std_prefix) +list(GET prefixes 1 lib_prefix) +if (NOT std_prefix STREQUAL lib_prefix) + string (APPEND RunCMake_TEST_FAILED "\nFound prefix: '${lib_prefix}', expected: '${std_prefix}'.") +endif() diff --git a/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake b/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake new file mode 100644 index 00000000000..fecb7dba493 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0122 NEW) +include(CMP0122-common.cmake) diff --git a/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake b/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake new file mode 100644 index 00000000000..01657d0c5e2 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-OLD-check.cmake @@ -0,0 +1,10 @@ + +cmake_policy(VERSION 3.1) + +file(STRINGS "${RunCMake_TEST_BINARY_DIR}/CMP0122-library-name.txt" prefixes) + +list(GET prefixes 1 lib_prefix) +if (lib_prefix) + # prefix must be empty + string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix: '${lib_prefix}'.") +endif() diff --git a/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake b/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake new file mode 100644 index 00000000000..a787b684974 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0122 OLD) +include(CMP0122-common.cmake) diff --git a/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt new file mode 100644 index 00000000000..37c4fbd7ac6 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-WARN-stderr.txt @@ -0,0 +1,10 @@ +CMake Warning \(dev\) at .*/Modules/UseSWIG.cmake:[0-9]+ \(message\): + Policy CMP0122 is not set: UseSWIG use standard library name conventions + for csharp language\. Run "cmake --help-policy CMP0122" for policy details\. + Use the cmake_policy command to set the policy and suppress this warning\. + +Call Stack \(most recent call first\): + CMP0122-common.cmake:9 \(swig_add_library\) + CMP0122-WARN.cmake:1 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake b/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake new file mode 100644 index 00000000000..5d571aa3ef1 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-WARN.cmake @@ -0,0 +1 @@ +include(CMP0122-common.cmake) diff --git a/Tests/RunCMake/UseSWIG/CMP0122-common.cmake b/Tests/RunCMake/UseSWIG/CMP0122-common.cmake new file mode 100644 index 00000000000..be880ec2468 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0122-common.cmake @@ -0,0 +1,12 @@ + +cmake_policy(SET CMP0078 NEW) +cmake_policy(SET CMP0086 NEW) + +set(SWIG_EXECUTABLE "swig") +set(SWIG_DIR "/swig") +include(UseSWIG) + +swig_add_library(example LANGUAGE csharp TYPE SHARED SOURCES example.i) + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/CMP0122-library-name.txt" + CONTENT "${CMAKE_SHARED_LIBRARY_PREFIX}\n$\n") diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake index 6acf7199c43..c7a118ffc5e 100644 --- a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake +++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake @@ -23,3 +23,7 @@ if (CMake_TEST_FindPython) run_cmake_target(CMP0086-NEW build example) endif() + +run_cmake(CMP0122-WARN) +run_cmake(CMP0122-OLD) +run_cmake(CMP0122-NEW) From a43783a08d621153daec4511474f939484b2b952 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Wed, 24 Mar 2021 18:21:38 +1100 Subject: [PATCH 0181/1519] CPackIFW: Fix parsing of name and version in component DEPENDS The DEPENDS or DEPENDENCIES arguments in a call to cpack_ifw_configure_component() or cpack_ifw_configure_component_group() specify a name and optionally a version constraint as a single string. QtIFW also allows a colon (requires QtIFW 3.1 or later) or a hyphen to separate the name and version. The version may optionally contain a leading operator, with = being assumed when no operator is present. The previous code was not handling : as a separator at all and was erroneously dropping the version part when no operator was given. Fix both of those non-conforming behaviors and also warn if trying to use a hyphen in a name with a QtIFW version that isn't recent enough to support it. Fixes: #21697 --- .../dev/ifw-default-version-operator.rst | 7 ++ Modules/CPackIFW.cmake | 10 ++ Source/CPack/IFW/cmCPackIFWPackage.cxx | 109 +++++++++++++----- 3 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 Help/release/dev/ifw-default-version-operator.rst diff --git a/Help/release/dev/ifw-default-version-operator.rst b/Help/release/dev/ifw-default-version-operator.rst new file mode 100644 index 00000000000..4aeace26870 --- /dev/null +++ b/Help/release/dev/ifw-default-version-operator.rst @@ -0,0 +1,7 @@ +ifw-default-version-operator +---------------------------- + +* Names given as ``DEPENDS`` or ``DEPENDENCIES`` arguments to + :command:`cpack_ifw_configure_component` or + :command:`cpack_ifw_configure_component_group` may now contain hyphens. + This requires QtIFW 3.1 or later. diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index d57cf18bac6..2087a518bca 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -125,6 +125,11 @@ The module defines the following commands: list of dependency component or component group identifiers in QtIFW style. + .. versionadded:: 3.21 + + Component or group names listed as dependencies may contain hyphens. + This requires QtIFW 3.1 or later. + ``AUTO_DEPEND_ON`` .. versionadded:: 3.8 @@ -260,6 +265,11 @@ The module defines the following commands: list of dependency component or component group identifiers in QtIFW style. + .. versionadded:: 3.21 + + Component or group names listed as dependencies may contain hyphens. + This requires QtIFW 3.1 or later. + ``AUTO_DEPEND_ON`` .. versionadded:: 3.8 diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 5191c96e30b..1429c4670e5 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -7,6 +7,8 @@ #include #include +#include + #include "cmCPackComponentGroup.h" #include "cmCPackIFWCommon.h" #include "cmCPackIFWGenerator.h" @@ -30,44 +32,67 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default; cmCPackIFWPackage::DependenceStruct::DependenceStruct( const std::string& dependence) { - // Search compare section + // Preferred format is name and version are separated by a colon (:), but + // note that this is only supported with QtIFW 3.1 or later. Backward + // compatibility allows a hyphen (-) as a separator instead, but names then + // cannot contain a hyphen. size_t pos; - if ((pos = dependence.find("<=")) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; - this->Compare.Value = dependence.substr(pos + 2); - } else if ((pos = dependence.find(">=")) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; - this->Compare.Value = dependence.substr(pos + 2); - } else if ((pos = dependence.find('<')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareLess; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('=')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareEqual; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('>')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareGreater; - this->Compare.Value = dependence.substr(pos + 1); - } else if ((pos = dependence.find('-')) != std::string::npos) { - this->Compare.Type = cmCPackIFWPackage::CompareNone; - this->Compare.Value = dependence.substr(pos + 1); - } - size_t dashPos = dependence.find('-'); - if (dashPos != std::string::npos) { - pos = dashPos; - } - this->Name = dependence.substr(0, pos); + if ((pos = dependence.find(':')) == std::string::npos) { + pos = dependence.find('-'); + } + + if (pos != std::string::npos) { + this->Name = dependence.substr(0, pos); + ++pos; + if (pos == dependence.size()) { + // Nothing after the separator. Treat this as no version constraint. + return; + } + + const auto versionPart = + cm::string_view(dependence.data() + pos, dependence.size() - pos); + + if (cmHasLiteralPrefix(versionPart, "<=")) { + this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; + this->Compare.Value = std::string(versionPart.substr(2)); + } else if (cmHasLiteralPrefix(versionPart, ">=")) { + this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; + this->Compare.Value = std::string(versionPart.substr(2)); + } else if (cmHasPrefix(versionPart, '<')) { + this->Compare.Type = cmCPackIFWPackage::CompareLess; + this->Compare.Value = std::string(versionPart.substr(1)); + } else if (cmHasPrefix(versionPart, '=')) { + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = std::string(versionPart.substr(1)); + } else if (cmHasPrefix(versionPart, '>')) { + this->Compare.Type = cmCPackIFWPackage::CompareGreater; + this->Compare.Value = std::string(versionPart.substr(1)); + } else { + // We found no operator but a version specification is still expected to + // follow. The default behavior is to treat this the same as =. We + // explicitly record that as our type (it simplifies our logic a little + // and is also clearer). + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = std::string(versionPart); + } + } else { + this->Name = dependence; + } } std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const { - if (this->Compare.Type == cmCPackIFWPackage::CompareNone) { - return this->Name; - } - std::string result = this->Name; - - if (this->Compare.Type != cmCPackIFWPackage::CompareNone || - !this->Compare.Value.empty()) { + if (this->Name.find('-') != std::string::npos) { + // When a name contains a hyphen, we must use a colon after the name to + // prevent the hyphen from being parsed by QtIFW as the separator between + // the name and the version. Note that a colon is only supported with + // QtIFW 3.1 or later. + result += ":"; + } else if (this->Compare.Type != cmCPackIFWPackage::CompareNone || + !this->Compare.Value.empty()) { + // No hyphen in the name and we know a version part will follow. Use a + // hyphen as a separator since this works for all QtIFW versions. result += "-"; } @@ -609,6 +634,9 @@ void cmCPackIFWPackage::GeneratePackageFile() } // Dependencies + const bool hyphensInNamesUnsupported = this->Generator && + !this->Generator->FrameworkVersion.empty() && this->IsVersionLess("3.1"); + bool warnUnsupportedNames = false; std::set compDepSet; for (DependenceStruct* ad : this->AlienDependencies) { compDepSet.insert(*ad); @@ -620,9 +648,13 @@ void cmCPackIFWPackage::GeneratePackageFile() if (!compDepSet.empty()) { std::ostringstream dependencies; auto it = compDepSet.begin(); + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << it->NameWithCompare(); ++it; while (it != compDepSet.end()) { + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << "," << it->NameWithCompare(); ++it; } @@ -638,15 +670,28 @@ void cmCPackIFWPackage::GeneratePackageFile() if (!compAutoDepSet.empty()) { std::ostringstream dependencies; auto it = compAutoDepSet.begin(); + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << it->NameWithCompare(); ++it; while (it != compAutoDepSet.end()) { + warnUnsupportedNames |= + hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos; dependencies << "," << it->NameWithCompare(); ++it; } xout.Element("AutoDependOn", dependencies.str()); } + if (warnUnsupportedNames) { + cmCPackIFWLogger( + WARNING, + "The dependencies for component \"" + << this->Name << "\" specify names that contain hyphens. " + << "This requires QtIFW 3.1 or later, but you are using version " + << this->Generator->FrameworkVersion << std::endl); + } + // Licenses (copy to meta dir) std::vector licenses = this->Licenses; for (size_t i = 1; i < licenses.size(); i += 2) { From b22c800604e22a0ffdb13aa5fd4cfb7ee26896a4 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 27 Mar 2021 00:01:17 -0400 Subject: [PATCH 0182/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fa9d567d79c..dc4fcaebe0c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210326) +set(CMake_VERSION_PATCH 20210327) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 44ad3f0b7f7e0aaf96e5cfd672d07a70e1b76410 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 20 Mar 2021 16:53:14 +1100 Subject: [PATCH 0183/1519] ctest: Support multiple -L and -LE options to mean "AND" Fixes: #21087 --- Help/manual/ctest.1.rst | 50 ++++++++++- Source/CTest/cmCTestGenericHandler.cxx | 52 +++++++++--- Source/CTest/cmCTestGenericHandler.h | 32 +++++++ Source/CTest/cmCTestTestCommand.cxx | 6 +- Source/CTest/cmCTestTestHandler.cxx | 103 +++++++++++++---------- Source/CTest/cmCTestTestHandler.h | 8 +- Source/cmCTest.cxx | 29 ++++--- Source/cmCTest.h | 2 + Source/ctest.cxx | 10 ++- Tests/CMakeTests/CMakeLists.txt | 1 + Tests/CTestTestLabelRegExp/test.cmake.in | 4 + Tests/QtAutogen/TestMacros.cmake | 1 + Tests/QtAutogen/Tests.cmake | 2 + Tests/RunCMake/CMakeLists.txt | 4 + 14 files changed, 222 insertions(+), 82 deletions(-) diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 175359d6c14..68409e1ed93 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -155,7 +155,10 @@ Options Run tests with labels matching regular expression. This option tells CTest to run only the tests whose labels match the - given regular expression. + given regular expression. When more than one ``-L`` option is given, + a test will only be run if each regular expression matches at least one + of the test's labels (i.e. the multiple ``-L`` labels form an ``AND`` + relationship). See `Label Matching`_. ``-R , --tests-regex `` Run tests matching regular expression. @@ -173,7 +176,10 @@ Options Exclude tests with labels matching regular expression. This option tells CTest to NOT run the tests whose labels match the - given regular expression. + given regular expression. When more than one ``-LE`` option is given, + a test will only be excluded if each regular expression matches at least one + of the test's labels (i.e. the multiple ``-LE`` labels form an ``AND`` + relationship). See `Label Matching`_. ``-FA , --fixture-exclude-any `` Exclude fixtures matching ```` from automatically adding any tests to @@ -398,6 +404,46 @@ Specify the directory in which to look for tests. .. include:: OPTIONS_HELP.txt +.. _`Label Matching`: + +Label Matching +============== + +Tests may have labels attached to them. Tests may be included +or excluded from a test run by filtering on the labels. +Each individual filter is a regular expression applied to +the labels attached to a test. + +When ``-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 ``-L`` option means "match **all** +of these". + +The ``-LE`` option works just like ``-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 ``-L`` will never +include that test, and ``-LE`` will never exclude that test. +As an example of tests with labels, consider five tests, +with the following labels: + +* *test1* has labels *tuesday* and *production* +* *test2* has labels *tuesday* and *test* +* *test3* has labels *wednesday* and *production* +* *test4* has label *wednesday* +* *test5* has labels *friday* and *test* + +Running ``ctest`` with ``-L tuesday -L test`` will select *test2*, which has +both labels. Running CTest with ``-L test`` will select *test2* and +*test5*, because both of them have a label that matches that regular +expression. + +Because the matching works with regular expressions, take note that +running CTest with ``-L es`` will match all five tests. +To select the *tuesday* and *wednesday* tests together, use a single +regular expression that matches either of them, like ``-L "tue|wed"``. + .. _`Label and Subproject Summary`: Label and Subproject Summary diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 91818bb2e89..cc756d7dc48 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -21,32 +21,47 @@ cmCTestGenericHandler::cmCTestGenericHandler() cmCTestGenericHandler::~cmCTestGenericHandler() = default; -void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) +/* Modify the given `map`, setting key `op` to `value` if `value` + * is non-null, otherwise removing key `op` (if it exists). + */ +static void SetMapValue(cmCTestGenericHandler::t_StringToString& map, + const std::string& op, const char* value) { if (!value) { - auto remit = this->Options.find(op); - if (remit != this->Options.end()) { - this->Options.erase(remit); - } + map.erase(op); return; } - this->Options[op] = value; + map[op] = value; +} + +void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) +{ + SetMapValue(this->Options, op, value); } void cmCTestGenericHandler::SetPersistentOption(const std::string& op, const char* value) { this->SetOption(op, value); - if (!value) { - auto remit = this->PersistentOptions.find(op); - if (remit != this->PersistentOptions.end()) { - this->PersistentOptions.erase(remit); - } - return; + SetMapValue(this->PersistentOptions, op, value); +} + +void cmCTestGenericHandler::AddMultiOption(const std::string& op, + const std::string& value) +{ + if (!value.empty()) { + this->MultiOptions[op].emplace_back(value); } +} - this->PersistentOptions[op] = value; +void cmCTestGenericHandler::AddPersistentMultiOption(const std::string& op, + const std::string& value) +{ + if (!value.empty()) { + this->MultiOptions[op].emplace_back(value); + this->PersistentMultiOptions[op].emplace_back(value); + } } void cmCTestGenericHandler::Initialize() @@ -68,6 +83,17 @@ const char* cmCTestGenericHandler::GetOption(const std::string& op) return remit->second.c_str(); } +std::vector cmCTestGenericHandler::GetMultiOption( + const std::string& optionName) const +{ + // Avoid inserting a key, which MultiOptions[op] would do. + auto remit = this->MultiOptions.find(optionName); + if (remit == this->MultiOptions.end()) { + return {}; + } + return remit->second; +} + bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part, const char* name, cmGeneratedFileStream& xofs) diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 89d75968e68..6f445453be4 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -72,11 +72,41 @@ class cmCTestGenericHandler virtual ~cmCTestGenericHandler(); using t_StringToString = std::map; + using t_StringToMultiString = + std::map>; + /** + * Options collect a single value from flags; passing the + * flag multiple times on the command-line *overwrites* values, + * and only the last one specified counts. Set an option to + * nullptr to "unset" it. + * + * The value is stored as a string. The values set for single + * and multi-options (see below) live in different spaces, + * so calling a single-getter for a key that has only been set + * as a multi-value will return nullptr. + */ void SetPersistentOption(const std::string& op, const char* value); void SetOption(const std::string& op, const char* value); const char* GetOption(const std::string& op); + /** + * Multi-Options collect one or more values from flags; passing + * the flag multiple times on the command-line *adds* values, + * rather than overwriting the previous values. + * + * Adding an empty value does nothing. + * + * The value is stored as a vector of strings. The values set for single + * (see above) and multi-options live in different spaces, + * so calling a multi-getter for a key that has only been set + * as a single-value will return an empty vector. + */ + void AddPersistentMultiOption(const std::string& optionName, + const std::string& value); + void AddMultiOption(const std::string& optionName, const std::string& value); + std::vector GetMultiOption(const std::string& op) const; + void SetCommand(cmCTestCommand* command) { this->Command = command; } void SetSubmitIndex(int idx) { this->SubmitIndex = idx; } @@ -100,6 +130,8 @@ class cmCTestGenericHandler cmCTest* CTest; t_StringToString Options; t_StringToString PersistentOptions; + t_StringToMultiString MultiOptions; + t_StringToMultiString PersistentMultiOptions; t_StringToString LogFileNames; cmCTestCommand* Command; diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 44037337315..886c2630679 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -73,11 +73,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() handler->SetOption("IncludeRegularExpression", this->Include.c_str()); } if (!this->ExcludeLabel.empty()) { - handler->SetOption("ExcludeLabelRegularExpression", - this->ExcludeLabel.c_str()); + handler->AddMultiOption("ExcludeLabelRegularExpression", + this->ExcludeLabel); } if (!this->IncludeLabel.empty()) { - handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str()); + handler->AddMultiOption("LabelRegularExpression", this->IncludeLabel); } if (!this->ExcludeFixture.empty()) { handler->SetOption("ExcludeFixtureRegularExpression", diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 42c4d5e06f0..742e78a7a98 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -287,8 +287,6 @@ cmCTestTestHandler::cmCTestTestHandler() { this->UseUnion = false; - this->UseIncludeLabelRegExpFlag = false; - this->UseExcludeLabelRegExpFlag = false; this->UseIncludeRegExpFlag = false; this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFirst = false; @@ -327,13 +325,11 @@ void cmCTestTestHandler::Initialize() this->TestsToRun.clear(); - this->UseIncludeLabelRegExpFlag = false; - this->UseExcludeLabelRegExpFlag = false; this->UseIncludeRegExpFlag = false; this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFirst = false; - this->IncludeLabelRegularExpression = ""; - this->ExcludeLabelRegularExpression = ""; + this->IncludeLabelRegularExpressions.clear(); + this->ExcludeLabelRegularExpressions.clear(); this->IncludeRegExp.clear(); this->ExcludeRegExp.clear(); this->ExcludeFixtureRegExp.clear(); @@ -479,6 +475,22 @@ int cmCTestTestHandler::ProcessHandler() return 0; } +/* Given a multi-option value `parts`, compile those parts into + * regular expressions in `expressions`. Skip empty values. + * Returns true if there were any expressions. + */ +static bool BuildLabelRE(const std::vector& parts, + std::vector& expressions) +{ + expressions.clear(); + for (const auto& p : parts) { + if (!p.empty()) { + expressions.emplace_back(p); + } + } + return !expressions.empty(); +} + bool cmCTestTestHandler::ProcessOptions() { // Update internal data structure from generic one @@ -519,18 +531,11 @@ bool cmCTestTestHandler::ProcessOptions() this->CTest->SetStopOnFailure(true); } - const char* val; - val = this->GetOption("LabelRegularExpression"); - if (val) { - this->UseIncludeLabelRegExpFlag = true; - this->IncludeLabelRegExp = val; - } - val = this->GetOption("ExcludeLabelRegularExpression"); - if (val) { - this->UseExcludeLabelRegExpFlag = true; - this->ExcludeLabelRegExp = val; - } - val = this->GetOption("IncludeRegularExpression"); + BuildLabelRE(this->GetMultiOption("LabelRegularExpression"), + this->IncludeLabelRegularExpressions); + BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), + this->ExcludeLabelRegularExpressions); + const char* val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -763,10 +768,40 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet); } +/** + * Check if the labels (from a test) match all the expressions. + * + * Each of the RE's must match at least one label + * (e.g. all of the REs must match **some** label, + * in order for the filter to apply to the test). + */ +static bool MatchLabelsAgainstFilterRE( + const std::vector& labels, + const std::vector& expressions) +{ + for (const auto& re : expressions) { + // check to see if the label regular expression matches + bool found = false; // assume it does not match + cmsys::RegularExpressionMatch match; + // loop over all labels and look for match + for (std::string const& l : labels) { + if (re.find(l.c_str(), match)) { + found = true; + break; + } + } + // if no match was found, exclude the test + if (!found) { + return false; + } + } + return true; +} + void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) { // if not using Labels to filter then return - if (!this->UseIncludeLabelRegExpFlag) { + if (this->IncludeLabelRegularExpressions.empty()) { return; } // if there are no labels and we are filtering by labels @@ -775,16 +810,9 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) it.IsInBasedOnREOptions = false; return; } - // check to see if the label regular expression matches - bool found = false; // assume it does not match - // loop over all labels and look for match - for (std::string const& l : it.Labels) { - if (this->IncludeLabelRegularExpression.find(l)) { - found = true; - } - } // if no match was found, exclude the test - if (!found) { + if (!MatchLabelsAgainstFilterRE(it.Labels, + this->IncludeLabelRegularExpressions)) { it.IsInBasedOnREOptions = false; } } @@ -792,7 +820,7 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) { // if not using Labels to filter then return - if (!this->UseExcludeLabelRegExpFlag) { + if (this->ExcludeLabelRegularExpressions.empty()) { return; } // if there are no labels and we are excluding by labels @@ -800,16 +828,9 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) if (it.Labels.empty()) { return; } - // check to see if the label regular expression matches - bool found = false; // assume it does not match - // loop over all labels and look for match - for (std::string const& l : it.Labels) { - if (this->ExcludeLabelRegularExpression.find(l)) { - found = true; - } - } // if match was found, exclude the test - if (found) { + if (MatchLabelsAgainstFilterRE(it.Labels, + this->ExcludeLabelRegularExpressions)) { it.IsInBasedOnREOptions = false; } } @@ -1704,12 +1725,6 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty( bool cmCTestTestHandler::GetListOfTests() { - if (!this->IncludeLabelRegExp.empty()) { - this->IncludeLabelRegularExpression.compile(this->IncludeLabelRegExp); - } - if (!this->ExcludeLabelRegExp.empty()) { - this->ExcludeLabelRegularExpression.compile(this->ExcludeLabelRegExp); - } if (!this->IncludeRegExp.empty()) { this->IncludeTestsRegularExpression.compile(this->IncludeRegExp); } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index aa29eeb0191..6fa18a900f0 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -320,20 +320,16 @@ class cmCTestTestHandler : public cmCTestGenericHandler std::vector TestsToRun; - bool UseIncludeLabelRegExpFlag; - bool UseExcludeLabelRegExpFlag; bool UseIncludeRegExpFlag; bool UseExcludeRegExpFlag; bool UseExcludeRegExpFirst; - std::string IncludeLabelRegExp; - std::string ExcludeLabelRegExp; std::string IncludeRegExp; std::string ExcludeRegExp; std::string ExcludeFixtureRegExp; std::string ExcludeFixtureSetupRegExp; std::string ExcludeFixtureCleanupRegExp; - cmsys::RegularExpression IncludeLabelRegularExpression; - cmsys::RegularExpression ExcludeLabelRegularExpression; + std::vector IncludeLabelRegularExpressions; + std::vector ExcludeLabelRegularExpressions; cmsys::RegularExpression IncludeTestsRegularExpression; cmsys::RegularExpression ExcludeTestsRegularExpression; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 4228d307e8c..0dfd1bd4fa9 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2108,17 +2108,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } else if (this->CheckArgument(arg, "-L"_s, "--label-regex") && i < args.size() - 1) { i++; - this->GetTestHandler()->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); - this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); + this->GetTestHandler()->AddPersistentMultiOption("LabelRegularExpression", + args[i]); + this->GetMemCheckHandler()->AddPersistentMultiOption( + "LabelRegularExpression", args[i]); } else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") && i < args.size() - 1) { i++; - this->GetTestHandler()->SetPersistentOption( - "ExcludeLabelRegularExpression", args[i].c_str()); - this->GetMemCheckHandler()->SetPersistentOption( - "ExcludeLabelRegularExpression", args[i].c_str()); + this->GetTestHandler()->AddPersistentMultiOption( + "ExcludeLabelRegularExpression", args[i]); + this->GetMemCheckHandler()->AddPersistentMultiOption( + "ExcludeLabelRegularExpression", args[i]); } else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") && @@ -2268,6 +2268,15 @@ void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value, } } +void cmCTest::AddPersistentMultiOptionIfNotEmpty(const std::string& value, + const std::string& optionName) +{ + if (!value.empty()) { + this->GetTestHandler()->AddPersistentMultiOption(optionName, value); + this->GetMemCheckHandler()->AddPersistentMultiOption(optionName, value); + } +} + bool cmCTest::SetArgsFromPreset(const std::string& presetName, bool listPresets) { @@ -2419,7 +2428,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (expandedPreset->Filter->Include) { this->SetPersistentOptionIfNotEmpty( expandedPreset->Filter->Include->Name, "IncludeRegularExpression"); - this->SetPersistentOptionIfNotEmpty( + this->AddPersistentMultiOptionIfNotEmpty( expandedPreset->Filter->Include->Label, "LabelRegularExpression"); if (expandedPreset->Filter->Include->Index) { @@ -2452,7 +2461,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (expandedPreset->Filter->Exclude) { this->SetPersistentOptionIfNotEmpty( expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression"); - this->SetPersistentOptionIfNotEmpty( + this->AddPersistentMultiOptionIfNotEmpty( expandedPreset->Filter->Exclude->Label, "ExcludeLabelRegularExpression"); diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 4669a1cc277..392eb1c4104 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -463,6 +463,8 @@ class cmCTest private: void SetPersistentOptionIfNotEmpty(const std::string& value, const std::string& optionName); + void AddPersistentMultiOptionIfNotEmpty(const std::string& value, + const std::string& optionName); int GenerateNotesFile(const std::string& files); diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 3c331d32bff..a4b85ae310c 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -55,8 +55,9 @@ static const char* cmDocumentationOptions[][2] = { "format of the test information and can be 'human' for the current text " "format or 'json-v1' for json format. Defaults to 'human'." }, { "-L , --label-regex ", - "Run tests with labels matching " - "regular expression." }, + "Run tests with labels matching regular expression. " + "With multiple -L, run tests where each " + "regular expression matches at least one label." }, { "-R , --tests-regex ", "Run tests matching regular " "expression." }, @@ -64,8 +65,9 @@ static const char* cmDocumentationOptions[][2] = { "Exclude tests matching regular " "expression." }, { "-LE , --label-exclude ", - "Exclude tests with labels " - "matching regular expression." }, + "Exclude tests with labels matching regular expression. " + "With multiple -LE, exclude tests where each " + "regular expression matches at least one label." }, { "-FA , --fixture-exclude-any ", "Do not automatically " "add any tests for " diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 6bbbe7d3552..52959e62eb3 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -7,6 +7,7 @@ macro(AddCMakeTest TestName PreArgs) add_test(NAME CMake.${TestName} COMMAND ${CMAKE_EXECUTABLE} ${PreArgs} -P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN}) + set_tests_properties("CMake.${TestName}" PROPERTIES LABELS "CMake;command") endmacro() diff --git a/Tests/CTestTestLabelRegExp/test.cmake.in b/Tests/CTestTestLabelRegExp/test.cmake.in index 5c0c9d7ffb4..dd40c3b5038 100644 --- a/Tests/CTestTestLabelRegExp/test.cmake.in +++ b/Tests/CTestTestLabelRegExp/test.cmake.in @@ -27,11 +27,15 @@ expect_test_list("test1.*test3.*Total Tests: 2" --label-regex foo) expect_test_list("test2.*test3.*Total Tests: 2" --label-regex bar) expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-regex foo|bar) expect_test_list("Total Tests: 0" --label-regex baz) +expect_test_list("Total Tests: 0" --label-regex foo --label-regex baz) +expect_test_list("test3.*Total Tests: 1" --label-regex foo --label-regex bar) expect_test_list("test2.*Total Tests: 1" --label-exclude foo) expect_test_list("test1.*Total Tests: 1" --label-exclude bar) expect_test_list("Total Tests: 0" --label-exclude foo|bar) expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude baz) +expect_test_list("test1.*test2.*Total Tests: 2" --label-exclude foo --label-exclude bar) +expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude foo --label-exclude baz) expect_test_list("test1.*Total Tests: 1" --label-regex foo --label-exclude bar) expect_test_list("test2.*Total Tests: 1" --label-regex bar --label-exclude foo) diff --git a/Tests/QtAutogen/TestMacros.cmake b/Tests/QtAutogen/TestMacros.cmake index 1024996ab03..9dcf31fbdcb 100644 --- a/Tests/QtAutogen/TestMacros.cmake +++ b/Tests/QtAutogen/TestMacros.cmake @@ -43,6 +43,7 @@ macro(ADD_AUTOGEN_TEST NAME) --build-options ${build_options} ${Autogen_BUILD_OPTIONS} ${_TestCommand} ) + set_tests_properties("${_QtXAutogen}.${NAME}" PROPERTIES LABELS "Qt${QT_TEST_VERSION}") list(APPEND TEST_BUILD_DIRS "${_BuildDir}") unset(_TestCommand) unset(_QtXAutogen) diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake index d1edd72f4f3..ab5686af656 100644 --- a/Tests/QtAutogen/Tests.cmake +++ b/Tests/QtAutogen/Tests.cmake @@ -36,7 +36,9 @@ ADD_AUTOGEN_TEST(UnityMocSource) if(QT_TEST_ALLOW_QT_MACROS) ADD_AUTOGEN_TEST(MocCMP0071) + set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0071" APPEND PROPERTY LABELS "policy") ADD_AUTOGEN_TEST(MocCMP0100) + set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0100" APPEND PROPERTY LABELS "policy") ADD_AUTOGEN_TEST(MocInclude) ADD_AUTOGEN_TEST(MocIncludeSymlink) ADD_AUTOGEN_TEST(MocSkipSource) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 354a04eca39..c05b1a7d886 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -29,6 +29,10 @@ macro(add_RunCMake_test test) ${TEST_ARGS} -P "${CMAKE_CURRENT_SOURCE_DIR}/${Test_Dir}/RunCMakeTest.cmake" ) + set_tests_properties("RunCMake.${test}" PROPERTIES LABELS "CMake;run") + if(${test} MATCHES ^CMP) + set_property(TEST "RunCMake.${test}" APPEND PROPERTY LABELS "policy") + endif() endmacro() function(add_RunCMake_test_group test types) From 699577e7b2ca4e3f987b4a74bb4f88e4cfeff786 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 28 Mar 2021 00:01:11 -0400 Subject: [PATCH 0184/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index dc4fcaebe0c..d2ba664de66 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210327) +set(CMake_VERSION_PATCH 20210328) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d0adb2386a87046e9236b1b2b4d1c2706c78a711 Mon Sep 17 00:00:00 2001 From: Domen Vrankar Date: Sat, 27 Mar 2021 23:52:56 +0100 Subject: [PATCH 0185/1519] CPackRPM: correctly handle empty dir in single package mode Enabling CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE while having an empty directory in non main component resulted in packaging error that the directory does not exist. Fixes: #21951 --- Modules/Internal/CPack/CPackRPM.cmake | 10 ++++++++-- .../CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake | 2 +- Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index 08bbc6804c6..d8531899070 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -1349,15 +1349,21 @@ function(cpack_rpm_generate_package) continue() endif() - file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES false RELATIVE + file(GLOB_RECURSE files_for_move_ LIST_DIRECTORIES true RELATIVE "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}" "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/*") foreach(f_ IN LISTS files_for_move_) - get_filename_component(dir_path_ "${f_}" DIRECTORY) set(src_file_ "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}/${component_}/${f_}") + if(IS_DIRECTORY "${src_file_}") + file(MAKE_DIRECTORY "${WDIR}/${f_}") + continue() + endif() + + get_filename_component(dir_path_ "${f_}" DIRECTORY) + # check that we are not overriding an existing file that doesn't # match the file that we want to copy if(EXISTS "${src_file_}" AND EXISTS "${WDIR}/${f_}") diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake index 936e4ed80f7..1dc70848a5b 100644 --- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake @@ -9,7 +9,7 @@ if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm") set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm") - set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") + set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so;/empty_dir") set(EXPECTED_FILE_4_COMPONENT "debuginfo") set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*") diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake index 60e9038fe27..064539ecd3d 100644 --- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake +++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake @@ -30,6 +30,9 @@ if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo") install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers) install(TARGETS test_lib DESTINATION bas COMPONENT libs) + + # test that we correctly handle empty dir in non main component + install(DIRECTORY DESTINATION empty_dir COMPONENT libs) elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo") set(CPACK_COMPONENTS_ALL applications) From d5ab6a53edef5f259f9b9446943dcc5113898b51 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 29 Mar 2021 00:01:18 -0400 Subject: [PATCH 0186/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d2ba664de66..64077c47908 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210328) +set(CMake_VERSION_PATCH 20210329) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2e7719903032f4a7a9e223e1cd65e2c5132636ce Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 30 Mar 2021 00:01:18 -0400 Subject: [PATCH 0187/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 64077c47908..3798d8c6dde 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210329) +set(CMake_VERSION_PATCH 20210330) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3c867cff4a98bb198211e3d9f8494fbb478a29e4 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Tue, 22 Dec 2020 13:07:20 -0700 Subject: [PATCH 0188/1519] Fujitsu: Add support for the Fujitsu compiler in Trad mode Co-Author: Yuichiro Utsumi --- Help/manual/cmake-compile-features.7.rst | 1 + Help/variable/CMAKE_LANG_COMPILER_ID.rst | 1 + ...CMakeCheckCompilerFlagCommonPatterns.cmake | 2 +- Modules/CMakeDetermineCompilerId.cmake | 25 +++++++++- Modules/CMakeFortranCompilerId.F.in | 9 ++++ Modules/CMakeParseImplicitIncludeInfo.cmake | 15 ++++++ Modules/CMakePlatformId.h.in | 6 ++- Modules/Compiler/Fujitsu-C.cmake | 20 ++++++++ Modules/Compiler/Fujitsu-CXX.cmake | 47 +++++++++++++++++++ .../Compiler/Fujitsu-DetermineCompiler.cmake | 17 ++++++- Modules/Compiler/Fujitsu-Fortran.cmake | 16 +++++++ Modules/Compiler/Fujitsu.cmake | 33 +++++++++++++ Modules/Platform/Linux-Fujitsu-CXX.cmake | 8 ++++ Modules/Platform/Linux-Fujitsu.cmake | 17 +++++++ 14 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 Modules/Compiler/Fujitsu-C.cmake create mode 100644 Modules/Compiler/Fujitsu-CXX.cmake create mode 100644 Modules/Compiler/Fujitsu-Fortran.cmake create mode 100644 Modules/Compiler/Fujitsu.cmake create mode 100644 Modules/Platform/Linux-Fujitsu-CXX.cmake create mode 100644 Modules/Platform/Linux-Fujitsu.cmake diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 0d15ddfc34a..56d16c0b4c2 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -359,6 +359,7 @@ following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: * ``Cray``: Cray Compiler Environment version 8.1+. +* ``Fujitsu``: Fujitsu HPC compiler 4.0+. * ``PGI``: PGI version 12.10+. * ``NVHPC``: NVIDIA HPC compilers version 11.0+. * ``TI``: Texas Instruments compiler. diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index 89d9e2757e7..c4f61a9e400 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -19,6 +19,7 @@ include: Cray = Cray Compiler (cray.com) Embarcadero, Borland = Embarcadero (embarcadero.com) Flang = Flang LLVM Fortran Compiler + Fujitsu = Fujitsu HPC compiler (Trad mode) G95 = G95 Fortran (g95.org) GNU = GNU Compiler Collection (gcc.gnu.org) GHS = Green Hills Software (www.ghs.com) diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake index 2dc75d694b0..05174de83be 100644 --- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake +++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake @@ -8,7 +8,7 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) set(${_VAR} - FAIL_REGEX "[Uu]nrecogni[sz]ed .*option" # GNU, NAG + FAIL_REGEX "[Uu]nrecogni[sz]ed .*option" # GNU, NAG, Fujitsu FAIL_REGEX "switch .* is no longer supported" # GNU FAIL_REGEX "unknown .*option" # Clang FAIL_REGEX "optimization flag .* not supported" # Clang diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index f406e5ae005..017c51a8bd7 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -165,6 +165,25 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() endif() + # The Fujitsu compiler does not always convey version information through + # preprocessor symbols so we extract through command line info + if (CMAKE_${lang}_COMPILER_ID STREQUAL "Fujitsu") + if(NOT CMAKE_${lang}_COMPILER_VERSION) + execute_process( + COMMAND "${CMAKE_${lang}_COMPILER}" -V + OUTPUT_VARIABLE output + ERROR_VARIABLE output + RESULT_VARIABLE result + TIMEOUT 10 + ) + if (result EQUAL 0) + if (output MATCHES [[Fujitsu [^ ]* Compiler ([0-9]+\.[0-9]+\.[0-9]+)]]) + set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_MATCH_1}") + endif() + endif() + endif() + endif() + # if the format is unknown after all files have been checked, put "Unknown" in the cache if(NOT CMAKE_EXECUTABLE_FORMAT) set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format") @@ -830,8 +849,10 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}") endif() if("${info}" MATCHES "INFO:compiler_version_internal\\[([^]\"]*)\\]") - string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION_INTERNAL "${CMAKE_MATCH_1}") - string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}") + set(COMPILER_VERSION_INTERNAL "${CMAKE_MATCH_1}") + string(REGEX REPLACE "^0+([0-9]+)" "\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}") + string(REGEX REPLACE "\\.0+([0-9]+)" ".\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}") + string(STRIP "${COMPILER_VERSION_INTERNAL}" COMPILER_VERSION_INTERNAL) endif() foreach(comp MAJOR MINOR PATCH TWEAK) foreach(digit 1 2 3 4 5 6 7 8 9) diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 0a3db4cf6b0..0b92b6a1aac 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -136,6 +136,15 @@ #define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10) #define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10) #define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD) +#elif defined(__FUJITSU) + PRINT *, 'INFO:compiler[Fujitsu]' +# if defined(__FRT_major__) +# define COMPILER_VERSION_MAJOR DEC(__FRT_major__) +# define COMPILER_VERSION_MINOR DEC(__FRT_minor__) +# define COMPILER_VERSION_PATCH DEC(__FRT_patchlevel__) +# elif defined(__FRT_version__) + PRINT *, 'INFO:compiler_version['//__FRT_version__//']' +# endif #else PRINT *, 'INFO:compiler[]' #endif diff --git a/Modules/CMakeParseImplicitIncludeInfo.cmake b/Modules/CMakeParseImplicitIncludeInfo.cmake index 7cd75488cd7..a8e6ac0b6ee 100644 --- a/Modules/CMakeParseImplicitIncludeInfo.cmake +++ b/Modules/CMakeParseImplicitIncludeInfo.cmake @@ -146,6 +146,21 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) endif() endif() + # Fujitsu compiler + if(CMAKE_${lang}_COMPILER_ID STREQUAL "Fujitsu" AND + line MATCHES "/ccpcom") + string(REGEX MATCHALL " (-I *|--sys_include=|--preinclude +)(\"[^\"]+\"|[^ \"]+)" incs "${line}") + foreach(inc IN LISTS incs) + string(REGEX REPLACE " (-I *|--sys_include=|--preinclude +)(\"[^\"]+\"|[^ \"]+)" "\\2" idir "${inc}") + list(APPEND rv "${idir}") + endforeach() + if(rv) + string(APPEND log " got implicit includes via fujitsu ccpcom parser!\n") + else() + string(APPEND log " warning: fujitsu ccpcom parse failed!\n") + endif() + endif() + if(log) set(${log_var} "${log}" PARENT_SCOPE) else() diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 1dc12c06067..3ae9f490203 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -256,8 +256,12 @@ ('0' + ((n)>>4 & 0xF)), \ ('0' + ((n) & 0xF)) +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + /* Construct a string literal encoding the version number components. */ -#ifdef COMPILER_VERSION_MAJOR +#elif defined(COMPILER_VERSION_MAJOR) char const info_version[] = { 'I', 'N', 'F', 'O', ':', 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', diff --git a/Modules/Compiler/Fujitsu-C.cmake b/Modules/Compiler/Fujitsu-C.cmake new file mode 100644 index 00000000000..0e0f1dc0e21 --- /dev/null +++ b/Modules/Compiler/Fujitsu-C.cmake @@ -0,0 +1,20 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. +include(Compiler/Fujitsu) +__compiler_fujitsu(C) + +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4) + set(CMAKE_C89_STANDARD_COMPILE_OPTION -std=c89) + set(CMAKE_C89_EXTENSION_COMPILE_OPTION -std=gnu89) + set(CMAKE_C89_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_C99_STANDARD_COMPILE_OPTION -std=c99) + set(CMAKE_C99_EXTENSION_COMPILE_OPTION -std=gnu99) + set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_C11_STANDARD_COMPILE_OPTION -std=c11) + set(CMAKE_C11_EXTENSION_COMPILE_OPTION -std=gnu11) + set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +__compiler_check_default_language_standard(C 4 11) diff --git a/Modules/Compiler/Fujitsu-CXX.cmake b/Modules/Compiler/Fujitsu-CXX.cmake new file mode 100644 index 00000000000..0f42196e888 --- /dev/null +++ b/Modules/Compiler/Fujitsu-CXX.cmake @@ -0,0 +1,47 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. +include(Compiler/Fujitsu) +__compiler_fujitsu(CXX) + +#set(CMAKE_PCH_EXTENSION .pch) +#set(CMAKE_PCH_EPILOGUE "#pragma hdrstop") +#set(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH --no_pch_messages -include --use_pch ) +#set(CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH --no_pch_messages -include --create_pch ) + +# The Fujitsu compiler offers both a 98 and 03 mode. These two are +# essentially interchangeable as 03 simply provides clarity to some 98 +# ambiguyity. +# +# Re: Stroustrup's C++ FAQ: +# What is the difference between C++98 and C++03? +# From a programmer's view there is none. The C++03 revision of the +# standard was a bug fix release for implementers to ensure greater +# consistency and portability. In particular, tutorial and reference +# material describing C++98 and C++03 can be used interchangeably by all +# except compiler writers and standards gurus. +# +# Since CMake doesn't actually have an 03 mode and they're effectively +# interchangeable then we're just going to explicitly use 03 mode in the +# compiler when 98 is requested. + +# The version matching is messy here. The std support seems to be related to +# the compiler tweak version derived from the patch id in the version string. + +if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 4) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION -std=c++03) + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -std=gnu++03) + set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION -std=c++11) + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -std=gnu++11) + set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_CXX14_STANDARD_COMPILE_OPTION -std=c++14) + set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION -std=gnu++14) + set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION -std=c++17) + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION -std=gnu++17) +endif() + +__compiler_check_default_language_standard(CXX 4 14) diff --git a/Modules/Compiler/Fujitsu-DetermineCompiler.cmake b/Modules/Compiler/Fujitsu-DetermineCompiler.cmake index 73ee38c87e3..a8c655da515 100644 --- a/Modules/Compiler/Fujitsu-DetermineCompiler.cmake +++ b/Modules/Compiler/Fujitsu-DetermineCompiler.cmake @@ -1,2 +1,17 @@ -set(_compiler_id_pp_test "defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version)") +set(_compiler_id_pp_test "defined(__FUJITSU) && !defined(__CLANG_FUJITSU)") + +set(_compiler_id_version_compute " +# if defined(__FCC_version__) +# define @PREFIX@COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__FCC_major__) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__FCC_minor__) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__fcc_version) +# elif defined(__FCC_VERSION) +# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__FCC_VERSION) +# endif +") diff --git a/Modules/Compiler/Fujitsu-Fortran.cmake b/Modules/Compiler/Fujitsu-Fortran.cmake new file mode 100644 index 00000000000..0f687bc21b7 --- /dev/null +++ b/Modules/Compiler/Fujitsu-Fortran.cmake @@ -0,0 +1,16 @@ +include(Compiler/Fujitsu) +__compiler_fujitsu(Fortran) + +set(CMAKE_Fortran_SUBMODULE_SEP ".") +set(CMAKE_Fortran_SUBMODULE_EXT ".smod") + +set(CMAKE_Fortran_PREPROCESS_SOURCE + " -Cpp -E > ") +set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-Cpp") + +set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-Fixed") +set(CMAKE_Fortran_FORMAT_FREE_FLAG "-Free") + +string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT "") + +set(CMAKE_Fortran_MODDIR_FLAG "-M ") diff --git a/Modules/Compiler/Fujitsu.cmake b/Modules/Compiler/Fujitsu.cmake new file mode 100644 index 00000000000..13bc57c90dd --- /dev/null +++ b/Modules/Compiler/Fujitsu.cmake @@ -0,0 +1,33 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_FUJITSU) + return() +endif() +set(__COMPILER_FUJITSU 1) + +include(Compiler/CMakeCommonCompilerMacros) + +macro(__compiler_fujitsu lang) + set(CMAKE_${lang}_VERBOSE_FLAG "-###") + + # Initial configuration flags + string(APPEND CMAKE_${lang}_FLAGS_INIT " ") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g -O0") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") + + # PIC flags + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + + # Passing link options to the compiler + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") + + # How to actually call the compiler + set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE + " -E $<$:-Cpp> > ") + set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE " -S -o ") +endmacro() diff --git a/Modules/Platform/Linux-Fujitsu-CXX.cmake b/Modules/Platform/Linux-Fujitsu-CXX.cmake new file mode 100644 index 00000000000..d72dd49dfe2 --- /dev/null +++ b/Modules/Platform/Linux-Fujitsu-CXX.cmake @@ -0,0 +1,8 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details + +include(Platform/Linux-Fujitsu) +__linux_compiler_fujitsu(CXX) + +# Special sauce to propagate the -std=xxx flag when linking +set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION ON) diff --git a/Modules/Platform/Linux-Fujitsu.cmake b/Modules/Platform/Linux-Fujitsu.cmake new file mode 100644 index 00000000000..be11b0a9ff7 --- /dev/null +++ b/Modules/Platform/Linux-Fujitsu.cmake @@ -0,0 +1,17 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +if(__LINUX_COMPILER_FUJITSU) + return() +endif() +set(__LINUX_COMPILER_FUJITSU 1) + +macro(__linux_compiler_fujitsu lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") + set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") +endmacro() From d0b9ffb6304834915ae983ce44af1c92ec9cdd39 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Tue, 30 Mar 2021 09:46:09 -0400 Subject: [PATCH 0189/1519] KWSys 2021-03-30 (db93a594) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit db93a5948e331c8920ac701e35b2f7e283646cae (master). Upstream Shortlog ----------------- Lemures Lemniscati (2): 9a6d6c54 Terminal: Avoid using Windows functions on Cygwin 4c61b968 SystemTools::FileIsFullPath: Do not accept Windows paths on Cygwin --- SystemTools.cxx | 2 +- Terminal.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SystemTools.cxx b/SystemTools.cxx index cf04799776d..4d974a898bb 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -3926,7 +3926,7 @@ bool SystemTools::FileIsFullPath(const char* in_name) bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) { -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) // On Windows, the name must be at least two characters long. if (len < 2) { return false; diff --git a/Terminal.c b/Terminal.c index 4d1b46c8717..9409d1b7642 100644 --- a/Terminal.c +++ b/Terminal.c @@ -10,7 +10,7 @@ #endif /* Configure support for this platform. */ -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) # define KWSYS_TERMINAL_SUPPORT_CONSOLE #endif #if !defined(_WIN32) From 31c184ad690be45494cf997df71ad09293a0d4b0 Mon Sep 17 00:00:00 2001 From: Domen Vrankar Date: Mon, 29 Mar 2021 00:06:05 +0200 Subject: [PATCH 0190/1519] CPackRPM: handle scripts in debuginfo single package mode Enabling CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE while using rpm install or erase scripts resulted in resulted missing scripts for non default components. Fixes: #21974 --- Modules/Internal/CPack/CPackRPM.cmake | 19 +++++++++++++++++++ .../RunCMake/CPack/RPM/Prerequirements.cmake | 7 +++++++ Tests/RunCMake/CPack/RunCMakeTest.cmake | 2 +- .../tests/INSTALL_SCRIPTS/ExpectedFiles.cmake | 7 ++++++- ...RPM-COMPONENT-single_debug_info-stderr.txt | 1 + .../INSTALL_SCRIPTS/RPM-Prerequirements.cmake | 11 +++++++++++ .../CPack/tests/INSTALL_SCRIPTS/test.cmake | 6 ++++++ 7 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index 08bbc6804c6..2ee062238c3 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -1637,6 +1637,25 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ %description -n \@CPACK_RPM_PACKAGE_NAME\@ \@CPACK_RPM_PACKAGE_DESCRIPTION\@ +%post -n \@CPACK_RPM_PACKAGE_NAME\@ +\@RPM_SYMLINK_POSTINSTALL\@ +\@CPACK_RPM_SPEC_POSTINSTALL\@ + +%posttrans -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_POSTTRANS\@ + +%postun -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_POSTUNINSTALL\@ + +%pre -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_PREINSTALL\@ + +%pretrans -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_PRETRANS\@ + +%preun -n \@CPACK_RPM_PACKAGE_NAME\@ +\@CPACK_RPM_SPEC_PREUNINSTALL\@ + %files -n \@CPACK_RPM_PACKAGE_NAME\@ %defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@) \@CPACK_RPM_INSTALL_FILES\@ diff --git a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake index 3416205bc61..e95cd151617 100644 --- a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake +++ b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake @@ -13,4 +13,11 @@ function(get_test_prerequirements found_var config_file) "\nset(RPMBUILD_EXECUTABLE \"${RPMBUILD_EXECUTABLE}\")") set(${found_var} true PARENT_SCOPE) endif() + + # optional tool for some tests + find_program(OBJDUMP_EXECUTABLE objdump) + if(OBJDUMP_EXECUTABLE) + file(APPEND "${config_file}" + "\nset(OBJDUMP_EXECUTABLE \"${OBJDUMP_EXECUTABLE}\")") + endif() endfunction() diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 15bfb60ee0e..48b9c1d95c8 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -16,7 +16,7 @@ run_cpack_test(VERSION "RPM.VERSION;DEB.VERSION" false "MONOLITHIC;COMPONENT") run_cpack_test(EXTRA "DEB.EXTRA" false "COMPONENT") run_cpack_test_subtests(GENERATE_SHLIBS "soversion_not_zero;soversion_zero" "DEB.GENERATE_SHLIBS" true "COMPONENT") run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB.GENERATE_SHLIBS_LDCONFIG" true "COMPONENT") -run_cpack_test(INSTALL_SCRIPTS "RPM.INSTALL_SCRIPTS" false "COMPONENT") +run_cpack_test_subtests(INSTALL_SCRIPTS "default;single_debug_info" "RPM.INSTALL_SCRIPTS" false "COMPONENT") run_cpack_test(LONG_FILENAMES "DEB.LONG_FILENAMES" false "MONOLITHIC") run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM.MAIN_COMPONENT" false "COMPONENT") run_cpack_test(MINIMAL "RPM.MINIMAL;DEB.MINIMAL;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake index de38df9ef4c..29e36a33fb1 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake @@ -1,5 +1,10 @@ +if(RunCMake_SUBTEST_SUFFIX STREQUAL "single_debug_info") + set(EXPECTED_FILE_1 "install_scripts-0.1.1-1.*.rpm") +else() + set(EXPECTED_FILE_1_COMPONENT "foo") +endif() + set(EXPECTED_FILES_COUNT "2") -set(EXPECTED_FILE_1_COMPONENT "foo") set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_COMPONENT "bar") set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt new file mode 100644 index 00000000000..8d98f9debde --- /dev/null +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-single_debug_info-stderr.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake new file mode 100644 index 00000000000..c5d20cc6919 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake @@ -0,0 +1,11 @@ +function(get_test_prerequirements found_var config_file) + if(SUBTEST_SUFFIX STREQUAL "single_debug_info") + include(${config_file}) + + if(OBJDUMP_EXECUTABLE) + set(${found_var} true PARENT_SCOPE) + endif() + else() + set(${found_var} true PARENT_SCOPE) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake index c200fa502ca..6877c577449 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake @@ -24,6 +24,12 @@ if(GENERATOR_TYPE STREQUAL "RPM") "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh") set(CPACK_RPM_foo_POST_TRANS_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh") + + if(RunCMake_SUBTEST_SUFFIX STREQUAL "single_debug_info") + set(CPACK_RPM_MAIN_COMPONENT "foo") + set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) + set(CPACK_RPM_FOO_FILE_NAME "RPM-DEFAULT") + endif() endif() set(CMAKE_BUILD_WITH_INSTALL_RPATH 1) From d796948f44c09d7714163948e79f20e9b1f8dbe6 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 31 Mar 2021 00:01:19 -0400 Subject: [PATCH 0191/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3798d8c6dde..660414801d0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210330) +set(CMake_VERSION_PATCH 20210331) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a55feff69c7967d56e0935d841cf1ea2c980a43a Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Tue, 22 Dec 2020 13:07:48 -0700 Subject: [PATCH 0192/1519] Tests: Update for the Fujitsu compiler --- Tests/CheckFortran.cmake | 2 +- Tests/CompileFeatures/CMakeLists.txt | 4 ++-- Tests/ConfigSources/CMakeLists.txt | 1 + .../Import/Interface/pch_iface_test.cpp | 3 ++- Tests/Fortran/CMakeLists.txt | 2 +- Tests/FortranOnly/CMakeLists.txt | 21 +++++++++---------- .../CMakeLists.txt | 4 ++-- Tests/RunCMake/CMakeLists.txt | 2 +- .../subdir/fortran/CMakeLists.txt | 5 +++++ 9 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Tests/CheckFortran.cmake b/Tests/CheckFortran.cmake index 33e1bfbbb05..36293f51ce0 100644 --- a/Tests/CheckFortran.cmake +++ b/Tests/CheckFortran.cmake @@ -7,7 +7,7 @@ if(NOT DEFINED CMAKE_Fortran_COMPILER) message(STATUS ${_desc}) file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran/CMakeLists.txt" - "cmake_minimum_required(VERSION 2.4) + "cmake_minimum_required(VERSION 2.8.12) project(CheckFortran Fortran) file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" \"set(CMAKE_Fortran_COMPILER \\\"\${CMAKE_Fortran_COMPILER}\\\")\\n\" diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 7771967a120..f4fab518fc5 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -18,7 +18,7 @@ macro(run_test feature lang) endif() endmacro() -if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$") +if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES) list(FILTER c_features EXCLUDE REGEX "^c_std_[0-9][0-9]") foreach(feature ${c_features}) @@ -26,7 +26,7 @@ if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$") endforeach() endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$") +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) list(FILTER cxx_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") foreach(feature ${cxx_features}) diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt index a3d98f685fa..219a9724404 100644 --- a/Tests/ConfigSources/CMakeLists.txt +++ b/Tests/ConfigSources/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.0) get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE) endif() diff --git a/Tests/ExportImport/Import/Interface/pch_iface_test.cpp b/Tests/ExportImport/Import/Interface/pch_iface_test.cpp index a18bbde23f7..d676a5bed3e 100644 --- a/Tests/ExportImport/Import/Interface/pch_iface_test.cpp +++ b/Tests/ExportImport/Import/Interface/pch_iface_test.cpp @@ -3,7 +3,8 @@ # ifndef PCH_PCH_H_INCLUDED # error "Expected PCH_PCH_H_INCLUDED." # endif -#elif defined(__PGIC__) || defined(__ibmxl__) || defined(_CRAYC) +#elif defined(__PGIC__) || defined(__ibmxl__) || defined(_CRAYC) || \ + defined(__FUJITSU) // No PCH expected but these compilers define macros below. #elif defined(__GNUC__) || defined(__clang__) || defined(_INTEL_COMPILER) || \ defined(_MSC_VER) diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt index c1476be3883..2fc47a5191d 100644 --- a/Tests/Fortran/CMakeLists.txt +++ b/Tests/Fortran/CMakeLists.txt @@ -46,7 +46,7 @@ function(test_fortran_c_interface_module) FortranCInterface_VERIFY() FortranCInterface_VERIFY(CXX) if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) - if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "SunPro|PathScale|Absoft") + if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "SunPro|PathScale|Absoft|Fujitsu") set(module_expected 1) endif() if(FortranCInterface_MODULE_FOUND OR module_expected) diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt index b5b5e56e7fc..cdf8ed6228b 100644 --- a/Tests/FortranOnly/CMakeLists.txt +++ b/Tests/FortranOnly/CMakeLists.txt @@ -117,15 +117,9 @@ if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") target_compile_definitions(IntelIfDef PRIVATE SOME_DEF) endif() -# Skip these tests if compiler/version doesn't have preprocessing flags -if((CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 4.4) - OR (CMAKE_Fortran_COMPILER_ID STREQUAL "XL" AND CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 15.1.6)) - set(test_pp_flags 0) -else() - set(test_pp_flags 1) -endif() - -if(test_pp_flags) +# Skip these tests if compiler/version does enable and disable preprocessing +if(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON AND + CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF) # Test that we can always preprocess a target add_executable(preprocess_target preprocess2.f) set_property(TARGET preprocess_target PROPERTY Fortran_PREPROCESS ON) @@ -145,17 +139,22 @@ set_property(SOURCE no_preprocess_source_lower.f PROPERTY Fortran_PREPROCESS OFF # Test that we can explicitly not preprocess a target or source. # This will not work on certain compilers due to either missing a -# "don't preprocess" flag, or due to choice of file extension. -if(test_pp_flags AND NOT CMAKE_Fortran_COMPILER_ID MATCHES "(Flang|NAG|PGI|NVHPC|SunPro|XL)") +# "don't preprocess" flag, or due to the flags being ignored for +# extensions like '.F' and '.fpp'. +if(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF AND + NOT CMAKE_Fortran_COMPILER_ID MATCHES "(Flang|NAG|PGI|NVHPC|SunPro|XL)") add_library(no_preprocess_target STATIC no_preprocess_target_upper.F) target_compile_options(no_preprocess_target PRIVATE -DINTEGER=nonsense) + add_library(no_preprocess_source STATIC no_preprocess_source_upper.F) target_compile_options(no_preprocess_source PRIVATE -DINTEGER=nonsense) + if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL "Cray" AND NOT "${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" MATCHES "Intel(LLVM)?;MSVC") target_sources(no_preprocess_target PRIVATE no_preprocess_target_fpp.fpp) target_sources(no_preprocess_source PRIVATE no_preprocess_source_fpp.fpp) endif() + set_property(TARGET no_preprocess_target PROPERTY Fortran_PREPROCESS OFF) set_property(SOURCE no_preprocess_source_upper.F no_preprocess_source_fpp.fpp PROPERTY Fortran_PREPROCESS OFF) endif() diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index 0cf74bf08ca..d438e5449e0 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -52,7 +52,7 @@ endmacro() # detailed features tables, not just meta-features if (CMAKE_C_COMPILE_FEATURES) - if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$") + if (NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") set(C_expected_features ${CMAKE_C_COMPILE_FEATURES}) list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]") endif() @@ -95,7 +95,7 @@ if (C_expected_features) endif() if (CMAKE_CXX_COMPILE_FEATURES) - if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$") + if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES}) list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") endif() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 354a04eca39..3f3c3a01dd2 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -273,7 +273,7 @@ add_RunCMake_test(Graphviz) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(LinkStatic) -if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang)$") +if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|Fujitsu)$") add_RunCMake_test(MetaCompileFeatures) endif() if(MSVC) diff --git a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt index abd06283658..950ec25d530 100644 --- a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt +++ b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt @@ -43,4 +43,9 @@ if(CMAKE_Fortran_COMPILER_ID MATCHES SunPro) target_link_libraries(hello PRIVATE sunquad) endif() endif() +elseif(CMAKE_Fortran_COMPILER_ID MATCHES Fujitsu) + # Fujitsu Fortran doesn't automatically link its runtime libraries into + # SOs + target_link_libraries(world PRIVATE fj90i fj90f fjsrcinfo) + target_link_libraries(hello PRIVATE fj90i fj90f fjsrcinfo) endif() From 27579e9cf12a9994fc15ff9e5487f73cc0406428 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Tue, 22 Dec 2020 14:11:34 -0700 Subject: [PATCH 0193/1519] FujitsuClang: Add support for the Fujitsu compiler in Clang mode This should be front end compatible with vanilla clang but giving it a unique identifier allows a project to pass additional options unique to Fujitsu and outside the scope of a CMake builtin. --- Help/variable/CMAKE_LANG_COMPILER_ID.rst | 1 + Modules/CMakeCompilerIdDetection.cmake | 1 + Modules/CMakePlatformId.h.in | 2 ++ Modules/Compiler/Fujitsu-DetermineCompiler.cmake | 2 +- Modules/Compiler/FujitsuClang-C.cmake | 6 ++++++ Modules/Compiler/FujitsuClang-CXX.cmake | 6 ++++++ Modules/Compiler/FujitsuClang-DetermineCompiler.cmake | 9 +++++++++ Modules/Compiler/FujitsuClang.cmake | 11 +++++++++++ Modules/Platform/Linux-Fujitsu-C.cmake | 1 + Modules/Platform/Linux-Fujitsu-CXX.cmake | 9 +-------- 10 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 Modules/Compiler/FujitsuClang-C.cmake create mode 100644 Modules/Compiler/FujitsuClang-CXX.cmake create mode 100644 Modules/Compiler/FujitsuClang-DetermineCompiler.cmake create mode 100644 Modules/Compiler/FujitsuClang.cmake create mode 100644 Modules/Platform/Linux-Fujitsu-C.cmake diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index c4f61a9e400..0abedde6a56 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -20,6 +20,7 @@ include: Embarcadero, Borland = Embarcadero (embarcadero.com) Flang = Flang LLVM Fortran Compiler Fujitsu = Fujitsu HPC compiler (Trad mode) + FujitsuClang = Fujitsu HPC compiler (Clang mode) G95 = G95 Fortran (g95.org) GNU = GNU Compiler Collection (gcc.gnu.org) GHS = Green Hills Software (www.ghs.com) diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index 214d58a8ef3..c79d4239a91 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -66,6 +66,7 @@ function(compiler_id_detection outvar lang) PGI Cray TI + FujitsuClang Fujitsu GHS ) diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 3ae9f490203..2643874d194 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -285,6 +285,8 @@ char const info_version_internal[] = { 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', 'i','n','t','e','r','n','a','l','[', COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; #endif /* Construct a string literal encoding the version number components. */ diff --git a/Modules/Compiler/Fujitsu-DetermineCompiler.cmake b/Modules/Compiler/Fujitsu-DetermineCompiler.cmake index a8c655da515..85349161050 100644 --- a/Modules/Compiler/Fujitsu-DetermineCompiler.cmake +++ b/Modules/Compiler/Fujitsu-DetermineCompiler.cmake @@ -1,5 +1,5 @@ -set(_compiler_id_pp_test "defined(__FUJITSU) && !defined(__CLANG_FUJITSU)") +set(_compiler_id_pp_test "defined(__FUJITSU)") set(_compiler_id_version_compute " # if defined(__FCC_version__) diff --git a/Modules/Compiler/FujitsuClang-C.cmake b/Modules/Compiler/FujitsuClang-C.cmake new file mode 100644 index 00000000000..f700d2d5245 --- /dev/null +++ b/Modules/Compiler/FujitsuClang-C.cmake @@ -0,0 +1,6 @@ +include(Compiler/FujitsuClang) + +set(_fjclang_ver "${CMAKE_C_COMPILER_VERSION_INTERNAL}") +set(CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION_INTERNAL}") +include(Compiler/Clang-C) +set(CMAKE_C_COMPILER_VERSION "${_fjclang_ver}") diff --git a/Modules/Compiler/FujitsuClang-CXX.cmake b/Modules/Compiler/FujitsuClang-CXX.cmake new file mode 100644 index 00000000000..c8790cde313 --- /dev/null +++ b/Modules/Compiler/FujitsuClang-CXX.cmake @@ -0,0 +1,6 @@ +include(Compiler/FujitsuClang) + +set(_fjclang_ver "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") +set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") +include(Compiler/Clang-CXX) +set(CMAKE_CXX_COMPILER_VERSION "${_fjclang_ver}") diff --git a/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake b/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake new file mode 100644 index 00000000000..f6719b1b54f --- /dev/null +++ b/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake @@ -0,0 +1,9 @@ + +set(_compiler_id_pp_test "defined(__CLANG_FUJITSU)") + +set(_compiler_id_version_compute " +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__FCC_major__) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__FCC_minor__) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__FCC_patchlevel__) +# define @PREFIX@COMPILER_VERSION_INTERNAL_STR __clang_version__ +") diff --git a/Modules/Compiler/FujitsuClang.cmake b/Modules/Compiler/FujitsuClang.cmake new file mode 100644 index 00000000000..a848248b267 --- /dev/null +++ b/Modules/Compiler/FujitsuClang.cmake @@ -0,0 +1,11 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_FUJITSUCLANG) + return() +endif() +set(__COMPILER_FUJITSUCLANG 1) + +include(Compiler/Clang) diff --git a/Modules/Platform/Linux-Fujitsu-C.cmake b/Modules/Platform/Linux-Fujitsu-C.cmake new file mode 100644 index 00000000000..e37573dcacb --- /dev/null +++ b/Modules/Platform/Linux-Fujitsu-C.cmake @@ -0,0 +1 @@ +include(Platform/Linux-Clang-C) diff --git a/Modules/Platform/Linux-Fujitsu-CXX.cmake b/Modules/Platform/Linux-Fujitsu-CXX.cmake index d72dd49dfe2..5257f138317 100644 --- a/Modules/Platform/Linux-Fujitsu-CXX.cmake +++ b/Modules/Platform/Linux-Fujitsu-CXX.cmake @@ -1,8 +1 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details - -include(Platform/Linux-Fujitsu) -__linux_compiler_fujitsu(CXX) - -# Special sauce to propagate the -std=xxx flag when linking -set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION ON) +include(Platform/Linux-Clang-CXX) From a2374509485d7507b42f03f093456aeb62ca6811 Mon Sep 17 00:00:00 2001 From: Yuichiro Utsumi Date: Fri, 5 Mar 2021 09:07:19 +0000 Subject: [PATCH 0194/1519] Tests: Update for the FujitsuClang compiler --- Tests/CompileFeatures/CMakeLists.txt | 4 ++-- Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt | 4 ++-- Tests/RunCMake/CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index f4fab518fc5..20988ac4662 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -18,7 +18,7 @@ macro(run_test feature lang) endif() endmacro() -if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") +if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$") get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES) list(FILTER c_features EXCLUDE REGEX "^c_std_[0-9][0-9]") foreach(feature ${c_features}) @@ -26,7 +26,7 @@ if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujits endforeach() endif() -if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") +if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$") get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) list(FILTER cxx_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") foreach(feature ${cxx_features}) diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index d438e5449e0..e4067580a8b 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -52,7 +52,7 @@ endmacro() # detailed features tables, not just meta-features if (CMAKE_C_COMPILE_FEATURES) - if (NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") + if (NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$") set(C_expected_features ${CMAKE_C_COMPILE_FEATURES}) list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]") endif() @@ -95,7 +95,7 @@ if (C_expected_features) endif() if (CMAKE_CXX_COMPILE_FEATURES) - if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu)$") + if (NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM|Fujitsu|FujitsuClang)$") set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES}) list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") endif() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 3f3c3a01dd2..9a6a103b189 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -273,7 +273,7 @@ add_RunCMake_test(Graphviz) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(LinkStatic) -if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|Fujitsu)$") +if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|Fujitsu|FujitsuClang)$") add_RunCMake_test(MetaCompileFeatures) endif() if(MSVC) From 9e0a1cf03ed91bd52df9b5b66af5f203cf8b05c5 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Thu, 5 Sep 2019 15:08:48 -0400 Subject: [PATCH 0195/1519] FindMPI: Add support for the Fujitsu compiler wrappers Co-Author: Yuichiro Utsumi --- Modules/FindMPI.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 195ca496786..bea0d8d0dcc 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -277,6 +277,11 @@ set(_MPI_Fortran_GENERIC_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r mpif77 mpif77_r mpf77 mpf77_r mpifc) +#Fujitsu cross/own compiler names +set(_MPI_Fujitsu_C_COMPILER_NAMES mpifccpx mpifcc) +set(_MPI_Fujitsu_CXX_COMPILER_NAMES mpiFCCpx mpiFCC) +set(_MPI_Fujitsu_Fortran_COMPILER_NAMES mpifrtpx mpifrt) + # GNU compiler names set(_MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r) set(_MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r mpigxx) @@ -337,7 +342,7 @@ set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95 # pick up the right settings for it. foreach (LANG IN ITEMS C CXX Fortran) set(_MPI_${LANG}_COMPILER_NAMES "") - foreach (id IN ITEMS GNU Intel IntelLLVM MSVC PGI XL) + foreach (id IN ITEMS Fujitsu FujitsuClang GNU Intel IntelLLVM MSVC PGI XL) if (NOT CMAKE_${LANG}_COMPILER_ID OR CMAKE_${LANG}_COMPILER_ID STREQUAL id) foreach(_COMPILER_NAME IN LISTS _MPI_${id}_${LANG}_COMPILER_NAMES) list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX}) From 376c300b259fe4267085265cf8519fa749f882e1 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Thu, 5 Sep 2019 15:14:29 -0400 Subject: [PATCH 0196/1519] FindOpenMP: Add support for Fujitsu compilers Co-Author: Yuichiro Utsumi --- Modules/FindOpenMP.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index 52330a49706..e982e2d593c 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -130,6 +130,8 @@ function(_OPENMP_FLAG_CANDIDATES LANG) set(OMP_FLAG_XL "-qsmp=omp") # Cray compiler activate OpenMP with -h omp, which is enabled by default. set(OMP_FLAG_Cray " " "-h omp") + set(OMP_FLAG_Fujitsu "-Kopenmp" "-KOMP") + set(OMP_FLAG_FujitsuClang "-fopenmp" "-Kopenmp") # If we know the correct flags, use those if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}) From 4c74c86f4099ed63f429d39394f7c7117430a8a6 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Wed, 27 Jan 2021 08:56:17 -0700 Subject: [PATCH 0197/1519] FindBLAS/LAPACK: Add support for the Fujitsu SSL2 library This also does some additional work to fix issues with libraries provided only via compiler options and no explicit library names. Co-Author: Yuichiro Utsumi --- Modules/FindBLAS.cmake | 75 ++++++++++++++++++++++++++---------- Modules/FindLAPACK.cmake | 83 ++++++++++++++++++++++++++++++++-------- 2 files changed, 122 insertions(+), 36 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 4cf812b7faa..14a8665627b 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -55,6 +55,8 @@ The following variables may be set to influence this module's behavior: * ``Arm_ilp64_mp`` * ``EML`` * ``EML_mt`` + * ``Fujitsu_SSL2`` (Fujitsu serial blas / lapack) + * ``Fujitsu_SSL2BLAMP`` (Fujitsu parallel blas / lapack) * ``Generic`` .. versionadded:: 3.6 @@ -78,6 +80,7 @@ The following variables may be set to influence this module's behavior: .. versionadded:: 3.20 Elbrus Math Library support (``EML``, ``EML_mt``). + Fujitsu SSL2 Library support (``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``) ``BLA_F95`` if ``ON`` tries to find the BLAS95 interfaces @@ -153,13 +156,18 @@ if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_CO endif() function(_add_blas_target) - if(NOT TARGET BLAS::BLAS) + if(BLAS_FOUND AND NOT TARGET BLAS::BLAS) add_library(BLAS::BLAS INTERFACE IMPORTED) if(BLAS_LIBRARIES) set_target_properties(BLAS::BLAS PROPERTIES INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARIES}" ) endif() + if(BLAS_LINKER_FLAGS) + set_target_properties(BLAS::BLAS PROPERTIES + INTERFACE_LINK_OPTIONS "${BLAS_LINKER_FLAGS}" + ) + endif() endif() endfunction() @@ -228,34 +236,34 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add endif() list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") - foreach(_library ${_list}) + foreach(_library ${_list} ${_threadlibs}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) set(${LIBRARIES} ${${LIBRARIES}} "${_library}") else() - set(_combined_name ${_combined_name}_${_library}) - if(NOT "${_threadlibs}" STREQUAL "") - set(_combined_name ${_combined_name}_threadlibs) - endif() + string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") + set(_combined_name ${_combined_name}_${_lib_var}) if(_libraries_work) - find_library(${_prefix}_${_library}_LIBRARY + find_library(${_prefix}_${_lib_var}_LIBRARY NAMES ${_library} NAMES_PER_DIR PATHS ${_extaddlibdir} PATH_SUFFIXES ${_subdirs} ) - #message("DEBUG: find_library(${_library}) got ${${_prefix}_${_library}_LIBRARY}") - mark_as_advanced(${_prefix}_${_library}_LIBRARY) - set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) - set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) + mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY) + set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_lib_var}_LIBRARY}) + set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY}) endif() endif() endforeach() + foreach(_flag ${_flags}) + string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}") + set(_combined_name ${_combined_name}_${_flag_var}) + endforeach() if(_libraries_work) # Test this combination of libraries. set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_threadlibs}) - #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}") if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -274,12 +282,12 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add else() set(${LIBRARIES} FALSE) endif() - #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}") endmacro() set(BLAS_LINKER_FLAGS) set(BLAS_LIBRARIES) set(BLAS95_LIBRARIES) +set(_blas_fphsa_req_var BLAS_LIBRARIES) if(NOT $ENV{BLA_VENDOR} STREQUAL "") set(BLA_VENDOR $ENV{BLA_VENDOR}) else() @@ -302,6 +310,9 @@ if(BLA_VENDOR STREQUAL "All") "" ) endif() + if(BLAS_WORKS) + set(_blas_fphsa_req_var BLAS_WORKS) + endif() endif() # BLAS in the Intel MKL 10+ library? @@ -1016,6 +1027,31 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") endif() +# Fujitsu SSL2 Library? +if(NOT BLAS_LIBRARIES AND + BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All") + if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP") + set(_ssl2_suffix BLAMP) + else() + set(_ssl2_suffix) + endif() + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "-SSL2${_ssl2_suffix}" + "" + "" + "" + "" + ) + if(BLAS_LIBRARIES) + set(BLAS_LINKER_FLAGS "-SSL2${_ssl2_suffix}") + set(_blas_fphsa_req_var BLAS_LINKER_FLAGS) + endif() + unset(_ssl2_suffix) +endif() + # Generic BLAS library? if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) @@ -1032,17 +1068,16 @@ if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All") endif() endif() -if(NOT BLA_F95) - find_package_handle_standard_args(BLAS REQUIRED_VARS BLAS_LIBRARIES) -endif() - - -# On compilers that implicitly link BLAS (such as ftn, cc, and CC on Cray HPC machines) -# we used a placeholder for empty BLAS_LIBRARIES to get through our logic above. +# On compilers that implicitly link BLAS (i.e. CrayPrgEnv) we used a +# placeholder for empty BLAS_LIBRARIES to get through our logic above. if(BLAS_LIBRARIES STREQUAL "BLAS_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES") set(BLAS_LIBRARIES "") endif() +if(NOT BLA_F95) + find_package_handle_standard_args(BLAS REQUIRED_VARS ${_blas_fphsa_req_var}) +endif() + _add_blas_target() cmake_pop_check_state() set(CMAKE_FIND_LIBRARY_SUFFIXES ${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 45e4be72ff6..a5b16ca2291 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -45,6 +45,8 @@ The following variables may be set to influence this module's behavior: * ``Arm_ilp64_mp`` * ``EML`` * ``EML_mt`` + * ``Fujitsu_SSL2`` (Fujitsu serial blas / lapack) + * ``Fujitsu_SSL2BLAMP`` (Fujitsu parallel blas / lapack) * ``Generic`` .. versionadded:: 3.6 @@ -68,6 +70,7 @@ The following variables may be set to influence this module's behavior: .. versionadded:: 3.20 Elbrus Math Library support (``EML``, ``EML_mt``). + Fujitsu SSL2 Library support (``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``) ``BLA_F95`` if ``ON`` tries to find the BLAS95/LAPACK95 interfaces @@ -130,20 +133,33 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) function(_add_lapack_target) if(LAPACK_FOUND AND NOT TARGET LAPACK::LAPACK) add_library(LAPACK::LAPACK INTERFACE IMPORTED) + + # Filter out redundant BLAS info and replace with the BLAS target set(_lapack_libs "${LAPACK_LIBRARIES}") - if(_lapack_libs AND TARGET BLAS::BLAS) - # remove the ${BLAS_LIBRARIES} from the interface and replace it - # with the BLAS::BLAS target - list(REMOVE_ITEM _lapack_libs "${BLAS_LIBRARIES}") + set(_lapack_flags "${LAPACK_LINKER_FLAGS}") + if(TARGET BLAS::BLAS) + if(_lapack_libs AND BLAS_LIBRARIES) + foreach(_blas_lib IN LISTS BLAS_LIBRARIES) + list(REMOVE_ITEM _lapack_libs "${_blas_lib}") + endforeach() + endif() + if(_lapack_flags AND BLAS_LINKER_FLAGS) + foreach(_blas_flag IN LISTS BLAS_LINKER_FLAGS) + list(REMOVE_ITEM _lapack_flags "${_blas_flag}") + endforeach() + endif() list(APPEND _lapack_libs BLAS::BLAS) endif() - if(_lapack_libs) set_target_properties(LAPACK::LAPACK PROPERTIES INTERFACE_LINK_LIBRARIES "${_lapack_libs}" ) endif() - unset(_lapack_libs) + if(_lapack_flags) + set_target_properties(LAPACK::LAPACK PROPERTIES + INTERFACE_LINK_OPTIONS "${_lapack_flags}" + ) + endif() endif() endfunction() @@ -202,32 +218,35 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a endif() list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") - foreach(_library ${_list}) + foreach(_library ${_list} ${_threadlibs}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) set(${LIBRARIES} ${${LIBRARIES}} "${_library}") else() - set(_combined_name ${_combined_name}_${_library}) + string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") + set(_combined_name ${_combined_name}_${_lib_var}) if(_libraries_work) - find_library(${_prefix}_${_library}_LIBRARY + find_library(${_prefix}_${_lib_var}_LIBRARY NAMES ${_library} NAMES_PER_DIR PATHS ${_extaddlibdir} PATH_SUFFIXES ${_subdirs} ) - #message("DEBUG: find_library(${_library}) got ${${_prefix}_${_library}_LIBRARY}") - mark_as_advanced(${_prefix}_${_library}_LIBRARY) - set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) - set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) + mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY) + set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_lib_var}_LIBRARY}) + set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY}) endif() endif() endforeach() unset(_library) + foreach(_flag ${_flags}) + string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}") + set(_combined_name ${_combined_name}_${_flag_var}) + endforeach() if(_libraries_work) # Test this combination of libraries. set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas} ${_threadlibs}) - #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}") if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -250,7 +269,6 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a unset(_extaddlibdir) unset(_libraries_work) unset(_combined_name) - #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}") endmacro() macro(_lapack_find_dependency dep) @@ -279,6 +297,7 @@ _lapack_find_library_setup() set(LAPACK_LINKER_FLAGS) set(LAPACK_LIBRARIES) set(LAPACK95_LIBRARIES) +set(_lapack_fphsa_req_var LAPACK_LIBRARIES) # Check the language being used if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED)) @@ -585,6 +604,38 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) ) endif() + # Fujitsu SSL2 Library? + if(NOT LAPACK_LIBRARIES + AND BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All") + if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP") + set(_ssl2_suffix BLAMP) + else() + set(_ssl2_suffix) + endif() + set(_ssl2_blas) + if(BLAS_LIBRARIES STREQUAL "") + set(_ssl2_blas "${BLAS_LINKER_FLAGS}") + else() + set(_ssl2_blas "${BLAS_LIBRARIES} ${BLAS_LINKER_FLAGS}") + endif() + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "-SSL2${_ssl2_suffix}" + "" + "" + "" + "" + "${_ssl2_blas}" + ) + if(LAPACK_LIBRARIES) + set(LAPACK_LINKER_FLAGS "-SSL2${_ssl2_suffix}") + set(_lapack_fphsa_req_var LAPACK_LINKER_FLAGS) + endif() + unset(_ssl2_suffix) + endif() + # Generic LAPACK library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "Generic" @@ -612,7 +663,7 @@ if(LAPACK_NOT_FOUND_MESSAGE) set(LAPACK_NOT_FOUND_MESSAGE REASON_FAILURE_MESSAGE ${LAPACK_NOT_FOUND_MESSAGE}) endif() -find_package_handle_standard_args(LAPACK REQUIRED_VARS LAPACK_LIBRARIES +find_package_handle_standard_args(LAPACK REQUIRED_VARS ${_lapack_fphsa_req_var} ${LAPACK_NOT_FOUND_MESSAGE}) unset(LAPACK_NOT_FOUND_MESSAGE) From 8ef55dec292b307e8be85d9d9a5424f0468d441f Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Tue, 22 Dec 2020 14:31:54 -0700 Subject: [PATCH 0198/1519] Help: Add release notes for Fujitsu compiler support --- Help/release/dev/fujitsu-compiler-support.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Help/release/dev/fujitsu-compiler-support.rst diff --git a/Help/release/dev/fujitsu-compiler-support.rst b/Help/release/dev/fujitsu-compiler-support.rst new file mode 100644 index 00000000000..c6f8cfbbcec --- /dev/null +++ b/Help/release/dev/fujitsu-compiler-support.rst @@ -0,0 +1,11 @@ +fujitsu-compiler-support +------------------------ + +* Addition of the ``Fujitsu`` compiler ID operating in traditional ``Trad`` + mode and ``FujitsuClang`` operating in ``Clang`` mode. +* The :module:`FindOpenMP` module learned to support ``Fujitsu`` and + ``FujitsuClang``. +* The :module:`FindMPI` module learned to support ``Fujitsu`` and + ``FujitsuClang`` in both host and cross compiling modes. +* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support + the serial ``Fujitsu SSL2`` and parallel ``Fujitsu SSL2BLAMP`` libraries. From 5ac8b923f503dcd02c47aa920afc747978bb07ab Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 31 Mar 2021 10:24:24 -0400 Subject: [PATCH 0199/1519] CMakePresets.json: Add matches condition --- Help/manual/cmake-presets.7.rst | 16 ++++++ Help/manual/presets/schema.json | 48 ++++++++++++++++ Source/cmCMakePresetsFile.cxx | 20 +++++++ Source/cmCMakePresetsFileInternal.h | 10 ++++ Source/cmCMakePresetsFileReadJSON.cxx | 20 +++++++ .../RunCMake/CMakePresets/Conditions.json.in | 57 +++++++++++++++++++ .../CMakePresets/InvalidRegex-result.txt | 1 + .../CMakePresets/InvalidRegex-stderr.txt | 2 + .../CMakePresets/InvalidRegex.json.in | 15 +++++ .../CMakePresets/ListConditions-stdout.txt | 4 ++ .../RunCMake/CMakePresets/RunCMakeTest.cmake | 1 + 11 files changed, 194 insertions(+) create mode 100644 Tests/RunCMake/CMakePresets/InvalidRegex-result.txt create mode 100644 Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/InvalidRegex.json.in diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index cc726032036..8543be388d8 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -864,6 +864,22 @@ object, it has the following fields: A required list of strings to search. This field supports macro expansion, and uses short-circuit evaluation. + ``"matches"`` + + ``"notMatches"`` + + Indicates that the condition searches for a regular expression in a string. + The condition object will have the following additional fields: + + ``string`` + + A required string to search. This field supports macro expansion. + + ``regex`` + + A required regular expression to search for. This field supports macro + expansion. + ``"anyOf"`` ``"allOf"`` diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index c3c3ca1fd24..9261519d681 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -1108,6 +1108,54 @@ ], "additionalProperties": false }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "matches" + }, + "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" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string specifying the type of the condition.", + "const": "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" + ], + "additionalProperties": false + }, { "type": "object", "properties": { diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index fbe9fe59d5d..d44dfb31c07 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -11,6 +11,8 @@ #include +#include "cmsys/RegularExpression.hxx" + #include "cmCMakePresetsFileInternal.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -561,6 +563,24 @@ bool cmCMakePresetsFileInternal::InListCondition::Evaluate( return true; } +bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate( + const std::vector& expanders, int version, + cm::optional& out) const +{ + std::string str = this->String; + CHECK_EXPAND(out, str, expanders, version); + std::string regexStr = this->Regex; + CHECK_EXPAND(out, regexStr, expanders, version); + + cmsys::RegularExpression regex; + if (!regex.compile(regexStr)) { + return false; + } + + out = regex.find(str); + return true; +} + bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate( const std::vector& expanders, int version, cm::optional& out) const diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h index ffb6ce93a6c..326927612af 100644 --- a/Source/cmCMakePresetsFileInternal.h +++ b/Source/cmCMakePresetsFileInternal.h @@ -81,6 +81,16 @@ class InListCondition : public cmCMakePresetsFile::Condition std::vector List; }; +class MatchesCondition : public cmCMakePresetsFile::Condition +{ +public: + bool Evaluate(const std::vector& expanders, int version, + cm::optional& out) const override; + + std::string String; + std::string Regex; +}; + class AnyAllOfCondition : public cmCMakePresetsFile::Condition { public: diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx index e26e7b47e70..403fac6a7fd 100644 --- a/Source/cmCMakePresetsFileReadJSON.cxx +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -93,6 +93,16 @@ auto const InListConditionHelper = .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List, ConditionStringListHelper, true); +auto const MatchesConditionHelper = + cmJSONObjectHelper(ReadFileResult::READ_OK, + ReadFileResult::INVALID_CONDITION, false) + .Bind("type"_s, nullptr, ConditionStringHelper, true) + .Bind("string"_s, &cmCMakePresetsFileInternal::MatchesCondition::String, + ConditionStringHelper, true) + .Bind("regex"_s, &cmCMakePresetsFileInternal::MatchesCondition::Regex, + ConditionStringHelper, true); + ReadFileResult SubConditionHelper( std::unique_ptr& out, const Json::Value* value); @@ -177,6 +187,16 @@ ReadFileResult ConditionHelper( return ReadFileResult::READ_OK; } + if (type == "matches" || type == "notMatches") { + auto c = cm::make_unique(); + CHECK_OK(MatchesConditionHelper(*c, value)); + out = std::move(c); + if (type == "notMatches") { + out = InvertCondition(std::move(out)); + } + return ReadFileResult::READ_OK; + } + if (type == "anyOf" || type == "allOf") { auto c = cm::make_unique(); diff --git a/Tests/RunCMake/CMakePresets/Conditions.json.in b/Tests/RunCMake/CMakePresets/Conditions.json.in index 9a01e2f0385..9c0c6bddf3e 100644 --- a/Tests/RunCMake/CMakePresets/Conditions.json.in +++ b/Tests/RunCMake/CMakePresets/Conditions.json.in @@ -180,6 +180,63 @@ ] } }, + { + "name": "MatchesTrue", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "aaa", + "regex": "^a*$" + } + }, + { + "name": "MatchesFalse", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "aab", + "regex": "^a*$" + } + }, + { + "name": "MatchesMacroString", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "${presetName}", + "regex": "^Matches" + } + }, + { + "name": "MatchesMacroRegex", + "inherits": "Base", + "condition": { + "type": "matches", + "string": "stuff", + "regex": "$env{CONDITION_REGEX}" + }, + "environment": { + "CONDITION_REGEX": "^stuf*$" + } + }, + { + "name": "NotMatchesTrue", + "inherits": "Base", + "condition": { + "type": "notMatches", + "string": "aab", + "regex": "^a*$" + } + }, + { + "name": "NotMatchesFalse", + "inherits": "Base", + "condition": { + "type": "notMatches", + "string": "aaa", + "regex": "^a*$" + } + }, { "name": "AnyOfTrue1", "inherits": "Base", diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/InvalidRegex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt new file mode 100644 index 00000000000..5b500e44e84 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/InvalidRegex-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/InvalidRegex: Invalid macro expansion$ diff --git a/Tests/RunCMake/CMakePresets/InvalidRegex.json.in b/Tests/RunCMake/CMakePresets/InvalidRegex.json.in new file mode 100644 index 00000000000..69114d2e30a --- /dev/null +++ b/Tests/RunCMake/CMakePresets/InvalidRegex.json.in @@ -0,0 +1,15 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "InvalidRegex", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@", + "condition": { + "type": "matches", + "string": "a", + "regex": "+" + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt index 19f91d4e835..91e001707a3 100644 --- a/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt +++ b/Tests/RunCMake/CMakePresets/ListConditions-stdout.txt @@ -12,6 +12,10 @@ Available configure presets: "InListMacroList" "InListShortCircuit" "NotInListTrue" + "MatchesTrue" + "MatchesMacroString" + "MatchesMacroRegex" + "NotMatchesTrue" "AnyOfTrue1" "AnyOfTrue2" "AnyOfShortCircuit" diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 22425b24aab..95234302f00 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -117,6 +117,7 @@ run_cmake_presets(NoSuchMacro) run_cmake_presets(EnvCycle) run_cmake_presets(EmptyEnv) run_cmake_presets(EmptyPenv) +run_cmake_presets(InvalidRegex) set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) run_cmake_presets(ConditionFuture) run_cmake_presets(SubConditionNull) From a8d2f7f459b861bee52990db9c1ed9f603dc6ef9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 1 Apr 2021 00:01:23 -0400 Subject: [PATCH 0200/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 660414801d0..9893e4bf322 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210331) +set(CMake_VERSION_PATCH 20210401) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 34c8a23044eaf8d56f405c4c9f13b53d0b47c963 Mon Sep 17 00:00:00 2001 From: Domen Vrankar Date: Thu, 1 Apr 2021 22:28:24 +0200 Subject: [PATCH 0201/1519] CPackRPM: add scriplets tags only if scripts exist Scriplet tags should not be added to generated spec files if scripts weren't provided as those tags are otherwise present in generated rpm file even if the script wasn't provided thereby generating unneeded dependency on shell. Fixes: #21345 --- Modules/Internal/CPack/CPackRPM.cmake | 103 ++++++++++------ Tests/RunCMake/CPack/RunCMakeTest.cmake | 2 +- .../tests/INSTALL_SCRIPTS/ExpectedFiles.cmake | 2 +- ...NT-no_scripts_single_debug_info-stderr.txt | 1 + .../INSTALL_SCRIPTS/RPM-Prerequirements.cmake | 2 +- .../tests/INSTALL_SCRIPTS/VerifyResult.cmake | 39 ++++--- .../CPack/tests/INSTALL_SCRIPTS/test.cmake | 110 +++++++++--------- 7 files changed, 153 insertions(+), 106 deletions(-) create mode 100644 Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index faaff7bd1a7..bece2dd1de2 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -6,6 +6,56 @@ cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST +function(set_spec_script_if_enabled TYPE PACKAGE_NAME VAR) + if(NOT "${VAR}" STREQUAL "" AND NOT "${VAR}" STREQUAL "\n") + if(PACKAGE_NAME) + set(PACKAGE_NAME " -n ${PACKAGE_NAME}") + endif() + set(${TYPE}_ + "%${TYPE}${PACKAGE_NAME}\n" + "${VAR}\n" PARENT_SCOPE) + else() + set(${TYPE} "" PARENT_SCOPE) + endif() +endfunction() + +macro(set_spec_scripts PACKAGE_NAME) + # we should only set scripts that were provided + # as script announcement without content inside + # spec file will generate unneeded dependency + # on shell + + set_spec_script_if_enabled( + "post" + "${PACKAGE_NAME}" + "${RPM_SYMLINK_POSTINSTALL}\n${CPACK_RPM_SPEC_POSTINSTALL}") + + set_spec_script_if_enabled( + "posttrans" + "${PACKAGE_NAME}" + "${CPACK_RPM_SPEC_POSTTRANS}") + + set_spec_script_if_enabled( + "postun" + "${PACKAGE_NAME}" + "${CPACK_RPM_SPEC_POSTUNINSTALL}") + + set_spec_script_if_enabled( + "pre" + "${PACKAGE_NAME}" + "${CPACK_RPM_SPEC_PREINSTALL}") + + set_spec_script_if_enabled( + "pretrans" + "${PACKAGE_NAME}" + "${CPACK_RPM_SPEC_PRETRANS}") + + set_spec_script_if_enabled( + "preun" + "${PACKAGE_NAME}" + "${CPACK_RPM_SPEC_PREUNINSTALL}") +endmacro() + function(get_file_permissions FILE RETURN_VAR) execute_process(COMMAND ls -l ${FILE} OUTPUT_VARIABLE permissions_ @@ -1613,6 +1663,9 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ ) elseif(GENERATE_SPEC_PARTS) # binary rpm with single debuginfo package + + set_spec_scripts("${CPACK_RPM_PACKAGE_NAME}") + file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in "# -*- rpm-spec -*- %package -n \@CPACK_RPM_PACKAGE_NAME\@ @@ -1643,24 +1696,12 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ %description -n \@CPACK_RPM_PACKAGE_NAME\@ \@CPACK_RPM_PACKAGE_DESCRIPTION\@ -%post -n \@CPACK_RPM_PACKAGE_NAME\@ -\@RPM_SYMLINK_POSTINSTALL\@ -\@CPACK_RPM_SPEC_POSTINSTALL\@ - -%posttrans -n \@CPACK_RPM_PACKAGE_NAME\@ -\@CPACK_RPM_SPEC_POSTTRANS\@ - -%postun -n \@CPACK_RPM_PACKAGE_NAME\@ -\@CPACK_RPM_SPEC_POSTUNINSTALL\@ - -%pre -n \@CPACK_RPM_PACKAGE_NAME\@ -\@CPACK_RPM_SPEC_PREINSTALL\@ - -%pretrans -n \@CPACK_RPM_PACKAGE_NAME\@ -\@CPACK_RPM_SPEC_PRETRANS\@ - -%preun -n \@CPACK_RPM_PACKAGE_NAME\@ -\@CPACK_RPM_SPEC_PREUNINSTALL\@ +\@post_\@ +\@posttrans_\@ +\@postun_\@ +\@pre_\@ +\@pretrans_\@ +\@preun_\@ %files -n \@CPACK_RPM_PACKAGE_NAME\@ %defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@) @@ -1687,6 +1728,8 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ set(RPMBUILD_FLAGS "-bb") if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE) + set_spec_scripts("") + file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in "# Restore old style debuginfo creation for rpm >= 4.14. %undefine _debugsource_packages @@ -1750,24 +1793,12 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT %clean -%post -\@RPM_SYMLINK_POSTINSTALL\@ -\@CPACK_RPM_SPEC_POSTINSTALL\@ - -%posttrans -\@CPACK_RPM_SPEC_POSTTRANS\@ - -%postun -\@CPACK_RPM_SPEC_POSTUNINSTALL\@ - -%pre -\@CPACK_RPM_SPEC_PREINSTALL\@ - -%pretrans -\@CPACK_RPM_SPEC_PRETRANS\@ - -%preun -\@CPACK_RPM_SPEC_PREUNINSTALL\@ +\@post_\@ +\@posttrans_\@ +\@postun_\@ +\@pre_\@ +\@pretrans_\@ +\@preun_\@ %files %defattr(\@TMP_DEFAULT_FILE_PERMISSIONS\@,\@TMP_DEFAULT_USER\@,\@TMP_DEFAULT_GROUP\@,\@TMP_DEFAULT_DIR_PERMISSIONS\@) diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 48b9c1d95c8..a3c72a1cf29 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -16,7 +16,7 @@ run_cpack_test(VERSION "RPM.VERSION;DEB.VERSION" false "MONOLITHIC;COMPONENT") run_cpack_test(EXTRA "DEB.EXTRA" false "COMPONENT") run_cpack_test_subtests(GENERATE_SHLIBS "soversion_not_zero;soversion_zero" "DEB.GENERATE_SHLIBS" true "COMPONENT") run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB.GENERATE_SHLIBS_LDCONFIG" true "COMPONENT") -run_cpack_test_subtests(INSTALL_SCRIPTS "default;single_debug_info" "RPM.INSTALL_SCRIPTS" false "COMPONENT") +run_cpack_test_subtests(INSTALL_SCRIPTS "default;single_debug_info;no_scripts;no_scripts_single_debug_info" "RPM.INSTALL_SCRIPTS" false "COMPONENT") run_cpack_test(LONG_FILENAMES "DEB.LONG_FILENAMES" false "MONOLITHIC") run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM.MAIN_COMPONENT" false "COMPONENT") run_cpack_test(MINIMAL "RPM.MINIMAL;DEB.MINIMAL;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake index 29e36a33fb1..5a87c442b55 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake @@ -1,4 +1,4 @@ -if(RunCMake_SUBTEST_SUFFIX STREQUAL "single_debug_info") +if(RunCMake_SUBTEST_SUFFIX MATCHES ".*single_debug_info") set(EXPECTED_FILE_1 "install_scripts-0.1.1-1.*.rpm") else() set(EXPECTED_FILE_1_COMPONENT "foo") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt new file mode 100644 index 00000000000..8d98f9debde --- /dev/null +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-COMPONENT-no_scripts_single_debug_info-stderr.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake index c5d20cc6919..90cfe4467fb 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake @@ -1,5 +1,5 @@ function(get_test_prerequirements found_var config_file) - if(SUBTEST_SUFFIX STREQUAL "single_debug_info") + if(SUBTEST_SUFFIX MATCHES ".*single_debug_info") include(${config_file}) if(OBJDUMP_EXECUTABLE) diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake index 1a1e9837370..0c42d906957 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/VerifyResult.cmake @@ -7,23 +7,34 @@ function(checkScripts_ FILE COMPARE_LIST) ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE "\n" ";" FILE_SCRIPTS_LIST_ "${FILE_SCRIPTS_}") + if(COMPARE_LIST STREQUAL "") + if(NOT FILE_SCRIPTS_ STREQUAL "") + message(FATAL_ERROR "No scripts were expected in '${FILE}'; file info: '${FILE_SCRIPTS_}'") + endif() + else() + string(REPLACE "\n" ";" FILE_SCRIPTS_LIST_ "${FILE_SCRIPTS_}") + + foreach(COMPARE_REGEX_ IN LISTS COMPARE_LIST) + unset(FOUND_) - foreach(COMPARE_REGEX_ IN LISTS COMPARE_LIST) - unset(FOUND_) + foreach(COMPARE_ IN LISTS FILE_SCRIPTS_LIST_) + if(COMPARE_ MATCHES "${COMPARE_REGEX_}") + set(FOUND_ true) + break() + endif() + endforeach() - foreach(COMPARE_ IN LISTS FILE_SCRIPTS_LIST_) - if(COMPARE_ MATCHES "${COMPARE_REGEX_}") - set(FOUND_ true) - break() + if(NOT FOUND_) + message(FATAL_ERROR "Missing scripts in '${FILE}'; file info: '${FILE_SCRIPTS_}'; missing: '${COMPARE_REGEX_}'") endif() endforeach() - - if(NOT FOUND_) - message(FATAL_ERROR "Missing scripts in '${FILE}'; file info: '${FILE_SCRIPTS_}'; missing: '${COMPARE_REGEX_}'") - endif() - endforeach() + endif() endfunction() -checkScripts_("${FOUND_FILE_1}" "echo \"pre install foo\";echo \"post install foo\";echo \"pre uninstall foo\";echo \"post uninstall foo\";echo \"pre trans foo\";echo \"post trans foo\"") -checkScripts_("${FOUND_FILE_2}" "echo \"pre install\";echo \"post install\";echo \"pre uninstall\";echo \"post uninstall\";echo \"pre trans\";echo \"post trans\"") +if(RunCMake_SUBTEST_SUFFIX MATCHES "no_scripts.*") + checkScripts_("${FOUND_FILE_1}" "") + checkScripts_("${FOUND_FILE_2}" "") +else() + checkScripts_("${FOUND_FILE_1}" "echo \"pre install foo\";echo \"post install foo\";echo \"pre uninstall foo\";echo \"post uninstall foo\";echo \"pre trans foo\";echo \"post trans foo\"") + checkScripts_("${FOUND_FILE_2}" "echo \"pre install\";echo \"post install\";echo \"pre uninstall\";echo \"post uninstall\";echo \"pre trans\";echo \"post trans\"") +endif() diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake index 6877c577449..ce5db0cfe83 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake @@ -1,31 +1,5 @@ if(GENERATOR_TYPE STREQUAL "RPM") - set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh") - set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh") - set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh") - set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh") - set(CPACK_RPM_PRE_TRANS_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh") - set(CPACK_RPM_POST_TRANS_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh") - - set(CPACK_RPM_foo_PRE_INSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh") - set(CPACK_RPM_foo_POST_INSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh") - set(CPACK_RPM_foo_PRE_UNINSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh") - set(CPACK_RPM_foo_POST_UNINSTALL_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh") - set(CPACK_RPM_foo_PRE_TRANS_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh") - set(CPACK_RPM_foo_POST_TRANS_SCRIPT_FILE - "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh") - - if(RunCMake_SUBTEST_SUFFIX STREQUAL "single_debug_info") + if(RunCMake_SUBTEST_SUFFIX MATCHES ".*single_debug_info") set(CPACK_RPM_MAIN_COMPONENT "foo") set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON) set(CPACK_RPM_FOO_FILE_NAME "RPM-DEFAULT") @@ -34,33 +8,63 @@ endif() set(CMAKE_BUILD_WITH_INSTALL_RPATH 1) -# default -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh" - "echo \"pre install\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh" - "echo \"post install\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh" - "echo \"pre uninstall\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh" - "echo \"post uninstall\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh" - "echo \"pre trans\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh" - "echo \"post trans\"\n") +if(NOT RunCMake_SUBTEST_SUFFIX MATCHES "no_scripts.*") + if(GENERATOR_TYPE STREQUAL "RPM") + set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh") + set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh") + set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh") + set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh") + set(CPACK_RPM_PRE_TRANS_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh") + set(CPACK_RPM_POST_TRANS_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh") + + set(CPACK_RPM_foo_PRE_INSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh") + set(CPACK_RPM_foo_POST_INSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh") + set(CPACK_RPM_foo_PRE_UNINSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh") + set(CPACK_RPM_foo_POST_UNINSTALL_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh") + set(CPACK_RPM_foo_PRE_TRANS_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh") + set(CPACK_RPM_foo_POST_TRANS_SCRIPT_FILE + "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh") + endif() + + # default + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh" + "echo \"pre install\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install.sh" + "echo \"post install\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall.sh" + "echo \"pre uninstall\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall.sh" + "echo \"post uninstall\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans.sh" + "echo \"pre trans\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans.sh" + "echo \"post trans\"\n") -# specific -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh" - "echo \"pre install foo\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh" - "echo \"post install foo\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh" - "echo \"pre uninstall foo\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh" - "echo \"post uninstall foo\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh" - "echo \"pre trans foo\"\n") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh" - "echo \"post trans foo\"\n") + # specific + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_install_foo.sh" + "echo \"pre install foo\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_install_foo.sh" + "echo \"post install foo\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_uninstall_foo.sh" + "echo \"pre uninstall foo\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_uninstall_foo.sh" + "echo \"post uninstall foo\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pre_trans_foo.sh" + "echo \"pre trans foo\"\n") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/post_trans_foo.sh" + "echo \"post trans foo\"\n") +endif() install(FILES CMakeLists.txt DESTINATION foo COMPONENT foo) install(FILES CMakeLists.txt DESTINATION bar COMPONENT bar) From ce1cadd35a26bd44879675581d8e70b00ff8e0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= Date: Thu, 1 Apr 2021 20:14:06 +0700 Subject: [PATCH 0202/1519] Tests/ConfigSources: fix for non main stream CMAKE_BUILD_TYPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - None is a valid CMAKE_BUILD_TYPE - Most of distros uses None as CMAKE_BUILD_TYPE - When CMAKE_BUILD_TYPE=None, main_other.cpp will be compiled and linked into final executable, this program requires some symbols only exist when CUSTOM_CFG_OTHER is defined. - And CMake also allows other CMAKE_BUILD_TYPE, too, CMake documentation specificaly mentions funny CMAKE_BUILD_TYPE like ReLeAsE [1] Let's define them when non main stream like None is specified as CMAKE_BUILD_TYPE. [1]: https://cmake.org/cmake/help/v3.20/variable/CMAKE_BUILD_TYPE.html --- Tests/ConfigSources/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt index a3d98f685fa..f83759ca10a 100644 --- a/Tests/ConfigSources/CMakeLists.txt +++ b/Tests/ConfigSources/CMakeLists.txt @@ -74,10 +74,10 @@ add_custom_command(APPEND VERBATIM ) foreach(n RANGE 1 5) - set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG) - foreach(other Release RelWithDebInfo MinSizeRel) + foreach(other ${CMAKE_BUILD_TYPE} Release RelWithDebInfo MinSizeRel) set_property(SOURCE custom${n}_${other}.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_OTHER) endforeach() + set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG) endforeach() add_library(Custom STATIC custom1_$.cpp From 55843b899ed1ef52e3c4746ae98c3c4a396760c1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 2 Apr 2021 00:01:22 -0400 Subject: [PATCH 0203/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9893e4bf322..e1d460f3100 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210401) +set(CMake_VERSION_PATCH 20210402) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d904b74c9e6b5d1eb0053d87463eed0afc198fc1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 3 Apr 2021 00:01:54 -0400 Subject: [PATCH 0204/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e1d460f3100..feee9c982ff 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210402) +set(CMake_VERSION_PATCH 20210403) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 20e90c08e3b1fa60b69442d384bcc236ff6f8a21 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 4 Apr 2021 00:01:11 -0400 Subject: [PATCH 0205/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index feee9c982ff..84568e0705a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210403) +set(CMake_VERSION_PATCH 20210404) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f6c47dd0b415f1542472ae785b52d05afa444f2a Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sun, 4 Apr 2021 10:57:14 +0100 Subject: [PATCH 0206/1519] Help: Fix a typo in the AUTOGEN_SOURCE_GROUP help --- Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst index 2e3232062ad..f9c5f48c81e 100644 --- a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst +++ b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst @@ -9,7 +9,7 @@ Name of the :command:`source_group` for :prop_tgt:`AUTOMOC` and Files generated by :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` are not always known at configure time and therefore can't be passed to :command:`source_group`. -:prop_gbl:`AUTOGEN_SOURCE_GROUP` an be used instead to generate or select +:prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used instead to generate or select a source group for :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` generated files. For :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` specific overrides see From 7f0151dc91805617cbc1d538ec9df2b34e0477d6 Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sun, 4 Apr 2021 10:59:50 +0100 Subject: [PATCH 0207/1519] Help: Document the AUTOUIC_SOURCE_GROUP property This property came into existence with the changes in b4a103bdecc437d37580d0ab540f6014006d661c because generated files are now being added for UIC. --- Auxiliary/vim/syntax/cmake.vim | 1 + Help/manual/cmake-properties.7.rst | 1 + Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst | 19 ++++++++++--------- Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst | 9 +++++++++ Help/prop_sf/GENERATED.rst | 7 ++++--- 5 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 955beaea177..067f80d2d9f 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -92,6 +92,7 @@ syn keyword cmakeProperty contained \ AUTOUIC_EXECUTABLE \ AUTOUIC_OPTIONS \ AUTOUIC_SEARCH_PATHS + \ AUTOUIC_SOURCE_GROUP \ BINARY_DIR \ BUILDSYSTEM_TARGETS \ BUILD_RPATH diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index af170dabdea..60a402895fb 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -21,6 +21,7 @@ Properties of Global Scope /prop_gbl/AUTOMOC_SOURCE_GROUP /prop_gbl/AUTOMOC_TARGETS_FOLDER /prop_gbl/AUTORCC_SOURCE_GROUP + /prop_gbl/AUTOUIC_SOURCE_GROUP /prop_gbl/CMAKE_C_KNOWN_FEATURES /prop_gbl/CMAKE_CUDA_KNOWN_FEATURES /prop_gbl/CMAKE_CXX_KNOWN_FEATURES diff --git a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst index f9c5f48c81e..07c732bd471 100644 --- a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst +++ b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst @@ -3,15 +3,16 @@ AUTOGEN_SOURCE_GROUP .. versionadded:: 3.9 -Name of the :command:`source_group` for :prop_tgt:`AUTOMOC` and -:prop_tgt:`AUTORCC` generated files. +Name of the :command:`source_group` for :prop_tgt:`AUTOMOC`, +:prop_tgt:`AUTORCC` and :prop_tgt:`AUTOUIC` generated files. -Files generated by :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` are not always -known at configure time and therefore can't be passed to -:command:`source_group`. +Files generated by :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTORCC` and +:prop_tgt:`AUTOUIC` are not always known at configure time and therefore can't +be passed to :command:`source_group`. :prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used instead to generate or select -a source group for :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` generated files. +a source group for :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTORCC` and +:prop_tgt:`AUTOUIC` generated files. -For :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` specific overrides see -:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP` -respectively. +For :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTORCC` and :prop_tgt:`AUTOUIC` specific +overrides see :prop_gbl:`AUTOMOC_SOURCE_GROUP`, :prop_gbl:`AUTORCC_SOURCE_GROUP` +and :prop_gbl:`AUTOUIC_SOURCE_GROUP` respectively. diff --git a/Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst new file mode 100644 index 00000000000..79ebfe0eccc --- /dev/null +++ b/Help/prop_gbl/AUTOUIC_SOURCE_GROUP.rst @@ -0,0 +1,9 @@ +AUTOUIC_SOURCE_GROUP +-------------------- + +.. versionadded:: 3.21 + +Name of the :command:`source_group` for :prop_tgt:`AUTOUIC` generated files. + +When set this is used instead of :prop_gbl:`AUTOGEN_SOURCE_GROUP` for +files generated by :prop_tgt:`AUTOUIC`. diff --git a/Help/prop_sf/GENERATED.rst b/Help/prop_sf/GENERATED.rst index 6ef45802268..216dfe8da33 100644 --- a/Help/prop_sf/GENERATED.rst +++ b/Help/prop_sf/GENERATED.rst @@ -32,9 +32,10 @@ The :ref:`Makefile Generators` will remove ``GENERATED`` files during ``make clean``. Generated sources may be hidden in some IDE tools, while in others they might -be shown. For the special case of sources generated by CMake's :prop_tgt:`AUTOMOC` -or :prop_tgt:`AUTORCC` functionality, the :prop_gbl:`AUTOGEN_SOURCE_GROUP`, -:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP` target +be shown. For the special case of sources generated by CMake's :prop_tgt:`AUTOMOC`, +:prop_tgt:`AUTORCC` or :prop_tgt:`AUTOUIC` functionality, the +:prop_gbl:`AUTOGEN_SOURCE_GROUP`, :prop_gbl:`AUTOMOC_SOURCE_GROUP`, +:prop_gbl:`AUTORCC_SOURCE_GROUP` and :prop_gbl:`AUTOUIC_SOURCE_GROUP` target properties may influence where the generated sources are grouped in the project's file lists. From e8ddc1e268d2db78a2f3edde1f6edb05d9243ada Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sun, 4 Apr 2021 12:21:59 +0100 Subject: [PATCH 0208/1519] Autogen: Fix a bug in setting the UIC source group If the relative path to a UI file was empty then the source group for the corresponding autogen header file would not apply because of a double slash in the path. --- Source/cmQtAutoGenInitializer.cxx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 65286879ece..e96ec63f624 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -943,8 +943,14 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->LocalGen->GetCurrentSourceDirectory(), cmSystemTools::GetFilenamePath(fullPath)); + // Avoid creating a path containing adjacent slashes + if (!uiHeaderRelativePath.empty() && + uiHeaderRelativePath.back() != '/') { + uiHeaderRelativePath += '/'; + } + auto uiHeaderFilePath = cmStrCat( - '/', uiHeaderRelativePath, '/', "ui_"_s, + '/', uiHeaderRelativePath, "ui_"_s, cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); ConfigString uiHeader; From 3d700254f4c4b7e4dde61ea16991964d221185ad Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 5 Apr 2021 00:01:24 -0400 Subject: [PATCH 0209/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 84568e0705a..ef5f2e418a4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210404) +set(CMake_VERSION_PATCH 20210405) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f6b4db365a5e5723029c06357e81aa6c93ba1f76 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Sun, 4 Apr 2021 22:57:58 +0200 Subject: [PATCH 0210/1519] Tests: bump cmake_minimum_required version to 2.8.12 This needlessly produces warnings during the test runs that no-one sees but that are distracting when actually inspecting the logs. --- Tests/BundleGeneratorTest/CMakeLists.txt | 2 +- Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt | 2 +- Tests/CMakeOnly/CheckLanguage/CMakeLists.txt | 2 +- Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt | 2 +- Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt | 2 +- Tests/CMakeOnly/TargetScope/CMakeLists.txt | 2 +- Tests/CPackComponents/CMakeLists.txt | 2 +- Tests/CTestTest2/test.cmake.in | 2 +- Tests/CTestTestBadExe/test.cmake.in | 2 +- Tests/CTestTestChecksum/test.cmake.in | 2 +- Tests/CTestTestCostSerial/test.cmake.in | 2 +- Tests/CTestTestCrash/CMakeLists.txt | 2 +- Tests/CTestTestCrash/test.cmake.in | 2 +- Tests/CTestTestCycle/CMakeLists.txt | 2 +- Tests/CTestTestCycle/test.cmake.in | 2 +- Tests/CTestTestDepends/CMakeLists.txt | 2 +- Tests/CTestTestDepends/test.cmake.in | 2 +- Tests/CTestTestFailure/CMakeLists.txt | 2 +- Tests/CTestTestFailure/testNoBuild.cmake.in | 2 +- Tests/CTestTestFailure/testNoExe.cmake.in | 2 +- Tests/CTestTestParallel/CMakeLists.txt | 2 +- Tests/CTestTestParallel/test.cmake.in | 2 +- Tests/CTestTestResourceLock/CMakeLists.txt | 2 +- Tests/CTestTestResourceLock/test.cmake.in | 2 +- Tests/CTestTestScheduler/CMakeLists.txt | 2 +- Tests/CTestTestScheduler/test.cmake.in | 2 +- Tests/CTestTestSkipReturnCode/test.cmake.in | 2 +- Tests/CTestTestStopTime/CMakeLists.txt | 2 +- Tests/CTestTestStopTime/test.cmake.in | 2 +- Tests/CTestTestSubdir/CMakeLists.txt | 2 +- Tests/CTestTestSubdir/test.cmake.in | 2 +- Tests/CTestTestTimeout/test.cmake.in | 2 +- Tests/CTestTestUpload/CMakeLists.txt | 2 +- Tests/CTestTestUpload/test.cmake.in | 2 +- Tests/CTestTestVerboseOutput/CMakeLists.txt | 2 +- Tests/CTestTestVerboseOutput/test.cmake.in | 2 +- Tests/CTestTestZeroTimeout/CMakeLists.txt | 2 +- Tests/CTestTestZeroTimeout/test.cmake.in | 2 +- Tests/CustomCommand/CMakeLists.txt | 2 +- Tests/CustomCommandWorkingDirectory/CMakeLists.txt | 2 +- Tests/Dependency/CMakeLists.txt | 2 +- Tests/Framework/CMakeLists.txt | 2 +- Tests/FunctionTest/CMakeLists.txt | 2 +- Tests/JCTest/CMakeLists.txt | 2 +- Tests/Java/CMakeLists.txt | 2 +- Tests/JavaJavah/CMakeLists.txt | 2 +- Tests/JavaNativeHeaders/CMakeLists.txt | 2 +- Tests/LoadCommand/CMakeCommands/CMakeLists.txt | 2 +- Tests/LoadCommand/CMakeLists.txt | 2 +- Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt | 2 +- Tests/LoadCommandOneConfig/CMakeLists.txt | 2 +- Tests/MakeClean/CMakeLists.txt | 2 +- Tests/ModuleDefinition/CMakeLists.txt | 2 +- Tests/NewlineArgs/CMakeLists.txt | 2 +- Tests/Plugin/CMakeLists.txt | 4 ++-- Tests/Preprocess/CMakeLists.txt | 2 +- Tests/ReturnTest/CMakeLists.txt | 2 +- Tests/StringFileTest/CMakeLists.txt | 2 +- Tests/SubDirSpaces/CMakeLists.txt | 2 +- Tests/TargetName/CMakeLists.txt | 2 +- Tests/TestDriver/CMakeLists.txt | 2 +- Tests/TestsWorkingDirectory/CMakeLists.txt | 2 +- Tests/TryCompile/CMakeLists.txt | 2 +- Tests/TryCompile/Inner/CMakeLists.txt | 2 +- Tests/VSExternalInclude/CMakeLists.txt | 2 +- 65 files changed, 66 insertions(+), 66 deletions(-) diff --git a/Tests/BundleGeneratorTest/CMakeLists.txt b/Tests/BundleGeneratorTest/CMakeLists.txt index 037df09c127..cf7e2ce864a 100644 --- a/Tests/BundleGeneratorTest/CMakeLists.txt +++ b/Tests/BundleGeneratorTest/CMakeLists.txt @@ -1,6 +1,6 @@ project(BundleGeneratorTest) -cmake_minimum_required(VERSION 2.7) +cmake_minimum_required(VERSION 2.8.12) # Build a shared library and install it in lib/ add_library(Library SHARED Library.cxx) diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt index 2028a135cfd..2784e3bc5d1 100644 --- a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt +++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt @@ -9,7 +9,7 @@ project(CheckCXXSymbolExists CXX) -cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../CheckSymbolExists") diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt index 1570c37896b..2e5d8d3b28d 100644 --- a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt +++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 2.8.12) project(CheckLanguage NONE) include(CheckLanguage) diff --git a/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt index 7f01463c06b..9a9bb2a3956 100644 --- a/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt +++ b/Tests/CMakeOnly/CheckSymbolExists/CMakeLists.txt @@ -9,7 +9,7 @@ project(CheckSymbolExists C) -cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt b/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt index 56e449afdd8..d66eb06d766 100644 --- a/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt +++ b/Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 2.8.12) project(LinkInterfaceLoop C) # Add a shared library that incorrectly names itself as a diff --git a/Tests/CMakeOnly/TargetScope/CMakeLists.txt b/Tests/CMakeOnly/TargetScope/CMakeLists.txt index fa5d8e23423..faf22509926 100644 --- a/Tests/CMakeOnly/TargetScope/CMakeLists.txt +++ b/Tests/CMakeOnly/TargetScope/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 2.8.12) project(TargetScope NONE) add_subdirectory(Sub) diff --git a/Tests/CPackComponents/CMakeLists.txt b/Tests/CPackComponents/CMakeLists.txt index 5b03c9e42cc..c1b348ef408 100644 --- a/Tests/CPackComponents/CMakeLists.txt +++ b/Tests/CPackComponents/CMakeLists.txt @@ -4,7 +4,7 @@ # application (mylibapp). We create a binary installer that allows # users to select which pieces will be installed: the example # application, the library binaries, and/or the header file. -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(CPackComponents) # Create the mylib library diff --git a/Tests/CTestTest2/test.cmake.in b/Tests/CTestTest2/test.cmake.in index a9bbc527d82..d5d4d2f39dd 100644 --- a/Tests/CTestTest2/test.cmake.in +++ b/Tests/CTestTest2/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestBadExe/test.cmake.in b/Tests/CTestTestBadExe/test.cmake.in index 43a85725b10..dd180f0fe73 100644 --- a/Tests/CTestTestBadExe/test.cmake.in +++ b/Tests/CTestTestBadExe/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestChecksum/test.cmake.in b/Tests/CTestTestChecksum/test.cmake.in index 2a435d20806..3bac0e00b09 100644 --- a/Tests/CTestTestChecksum/test.cmake.in +++ b/Tests/CTestTestChecksum/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestCostSerial/test.cmake.in b/Tests/CTestTestCostSerial/test.cmake.in index 9b32a468b24..1c46d4ca5a5 100644 --- a/Tests/CTestTestCostSerial/test.cmake.in +++ b/Tests/CTestTestCostSerial/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestCrash/CMakeLists.txt b/Tests/CTestTestCrash/CMakeLists.txt index 77986df349b..663d2e45ca5 100644 --- a/Tests/CTestTestCrash/CMakeLists.txt +++ b/Tests/CTestTestCrash/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestCrash) include(CTest) diff --git a/Tests/CTestTestCrash/test.cmake.in b/Tests/CTestTestCrash/test.cmake.in index 3641cb01f4d..916d4e9fc22 100644 --- a/Tests/CTestTestCrash/test.cmake.in +++ b/Tests/CTestTestCrash/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestCycle/CMakeLists.txt b/Tests/CTestTestCycle/CMakeLists.txt index 6ba6b8c9530..19f4dd7d10b 100644 --- a/Tests/CTestTestCycle/CMakeLists.txt +++ b/Tests/CTestTestCycle/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestCycle) include(CTest) diff --git a/Tests/CTestTestCycle/test.cmake.in b/Tests/CTestTestCycle/test.cmake.in index 4a63dd612c8..507d46bc5f1 100644 --- a/Tests/CTestTestCycle/test.cmake.in +++ b/Tests/CTestTestCycle/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestDepends/CMakeLists.txt b/Tests/CTestTestDepends/CMakeLists.txt index 5cd6d666577..462ad8c7a89 100644 --- a/Tests/CTestTestDepends/CMakeLists.txt +++ b/Tests/CTestTestDepends/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestDepends) include(CTest) diff --git a/Tests/CTestTestDepends/test.cmake.in b/Tests/CTestTestDepends/test.cmake.in index 74fddb3d3ca..11bc92a2501 100644 --- a/Tests/CTestTestDepends/test.cmake.in +++ b/Tests/CTestTestDepends/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestFailure/CMakeLists.txt b/Tests/CTestTestFailure/CMakeLists.txt index 01fbb2c4f3a..db14b3d9248 100644 --- a/Tests/CTestTestFailure/CMakeLists.txt +++ b/Tests/CTestTestFailure/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestFailure) include(CTest) diff --git a/Tests/CTestTestFailure/testNoBuild.cmake.in b/Tests/CTestTestFailure/testNoBuild.cmake.in index 86333af4a1d..47d254f5678 100644 --- a/Tests/CTestTestFailure/testNoBuild.cmake.in +++ b/Tests/CTestTestFailure/testNoBuild.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestFailure/testNoExe.cmake.in b/Tests/CTestTestFailure/testNoExe.cmake.in index 8875cee3614..8496c80e1a1 100644 --- a/Tests/CTestTestFailure/testNoExe.cmake.in +++ b/Tests/CTestTestFailure/testNoExe.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestParallel/CMakeLists.txt b/Tests/CTestTestParallel/CMakeLists.txt index e47085a09bf..819fee4ebe2 100644 --- a/Tests/CTestTestParallel/CMakeLists.txt +++ b/Tests/CTestTestParallel/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestParallel) include(CTest) diff --git a/Tests/CTestTestParallel/test.cmake.in b/Tests/CTestTestParallel/test.cmake.in index 045a4ca06c8..517db726ec6 100644 --- a/Tests/CTestTestParallel/test.cmake.in +++ b/Tests/CTestTestParallel/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestResourceLock/CMakeLists.txt b/Tests/CTestTestResourceLock/CMakeLists.txt index 4001643fdf1..4bc4366c3a5 100644 --- a/Tests/CTestTestResourceLock/CMakeLists.txt +++ b/Tests/CTestTestResourceLock/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestResourceLock) include(CTest) diff --git a/Tests/CTestTestResourceLock/test.cmake.in b/Tests/CTestTestResourceLock/test.cmake.in index 67dde18032b..826226de0b5 100644 --- a/Tests/CTestTestResourceLock/test.cmake.in +++ b/Tests/CTestTestResourceLock/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestScheduler/CMakeLists.txt b/Tests/CTestTestScheduler/CMakeLists.txt index ccd7b2cbb0a..a3f0f27cdcb 100644 --- a/Tests/CTestTestScheduler/CMakeLists.txt +++ b/Tests/CTestTestScheduler/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project (CTestTestScheduler) include (CTest) diff --git a/Tests/CTestTestScheduler/test.cmake.in b/Tests/CTestTestScheduler/test.cmake.in index f8c8ab74758..5dcfb635ad0 100644 --- a/Tests/CTestTestScheduler/test.cmake.in +++ b/Tests/CTestTestScheduler/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestSkipReturnCode/test.cmake.in b/Tests/CTestTestSkipReturnCode/test.cmake.in index 112b0cd0fd0..2988d2fe95e 100644 --- a/Tests/CTestTestSkipReturnCode/test.cmake.in +++ b/Tests/CTestTestSkipReturnCode/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestStopTime/CMakeLists.txt b/Tests/CTestTestStopTime/CMakeLists.txt index bd8bebdda94..08116e25b9f 100644 --- a/Tests/CTestTestStopTime/CMakeLists.txt +++ b/Tests/CTestTestStopTime/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestStopTime) include(CTest) diff --git a/Tests/CTestTestStopTime/test.cmake.in b/Tests/CTestTestStopTime/test.cmake.in index d3a9a4a920f..3797d40eda9 100644 --- a/Tests/CTestTestStopTime/test.cmake.in +++ b/Tests/CTestTestStopTime/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestSubdir/CMakeLists.txt b/Tests/CTestTestSubdir/CMakeLists.txt index b7cc7e2f154..87c4604d8ad 100644 --- a/Tests/CTestTestSubdir/CMakeLists.txt +++ b/Tests/CTestTestSubdir/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestSubdir) include(CTest) diff --git a/Tests/CTestTestSubdir/test.cmake.in b/Tests/CTestTestSubdir/test.cmake.in index 8b3957b4e16..3b1fb5fc86f 100644 --- a/Tests/CTestTestSubdir/test.cmake.in +++ b/Tests/CTestTestSubdir/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestTimeout/test.cmake.in b/Tests/CTestTestTimeout/test.cmake.in index 4b5157ef094..ce9c4979f0d 100644 --- a/Tests/CTestTestTimeout/test.cmake.in +++ b/Tests/CTestTestTimeout/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestUpload/CMakeLists.txt b/Tests/CTestTestUpload/CMakeLists.txt index 90d811cd94c..5e02b2f4ac5 100644 --- a/Tests/CTestTestUpload/CMakeLists.txt +++ b/Tests/CTestTestUpload/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestUpload) add_executable (Sleep sleep.c) diff --git a/Tests/CTestTestUpload/test.cmake.in b/Tests/CTestTestUpload/test.cmake.in index 701439d3717..74fd1ecdf4d 100644 --- a/Tests/CTestTestUpload/test.cmake.in +++ b/Tests/CTestTestUpload/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestVerboseOutput/CMakeLists.txt b/Tests/CTestTestVerboseOutput/CMakeLists.txt index 4cdd29c689f..37923858424 100644 --- a/Tests/CTestTestVerboseOutput/CMakeLists.txt +++ b/Tests/CTestTestVerboseOutput/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CTestTestVerboseOutput) include(CTest) diff --git a/Tests/CTestTestVerboseOutput/test.cmake.in b/Tests/CTestTestVerboseOutput/test.cmake.in index 7f49548419d..9c9a4dca835 100644 --- a/Tests/CTestTestVerboseOutput/test.cmake.in +++ b/Tests/CTestTestVerboseOutput/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CTestTestZeroTimeout/CMakeLists.txt b/Tests/CTestTestZeroTimeout/CMakeLists.txt index 4d2b79dc2f2..2d404c8cbda 100644 --- a/Tests/CTestTestZeroTimeout/CMakeLists.txt +++ b/Tests/CTestTestZeroTimeout/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project (CTestTestZeroTimeout) include (CTest) diff --git a/Tests/CTestTestZeroTimeout/test.cmake.in b/Tests/CTestTestZeroTimeout/test.cmake.in index b829fefe27e..50dbba03ff6 100644 --- a/Tests/CTestTestZeroTimeout/test.cmake.in +++ b/Tests/CTestTestZeroTimeout/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.8.12) # Settings: set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index 80545c483ad..11d005f78e8 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -1,7 +1,7 @@ # # Wrapping # -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project (CustomCommand) add_subdirectory(GeneratedHeader) diff --git a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt index 3bab1fec0fa..7697a9b727d 100644 --- a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt +++ b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(TestWorkingDir) add_custom_command( diff --git a/Tests/Dependency/CMakeLists.txt b/Tests/Dependency/CMakeLists.txt index ebc2d1066ff..58d3fb7c51f 100644 --- a/Tests/Dependency/CMakeLists.txt +++ b/Tests/Dependency/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project( Dependency ) # to test directories with only one character One was changed to 1 diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt index 6e82f868b31..287be949d75 100644 --- a/Tests/Framework/CMakeLists.txt +++ b/Tests/Framework/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(Framework) add_library(foo SHARED diff --git a/Tests/FunctionTest/CMakeLists.txt b/Tests/FunctionTest/CMakeLists.txt index 68da972c652..64504470d42 100644 --- a/Tests/FunctionTest/CMakeLists.txt +++ b/Tests/FunctionTest/CMakeLists.txt @@ -1,5 +1,5 @@ # a simple C only test case -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project (FunctionTest) function(FAILED testname) diff --git a/Tests/JCTest/CMakeLists.txt b/Tests/JCTest/CMakeLists.txt index 31dcc3abfad..b1206408d28 100644 --- a/Tests/JCTest/CMakeLists.txt +++ b/Tests/JCTest/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(TestTime) enable_testing() add_executable(TestTime TestTime.cxx) diff --git a/Tests/Java/CMakeLists.txt b/Tests/Java/CMakeLists.txt index aea4282e700..e4f28211c6c 100644 --- a/Tests/Java/CMakeLists.txt +++ b/Tests/Java/CMakeLists.txt @@ -1,6 +1,6 @@ project(hello Java) -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) set(CMAKE_VERBOSE_MAKEFILE 1) include(CTest) diff --git a/Tests/JavaJavah/CMakeLists.txt b/Tests/JavaJavah/CMakeLists.txt index 77c292a32c5..b56cc216ee7 100644 --- a/Tests/JavaJavah/CMakeLists.txt +++ b/Tests/JavaJavah/CMakeLists.txt @@ -1,6 +1,6 @@ project(helloJavah Java CXX) -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) set(CMAKE_VERBOSE_MAKEFILE 1) include(CTest) diff --git a/Tests/JavaNativeHeaders/CMakeLists.txt b/Tests/JavaNativeHeaders/CMakeLists.txt index f3cc89d68a0..2471e013fd7 100644 --- a/Tests/JavaNativeHeaders/CMakeLists.txt +++ b/Tests/JavaNativeHeaders/CMakeLists.txt @@ -1,6 +1,6 @@ project(helloJavaNativeHeaders Java CXX) -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) set(CMAKE_VERBOSE_MAKEFILE 1) include (CTest) diff --git a/Tests/LoadCommand/CMakeCommands/CMakeLists.txt b/Tests/LoadCommand/CMakeCommands/CMakeLists.txt index 99b1aba82a4..cafa99b90b6 100644 --- a/Tests/LoadCommand/CMakeCommands/CMakeLists.txt +++ b/Tests/LoadCommand/CMakeCommands/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CMAKE_LOADED_COMMANDS) if (MUDSLIDE_TYPE MATCHES MUCHO) diff --git a/Tests/LoadCommand/CMakeLists.txt b/Tests/LoadCommand/CMakeLists.txt index cfaebade47c..e1c4998c69a 100644 --- a/Tests/LoadCommand/CMakeLists.txt +++ b/Tests/LoadCommand/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(LoadCommand) # set a definition diff --git a/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt b/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt index 5ee2ed0f1eb..dc029a4f7db 100644 --- a/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt +++ b/Tests/LoadCommandOneConfig/CMakeCommands/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(CMAKE_LOADED_COMMANDS) if (MUDSLIDE_TYPE MATCHES MUCHO) diff --git a/Tests/LoadCommandOneConfig/CMakeLists.txt b/Tests/LoadCommandOneConfig/CMakeLists.txt index 65de04230bb..fef4bb777a4 100644 --- a/Tests/LoadCommandOneConfig/CMakeLists.txt +++ b/Tests/LoadCommandOneConfig/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(LoadCommand) # set a definition diff --git a/Tests/MakeClean/CMakeLists.txt b/Tests/MakeClean/CMakeLists.txt index fbd499534a5..809d65bcc07 100644 --- a/Tests/MakeClean/CMakeLists.txt +++ b/Tests/MakeClean/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(MakeClean) # Build the to-clean project. diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt index e49ebea529c..567fb4b9f89 100644 --- a/Tests/ModuleDefinition/CMakeLists.txt +++ b/Tests/ModuleDefinition/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(ModuleDefinition C) # Test .def file source recognition for DLLs. diff --git a/Tests/NewlineArgs/CMakeLists.txt b/Tests/NewlineArgs/CMakeLists.txt index 7551601024e..3e4b436f5b6 100644 --- a/Tests/NewlineArgs/CMakeLists.txt +++ b/Tests/NewlineArgs/CMakeLists.txt @@ -1,5 +1,5 @@ # a simple CXX only test case -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project (NewlineArgs CXX) add_definitions("-DTEST_FLAG_1 diff --git a/Tests/Plugin/CMakeLists.txt b/Tests/Plugin/CMakeLists.txt index 729bba3478c..ec22bf43669 100644 --- a/Tests/Plugin/CMakeLists.txt +++ b/Tests/Plugin/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) cmake_policy(SET CMP0054 NEW) project(Plugin) @@ -46,7 +46,7 @@ target_link_libraries(example_mod_1 example_exe) if(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG AND "${CMAKE_C_CREATE_SHARED_MODULE}" MATCHES "SONAME_FLAG") # Verify that targets export with proper IMPORTED SONAME properties. - export(TARGETS example_mod_1 NAMESPACE exp_ + export(TARGETS example_mod_1 example_exe NAMESPACE exp_ FILE ${CMAKE_CURRENT_BINARY_DIR}/mods.cmake) include(ExternalProject) diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt index bf2af645c8a..4347459f13e 100644 --- a/Tests/Preprocess/CMakeLists.txt +++ b/Tests/Preprocess/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(Preprocess) # This test is meant both as a test and as a reference for supported diff --git a/Tests/ReturnTest/CMakeLists.txt b/Tests/ReturnTest/CMakeLists.txt index c4c606c58cd..78e3fc1ca45 100644 --- a/Tests/ReturnTest/CMakeLists.txt +++ b/Tests/ReturnTest/CMakeLists.txt @@ -1,5 +1,5 @@ # a simple C only test case -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project (ReturnTest) function (FAILED testname) diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt index faf3bc90b6d..068fae9947a 100644 --- a/Tests/StringFileTest/CMakeLists.txt +++ b/Tests/StringFileTest/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(StringFileTest) include_directories(${StringFileTest_BINARY_DIR}) diff --git a/Tests/SubDirSpaces/CMakeLists.txt b/Tests/SubDirSpaces/CMakeLists.txt index 0d45db85c5c..ecd4353b763 100644 --- a/Tests/SubDirSpaces/CMakeLists.txt +++ b/Tests/SubDirSpaces/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(SUBDIR) # Some systems do not seem to support rpath with spaces. diff --git a/Tests/TargetName/CMakeLists.txt b/Tests/TargetName/CMakeLists.txt index 9729d21ffdc..21752b7fd59 100644 --- a/Tests/TargetName/CMakeLists.txt +++ b/Tests/TargetName/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(TargetName) add_subdirectory(executables) diff --git a/Tests/TestDriver/CMakeLists.txt b/Tests/TestDriver/CMakeLists.txt index 663ecab551e..3cc69c03e32 100644 --- a/Tests/TestDriver/CMakeLists.txt +++ b/Tests/TestDriver/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(TestDriverTest) set(Extra_SRCS testExtraStuff.cxx testExtraStuff2.cxx ) diff --git a/Tests/TestsWorkingDirectory/CMakeLists.txt b/Tests/TestsWorkingDirectory/CMakeLists.txt index 6a6e9b6c7cf..2a0b015659b 100644 --- a/Tests/TestsWorkingDirectory/CMakeLists.txt +++ b/Tests/TestsWorkingDirectory/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(TestsWorkingDirectoryProj) add_executable(WorkingDirectory main.c) diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index 0c6b9382cc7..fa0549f1bff 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(TryCompile) macro(TEST_ASSERT value msg) diff --git a/Tests/TryCompile/Inner/CMakeLists.txt b/Tests/TryCompile/Inner/CMakeLists.txt index d62bcc4dd28..d8c22d00a54 100644 --- a/Tests/TryCompile/Inner/CMakeLists.txt +++ b/Tests/TryCompile/Inner/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.12) project(TryCompileInner C) try_compile(SHOULD_PASS diff --git a/Tests/VSExternalInclude/CMakeLists.txt b/Tests/VSExternalInclude/CMakeLists.txt index 8ca72524948..e38df8e81ac 100644 --- a/Tests/VSExternalInclude/CMakeLists.txt +++ b/Tests/VSExternalInclude/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 2.8.12) project(VSExternalInclude) if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") From 5160204fc2654c70f46dcfc025b1676f7326a5e1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 6 Apr 2021 00:01:30 -0400 Subject: [PATCH 0211/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ef5f2e418a4..b7ca022c628 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210405) +set(CMake_VERSION_PATCH 20210406) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3654068e80247f4f06a951d258f254da70aeef89 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 4 Apr 2021 08:04:22 -0400 Subject: [PATCH 0212/1519] FindHDF5: find include directories after the library Some include paths might depend on the library location (primarily for Fortran). --- Modules/FindHDF5.cmake | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index ec5ebdd66f4..7bacfac920f 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -811,26 +811,6 @@ if( NOT HDF5_FOUND ) endif() foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) - # find the HDF5 include directories - if("${_lang}" STREQUAL "Fortran") - set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod) - elseif("${_lang}" STREQUAL "CXX") - set(HDF5_INCLUDE_FILENAME H5Cpp.h) - else() - set(HDF5_INCLUDE_FILENAME hdf5.h) - endif() - - find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} - HINTS ${HDF5_ROOT} - PATHS $ENV{HOME}/.local/include - PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} - ${_HDF5_SEARCH_OPTS} - ) - mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR) - # set the _DIRS variable as this is what the user will normally use - set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) - list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) - # find the HDF5 libraries foreach(LIB IN LISTS HDF5_${_lang}_LIBRARY_NAMES) if(HDF5_USE_STATIC_LIBRARIES) @@ -872,6 +852,26 @@ if( NOT HDF5_FOUND ) # required libraries. list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES}) + # find the HDF5 include directories + if("${_lang}" STREQUAL "Fortran") + set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod) + elseif("${_lang}" STREQUAL "CXX") + set(HDF5_INCLUDE_FILENAME H5Cpp.h) + else() + set(HDF5_INCLUDE_FILENAME hdf5.h) + endif() + + find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} + HINTS ${HDF5_ROOT} + PATHS $ENV{HOME}/.local/include + PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} + ${_HDF5_SEARCH_OPTS} + ) + mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR) + # set the _DIRS variable as this is what the user will normally use + set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) + list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) + if(HDF5_FIND_HL) foreach(LIB IN LISTS HDF5_${_lang}_HL_LIBRARY_NAMES) if(HDF5_USE_STATIC_LIBRARIES) From 78287ec0af1eb5f968df09c8b4321dd56510a429 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 4 Apr 2021 08:09:23 -0400 Subject: [PATCH 0213/1519] FindHDF5: track the "main" library for each language This will be used to build up additional include paths to search. --- Modules/FindHDF5.cmake | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 7bacfac920f..7eec6de2164 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -811,6 +811,9 @@ if( NOT HDF5_FOUND ) endif() foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + # The "main" library. + set(_hdf5_main_library "") + # find the HDF5 libraries foreach(LIB IN LISTS HDF5_${_lang}_LIBRARY_NAMES) if(HDF5_USE_STATIC_LIBRARIES) @@ -841,6 +844,15 @@ if( NOT HDF5_FOUND ) ${_HDF5_SEARCH_OPTS} ) + # Set the "main" library if not already set. + if (NOT _hdf5_main_library) + if (HDF5_${LIB}_LIBRARY_RELEASE) + set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_RELEASE}") + elseif (HDF5_${LIB}_LIBRARY_DEBUG) + set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_DEBUG}") + endif () + endif () + select_library_configurations( HDF5_${LIB} ) list(APPEND HDF5_${_lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) endforeach() @@ -861,6 +873,8 @@ if( NOT HDF5_FOUND ) set(HDF5_INCLUDE_FILENAME hdf5.h) endif() + unset(_hdf5_main_library) + find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} HINTS ${HDF5_ROOT} PATHS $ENV{HOME}/.local/include From cd48433e96820c5e1d219696bb48174843e9c15b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 4 Apr 2021 08:09:48 -0400 Subject: [PATCH 0214/1519] FindHDF5: add compiler-specific module search paths --- Modules/FindHDF5.cmake | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 7eec6de2164..e33535513a3 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -865,8 +865,21 @@ if( NOT HDF5_FOUND ) list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES}) # find the HDF5 include directories + set(_hdf5_inc_extra_paths) + set(_hdf5_inc_extra_suffixes) if("${_lang}" STREQUAL "Fortran") set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod) + + # Add library-based search paths for Fortran modules. + if (NOT _hdf5_main_library STREQUAL "") + # gfortran module directory + if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + get_filename_component(_hdf5_library_dir "${_hdf5_main_library}" DIRECTORY) + list(APPEND _hdf5_inc_extra_paths "${_hdf5_library_dir}") + unset(_hdf5_library_dir) + list(APPEND _hdf5_inc_extra_suffixes gfortran/modules) + endif () + endif () elseif("${_lang}" STREQUAL "CXX") set(HDF5_INCLUDE_FILENAME H5Cpp.h) else() @@ -877,11 +890,13 @@ if( NOT HDF5_FOUND ) find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} HINTS ${HDF5_ROOT} - PATHS $ENV{HOME}/.local/include - PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} + PATHS $ENV{HOME}/.local/include ${_hdf5_inc_extra_paths} + PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} ${_hdf5_inc_extra_suffixes} ${_HDF5_SEARCH_OPTS} ) mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR) + unset(_hdf5_inc_extra_paths) + unset(_hdf5_inc_extra_suffixes) # set the _DIRS variable as this is what the user will normally use set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) From 1035848e9cfcc148f99c9b6008c419b58f067d8e Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 30 Mar 2021 14:55:51 -0400 Subject: [PATCH 0215/1519] ci: Enable FindDevIL tests on Linux builds --- .gitlab/ci/configure_debian10_aarch64_ninja.cmake | 1 + .gitlab/ci/configure_debian10_ninja.cmake | 1 + .gitlab/ci/configure_fedora33_makefiles.cmake | 1 + 3 files changed, 3 insertions(+) diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index 023cc9e8e11..1ad3ac4405c 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -5,6 +5,7 @@ set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") set(CMake_TEST_FindCups "ON" CACHE BOOL "") set(CMake_TEST_FindCURL "ON" CACHE BOOL "") +set(CMake_TEST_FindDevIL "ON" CACHE BOOL "") set(CMake_TEST_FindDoxygen_Dot "ON" CACHE BOOL "") set(CMake_TEST_FindDoxygen "ON" CACHE BOOL "") set(CMake_TEST_FindEXPAT "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index 74d9f12ef0f..d9253870e80 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -5,6 +5,7 @@ set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") set(CMake_TEST_FindCups "ON" CACHE BOOL "") set(CMake_TEST_FindCURL "ON" CACHE BOOL "") +set(CMake_TEST_FindDevIL "ON" CACHE BOOL "") set(CMake_TEST_FindDoxygen_Dot "ON" CACHE BOOL "") set(CMake_TEST_FindDoxygen "ON" CACHE BOOL "") set(CMake_TEST_FindEXPAT "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora33_makefiles.cmake b/.gitlab/ci/configure_fedora33_makefiles.cmake index db2d0059be0..882ffcdf947 100644 --- a/.gitlab/ci/configure_fedora33_makefiles.cmake +++ b/.gitlab/ci/configure_fedora33_makefiles.cmake @@ -5,6 +5,7 @@ set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") set(CMake_TEST_FindCups "ON" CACHE BOOL "") set(CMake_TEST_FindCURL "ON" CACHE BOOL "") +set(CMake_TEST_FindDevIL "ON" CACHE BOOL "") set(CMake_TEST_FindDoxygen_Dot "ON" CACHE BOOL "") set(CMake_TEST_FindDoxygen "ON" CACHE BOOL "") set(CMake_TEST_FindEXPAT "ON" CACHE BOOL "") From 80da23f2a2cb5b24d0f785384640198366173a25 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 6 Apr 2021 12:42:41 -0400 Subject: [PATCH 0216/1519] Tests: Add RunCTest helper option to control CTest verbose flag --- Tests/RunCMake/RunCTest.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/RunCMake/RunCTest.cmake b/Tests/RunCMake/RunCTest.cmake index 98fdf20ac90..59db395e1b0 100644 --- a/Tests/RunCMake/RunCTest.cmake +++ b/Tests/RunCMake/RunCTest.cmake @@ -11,10 +11,13 @@ function(run_ctest CASE_NAME) endif() configure_file(${RunCMake_SOURCE_DIR}/CMakeLists.txt.in ${RunCMake_BINARY_DIR}/${CASE_NAME}/CMakeLists.txt @ONLY) + if(NOT DEFINED RunCTest_VERBOSE_FLAG) + set(RunCTest_VERBOSE_FLAG "-V") + endif() run_cmake_command(${CASE_NAME} ${CMAKE_CTEST_COMMAND} -C Debug -S ${RunCMake_BINARY_DIR}/${CASE_NAME}/test.cmake - -V + ${RunCTest_VERBOSE_FLAG} --output-log ${RunCMake_BINARY_DIR}/${CASE_NAME}-build/testOutput.log --no-compress-output ${ARGN} From 82e40607a4b36d2ee8d3abec4dcd30a18b632ce9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 6 Apr 2021 12:43:44 -0400 Subject: [PATCH 0217/1519] ctest: Display test "WAITING" messages only in extra-verbose mode These messages are incidental scheduling output. Avoid cluttering the normal verbose output showing tests starting and finishing. --- Source/CTest/cmCTestMultiProcessHandler.cxx | 10 +++++----- .../CTestCommandLine/RunCMakeTest.cmake | 2 +- .../test-load-invalid-stdout.txt | 17 +++++++++++++++-- .../CTestCommandLine/test-load-pass-stdout.txt | 17 +++++++++++++++-- .../CTestCommandLine/test-load-wait-stdout.txt | 17 +++++++++++++++-- .../ctest_test/CTestTestLoadInvalid-stdout.txt | 9 ++++++++- .../ctest_test/CTestTestLoadPass-stdout.txt | 9 ++++++++- .../ctest_test/CTestTestLoadWait-stdout.txt | 9 ++++++++- Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 2 ++ .../ctest_test/TestLoadInvalid-stdout.txt | 9 ++++++++- .../ctest_test/TestLoadOrder-stdout.txt | 9 ++++++++- .../RunCMake/ctest_test/TestLoadPass-stdout.txt | 9 ++++++++- .../RunCMake/ctest_test/TestLoadWait-stdout.txt | 9 ++++++++- 13 files changed, 109 insertions(+), 19 deletions(-) diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 852f9d91d8e..86a8e00a626 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -587,24 +587,24 @@ void cmCTestMultiProcessHandler::StartNextTests() onlyRunSerialTestsLeft = false; } } - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, "); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "***** WAITING, "); if (this->SerialTestRunning) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Waiting for RUN_SERIAL test to finish."); } else if (onlyRunSerialTestsLeft) { - cmCTestLog(this->CTest, HANDLER_OUTPUT, + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Only RUN_SERIAL tests remain, awaiting available slot."); } else { /* clang-format off */ - cmCTestLog(this->CTest, HANDLER_OUTPUT, + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "System Load: " << systemLoad << ", " "Max Allowed Load: " << this->TestLoad << ", " "Smallest test " << testWithMinProcessors << " requires " << minProcessorsRequired); /* clang-format on */ } - cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "*****" << std::endl); // Wait between 1 and 5 seconds before trying again. unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000; diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index 6cf1476ca1e..2f4d731f067 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -202,7 +202,7 @@ function(run_TestLoad name load) add_test(TestLoad1 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\") add_test(TestLoad2 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\") ") - run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -j2 --test-load ${load}) + run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -VV -j2 --test-load ${load}) endfunction() # Tests for the --test-load feature of ctest diff --git a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt index 7ee3daee179..5101985f177 100644 --- a/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt +++ b/Tests/RunCMake/CTestCommandLine/test-load-invalid-stdout.txt @@ -1,7 +1,20 @@ -^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad +Test project [^ +]*/Tests/RunCMake/CTestCommandLine/TestLoad( +[^*][^ +]*)* +test 1 Start 1: TestLoad1 ++( +[^*][^ +]*)* +test 2 Start 2: TestLoad2 -1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec ++( +[^*][^ +]*)* +1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec( +[^*][^ +]*)* 2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 2 diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt index 7ee3daee179..5101985f177 100644 --- a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt +++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt @@ -1,7 +1,20 @@ -^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad +Test project [^ +]*/Tests/RunCMake/CTestCommandLine/TestLoad( +[^*][^ +]*)* +test 1 Start 1: TestLoad1 ++( +[^*][^ +]*)* +test 2 Start 2: TestLoad2 -1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec ++( +[^*][^ +]*)* +1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec( +[^*][^ +]*)* 2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 2 diff --git a/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt index 11a768a9c7d..db7d7f34bfe 100644 --- a/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt +++ b/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt @@ -1,8 +1,21 @@ -^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad +Test project [^ +]*/Tests/RunCMake/CTestCommandLine/TestLoad( +[^*][^ +]*)* \*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 3, Smallest test TestLoad[1-2] requires 1\*\*\*\*\* +test 1 Start 1: TestLoad1 ++( +[^*][^ +]*)* +test 2 Start 2: TestLoad2 -1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec ++( +[^*][^ +]*)* +1/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec( +[^*][^ +]*)* 2/2 Test #[1-2]: TestLoad[1-2] ........................ Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 2 diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt index b54220cff03..acda9e26e56 100644 --- a/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt +++ b/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-stdout.txt @@ -1,5 +1,12 @@ -Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-build +Test project [^ +]*/Tests/RunCMake/ctest_test/CTestTestLoadInvalid-build( +[^*][^ +]*)* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt index c221eed72c8..4081f987676 100644 --- a/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt +++ b/Tests/RunCMake/ctest_test/CTestTestLoadPass-stdout.txt @@ -1,5 +1,12 @@ -Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadPass-build +Test project [^ +]*/Tests/RunCMake/ctest_test/CTestTestLoadPass-build( +[^*][^ +]*)* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt index 2af3838ed00..2f4468f9ffb 100644 --- a/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt +++ b/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt @@ -1,6 +1,13 @@ -Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadWait-build +Test project [^ +]*/Tests/RunCMake/ctest_test/CTestTestLoadWait-build( +[^*][^ +]*)* \*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 4, Smallest test RunCMakeVersion requires 1\*\*\*\*\* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index b82335f1b3e..8cf6a61415c 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -18,6 +18,7 @@ run_ctest_test(TestQuiet QUIET) # # Spoof a load average value to make these tests more reliable. set(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING} 5) +set(RunCTest_VERBOSE_FLAG -VV) # Verify that new tests are started when the load average falls below # our threshold. @@ -53,6 +54,7 @@ run_ctest_test(TestLoadOrder TEST_LOAD "ERR4") unset(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING}) unset(CASE_CTEST_TEST_LOAD) +unset(RunCTest_VERBOSE_FLAG) function(run_TestChangeId) set(CASE_TEST_PREFIX_CODE [[ diff --git a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt index c4fd35b4aab..8d21f916ed7 100644 --- a/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt +++ b/Tests/RunCMake/ctest_test/TestLoadInvalid-stdout.txt @@ -1,5 +1,12 @@ -Test project .*/Tests/RunCMake/ctest_test/TestLoadInvalid-build +Test project [^ +]*/Tests/RunCMake/ctest_test/TestLoadInvalid-build( +[^*][^ +]*)* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 diff --git a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt index 22da0921191..1ef5f5acc56 100644 --- a/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt +++ b/Tests/RunCMake/ctest_test/TestLoadOrder-stdout.txt @@ -1,5 +1,12 @@ -Test project .*/Tests/RunCMake/ctest_test/TestLoadOrder-build +Test project [^ +]*/Tests/RunCMake/ctest_test/TestLoadOrder-build( +[^*][^ +]*)* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 diff --git a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt index e5048f4b439..f3e7cd1efd1 100644 --- a/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt +++ b/Tests/RunCMake/ctest_test/TestLoadPass-stdout.txt @@ -1,5 +1,12 @@ -Test project .*/Tests/RunCMake/ctest_test/TestLoadPass-build +Test project [^ +]*/Tests/RunCMake/ctest_test/TestLoadPass-build( +[^*][^ +]*)* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 diff --git a/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt index 07f4ed36145..fc329586ac8 100644 --- a/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt +++ b/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt @@ -1,6 +1,13 @@ -Test project .*/Tests/RunCMake/ctest_test/TestLoadWait-build +Test project [^ +]*/Tests/RunCMake/ctest_test/TestLoadWait-build( +[^*][^ +]*)* \*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test RunCMakeVersion requires 1\*\*\*\*\* +test 1 Start 1: RunCMakeVersion ++( +[^*][^ +]*)* 1/1 Test #1: RunCMakeVersion .................. Passed +[0-9.]+ sec + 100% tests passed, 0 tests failed out of 1 From d6da6784bfdb59456942d11d476593906945adbb Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 6 Apr 2021 10:36:57 -0400 Subject: [PATCH 0218/1519] FindThreads: Reduce amount of false positive error logging When a CMake based project fails, users start looking at CMakeError.log and think that the FindThread output is the problem, but it is a false positive. Now FindThreads only logs to `CMakeError.log` when it fails to find a suitable flag, reducing the amount of false positives in `CMakeError.log`. Fixes #16540, Fixes #19344 --- Modules/FindThreads.cmake | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index 87e88bc3186..28dffc0aad7 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -119,7 +119,10 @@ macro(_check_pthreads_flag) ${CMAKE_BINARY_DIR} ${_threads_src} CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread - OUTPUT_VARIABLE OUTPUT) + OUTPUT_VARIABLE _cmake_check_pthreads_output) + + string(APPEND _cmake_find_threads_output "${_cmake_check_pthreads_output}") + unset(_cmake_check_pthreads_output) unset(_threads_src) if(THREADS_HAVE_PTHREAD_ARG) @@ -127,9 +130,6 @@ macro(_check_pthreads_flag) message(CHECK_PASS "yes") else() message(CHECK_FAIL "no") - file(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n") endif() endif() @@ -249,4 +249,10 @@ if(THREADS_FOUND AND NOT TARGET Threads::Threads) if(CMAKE_THREAD_LIBS_INIT) set_property(TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") endif() +elseif(NOT THREADS_FOUND AND _cmake_find_threads_output) + file(APPEND + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if compiler accepts -pthread failed with the following output:\n${_cmake_find_threads_output}\n\n") endif() + +unset(_cmake_find_threads_output) From 06e69813360560347434a5320f1a366ba004e033 Mon Sep 17 00:00:00 2001 From: friendlyanon Date: Fri, 26 Mar 2021 13:31:43 +0100 Subject: [PATCH 0219/1519] cmake-presets: Make generator and binaryDir fields optional In v3 of the presets, generator and buildDir can be omitted to fall back to regular cmake behavior when these values are not explicitly provided by the user. Fixes: #21987 --- Help/manual/cmake-presets.7.rst | 7 +++- Help/manual/presets/schema.json | 8 ++++ ...esets-optional-generator-and-binarydir.rst | 5 +++ Source/QtDialog/QCMake.cxx | 2 +- Source/cmCMakePresetsFile.cxx | 38 +++++++++++-------- Source/cmCMakePresetsFile.h | 8 ++-- Source/cmake.cxx | 9 +++-- .../CMakePresets/OptionalBinaryDirField.cmake | 3 ++ .../OptionalBinaryDirField.json.in | 9 +++++ .../CMakePresets/OptionalGeneratorField.cmake | 3 ++ .../OptionalGeneratorField.json.in | 9 +++++ .../RunCMake/CMakePresets/RunCMakeTest.cmake | 5 +++ 12 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst create mode 100644 Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake create mode 100644 Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in create mode 100644 Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake create mode 100644 Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 8543be388d8..3714004a5df 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -145,7 +145,9 @@ that may contain the following fields: 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``). + ``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 Visual Studio generators, unlike in the command line ``-G`` argument, you cannot include the platform name in the generator name. Use @@ -186,7 +188,8 @@ that may contain the following fields: 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``). + preset is ``hidden``). In version ``3`` or above, this field may be + omitted. ``installDir`` diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index 9261519d681..e0663626977 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -79,6 +79,14 @@ "type": "object", "description": "A configure preset object.", "properties": { + "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." + }, "installDir": { "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)." diff --git a/Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst b/Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst new file mode 100644 index 00000000000..79734896b9c --- /dev/null +++ b/Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst @@ -0,0 +1,5 @@ +cmake-presets-optional-generator-and-binarydir +---------------------------------------------- + +* :manual:`cmake-presets(7)` now support omitting the ``generator`` and + ``binaryDir`` fields. diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 7d037e34dbc..6796e25bb08 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -160,7 +160,7 @@ void QCMake::setPreset(const QString& name, bool setBinary) auto const& expandedPreset = this->CMakePresetsFile.ConfigurePresets[presetName].Expanded; if (expandedPreset) { - if (setBinary) { + if (setBinary && !expandedPreset->BinaryDir.empty()) { QString binaryDir = QString::fromLocal8Bit(expandedPreset->BinaryDir.data()); this->setBinaryDirectory(binaryDir); diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index d44dfb31c07..39cce9818b2 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -78,7 +78,7 @@ void InheritVector(std::vector& child, const std::vector& parent) template ReadFileResult VisitPreset( T& preset, std::map>& presets, - std::map cycleStatus) + std::map cycleStatus, int version) { switch (cycleStatus[preset.Name]) { case CycleStatus::InProgress: @@ -108,7 +108,7 @@ ReadFileResult VisitPreset( return ReadFileResult::USER_PRESET_INHERITANCE; } - auto result = VisitPreset(parentPreset, presets, cycleStatus); + auto result = VisitPreset(parentPreset, presets, cycleStatus, version); if (result != ReadFileResult::READ_OK) { return result; } @@ -128,7 +128,7 @@ ReadFileResult VisitPreset( preset.ConditionEvaluator.reset(); } - CHECK_OK(preset.VisitPresetAfterInherit()) + CHECK_OK(preset.VisitPresetAfterInherit(version)) cycleStatus[preset.Name] = CycleStatus::Verified; return ReadFileResult::READ_OK; @@ -136,7 +136,8 @@ ReadFileResult VisitPreset( template ReadFileResult ComputePresetInheritance( - std::map>& presets) + std::map>& presets, + const cmCMakePresetsFile& file) { std::map cycleStatus; for (auto const& it : presets) { @@ -144,7 +145,9 @@ ReadFileResult ComputePresetInheritance( } for (auto& it : presets) { - auto result = VisitPreset(it.second.Unexpanded, presets, cycleStatus); + auto& preset = it.second.Unexpanded; + auto result = + VisitPreset(preset, presets, cycleStatus, file.GetVersion(preset)); if (result != ReadFileResult::READ_OK) { return result; } @@ -667,16 +670,19 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit() } cmCMakePresetsFile::ReadFileResult -cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit() +cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit(int version) { auto& preset = *this; if (!preset.Hidden) { - if (preset.Generator.empty()) { - return ReadFileResult::INVALID_PRESET; - } - if (preset.BinaryDir.empty()) { - return ReadFileResult::INVALID_PRESET; + if (version < 3) { + if (preset.Generator.empty()) { + return ReadFileResult::INVALID_PRESET; + } + if (preset.BinaryDir.empty()) { + return ReadFileResult::INVALID_PRESET; + } } + if (preset.WarnDev == false && preset.ErrorDev == true) { return ReadFileResult::INVALID_PRESET; } @@ -712,7 +718,7 @@ cmCMakePresetsFile::BuildPreset::VisitPresetInherit( } cmCMakePresetsFile::ReadFileResult -cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit() +cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit(int /* version */) { auto& preset = *this; if (!preset.Hidden && preset.ConfigurePreset.empty()) { @@ -822,7 +828,7 @@ cmCMakePresetsFile::TestPreset::VisitPresetInherit( } cmCMakePresetsFile::ReadFileResult -cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit() +cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit(int /* version */) { auto& preset = *this; if (!preset.Hidden && preset.ConfigurePreset.empty()) { @@ -883,9 +889,9 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles) : ReadFileResult::FILE_NOT_FOUND; } - CHECK_OK(ComputePresetInheritance(this->ConfigurePresets)) - CHECK_OK(ComputePresetInheritance(this->BuildPresets)) - CHECK_OK(ComputePresetInheritance(this->TestPresets)) + CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this)) + CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this)) + CHECK_OK(ComputePresetInheritance(this->TestPresets, *this)) for (auto& it : this->ConfigurePresets) { if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) { diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index 0999d5a1a59..fc14830f48c 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -89,7 +89,7 @@ class cmCMakePresetsFile return ReadFileResult::READ_OK; } - virtual ReadFileResult VisitPresetAfterInherit() + virtual ReadFileResult VisitPresetAfterInherit(int /* version */) { return ReadFileResult::READ_OK; } @@ -132,7 +132,7 @@ class cmCMakePresetsFile ReadFileResult VisitPresetInherit(const Preset& parent) override; ReadFileResult VisitPresetBeforeInherit() override; - ReadFileResult VisitPresetAfterInherit() override; + ReadFileResult VisitPresetAfterInherit(int version) override; }; class BuildPreset : public Preset @@ -158,7 +158,7 @@ class cmCMakePresetsFile std::vector NativeToolOptions; ReadFileResult VisitPresetInherit(const Preset& parent) override; - ReadFileResult VisitPresetAfterInherit() override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; }; class TestPreset : public Preset @@ -285,7 +285,7 @@ class cmCMakePresetsFile cm::optional Execution; ReadFileResult VisitPresetInherit(const Preset& parent) override; - ReadFileResult VisitPresetAfterInherit() override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; }; template diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a04338fec8a..1d4bbf4e7fa 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1223,10 +1223,11 @@ void cmake::SetArgs(const std::vector& args) return; } - if (!this->State->IsCacheLoaded() && !haveBArg) { + if (!this->State->IsCacheLoaded() && !haveBArg && + !expandedPreset->BinaryDir.empty()) { this->SetHomeOutputDirectory(expandedPreset->BinaryDir); } - if (!this->GlobalGenerator) { + if (!this->GlobalGenerator && !expandedPreset->Generator.empty()) { if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator, false)) { return; @@ -3203,7 +3204,9 @@ int cmake::Build(int jobs, std::string dir, std::vector targets, return 1; } - dir = expandedConfigurePreset->BinaryDir; + if (!expandedConfigurePreset->BinaryDir.empty()) { + dir = expandedConfigurePreset->BinaryDir; + } this->UnprocessedPresetEnvironment = expandedPreset->Environment; this->ProcessPresetEnvironment(); diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake new file mode 100644 index 00000000000..49e7a255060 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.cmake @@ -0,0 +1,3 @@ +include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake) + +test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build") diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in new file mode 100644 index 00000000000..ee17a222cc8 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirField.json.in @@ -0,0 +1,9 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "OptionalBinaryDirField", + "generator": "@RunCMake_GENERATOR@" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake new file mode 100644 index 00000000000..4319e72167f --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.cmake @@ -0,0 +1,3 @@ +include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake) + +test_variable(CMAKE_GENERATOR "" "${RunCMake_GENERATOR}") diff --git a/Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in new file mode 100644 index 00000000000..920d05632aa --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OptionalGeneratorField.json.in @@ -0,0 +1,9 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "OptionalGeneratorField", + "binaryDir": "${sourceDir}/build" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 95234302f00..bcbd177f8e7 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -275,6 +275,11 @@ set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Conditions.json.in") run_cmake_presets(ListConditions --list-presets) run_cmake_presets(SimpleTrue) run_cmake_presets(SimpleFalse) +unset(CMakePresets_FILE) + +# Test optional generator and buildDir fields +run_cmake_presets(OptionalBinaryDirField -B "${RunCMake_BINARY_DIR}/OptionalBinaryDirField/build") +run_cmake_presets(OptionalGeneratorField -G "${RunCMake_GENERATOR}") # Test the example from the documentation file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example) From a8b6b54239ac39493947e97cbe5164ac2b1c323e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 7 Apr 2021 00:06:15 -0400 Subject: [PATCH 0220/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b7ca022c628..7072e532fe4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210406) +set(CMake_VERSION_PATCH 20210407) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f71e7b8156423512f4631f393d955b31557cdd8e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 7 Apr 2021 12:28:57 -0400 Subject: [PATCH 0221/1519] Help/dev/review: mention `--pretty=reference` This was added in Git 2.25 (13 Jan 2020). --- Help/dev/review.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Help/dev/review.rst b/Help/dev/review.rst index 8326e701525..10ff87b95dc 100644 --- a/Help/dev/review.rst +++ b/Help/dev/review.rst @@ -254,7 +254,8 @@ The preferred form for references to other commits is The author date of the commit, in its original time zone, formatted as ``CCYY-MM-DD``. ``git-log(1)`` shows the original time zone by default. -This may be generated with +This may be generated with ``git show -s --pretty=reference `` with +Git 2.25 and newer. Older versions of Git can generate the same format via ``git show -s --date=short --pretty="format:%h (%s, %ad)" ``. If the commit is a fix for the mentioned commit, consider using a ``Fixes:`` From 8ffd3b49464005b6bb6ba2902616b2e8a5ce3a8d Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 8 Apr 2021 00:01:25 -0400 Subject: [PATCH 0222/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7072e532fe4..f37f3b986d4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210407) +set(CMake_VERSION_PATCH 20210408) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From eb62097dec525ade99299697365d9e129455ddaf Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 9 Apr 2021 00:01:21 -0400 Subject: [PATCH 0223/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f37f3b986d4..fc8d6f9ed14 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210408) +set(CMake_VERSION_PATCH 20210409) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From aa283fdba161eb458b02caaa9f0c32d97c648d6f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 10 Apr 2021 00:01:04 -0400 Subject: [PATCH 0224/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fc8d6f9ed14..9d81c40970e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210409) +set(CMake_VERSION_PATCH 20210410) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0656bebeaecb85c2297b3d87634aed6ce8a80f34 Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sat, 3 Apr 2021 11:49:11 +0100 Subject: [PATCH 0225/1519] Autogen: Rename the variable for UI files with UIC options Monitoring for UI file changes in the target sources will require keeping track of the files without options as well so this will improve clarity. --- Source/cmQtAutoGenInitializer.cxx | 5 +++-- Source/cmQtAutoGenInitializer.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index e96ec63f624..f0c799efb4a 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -936,7 +936,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Check if the .ui file has uic options std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); if (!uicOpts.empty()) { - this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts)); + this->Uic.UiFilesWithOptions.emplace_back(fullPath, + cmExpandedList(uicOpts)); } auto uiHeaderRelativePath = cmSystemTools::RelativePath( @@ -1626,7 +1627,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end()); info.SetArray("UIC_SKIP", uic_skip); - info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles, + info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFilesWithOptions, [](Json::Value& jval, UicT::UiFileT const& uiFile) { jval.resize(2u); jval[0u] = uiFile.first; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index fdb65d3df02..9fe0cf08214 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -236,7 +236,7 @@ class cmQtAutoGenInitializer : public cmQtAutoGen : GenVarsT(GenT::UIC){}; std::set SkipUi; - std::vector UiFiles; + std::vector UiFilesWithOptions; ConfigStrings> Options; std::vector SearchPaths; std::vector> From 087b717aefd5439fc5bc6ae25b9795cbb5563e02 Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sat, 3 Apr 2021 19:52:53 +0100 Subject: [PATCH 0226/1519] Autogen: Move duplicated executable dependency code into a function --- Source/cmQtAutoGenInitializer.cxx | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index f0c799efb4a..a1602bd3f3f 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -294,6 +294,17 @@ bool InfoWriter::Save(std::string const& filename) return fileStream.Close(); } +void AddAutogenExecutableToDependencies( + cmQtAutoGenInitializer::GenVarsT const& genVars, + std::vector& dependencies) +{ + if (genVars.ExecutableTarget != nullptr) { + dependencies.push_back(genVars.ExecutableTarget->Target->GetName()); + } else if (!genVars.Executable.empty()) { + dependencies.push_back(genVars.Executable); + } +} + } // End of unnamed namespace cmQtAutoGenInitializer::cmQtAutoGenInitializer( @@ -1279,16 +1290,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() dependencies.clear(); dependencies.push_back(timestampTargetName); - if (this->Moc.ExecutableTarget != nullptr) { - dependencies.push_back(this->Moc.ExecutableTarget->Target->GetName()); - } else if (!this->Moc.Executable.empty()) { - dependencies.push_back(this->Moc.Executable); - } - if (this->Uic.ExecutableTarget != nullptr) { - dependencies.push_back(this->Uic.ExecutableTarget->Target->GetName()); - } else if (!this->Uic.Executable.empty()) { - dependencies.push_back(this->Uic.Executable); - } + AddAutogenExecutableToDependencies(this->Moc, dependencies); + AddAutogenExecutableToDependencies(this->Uic, dependencies); // Create the custom command that outputs the timestamp file. const char timestampFileName[] = "timestamp"; From 1876f2d03fe3ccc4ea02c27fe345657b3366b48e Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sat, 10 Apr 2021 15:04:22 +0100 Subject: [PATCH 0227/1519] Autogen: Move duplicated filename generation code into a function --- Source/cmQtAutoGenInitializer.cxx | 47 ++++++++++++++----------------- Source/cmQtAutoGenInitializer.h | 2 ++ 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a1602bd3f3f..816d7e532a0 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -430,12 +430,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() cmSystemTools::ConvertToUnixSlashes(this->Dir.Work); // Include directory - this->ConfigFileNames(this->Dir.Include, - cmStrCat(this->Dir.Build, "/include"), ""); - this->Dir.IncludeGenExp = this->Dir.Include.Default; - if (this->MultiConfig) { - this->Dir.IncludeGenExp += "_$"; - } + this->ConfigFileNamesAndGenex(this->Dir.Include, this->Dir.IncludeGenExp, + cmStrCat(this->Dir.Build, "/include"), ""); } // Moc, Uic and _autogen target settings @@ -586,15 +582,9 @@ bool cmQtAutoGenInitializer::InitMoc() cmStrCat(this->Dir.Build, "/mocs_compilation.cpp"); this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default; } else { - this->ConfigFileNames(this->Moc.CompilationFile, - cmStrCat(this->Dir.Build, "/mocs_compilation"), - ".cpp"); - if (this->MultiConfig) { - this->Moc.CompilationFileGenex = - cmStrCat(this->Dir.Build, "/mocs_compilation_$.cpp"_s); - } else { - this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default; - } + this->ConfigFileNamesAndGenex( + this->Moc.CompilationFile, this->Moc.CompilationFileGenex, + cmStrCat(this->Dir.Build, "/mocs_compilation"_s), ".cpp"_s); } // Moc predefs @@ -966,17 +956,10 @@ bool cmQtAutoGenInitializer::InitScanFiles() cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); ConfigString uiHeader; - uiHeader.Default = - cmStrCat(this->Dir.Build, "/include"_s, uiHeaderFilePath); - auto uiHeaderGenex = uiHeader.Default; - if (this->MultiConfig) { - uiHeaderGenex = cmStrCat(this->Dir.Build, "/include_$"_s, - uiHeaderFilePath); - for (std::string const& cfg : this->ConfigsList) { - uiHeader.Config[cfg] = cmStrCat(this->Dir.Build, "/include_"_s, - cfg, uiHeaderFilePath); - } - } + std::string uiHeaderGenex; + this->ConfigFileNamesAndGenex( + uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s), + uiHeaderFilePath); this->Uic.UiHeaders.emplace_back( std::make_pair(uiHeader, uiHeaderGenex)); @@ -1790,6 +1773,18 @@ void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString, } } +void cmQtAutoGenInitializer::ConfigFileNamesAndGenex( + ConfigString& configString, std::string& genex, cm::string_view const prefix, + cm::string_view const suffix) +{ + this->ConfigFileNames(configString, prefix, suffix); + if (this->MultiConfig) { + genex = cmStrCat(prefix, "_$"_s, suffix); + } else { + genex = configString.Default; + } +} + void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString) { this->AddCleanFile(configString.Default); diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 9fe0cf08214..d096315f4bb 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -141,6 +141,8 @@ class cmQtAutoGenInitializer : public cmQtAutoGen void ConfigFileNames(ConfigString& configString, cm::string_view prefix, cm::string_view suffix); + void ConfigFileNamesAndGenex(ConfigString& configString, std::string& genex, + cm::string_view prefix, cm::string_view suffix); void ConfigFileClean(ConfigString& configString); std::string GetMocBuildPath(MUFile const& muf); From a8d879cf4507f0460dd8386a10c3b4ffe79c3566 Mon Sep 17 00:00:00 2001 From: Duncan Barber <7744-dunquan@users.noreply.gitlab.kitware.com> Date: Sat, 3 Apr 2021 11:53:53 +0100 Subject: [PATCH 0228/1519] Autogen: Add detection of UI file changes to the pre-build VS case This is achieved by adding a rule file which carries the UI files as dependencies but performs no meaningful command. Its output path points to a timestamp file which is instead touched by the pre-build command that runs autogen. The rule file therefore triggers the build if any of the files have been changed more recently than the last autogen run. Fixes: #17959 Fixes: #18741 --- Source/cmQtAutoGenInitializer.cxx | 40 ++++++++++++++++++++++++++++++- Source/cmQtAutoGenInitializer.h | 1 + 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 816d7e532a0..3adeb1aee0c 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -936,7 +936,9 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!skipUic) { // Check if the .ui file has uic options std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); - if (!uicOpts.empty()) { + if (uicOpts.empty()) { + this->Uic.UiFilesNoOptions.emplace_back(fullPath); + } else { this->Uic.UiFilesWithOptions.emplace_back(fullPath, cmExpandedList(uicOpts)); } @@ -1181,6 +1183,42 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->Makefile); } + if (!this->Uic.UiFilesNoOptions.empty() || + !this->Uic.UiFilesWithOptions.empty()) { + // Add a generated timestamp file + ConfigString timestampFile; + std::string timestampFileGenex; + ConfigFileNamesAndGenex(timestampFile, timestampFileGenex, + cmStrCat(this->Dir.Build, "/autouic"_s), + ".stamp"_s); + this->AddGeneratedSource(timestampFile, this->Uic); + + // Add a step in the pre-build command to touch the timestamp file + commandLines.push_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "touch", + timestampFileGenex })); + + // UIC needs to be re-run if any of the known UI files change or the + // executable itself has been updated + auto uicDependencies = this->Uic.UiFilesNoOptions; + for (auto const& uiFile : this->Uic.UiFilesWithOptions) { + uicDependencies.push_back(uiFile.first); + } + AddAutogenExecutableToDependencies(this->Uic, uicDependencies); + + // Add a rule file to cause the target to build if a dependency has + // changed, which will trigger the pre-build command to run autogen + std::string no_main_dependency; + cmCustomCommandLines no_command_lines; + this->LocalGen->AddCustomCommandToOutput( + timestampFileGenex, uicDependencies, no_main_dependency, + no_command_lines, /*comment=*/"", this->Dir.Work.c_str(), + /*cmp0116=*/cmPolicies::NEW, /*replace=*/false, + /*escapeOldStyle=*/false, /*uses_terminal=*/false, + /*command_expand_lists=*/false, /*depfile=*/"", /*job_pool=*/"", + stdPipesUTF8); + } + // Add the pre-build command directly to bypass the OBJECT_LIBRARY // rejection in cmMakefile::AddCustomCommandToTarget because we know // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index d096315f4bb..8a6d8f924fa 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -238,6 +238,7 @@ class cmQtAutoGenInitializer : public cmQtAutoGen : GenVarsT(GenT::UIC){}; std::set SkipUi; + std::vector UiFilesNoOptions; std::vector UiFilesWithOptions; ConfigStrings> Options; std::vector SearchPaths; From b1c739ad8bcacae6d66d88514102dcd4423c2dcb Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 11 Apr 2021 00:01:04 -0400 Subject: [PATCH 0229/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9d81c40970e..b2c866b4383 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210410) +set(CMake_VERSION_PATCH 20210411) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f62a2bf44f392f6a23836848714ed36cd02975af Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 11 Apr 2021 18:05:14 +1000 Subject: [PATCH 0230/1519] Tests: Factor out XcodeProject-Embed check function findAttribute() --- .../EmbedFrameworksFlagsOff-check.cmake | 16 +++------------- ...EmbedFrameworksFlagsOnNoSubdir-check.cmake | 16 +++------------- ...bedFrameworksFlagsOnWithSubdir-check.cmake | 16 +++------------- .../XcodeProject-Embed/findAttribute.cmake | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 39 deletions(-) create mode 100644 Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake index 9cc03b9f4e4..dbd3e87749f 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake @@ -1,14 +1,4 @@ -function(findAttribute project attr) - execute_process( - COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj - OUTPUT_VARIABLE output_var - RESULT_VARIABLE result_var - ) +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) - if(NOT result_var) - set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE) - endif() -endfunction() - -findAttribute(${test} "RemoveHeadersOnCopy") -findAttribute(${test} "CodeSignOnCopy") +findAttribute(${test} "RemoveHeadersOnCopy" FALSE) +findAttribute(${test} "CodeSignOnCopy" FALSE) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake index 3f62640c93d..0f578206617 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake @@ -1,14 +1,4 @@ -function(findAttribute project attr) - execute_process( - COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj - OUTPUT_VARIABLE output_var - RESULT_VARIABLE result_var - ) +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) - if(result_var) - set(RunCMake_TEST_FAILED "${attr} attribute not set" PARENT_SCOPE) - endif() -endfunction() - -findAttribute(${test} "RemoveHeadersOnCopy") -findAttribute(${test} "CodeSignOnCopy") +findAttribute(${test} "RemoveHeadersOnCopy" TRUE) +findAttribute(${test} "CodeSignOnCopy" TRUE) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake index 3f62640c93d..0f578206617 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake @@ -1,14 +1,4 @@ -function(findAttribute project attr) - execute_process( - COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj - OUTPUT_VARIABLE output_var - RESULT_VARIABLE result_var - ) +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) - if(result_var) - set(RunCMake_TEST_FAILED "${attr} attribute not set" PARENT_SCOPE) - endif() -endfunction() - -findAttribute(${test} "RemoveHeadersOnCopy") -findAttribute(${test} "CodeSignOnCopy") +findAttribute(${test} "RemoveHeadersOnCopy" TRUE) +findAttribute(${test} "CodeSignOnCopy" TRUE) diff --git a/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake new file mode 100644 index 00000000000..b1963e248bb --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake @@ -0,0 +1,19 @@ +cmake_policy(VERSION 3.1...3.20) + +function(findAttribute project attr expectPresent) + execute_process( + COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj + OUTPUT_VARIABLE output_var + RESULT_VARIABLE result_var + ) + + if(${expectPresent}) + if(result_var) + set(RunCMake_TEST_FAILED "${attr} attribute is not set" PARENT_SCOPE) + endif() + else() + if(NOT result_var) + set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE) + endif() + endif() +endfunction() From 43ecda68eb85bdb38c635ecd3e5a5296a2451f81 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 12 Apr 2021 00:01:08 -0400 Subject: [PATCH 0231/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b2c866b4383..22237e6eae1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210411) +set(CMake_VERSION_PATCH 20210412) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0c47b91fccf5d55a0edc1512a543b8445a8fa4ba Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 9 Apr 2021 19:09:52 +0200 Subject: [PATCH 0232/1519] Genex: add_custom_command: DEPFILE supports genex This facility is very useful for 'Ninja Multi-Config' and required as well for future support of DEPFILE in 'Xcode' and 'Visual Studio' generators (#20286). --- Help/command/add_custom_command.rst | 7 ++++++- .../dev/add_custom_command-DEPFILE-genex.rst | 5 +++++ Source/cmCustomCommandGenerator.cxx | 21 ++++++++++++++++++- Source/cmCustomCommandGenerator.h | 1 + Source/cmLocalNinjaGenerator.cxx | 2 +- .../BuildDepends/CustomCommandDepfile.cmake | 8 +++---- .../Ninja/CustomCommandDepfile-check.cmake | 7 ++++++- .../RunCMake/Ninja/CustomCommandDepfile.cmake | 13 +++++++++++- Tests/RunCMake/Ninja/RunCMakeTest.cmake | 2 +- .../CustomCommandDepfile-check.cmake | 7 ++++++- .../CustomCommandDepfile.cmake | 13 +++++++++++- 11 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 Help/release/dev/add_custom_command-DEPFILE-genex.rst diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index c0b95934bed..b6ff0ea35bc 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -272,7 +272,9 @@ The options are: .. versionadded:: 3.7 Specify a ``.d`` depfile for the :generator:`Ninja` generator and - :ref:`Makefile Generators`. + :ref:`Makefile Generators`. The depfile may use "generator expressions" with + the syntax ``$<...>``. See the :manual:`generator-expressions(7) + ` manual for available expressions. A ``.d`` file holds dependencies usually emitted by the custom command itself. Using ``DEPFILE`` with other generators than :generator:`Ninja` or @@ -281,6 +283,9 @@ The options are: .. versionadded:: 3.20 Added the support of :ref:`Makefile Generators`. + .. versionadded:: 3.21 + Added the support of :manual:`generator expressions `. + If the ``DEPFILE`` argument is relative, it should be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR` diff --git a/Help/release/dev/add_custom_command-DEPFILE-genex.rst b/Help/release/dev/add_custom_command-DEPFILE-genex.rst new file mode 100644 index 00000000000..52e5e9fabff --- /dev/null +++ b/Help/release/dev/add_custom_command-DEPFILE-genex.rst @@ -0,0 +1,5 @@ +add_custom_command-DEPFILE-genex +-------------------------------- + +* The :command:`add_custom_command` command ``DEPFILE`` option learned to + support :manual:`generator expressions `. diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 4329cafc48d..4705443190e 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -139,6 +139,14 @@ std::vector EvaluateOutputs(std::vector const& paths, } return outputs; } + +std::string EvaluateDepfile(std::string const& path, + cmGeneratorExpression const& ge, + cmLocalGenerator* lg, std::string const& config) +{ + std::unique_ptr cge = ge.Parse(path); + return cge->Evaluate(lg, config); +} } cmCustomCommandGenerator::cmCustomCommandGenerator( @@ -381,9 +389,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, } } +std::string cmCustomCommandGenerator::GetDepfile() const +{ + const auto& depfile = this->CC->GetDepfile(); + if (depfile.empty()) { + return ""; + } + + cmGeneratorExpression ge(this->CC->GetBacktrace()); + return EvaluateDepfile(depfile, ge, this->LG, this->OutputConfig); +} + std::string cmCustomCommandGenerator::GetFullDepfile() const { - std::string depfile = this->CC->GetDepfile(); + std::string depfile = this->GetDepfile(); if (depfile.empty()) { return ""; } diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 4be5b3fd26f..53e55737da8 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -57,6 +57,7 @@ class cmCustomCommandGenerator std::vector const& GetDepends() const; std::set>> const& GetUtilities() const; bool HasOnlyEmptyCommandLines() const; + std::string GetDepfile() const; std::string GetFullDepfile() const; std::string GetInternalDepfile() const; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 03d16973b23..c2a64109143 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -670,7 +670,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( cmCryptoHash hash(cmCryptoHash::AlgoSHA256); customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7); - std::string depfile = cc->GetDepfile(); + std::string depfile = ccg.GetDepfile(); if (!depfile.empty()) { switch (cc->GetCMP0116Status()) { case cmPolicies::WARN: diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake index 01eac91dddc..e4fdb4ae5d4 100644 --- a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake +++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake @@ -3,15 +3,15 @@ enable_language(C) add_custom_command( OUTPUT topcc.c - DEPFILE topcc.c.d - COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" + DEPFILE topcc_$.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc_$.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" ) add_custom_target(topcc ALL DEPENDS topcc.c) add_custom_command( OUTPUT topexe.c - DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe.c.d - COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" + DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe_$.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe_$.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" ) add_executable(topexe "${CMAKE_CURRENT_BINARY_DIR}/topexe.c") diff --git a/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake b/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake index 189de6417aa..51f4f52cc70 100644 --- a/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake +++ b/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake @@ -1,5 +1,10 @@ set(log "${RunCMake_BINARY_DIR}/CustomCommandDepfile-build/build.ninja") file(READ "${log}" build_file) + +set(RunCMake_TEST_FAILED) if(NOT "${build_file}" MATCHES "depfile = test\\.d") - set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d") + list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d") +endif() +if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d") + list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d") endif() diff --git a/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake b/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake index dbef2a53542..0838d143399 100644 --- a/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake +++ b/Tests/RunCMake/Ninja/CustomCommandDepfile.cmake @@ -6,6 +6,17 @@ add_custom_command( WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DEPFILE "test.d" ) -add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c") + +add_custom_command( + OUTPUT hello.copy2.c + COMMAND "${CMAKE_COMMAND}" -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/hello.c" + hello.copy2.c + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + DEPFILE "test_$.d" + ) + +add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c" + "${CMAKE_CURRENT_BINARY_DIR}/hello.copy2.c") include(CheckNoPrefixSubDir.cmake) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 0c0619dbfea..1350326164b 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -67,7 +67,7 @@ run_CMP0058(WARN-by) run_CMP0058(NEW-no) run_CMP0058(NEW-by) -run_cmake(CustomCommandDepfile) +run_cmake_with_options(CustomCommandDepfile -DCMAKE_BUILD_TYPE=Debug) run_cmake(CustomCommandJobPool) run_cmake(JobPoolUsesTerminal) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake index c595b1097bf..a7837ca98d1 100644 --- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake @@ -1,5 +1,10 @@ set(log "${RunCMake_BINARY_DIR}/CustomCommandDepfile-build/CMakeFiles/impl-Debug.ninja") file(READ "${log}" build_file) + +set(RunCMake_TEST_FAILED) if(NOT "${build_file}" MATCHES "depfile = test\\.d") - set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d") + list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d") +endif() +if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d") + list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d") endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake index 1a42670c9bb..4f8c114300e 100644 --- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile.cmake @@ -6,4 +6,15 @@ add_custom_command( WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DEPFILE "test.d" ) -add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.copy.c") + +add_custom_command( + OUTPUT main.copy2.c + COMMAND "${CMAKE_COMMAND}" -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/main.c" + main.copy2.c + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + DEPFILE "test_$.d" + ) + +add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.copy.c" + "${CMAKE_CURRENT_BINARY_DIR}/main.copy2.c") From 4bfe724e8149938031dde808610d369b1dc890ba Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 13 Apr 2021 00:01:05 -0400 Subject: [PATCH 0233/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 22237e6eae1..2d072ce4b46 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210412) +set(CMake_VERSION_PATCH 20210413) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 156504fe755dedbdc9ed9147a65f4c730aad4b8a Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 14 Apr 2021 00:01:04 -0400 Subject: [PATCH 0234/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2d072ce4b46..8930a5fffd0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210413) +set(CMake_VERSION_PATCH 20210414) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a790167101290eaf77d7a3ef8fd807160af1b9a9 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Wed, 14 Apr 2021 12:02:30 -0400 Subject: [PATCH 0235/1519] KWSys 2021-04-14 (7ab1c601) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 7ab1c60177e76707fbdd462fdbf7304ad2532edc (master). Upstream Shortlog ----------------- Brad King (11): 85e76a10 Status: Add class to hold an OS-specific status of a system operation eec0add2 Directory: Return Status from Load 955e7c1e SystemTools: Return Status from RemoveFile and RemoveADirectory c5a99e59 SystemTools: Return Status from GetPermissions and SetPermissions fadfd7a0 SystemTools: Return Status from Touch 06216f0b SystemTools: Return Status from FileTimeCompare ab198a22 SystemTools: Return Status from GetShortPath 2446b205 SystemTools: Return Status from MakeDirectory 6aec6af9 SystemTools: Return Status from ChangeDirectory 0664553b SystemTools: Return Status from copy operations a95f61cf SystemTools: Return Status from symlink operations --- CMakeLists.txt | 6 +- Directory.cxx | 35 +++--- Directory.hxx.in | 6 +- Status.cxx | 60 +++++++++ Status.hxx.in | 101 +++++++++++++++ SystemTools.cxx | 300 +++++++++++++++++++++++++-------------------- SystemTools.hxx.in | 65 +++++----- testDirectory.cxx | 4 +- testStatus.cxx | 117 ++++++++++++++++++ 9 files changed, 503 insertions(+), 191 deletions(-) create mode 100644 Status.cxx create mode 100644 Status.hxx.in create mode 100644 testStatus.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index b0a85429292..bf8543ec720 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR) set(KWSYS_USE_MD5 1) set(KWSYS_USE_Process 1) set(KWSYS_USE_RegularExpression 1) + set(KWSYS_USE_Status 1) set(KWSYS_USE_System 1) set(KWSYS_USE_SystemTools 1) set(KWSYS_USE_CommandLineArguments 1) @@ -157,6 +158,7 @@ if(KWSYS_USE_SystemTools) set(KWSYS_USE_Directory 1) set(KWSYS_USE_FStream 1) set(KWSYS_USE_Encoding 1) + set(KWSYS_USE_Status 1) endif() if(KWSYS_USE_Glob) set(KWSYS_USE_Directory 1) @@ -177,6 +179,7 @@ if(KWSYS_USE_System) endif() if(KWSYS_USE_Directory) set(KWSYS_USE_Encoding 1) + set(KWSYS_USE_Status 1) endif() if(KWSYS_USE_DynamicLoader) set(KWSYS_USE_Encoding 1) @@ -630,7 +633,7 @@ set(KWSYS_HXX_FILES Configure String) # Add selected C++ classes. set(cppclasses Directory DynamicLoader Encoding Glob RegularExpression SystemTools - CommandLineArguments FStream SystemInformation ConsoleBuf + CommandLineArguments FStream SystemInformation ConsoleBuf Status ) foreach(cpp ${cppclasses}) if(KWSYS_USE_${cpp}) @@ -963,6 +966,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR) # C++ tests set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testConfigure.cxx + testStatus.cxx testSystemTools.cxx testCommandLineArguments.cxx testCommandLineArguments1.cxx diff --git a/Directory.cxx b/Directory.cxx index e70d4e86882..2e8aa83f4c0 100644 --- a/Directory.cxx +++ b/Directory.cxx @@ -94,7 +94,7 @@ void Directory::Clear() namespace KWSYS_NAMESPACE { -bool Directory::Load(const std::string& name, std::string* errorMessage) +Status Directory::Load(std::string const& name, std::string* errorMessage) { this->Clear(); intptr_t srchHandle; @@ -121,21 +121,11 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) delete[] buf; if (srchHandle == -1) { + Status status = Status::POSIX_errno(); if (errorMessage) { - if (unsigned int errorId = GetLastError()) { - LPSTR message = nullptr; - DWORD size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&message, 0, nullptr); - *errorMessage = std::string(message, size); - LocalFree(message); - } else { - *errorMessage = "Unknown error."; - } + *errorMessage = status.GetString(); } - return false; + return status; } // Loop through names @@ -143,7 +133,14 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) this->Internal->Files.push_back(Encoding::ToNarrow(data.name)); } while (_wfindnext(srchHandle, &data) != -1); this->Internal->Path = name; - return _findclose(srchHandle) != -1; + if (_findclose(srchHandle) == -1) { + Status status = Status::POSIX_errno(); + if (errorMessage) { + *errorMessage = status.GetString(); + } + return status; + } + return Status::Success(); } unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, @@ -220,7 +217,7 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, namespace KWSYS_NAMESPACE { -bool Directory::Load(const std::string& name, std::string* errorMessage) +Status Directory::Load(std::string const& name, std::string* errorMessage) { this->Clear(); @@ -231,7 +228,7 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) if (errorMessage != nullptr) { *errorMessage = std::string(strerror(errno)); } - return false; + return Status::POSIX_errno(); } errno = 0; @@ -242,12 +239,12 @@ bool Directory::Load(const std::string& name, std::string* errorMessage) if (errorMessage != nullptr) { *errorMessage = std::string(strerror(errno)); } - return false; + return Status::POSIX_errno(); } this->Internal->Path = name; closedir(dir); - return true; + return Status::Success(); } unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, diff --git a/Directory.hxx.in b/Directory.hxx.in index 7bc9db024e7..d5011161512 100644 --- a/Directory.hxx.in +++ b/Directory.hxx.in @@ -4,6 +4,7 @@ #define @KWSYS_NAMESPACE@_Directory_hxx #include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/Status.hxx> #include @@ -32,10 +33,9 @@ public: /** * Load the specified directory and load the names of the files - * in that directory. 0 is returned if the directory can not be - * opened, 1 if it is opened. + * in that directory. */ - bool Load(const std::string&, std::string* errorMessage = nullptr); + Status Load(std::string const&, std::string* errorMessage = nullptr); /** * Return the number of files in the current directory. diff --git a/Status.cxx b/Status.cxx new file mode 100644 index 00000000000..503d1e1d513 --- /dev/null +++ b/Status.cxx @@ -0,0 +1,60 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Status.hxx) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Status.hxx.in" +#endif + +#include +#include +#include + +#if defined(_WIN32) +# include +#endif + +namespace KWSYS_NAMESPACE { + +Status Status::POSIX_errno() +{ + return Status::POSIX(errno); +} + +#ifdef _WIN32 +Status Status::Windows_GetLastError() +{ + return Status::Windows(GetLastError()); +} +#endif + +std::string Status::GetString() const +{ + std::string err; + switch (this->Kind_) { + case Kind::Success: + err = "Success"; + break; + case Kind::POSIX: + err = strerror(this->POSIX_); + break; +#ifdef _WIN32 + case Kind::Windows: { + LPSTR message = NULL; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, this->Windows_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message, 0, NULL); + err = std::string(message, size); + LocalFree(message); + } break; +#endif + }; + return err; +} + +} // namespace KWSYS_NAMESPACE diff --git a/Status.hxx.in b/Status.hxx.in new file mode 100644 index 00000000000..feb5b848b99 --- /dev/null +++ b/Status.hxx.in @@ -0,0 +1,101 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#ifndef @KWSYS_NAMESPACE@_Status_hxx +#define @KWSYS_NAMESPACE@_Status_hxx + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include + +namespace @KWSYS_NAMESPACE@ { + +/** \class Status + * \brief OS-specific status of a system operation. + */ +class @KWSYS_NAMESPACE@_EXPORT Status +{ +public: + enum class Kind + { + Success, + POSIX, +#ifdef _WIN32 + Windows, +#endif + }; + + /** Construct with kind "Success". */ + Status() = default; + + /** Construct with kind "Success". */ + static Status Success() { return Status(); } + + /** Construct with kind "POSIX" using given errno-style value. */ + static Status POSIX(int e) + { + Status s(Kind::POSIX); + s.POSIX_ = e; + return s; + } + + /** Construct with kind "POSIX" using errno. */ + static Status POSIX_errno(); + +#ifdef _WIN32 + /** Construct with kind "Windows" using given GetLastError()-style value. */ + static Status Windows(unsigned int e) + { + Status s(Kind::Windows); + s.Windows_ = e; + return s; + } + + /** Construct with kind "Windows" using GetLastError(). */ + static Status Windows_GetLastError(); +#endif + + /** Return true on "Success", false otherwise. */ + explicit operator bool() const { return this->Kind_ == Kind::Success; } + + /** Return the kind of status. */ + Kind GetKind() const { return this->Kind_; } + + /** If the kind is "POSIX", returns the errno-style value. + Otherwise, returns 0. */ + int GetPOSIX() const + { + return this->Kind_ == Kind::POSIX ? this->POSIX_ : 0; + } + +#ifdef _WIN32 + /** If the kind is "Windows", returns the GetLastError()-style value. + Otherwise, returns 0. */ + int GetWindows() const + { + return this->Kind_ == Kind::Windows ? this->Windows_ : 0; + } +#endif + + /** Return a human-readable description of the status. */ + std::string GetString() const; + +private: + Status(Kind kind) + : Kind_(kind) + { + } + + Kind Kind_ = Kind::Success; + + union + { + int POSIX_; +#ifdef _WIN32 + unsigned int Windows_; +#endif + }; +}; + +} // namespace @KWSYS_NAMESPACE@ + +#endif diff --git a/SystemTools.cxx b/SystemTools.cxx index 4d974a898bb..25188454c0f 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -882,21 +882,24 @@ FILE* SystemTools::Fopen(const std::string& file, const char* mode) #endif } -bool SystemTools::MakeDirectory(const char* path, const mode_t* mode) +Status SystemTools::MakeDirectory(const char* path, const mode_t* mode) { if (!path) { - return false; + return Status::POSIX(EINVAL); } return SystemTools::MakeDirectory(std::string(path), mode); } -bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) +Status SystemTools::MakeDirectory(std::string const& path, const mode_t* mode) { - if (SystemTools::PathExists(path)) { - return SystemTools::FileIsDirectory(path); - } if (path.empty()) { - return false; + return Status::POSIX(EINVAL); + } + if (SystemTools::PathExists(path)) { + if (SystemTools::FileIsDirectory(path)) { + return Status::Success(); + } + return Status::POSIX(EEXIST); } std::string dir = path; SystemTools::ConvertToUnixSlashes(dir); @@ -914,15 +917,11 @@ bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode) ++pos; } topdir = dir; - if (Mkdir(topdir, mode) != 0) { - // if it is some other error besides directory exists - // then return false - if (errno != EEXIST) { - return false; - } + if (Mkdir(topdir, mode) != 0 && errno != EEXIST) { + return Status::POSIX_errno(); } - return true; + return Status::Success(); } // replace replace with with as many times as it shows up in source. @@ -1411,18 +1410,18 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf) #endif } -bool SystemTools::Touch(const std::string& filename, bool create) +Status SystemTools::Touch(std::string const& filename, bool create) { if (!SystemTools::FileExists(filename)) { if (create) { FILE* file = Fopen(filename, "a+b"); if (file) { fclose(file); - return true; + return Status::Success(); } - return false; + return Status::POSIX_errno(); } else { - return true; + return Status::Success(); } } #if defined(_WIN32) && !defined(__CYGWIN__) @@ -1430,31 +1429,32 @@ bool SystemTools::Touch(const std::string& filename, bool create) FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); if (!h) { - return false; + return Status::Windows_GetLastError(); } FILETIME mtime; GetSystemTimeAsFileTime(&mtime); if (!SetFileTime(h, 0, 0, &mtime)) { + Status status = Status::Windows_GetLastError(); CloseHandle(h); - return false; + return status; } CloseHandle(h); #elif KWSYS_CXX_HAS_UTIMENSAT // utimensat is only available on newer Unixes and macOS 10.13+ if (utimensat(AT_FDCWD, filename.c_str(), nullptr, 0) < 0) { - return false; + return Status::POSIX_errno(); } #else // fall back to utimes if (utimes(filename.c_str(), nullptr) < 0) { - return false; + return Status::POSIX_errno(); } #endif - return true; + return Status::Success(); } -bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, - int* result) +Status SystemTools::FileTimeCompare(std::string const& f1, + std::string const& f2, int* result) { // Default to same time. *result = 0; @@ -1462,11 +1462,11 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, // POSIX version. Use stat function to get file modification time. struct stat s1; if (stat(f1.c_str(), &s1) != 0) { - return false; + return Status::POSIX_errno(); } struct stat s2; if (stat(f2.c_str(), &s2) != 0) { - return false; + return Status::POSIX_errno(); } # if KWSYS_CXX_STAT_HAS_ST_MTIM // Compare using nanosecond resolution. @@ -1504,17 +1504,17 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, WIN32_FILE_ATTRIBUTE_DATA f2d; if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(), GetFileExInfoStandard, &f1d)) { - return false; + return Status::Windows_GetLastError(); } if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(), GetFileExInfoStandard, &f2d)) { - return false; + return Status::Windows_GetLastError(); } // Compare the file times using resolution provided by system call. *result = (int)CompareFileTime(&f1d.ftLastWriteTime, &f2d.ftLastWriteTime); #endif - return true; + return Status::Success(); } // Return a capitalized string (i.e the first letter is uppercased, all other @@ -2129,8 +2129,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir) return new_destination + '/' + SystemTools::GetFilenameName(source); } -bool SystemTools::CopyFileIfDifferent(const std::string& source, - const std::string& destination) +Status SystemTools::CopyFileIfDifferent(std::string const& source, + std::string const& destination) { // special check for a destination that is a directory // FilesDiffer does not handle file to directory compare @@ -2147,7 +2147,7 @@ bool SystemTools::CopyFileIfDifferent(const std::string& source, } } // at this point the files must be the same so return true - return true; + return Status::Success(); } #define KWSYS_ST_BUFFER 4096 @@ -2273,13 +2273,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1, return false; } -bool SystemTools::CopyFileContentBlockwise(const std::string& source, - const std::string& destination) +Status SystemTools::CopyFileContentBlockwise(std::string const& source, + std::string const& destination) { // Open files kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); if (!fin) { - return false; + return Status::POSIX_errno(); } // try and remove the destination file so that read only destination files @@ -2291,7 +2291,7 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source, kwsys::ofstream fout(destination.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); if (!fout) { - return false; + return Status::POSIX_errno(); } // This copy loop is very sensitive on certain platforms with @@ -2320,10 +2320,10 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source, fout.close(); if (!fout) { - return false; + return Status::POSIX_errno(); } - return true; + return Status::Success(); } /** @@ -2338,13 +2338,13 @@ bool SystemTools::CopyFileContentBlockwise(const std::string& source, * - The underlying filesystem does not support file cloning * - An unspecified error occurred */ -bool SystemTools::CloneFileContent(const std::string& source, - const std::string& destination) +Status SystemTools::CloneFileContent(std::string const& source, + std::string const& destination) { #if defined(__linux) && defined(FICLONE) int in = open(source.c_str(), O_RDONLY); if (in < 0) { - return false; + return Status::POSIX_errno(); } SystemTools::RemoveFile(destination); @@ -2352,38 +2352,42 @@ bool SystemTools::CloneFileContent(const std::string& source, int out = open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (out < 0) { + Status status = Status::POSIX_errno(); close(in); - return false; + return status; } - int result = ioctl(out, FICLONE, in); + Status status = Status::Success(); + if (ioctl(out, FICLONE, in) < 0) { + status = Status::POSIX_errno(); + } close(in); close(out); - if (result < 0) { - return false; - } - - return true; + return status; #else (void)source; (void)destination; - return false; + return Status::POSIX(ENOSYS); #endif } /** * Copy a file named by "source" to the file named by "destination". */ -bool SystemTools::CopyFileAlways(const std::string& source, - const std::string& destination) +Status SystemTools::CopyFileAlways(std::string const& source, + std::string const& destination) { + Status status; mode_t perm = 0; - bool perms = SystemTools::GetPermissions(source, perm); + Status perms = SystemTools::GetPermissions(source, perm); std::string real_destination = destination; if (SystemTools::FileIsDirectory(source)) { - SystemTools::MakeDirectory(destination); + status = SystemTools::MakeDirectory(destination); + if (!status) { + return status; + } } else { // If destination is a directory, try to create a file with the same // name as the source in that directory. @@ -2400,30 +2404,34 @@ bool SystemTools::CopyFileAlways(const std::string& source, } // If files are the same do not copy if (SystemTools::SameFile(source, real_destination)) { - return true; + return status; } // Create destination directory - - SystemTools::MakeDirectory(destination_dir); - - if (!SystemTools::CloneFileContent(source, real_destination)) { - // if cloning did not succeed, fall back to blockwise copy - if (!SystemTools::CopyFileContentBlockwise(source, real_destination)) { - return false; + if (!destination_dir.empty()) { + status = SystemTools::MakeDirectory(destination_dir); + if (!status) { + return status; } } + + status = SystemTools::CloneFileContent(source, real_destination); + // if cloning did not succeed, fall back to blockwise copy + if (!status) { + status = SystemTools::CopyFileContentBlockwise(source, real_destination); + } + if (!status) { + return status; + } } if (perms) { - if (!SystemTools::SetPermissions(real_destination, perm)) { - return false; - } + status = SystemTools::SetPermissions(real_destination, perm); } - return true; + return status; } -bool SystemTools::CopyAFile(const std::string& source, - const std::string& destination, bool always) +Status SystemTools::CopyAFile(std::string const& source, + std::string const& destination, bool always) { if (always) { return SystemTools::CopyFileAlways(source, destination); @@ -2436,18 +2444,21 @@ bool SystemTools::CopyAFile(const std::string& source, * Copy a directory content from "source" directory to the directory named by * "destination". */ -bool SystemTools::CopyADirectory(const std::string& source, - const std::string& destination, bool always) +Status SystemTools::CopyADirectory(std::string const& source, + std::string const& destination, bool always) { + Status status; Directory dir; - if (dir.Load(source) == 0) { - return false; + status = dir.Load(source); + if (!status) { + return status; } - size_t fileNum; - if (!SystemTools::MakeDirectory(destination)) { - return false; + status = SystemTools::MakeDirectory(destination); + if (!status) { + return status; } - for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { + + for (size_t fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { if (strcmp(dir.GetFile(static_cast(fileNum)), ".") != 0 && strcmp(dir.GetFile(static_cast(fileNum)), "..") != 0) { std::string fullPath = source; @@ -2457,18 +2468,20 @@ bool SystemTools::CopyADirectory(const std::string& source, std::string fullDestPath = destination; fullDestPath += "/"; fullDestPath += dir.GetFile(static_cast(fileNum)); - if (!SystemTools::CopyADirectory(fullPath, fullDestPath, always)) { - return false; + status = SystemTools::CopyADirectory(fullPath, fullDestPath, always); + if (!status) { + return status; } } else { - if (!SystemTools::CopyAFile(fullPath, destination, always)) { - return false; + status = SystemTools::CopyAFile(fullPath, destination, always); + if (!status) { + return status; } } } } - return true; + return status; } // return size of file; also returns zero if no file exists @@ -2550,26 +2563,26 @@ std::string SystemTools::GetLastSystemError() return strerror(e); } -bool SystemTools::RemoveFile(const std::string& source) +Status SystemTools::RemoveFile(std::string const& source) { #ifdef _WIN32 std::wstring const& ws = Encoding::ToWindowsExtendedPath(source); if (DeleteFileW(ws.c_str())) { - return true; + return Status::Success(); } DWORD err = GetLastError(); if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) { - return true; + return Status::Success(); } if (err != ERROR_ACCESS_DENIED) { - return false; + return Status::Windows(err); } /* The file may be read-only. Try adding write permission. */ mode_t mode; if (!SystemTools::GetPermissions(source, mode) || !SystemTools::SetPermissions(source, S_IWRITE)) { SetLastError(err); - return false; + return Status::Windows(err); } const DWORD DIRECTORY_SOFT_LINK_ATTRS = @@ -2578,26 +2591,29 @@ bool SystemTools::RemoveFile(const std::string& source) if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & DIRECTORY_SOFT_LINK_ATTRS) == DIRECTORY_SOFT_LINK_ATTRS && RemoveDirectoryW(ws.c_str())) { - return true; + return Status::Success(); } if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) { - return true; + return Status::Success(); } /* Try to restore the original permissions. */ SystemTools::SetPermissions(source, mode); SetLastError(err); - return false; + return Status::Windows(err); #else - return unlink(source.c_str()) == 0 || errno == ENOENT; + if (unlink(source.c_str()) != 0 && errno != ENOENT) { + return Status::POSIX_errno(); + } + return Status::Success(); #endif } -bool SystemTools::RemoveADirectory(const std::string& source) +Status SystemTools::RemoveADirectory(std::string const& source) { // Add write permission to the directory so we can modify its // content to remove files and directories from it. - mode_t mode; + mode_t mode = 0; if (SystemTools::GetPermissions(source, mode)) { #if defined(_WIN32) && !defined(__CYGWIN__) mode |= S_IWRITE; @@ -2607,8 +2623,13 @@ bool SystemTools::RemoveADirectory(const std::string& source) SystemTools::SetPermissions(source, mode); } + Status status; Directory dir; - dir.Load(source); + status = dir.Load(source); + if (!status) { + return status; + } + size_t fileNum; for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { if (strcmp(dir.GetFile(static_cast(fileNum)), ".") != 0 && @@ -2618,18 +2639,23 @@ bool SystemTools::RemoveADirectory(const std::string& source) fullPath += dir.GetFile(static_cast(fileNum)); if (SystemTools::FileIsDirectory(fullPath) && !SystemTools::FileIsSymlink(fullPath)) { - if (!SystemTools::RemoveADirectory(fullPath)) { - return false; + status = SystemTools::RemoveADirectory(fullPath); + if (!status) { + return status; } } else { - if (!SystemTools::RemoveFile(fullPath)) { - return false; + status = SystemTools::RemoveFile(fullPath); + if (!status) { + return status; } } } } - return (Rmdir(source) == 0); + if (Rmdir(source) != 0) { + status = Status::POSIX_errno(); + } + return status; } /** @@ -3023,44 +3049,49 @@ bool SystemTools::FileIsFIFO(const std::string& name) } #if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::CreateSymlink(const std::string&, const std::string&) +Status SystemTools::CreateSymlink(std::string const&, std::string const&) { - return false; + return Status::Windows(ERROR_NOT_SUPPORTED); } #else -bool SystemTools::CreateSymlink(const std::string& origName, - const std::string& newName) +Status SystemTools::CreateSymlink(std::string const& origName, + std::string const& newName) { - return symlink(origName.c_str(), newName.c_str()) >= 0; + if (symlink(origName.c_str(), newName.c_str()) < 0) { + return Status::POSIX_errno(); + } + return Status::Success(); } #endif #if defined(_WIN32) && !defined(__CYGWIN__) -bool SystemTools::ReadSymlink(const std::string&, std::string&) +Status SystemTools::ReadSymlink(std::string const&, std::string&) { - return false; + return Status::Windows(ERROR_NOT_SUPPORTED); } #else -bool SystemTools::ReadSymlink(const std::string& newName, - std::string& origName) +Status SystemTools::ReadSymlink(std::string const& newName, + std::string& origName) { char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1]; int count = static_cast( readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH)); - if (count >= 0) { - // Add null-terminator. - buf[count] = 0; - origName = buf; - return true; - } else { - return false; + if (count < 0) { + return Status::POSIX_errno(); } + // Add null-terminator. + buf[count] = 0; + origName = buf; + return Status::Success(); } #endif -int SystemTools::ChangeDirectory(const std::string& dir) +Status SystemTools::ChangeDirectory(std::string const& dir) { - return Chdir(dir); + if (Chdir(dir) < 0) { + return Status::POSIX_errno(); + } + return Status::Success(); } std::string SystemTools::GetCurrentWorkingDirectory() @@ -3957,7 +3988,8 @@ bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) return false; } -bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath) +Status SystemTools::GetShortPath(std::string const& path, + std::string& shortPath) { #if defined(_WIN32) && !defined(__CYGWIN__) std::string tempPath = path; // create a buffer @@ -3977,14 +4009,14 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath) } if (ret == 0) { - return false; + return Status::Windows_GetLastError(); } else { shortPath = Encoding::ToNarrow(&buffer[0]); - return true; + return Status::Success(); } #else shortPath = path; - return true; + return Status::Success(); #endif } @@ -4085,21 +4117,21 @@ int SystemTools::GetTerminalWidth() return width; } -bool SystemTools::GetPermissions(const char* file, mode_t& mode) +Status SystemTools::GetPermissions(const char* file, mode_t& mode) { if (!file) { - return false; + return Status::POSIX(EINVAL); } return SystemTools::GetPermissions(std::string(file), mode); } -bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) +Status SystemTools::GetPermissions(std::string const& file, mode_t& mode) { #if defined(_WIN32) DWORD attr = GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str()); if (attr == INVALID_FILE_ATTRIBUTES) { - return false; + return Status::Windows_GetLastError(); } if ((attr & FILE_ATTRIBUTE_READONLY) != 0) { mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)); @@ -4122,27 +4154,27 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) #else struct stat st; if (stat(file.c_str(), &st) < 0) { - return false; + return Status::POSIX_errno(); } mode = st.st_mode; #endif - return true; + return Status::Success(); } -bool SystemTools::SetPermissions(const char* file, mode_t mode, - bool honor_umask) +Status SystemTools::SetPermissions(const char* file, mode_t mode, + bool honor_umask) { if (!file) { - return false; + return Status::POSIX(EINVAL); } return SystemTools::SetPermissions(std::string(file), mode, honor_umask); } -bool SystemTools::SetPermissions(const std::string& file, mode_t mode, - bool honor_umask) +Status SystemTools::SetPermissions(std::string const& file, mode_t mode, + bool honor_umask) { if (!SystemTools::PathExists(file)) { - return false; + return Status::POSIX(ENOENT); } if (honor_umask) { mode_t currentMask = umask(0); @@ -4155,10 +4187,10 @@ bool SystemTools::SetPermissions(const std::string& file, mode_t mode, if (chmod(file.c_str(), mode) < 0) #endif { - return false; + return Status::POSIX_errno(); } - return true; + return Status::Success(); } std::string SystemTools::GetParentDirectory(const std::string& fileOrDir) diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index a7b1288733e..e5d115e0896 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -4,6 +4,7 @@ #define @KWSYS_NAMESPACE@_SystemTools_hxx #include <@KWSYS_NAMESPACE@/Configure.hxx> +#include <@KWSYS_NAMESPACE@/Status.hxx> #include #include @@ -339,7 +340,7 @@ public: /** Change the modification time or create a file */ - static bool Touch(const std::string& filename, bool create); + static Status Touch(std::string const& filename, bool create); /** * Compare file modification times. @@ -347,8 +348,8 @@ public: * When true is returned, result has -1, 0, +1 for * f1 older, same, or newer than f2. */ - static bool FileTimeCompare(const std::string& f1, const std::string& f2, - int* result); + static Status FileTimeCompare(std::string const& f1, std::string const& f2, + int* result); /** * Get the file extension (including ".") needed for an executable @@ -507,7 +508,7 @@ public: * For windows return the short path for the given path, * Unix just a pass through */ - static bool GetShortPath(const std::string& path, std::string& result); + static Status GetShortPath(std::string const& path, std::string& result); /** * Read line from file. Make sure to read a full line and truncates it if @@ -553,16 +554,16 @@ public: * can make a full path even if none of the directories existed * prior to calling this function. */ - static bool MakeDirectory(const char* path, const mode_t* mode = nullptr); - static bool MakeDirectory(const std::string& path, - const mode_t* mode = nullptr); + static Status MakeDirectory(const char* path, const mode_t* mode = nullptr); + static Status MakeDirectory(std::string const& path, + const mode_t* mode = nullptr); /** * Copy the source file to the destination file only * if the two files differ. */ - static bool CopyFileIfDifferent(const std::string& source, - const std::string& destination); + static Status CopyFileIfDifferent(std::string const& source, + std::string const& destination); /** * Compare the contents of two files. Return true if different @@ -580,13 +581,13 @@ public: /** * Blockwise copy source to destination file */ - static bool CopyFileContentBlockwise(const std::string& source, - const std::string& destination); + static Status CopyFileContentBlockwise(std::string const& source, + std::string const& destination); /** * Clone the source file to the destination file */ - static bool CloneFileContent(const std::string& source, - const std::string& destination); + static Status CloneFileContent(std::string const& source, + std::string const& destination); /** * Return true if the two files are the same file @@ -596,16 +597,16 @@ public: /** * Copy a file. */ - static bool CopyFileAlways(const std::string& source, - const std::string& destination); + static Status CopyFileAlways(std::string const& source, + std::string const& destination); /** * Copy a file. If the "always" argument is true the file is always * copied. If it is false, the file is copied only if it is new or * has changed. */ - static bool CopyAFile(const std::string& source, - const std::string& destination, bool always = true); + static Status CopyAFile(std::string const& source, + std::string const& destination, bool always = true); /** * Copy content directory to another directory with all files and @@ -613,19 +614,19 @@ public: * always copied. If it is false, only files that have changed or * are new are copied. */ - static bool CopyADirectory(const std::string& source, - const std::string& destination, - bool always = true); + static Status CopyADirectory(std::string const& source, + std::string const& destination, + bool always = true); /** * Remove a file */ - static bool RemoveFile(const std::string& source); + static Status RemoveFile(std::string const& source); /** * Remove a directory */ - static bool RemoveADirectory(const std::string& source); + static Status RemoveADirectory(std::string const& source); /** * Get the maximum full file path length @@ -719,14 +720,14 @@ public: * Create a symbolic link if the platform supports it. Returns whether * creation succeeded. */ - static bool CreateSymlink(const std::string& origName, - const std::string& newName); + static Status CreateSymlink(std::string const& origName, + std::string const& newName); /** * Read the contents of a symbolic link. Returns whether reading * succeeded. */ - static bool ReadSymlink(const std::string& newName, std::string& origName); + static Status ReadSymlink(std::string const& newName, std::string& origName); /** * Try to locate the file 'filename' in the directory 'dir'. @@ -776,12 +777,12 @@ public: * WARNING: A non-thread-safe method is currently used to get the umask * if a honor_umask parameter is set to true. */ - static bool GetPermissions(const char* file, mode_t& mode); - static bool GetPermissions(const std::string& file, mode_t& mode); - static bool SetPermissions(const char* file, mode_t mode, - bool honor_umask = false); - static bool SetPermissions(const std::string& file, mode_t mode, - bool honor_umask = false); + static Status GetPermissions(const char* file, mode_t& mode); + static Status GetPermissions(std::string const& file, mode_t& mode); + static Status SetPermissions(const char* file, mode_t mode, + bool honor_umask = false); + static Status SetPermissions(std::string const& file, mode_t mode, + bool honor_umask = false); /** ----------------------------------------------------------------- * Time Manipulation Routines @@ -878,7 +879,7 @@ public: /** * Change directory to the directory specified */ - static int ChangeDirectory(const std::string& dir); + static Status ChangeDirectory(std::string const& dir); /** * Get the result of strerror(errno) diff --git a/testDirectory.cxx b/testDirectory.cxx index eb3ca3254c7..06a22dc4753 100644 --- a/testDirectory.cxx +++ b/testDirectory.cxx @@ -88,7 +88,7 @@ int _nonExistentDirectoryTest() errorMessage = "foo"; // Increment res failure if directory lists - res += testdir.Load(testdirpath, &errorMessage); + res += testdir.Load(testdirpath, &errorMessage) ? 1 : 0; #if !defined(_WIN32) || defined(__CYGWIN__) // Increment res failure if errorMessage is unmodified res += (errorMessage == "foo"); @@ -120,7 +120,7 @@ int _copyDirectoryTest() std::cerr << destination << " shouldn't exist before test" << std::endl; return 2; } - const bool copysuccess = SystemTools::CopyADirectory(source, destination); + const Status copysuccess = SystemTools::CopyADirectory(source, destination); const bool destinationexists = SystemTools::PathExists(destination); if (copysuccess) { std::cerr << "CopyADirectory should have returned false" << std::endl; diff --git a/testStatus.cxx b/testStatus.cxx new file mode 100644 index 00000000000..f85ef422dbf --- /dev/null +++ b/testStatus.cxx @@ -0,0 +1,117 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying +file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Status.hxx) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Status.hxx.in" +#endif + +#include +#include + +#ifdef _WIN32 +# include +#endif + +int testStatus(int, char* []) +{ + bool res = true; + { + kwsys::Status status; + if (status.GetKind() != kwsys::Status::Kind::Success) { + std::cerr << "Status default constructor does not produce Success\n"; + res = false; + } + + status = kwsys::Status::Success(); + if (status.GetKind() != kwsys::Status::Kind::Success) { + std::cerr << "Status Success constructor does not produce Success\n"; + res = false; + } + if (!status) { + std::cerr << "Status Success kind is not true\n"; + res = false; + } + if (status.GetPOSIX() != 0) { + std::cerr << "Status Success kind does not return POSIX 0\n"; + res = false; + } +#ifdef _WIN32 + if (status.GetWindows() != 0) { + std::cerr << "Status Success kind does not return Windows 0\n"; + res = false; + } +#endif + if (status.GetString() != "Success") { + std::cerr << "Status Success kind does not return \"Success\" string\n"; + res = false; + } + + status = kwsys::Status::POSIX(EINVAL); + if (status.GetKind() != kwsys::Status::Kind::POSIX) { + std::cerr << "Status POSIX constructor does not produce POSIX\n"; + res = false; + } + if (status) { + std::cerr << "Status POSIX kind is not false\n"; + res = false; + } + if (status.GetPOSIX() != EINVAL) { + std::cerr << "Status POSIX kind does not preserve POSIX value\n"; + res = false; + } +#ifdef _WIN32 + if (status.GetWindows() != 0) { + std::cerr << "Status POSIX kind does not return Windows 0\n"; + res = false; + } +#endif + if (status.GetString().empty()) { + std::cerr << "Status POSIX kind returns empty string\n"; + res = false; + } + errno = ENOENT; + status = kwsys::Status::POSIX_errno(); + if (status.GetPOSIX() != ENOENT) { + std::cerr << "Status POSIX_errno did not use errno\n"; + res = false; + } + errno = 0; + +#ifdef _WIN32 + status = kwsys::Status::Windows(ERROR_INVALID_PARAMETER); + if (status.GetKind() != kwsys::Status::Kind::Windows) { + std::cerr << "Status Windows constructor does not produce Windows\n"; + res = false; + } + if (status) { + std::cerr << "Status Windows kind is not false\n"; + res = false; + } + if (status.GetWindows() != ERROR_INVALID_PARAMETER) { + std::cerr << "Status Windows kind does not preserve Windows value\n"; + res = false; + } + if (status.GetPOSIX() != 0) { + std::cerr << "Status Windows kind does not return POSIX 0\n"; + res = false; + } + if (status.GetString().empty()) { + std::cerr << "Status Windows kind returns empty string\n"; + res = false; + } + + SetLastError(ERROR_FILE_NOT_FOUND); + status = kwsys::Status::Windows_GetLastError(); + if (status.GetWindows() != ERROR_FILE_NOT_FOUND) { + std::cerr << "Status Windows_GetLastError did not use GetLastError()\n"; + res = false; + } + SetLastError(ERROR_SUCCESS); +#endif + } + return res ? 0 : 1; +} From ec1b6157cbfefdcac5c971021a5700dd80318a09 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 12:15:54 -0400 Subject: [PATCH 0236/1519] Update CMake code using KWSys to account for Status return values KWSys as of 2021-04-14 changed the return type of `SystemTools` operations from `bool` to `Status`. Update our call sites. This may improve error reporting accuracy in a few places. --- Source/CPack/cmCPackSTGZGenerator.cxx | 13 +++++++------ Source/CTest/cmCTestScriptHandler.cxx | 2 +- Source/CTest/cmCTestTestHandler.cxx | 2 +- Source/cmCTest.cxx | 6 +++--- Source/cmConditionEvaluator.cxx | 4 ++-- Source/cmFileCommand.cxx | 9 ++++++--- Source/cmQtAutoGenerator.cxx | 2 +- Source/cmSystemTools.cxx | 4 ++-- Source/cmSystemTools.h | 1 + Source/cmWorkingDirectory.cxx | 2 +- Source/cmcmd.cxx | 2 +- bootstrap | 2 ++ 12 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 3e36e8cc18e..ad0a3e21b05 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -51,15 +51,16 @@ int cmCPackSTGZGenerator::PackageFiles() * so we must iterate over generated packages. */ for (std::string const& pfn : this->packageFileNames) { - retval &= cmSystemTools::SetPermissions(pfn.c_str(), + retval &= static_cast( + cmSystemTools::SetPermissions(pfn.c_str(), #if defined(_MSC_VER) || defined(__MINGW32__) - S_IREAD | S_IWRITE | S_IEXEC + S_IREAD | S_IWRITE | S_IEXEC #else - S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IWGRP | S_IXGRP | - S_IROTH | S_IWOTH | S_IXOTH + S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | + S_IXOTH #endif - ); + )); } return retval; } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index ff0b179a6da..d2cad3992a7 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -921,7 +921,7 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce( } } - return cmSystemTools::RemoveADirectory(directoryPath); + return static_cast(cmSystemTools::RemoveADirectory(directoryPath)); } cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed() diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 742e78a7a98..db5cb9c2bef 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1881,7 +1881,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() std::string dirName = this->CTest->GetBinaryDir() + "/Testing/Temporary"; cmsys::Directory directory; - if (directory.Load(dirName) == 0) { + if (!directory.Load(dirName)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of " << dirName << std::endl); return; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 0dfd1bd4fa9..643b43f6dd0 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -2842,9 +2841,10 @@ int cmCTest::ExecuteTests() cmCTestLog(this, OUTPUT, "Internal ctest changing into directory: " << workDir << std::endl); - if (cmSystemTools::ChangeDirectory(workDir) != 0) { + cmsys::Status status = cmSystemTools::ChangeDirectory(workDir); + if (!status) { auto msg = "Failed to change working directory to \"" + workDir + - "\" : " + std::strerror(errno) + "\n"; + "\" : " + status.GetString() + "\n"; cmCTestLog(this, ERROR_MESSAGE, msg); return 1; } diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 62bc52691d2..f99592cc092 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -654,10 +654,10 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { int fileIsNewer = 0; - bool success = cmSystemTools::FileTimeCompare( + cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( arg->GetValue(), (argP2)->GetValue(), &fileIsNewer); this->HandleBinaryOp( - (!success || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg, + (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg, newArgs, argP1, argP2); } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index a06ed48627c..26bdedfd948 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2956,9 +2956,12 @@ bool HandleCreateLinkCommand(std::vector const& args, // Check if copy-on-error is enabled in the arguments. if (!completed && arguments.CopyOnError) { - completed = cmsys::SystemTools::CopyFileAlways(fileName, newFileName); - if (!completed) { - result = "Copy failed: " + cmSystemTools::GetLastSystemError(); + cmsys::Status copied = + cmsys::SystemTools::CopyFileAlways(fileName, newFileName); + if (copied) { + completed = true; + } else { + result = "Copy failed: " + copied.GetString(); } } diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 6e88e266f6a..568926e3c5d 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -116,7 +116,7 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename) bool success = true; std::string const dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { - success = cmSystemTools::MakeDirectory(dirName); + success = static_cast(cmSystemTools::MakeDirectory(dirName)); } return success; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 3a438fda4cf..a2a406c2210 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1016,7 +1016,7 @@ cmSystemTools::CopyResult cmSystemTools::CopySingleFile( } mode_t perm = 0; - bool perms = SystemTools::GetPermissions(oldname, perm); + cmsys::Status perms = SystemTools::GetPermissions(oldname, perm); // If files are the same do not copy if (SystemTools::SameFile(oldname, newname)) { @@ -3130,7 +3130,7 @@ bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir) } return false; #else - return cmSystemTools::RemoveADirectory(dir); + return static_cast(cmSystemTools::RemoveADirectory(dir)); #endif } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 562089973af..99f20e0240a 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -12,6 +12,7 @@ #include #include "cmsys/Process.h" +#include "cmsys/Status.hxx" // IWYU pragma: export #include "cmsys/SystemTools.hxx" // IWYU pragma: export #include "cmCryptoHash.h" diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx index 5700b1cc771..12fae1278cd 100644 --- a/Source/cmWorkingDirectory.cxx +++ b/Source/cmWorkingDirectory.cxx @@ -19,7 +19,7 @@ cmWorkingDirectory::~cmWorkingDirectory() bool cmWorkingDirectory::SetDirectory(std::string const& newdir) { - if (cmSystemTools::ChangeDirectory(newdir) == 0) { + if (cmSystemTools::ChangeDirectory(newdir)) { this->ResultCode = 0; return true; } diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 9ba4b93de76..a47eccde4af 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1635,7 +1635,7 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link) cmSystemTools::RemoveFile(link); } #if defined(_WIN32) && !defined(__CYGWIN__) - return cmSystemTools::CopyFileAlways(file, link); + return static_cast(cmSystemTools::CopyFileAlways(file, link)); #else std::string linktext = cmSystemTools::GetFilenameName(file); return cmSystemTools::CreateSymlink(linktext, link); diff --git a/bootstrap b/bootstrap index 768750da20d..2a81ef2c073 100755 --- a/bootstrap +++ b/bootstrap @@ -525,6 +525,7 @@ KWSYS_CXX_SOURCES="\ FStream \ Glob \ RegularExpression \ + Status \ SystemTools" KWSYS_FILES="\ @@ -535,6 +536,7 @@ KWSYS_FILES="\ Glob.hxx \ Process.h \ RegularExpression.hxx \ + Status.hxx \ String.h \ String.hxx \ System.h \ From 3ef5dab010aef5ebab2022021989cb80718d00fc Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 12:20:00 -0400 Subject: [PATCH 0237/1519] cmSystemTools: Simplify using KWSys Status --- Source/cmSystemTools.cxx | 57 ++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index a2a406c2210..2b3266d5feb 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -153,27 +153,6 @@ static int cm_archive_read_open_file(struct archive* a, const char* file, # define environ (*_NSGetEnviron()) #endif -namespace { -void ReportError(std::string* err) -{ - if (!err) { - return; - } -#ifdef _WIN32 - LPSTR message = NULL; - DWORD size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&message, 0, NULL); - *err = std::string(message, size); - LocalFree(message); -#else - *err = strerror(errno); -#endif -} -} - bool cmSystemTools::s_RunCommandHideConsole = false; bool cmSystemTools::s_DisableRunCommandOutput = false; bool cmSystemTools::s_ErrorOccured = false; @@ -1023,16 +1002,24 @@ cmSystemTools::CopyResult cmSystemTools::CopySingleFile( return CopyResult::Success; } - if (!cmsys::SystemTools::CloneFileContent(oldname, newname)) { + cmsys::Status status; + status = cmsys::SystemTools::CloneFileContent(oldname, newname); + if (!status) { // if cloning did not succeed, fall back to blockwise copy - if (!cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname)) { - ReportError(err); - return CopyResult::Failure; + status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname); + } + if (!status) { + if (err) { + *err = status.GetString(); } + return CopyResult::Failure; } if (perms) { - if (!SystemTools::SetPermissions(newname, perm)) { - ReportError(err); + status = SystemTools::SetPermissions(newname, perm); + if (!status) { + if (err) { + *err = status.GetString(); + } return CopyResult::Failure; } } @@ -1090,7 +1077,9 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile( if (replace == Replace::No && move_last_error == ERROR_ALREADY_EXISTS) { return RenameResult::NoReplace; } - ReportError(err); + if (err) { + *err = cmsys::Status::Windows(move_last_error).GetString(); + } return RenameResult::Failure; } @@ -1121,7 +1110,9 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile( if (replace == Replace::No && GetLastError() == ERROR_ALREADY_EXISTS) { return RenameResult::NoReplace; } - ReportError(err); + if (err) { + *err = cmsys::Status::Windows_GetLastError().GetString(); + } return RenameResult::Failure; #else // On UNIX we have OS-provided calls to create 'newname' atomically. @@ -1132,13 +1123,17 @@ cmSystemTools::RenameResult cmSystemTools::RenameFile( if (errno == EEXIST) { return RenameResult::NoReplace; } - ReportError(err); + if (err) { + *err = cmsys::Status::POSIX_errno().GetString(); + } return RenameResult::Failure; } if (rename(oldname.c_str(), newname.c_str()) == 0) { return RenameResult::Success; } - ReportError(err); + if (err) { + *err = cmsys::Status::POSIX_errno().GetString(); + } return RenameResult::Failure; #endif } From 44bcec240bed6980fdc6f38e7238371d7d3c1f1b Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 13:58:47 -0400 Subject: [PATCH 0238/1519] ci: factor out Intel Compiler common configure script Share common content between the intelclassic and inteloneapi variants. --- .gitlab/ci/configure_intelclassic_makefiles.cmake | 2 +- .gitlab/ci/configure_intelcompiler_common.cmake | 1 + .gitlab/ci/configure_inteloneapi_makefiles.cmake | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 .gitlab/ci/configure_intelcompiler_common.cmake diff --git a/.gitlab/ci/configure_intelclassic_makefiles.cmake b/.gitlab/ci/configure_intelclassic_makefiles.cmake index 20863a2fb08..469b8256613 100644 --- a/.gitlab/ci/configure_intelclassic_makefiles.cmake +++ b/.gitlab/ci/configure_intelclassic_makefiles.cmake @@ -1 +1 @@ -include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/configure_intelcompiler_common.cmake") diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake new file mode 100644 index 00000000000..20863a2fb08 --- /dev/null +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/configure_inteloneapi_makefiles.cmake b/.gitlab/ci/configure_inteloneapi_makefiles.cmake index 20863a2fb08..469b8256613 100644 --- a/.gitlab/ci/configure_inteloneapi_makefiles.cmake +++ b/.gitlab/ci/configure_inteloneapi_makefiles.cmake @@ -1 +1 @@ -include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/configure_intelcompiler_common.cmake") From 116edb5c04790e5d9127b5cfb51943eebd5d33d8 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 13:33:42 -0400 Subject: [PATCH 0239/1519] Find{BLAS,LAPACK}: Revert bad refactoring of internal CHECK_*_LIBRARIES Refactoring in commit 4c74c86f40 (FindBLAS/LAPACK: Add support for the Fujitsu SSL2 library, 2021-01-27) was done in order to support calling `find_library` on the dependencies as well as the candidate libraries. However, it broke a few things: * Intel MKL's BLAS/LAPACK are no longer found. We specify their dependencies using `-l...` flags, so we should not try to use `find_library` for them. * The dependencies are repeated because we accumulate them in the `find_library` search loop and then append them at the end too. Revert the incorrect part of the refactoring. Retain the flags part needed for the Fujitsu vendor. Fixes: #22056 --- Modules/FindBLAS.cmake | 16 +++++++++------- Modules/FindLAPACK.cmake | 16 +++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 510f47d3af7..fafbc0f1809 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -236,23 +236,25 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add endif() list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") - foreach(_library ${_list} ${_threadlibs}) + foreach(_library ${_list}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) set(${LIBRARIES} ${${LIBRARIES}} "${_library}") else() - string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") - set(_combined_name ${_combined_name}_${_lib_var}) + set(_combined_name ${_combined_name}_${_library}) + if(NOT "${_threadlibs}" STREQUAL "") + set(_combined_name ${_combined_name}_threadlibs) + endif() if(_libraries_work) - find_library(${_prefix}_${_lib_var}_LIBRARY + find_library(${_prefix}_${_library}_LIBRARY NAMES ${_library} NAMES_PER_DIR PATHS ${_extaddlibdir} PATH_SUFFIXES ${_subdirs} ) - mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY) - set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_lib_var}_LIBRARY}) - set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY}) + mark_as_advanced(${_prefix}_${_library}_LIBRARY) + set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) + set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) endif() endif() endforeach() diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index a5b16ca2291..74e1c5d06c7 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -218,23 +218,25 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a endif() list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") - foreach(_library ${_list} ${_threadlibs}) + foreach(_library ${_list}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) set(${LIBRARIES} ${${LIBRARIES}} "${_library}") else() - string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") - set(_combined_name ${_combined_name}_${_lib_var}) + set(_combined_name ${_combined_name}_${_library}) + if(NOT "${_threadlibs}" STREQUAL "") + set(_combined_name ${_combined_name}_threadlibs) + endif() if(_libraries_work) - find_library(${_prefix}_${_lib_var}_LIBRARY + find_library(${_prefix}_${_library}_LIBRARY NAMES ${_library} NAMES_PER_DIR PATHS ${_extaddlibdir} PATH_SUFFIXES ${_subdirs} ) - mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY) - set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_lib_var}_LIBRARY}) - set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY}) + mark_as_advanced(${_prefix}_${_library}_LIBRARY) + set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) + set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) endif() endif() endforeach() From e4649d1d159de9c1a6f4833d6f9a5a44e5c4781b Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 13:53:03 -0400 Subject: [PATCH 0240/1519] Find{BLAS,LAPACK}: Add test case covering Intel MKL --- .../ci/configure_debian10_aarch64_ninja.cmake | 4 ++-- .gitlab/ci/configure_debian10_ninja.cmake | 4 ++-- .gitlab/ci/configure_fedora33_makefiles.cmake | 4 ++-- .../ci/configure_intelcompiler_common.cmake | 3 +++ Tests/FindBLAS/CMakeLists.txt | 22 ++++++++++--------- Tests/FindBLAS/Test/CMakeLists.txt | 6 +++++ Tests/FindLAPACK/CMakeLists.txt | 22 ++++++++++--------- Tests/FindLAPACK/Test/CMakeLists.txt | 6 +++++ 8 files changed, 45 insertions(+), 26 deletions(-) diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index 1ad3ac4405c..f665f7d20d5 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -1,5 +1,5 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") -set(CMake_TEST_FindBLAS "ON" CACHE BOOL "") +set(CMake_TEST_FindBLAS "All" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -23,7 +23,7 @@ set(CMake_TEST_FindIconv "ON" CACHE BOOL "") set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") -set(CMake_TEST_FindLAPACK "ON" CACHE BOOL "") +set(CMake_TEST_FindLAPACK "All" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index d9253870e80..9de30134280 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -1,5 +1,5 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") -set(CMake_TEST_FindBLAS "ON" CACHE BOOL "") +set(CMake_TEST_FindBLAS "All" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -23,7 +23,7 @@ set(CMake_TEST_FindIconv "ON" CACHE BOOL "") set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") -set(CMake_TEST_FindLAPACK "ON" CACHE BOOL "") +set(CMake_TEST_FindLAPACK "All" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora33_makefiles.cmake b/.gitlab/ci/configure_fedora33_makefiles.cmake index 882ffcdf947..4143134800b 100644 --- a/.gitlab/ci/configure_fedora33_makefiles.cmake +++ b/.gitlab/ci/configure_fedora33_makefiles.cmake @@ -1,5 +1,5 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") -set(CMake_TEST_FindBLAS "ON" CACHE BOOL "") +set(CMake_TEST_FindBLAS "All" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -23,7 +23,7 @@ set(CMake_TEST_FindIconv "ON" CACHE BOOL "") set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") -set(CMake_TEST_FindLAPACK "ON" CACHE BOOL "") +set(CMake_TEST_FindLAPACK "All" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake index 20863a2fb08..be3d15b6d1b 100644 --- a/.gitlab/ci/configure_intelcompiler_common.cmake +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -1 +1,4 @@ +set(CMake_TEST_FindBLAS "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindLAPACK "Intel10_64lp" CACHE STRING "") + include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt index 667195dd967..47ec5681408 100644 --- a/Tests/FindBLAS/CMakeLists.txt +++ b/Tests/FindBLAS/CMakeLists.txt @@ -1,10 +1,12 @@ -add_test(NAME FindBLAS.Test COMMAND - ${CMAKE_CTEST_COMMAND} -C $ - --build-and-test - "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" - "${CMake_BINARY_DIR}/Tests/FindBLAS/Test" - ${build_generator_args} - --build-project TestFindBLAS - --build-options ${build_options} - --test-command ${CMAKE_CTEST_COMMAND} -V -C $ - ) +foreach(vendor IN LISTS CMake_TEST_FindBLAS) + add_test(NAME FindBLAS.Test_${vendor} COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" + "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${vendor}" + ${build_generator_args} + --build-project TestFindBLAS + --build-options ${build_options} -DBLA_VENDOR=${vendor} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +endforeach() diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt index 59418f34a46..1bebf8e99c4 100644 --- a/Tests/FindBLAS/Test/CMakeLists.txt +++ b/Tests/FindBLAS/Test/CMakeLists.txt @@ -11,3 +11,9 @@ add_test(NAME test_tgt COMMAND test_tgt) add_executable(test_var main.c) target_link_libraries(test_var PRIVATE ${BLAS_LIBRARIES}) add_test(NAME test_var COMMAND test_var) + +if(BLA_VENDOR STREQUAL "Intel10_64lp") + if(NOT BLAS_LIBRARIES MATCHES "^[^;]*mkl_intel_lp64") + message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_lp64:\n ${BLAS_LIBRARIES}") + endif() +endif() diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt index 2081d592499..5e2ea7a6a3c 100644 --- a/Tests/FindLAPACK/CMakeLists.txt +++ b/Tests/FindLAPACK/CMakeLists.txt @@ -1,10 +1,12 @@ -add_test(NAME FindLAPACK.Test COMMAND - ${CMAKE_CTEST_COMMAND} -C $ - --build-and-test - "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" - "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test" - ${build_generator_args} - --build-project TestFindLAPACK - --build-options ${build_options} - --test-command ${CMAKE_CTEST_COMMAND} -V -C $ - ) +foreach(vendor IN LISTS CMake_TEST_FindLAPACK) + add_test(NAME FindLAPACK.Test_${vendor} COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" + "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${vendor}" + ${build_generator_args} + --build-project TestFindLAPACK + --build-options ${build_options} -DBLA_VENDOR=${vendor} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +endforeach() diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt index 8afa36a122d..67fb9bd6d00 100644 --- a/Tests/FindLAPACK/Test/CMakeLists.txt +++ b/Tests/FindLAPACK/Test/CMakeLists.txt @@ -11,3 +11,9 @@ add_test(NAME test_tgt COMMAND test_tgt) add_executable(test_var main.c) target_link_libraries(test_var PRIVATE ${LAPACK_LIBRARIES}) add_test(NAME test_var COMMAND test_var) + +if(BLA_VENDOR STREQUAL "Intel10_64lp") + if(NOT LAPACK_LIBRARIES MATCHES "^[^;]*mkl_intel_lp64") + message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_lp64:\n ${LAPACK_LIBRARIES}") + endif() +endif() From d248401d12a4766dad7ddd69ee3f2947960f6f5f Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 14:11:39 -0400 Subject: [PATCH 0241/1519] Find{BLAS,LAPACK}: Simplify appending to list of libraries --- Modules/FindBLAS.cmake | 6 +++--- Modules/FindLAPACK.cmake | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index fafbc0f1809..84d707489fe 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -239,7 +239,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add foreach(_library ${_list}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) - set(${LIBRARIES} ${${LIBRARIES}} "${_library}") + list(APPEND ${LIBRARIES} "${_library}") else() set(_combined_name ${_combined_name}_${_library}) if(NOT "${_threadlibs}" STREQUAL "") @@ -253,7 +253,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add PATH_SUFFIXES ${_subdirs} ) mark_as_advanced(${_prefix}_${_library}_LIBRARY) - set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) + list(APPEND ${LIBRARIES} ${${_prefix}_${_library}_LIBRARY}) set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) endif() endif() @@ -279,7 +279,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add if("${_list}" STREQUAL "") set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") else() - set(${LIBRARIES} ${${LIBRARIES}} ${_threadlibs}) + list(APPEND ${LIBRARIES} ${_threadlibs}) endif() else() set(${LIBRARIES} FALSE) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 74e1c5d06c7..ea49629c9ae 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -221,7 +221,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a foreach(_library ${_list}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) - set(${LIBRARIES} ${${LIBRARIES}} "${_library}") + list(APPEND ${LIBRARIES} "${_library}") else() set(_combined_name ${_combined_name}_${_library}) if(NOT "${_threadlibs}" STREQUAL "") @@ -235,7 +235,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a PATH_SUFFIXES ${_subdirs} ) mark_as_advanced(${_prefix}_${_library}_LIBRARY) - set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) + list(APPEND ${LIBRARIES} ${${_prefix}_${_library}_LIBRARY}) set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) endif() endif() @@ -262,7 +262,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a if("${_list}${_blas}" STREQUAL "") set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") else() - set(${LIBRARIES} ${${LIBRARIES}} ${_blas} ${_threadlibs}) + list(APPEND ${LIBRARIES} ${_blas} ${_threadlibs}) endif() else() set(${LIBRARIES} FALSE) From a5a6ac7033f107626e76eb09ccd86bf49ccdbecd Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 14:12:33 -0400 Subject: [PATCH 0242/1519] Find{BLAS,LAPACK}: Clarify name of internal argument for dependencies --- Modules/FindBLAS.cmake | 10 +++++----- Modules/FindLAPACK.cmake | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 84d707489fe..a61d71fd052 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -208,7 +208,7 @@ endif() # TODO: move this stuff to a separate module -macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _addlibdir _subdirs) +macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs) # This macro checks for the existence of the combination of fortran libraries # given by _list. If the combination is found, this macro checks (using the # Check_Fortran_Function_Exists macro) whether can link against that library @@ -242,8 +242,8 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add list(APPEND ${LIBRARIES} "${_library}") else() set(_combined_name ${_combined_name}_${_library}) - if(NOT "${_threadlibs}" STREQUAL "") - set(_combined_name ${_combined_name}_threadlibs) + if(NOT "${_deps}" STREQUAL "") + set(_combined_name ${_combined_name}_deps) endif() if(_libraries_work) find_library(${_prefix}_${_library}_LIBRARY @@ -265,7 +265,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add endforeach() if(_libraries_work) # Test this combination of libraries. - set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_threadlibs}) + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_deps}) if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -279,7 +279,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _add if("${_list}" STREQUAL "") set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") else() - list(APPEND ${LIBRARIES} ${_threadlibs}) + list(APPEND ${LIBRARIES} ${_deps}) endif() else() set(${LIBRARIES} FALSE) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index ea49629c9ae..239a4387261 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -190,7 +190,7 @@ endmacro() # TODO: move this stuff to a separate module -macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _addlibdir _subdirs _blas) +macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs _blas) # This macro checks for the existence of the combination of fortran libraries # given by _list. If the combination is found, this macro checks (using the # Check_Fortran_Function_Exists macro) whether can link against that library @@ -224,8 +224,8 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a list(APPEND ${LIBRARIES} "${_library}") else() set(_combined_name ${_combined_name}_${_library}) - if(NOT "${_threadlibs}" STREQUAL "") - set(_combined_name ${_combined_name}_threadlibs) + if(NOT "${_deps}" STREQUAL "") + set(_combined_name ${_combined_name}_deps) endif() if(_libraries_work) find_library(${_prefix}_${_library}_LIBRARY @@ -248,7 +248,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a endforeach() if(_libraries_work) # Test this combination of libraries. - set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas} ${_threadlibs}) + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas} ${_deps}) if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -262,7 +262,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _threadlibs _a if("${_list}${_blas}" STREQUAL "") set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") else() - list(APPEND ${LIBRARIES} ${_blas} ${_threadlibs}) + list(APPEND ${LIBRARIES} ${_blas} ${_deps}) endif() else() set(${LIBRARIES} FALSE) From a57c4eef76d623078fe7ff718951a71da000a499 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 14:14:46 -0400 Subject: [PATCH 0243/1519] Find{BLAS,LAPACK}: Convert internal CHECK_*_LIBRARIES to functions --- Modules/FindBLAS.cmake | 37 +++++++++++++++-------------------- Modules/FindLAPACK.cmake | 42 +++++++++++++++------------------------- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index a61d71fd052..0ad5d8c551e 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -208,22 +208,16 @@ endif() # TODO: move this stuff to a separate module -macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs) - # This macro checks for the existence of the combination of fortran libraries - # given by _list. If the combination is found, this macro checks (using the - # Check_Fortran_Function_Exists macro) whether can link against that library - # combination using the name of a routine given by _name using the linker - # flags given by _flags. If the combination of libraries is found and passes - # the link test, LIBRARIES is set to the list of complete library paths that - # have been found. Otherwise, LIBRARIES is set to FALSE. - - # N.B. _prefix is the prefix applied to the names of all cached variables that - # are generated internally and marked advanced by this macro. - # _addlibdir is a list of additional search paths. _subdirs is a list of path - # suffixes to be used by find_library(). +function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs) + # This function checks for the existence of the combination of libraries + # given by _list. If the combination is found, this checks whether can link + # against that library combination using the name of a routine given by _name + # using the linker flags given by _flags. If the combination of libraries is + # found and passes the link test, ${LIBRARIES} is set to the list of complete + # library paths that have been found. Otherwise, ${LIBRARIES} is set to FALSE. set(_libraries_work TRUE) - set(${LIBRARIES}) + set(_libraries) set(_combined_name) set(_extaddlibdir "${_addlibdir}") @@ -239,7 +233,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir foreach(_library ${_list}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) - list(APPEND ${LIBRARIES} "${_library}") + list(APPEND _libraries "${_library}") else() set(_combined_name ${_combined_name}_${_library}) if(NOT "${_deps}" STREQUAL "") @@ -253,7 +247,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir PATH_SUFFIXES ${_subdirs} ) mark_as_advanced(${_prefix}_${_library}_LIBRARY) - list(APPEND ${LIBRARIES} ${${_prefix}_${_library}_LIBRARY}) + list(APPEND _libraries ${${_prefix}_${_library}_LIBRARY}) set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) endif() endif() @@ -265,7 +259,7 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir endforeach() if(_libraries_work) # Test this combination of libraries. - set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_deps}) + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_deps}) if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -277,14 +271,15 @@ macro(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir if(_libraries_work) if("${_list}" STREQUAL "") - set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") + set(_libraries "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") else() - list(APPEND ${LIBRARIES} ${_deps}) + list(APPEND _libraries ${_deps}) endif() else() - set(${LIBRARIES} FALSE) + set(_libraries FALSE) endif() -endmacro() + set(${LIBRARIES} "${_libraries}" PARENT_SCOPE) +endfunction() set(BLAS_LINKER_FLAGS) set(BLAS_LIBRARIES) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 239a4387261..2c74c6e5d18 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -190,22 +190,16 @@ endmacro() # TODO: move this stuff to a separate module -macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs _blas) - # This macro checks for the existence of the combination of fortran libraries - # given by _list. If the combination is found, this macro checks (using the - # Check_Fortran_Function_Exists macro) whether can link against that library - # combination using the name of a routine given by _name using the linker - # flags given by _flags. If the combination of libraries is found and passes - # the link test, LIBRARIES is set to the list of complete library paths that - # have been found. Otherwise, LIBRARIES is set to FALSE. - - # N.B. _prefix is the prefix applied to the names of all cached variables that - # are generated internally and marked advanced by this macro. - # _addlibdir is a list of additional search paths. _subdirs is a list of path - # suffixes to be used by find_library(). +function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs _blas) + # This function checks for the existence of the combination of libraries + # given by _list. If the combination is found, this checks whether can link + # against that library combination using the name of a routine given by _name + # using the linker flags given by _flags. If the combination of libraries is + # found and passes the link test, ${LIBRARIES} is set to the list of complete + # library paths that have been found. Otherwise, ${LIBRARIES} is set to FALSE. set(_libraries_work TRUE) - set(${LIBRARIES}) + set(_libraries) set(_combined_name) set(_extaddlibdir "${_addlibdir}") @@ -221,7 +215,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibd foreach(_library ${_list}) if(_library MATCHES "^-Wl,--(start|end)-group$") # Respect linker flags like --start/end-group (required by MKL) - list(APPEND ${LIBRARIES} "${_library}") + list(APPEND _libraries "${_library}") else() set(_combined_name ${_combined_name}_${_library}) if(NOT "${_deps}" STREQUAL "") @@ -235,12 +229,11 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibd PATH_SUFFIXES ${_subdirs} ) mark_as_advanced(${_prefix}_${_library}_LIBRARY) - list(APPEND ${LIBRARIES} ${${_prefix}_${_library}_LIBRARY}) + list(APPEND _libraries ${${_prefix}_${_library}_LIBRARY}) set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) endif() endif() endforeach() - unset(_library) foreach(_flag ${_flags}) string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}") @@ -248,7 +241,7 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibd endforeach() if(_libraries_work) # Test this combination of libraries. - set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas} ${_deps}) + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_blas} ${_deps}) if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -260,18 +253,15 @@ macro(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibd if(_libraries_work) if("${_list}${_blas}" STREQUAL "") - set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") + set(_libraries "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") else() - list(APPEND ${LIBRARIES} ${_blas} ${_deps}) + list(APPEND _libraries ${_blas} ${_deps}) endif() else() - set(${LIBRARIES} FALSE) + set(_libraries FALSE) endif() - - unset(_extaddlibdir) - unset(_libraries_work) - unset(_combined_name) -endmacro() + set(${LIBRARIES} "${_libraries}" PARENT_SCOPE) +endfunction() macro(_lapack_find_dependency dep) set(_lapack_quiet_arg) From 98ef6632d9f7de15472246ccde76a749be0d37ca Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 14:18:25 -0400 Subject: [PATCH 0244/1519] Find{BLAS,LAPACK}: Generalize recognition of dependencies as link flags --- Modules/FindBLAS.cmake | 4 ++-- Modules/FindLAPACK.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 0ad5d8c551e..61e92c985dc 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -231,8 +231,8 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") foreach(_library ${_list}) - if(_library MATCHES "^-Wl,--(start|end)-group$") - # Respect linker flags like --start/end-group (required by MKL) + if(_library MATCHES "^-") + # Respect linker flags as-is (required by MKL) list(APPEND _libraries "${_library}") else() set(_combined_name ${_combined_name}_${_library}) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 2c74c6e5d18..11bd4118556 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -213,8 +213,8 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl list(APPEND _extaddlibdir "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") foreach(_library ${_list}) - if(_library MATCHES "^-Wl,--(start|end)-group$") - # Respect linker flags like --start/end-group (required by MKL) + if(_library MATCHES "^-") + # Respect linker flags as-is (required by MKL) list(APPEND _libraries "${_library}") else() set(_combined_name ${_combined_name}_${_library}) From dcd604ee621e191acf9e91faab8e47507184d7e9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Apr 2021 14:46:49 -0400 Subject: [PATCH 0245/1519] Find{BLAS,LAPACK}: Make library variable names more robust --- Modules/FindBLAS.cmake | 11 ++++++----- Modules/FindLAPACK.cmake | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 61e92c985dc..c23e41bac88 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -235,20 +235,21 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib # Respect linker flags as-is (required by MKL) list(APPEND _libraries "${_library}") else() - set(_combined_name ${_combined_name}_${_library}) + string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") + set(_combined_name ${_combined_name}_${_lib_var}) if(NOT "${_deps}" STREQUAL "") set(_combined_name ${_combined_name}_deps) endif() if(_libraries_work) - find_library(${_prefix}_${_library}_LIBRARY + find_library(${_prefix}_${_lib_var}_LIBRARY NAMES ${_library} NAMES_PER_DIR PATHS ${_extaddlibdir} PATH_SUFFIXES ${_subdirs} ) - mark_as_advanced(${_prefix}_${_library}_LIBRARY) - list(APPEND _libraries ${${_prefix}_${_library}_LIBRARY}) - set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) + mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY) + list(APPEND _libraries ${${_prefix}_${_lib_var}_LIBRARY}) + set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY}) endif() endif() endforeach() diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 11bd4118556..d89c40d0c4d 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -217,20 +217,21 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl # Respect linker flags as-is (required by MKL) list(APPEND _libraries "${_library}") else() - set(_combined_name ${_combined_name}_${_library}) + string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") + set(_combined_name ${_combined_name}_${_lib_var}) if(NOT "${_deps}" STREQUAL "") set(_combined_name ${_combined_name}_deps) endif() if(_libraries_work) - find_library(${_prefix}_${_library}_LIBRARY + find_library(${_prefix}_${_lib_var}_LIBRARY NAMES ${_library} NAMES_PER_DIR PATHS ${_extaddlibdir} PATH_SUFFIXES ${_subdirs} ) - mark_as_advanced(${_prefix}_${_library}_LIBRARY) - list(APPEND _libraries ${${_prefix}_${_library}_LIBRARY}) - set(_libraries_work ${${_prefix}_${_library}_LIBRARY}) + mark_as_advanced(${_prefix}_${_lib_var}_LIBRARY) + list(APPEND _libraries ${${_prefix}_${_lib_var}_LIBRARY}) + set(_libraries_work ${${_prefix}_${_lib_var}_LIBRARY}) endif() endif() endforeach() From ec78e86cc868ffb39f144dd1c2ae29552413f65d Mon Sep 17 00:00:00 2001 From: Paul Zehner Date: Fri, 9 Apr 2021 19:25:53 +0900 Subject: [PATCH 0246/1519] FujitsuClang: Use GNU-like command-line --- Modules/CMakeDetermineCompilerId.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index d7b7f26d16b..519fe6baa32 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -223,6 +223,8 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) else() set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "GNU") endif() + elseif("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xFujitsuClang") + set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "GNU") else() set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "") endif() From cc0d2004b208d893c20f243ed83391e344589226 Mon Sep 17 00:00:00 2001 From: Paul Zehner Date: Fri, 9 Apr 2021 19:28:08 +0900 Subject: [PATCH 0247/1519] Fujitsu: Fix C90 standard flags Fix typos from commit 3c867cff4a (Fujitsu: Add support for the Fujitsu compiler in Trad mode, 2020-12-22). --- Modules/Compiler/Fujitsu-C.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Compiler/Fujitsu-C.cmake b/Modules/Compiler/Fujitsu-C.cmake index 0e0f1dc0e21..dd31e43802e 100644 --- a/Modules/Compiler/Fujitsu-C.cmake +++ b/Modules/Compiler/Fujitsu-C.cmake @@ -4,9 +4,9 @@ include(Compiler/Fujitsu) __compiler_fujitsu(C) if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4) - set(CMAKE_C89_STANDARD_COMPILE_OPTION -std=c89) - set(CMAKE_C89_EXTENSION_COMPILE_OPTION -std=gnu89) - set(CMAKE_C89_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C90_STANDARD_COMPILE_OPTION -std=c89) + set(CMAKE_C90_EXTENSION_COMPILE_OPTION -std=gnu89) + set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C99_STANDARD_COMPILE_OPTION -std=c99) set(CMAKE_C99_EXTENSION_COMPILE_OPTION -std=gnu99) From 498b916cdd96330baa33bc10667b43cbb78674d4 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 15 Apr 2021 00:04:10 -0400 Subject: [PATCH 0248/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8930a5fffd0..14ed1827079 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210414) +set(CMake_VERSION_PATCH 20210415) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 13838bbb36dbfeb36243d661378732672477ac8a Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 15 Apr 2021 10:12:15 -0400 Subject: [PATCH 0249/1519] CMAKE_TOOLCHAIN_FILE: Document relative path behavior --- Help/variable/CMAKE_TOOLCHAIN_FILE.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst index 168ee74c756..423da9cd2d7 100644 --- a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst +++ b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst @@ -7,3 +7,6 @@ This variable is specified on the command line when cross-compiling with CMake. It is the path to a file which is read early in the CMake run and which specifies locations for compilers and toolchain utilities, and other target platform and compiler related information. + +Relative paths are allowed and are interpreted first as relative to the +build directory, and if not found, relative to the soruce directory. From d5c3e4ac326328dd4ca48b12b27b11ea19d87363 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 7 Apr 2021 14:24:14 -0400 Subject: [PATCH 0250/1519] cmake: add support for --toolchain command argument --- Help/manual/OPTIONS_BUILD.txt | 4 ++++ Help/manual/cmake-toolchains.7.rst | 4 ++-- Help/release/dev/cmake-toolchain-command.rst | 5 ++++ Source/cmake.cxx | 14 +++++++++++ Source/cmake.h | 2 ++ Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 24 ++++++++++++++++++- .../CommandLine/Toolchain/CMakeLists.txt | 3 +++ .../CommandLine/Toolchain/toolchain.cmake | 2 ++ .../CommandLine/toolchain-no-arg-result.txt | 1 + .../CommandLine/toolchain-no-arg-stderr.txt | 1 + .../toolchain-valid-abs-path-result.txt | 1 + .../toolchain-valid-abs-path-stderr.txt | 1 + .../toolchain-valid-rel-build-path-result.txt | 1 + .../toolchain-valid-rel-build-path-stderr.txt | 1 + .../toolchain-valid-rel-src-path-result.txt | 1 + .../toolchain-valid-rel-src-path-stderr.txt | 1 + 16 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 Help/release/dev/cmake-toolchain-command.rst create mode 100644 Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt create mode 100644 Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake create mode 100644 Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt create mode 100644 Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index c4f9be8a98c..c4f83f7b630 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -76,6 +76,10 @@ native build system to choose a compiler or SDK. See the :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. +``--toolchain `` + Specify the cross compiling toolchain file, equivalant to setting + :variable:`CMAKE_TOOLCHAIN_FILE` variable. + ``--install-prefix `` Specify the installation directory, used by the :variable:`CMAKE_INSTALL_PREFIX` variable. Must be an absolute path. diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst index 1ededee1899..a94131049d0 100644 --- a/Help/manual/cmake-toolchains.7.rst +++ b/Help/manual/cmake-toolchains.7.rst @@ -96,8 +96,8 @@ Cross Compiling =============== If :manual:`cmake(1)` is invoked with the command line parameter -``-DCMAKE_TOOLCHAIN_FILE=path/to/file``, the file will be loaded early to set -values for the compilers. +``--toolchain path/to/file`` or ``-DCMAKE_TOOLCHAIN_FILE=path/to/file``, the +file will be loaded early to set values for the compilers. The :variable:`CMAKE_CROSSCOMPILING` variable is set to true when CMake is cross-compiling. diff --git a/Help/release/dev/cmake-toolchain-command.rst b/Help/release/dev/cmake-toolchain-command.rst new file mode 100644 index 00000000000..111ca49a5f3 --- /dev/null +++ b/Help/release/dev/cmake-toolchain-command.rst @@ -0,0 +1,5 @@ +cmake-toolchain-command +---------------------------- + +* The :manual:`cmake(1)` command gained the ``--toolchain `` + command line option to specify a toolchain file. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a04338fec8a..9191abd0834 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -509,6 +509,16 @@ bool cmake::SetCacheArgs(const std::vector& args) return false; }; + auto ToolchainLambda = [&](std::string const& path, cmake* state) -> bool { + const std::string var = "CMAKE_TOOLCHAIN_FILE"; + cmStateEnums::CacheEntryType type = cmStateEnums::FILEPATH; +#ifndef CMAKE_BOOTSTRAP + state->UnprocessedPresetVariables.erase(var); +#endif + state->ProcessCacheArg(var, path, type); + return true; + }; + std::vector arguments = { CommandArgument{ "-D", "-D must be followed with VAR=VALUE.", CommandArgument::Values::One, DefineLambda }, @@ -530,6 +540,8 @@ bool cmake::SetCacheArgs(const std::vector& args) CommandArgument{ "-P", "-P must be followed by a file name.", CommandArgument::Values::One, ScriptLambda }, + CommandArgument{ "--toolchain", "No file specified for --toolchain", + CommandArgument::Values::One, ToolchainLambda }, CommandArgument{ "--install-prefix", "No install directory specified for --install-prefix", CommandArgument::Values::One, PrefixLambda }, @@ -835,6 +847,8 @@ void cmake::SetArgs(const std::vector& args) CommandArgument::Values::One, PlatformLambda }, CommandArgument{ "-T", "No toolset specified for -T", CommandArgument::Values::One, ToolsetLamda }, + CommandArgument{ "--toolchain", "No file specified for --toolchain", + CommandArgument::Values::One, IgnoreAndTrueLambda }, CommandArgument{ "--install-prefix", "No install directory specified for --install-prefix", CommandArgument::Values::One, IgnoreAndTrueLambda }, diff --git a/Source/cmake.h b/Source/cmake.h index ab2ed21a9c6..9b29098ff6d 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -712,6 +712,8 @@ class cmake "Specify toolset name if supported by generator." }, \ { "-A ", \ "Specify platform name if supported by generator." }, \ + { "--toolchain ", \ + "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." }, \ { "--install-prefix ", \ "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \ { "-Wdev", "Enable developer warnings." }, \ diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index c497472a506..bf5a96e54b5 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -61,7 +61,6 @@ run_cmake_command(build-bad-dir run_cmake_command(build-bad-generator ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator) - run_cmake_command(install-prefix-no-arg ${CMAKE_COMMAND} -B DummyBuildDir --install-prefix) run_cmake_command(install-no-dir @@ -153,6 +152,29 @@ project(ExplicitDirsMissing LANGUAGES NONE) endfunction() run_ExplicitDirs() +function(run_Toolchain) + set(RunCMake_TEST_NO_SOURCE_DIR 1) + set(source_dir ${RunCMake_SOURCE_DIR}/Toolchain) + + run_cmake_with_options(toolchain-no-arg -S ${source_dir} --toolchain=) + run_cmake_with_options(toolchain-valid-abs-path -S ${source_dir} --toolchain "${source_dir}/toolchain.cmake") + run_cmake_with_options(toolchain-valid-rel-src-path -S ${source_dir} --toolchain=toolchain.cmake) + + set(RunCMake_TEST_NO_CLEAN 1) + set(binary_dir ${RunCMake_BINARY_DIR}/Toolchain-build) + set(RunCMake_TEST_BINARY_DIR "${binary_dir}") + file(REMOVE_RECURSE "${binary_dir}") + + # Test that we both search the binary dir for toolchain files, and it takes + # precedence over source dir + file(WRITE ${binary_dir}/toolchain.cmake [=[ +set(CMAKE_SYSTEM_NAME Linux) +set(toolchain_file binary_dir) +]=]) + run_cmake_with_options(toolchain-valid-rel-build-path ${CMAKE_COMMAND} -S ${source_dir} -B ${binary_dir} --toolchain toolchain.cmake) +endfunction() +run_Toolchain() + function(run_BuildDir) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BuildDir-build) diff --git a/Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt b/Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt new file mode 100644 index 00000000000..80d42b828b4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Toolchain/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.20) +project(Toolchain LANGUAGES NONE) +message(FATAL_ERROR "${toolchain_file}") diff --git a/Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake b/Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake new file mode 100644 index 00000000000..719556c0af1 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Toolchain/toolchain.cmake @@ -0,0 +1,2 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(toolchain_file source_dir) diff --git a/Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt b/Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-no-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt new file mode 100644 index 00000000000..2fec517a556 --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-no-arg-stderr.txt @@ -0,0 +1 @@ +^CMake Error: No file specified for --toolchain diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt new file mode 100644 index 00000000000..21d5db6464c --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-valid-abs-path-stderr.txt @@ -0,0 +1 @@ +^CMake Error.*source_dir diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt new file mode 100644 index 00000000000..19800516625 --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-build-path-stderr.txt @@ -0,0 +1 @@ +^CMake Error.*binary_dir diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt new file mode 100644 index 00000000000..21d5db6464c --- /dev/null +++ b/Tests/RunCMake/CommandLine/toolchain-valid-rel-src-path-stderr.txt @@ -0,0 +1 @@ +^CMake Error.*source_dir From d67cc4882d54a18abbd5d01365ce1fc72d702a0e Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 15 Apr 2021 14:13:57 +0200 Subject: [PATCH 0251/1519] Xcode: Add support of DEPFILE for add_custom_command Issue: #20286 --- Help/command/add_custom_command.rst | 30 +++++++++++------ .../dev/Xcode-add_custom_command-DEPFILE.rst | 5 +++ Source/cmCustomCommandGenerator.cxx | 30 +++++++++++++---- Source/cmCustomCommandGenerator.h | 13 ++++++-- Source/cmGlobalXCodeGenerator.cxx | 33 ++++++++++++++++--- Source/cmGlobalXCodeGenerator.h | 13 ++++++++ Source/cmTransformDepfile.cxx | 14 ++++++-- .../RunCMake/BuildDepends/RunCMakeTest.cmake | 3 +- Tests/RunCMake/CMakeLists.txt | 1 + 9 files changed, 115 insertions(+), 27 deletions(-) create mode 100644 Help/release/dev/Xcode-add_custom_command-DEPFILE.rst diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index b6ff0ea35bc..c0ff81ae839 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -271,32 +271,42 @@ The options are: ``DEPFILE`` .. versionadded:: 3.7 - Specify a ``.d`` depfile for the :generator:`Ninja` generator and - :ref:`Makefile Generators`. The depfile may use "generator expressions" with - the syntax ``$<...>``. See the :manual:`generator-expressions(7) - ` manual for available expressions. - A ``.d`` file holds dependencies usually emitted by the custom - command itself. - Using ``DEPFILE`` with other generators than :generator:`Ninja` or - :ref:`Makefile Generators` is an error. + Specify a ``.d`` depfile for the :generator:`Ninja`, :generator:`Xcode` and + :ref:`Makefile ` generators. The depfile may use + "generator expressions" with the syntax ``$<...>``. See the + :manual:`generator-expressions(7) ` manual + for available expressions. A ``.d`` file holds dependencies usually emitted + by the custom command itself. + + Using ``DEPFILE`` with other generators than :generator:`Ninja`, + :generator:`Xcode` or :ref:`Makefile ` is an error. .. versionadded:: 3.20 Added the support of :ref:`Makefile Generators`. .. versionadded:: 3.21 - Added the support of :manual:`generator expressions `. + Added the support of :generator:`Xcode` generator and + :manual:`generator expressions `. If the ``DEPFILE`` argument is relative, it should be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR` (see policy :policy:`CMP0116`. This policy is always ``NEW`` for - :ref:`Makefile Generators`). + :ref:`Makefile ` and :generator:`Xcode` generators). .. note:: For :ref:`Makefile Generators`, this option cannot be specified at the same time as ``IMPLICIT_DEPENDS`` option. + .. note:: + + For the :generator:`Xcode` generator, this option requires that the + :ref:`Xcode Build System Selection` uses the ``buildsystem=12`` variant + or higher. This is the default when using Xcode 12 or above. + The :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable indicates which variant + of the Xcode build system is used. + Examples: Generating Files ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst b/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst new file mode 100644 index 00000000000..4c4d48c7690 --- /dev/null +++ b/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst @@ -0,0 +1,5 @@ +Xcode-add_custom_command-DEPFILE +-------------------------------- + +* The :command:`add_custom_command` command gained ``DEPFILE`` support on + :generator:`Xcode` generator. diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 4705443190e..7659792dddc 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -151,7 +151,9 @@ std::string EvaluateDepfile(std::string const& path, cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, - bool transformDepfile, cm::optional crossConfig) + bool transformDepfile, cm::optional crossConfig, + std::function + computeInternalDepfile) : CC(&cc) , OutputConfig(crossConfig ? *crossConfig : config) , CommandConfig(std::move(config)) @@ -159,7 +161,15 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( , OldStyle(cc.GetEscapeOldStyle()) , MakeVars(cc.GetEscapeAllowMakeVars()) , EmulatorsWithArguments(cc.GetCommandLines().size()) + , ComputeInternalDepfile(std::move(computeInternalDepfile)) { + if (!this->ComputeInternalDepfile) { + this->ComputeInternalDepfile = + [this](const std::string& cfg, const std::string& file) -> std::string { + return this->GetInternalDepfileName(cfg, file); + }; + } + cmGeneratorExpression ge(cc.GetBacktrace()); const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines(); @@ -413,13 +423,9 @@ std::string cmCustomCommandGenerator::GetFullDepfile() const return cmSystemTools::CollapseFullPath(depfile); } -std::string cmCustomCommandGenerator::GetInternalDepfile() const +std::string cmCustomCommandGenerator::GetInternalDepfileName( + const std::string& /*config*/, const std::string& depfile) { - std::string depfile = this->GetFullDepfile(); - if (depfile.empty()) { - return ""; - } - cmCryptoHash hash(cmCryptoHash::AlgoSHA256); std::string extension; switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) { @@ -434,6 +440,16 @@ std::string cmCustomCommandGenerator::GetInternalDepfile() const hash.HashString(depfile), extension); } +std::string cmCustomCommandGenerator::GetInternalDepfile() const +{ + std::string depfile = this->GetFullDepfile(); + if (depfile.empty()) { + return ""; + } + + return this->ComputeInternalDepfile(this->OutputConfig, depfile); +} + const char* cmCustomCommandGenerator::GetComment() const { return this->CC->GetComment(); diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 53e55737da8..e70909a74a0 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include #include #include #include @@ -19,6 +20,8 @@ class cmLocalGenerator; class cmCustomCommandGenerator { + std::string GetInternalDepfileName(const std::string&, const std::string&); + cmCustomCommand const* CC; std::string OutputConfig; std::string CommandConfig; @@ -32,15 +35,19 @@ class cmCustomCommandGenerator std::vector Depends; std::string WorkingDirectory; std::set>> Utilities; + std::function + ComputeInternalDepfile; void FillEmulatorsWithArguments(); std::vector GetCrossCompilingEmulator(unsigned int c) const; const char* GetArgv0Location(unsigned int c) const; public: - cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config, - cmLocalGenerator* lg, bool transformDepfile = true, - cm::optional crossConfig = {}); + cmCustomCommandGenerator( + cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, + bool transformDepfile = true, cm::optional crossConfig = {}, + std::function + computeInternalDepfile = {}); cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete; cmCustomCommandGenerator(cmCustomCommandGenerator&&) = default; cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) = diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7dd17045ee1..dc3d3f253e1 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -17,6 +17,7 @@ #include "cmsys/RegularExpression.hxx" +#include "cmCMakePath.h" #include "cmComputeLinkInformation.h" #include "cmCryptoHash.h" #include "cmCustomCommand.h" @@ -1864,9 +1865,20 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( std::set allConfigInputs; std::set allConfigOutputs; + cmXCodeObject* buildPhase = + this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase, + cmStrCat(gt->GetName(), ':', sf->GetFullPath())); + + auto depfilesDirectory = cmStrCat( + gt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/d/"); + auto depfilesPrefix = cmStrCat(depfilesDirectory, buildPhase->GetId(), "."); + std::string shellScript = "set -e\n"; for (std::string const& configName : this->CurrentConfigurationTypes) { - cmCustomCommandGenerator ccg(cc, configName, this->CurrentLocalGenerator); + cmCustomCommandGenerator ccg( + cc, configName, this->CurrentLocalGenerator, true, {}, + [&depfilesPrefix](const std::string& config, const std::string&) + -> std::string { return cmStrCat(depfilesPrefix, config, ".d"); }); std::vector realDepends; realDepends.reserve(ccg.GetDepends().size()); for (auto const& d : ccg.GetDepends()) { @@ -1886,9 +1898,22 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( "\"; then :\n", this->ConstructScript(ccg), "fi\n"); } - cmXCodeObject* buildPhase = - this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase, - cmStrCat(gt->GetName(), ':', sf->GetFullPath())); + if (!cc.GetDepfile().empty()) { + buildPhase->AddAttribute( + "dependencyFile", + this->CreateString(cmStrCat(depfilesDirectory, buildPhase->GetId(), + ".$(CONFIGURATION).d"))); + // to avoid spurious errors during first build, create empty dependency + // files + cmSystemTools::MakeDirectory(depfilesDirectory); + for (std::string const& configName : this->CurrentConfigurationTypes) { + auto file = cmStrCat(depfilesPrefix, configName, ".d"); + if (!cmSystemTools::FileExists(file)) { + cmSystemTools::Touch(file, true); + } + } + } + buildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1ab56e20eb0..24064723517 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -14,6 +14,7 @@ #include #include "cmGlobalGenerator.h" +#include "cmTransformDepfile.h" #include "cmXCodeObject.h" class cmCustomCommand; @@ -111,6 +112,18 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator bool ShouldStripResourcePath(cmMakefile*) const override; + /** + * Used to determine if this generator supports DEPFILE option. + */ + bool SupportsCustomCommandDepfile() const override + { + return this->XcodeBuildSystem >= BuildSystem::Twelve; + } + virtual cm::optional DepfileFormat() const override + { + return cmDepfileFormat::GccDepfile; + } + bool SetSystemName(std::string const& s, cmMakefile* mf) override; bool SetGeneratorToolset(std::string const& ts, bool build, cmMakefile* mf) override; diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 78aa4b2df35..b693582ec32 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTransformDepfile.h" +#include #include #include #include @@ -13,6 +14,7 @@ #include "cmGccDepfileReader.h" #include "cmGccDepfileReaderTypes.h" +#include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmSystemTools.h" @@ -38,6 +40,14 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, const cmGccDepfileContent& content) { const auto& binDir = lg.GetBinaryDirectory(); + std::function formatPath = + [&lg, &binDir](const std::string& path) -> std::string { + return lg.MaybeConvertToRelativePath(binDir, path); + }; + if (lg.GetGlobalGenerator()->GetName() == "Xcode") { + // full paths must be preserved for Xcode compliance + formatPath = [](const std::string& path) -> std::string { return path; }; + } for (auto const& dep : content) { bool first = true; @@ -46,12 +56,12 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, fout << " \\\n "; } first = false; - WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, rule)); + WriteFilenameGcc(fout, formatPath(rule)); } fout << ':'; for (auto const& path : dep.paths) { fout << " \\\n "; - WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, path)); + WriteFilenameGcc(fout, formatPath(path)); } fout << '\n'; } diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 62326345e4d..a6e08da51f6 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -155,7 +155,8 @@ if (RunCMake_GENERATOR MATCHES "Makefiles") run_cmake(CustomCommandDependencies-BadArgs) endif() -if(RunCMake_GENERATOR MATCHES "Make|Ninja") +if(RunCMake_GENERATOR MATCHES "Make|Ninja" OR + (RunCMake_GENERATOR STREQUAL "Xcode" AND CMAKE_XCODE_BUILD_SYSTEM GREATER_EQUAL "12")) unset(run_BuildDepends_skip_step_3) run_BuildDepends(CustomCommandDepfile) set(run_BuildDepends_skip_step_3 1) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 5f23c0582cb..be59a55eb27 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -222,6 +222,7 @@ endif() add_RunCMake_test(BuildDepends -DMSVC_VERSION=${MSVC_VERSION} + -DCMAKE_XCODE_BUILD_SYSTEM=${CMAKE_XCODE_BUILD_SYSTEM} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS} ) From 7f89053953f81aaa3d0283ba4b8d8b29ce234292 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Apr 2021 12:31:41 -0400 Subject: [PATCH 0252/1519] cmSystemTools: Return KWSys Status from CreateLink and CreateSymlink --- Source/cmFileCommand.cxx | 6 ++++-- Source/cmSystemTools.cxx | 24 ++++++++++++------------ Source/cmSystemTools.h | 12 ++++++------ 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 26bdedfd948..05ebcca1216 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2949,9 +2949,11 @@ bool HandleCreateLinkCommand(std::vector const& args, // Check if the command requires a symbolic link. if (arguments.Symbolic) { - completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result); + completed = static_cast( + cmSystemTools::CreateSymlink(fileName, newFileName, &result)); } else { - completed = cmSystemTools::CreateLink(fileName, newFileName, &result); + completed = static_cast( + cmSystemTools::CreateLink(fileName, newFileName, &result)); } // Check if copy-on-error is enabled in the arguments. diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 2b3266d5feb..5382fac250a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -3158,9 +3158,9 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) return out; } -bool cmSystemTools::CreateSymlink(const std::string& origName, - const std::string& newName, - std::string* errorMessage) +cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName, + std::string const& newName, + std::string* errorMessage) { uv_fs_t req; int flags = 0; @@ -3171,7 +3171,9 @@ bool cmSystemTools::CreateSymlink(const std::string& origName, #endif int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(), flags, nullptr); + cmsys::Status status; if (err) { + status = cmsys::Status::POSIX(-err); std::string e = "failed to create symbolic link '" + newName + "': " + uv_strerror(err); if (errorMessage) { @@ -3179,20 +3181,20 @@ bool cmSystemTools::CreateSymlink(const std::string& origName, } else { cmSystemTools::Error(e); } - return false; } - - return true; + return status; } -bool cmSystemTools::CreateLink(const std::string& origName, - const std::string& newName, - std::string* errorMessage) +cmsys::Status cmSystemTools::CreateLink(std::string const& origName, + std::string const& newName, + std::string* errorMessage) { uv_fs_t req; int err = uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr); + cmsys::Status status; if (err) { + status = cmsys::Status::POSIX(-err); std::string e = "failed to create link '" + newName + "': " + uv_strerror(err); if (errorMessage) { @@ -3200,10 +3202,8 @@ bool cmSystemTools::CreateLink(const std::string& origName, } else { cmSystemTools::Error(e); } - return false; } - - return true; + return status; } cm::string_view cmSystemTools::GetSystemName() diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 99f20e0240a..0aecf716fa8 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -489,15 +489,15 @@ class cmSystemTools : public cmsys::SystemTools /** Create a symbolic link if the platform supports it. Returns whether creation succeeded. */ - static bool CreateSymlink(const std::string& origName, - const std::string& newName, - std::string* errorMessage = nullptr); + static cmsys::Status CreateSymlink(std::string const& origName, + std::string const& newName, + std::string* errorMessage = nullptr); /** Create a hard link if the platform supports it. Returns whether creation succeeded. */ - static bool CreateLink(const std::string& origName, - const std::string& newName, - std::string* errorMessage = nullptr); + static cmsys::Status CreateLink(std::string const& origName, + std::string const& newName, + std::string* errorMessage = nullptr); /** Get the system name. */ static cm::string_view GetSystemName(); From 79a2f1e22a4ff95d7d96478d579a7f52b3c289da Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Apr 2021 12:39:57 -0400 Subject: [PATCH 0253/1519] cmcmd: Improve error message from cmake_symlink_{library,executable} --- Source/cmcmd.cxx | 23 +++++++++++++++-------- Source/cmcmd.h | 6 ++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index a47eccde4af..928435e4374 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1601,14 +1601,18 @@ int cmcmd::SymlinkLibrary(std::vector const& args) cmSystemTools::ConvertToUnixSlashes(soName); cmSystemTools::ConvertToUnixSlashes(name); if (soName != realName) { - if (!cmcmd::SymlinkInternal(realName, soName)) { - cmSystemTools::ReportLastSystemError("cmake_symlink_library"); + cmsys::Status status = cmcmd::SymlinkInternal(realName, soName); + if (!status) { + cmSystemTools::Error( + cmStrCat("cmake_symlink_library: System Error: ", status.GetString())); result = 1; } } if (name != soName) { - if (!cmcmd::SymlinkInternal(soName, name)) { - cmSystemTools::ReportLastSystemError("cmake_symlink_library"); + cmsys::Status status = cmcmd::SymlinkInternal(soName, name); + if (!status) { + cmSystemTools::Error( + cmStrCat("cmake_symlink_library: System Error: ", status.GetString())); result = 1; } } @@ -1621,21 +1625,24 @@ int cmcmd::SymlinkExecutable(std::vector const& args) std::string const& realName = args[2]; std::string const& name = args[3]; if (name != realName) { - if (!cmcmd::SymlinkInternal(realName, name)) { - cmSystemTools::ReportLastSystemError("cmake_symlink_executable"); + cmsys::Status status = cmcmd::SymlinkInternal(realName, name); + if (!status) { + cmSystemTools::Error(cmStrCat("cmake_symlink_executable: System Error: ", + status.GetString())); result = 1; } } return result; } -bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link) +cmsys::Status cmcmd::SymlinkInternal(std::string const& file, + std::string const& link) { if (cmSystemTools::FileExists(link) || cmSystemTools::FileIsSymlink(link)) { cmSystemTools::RemoveFile(link); } #if defined(_WIN32) && !defined(__CYGWIN__) - return static_cast(cmSystemTools::CopyFileAlways(file, link)); + return cmSystemTools::CopyFileAlways(file, link); #else std::string linktext = cmSystemTools::GetFilenameName(file); return cmSystemTools::CreateSymlink(linktext, link); diff --git a/Source/cmcmd.h b/Source/cmcmd.h index a2e0b1ea3d8..ba78edb003a 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -8,6 +8,8 @@ #include #include +#include "cmsys/Status.hxx" + #include "cmCryptoHash.h" class cmConsoleBuf; @@ -28,8 +30,8 @@ class cmcmd cmCryptoHash::Algo algo); static int SymlinkLibrary(std::vector const& args); static int SymlinkExecutable(std::vector const& args); - static bool SymlinkInternal(std::string const& file, - std::string const& link); + static cmsys::Status SymlinkInternal(std::string const& file, + std::string const& link); static int ExecuteEchoColor(std::vector const& args); static int ExecuteLinkScript(std::vector const& args); static int WindowsCEEnvironment(const char* version, From c2d2772f15d08f006c0841d4caf028c41f315ca4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Apr 2021 12:02:16 -0400 Subject: [PATCH 0254/1519] try_compile: Improve error message when a file cannot be removed --- Source/cmCoreTryCompile.cxx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 6672aa6761c..cb84d1d9f45 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -1015,17 +1015,21 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir) // cannot delete them immediately. Try a few times. cmSystemTools::WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); - while (!cmSystemTools::RemoveFile(fullPath) && --retry.Count && - cmSystemTools::FileExists(fullPath)) { + cmsys::Status status; + while (!((status = cmSystemTools::RemoveFile(fullPath))) && + --retry.Count && cmSystemTools::FileExists(fullPath)) { cmSystemTools::Delay(retry.Delay); } if (retry.Count == 0) #else - if (!cmSystemTools::RemoveFile(fullPath)) + cmsys::Status status = cmSystemTools::RemoveFile(fullPath); + if (!status) #endif { - std::string m = "Remove failed on file: " + fullPath; - cmSystemTools::ReportLastSystemError(m.c_str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The file:\n ", fullPath, + "\ncould not be removed:\n ", status.GetString())); } } } From e5a098968c3a25df75b82363515795e793a668ae Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 16 Apr 2021 00:01:04 -0400 Subject: [PATCH 0255/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 14ed1827079..985d944a9c1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210415) +set(CMake_VERSION_PATCH 20210416) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ae2c24b0bafd341928fd6e95acc60ece2c45aa0e Mon Sep 17 00:00:00 2001 From: nic-kaczinsky Date: Fri, 16 Apr 2021 06:55:30 +0000 Subject: [PATCH 0256/1519] Tests: Fix warning clang-analyzer-cplusplus.NewDeleteLeaks Fix the warning: `potential leak of memory pointed to by "vp"`. --- Tests/CompileFeatures/cxx_contextual_conversions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CompileFeatures/cxx_contextual_conversions.cpp b/Tests/CompileFeatures/cxx_contextual_conversions.cpp index 247f13f9fea..fe8d5c0f5b0 100644 --- a/Tests/CompileFeatures/cxx_contextual_conversions.cpp +++ b/Tests/CompileFeatures/cxx_contextual_conversions.cpp @@ -1,4 +1,3 @@ - #define assert(E) \ if (!(E)) \ return 1; @@ -38,6 +37,7 @@ int someFunc() } int* vp = new int[i]; + delete[] vp; return 0; } From 94fb2516f00fe345326f6a82dc41f2236c481ed3 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 17 Apr 2021 00:01:08 -0400 Subject: [PATCH 0257/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 985d944a9c1..49e932647c8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210416) +set(CMake_VERSION_PATCH 20210417) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 253aff6c94401f468ea8f9c953d325c5a8c72eb0 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 16 Apr 2021 14:39:23 +0200 Subject: [PATCH 0258/1519] Xcode: Add support of DEPFILE for add_custom_command, part 2 This MR extend the support of 'DEPFILE' to buildsystem version 1. Issue: #20286 --- Help/command/add_custom_command.rst | 8 ------ Source/cmCustomCommandGenerator.cxx | 4 +++ Source/cmGlobalXCodeGenerator.cxx | 28 +++++++++++++++++-- Source/cmGlobalXCodeGenerator.h | 9 +++--- Source/cmTransformDepfile.cxx | 20 +++++++++++-- Source/cmTransformDepfile.h | 1 + Source/cmcmd.cxx | 2 ++ .../RunCMake/BuildDepends/RunCMakeTest.cmake | 3 +- Tests/RunCMake/CMakeLists.txt | 1 - 9 files changed, 55 insertions(+), 21 deletions(-) diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index c0ff81ae839..569f1e853b3 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -299,14 +299,6 @@ The options are: For :ref:`Makefile Generators`, this option cannot be specified at the same time as ``IMPLICIT_DEPENDS`` option. - .. note:: - - For the :generator:`Xcode` generator, this option requires that the - :ref:`Xcode Build System Selection` uses the ``buildsystem=12`` variant - or higher. This is the default when using Xcode 12 or above. - The :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable indicates which variant - of the Xcode build system is used. - Examples: Generating Files ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 7659792dddc..1054beb375f 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -226,6 +226,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( case cmDepfileFormat::VsTlog: argv.emplace_back("vstlog"); break; + case cmDepfileFormat::MakeDepfile: + argv.emplace_back("makedepfile"); + break; } argv.push_back(this->LG->GetSourceDirectory()); argv.push_back(this->LG->GetCurrentSourceDirectory()); @@ -430,6 +433,7 @@ std::string cmCustomCommandGenerator::GetInternalDepfileName( std::string extension; switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) { case cmDepfileFormat::GccDepfile: + case cmDepfileFormat::MakeDepfile: extension = ".d"; break; case cmDepfileFormat::VsTlog: diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index dc3d3f253e1..92dd5556dbf 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2213,9 +2213,33 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( } } makefileStream << "\n\n"; + + auto depfilesDirectory = + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/CMakeFiles/d/"); + for (auto const& command : commands) { - cmCustomCommandGenerator ccg(command, configName, - this->CurrentLocalGenerator); + cmCustomCommandGenerator ccg( + command, configName, this->CurrentLocalGenerator, true, {}, + [this, &depfilesDirectory](const std::string& config, + const std::string& file) -> std::string { + return cmStrCat( + depfilesDirectory, + this->GetObjectId(cmXCodeObject::PBXShellScriptBuildPhase, file), + ".", config, ".d"); + }); + + auto depfile = ccg.GetInternalDepfile(); + if (!depfile.empty()) { + makefileStream << "include " + << cmSystemTools::ConvertToOutputPath(depfile) << "\n\n"; + + cmSystemTools::MakeDirectory(depfilesDirectory); + if (!cmSystemTools::FileExists(depfile)) { + cmSystemTools::Touch(depfile, true); + } + } + std::vector realDepends; realDepends.reserve(ccg.GetDepends().size()); for (auto const& d : ccg.GetDepends()) { diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 24064723517..ef61601b321 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -115,13 +115,12 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator /** * Used to determine if this generator supports DEPFILE option. */ - bool SupportsCustomCommandDepfile() const override - { - return this->XcodeBuildSystem >= BuildSystem::Twelve; - } + bool SupportsCustomCommandDepfile() const override { return true; } virtual cm::optional DepfileFormat() const override { - return cmDepfileFormat::GccDepfile; + return this->XcodeBuildSystem == BuildSystem::One + ? cmDepfileFormat::MakeDepfile + : cmDepfileFormat::GccDepfile; } bool SetSystemName(std::string const& s, cmMakefile* mf) override; diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index b693582ec32..6e0366c2ba2 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -36,8 +36,9 @@ void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename) } } -void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, - const cmGccDepfileContent& content) +void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout, + const cmLocalGenerator& lg, + const cmGccDepfileContent& content) { const auto& binDir = lg.GetBinaryDirectory(); std::function formatPath = @@ -65,6 +66,18 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, } fout << '\n'; } + + if (format == cmDepfileFormat::MakeDepfile) { + // In this case, phony targets must be added for all dependencies + fout << "\n"; + for (auto const& dep : content) { + for (auto const& path : dep.paths) { + fout << "\n"; + WriteFilenameGcc(fout, formatPath(path)); + fout << ":\n"; + } + } + } } // tlog format : always windows paths on Windows regardless the generator @@ -122,7 +135,8 @@ bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, } switch (format) { case cmDepfileFormat::GccDepfile: - WriteGccDepfile(fout, lg, content); + case cmDepfileFormat::MakeDepfile: + WriteDepfile(format, fout, lg, content); break; case cmDepfileFormat::VsTlog: WriteVsTlog(fout, lg, content); diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h index c43a45f2794..c31e4abfeb4 100644 --- a/Source/cmTransformDepfile.h +++ b/Source/cmTransformDepfile.h @@ -8,6 +8,7 @@ enum class cmDepfileFormat { GccDepfile, VsTlog, + MakeDepfile }; class cmLocalGenerator; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 928435e4374..2c2ae4d17a7 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1527,6 +1527,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, format = cmDepfileFormat::GccDepfile; } else if (args[3] == "vstlog") { format = cmDepfileFormat::VsTlog; + } else if (args[3] == "makedepfile") { + format = cmDepfileFormat::MakeDepfile; } else { return 1; } diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index a6e08da51f6..72faddb0c89 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -155,8 +155,7 @@ if (RunCMake_GENERATOR MATCHES "Makefiles") run_cmake(CustomCommandDependencies-BadArgs) endif() -if(RunCMake_GENERATOR MATCHES "Make|Ninja" OR - (RunCMake_GENERATOR STREQUAL "Xcode" AND CMAKE_XCODE_BUILD_SYSTEM GREATER_EQUAL "12")) +if(RunCMake_GENERATOR MATCHES "Make|Ninja|Xcode") unset(run_BuildDepends_skip_step_3) run_BuildDepends(CustomCommandDepfile) set(run_BuildDepends_skip_step_3 1) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index be59a55eb27..5f23c0582cb 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -222,7 +222,6 @@ endif() add_RunCMake_test(BuildDepends -DMSVC_VERSION=${MSVC_VERSION} - -DCMAKE_XCODE_BUILD_SYSTEM=${CMAKE_XCODE_BUILD_SYSTEM} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS} ) From 388c347a4bfc99bace477f83af4faa949f7f0951 Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Sat, 17 Apr 2021 22:53:28 +0200 Subject: [PATCH 0259/1519] Help: Fix typo in CMAKE_TOOLCHAIN_FILE docs --- Help/variable/CMAKE_TOOLCHAIN_FILE.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst index 423da9cd2d7..e462c5e8513 100644 --- a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst +++ b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst @@ -9,4 +9,4 @@ specifies locations for compilers and toolchain utilities, and other target platform and compiler related information. Relative paths are allowed and are interpreted first as relative to the -build directory, and if not found, relative to the soruce directory. +build directory, and if not found, relative to the source directory. From d46170970b0626cda9a420189bd0d904c25a7e93 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 18 Apr 2021 00:01:04 -0400 Subject: [PATCH 0260/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 49e932647c8..9cf89724d0f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210417) +set(CMake_VERSION_PATCH 20210418) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 42bede8385c1a9d729498d50cbe2aaf2602213fd Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 19 Apr 2021 00:01:15 -0400 Subject: [PATCH 0261/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9cf89724d0f..2b11de7aaa0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210418) +set(CMake_VERSION_PATCH 20210419) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d98342d868a51f2c777f0424d2ea04f2fb1fd3ca Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Mon, 19 Apr 2021 09:26:45 -0400 Subject: [PATCH 0262/1519] KWSys 2021-04-19 (d6139c66) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit d6139c66c8760552ab6bc4a08401ae8105217469 (master). Upstream Shortlog ----------------- Orgad Shaneh (3): 17f4af9b SystemTools: Use octal base for error messages in permission test f00dd83e SystemTools: Avoid unnecessary assumption of working directory in test case 5b941f33 SystemTools: Adapt permissions test to MSYS --- testSystemTools.cxx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/testSystemTools.cxx b/testSystemTools.cxx index cfa420df498..04f66ffcecd 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -290,15 +290,17 @@ static bool CheckFileOperations() res = false; } + std::cerr << std::oct; // Reset umask -#if defined(_WIN32) && !defined(__CYGWIN__) +#ifdef __MSYS__ + mode_t fullMask = S_IWRITE; +#elif defined(_WIN32) && !defined(__CYGWIN__) // NOTE: Windows doesn't support toggling _S_IREAD. mode_t fullMask = _S_IWRITE; #else // On a normal POSIX platform, we can toggle all permissions. mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO; #endif - mode_t orig_umask = umask(fullMask); // Test file permissions without umask mode_t origPerm, thisPerm; @@ -370,6 +372,7 @@ static bool CheckFileOperations() res = false; } + mode_t orig_umask = umask(fullMask); // Test setting file permissions while honoring umask if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask, true)) { std::cerr << "Problem with SetPermissions (3) for: " << testNewFile @@ -496,6 +499,7 @@ static bool CheckFileOperations() } #endif + std::cerr << std::dec; return res; } @@ -1093,7 +1097,7 @@ static bool CheckCopyFileIfDifferent() ret = false; continue; } - std::string bdata = readFile("file_b"); + std::string bdata = readFile(cptarget); if (diff_test_cases[i].a != bdata) { std::cerr << "Incorrect CopyFileIfDifferent file contents in test case " << i + 1 << "." << std::endl; From e1896d9c544e4afcac6b3744247964f431571a7b Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 20 Apr 2021 00:01:09 -0400 Subject: [PATCH 0263/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2b11de7aaa0..3ba0698add7 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210419) +set(CMake_VERSION_PATCH 20210420) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 408e6d6185427dc57470f5685e9774e579bd6283 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 19 Apr 2021 11:06:04 -0400 Subject: [PATCH 0264/1519] Utilities: Suppress warnings in third-party code with NVHPC --- Source/CursesDialog/form/CMakeLists.txt | 2 +- Utilities/cmbzip2/CMakeLists.txt | 2 +- Utilities/cmcurl/CMakeLists.txt | 2 +- Utilities/cmexpat/CMakeLists.txt | 2 +- Utilities/cmjsoncpp/CMakeLists.txt | 2 +- Utilities/cmlibarchive/CMakeLists.txt | 2 +- Utilities/cmliblzma/CMakeLists.txt | 2 +- Utilities/cmlibrhash/CMakeLists.txt | 2 +- Utilities/cmlibuv/CMakeLists.txt | 2 +- Utilities/cmnghttp2/CMakeLists.txt | 2 +- Utilities/cmzlib/CMakeLists.txt | 2 +- Utilities/cmzstd/CMakeLists.txt | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt index 8f26b9aaa68..9202bc12e3c 100644 --- a/Source/CursesDialog/form/CMakeLists.txt +++ b/Source/CursesDialog/form/CMakeLists.txt @@ -5,7 +5,7 @@ project(CMAKE_FORM) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmbzip2/CMakeLists.txt b/Utilities/cmbzip2/CMakeLists.txt index 9b53b0f1278..ff90bb68452 100644 --- a/Utilities/cmbzip2/CMakeLists.txt +++ b/Utilities/cmbzip2/CMakeLists.txt @@ -2,7 +2,7 @@ project(bzip2) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 4fb93615c99..57860a9980e 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -97,7 +97,7 @@ endif(APPLE) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt index b8dc4e8cc40..904809683a6 100644 --- a/Utilities/cmexpat/CMakeLists.txt +++ b/Utilities/cmexpat/CMakeLists.txt @@ -1,6 +1,6 @@ # Disable warnings to avoid changing 3rd party code. IF(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt index 74e998823c1..029ae860c43 100644 --- a/Utilities/cmjsoncpp/CMakeLists.txt +++ b/Utilities/cmjsoncpp/CMakeLists.txt @@ -2,7 +2,7 @@ project(JsonCpp CXX) # Disable warnings to avoid changing 3rd party code. if(CMAKE_CXX_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "PathScale") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -woffall") diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index 689d98afb92..79452ffff65 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -94,7 +94,7 @@ SET(CMAKE_REQUIRED_FLAGS) # Disable warnings to avoid changing 3rd party code. IF(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt index 32a14dc239a..5dd7035da3c 100644 --- a/Utilities/cmliblzma/CMakeLists.txt +++ b/Utilities/cmliblzma/CMakeLists.txt @@ -148,7 +148,7 @@ INCLUDE_DIRECTORIES( # Disable warnings to avoid changing 3rd party code. IF(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmlibrhash/CMakeLists.txt b/Utilities/cmlibrhash/CMakeLists.txt index 37e2399c4cd..1a01165c090 100644 --- a/Utilities/cmlibrhash/CMakeLists.txt +++ b/Utilities/cmlibrhash/CMakeLists.txt @@ -2,7 +2,7 @@ project(librhash C) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index f8b47af467e..a4f014865c5 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -2,7 +2,7 @@ project(libuv C) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmnghttp2/CMakeLists.txt b/Utilities/cmnghttp2/CMakeLists.txt index 17cc6ddb2d4..3bc2778ea98 100644 --- a/Utilities/cmnghttp2/CMakeLists.txt +++ b/Utilities/cmnghttp2/CMakeLists.txt @@ -1,6 +1,6 @@ # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmzlib/CMakeLists.txt b/Utilities/cmzlib/CMakeLists.txt index d266af936f9..d57cb29a4ae 100644 --- a/Utilities/cmzlib/CMakeLists.txt +++ b/Utilities/cmzlib/CMakeLists.txt @@ -2,7 +2,7 @@ PROJECT(CMZLIB) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") diff --git a/Utilities/cmzstd/CMakeLists.txt b/Utilities/cmzstd/CMakeLists.txt index 323151c08f6..199719553b3 100644 --- a/Utilities/cmzstd/CMakeLists.txt +++ b/Utilities/cmzstd/CMakeLists.txt @@ -2,7 +2,7 @@ project(zstd C) # Disable warnings to avoid changing 3rd party code. if(CMAKE_C_COMPILER_ID MATCHES - "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$") + "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") From 46d4c8e4df69ebba1d9fa711896e471a5bfbbafa Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 19 Apr 2021 11:12:26 -0400 Subject: [PATCH 0265/1519] CTestCustom: Ignore warning from FD_ZERO macro on NVHPC --- CTestCustom.cmake.in | 1 + 1 file changed, 1 insertion(+) diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index 4c8267de8c2..238ca1590ba 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -7,6 +7,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "warning LNK4221" "warning LNK4204" # Occurs by race condition with objects in small libs "variable .var_args[2]*. is used before its value is set" + "warning: variable .__d[01]. was set but never used" # FD_ZERO on NVHPC "jobserver unavailable" "warning: \\(Long double usage is reported only once for each file" "warning: To disable this warning use" From e4ff2b51b95d26dcfb70f0351328d1a285c22800 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 20 Apr 2021 13:25:53 -0400 Subject: [PATCH 0266/1519] Help: Demonstrate using set_target_properties with CUDA architectures A common anti-pattern is to copy from the `CUDA_ARCHITECTURES` documentation. If at any point the user tries to simplify by changin `set_property` to `set_target_properties` the code breaks. To better train users, provide and example of how to set multiple CUDA architectures with `set_target_properties`. --- Help/policy/CMP0104.rst | 2 +- Help/prop_tgt/CUDA_ARCHITECTURES.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/policy/CMP0104.rst b/Help/policy/CMP0104.rst index 7c7a16e3784..b125729ddf3 100644 --- a/Help/policy/CMP0104.rst +++ b/Help/policy/CMP0104.rst @@ -41,7 +41,7 @@ Examples .. code-block:: cmake - set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 35 50 72) + set_target_properties(tgt PROPERTIES CUDA_ARCHITECTURES "35;50;72") Generates code for real and virtual architectures ``30``, ``50`` and ``72``. diff --git a/Help/prop_tgt/CUDA_ARCHITECTURES.rst b/Help/prop_tgt/CUDA_ARCHITECTURES.rst index d56b76908dc..a3191e8e012 100644 --- a/Help/prop_tgt/CUDA_ARCHITECTURES.rst +++ b/Help/prop_tgt/CUDA_ARCHITECTURES.rst @@ -25,7 +25,7 @@ Examples .. code-block:: cmake - set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES 35 50 72) + set_target_properties(tgt PROPERTIES CUDA_ARCHITECTURES "35;50;72") Generates code for real and virtual architectures ``30``, ``50`` and ``72``. From b94bf12a310717cc548033dd69337c363d0b3e6f Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 20 Apr 2021 13:50:42 -0400 Subject: [PATCH 0267/1519] Help: cmake_minimum_required specify max is only for policies Make it even clearer that for the signature `...` that the second value is only used for policies, and is not a clamp range of supported CMake versions. --- Help/command/cmake_minimum_required.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst index c3b3e7370c0..2cc3cfe5ba3 100644 --- a/Help/command/cmake_minimum_required.rst +++ b/Help/command/cmake_minimum_required.rst @@ -5,21 +5,21 @@ Require a minimum version of cmake. .. code-block:: cmake - cmake_minimum_required(VERSION [...] [FATAL_ERROR]) + cmake_minimum_required(VERSION [...] [FATAL_ERROR]) .. versionadded:: 3.12 - The optional ```` version. + The optional ```` version. Sets the minimum required version of cmake for a project. Also updates the policy settings as explained below. -```` and the optional ```` are each CMake versions of the form -``major.minor[.patch[.tweak]]``, and the ``...`` is literal. +```` and the optional ```` are each CMake versions of the +form ``major.minor[.patch[.tweak]]``, and the ``...`` is literal. If the running version of CMake is lower than the ```` required version it will stop processing the project and report an error. -The optional ```` version, if specified, must be at least the -```` version and affects policy settings as described below. +The optional ```` version, if specified, must be at least the +```` version and affects policy settings as described in `Policy Settings`_. If the running version of CMake is older than 3.12, the extra ``...`` dots will be seen as version component separators, resulting in the ``...`` part being ignored and preserving the pre-3.12 behavior @@ -43,6 +43,8 @@ with an error instead of just a warning. limits some effects to the function scope when invoked. Such calls should not be made with the intention of having global effects. +.. _`Policy Settings`: + Policy Settings ^^^^^^^^^^^^^^^ From dfb47335dafc4be5df67a212b3911f65c35607fa Mon Sep 17 00:00:00 2001 From: Alexander Pivovarov Date: Tue, 20 Apr 2021 13:39:34 -0700 Subject: [PATCH 0268/1519] Tutorial: Step12 install MathFunctionsConfigVersion.cmake --- Help/guide/tutorial/Step12/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index eca79d9df7b..1b0c82667ff 100644 --- a/Help/guide/tutorial/Step12/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -110,6 +110,7 @@ write_basic_package_version_file( # install the configuration file install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake DESTINATION lib/cmake/MathFunctions ) From 71cbddf83ae552bab98620624573b820a7cb4161 Mon Sep 17 00:00:00 2001 From: friendlyanon Date: Wed, 21 Apr 2021 03:22:01 +0200 Subject: [PATCH 0269/1519] cmake(1): Change wording for fields in presets The placement of the word "optionally" implied that the fields mentioned before are not optional, which is not the case starting from version 3 of the presets. --- Help/manual/cmake.1.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 02828ac5b14..f416f86283a 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -381,9 +381,9 @@ Options ``--preset ``, ``--preset=`` Reads a :manual:`preset ` from ``/CMakePresets.json`` and - ``/CMakeUserPresets.json``. The preset specifies the - generator and the build directory, and optionally a list of variables and - other arguments to pass to CMake. The current working directory must contain + ``/CMakeUserPresets.json``. The preset may specify the + generator and the build directory, and a list of variables and other + arguments to pass to CMake. The current working directory must contain CMake preset files. The :manual:`CMake GUI ` can also recognize ``CMakePresets.json`` and ``CMakeUserPresets.json`` files. For full details on these files, see :manual:`cmake-presets(7)`. From 57872e6d44ca4ea639ef5a6a712be4dd0f12710e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 21 Apr 2021 00:01:08 -0400 Subject: [PATCH 0270/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3ba0698add7..0da463a0fcb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210420) +set(CMake_VERSION_PATCH 20210421) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 11c0bfff89d6a3ff20129db056b6ad656004f897 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 10:18:07 -0400 Subject: [PATCH 0271/1519] VS: Generalize CSharp /langversion flag mapping Map the `/langversion:` flag followed by any value to a `LangVersion` element with the specified value in the `.csproj` file. Fixes: #22089 --- Templates/MSBuild/FlagTables/v10_CSharp.json | 51 +++---------------- Templates/MSBuild/FlagTables/v11_CSharp.json | 51 +++---------------- Templates/MSBuild/FlagTables/v12_CSharp.json | 51 +++---------------- Templates/MSBuild/FlagTables/v140_CSharp.json | 51 +++---------------- Templates/MSBuild/FlagTables/v141_CSharp.json | 51 +++---------------- Templates/MSBuild/FlagTables/v142_CSharp.json | 51 +++---------------- 6 files changed, 36 insertions(+), 270 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v10_CSharp.json b/Templates/MSBuild/FlagTables/v10_CSharp.json index 5989aea1ecb..9f21d9a27bd 100644 --- a/Templates/MSBuild/FlagTables/v10_CSharp.json +++ b/Templates/MSBuild/FlagTables/v10_CSharp.json @@ -363,52 +363,13 @@ }, { "name": "LangVersion", - "switch": "langversion:ISO-1", + "switch": "langversion:", "comment": "", - "value": "ISO-1", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:ISO-2", - "comment": "", - "value": "ISO-2", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:3", - "comment": "", - "value": "3", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:4", - "comment": "", - "value": "4", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:5", - "comment": "", - "value": "5", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:6", - "comment": "", - "value": "6", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:default", - "comment": "", - "value": "default", - "flags": [] + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] }, { "name": "DelaySign", diff --git a/Templates/MSBuild/FlagTables/v11_CSharp.json b/Templates/MSBuild/FlagTables/v11_CSharp.json index 5989aea1ecb..9f21d9a27bd 100644 --- a/Templates/MSBuild/FlagTables/v11_CSharp.json +++ b/Templates/MSBuild/FlagTables/v11_CSharp.json @@ -363,52 +363,13 @@ }, { "name": "LangVersion", - "switch": "langversion:ISO-1", + "switch": "langversion:", "comment": "", - "value": "ISO-1", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:ISO-2", - "comment": "", - "value": "ISO-2", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:3", - "comment": "", - "value": "3", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:4", - "comment": "", - "value": "4", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:5", - "comment": "", - "value": "5", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:6", - "comment": "", - "value": "6", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:default", - "comment": "", - "value": "default", - "flags": [] + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] }, { "name": "DelaySign", diff --git a/Templates/MSBuild/FlagTables/v12_CSharp.json b/Templates/MSBuild/FlagTables/v12_CSharp.json index 5989aea1ecb..9f21d9a27bd 100644 --- a/Templates/MSBuild/FlagTables/v12_CSharp.json +++ b/Templates/MSBuild/FlagTables/v12_CSharp.json @@ -363,52 +363,13 @@ }, { "name": "LangVersion", - "switch": "langversion:ISO-1", + "switch": "langversion:", "comment": "", - "value": "ISO-1", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:ISO-2", - "comment": "", - "value": "ISO-2", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:3", - "comment": "", - "value": "3", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:4", - "comment": "", - "value": "4", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:5", - "comment": "", - "value": "5", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:6", - "comment": "", - "value": "6", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:default", - "comment": "", - "value": "default", - "flags": [] + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] }, { "name": "DelaySign", diff --git a/Templates/MSBuild/FlagTables/v140_CSharp.json b/Templates/MSBuild/FlagTables/v140_CSharp.json index 5989aea1ecb..9f21d9a27bd 100644 --- a/Templates/MSBuild/FlagTables/v140_CSharp.json +++ b/Templates/MSBuild/FlagTables/v140_CSharp.json @@ -363,52 +363,13 @@ }, { "name": "LangVersion", - "switch": "langversion:ISO-1", + "switch": "langversion:", "comment": "", - "value": "ISO-1", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:ISO-2", - "comment": "", - "value": "ISO-2", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:3", - "comment": "", - "value": "3", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:4", - "comment": "", - "value": "4", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:5", - "comment": "", - "value": "5", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:6", - "comment": "", - "value": "6", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:default", - "comment": "", - "value": "default", - "flags": [] + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] }, { "name": "DelaySign", diff --git a/Templates/MSBuild/FlagTables/v141_CSharp.json b/Templates/MSBuild/FlagTables/v141_CSharp.json index 5989aea1ecb..9f21d9a27bd 100644 --- a/Templates/MSBuild/FlagTables/v141_CSharp.json +++ b/Templates/MSBuild/FlagTables/v141_CSharp.json @@ -363,52 +363,13 @@ }, { "name": "LangVersion", - "switch": "langversion:ISO-1", + "switch": "langversion:", "comment": "", - "value": "ISO-1", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:ISO-2", - "comment": "", - "value": "ISO-2", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:3", - "comment": "", - "value": "3", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:4", - "comment": "", - "value": "4", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:5", - "comment": "", - "value": "5", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:6", - "comment": "", - "value": "6", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:default", - "comment": "", - "value": "default", - "flags": [] + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] }, { "name": "DelaySign", diff --git a/Templates/MSBuild/FlagTables/v142_CSharp.json b/Templates/MSBuild/FlagTables/v142_CSharp.json index 4dcea9de32f..ae1bd47bf6b 100644 --- a/Templates/MSBuild/FlagTables/v142_CSharp.json +++ b/Templates/MSBuild/FlagTables/v142_CSharp.json @@ -381,52 +381,13 @@ }, { "name": "LangVersion", - "switch": "langversion:ISO-1", + "switch": "langversion:", "comment": "", - "value": "ISO-1", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:ISO-2", - "comment": "", - "value": "ISO-2", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:3", - "comment": "", - "value": "3", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:4", - "comment": "", - "value": "4", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:5", - "comment": "", - "value": "5", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:6", - "comment": "", - "value": "6", - "flags": [] - }, - { - "name": "LangVersion", - "switch": "langversion:default", - "comment": "", - "value": "default", - "flags": [] + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] }, { "name": "DelaySign", From 835896e985a0333e56623d16761dfa2b37d0a7e2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 20 Apr 2021 12:11:50 -0400 Subject: [PATCH 0272/1519] cmake: Improve error message when failing to update generation timestamp Include the underlying system error description. Issue: #21571, #22086 --- Source/cmake.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index af3a504fd97..d24e268d450 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3074,12 +3074,16 @@ static bool cmakeCheckStampFile(const std::string& stampName) cmsys::ofstream stamp(stampTemp.c_str()); stamp << "# CMake generation timestamp file for this directory.\n"; } - if (cmSystemTools::RenameFile(stampTemp, stampName)) { + std::string err; + if (cmSystemTools::RenameFile(stampTemp, stampName, + cmSystemTools::Replace::Yes, &err) == + cmSystemTools::RenameResult::Success) { // CMake does not need to re-run because the stamp file is up-to-date. return true; } cmSystemTools::RemoveFile(stampTemp); - cmSystemTools::Error("Cannot restore timestamp " + stampName); + cmSystemTools::Error( + cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err)); return false; } From 1b37305b0f3bfcf510a47fd38fb226c0364958ea Mon Sep 17 00:00:00 2001 From: oltolm Date: Wed, 21 Apr 2021 15:46:53 +0000 Subject: [PATCH 0273/1519] VS: Add support for ASAN -fsanitize=address flag Map it to the `EnableASAN` element in `.vcxproj` files. Fixes: #21081 --- Templates/MSBuild/FlagTables/v142_CL.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 7c2d291f9a1..9f079612963 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -1222,5 +1222,12 @@ "UserValue", "UserRequired" ] + }, + { + "name": "EnableASAN", + "switch": "fsanitize=address", + "comment": "Enable Address Sanitizer", + "value": "true", + "flags": [] } ] From 2e2db28e2f19ebde06d2bd5248a8828568dbd306 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 14:20:28 -0400 Subject: [PATCH 0274/1519] Find{BLAS,LAPACK}: Simplify check_function_exists state maintenance Now that `CHECK_{BLAS,LAPACK}_LIBRARIES` are functions, we can set `CMAKE_REQUIRED_QUIET` locally without affecting the global state. --- Modules/FindBLAS.cmake | 5 +---- Modules/FindLAPACK.cmake | 6 +----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index c23e41bac88..855d07902fd 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -176,10 +176,7 @@ if(CMAKE_Fortran_COMPILER_LOADED) else() include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake) endif() -include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -cmake_push_check_state() -set(CMAKE_REQUIRED_QUIET ${BLAS_FIND_QUIETLY}) if(BLA_PREFER_PKGCONFIG) find_package(PkgConfig) @@ -261,6 +258,7 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib if(_libraries_work) # Test this combination of libraries. set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_deps}) + set(CMAKE_REQUIRED_QUIET ${BLAS_FIND_QUIETLY}) if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() @@ -1086,5 +1084,4 @@ if(NOT BLA_F95) endif() _add_blas_target() -cmake_pop_check_state() set(CMAKE_FIND_LIBRARY_SUFFIXES ${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index d89c40d0c4d..3529b126c7f 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -127,7 +127,6 @@ if(CMAKE_Fortran_COMPILER_LOADED) else() include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake) endif() -include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) function(_add_lapack_target) @@ -164,9 +163,6 @@ function(_add_lapack_target) endfunction() macro(_lapack_find_library_setup) - cmake_push_check_state() - set(CMAKE_REQUIRED_QUIET ${LAPACK_FIND_QUIETLY}) - set(_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) if(BLA_STATIC) if(WIN32) @@ -185,7 +181,6 @@ endmacro() macro(_lapack_find_library_teardown) set(CMAKE_FIND_LIBRARY_SUFFIXES ${_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) unset(_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES) - cmake_pop_check_state() endmacro() # TODO: move this stuff to a separate module @@ -243,6 +238,7 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl if(_libraries_work) # Test this combination of libraries. set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${_libraries} ${_blas} ${_deps}) + set(CMAKE_REQUIRED_QUIET ${LAPACK_FIND_QUIETLY}) if(CMAKE_Fortran_COMPILER_LOADED) check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS) else() From 193714d67ddddee36f7b5245e05d40b96f1de802 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 14:22:35 -0400 Subject: [PATCH 0275/1519] Find{BLAS,LAPACK}: Simplify search for static libraries Now that `CHECK_{BLAS,LAPACK}_LIBRARIES` are functions, we can set `CMAKE_FIND_LIBRARY_SUFFIXES` locally without affecting the global state. This avoids the need for local state switching that was added in commit 9ef82d95d8 (FindBLAS: Fix detection of OpenMP as dependency of BLA_STATIC, 2021-04-07, v3.20.1~3^2), so remove that. --- Modules/FindBLAS.cmake | 32 +++++++++++++------------------- Modules/FindLAPACK.cmake | 38 +++++++++++++------------------------- 2 files changed, 26 insertions(+), 44 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 855d07902fd..f3a8b7439b5 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -189,20 +189,6 @@ if(BLA_PREFER_PKGCONFIG) endif() endif() -set(_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) -if(BLA_STATIC) - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) - endif() -else() - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - # for ubuntu's libblas3gf and liblapack3gf packages - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf) - endif() -endif() - # TODO: move this stuff to a separate module function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs) @@ -217,6 +203,19 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib set(_libraries) set(_combined_name) + if(BLA_STATIC) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + endif() + else() + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # for ubuntu's libblas3gf and liblapack3gf packages + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf) + endif() + endif() + set(_extaddlibdir "${_addlibdir}") if(WIN32) list(APPEND _extaddlibdir ENV LIB) @@ -626,8 +625,6 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All") endif() set(_threadlibs "${CMAKE_THREAD_LIBS_INIT}") if(BLA_STATIC) - set(_blas_STATIC_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") - set(CMAKE_FIND_LIBRARY_SUFFIXES "${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}") if (CMAKE_C_COMPILER_LOADED) find_package(OpenMP COMPONENTS C) list(PREPEND _threadlibs "${OpenMP_C_LIBRARIES}") @@ -635,8 +632,6 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All") find_package(OpenMP COMPONENTS CXX) list(PREPEND _threadlibs "${OpenMP_CXX_LIBRARIES}") endif() - set(CMAKE_FIND_LIBRARY_SUFFIXES "${_blas_STATIC_CMAKE_FIND_LIBRARY_SUFFIXES}") - unset(_blas_STATIC_CMAKE_FIND_LIBRARY_SUFFIXES) endif() check_blas_libraries( BLAS_LIBRARIES @@ -1084,4 +1079,3 @@ if(NOT BLA_F95) endif() _add_blas_target() -set(CMAKE_FIND_LIBRARY_SUFFIXES ${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 3529b126c7f..37ea1565a9a 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -162,27 +162,6 @@ function(_add_lapack_target) endif() endfunction() -macro(_lapack_find_library_setup) - set(_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(BLA_STATIC) - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) - endif() - else() - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - # for ubuntu's libblas3gf and liblapack3gf packages - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf) - endif() - endif() -endmacro() - -macro(_lapack_find_library_teardown) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) - unset(_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES) -endmacro() - # TODO: move this stuff to a separate module function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlibdir _subdirs _blas) @@ -197,6 +176,19 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl set(_libraries) set(_combined_name) + if(BLA_STATIC) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + endif() + else() + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # for ubuntu's libblas3gf and liblapack3gf packages + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf) + endif() + endif() + set(_extaddlibdir "${_addlibdir}") if(WIN32) list(APPEND _extaddlibdir ENV LIB) @@ -281,8 +273,6 @@ macro(_lapack_find_dependency dep) set(_lapack_quiet_arg) endmacro() -_lapack_find_library_setup() - set(LAPACK_LINKER_FLAGS) set(LAPACK_LIBRARIES) set(LAPACK95_LIBRARIES) @@ -667,5 +657,3 @@ if(LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES") endif() _add_lapack_target() - -_lapack_find_library_teardown() From cb6889a09c8cd538a0856942e429fddc78dbd24e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 14:26:18 -0400 Subject: [PATCH 0276/1519] FindLAPACK: Fix finding generic LAPACK with BLA_STATIC Fixes: #21071 --- Modules/FindLAPACK.cmake | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 37ea1565a9a..ab6214b48d5 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -620,17 +620,25 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) AND (BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All")) + if(BLA_STATIC) + # We do not know for sure how the LAPACK reference implementation + # is built on this host. Guess typical dependencies. + set(_lapack_generic_deps "-lgfortran;-lm") + else() + set(_lapack_generic_deps "") + endif() check_lapack_libraries( LAPACK_LIBRARIES LAPACK cheev "" "lapack" - "" + "${_lapack_generic_deps}" "" "" "${BLAS_LIBRARIES}" ) + unset(_lapack_generic_deps) endif() endif() From f3f715688fb2b73652aee97b478d14d9c7689322 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 14:30:17 -0400 Subject: [PATCH 0277/1519] Find{BLAS,LAPACK}: Add test case covering BLA_STATIC with Generic vendor --- .gitlab/ci/configure_debian10_aarch64_ninja.cmake | 2 ++ .gitlab/ci/configure_debian10_ninja.cmake | 2 ++ .gitlab/ci/configure_fedora33_makefiles.cmake | 2 ++ Tests/FindBLAS/CMakeLists.txt | 13 +++++++++++++ Tests/FindLAPACK/CMakeLists.txt | 13 +++++++++++++ 5 files changed, 32 insertions(+) diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index f665f7d20d5..8fc850c03b5 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -1,5 +1,6 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") set(CMake_TEST_FindBLAS "All" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC "Generic" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -24,6 +25,7 @@ set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") set(CMake_TEST_FindLAPACK "All" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC "Generic" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index 9de30134280..94cf6c102a2 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -1,5 +1,6 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") set(CMake_TEST_FindBLAS "All" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC "Generic" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -24,6 +25,7 @@ set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") set(CMake_TEST_FindLAPACK "All" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC "Generic" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora33_makefiles.cmake b/.gitlab/ci/configure_fedora33_makefiles.cmake index 4143134800b..7519d95c1d9 100644 --- a/.gitlab/ci/configure_fedora33_makefiles.cmake +++ b/.gitlab/ci/configure_fedora33_makefiles.cmake @@ -1,5 +1,6 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") set(CMake_TEST_FindBLAS "All" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC "Generic" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -24,6 +25,7 @@ set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") set(CMake_TEST_FindLAPACK "All" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC "Generic" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt index 47ec5681408..63ef1dde3b7 100644 --- a/Tests/FindBLAS/CMakeLists.txt +++ b/Tests/FindBLAS/CMakeLists.txt @@ -10,3 +10,16 @@ foreach(vendor IN LISTS CMake_TEST_FindBLAS) --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) endforeach() + +foreach(vendor IN LISTS CMake_TEST_FindBLAS_STATIC) + add_test(NAME FindBLAS.Test_${vendor}_Static COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" + "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${vendor}_Static" + ${build_generator_args} + --build-project TestFindBLAS + --build-options ${build_options} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +endforeach() diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt index 5e2ea7a6a3c..eab5bb44d6a 100644 --- a/Tests/FindLAPACK/CMakeLists.txt +++ b/Tests/FindLAPACK/CMakeLists.txt @@ -10,3 +10,16 @@ foreach(vendor IN LISTS CMake_TEST_FindLAPACK) --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) endforeach() + +foreach(vendor IN LISTS CMake_TEST_FindLAPACK_STATIC) + add_test(NAME FindLAPACK.Test_${vendor}_Static COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" + "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${vendor}_Static" + ${build_generator_args} + --build-project TestFindLAPACK + --build-options ${build_options} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +endforeach() From 051c3a04498f89483edc43b468ae25748a7032a4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 14:36:13 -0400 Subject: [PATCH 0278/1519] Find{BLAS,LAPACK}: Add test case covering BLA_STATIC with Intel MKL --- .gitlab/ci/configure_intelcompiler_common.cmake | 2 ++ Tests/FindBLAS/Test/CMakeLists.txt | 2 +- Tests/FindLAPACK/Test/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake index be3d15b6d1b..79f657be92b 100644 --- a/.gitlab/ci/configure_intelcompiler_common.cmake +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -1,4 +1,6 @@ set(CMake_TEST_FindBLAS "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC "Intel10_64lp" CACHE STRING "") set(CMake_TEST_FindLAPACK "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC "Intel10_64lp" CACHE STRING "") include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt index 1bebf8e99c4..98e12d5947c 100644 --- a/Tests/FindBLAS/Test/CMakeLists.txt +++ b/Tests/FindBLAS/Test/CMakeLists.txt @@ -13,7 +13,7 @@ target_link_libraries(test_var PRIVATE ${BLAS_LIBRARIES}) add_test(NAME test_var COMMAND test_var) if(BLA_VENDOR STREQUAL "Intel10_64lp") - if(NOT BLAS_LIBRARIES MATCHES "^[^;]*mkl_intel_lp64") + if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64") message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_lp64:\n ${BLAS_LIBRARIES}") endif() endif() diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt index 67fb9bd6d00..bb334824bc2 100644 --- a/Tests/FindLAPACK/Test/CMakeLists.txt +++ b/Tests/FindLAPACK/Test/CMakeLists.txt @@ -13,7 +13,7 @@ target_link_libraries(test_var PRIVATE ${LAPACK_LIBRARIES}) add_test(NAME test_var COMMAND test_var) if(BLA_VENDOR STREQUAL "Intel10_64lp") - if(NOT LAPACK_LIBRARIES MATCHES "^[^;]*mkl_intel_lp64") + if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64") message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_lp64:\n ${LAPACK_LIBRARIES}") endif() endif() From e4b793c614f2a499d4d235ec2267ad6bff56a697 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Tue, 20 Apr 2021 18:46:26 +0200 Subject: [PATCH 0279/1519] file(REAL_PATH): add option EXPAND_TILDE This option enables the replacement of any leading tilde with the path to the user's home directory. --- Help/command/cmake_path.rst | 3 +- Help/command/file.rst | 20 +++++++--- .../dev/file-REAL_PATH-EXPAND_TILDE.rst | 5 +++ Source/cmFileCommand.cxx | 23 +++++++++-- Tests/RunCMake/file/REAL_PATH.cmake | 40 ++++++++++++++----- Tests/RunCMake/file/RunCMakeTest.cmake | 7 ++-- 6 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst index a8999f35b12..193180d1728 100644 --- a/Help/command/cmake_path.rst +++ b/Help/command/cmake_path.rst @@ -687,7 +687,8 @@ When the ``NORMALIZE`` option is specified, the path is :ref:`normalized ` after the path computation. Because ``cmake_path()`` does not access the filesystem, symbolic links are -not resolved. To compute a real path with symbolic links resolved, use the +not resolved and any leading tilde is not expanded. To compute a real path +with symbolic links resolved and leading tildes expanded, use the :command:`file(REAL_PATH)` command instead. Native Conversion diff --git a/Help/command/file.rst b/Help/command/file.rst index 62642cfd5ee..e1705263337 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -50,7 +50,7 @@ Synopsis file(`CHMOD_RECURSE`_ ... ... PERMISSIONS ... [...]) `Path Conversion`_ - file(`REAL_PATH`_ [BASE_DIRECTORY ]) + file(`REAL_PATH`_ [BASE_DIRECTORY ] [EXPAND_TILDE]) file(`RELATIVE_PATH`_ ) file({`TO_CMAKE_PATH`_ | `TO_NATIVE_PATH`_} ) @@ -924,16 +924,26 @@ Path Conversion .. code-block:: cmake - file(REAL_PATH [BASE_DIRECTORY ]) + file(REAL_PATH [BASE_DIRECTORY ] [EXPAND_TILDE]) .. versionadded:: 3.19 Compute the absolute path to an existing file or directory with symlinks resolved. -If the provided ```` is a relative path, it is evaluated relative to the -given base directory ````. If no base directory is provided, the default -base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`. +``BASE_DIRECTORY `` + If the provided ```` is a relative path, it is evaluated relative to the + given base directory ````. If no base directory is provided, the default + base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`. + +``EXPAND_TILDE`` + .. versionadded:: 3.21 + + If the ```` is ``~`` or starts with ``~/``, the ``~`` is replaced by + the user's home directory. The path to the home directory is obtained from + environment variables. On Windows, the ``USERPROFILE`` environment variable + is used, falling back to the ``HOME`` environment variable if ``USERPROFILE`` + is not defined. On all other platforms, only ``HOME`` is used. .. _RELATIVE_PATH: diff --git a/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst b/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst new file mode 100644 index 00000000000..cdf1efa3cba --- /dev/null +++ b/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst @@ -0,0 +1,5 @@ +file-REAL_PATH-EXPAND_TILDE +--------------------------- + +* The :command:`file(REAL_PATH)` command gained the option ``EXPAND_TILDE`` to + replace any leading tilde with the path to the user's home directory. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 05ebcca1216..a94325834dc 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1246,9 +1246,12 @@ bool HandleRealPathCommand(std::vector const& args, struct Arguments { std::string BaseDirectory; + bool ExpandTilde = false; }; - static auto const parser = cmArgumentParser{}.Bind( - "BASE_DIRECTORY"_s, &Arguments::BaseDirectory); + static auto const parser = + cmArgumentParser{} + .Bind("BASE_DIRECTORY"_s, &Arguments::BaseDirectory) + .Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde); std::vector unparsedArguments; std::vector keywordsMissingValue; @@ -1270,7 +1273,21 @@ bool HandleRealPathCommand(std::vector const& args, arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); } - cmCMakePath path(args[1]); + auto input = args[1]; + if (arguments.ExpandTilde && !input.empty()) { + if (input[0] == '~' && (input.length() == 1 || input[1] == '/')) { + std::string home; + if ( +#if defined(_WIN32) && !defined(__CYGWIN__) + cmSystemTools::GetEnv("USERPROFILE", home) || +#endif + cmSystemTools::GetEnv("HOME", home)) { + input.replace(0, 1, home); + } + } + } + + cmCMakePath path(input, cmCMakePath::auto_format); path = path.Absolute(arguments.BaseDirectory).Normal(); auto realPath = cmSystemTools::GetRealPath(path.GenericString()); diff --git a/Tests/RunCMake/file/REAL_PATH.cmake b/Tests/RunCMake/file/REAL_PATH.cmake index be25706b291..0b5d3c0fd10 100644 --- a/Tests/RunCMake/file/REAL_PATH.cmake +++ b/Tests/RunCMake/file/REAL_PATH.cmake @@ -1,14 +1,36 @@ -file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt") -file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym") -file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC) +if (NOT WIN32 OR CYGWIN) + file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym") + file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC) -file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path) -if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") - message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") + file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path) + if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") + endif() + + file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") + endif() +endif() + + +If (WIN32) + cmake_path(SET HOME_DIR "$ENV{USERPROFILE}") + if (NOT HOME_DIR) + cmake_path(SET HOME_DIR "$ENV{HOME}") + endif() +else() + set(HOME_DIR "$ENV{HOME}") +endif() + +file(REAL_PATH "~" real_path EXPAND_TILDE) +if (NOT real_path STREQUAL "${HOME_DIR}") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${HOME_DIR}\"") endif() -file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") - message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") +file(REAL_PATH "~/test.txt" real_path EXPAND_TILDE) +if (NOT real_path STREQUAL "${HOME_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${HOME_DIR}/test.txt\"") endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index b4ea9bac309..6d1109a10de 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -96,11 +96,12 @@ if(NOT WIN32 OR CYGWIN) run_cmake(READ_SYMLINK-noexist) run_cmake(READ_SYMLINK-notsymlink) run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) - run_cmake(REAL_PATH-unexpected-arg) - run_cmake(REAL_PATH-no-base-dir) - run_cmake(REAL_PATH) endif() +run_cmake(REAL_PATH-unexpected-arg) +run_cmake(REAL_PATH-no-base-dir) +run_cmake(REAL_PATH) + if(RunCMake_GENERATOR MATCHES "Ninja") # Detect ninja version so we know what tests can be supported. execute_process( From 86b2457e922810a7648f0ab2c4104124ef73e5f0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 22 Apr 2021 00:01:07 -0400 Subject: [PATCH 0280/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0da463a0fcb..970dfaade10 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210421) +set(CMake_VERSION_PATCH 20210422) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From eb5e33ba474e061b302cd0b3b1ecb62625489532 Mon Sep 17 00:00:00 2001 From: Alexander Akhundzhanov Date: Sun, 11 Apr 2021 18:08:15 +1000 Subject: [PATCH 0281/1519] Xcode: Add support for embedding app extensions Co-Authored-By: Craig Scott --- Help/manual/cmake-properties.7.rst | 2 + ...ODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst | 5 ++ ...MBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst | 6 ++ Help/prop_tgt/XCODE_EMBED_type.rst | 20 ++++-- .../XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst | 18 +++++ Help/prop_tgt/XCODE_EMBED_type_PATH.rst | 13 +++- ...CODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst | 20 ++++++ Help/release/dev/xcode_app_extensions.rst | 11 +++ Source/cmGlobalXCodeGenerator.cxx | 71 +++++++++++++------ Source/cmGlobalXCodeGenerator.h | 13 ++++ Tests/RunCMake/CMakeLists.txt | 2 +- .../EmbedAppExtensions-iOS-check.cmake | 4 ++ .../EmbedAppExtensions-iOS.cmake | 1 + .../EmbedAppExtensions-macOS-check.cmake | 4 ++ .../EmbedAppExtensions-macOS.cmake | 1 + .../EmbedAppExtensions.cmake | 21 ++++++ Tests/RunCMake/XcodeProject-Embed/Empty.txt | 0 .../RunCMake/XcodeProject-Embed/Info.plist.in | 31 ++++++++ .../XcodeProject-Embed/RunCMakeTest.cmake | 31 ++++++++ 19 files changed, 246 insertions(+), 28 deletions(-) create mode 100644 Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst create mode 100644 Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst create mode 100644 Help/release/dev/xcode_app_extensions.rst create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake create mode 100644 Tests/RunCMake/XcodeProject-Embed/Empty.txt create mode 100644 Tests/RunCMake/XcodeProject-Embed/Info.plist.in diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index af170dabdea..d5600dd4494 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -402,7 +402,9 @@ Properties on Targets /prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY /prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY /prop_tgt/XCODE_EMBED_type + /prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY /prop_tgt/XCODE_EMBED_type_PATH + /prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY /prop_tgt/XCODE_EXPLICIT_FILE_TYPE /prop_tgt/XCODE_GENERATE_SCHEME /prop_tgt/XCODE_LINK_BUILD_PHASE_MODE diff --git a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst index 7b681267895..2a4d66672c9 100644 --- a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst +++ b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst @@ -6,3 +6,8 @@ XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY Tell the :generator:`Xcode` generator to perform code signing for all the frameworks and libraries that are embedded using the :prop_tgt:`XCODE_EMBED_FRAMEWORKS >` property. + +.. versionadded:: 3.21 + +This property was generalized to other types of embedded items. See +:prop_tgt:`XCODE_EMBED__CODE_SIGN_ON_COPY` for the more general form. diff --git a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst index 29f8c5c0341..04daa8559f8 100644 --- a/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst +++ b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst @@ -6,3 +6,9 @@ XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY Tell the :generator:`Xcode` generator to remove headers from all the frameworks that are embedded using the :prop_tgt:`XCODE_EMBED_FRAMEWORKS >` property. + +.. versionadded:: 3.21 + +This property was generalized to other types of embedded items. See +:prop_tgt:`XCODE_EMBED__REMOVE_HEADERS_ON_COPY` for the more +general form. diff --git a/Help/prop_tgt/XCODE_EMBED_type.rst b/Help/prop_tgt/XCODE_EMBED_type.rst index 90c5bc7879f..a1af56f12c2 100644 --- a/Help/prop_tgt/XCODE_EMBED_type.rst +++ b/Help/prop_tgt/XCODE_EMBED_type.rst @@ -5,10 +5,20 @@ XCODE_EMBED_ Tell the :generator:`Xcode` generator to embed the specified list of items into the target bundle. ```` specifies the embed build phase to use. +See the Xcode documentation for the base location of each ````. + +The supported values for ```` are: + +``FRAMEWORKS`` + The specified items will be added to the ``Embed Frameworks`` build phase. + The items can be CMake target names or paths to frameworks or libraries. + +``APP_EXTENSIONS`` + .. versionadded:: 3.21 + + The specified items will be added to the ``Embed App Extensions`` build phase. + They must be CMake target names. -Currently, the only supported value for ```` is ``FRAMEWORKS``. -The specified items will be added to the ``Embed Frameworks`` build phase. -The items can be CMake target names or paths to frameworks or libraries. See also :prop_tgt:`XCODE_EMBED__PATH`, -:prop_tgt:`XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY` and -:prop_tgt:`XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY`. +:prop_tgt:`XCODE_EMBED__REMOVE_HEADERS_ON_COPY` and +:prop_tgt:`XCODE_EMBED__CODE_SIGN_ON_COPY`. diff --git a/Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst new file mode 100644 index 00000000000..7ec03857b47 --- /dev/null +++ b/Help/prop_tgt/XCODE_EMBED_type_CODE_SIGN_ON_COPY.rst @@ -0,0 +1,18 @@ +XCODE_EMBED__CODE_SIGN_ON_COPY +------------------------------------ + +.. versionadded:: 3.20 + +Boolean property used only by the :generator:`Xcode` generator. It specifies +whether to perform code signing for the items that are embedded using the +:prop_tgt:`XCODE_EMBED_` property. + +The supported values for ```` are: + +``FRAMEWORKS`` + +``APP_EXTENSIONS`` + .. versionadded:: 3.21 + +If a ``XCODE_EMBED__CODE_SIGN_ON_COPY`` property is not defined on the +target, no code signing on copy will be performed for that ````. diff --git a/Help/prop_tgt/XCODE_EMBED_type_PATH.rst b/Help/prop_tgt/XCODE_EMBED_type_PATH.rst index 887cf5721e4..a6f980dccf5 100644 --- a/Help/prop_tgt/XCODE_EMBED_type_PATH.rst +++ b/Help/prop_tgt/XCODE_EMBED_type_PATH.rst @@ -3,7 +3,16 @@ XCODE_EMBED__PATH .. versionadded:: 3.20 -Tell the :generator:`Xcode` generator the relative path to use when embedding -the items specified by :prop_tgt:`XCODE_EMBED_`. The path is relative +This property is used only by the :generator:`Xcode` generator. When defined, +it specifies the relative path to use when embedding the items specified by +:prop_tgt:`XCODE_EMBED_`. The path is relative to the base location of the ``Embed XXX`` build phase associated with +````. See the Xcode documentation for the base location of each ````. + +The supported values for ```` are: + +``FRAMEWORKS`` + +``APP_EXTENSIONS`` + .. versionadded:: 3.21 diff --git a/Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst b/Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst new file mode 100644 index 00000000000..75c8eae13e5 --- /dev/null +++ b/Help/prop_tgt/XCODE_EMBED_type_REMOVE_HEADERS_ON_COPY.rst @@ -0,0 +1,20 @@ +XCODE_EMBED__REMOVE_HEADERS_ON_COPY +----------------------------------------- + +.. versionadded:: 3.20 + +Boolean property used only by the :generator:`Xcode` generator. It specifies +whether to remove headers from all the frameworks that are embedded using the +:prop_tgt:`XCODE_EMBED_` property. + +The supported values for ```` are: + +``FRAMEWORKS`` + If the ``XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY`` property is not + defined, headers will not be removed on copy by default. + +``APP_EXTENSIONS`` + .. versionadded:: 3.21 + + If the ``XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY`` property is not + defined, headers WILL be removed on copy by default. diff --git a/Help/release/dev/xcode_app_extensions.rst b/Help/release/dev/xcode_app_extensions.rst new file mode 100644 index 00000000000..7be7d82ecef --- /dev/null +++ b/Help/release/dev/xcode_app_extensions.rst @@ -0,0 +1,11 @@ +xcode_app_extensions +-------------------- + +* The :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS >` target property + was added to tell the :generator:`Xcode` generator to embed app extensions + such as iMessage sticker packs. + Aspects of the embedding can be customized with the + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_PATH >`, + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_CODE_SIGN_ON_COPY _CODE_SIGN_ON_COPY>` and + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY _REMOVE_HEADERS_ON_COPY>` + properties. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7dd17045ee1..e31cf01743f 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3728,7 +3728,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } } -void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) +void cmGlobalXCodeGenerator::AddEmbeddedObjects( + cmXCodeObject* target, const std::string& copyFilesBuildPhaseName, + const std::string& embedPropertyName, const std::string& dstSubfolderSpec, + int actionsOnByDefault) { cmGeneratorTarget* gt = target->GetTarget(); if (!gt) { @@ -3744,7 +3747,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { return; } - cmProp files = gt->GetProperty("XCODE_EMBED_FRAMEWORKS"); + cmProp files = gt->GetProperty(embedPropertyName); if (!files) { return; } @@ -3752,16 +3755,15 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) // Create an "Embedded Frameworks" build phase auto* copyFilesBuildPhase = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - std::string copyFilesBuildPhaseName = "Embed Frameworks"; - std::string destinationFrameworks = "10"; copyFilesBuildPhase->SetComment(copyFilesBuildPhaseName); copyFilesBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString(destinationFrameworks)); + this->CreateString(dstSubfolderSpec)); copyFilesBuildPhase->AddAttribute( "name", this->CreateString(copyFilesBuildPhaseName)); - if (cmProp fwEmbedPath = gt->GetProperty("XCODE_EMBED_FRAMEWORKS_PATH")) { + if (cmProp fwEmbedPath = + gt->GetProperty(cmStrCat(embedPropertyName, "_PATH"))) { copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(*fwEmbedPath)); } else { @@ -3775,10 +3777,10 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) for (std::string const& relFile : relFiles) { cmXCodeObject* buildFile{ nullptr }; std::string filePath = relFile; - auto* genTarget = FindGeneratorTarget(relFile); + auto* genTarget = this->FindGeneratorTarget(relFile); if (genTarget) { // This is a target - get it's product path reference - auto* xcTarget = FindXCodeTarget(genTarget); + auto* xcTarget = this->FindXCodeTarget(genTarget); if (!xcTarget) { cmSystemTools::Error("Can not find a target for " + genTarget->GetName()); @@ -3792,18 +3794,18 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) " is missing product reference"); continue; } - auto it = FileRefToEmbedBuildFileMap.find(fileRefObject); - if (it == FileRefToEmbedBuildFileMap.end()) { + auto it = this->FileRefToEmbedBuildFileMap.find(fileRefObject); + if (it == this->FileRefToEmbedBuildFileMap.end()) { buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); buildFile->AddAttribute("fileRef", fileRefObject); - FileRefToEmbedBuildFileMap[fileRefObject] = buildFile; + this->FileRefToEmbedBuildFileMap[fileRefObject] = buildFile; } else { buildFile = it->second; } } else if (cmSystemTools::IsPathToFramework(relFile)) { // This is a regular string path - create file reference - auto it = EmbeddedLibRefs.find(relFile); - if (it == EmbeddedLibRefs.end()) { + auto it = this->EmbeddedLibRefs.find(relFile); + if (it == this->EmbeddedLibRefs.end()) { cmXCodeObject* fileRef = this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr); if (fileRef) { @@ -3829,16 +3831,25 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); - const auto& rmHeadersProp = - gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY"); - if (cmIsOn(rmHeadersProp)) { + + bool removeHeaders = actionsOnByDefault & RemoveHeadersOnCopyByDefault; + if (auto prop = gt->GetProperty( + cmStrCat(embedPropertyName, "_REMOVE_HEADERS_ON_COPY"))) { + removeHeaders = cmIsOn(*prop); + } + if (removeHeaders) { attrs->AddObject(this->CreateString("RemoveHeadersOnCopy")); } - const auto& codeSignProp = - gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY"); - if (cmIsOn(codeSignProp)) { + + bool codeSign = actionsOnByDefault & CodeSignOnCopyByDefault; + if (auto prop = + gt->GetProperty(cmStrCat(embedPropertyName, "_CODE_SIGN_ON_COPY"))) { + codeSign = cmIsOn(*prop); + } + if (codeSign) { attrs->AddObject(this->CreateString("CodeSignOnCopy")); } + settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs); buildFile->AddAttributeIfNotEmpty("settings", settings); if (!buildFiles->HasObject(buildFile)) { @@ -3847,11 +3858,30 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) } copyFilesBuildPhase->AddAttribute("files", buildFiles); auto* buildPhases = target->GetAttribute("buildPhases"); - // Insert embed build phase right before the post-build command + // Embed-something build phases must be inserted before the post-build + // command because that command is expected to be last buildPhases->InsertObject(buildPhases->GetObjectCount() - 1, copyFilesBuildPhase); } +void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) +{ + static const auto dstSubfolderSpec = "10"; + + this->AddEmbeddedObjects(target, "Embed Frameworks", + "XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec, + NoActionOnCopyByDefault); +} + +void cmGlobalXCodeGenerator::AddEmbeddedAppExtensions(cmXCodeObject* target) +{ + static const auto dstSubfolderSpec = "13"; + + this->AddEmbeddedObjects(target, "Embed App Extensions", + "XCODE_EMBED_APP_EXTENSIONS", dstSubfolderSpec, + RemoveHeadersOnCopyByDefault); +} + bool cmGlobalXCodeGenerator::CreateGroups( std::vector& generators) { @@ -4231,6 +4261,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( for (auto t : targets) { this->AddDependAndLinkInformation(t); this->AddEmbeddedFrameworks(t); + this->AddEmbeddedAppExtensions(t); // Inherit project-wide values for any target-specific search paths. this->InheritBuildSettingAttribute(t, "HEADER_SEARCH_PATHS"); this->InheritBuildSettingAttribute(t, "SYSTEM_HEADER_SEARCH_PATHS"); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1ab56e20eb0..f182584616d 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -132,6 +132,13 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator } private: + enum EmbedActionFlags + { + NoActionOnCopyByDefault = 0, + CodeSignOnCopyByDefault = 1, + RemoveHeadersOnCopyByDefault = 2, + }; + bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); bool ProcessGeneratorToolsetField(std::string const& key, std::string const& value, cmMakefile* mf); @@ -196,7 +203,13 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator const char* attribute); cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt); void AddDependAndLinkInformation(cmXCodeObject* target); + void AddEmbeddedObjects(cmXCodeObject* target, + const std::string& copyFilesBuildPhaseName, + const std::string& embedPropertyName, + const std::string& dstSubfolderSpec, + int actionsOnByDefault); void AddEmbeddedFrameworks(cmXCodeObject* target); + void AddEmbeddedAppExtensions(cmXCodeObject* target); void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target, cmXCodeObject* buildSettings, const std::string& configName); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 354a04eca39..68db0f2d899 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -545,7 +545,7 @@ endif() if(XCODE_VERSION) add_RunCMake_test(XcodeProject -DXCODE_VERSION=${XCODE_VERSION}) - add_RunCMake_test(XcodeProject-Embed) + add_RunCMake_test(XcodeProject-Embed -DXCODE_VERSION=${XCODE_VERSION}) # This test can take a very long time due to lots of combinations. # Use a long default timeout and provide an option to customize it. diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake new file mode 100644 index 00000000000..576be11f0a7 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS-check.cmake @@ -0,0 +1,4 @@ +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) + +findAttribute(${test} "RemoveHeadersOnCopy" TRUE) +findAttribute(${test} "CodeSignOnCopy" FALSE) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake new file mode 100644 index 00000000000..839f8424d17 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-iOS.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/EmbedAppExtensions.cmake) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake new file mode 100644 index 00000000000..576be11f0a7 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS-check.cmake @@ -0,0 +1,4 @@ +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) + +findAttribute(${test} "RemoveHeadersOnCopy" TRUE) +findAttribute(${test} "CodeSignOnCopy" FALSE) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake new file mode 100644 index 00000000000..839f8424d17 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions-macOS.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/EmbedAppExtensions.cmake) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake new file mode 100644 index 00000000000..d7494ea195c --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedAppExtensions.cmake @@ -0,0 +1,21 @@ +add_library(app_extension MODULE Empty.txt) +set_target_properties(app_extension PROPERTIES + LINKER_LANGUAGE CXX + BUNDLE YES + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" + XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in" + MACOSX_BUNDLE_GUI_IDENTIFIER "com.example.app.app_extension" + XCODE_PRODUCT_TYPE "com.apple.product-type.app-extension" + XCODE_EXPLICIT_FILE_TYPE "wrapper.app-extension" +) + +add_executable(app MACOSX_BUNDLE main.m) +add_dependencies(app app_extension) +set_target_properties(app PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" + XCODE_EMBED_APP_EXTENSIONS app_extension + MACOSX_BUNDLE_GUI_IDENTIFIER "com.example.app" +) diff --git a/Tests/RunCMake/XcodeProject-Embed/Empty.txt b/Tests/RunCMake/XcodeProject-Embed/Empty.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/XcodeProject-Embed/Info.plist.in b/Tests/RunCMake/XcodeProject-Embed/Info.plist.in new file mode 100644 index 00000000000..a26f3163039 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/Info.plist.in @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + SomeExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.example.app.app_extension + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + app + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1.0.0 + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + NSExtensionPrincipalClass + SomeExtensionBrowserViewController + + + diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake index 0dc1cf31c32..e94d084c10c 100644 --- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake @@ -41,3 +41,34 @@ endfunction() TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir) TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir) + + +function(TestAppExtension platform) + set(testName EmbedAppExtensions-${platform}) + if(NOT platform STREQUAL "macOS") + set(RunCMake_TEST_OPTIONS -DCMAKE_SYSTEM_NAME=${platform}) + endif() + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build) + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(${testName}) + run_cmake_command(${testName}-build + ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} + --config Debug + --target app + ) +endfunction() + +# Isolate device tests from host architecture selection. +unset(ENV{CMAKE_OSX_ARCHITECTURES}) + +if(XCODE_VERSION VERSION_GREATER_EQUAL 8) + # The various flag on/off combinations are tested by the EmbedFrameworks... + # tests, so we don't duplicate all the combinations here. We only verify the + # defaults, which is to remove headers on copy, but not code sign. + TestAppExtension(macOS) + TestAppExtension(iOS) +endif() From 625ef88a92d6632e3efd5ee4d6578bfc77928679 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Apr 2021 09:51:31 -0400 Subject: [PATCH 0282/1519] CUDA: Add CMAKE_CUDA_HOST_COMPILER support on Windows non-VS generators --- Help/envvar/CUDAHOSTCXX.rst | 4 ++++ Help/variable/CMAKE_CUDA_HOST_COMPILER.rst | 4 ++++ Modules/CMakeCUDAInformation.cmake | 7 ------- Modules/CMakeDetermineCUDACompiler.cmake | 15 +++++++++------ Modules/Compiler/NVIDIA-CUDA.cmake | 14 +++++--------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Help/envvar/CUDAHOSTCXX.rst b/Help/envvar/CUDAHOSTCXX.rst index 963f9d11301..cf65927a51c 100644 --- a/Help/envvar/CUDAHOSTCXX.rst +++ b/Help/envvar/CUDAHOSTCXX.rst @@ -15,6 +15,10 @@ ignored if the :variable:`CMAKE_CUDA_HOST_COMPILER` variable is defined. This environment variable is primarily meant for use with projects that enable ``CUDA`` as a first-class language. +.. note:: + + Ignored when using :ref:`Visual Studio Generators`. + .. versionadded:: 3.13 The :module:`FindCUDA` module will use this variable to initialize its ``CUDA_HOST_COMPILER`` setting. diff --git a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst index d5fcb7dbf0b..9817b1a1207 100644 --- a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst +++ b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst @@ -23,3 +23,7 @@ is read-only and changes to it are undefined behavior. :variable:`CMAKE_CUDA_COMPILER_ID _COMPILER_ID>` is ``NVIDIA``, it does not make sense to set ``CMAKE_CUDA_HOST_COMPILER`` without also setting ``CMAKE_CUDA_COMPILER`` to NVCC. + +.. note:: + + Ignored when using :ref:`Visual Studio Generators`. diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 44e2c2c3304..541d207f84a 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -110,13 +110,6 @@ include(CMakeCommonLanguageInclude) # CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION # CMAKE_CUDA_LINK_EXECUTABLE -if(CMAKE_CUDA_HOST_COMPILER AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") - # FIXME: This is too late for the Platform/Windows-NVIDIA-CUDA module to - # see it, so we do not support CMAKE_CUDA_HOST_COMPILER on Windows. - # Move this to Compiler/NVIDIA-CUDA and update the VS generator too. - string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=") -endif() - # create a shared library if(NOT CMAKE_CUDA_CREATE_SHARED_LIBRARY) set(CMAKE_CUDA_CREATE_SHARED_LIBRARY diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 0f507eaa174..38c5e9cab2e 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -11,6 +11,9 @@ if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR endif() if(${CMAKE_GENERATOR} MATCHES "Visual Studio") + if(DEFINED ENV{CUDAHOSTCXX} OR DEFINED CMAKE_CUDA_HOST_COMPILER) + message(WARNING "Visual Studio does not support specifying CUDAHOSTCXX or CMAKE_CUDA_HOST_COMPILER. Using the C++ compiler provided by Visual Studio.") + endif() else() if(NOT CMAKE_CUDA_COMPILER) set(CMAKE_CUDA_COMPILER_INIT NOTFOUND) @@ -39,13 +42,13 @@ else() endif() mark_as_advanced(CMAKE_CUDA_COMPILER) -endif() -#Allow the user to specify a host compiler -if(NOT $ENV{CUDAHOSTCXX} STREQUAL "") - get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM) - if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER}) - message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}") + #Allow the user to specify a host compiler except for Visual Studio + if(NOT $ENV{CUDAHOSTCXX} STREQUAL "") + get_filename_component(CMAKE_CUDA_HOST_COMPILER $ENV{CUDAHOSTCXX} PROGRAM) + if(NOT EXISTS ${CMAKE_CUDA_HOST_COMPILER}) + message(FATAL_ERROR "Could not find compiler set in environment variable CUDAHOSTCXX:\n$ENV{CUDAHOSTCXX}.\n${CMAKE_CUDA_HOST_COMPILER}") + endif() endif() endif() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index a0f7c05e849..c2fe42df201 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -24,21 +24,17 @@ else() set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") endif() +if(CMAKE_CUDA_HOST_COMPILER AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") + string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=") +endif() + if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) # The -MD flag was only added to nvcc in 10.2 so # before that we had to invoke the compiler twice # to get header dependency information set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT -MF ") else() - if(CMAKE_CUDA_HOST_COMPILER AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - # FIXME: Move the main -ccbin= flag from CMakeCUDAInformation to - # a block above, remove this copy, and update the VS generator too. - set(_CMAKE_CUDA_EXTRA_FLAGS_LOCAL " -ccbin=") - else() - set(_CMAKE_CUDA_EXTRA_FLAGS_LOCAL "") - endif() - set(CMAKE_CUDA_DEPENDS_EXTRA_COMMANDS " ${_CMAKE_CUDA_EXTRA_FLAGS}${_CMAKE_CUDA_EXTRA_FLAGS_LOCAL} ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M -MT -o ") - unset(_CMAKE_CUDA_EXTRA_FLAGS_LOCAL) + set(CMAKE_CUDA_DEPENDS_EXTRA_COMMANDS " ${_CMAKE_CUDA_EXTRA_FLAGS} ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M -MT -o ") endif() set(CMAKE_CUDA_DEPFILE_FORMAT gcc) if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) From 741b85b42b4c8d826634b3f968d7de21df5f6c85 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Fri, 16 Apr 2021 18:00:46 +0200 Subject: [PATCH 0283/1519] liblzma: Revise update script to get version 5.2.5 Keep files related to multi threaded stream encoding. --- Utilities/Scripts/update-liblzma.bash | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-liblzma.bash b/Utilities/Scripts/update-liblzma.bash index fdf66b3eca6..a5a71750e0d 100755 --- a/Utilities/Scripts/update-liblzma.bash +++ b/Utilities/Scripts/update-liblzma.bash @@ -8,12 +8,17 @@ readonly name="liblzma" readonly ownership="liblzma upstream " readonly subtree="Utilities/cmliblzma" readonly repo="https://git.tukaani.org/xz.git" -readonly tag="v5.2.4" +readonly tag="v5.2.5" readonly shortlog=false readonly paths=" COPYING src/common/common_w32res.rc + src/common/mythread.h src/common/sysdefs.h + src/common/tuklib_common.h + src/common/tuklib_config.h + src/common/tuklib_cpucores.c + src/common/tuklib_cpucores.h src/common/tuklib_integer.h src/liblzma/ " From 298760661f30faf2014f609506f15ff2d3489ddf Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 22 Apr 2021 13:06:11 -0400 Subject: [PATCH 0284/1519] ExternalData: Improve error message when we fail to create a file Report the underlying system error. --- Modules/ExternalData.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 1850e746252..189374be42c 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -949,7 +949,7 @@ function(_ExternalData_link_or_copy src dst) endif() if(result) file(REMOVE "${tmp}") - message(FATAL_ERROR "Failed to create\n ${tmp}\nfrom\n ${obj}") + message(FATAL_ERROR "Failed to create:\n \"${tmp}\"\nfrom:\n \"${obj}\"\nwith error:\n ${result}") endif() # Atomically create/replace the real destination. From c54c284de7bab8fcc88bf8cb58fb79f2e3b47f72 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 22 Apr 2021 13:43:04 -0400 Subject: [PATCH 0285/1519] Tests: Improve RunCMake.CPack* test error formatting Format message content for `message(FATAL_ERROR)`. --- Tests/RunCMake/CPack/VerifyResult.cmake | 36 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake index 0ab545a28e0..294b9e8427f 100644 --- a/Tests/RunCMake/CPack/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/VerifyResult.cmake @@ -29,8 +29,16 @@ file(READ "${bin_dir}/test_output.txt" output) file(READ "${bin_dir}/test_error.txt" error) file(READ "${config_file}" config_file_content) -set(output_error_message - "\nCPack output: '${output}'\nCPack error: '${error}';\nCPack result: '${PACKAGING_RESULT}';\nconfig file: '${config_file_content}'") +string(REPLACE "\n" "\n cpack-out> " cpack_out "\n${output}") +string(REPLACE "\n" "\n cpack-err> " cpack_err "\n${error}") +string(REPLACE "\n" "\n cpack-res> " cpack_res "\n${PACKAGING_RESULT}") +string(REPLACE "\n" "\n cpack-cfg> " cpack_cfg "\n${config_file_content}") +string(CONCAT output_error_message + "CPack output:${cpack_out}\n" + "CPack error:${cpack_err}\n" + "CPack result:${cpack_res}\n" + "CPack config file:${cpack_cfg}" + ) # generate default expected files data include("${src_dir}/tests/${RunCMake_TEST_FILE_PREFIX}/ExpectedFiles.cmake") @@ -74,22 +82,22 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0) string(REPLACE "\n" "\n actual> " msg_actual "\n${PACKAGE_CONTENT}") string(REPLACE "\n" "\n expect> " msg_expected "\n${EXPECTED_FILE_CONTENT_${file_no_}}") message(FATAL_ERROR - "Unexpected file content for file No. '${file_no_}'!\n" + "Unexpected file content for file ${file_no_}!\n" "The content was:${msg_actual}\n" "which does not match:${msg_expected}\n" "${output_error_message}") endif() elseif(foundFilescount_ EQUAL 0) message(FATAL_ERROR - "Found no files for file No. '${file_no_}'!" - " Globbing expression: '${EXPECTED_FILE_${file_no_}}'" + "Found no files for file ${file_no_}!\n" + "Globbing expression:\n '${EXPECTED_FILE_${file_no_}}'\n" "${output_error_message}") else() message(FATAL_ERROR - "Found more than one file for file No. '${file_no_}'!" - " Found files count '${foundFilesCount_}'." - " Files: '${FOUND_FILE_${file_no_}}'" - " Globbing expression: '${EXPECTED_FILE_${file_no_}}'" + "Found more than one file for file ${file_no_}!\n" + "Found files count '${foundFilesCount_}'.\n" + "Files:\n '${FOUND_FILE_${file_no_}}'\n" + "Globbing expression:\n '${EXPECTED_FILE_${file_no_}}'\n" "${output_error_message}") endif() endforeach() @@ -105,7 +113,8 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0) if(NOT foundFilesCount_ EQUAL allFoundFilesCount_) message(FATAL_ERROR - "Found more files than expected! Found files: '${allFoundFiles_}'" + "Found more files than expected!\n" + "Found files:\n '${allFoundFiles_}'\n" "${output_error_message}") endif() @@ -116,8 +125,9 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0) if(found_ EQUAL -1) message(FATAL_ERROR - "Expected files don't match found files! Found files:" - " '${allFoundFiles_}'" + "Expected files don't match found files!\n" + "Found files:\n" + " '${allFoundFiles_}'\n" "${output_error_message}") endif() endforeach() @@ -127,7 +137,7 @@ else() file(GLOB checkMissingFiles_ RELATIVE "${bin_dir}" "${missing_file_glob_}") if(checkMissingFiles_) - message(FATAL_ERROR "Unexpected files found: '${checkMissingFiles_}'" + message(FATAL_ERROR "Unexpected files found:\n '${checkMissingFiles_}'\n" "${output_error_message}") endif() endforeach() From ee909a8e8b785b68c6a14fd52cc12b1841051a7d Mon Sep 17 00:00:00 2001 From: liblzma upstream Date: Tue, 17 Mar 2020 16:27:42 +0200 Subject: [PATCH 0286/1519] liblzma 2020-03-17 (2327a461) Code extracted from: https://git.tukaani.org/xz.git at commit 2327a461e1afce862c22269b80d3517801103c1b (v5.2.5). --- common/mythread.h | 521 +++++++++++++++++++++ common/sysdefs.h | 11 +- common/tuklib_common.h | 71 +++ common/tuklib_config.h | 7 + common/tuklib_cpucores.c | 100 ++++ common/tuklib_cpucores.h | 23 + common/tuklib_integer.h | 520 ++++++++++++++------ liblzma/api/lzma.h | 5 +- liblzma/api/lzma/block.h | 2 +- liblzma/api/lzma/filter.h | 7 +- liblzma/api/lzma/hardware.h | 2 +- liblzma/api/lzma/lzma12.h | 2 +- liblzma/api/lzma/version.h | 2 +- liblzma/api/lzma/vli.h | 2 +- liblzma/check/crc32_fast.c | 4 +- liblzma/check/crc32_table.c | 3 + liblzma/check/crc64_fast.c | 4 +- liblzma/check/crc64_table.c | 3 + liblzma/common/alone_decoder.c | 3 +- liblzma/common/alone_encoder.c | 9 +- liblzma/common/block_header_decoder.c | 4 +- liblzma/common/block_header_encoder.c | 2 +- liblzma/common/block_util.c | 2 +- liblzma/common/common.c | 8 +- liblzma/common/filter_common.h | 2 +- liblzma/common/filter_decoder.h | 2 +- liblzma/common/filter_flags_encoder.c | 2 +- liblzma/common/hardware_physmem.c | 2 +- liblzma/common/index.c | 8 +- liblzma/common/memcmplen.h | 19 +- liblzma/common/stream_encoder_mt.c | 4 +- liblzma/common/stream_flags_decoder.c | 6 +- liblzma/common/stream_flags_encoder.c | 8 +- liblzma/common/vli_decoder.c | 2 +- liblzma/delta/delta_decoder.c | 2 +- liblzma/lz/lz_decoder.c | 17 +- liblzma/lz/lz_encoder_hash.h | 2 +- liblzma/lz/lz_encoder_mf.c | 2 +- liblzma/lzma/fastpos.h | 2 +- liblzma/lzma/fastpos_tablegen.c | 1 - liblzma/lzma/lzma2_decoder.c | 8 +- liblzma/lzma/lzma_common.h | 3 +- liblzma/lzma/lzma_decoder.c | 18 +- liblzma/lzma/lzma_encoder.c | 2 +- liblzma/lzma/lzma_encoder_optimum_normal.c | 16 +- liblzma/lzma/lzma_encoder_private.h | 3 +- liblzma/simple/arm.c | 6 +- liblzma/simple/armthumb.c | 8 +- liblzma/simple/ia64.c | 2 +- liblzma/simple/powerpc.c | 9 +- liblzma/simple/simple_coder.c | 10 +- liblzma/simple/simple_decoder.c | 2 +- liblzma/simple/simple_encoder.c | 2 +- liblzma/simple/x86.c | 2 +- 54 files changed, 1216 insertions(+), 273 deletions(-) create mode 100644 common/mythread.h create mode 100644 common/tuklib_common.h create mode 100644 common/tuklib_config.h create mode 100644 common/tuklib_cpucores.c create mode 100644 common/tuklib_cpucores.h diff --git a/common/mythread.h b/common/mythread.h new file mode 100644 index 00000000000..be22654240a --- /dev/null +++ b/common/mythread.h @@ -0,0 +1,521 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file mythread.h +/// \brief Some threading related helper macros and functions +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef MYTHREAD_H +#define MYTHREAD_H + +#include "sysdefs.h" + +// If any type of threading is enabled, #define MYTHREAD_ENABLED. +#if defined(MYTHREAD_POSIX) || defined(MYTHREAD_WIN95) \ + || defined(MYTHREAD_VISTA) +# define MYTHREAD_ENABLED 1 +#endif + + +#ifdef MYTHREAD_ENABLED + +//////////////////////////////////////// +// Shared between all threading types // +//////////////////////////////////////// + +// Locks a mutex for a duration of a block. +// +// Perform mythread_mutex_lock(&mutex) in the beginning of a block +// and mythread_mutex_unlock(&mutex) at the end of the block. "break" +// may be used to unlock the mutex and jump out of the block. +// mythread_sync blocks may be nested. +// +// Example: +// +// mythread_sync(mutex) { +// foo(); +// if (some_error) +// break; // Skips bar() +// bar(); +// } +// +// At least GCC optimizes the loops completely away so it doesn't slow +// things down at all compared to plain mythread_mutex_lock(&mutex) +// and mythread_mutex_unlock(&mutex) calls. +// +#define mythread_sync(mutex) mythread_sync_helper1(mutex, __LINE__) +#define mythread_sync_helper1(mutex, line) mythread_sync_helper2(mutex, line) +#define mythread_sync_helper2(mutex, line) \ + for (unsigned int mythread_i_ ## line = 0; \ + mythread_i_ ## line \ + ? (mythread_mutex_unlock(&(mutex)), 0) \ + : (mythread_mutex_lock(&(mutex)), 1); \ + mythread_i_ ## line = 1) \ + for (unsigned int mythread_j_ ## line = 0; \ + !mythread_j_ ## line; \ + mythread_j_ ## line = 1) +#endif + + +#if !defined(MYTHREAD_ENABLED) + +////////////////// +// No threading // +////////////////// + +// Calls the given function once. This isn't thread safe. +#define mythread_once(func) \ +do { \ + static bool once_ = false; \ + if (!once_) { \ + func(); \ + once_ = true; \ + } \ +} while (0) + + +#if !(defined(_WIN32) && !defined(__CYGWIN__)) +// Use sigprocmask() to set the signal mask in single-threaded programs. +#include + +static inline void +mythread_sigmask(int how, const sigset_t *restrict set, + sigset_t *restrict oset) +{ + int ret = sigprocmask(how, set, oset); + assert(ret == 0); + (void)ret; +} +#endif + + +#elif defined(MYTHREAD_POSIX) + +//////////////////// +// Using pthreads // +//////////////////// + +#include +#include +#include +#include +#include + +#define MYTHREAD_RET_TYPE void * +#define MYTHREAD_RET_VALUE NULL + +typedef pthread_t mythread; +typedef pthread_mutex_t mythread_mutex; + +typedef struct { + pthread_cond_t cond; +#ifdef HAVE_CLOCK_GETTIME + // Clock ID (CLOCK_REALTIME or CLOCK_MONOTONIC) associated with + // the condition variable. + clockid_t clk_id; +#endif +} mythread_cond; + +typedef struct timespec mythread_condtime; + + +// Calls the given function once in a thread-safe way. +#define mythread_once(func) \ + do { \ + static pthread_once_t once_ = PTHREAD_ONCE_INIT; \ + pthread_once(&once_, &func); \ + } while (0) + + +// Use pthread_sigmask() to set the signal mask in multi-threaded programs. +// Do nothing on OpenVMS since it lacks pthread_sigmask(). +static inline void +mythread_sigmask(int how, const sigset_t *restrict set, + sigset_t *restrict oset) +{ +#ifdef __VMS + (void)how; + (void)set; + (void)oset; +#else + int ret = pthread_sigmask(how, set, oset); + assert(ret == 0); + (void)ret; +#endif +} + + +// Creates a new thread with all signals blocked. Returns zero on success +// and non-zero on error. +static inline int +mythread_create(mythread *thread, void *(*func)(void *arg), void *arg) +{ + sigset_t old; + sigset_t all; + sigfillset(&all); + + mythread_sigmask(SIG_SETMASK, &all, &old); + const int ret = pthread_create(thread, NULL, func, arg); + mythread_sigmask(SIG_SETMASK, &old, NULL); + + return ret; +} + +// Joins a thread. Returns zero on success and non-zero on error. +static inline int +mythread_join(mythread thread) +{ + return pthread_join(thread, NULL); +} + + +// Initiatlizes a mutex. Returns zero on success and non-zero on error. +static inline int +mythread_mutex_init(mythread_mutex *mutex) +{ + return pthread_mutex_init(mutex, NULL); +} + +static inline void +mythread_mutex_destroy(mythread_mutex *mutex) +{ + int ret = pthread_mutex_destroy(mutex); + assert(ret == 0); + (void)ret; +} + +static inline void +mythread_mutex_lock(mythread_mutex *mutex) +{ + int ret = pthread_mutex_lock(mutex); + assert(ret == 0); + (void)ret; +} + +static inline void +mythread_mutex_unlock(mythread_mutex *mutex) +{ + int ret = pthread_mutex_unlock(mutex); + assert(ret == 0); + (void)ret; +} + + +// Initializes a condition variable. +// +// Using CLOCK_MONOTONIC instead of the default CLOCK_REALTIME makes the +// timeout in pthread_cond_timedwait() work correctly also if system time +// is suddenly changed. Unfortunately CLOCK_MONOTONIC isn't available +// everywhere while the default CLOCK_REALTIME is, so the default is +// used if CLOCK_MONOTONIC isn't available. +// +// If clock_gettime() isn't available at all, gettimeofday() will be used. +static inline int +mythread_cond_init(mythread_cond *mycond) +{ +#ifdef HAVE_CLOCK_GETTIME + // NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1. +# if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && HAVE_DECL_CLOCK_MONOTONIC + struct timespec ts; + pthread_condattr_t condattr; + + // POSIX doesn't seem to *require* that pthread_condattr_setclock() + // will fail if given an unsupported clock ID. Test that + // CLOCK_MONOTONIC really is supported using clock_gettime(). + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0 + && pthread_condattr_init(&condattr) == 0) { + int ret = pthread_condattr_setclock( + &condattr, CLOCK_MONOTONIC); + if (ret == 0) + ret = pthread_cond_init(&mycond->cond, &condattr); + + pthread_condattr_destroy(&condattr); + + if (ret == 0) { + mycond->clk_id = CLOCK_MONOTONIC; + return 0; + } + } + + // If anything above fails, fall back to the default CLOCK_REALTIME. + // POSIX requires that all implementations of clock_gettime() must + // support at least CLOCK_REALTIME. +# endif + + mycond->clk_id = CLOCK_REALTIME; +#endif + + return pthread_cond_init(&mycond->cond, NULL); +} + +static inline void +mythread_cond_destroy(mythread_cond *cond) +{ + int ret = pthread_cond_destroy(&cond->cond); + assert(ret == 0); + (void)ret; +} + +static inline void +mythread_cond_signal(mythread_cond *cond) +{ + int ret = pthread_cond_signal(&cond->cond); + assert(ret == 0); + (void)ret; +} + +static inline void +mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex) +{ + int ret = pthread_cond_wait(&cond->cond, mutex); + assert(ret == 0); + (void)ret; +} + +// Waits on a condition or until a timeout expires. If the timeout expires, +// non-zero is returned, otherwise zero is returned. +static inline int +mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex, + const mythread_condtime *condtime) +{ + int ret = pthread_cond_timedwait(&cond->cond, mutex, condtime); + assert(ret == 0 || ret == ETIMEDOUT); + return ret; +} + +// Sets condtime to the absolute time that is timeout_ms milliseconds +// in the future. The type of the clock to use is taken from cond. +static inline void +mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond, + uint32_t timeout_ms) +{ + condtime->tv_sec = timeout_ms / 1000; + condtime->tv_nsec = (timeout_ms % 1000) * 1000000; + +#ifdef HAVE_CLOCK_GETTIME + struct timespec now; + int ret = clock_gettime(cond->clk_id, &now); + assert(ret == 0); + (void)ret; + + condtime->tv_sec += now.tv_sec; + condtime->tv_nsec += now.tv_nsec; +#else + (void)cond; + + struct timeval now; + gettimeofday(&now, NULL); + + condtime->tv_sec += now.tv_sec; + condtime->tv_nsec += now.tv_usec * 1000L; +#endif + + // tv_nsec must stay in the range [0, 999_999_999]. + if (condtime->tv_nsec >= 1000000000L) { + condtime->tv_nsec -= 1000000000L; + ++condtime->tv_sec; + } +} + + +#elif defined(MYTHREAD_WIN95) || defined(MYTHREAD_VISTA) + +///////////////////// +// Windows threads // +///////////////////// + +#define WIN32_LEAN_AND_MEAN +#ifdef MYTHREAD_VISTA +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +#endif +#include +#include + +#define MYTHREAD_RET_TYPE unsigned int __stdcall +#define MYTHREAD_RET_VALUE 0 + +typedef HANDLE mythread; +typedef CRITICAL_SECTION mythread_mutex; + +#ifdef MYTHREAD_WIN95 +typedef HANDLE mythread_cond; +#else +typedef CONDITION_VARIABLE mythread_cond; +#endif + +typedef struct { + // Tick count (milliseconds) in the beginning of the timeout. + // NOTE: This is 32 bits so it wraps around after 49.7 days. + // Multi-day timeouts may not work as expected. + DWORD start; + + // Length of the timeout in milliseconds. The timeout expires + // when the current tick count minus "start" is equal or greater + // than "timeout". + DWORD timeout; +} mythread_condtime; + + +// mythread_once() is only available with Vista threads. +#ifdef MYTHREAD_VISTA +#define mythread_once(func) \ + do { \ + static INIT_ONCE once_ = INIT_ONCE_STATIC_INIT; \ + BOOL pending_; \ + if (!InitOnceBeginInitialize(&once_, 0, &pending_, NULL)) \ + abort(); \ + if (pending_) \ + func(); \ + if (!InitOnceComplete(&once, 0, NULL)) \ + abort(); \ + } while (0) +#endif + + +// mythread_sigmask() isn't available on Windows. Even a dummy version would +// make no sense because the other POSIX signal functions are missing anyway. + + +static inline int +mythread_create(mythread *thread, + unsigned int (__stdcall *func)(void *arg), void *arg) +{ + uintptr_t ret = _beginthreadex(NULL, 0, func, arg, 0, NULL); + if (ret == 0) + return -1; + + *thread = (HANDLE)ret; + return 0; +} + +static inline int +mythread_join(mythread thread) +{ + int ret = 0; + + if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) + ret = -1; + + if (!CloseHandle(thread)) + ret = -1; + + return ret; +} + + +static inline int +mythread_mutex_init(mythread_mutex *mutex) +{ + InitializeCriticalSection(mutex); + return 0; +} + +static inline void +mythread_mutex_destroy(mythread_mutex *mutex) +{ + DeleteCriticalSection(mutex); +} + +static inline void +mythread_mutex_lock(mythread_mutex *mutex) +{ + EnterCriticalSection(mutex); +} + +static inline void +mythread_mutex_unlock(mythread_mutex *mutex) +{ + LeaveCriticalSection(mutex); +} + + +static inline int +mythread_cond_init(mythread_cond *cond) +{ +#ifdef MYTHREAD_WIN95 + *cond = CreateEvent(NULL, FALSE, FALSE, NULL); + return *cond == NULL ? -1 : 0; +#else + InitializeConditionVariable(cond); + return 0; +#endif +} + +static inline void +mythread_cond_destroy(mythread_cond *cond) +{ +#ifdef MYTHREAD_WIN95 + CloseHandle(*cond); +#else + (void)cond; +#endif +} + +static inline void +mythread_cond_signal(mythread_cond *cond) +{ +#ifdef MYTHREAD_WIN95 + SetEvent(*cond); +#else + WakeConditionVariable(cond); +#endif +} + +static inline void +mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex) +{ +#ifdef MYTHREAD_WIN95 + LeaveCriticalSection(mutex); + WaitForSingleObject(*cond, INFINITE); + EnterCriticalSection(mutex); +#else + BOOL ret = SleepConditionVariableCS(cond, mutex, INFINITE); + assert(ret); + (void)ret; +#endif +} + +static inline int +mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex, + const mythread_condtime *condtime) +{ +#ifdef MYTHREAD_WIN95 + LeaveCriticalSection(mutex); +#endif + + DWORD elapsed = GetTickCount() - condtime->start; + DWORD timeout = elapsed >= condtime->timeout + ? 0 : condtime->timeout - elapsed; + +#ifdef MYTHREAD_WIN95 + DWORD ret = WaitForSingleObject(*cond, timeout); + assert(ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT); + + EnterCriticalSection(mutex); + + return ret == WAIT_TIMEOUT; +#else + BOOL ret = SleepConditionVariableCS(cond, mutex, timeout); + assert(ret || GetLastError() == ERROR_TIMEOUT); + return !ret; +#endif +} + +static inline void +mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond, + uint32_t timeout) +{ + (void)cond; + condtime->start = GetTickCount(); + condtime->timeout = timeout; +} + +#endif + +#endif diff --git a/common/sysdefs.h b/common/sysdefs.h index e056ca4ac90..df7ecf40028 100644 --- a/common/sysdefs.h +++ b/common/sysdefs.h @@ -44,9 +44,7 @@ // Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The // limits are also used to figure out some macros missing from pre-C99 systems. -#ifdef HAVE_LIMITS_H -# include -#endif +#include // Be more compatible with systems that have non-conforming inttypes.h. // We assume that int is 32-bit and that long is either 32-bit or 64-bit. @@ -153,9 +151,7 @@ typedef unsigned char _Bool; // string.h should be enough but let's include strings.h and memory.h too if // they exists, since that shouldn't do any harm, but may improve portability. -#ifdef HAVE_STRING_H -# include -#endif +#include #ifdef HAVE_STRINGS_H # include @@ -193,7 +189,8 @@ typedef unsigned char _Bool; # define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif -#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 +#if defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4) # define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x))) #else # define lzma_attr_alloc_size(x) diff --git a/common/tuklib_common.h b/common/tuklib_common.h new file mode 100644 index 00000000000..31fbab58b00 --- /dev/null +++ b/common/tuklib_common.h @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_common.h +/// \brief Common definitions for tuklib modules +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_COMMON_H +#define TUKLIB_COMMON_H + +// The config file may be replaced by a package-specific file. +// It should include at least stddef.h, inttypes.h, and limits.h. +#include "tuklib_config.h" + +// TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by +// the tuklib modules. If you use a tuklib module in a library, +// you should use TUKLIB_SYMBOL_PREFIX to make sure that there +// are no symbol conflicts in case someone links your library +// into application that also uses the same tuklib module. +#ifndef TUKLIB_SYMBOL_PREFIX +# define TUKLIB_SYMBOL_PREFIX +#endif + +#define TUKLIB_CAT_X(a, b) a ## b +#define TUKLIB_CAT(a, b) TUKLIB_CAT_X(a, b) + +#ifndef TUKLIB_SYMBOL +# define TUKLIB_SYMBOL(sym) TUKLIB_CAT(TUKLIB_SYMBOL_PREFIX, sym) +#endif + +#ifndef TUKLIB_DECLS_BEGIN +# ifdef __cplusplus +# define TUKLIB_DECLS_BEGIN extern "C" { +# else +# define TUKLIB_DECLS_BEGIN +# endif +#endif + +#ifndef TUKLIB_DECLS_END +# ifdef __cplusplus +# define TUKLIB_DECLS_END } +# else +# define TUKLIB_DECLS_END +# endif +#endif + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define TUKLIB_GNUC_REQ(major, minor) \ + ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \ + || __GNUC__ > (major)) +#else +# define TUKLIB_GNUC_REQ(major, minor) 0 +#endif + +#if TUKLIB_GNUC_REQ(2, 5) +# define tuklib_attr_noreturn __attribute__((__noreturn__)) +#else +# define tuklib_attr_noreturn +#endif + +#if (defined(_WIN32) && !defined(__CYGWIN__)) \ + || defined(__OS2__) || defined(__MSDOS__) +# define TUKLIB_DOSLIKE 1 +#endif + +#endif diff --git a/common/tuklib_config.h b/common/tuklib_config.h new file mode 100644 index 00000000000..549cb24d773 --- /dev/null +++ b/common/tuklib_config.h @@ -0,0 +1,7 @@ +#ifdef HAVE_CONFIG_H +# include "sysdefs.h" +#else +# include +# include +# include +#endif diff --git a/common/tuklib_cpucores.c b/common/tuklib_cpucores.c new file mode 100644 index 00000000000..cc968dd25ef --- /dev/null +++ b/common/tuklib_cpucores.c @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_cpucores.c +/// \brief Get the number of CPU cores online +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tuklib_cpucores.h" + +#if defined(_WIN32) || defined(__CYGWIN__) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# include + +// glibc >= 2.9 +#elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY) +# include + +// FreeBSD +#elif defined(TUKLIB_CPUCORES_CPUSET) +# include +# include + +#elif defined(TUKLIB_CPUCORES_SYSCTL) +# ifdef HAVE_SYS_PARAM_H +# include +# endif +# include + +#elif defined(TUKLIB_CPUCORES_SYSCONF) +# include + +// HP-UX +#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC) +# include +# include +#endif + + +extern uint32_t +tuklib_cpucores(void) +{ + uint32_t ret = 0; + +#if defined(_WIN32) || defined(__CYGWIN__) + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + ret = sysinfo.dwNumberOfProcessors; + +#elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY) + cpu_set_t cpu_mask; + if (sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask) == 0) + ret = (uint32_t)CPU_COUNT(&cpu_mask); + +#elif defined(TUKLIB_CPUCORES_CPUSET) + cpuset_t set; + if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, + sizeof(set), &set) == 0) { +# ifdef CPU_COUNT + ret = (uint32_t)CPU_COUNT(&set); +# else + for (unsigned i = 0; i < CPU_SETSIZE; ++i) + if (CPU_ISSET(i, &set)) + ++ret; +# endif + } + +#elif defined(TUKLIB_CPUCORES_SYSCTL) + int name[2] = { CTL_HW, HW_NCPU }; + int cpus; + size_t cpus_size = sizeof(cpus); + if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1 + && cpus_size == sizeof(cpus) && cpus > 0) + ret = (uint32_t)cpus; + +#elif defined(TUKLIB_CPUCORES_SYSCONF) +# ifdef _SC_NPROCESSORS_ONLN + // Most systems + const long cpus = sysconf(_SC_NPROCESSORS_ONLN); +# else + // IRIX + const long cpus = sysconf(_SC_NPROC_ONLN); +# endif + if (cpus > 0) + ret = (uint32_t)cpus; + +#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC) + struct pst_dynamic pst; + if (pstat_getdynamic(&pst, sizeof(pst), 1, 0) != -1) + ret = (uint32_t)pst.psd_proc_cnt; +#endif + + return ret; +} diff --git a/common/tuklib_cpucores.h b/common/tuklib_cpucores.h new file mode 100644 index 00000000000..be1ce1c175a --- /dev/null +++ b/common/tuklib_cpucores.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_cpucores.h +/// \brief Get the number of CPU cores online +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_CPUCORES_H +#define TUKLIB_CPUCORES_H + +#include "tuklib_common.h" +TUKLIB_DECLS_BEGIN + +#define tuklib_cpucores TUKLIB_SYMBOL(tuklib_cpucores) +extern uint32_t tuklib_cpucores(void); + +TUKLIB_DECLS_END +#endif diff --git a/common/tuklib_integer.h b/common/tuklib_integer.h index b1e84d5c1d0..6f44a7a0ac2 100644 --- a/common/tuklib_integer.h +++ b/common/tuklib_integer.h @@ -6,22 +6,26 @@ /// This file provides macros or functions to do some basic integer and bit /// operations. /// -/// Endianness related integer operations (XX = 16, 32, or 64; Y = b or l): -/// - Byte swapping: bswapXX(num) -/// - Byte order conversions to/from native: convXXYe(num) -/// - Aligned reads: readXXYe(ptr) -/// - Aligned writes: writeXXYe(ptr, num) -/// - Unaligned reads (16/32-bit only): unaligned_readXXYe(ptr) -/// - Unaligned writes (16/32-bit only): unaligned_writeXXYe(ptr, num) +/// Native endian inline functions (XX = 16, 32, or 64): +/// - Unaligned native endian reads: readXXne(ptr) +/// - Unaligned native endian writes: writeXXne(ptr, num) +/// - Aligned native endian reads: aligned_readXXne(ptr) +/// - Aligned native endian writes: aligned_writeXXne(ptr, num) /// -/// Since they can macros, the arguments should have no side effects since -/// they may be evaluated more than once. +/// Endianness-converting integer operations (these can be macros!) +/// (XX = 16, 32, or 64; Y = b or l): +/// - Byte swapping: bswapXX(num) +/// - Byte order conversions to/from native (byteswaps if Y isn't +/// the native endianness): convXXYe(num) +/// - Unaligned reads (16/32-bit only): readXXYe(ptr) +/// - Unaligned writes (16/32-bit only): writeXXYe(ptr, num) +/// - Aligned reads: aligned_readXXYe(ptr) +/// - Aligned writes: aligned_writeXXYe(ptr, num) /// -/// \todo PowerPC and possibly some other architectures support -/// byte swapping load and store instructions. This file -/// doesn't take advantage of those instructions. +/// Since the above can macros, the arguments should have no side effects +/// because they may be evaluated more than once. /// -/// Bit scan operations for non-zero 32-bit integers: +/// Bit scan operations for non-zero 32-bit integers (inline functions): /// - Bit scan reverse (find highest non-zero bit): bsr32(num) /// - Count leading zeros: clz32(num) /// - Count trailing zeros: ctz32(num) @@ -42,13 +46,26 @@ #define TUKLIB_INTEGER_H #include "tuklib_common.h" +#include + +// Newer Intel C compilers require immintrin.h for _bit_scan_reverse() +// and such functions. +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) +# include +#endif -//////////////////////////////////////// -// Operating system specific features // -//////////////////////////////////////// +/////////////////// +// Byte swapping // +/////////////////// -#if defined(HAVE_BYTESWAP_H) +#if defined(HAVE___BUILTIN_BSWAPXX) + // GCC >= 4.8 and Clang +# define bswap16(n) __builtin_bswap16(n) +# define bswap32(n) __builtin_bswap32(n) +# define bswap64(n) __builtin_bswap64(n) + +#elif defined(HAVE_BYTESWAP_H) // glibc, uClibc, dietlibc # include # ifdef HAVE_BSWAP_16 @@ -97,45 +114,33 @@ # endif #endif - -//////////////////////////////// -// Compiler-specific features // -//////////////////////////////// - -// Newer Intel C compilers require immintrin.h for _bit_scan_reverse() -// and such functions. -#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) -# include -#endif - - -/////////////////// -// Byte swapping // -/////////////////// - #ifndef bswap16 -# define bswap16(num) \ - (((uint16_t)(num) << 8) | ((uint16_t)(num) >> 8)) +# define bswap16(n) (uint16_t)( \ + (((n) & 0x00FFU) << 8) \ + | (((n) & 0xFF00U) >> 8) \ + ) #endif #ifndef bswap32 -# define bswap32(num) \ - ( (((uint32_t)(num) << 24) ) \ - | (((uint32_t)(num) << 8) & UINT32_C(0x00FF0000)) \ - | (((uint32_t)(num) >> 8) & UINT32_C(0x0000FF00)) \ - | (((uint32_t)(num) >> 24) ) ) +# define bswap32(n) (uint32_t)( \ + (((n) & UINT32_C(0x000000FF)) << 24) \ + | (((n) & UINT32_C(0x0000FF00)) << 8) \ + | (((n) & UINT32_C(0x00FF0000)) >> 8) \ + | (((n) & UINT32_C(0xFF000000)) >> 24) \ + ) #endif #ifndef bswap64 -# define bswap64(num) \ - ( (((uint64_t)(num) << 56) ) \ - | (((uint64_t)(num) << 40) & UINT64_C(0x00FF000000000000)) \ - | (((uint64_t)(num) << 24) & UINT64_C(0x0000FF0000000000)) \ - | (((uint64_t)(num) << 8) & UINT64_C(0x000000FF00000000)) \ - | (((uint64_t)(num) >> 8) & UINT64_C(0x00000000FF000000)) \ - | (((uint64_t)(num) >> 24) & UINT64_C(0x0000000000FF0000)) \ - | (((uint64_t)(num) >> 40) & UINT64_C(0x000000000000FF00)) \ - | (((uint64_t)(num) >> 56) ) ) +# define bswap64(n) (uint64_t)( \ + (((n) & UINT64_C(0x00000000000000FF)) << 56) \ + | (((n) & UINT64_C(0x000000000000FF00)) << 40) \ + | (((n) & UINT64_C(0x0000000000FF0000)) << 24) \ + | (((n) & UINT64_C(0x00000000FF000000)) << 8) \ + | (((n) & UINT64_C(0x000000FF00000000)) >> 8) \ + | (((n) & UINT64_C(0x0000FF0000000000)) >> 24) \ + | (((n) & UINT64_C(0x00FF000000000000)) >> 40) \ + | (((n) & UINT64_C(0xFF00000000000000)) >> 56) \ + ) #endif // Define conversion macros using the basic byte swapping macros. @@ -180,76 +185,76 @@ #endif -////////////////////////////// -// Aligned reads and writes // -////////////////////////////// - -static inline uint16_t -read16be(const uint8_t *buf) -{ - uint16_t num = *(const uint16_t *)buf; - return conv16be(num); -} +//////////////////////////////// +// Unaligned reads and writes // +//////////////////////////////// +// The traditional way of casting e.g. *(const uint16_t *)uint8_pointer +// is bad even if the uint8_pointer is properly aligned because this kind +// of casts break strict aliasing rules and result in undefined behavior. +// With unaligned pointers it's even worse: compilers may emit vector +// instructions that require aligned pointers even if non-vector +// instructions work with unaligned pointers. +// +// Using memcpy() is the standard compliant way to do unaligned access. +// Many modern compilers inline it so there is no function call overhead. +// For those compilers that don't handle the memcpy() method well, the +// old casting method (that violates strict aliasing) can be requested at +// build time. A third method, casting to a packed struct, would also be +// an option but isn't provided to keep things simpler (it's already a mess). +// Hopefully this is flexible enough in practice. static inline uint16_t -read16le(const uint8_t *buf) +read16ne(const uint8_t *buf) { - uint16_t num = *(const uint16_t *)buf; - return conv16le(num); -} - - -static inline uint32_t -read32be(const uint8_t *buf) -{ - uint32_t num = *(const uint32_t *)buf; - return conv32be(num); +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) + return *(const uint16_t *)buf; +#else + uint16_t num; + memcpy(&num, buf, sizeof(num)); + return num; +#endif } static inline uint32_t -read32le(const uint8_t *buf) -{ - uint32_t num = *(const uint32_t *)buf; - return conv32le(num); -} - - -static inline uint64_t -read64be(const uint8_t *buf) +read32ne(const uint8_t *buf) { - uint64_t num = *(const uint64_t *)buf; - return conv64be(num); +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) + return *(const uint32_t *)buf; +#else + uint32_t num; + memcpy(&num, buf, sizeof(num)); + return num; +#endif } static inline uint64_t -read64le(const uint8_t *buf) +read64ne(const uint8_t *buf) { - uint64_t num = *(const uint64_t *)buf; - return conv64le(num); +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) + return *(const uint64_t *)buf; +#else + uint64_t num; + memcpy(&num, buf, sizeof(num)); + return num; +#endif } -// NOTE: Possible byte swapping must be done in a macro to allow GCC -// to optimize byte swapping of constants when using glibc's or *BSD's -// byte swapping macros. The actual write is done in an inline function -// to make type checking of the buf pointer possible similarly to readXXYe() -// functions. - -#define write16be(buf, num) write16ne((buf), conv16be(num)) -#define write16le(buf, num) write16ne((buf), conv16le(num)) -#define write32be(buf, num) write32ne((buf), conv32be(num)) -#define write32le(buf, num) write32ne((buf), conv32le(num)) -#define write64be(buf, num) write64ne((buf), conv64be(num)) -#define write64le(buf, num) write64ne((buf), conv64le(num)) - - static inline void write16ne(uint8_t *buf, uint16_t num) { +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) *(uint16_t *)buf = num; +#else + memcpy(buf, &num, sizeof(num)); +#endif return; } @@ -257,7 +262,12 @@ write16ne(uint8_t *buf, uint16_t num) static inline void write32ne(uint8_t *buf, uint32_t num) { +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) *(uint32_t *)buf = num; +#else + memcpy(buf, &num, sizeof(num)); +#endif return; } @@ -265,90 +275,114 @@ write32ne(uint8_t *buf, uint32_t num) static inline void write64ne(uint8_t *buf, uint64_t num) { +#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ + && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) *(uint64_t *)buf = num; +#else + memcpy(buf, &num, sizeof(num)); +#endif return; } -//////////////////////////////// -// Unaligned reads and writes // -//////////////////////////////// - -// NOTE: TUKLIB_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and -// 32-bit unaligned integer loads and stores. It's possible that 64-bit -// unaligned access doesn't work or is slower than byte-by-byte access. -// Since unaligned 64-bit is probably not needed as often as 16-bit or -// 32-bit, we simply don't support 64-bit unaligned access for now. -#ifdef TUKLIB_FAST_UNALIGNED_ACCESS -# define unaligned_read16be read16be -# define unaligned_read16le read16le -# define unaligned_read32be read32be -# define unaligned_read32le read32le -# define unaligned_write16be write16be -# define unaligned_write16le write16le -# define unaligned_write32be write32be -# define unaligned_write32le write32le - -#else - static inline uint16_t -unaligned_read16be(const uint8_t *buf) +read16be(const uint8_t *buf) { +#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) + uint16_t num = read16ne(buf); + return conv16be(num); +#else uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1]; return num; +#endif } static inline uint16_t -unaligned_read16le(const uint8_t *buf) +read16le(const uint8_t *buf) { +#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) + uint16_t num = read16ne(buf); + return conv16le(num); +#else uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8); return num; +#endif } static inline uint32_t -unaligned_read32be(const uint8_t *buf) +read32be(const uint8_t *buf) { +#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) + uint32_t num = read32ne(buf); + return conv32be(num); +#else uint32_t num = (uint32_t)buf[0] << 24; num |= (uint32_t)buf[1] << 16; num |= (uint32_t)buf[2] << 8; num |= (uint32_t)buf[3]; return num; +#endif } static inline uint32_t -unaligned_read32le(const uint8_t *buf) +read32le(const uint8_t *buf) { +#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) + uint32_t num = read32ne(buf); + return conv32le(num); +#else uint32_t num = (uint32_t)buf[0]; num |= (uint32_t)buf[1] << 8; num |= (uint32_t)buf[2] << 16; num |= (uint32_t)buf[3] << 24; return num; +#endif } +// NOTE: Possible byte swapping must be done in a macro to allow the compiler +// to optimize byte swapping of constants when using glibc's or *BSD's +// byte swapping macros. The actual write is done in an inline function +// to make type checking of the buf pointer possible. +#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) +# define write16be(buf, num) write16ne(buf, conv16be(num)) +# define write32be(buf, num) write32ne(buf, conv32be(num)) +#endif + +#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) +# define write16le(buf, num) write16ne(buf, conv16le(num)) +# define write32le(buf, num) write32ne(buf, conv32le(num)) +#endif + + +#ifndef write16be static inline void -unaligned_write16be(uint8_t *buf, uint16_t num) +write16be(uint8_t *buf, uint16_t num) { buf[0] = (uint8_t)(num >> 8); buf[1] = (uint8_t)num; return; } +#endif +#ifndef write16le static inline void -unaligned_write16le(uint8_t *buf, uint16_t num) +write16le(uint8_t *buf, uint16_t num) { buf[0] = (uint8_t)num; buf[1] = (uint8_t)(num >> 8); return; } +#endif +#ifndef write32be static inline void -unaligned_write32be(uint8_t *buf, uint32_t num) +write32be(uint8_t *buf, uint32_t num) { buf[0] = (uint8_t)(num >> 24); buf[1] = (uint8_t)(num >> 16); @@ -356,10 +390,12 @@ unaligned_write32be(uint8_t *buf, uint32_t num) buf[3] = (uint8_t)num; return; } +#endif +#ifndef write32le static inline void -unaligned_write32le(uint8_t *buf, uint32_t num) +write32le(uint8_t *buf, uint32_t num) { buf[0] = (uint8_t)num; buf[1] = (uint8_t)(num >> 8); @@ -367,10 +403,184 @@ unaligned_write32le(uint8_t *buf, uint32_t num) buf[3] = (uint8_t)(num >> 24); return; } +#endif + + +////////////////////////////// +// Aligned reads and writes // +////////////////////////////// +// Separate functions for aligned reads and writes are provided since on +// strict-align archs aligned access is much faster than unaligned access. +// +// Just like in the unaligned case, memcpy() is needed to avoid +// strict aliasing violations. However, on archs that don't support +// unaligned access the compiler cannot know that the pointers given +// to memcpy() are aligned which results in slow code. As of C11 there is +// no standard way to tell the compiler that we know that the address is +// aligned but some compilers have language extensions to do that. With +// such language extensions the memcpy() method gives excellent results. +// +// What to do on a strict-align system when no known language extentensions +// are available? Falling back to byte-by-byte access would be safe but ruin +// optimizations that have been made specifically with aligned access in mind. +// As a compromise, aligned reads will fall back to non-compliant type punning +// but aligned writes will be byte-by-byte, that is, fast reads are preferred +// over fast writes. This obviously isn't great but hopefully it's a working +// compromise for now. +// +// __builtin_assume_aligned is support by GCC >= 4.7 and clang >= 3.6. +#ifdef HAVE___BUILTIN_ASSUME_ALIGNED +# define tuklib_memcpy_aligned(dest, src, size) \ + memcpy(dest, __builtin_assume_aligned(src, size), size) +#else +# define tuklib_memcpy_aligned(dest, src, size) \ + memcpy(dest, src, size) +# ifndef TUKLIB_FAST_UNALIGNED_ACCESS +# define TUKLIB_USE_UNSAFE_ALIGNED_READS 1 +# endif #endif +static inline uint16_t +aligned_read16ne(const uint8_t *buf) +{ +#if defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) \ + || defined(TUKLIB_USE_UNSAFE_ALIGNED_READS) + return *(const uint16_t *)buf; +#else + uint16_t num; + tuklib_memcpy_aligned(&num, buf, sizeof(num)); + return num; +#endif +} + + +static inline uint32_t +aligned_read32ne(const uint8_t *buf) +{ +#if defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) \ + || defined(TUKLIB_USE_UNSAFE_ALIGNED_READS) + return *(const uint32_t *)buf; +#else + uint32_t num; + tuklib_memcpy_aligned(&num, buf, sizeof(num)); + return num; +#endif +} + + +static inline uint64_t +aligned_read64ne(const uint8_t *buf) +{ +#if defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) \ + || defined(TUKLIB_USE_UNSAFE_ALIGNED_READS) + return *(const uint64_t *)buf; +#else + uint64_t num; + tuklib_memcpy_aligned(&num, buf, sizeof(num)); + return num; +#endif +} + + +static inline void +aligned_write16ne(uint8_t *buf, uint16_t num) +{ +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING + *(uint16_t *)buf = num; +#else + tuklib_memcpy_aligned(buf, &num, sizeof(num)); +#endif + return; +} + + +static inline void +aligned_write32ne(uint8_t *buf, uint32_t num) +{ +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING + *(uint32_t *)buf = num; +#else + tuklib_memcpy_aligned(buf, &num, sizeof(num)); +#endif + return; +} + + +static inline void +aligned_write64ne(uint8_t *buf, uint64_t num) +{ +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING + *(uint64_t *)buf = num; +#else + tuklib_memcpy_aligned(buf, &num, sizeof(num)); +#endif + return; +} + + +static inline uint16_t +aligned_read16be(const uint8_t *buf) +{ + uint16_t num = aligned_read16ne(buf); + return conv16be(num); +} + + +static inline uint16_t +aligned_read16le(const uint8_t *buf) +{ + uint16_t num = aligned_read16ne(buf); + return conv16le(num); +} + + +static inline uint32_t +aligned_read32be(const uint8_t *buf) +{ + uint32_t num = aligned_read32ne(buf); + return conv32be(num); +} + + +static inline uint32_t +aligned_read32le(const uint8_t *buf) +{ + uint32_t num = aligned_read32ne(buf); + return conv32le(num); +} + + +static inline uint64_t +aligned_read64be(const uint8_t *buf) +{ + uint64_t num = aligned_read64ne(buf); + return conv64be(num); +} + + +static inline uint64_t +aligned_read64le(const uint8_t *buf) +{ + uint64_t num = aligned_read64ne(buf); + return conv64le(num); +} + + +// These need to be macros like in the unaligned case. +#define aligned_write16be(buf, num) aligned_write16ne((buf), conv16be(num)) +#define aligned_write16le(buf, num) aligned_write16ne((buf), conv16le(num)) +#define aligned_write32be(buf, num) aligned_write32ne((buf), conv32be(num)) +#define aligned_write32le(buf, num) aligned_write32ne((buf), conv32le(num)) +#define aligned_write64be(buf, num) aligned_write64ne((buf), conv64be(num)) +#define aligned_write64le(buf, num) aligned_write64ne((buf), conv64le(num)) + + +//////////////////// +// Bit operations // +//////////////////// + static inline uint32_t bsr32(uint32_t n) { @@ -383,44 +593,42 @@ bsr32(uint32_t n) // multiple architectures. On x86, __builtin_clz() ^ 31U becomes // either plain BSR (so the XOR gets optimized away) or LZCNT and // XOR (if -march indicates that SSE4a instructions are supported). - return __builtin_clz(n) ^ 31U; + return (uint32_t)__builtin_clz(n) ^ 31U; #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) uint32_t i; __asm__("bsrl %1, %0" : "=r" (i) : "rm" (n)); return i; -#elif defined(_MSC_VER) && _MSC_VER >= 1400 - // MSVC isn't supported by tuklib, but since this code exists, - // it doesn't hurt to have it here anyway. - uint32_t i; - _BitScanReverse((DWORD *)&i, n); +#elif defined(_MSC_VER) + unsigned long i; + _BitScanReverse(&i, n); return i; #else uint32_t i = 31; - if ((n & UINT32_C(0xFFFF0000)) == 0) { + if ((n & 0xFFFF0000) == 0) { n <<= 16; i = 15; } - if ((n & UINT32_C(0xFF000000)) == 0) { + if ((n & 0xFF000000) == 0) { n <<= 8; i -= 8; } - if ((n & UINT32_C(0xF0000000)) == 0) { + if ((n & 0xF0000000) == 0) { n <<= 4; i -= 4; } - if ((n & UINT32_C(0xC0000000)) == 0) { + if ((n & 0xC0000000) == 0) { n <<= 2; i -= 2; } - if ((n & UINT32_C(0x80000000)) == 0) + if ((n & 0x80000000) == 0) --i; return i; @@ -435,7 +643,7 @@ clz32(uint32_t n) return _bit_scan_reverse(n) ^ 31U; #elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX - return __builtin_clz(n); + return (uint32_t)__builtin_clz(n); #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) uint32_t i; @@ -444,35 +652,35 @@ clz32(uint32_t n) : "=r" (i) : "rm" (n)); return i; -#elif defined(_MSC_VER) && _MSC_VER >= 1400 - uint32_t i; - _BitScanReverse((DWORD *)&i, n); +#elif defined(_MSC_VER) + unsigned long i; + _BitScanReverse(&i, n); return i ^ 31U; #else uint32_t i = 0; - if ((n & UINT32_C(0xFFFF0000)) == 0) { + if ((n & 0xFFFF0000) == 0) { n <<= 16; i = 16; } - if ((n & UINT32_C(0xFF000000)) == 0) { + if ((n & 0xFF000000) == 0) { n <<= 8; i += 8; } - if ((n & UINT32_C(0xF0000000)) == 0) { + if ((n & 0xF0000000) == 0) { n <<= 4; i += 4; } - if ((n & UINT32_C(0xC0000000)) == 0) { + if ((n & 0xC0000000) == 0) { n <<= 2; i += 2; } - if ((n & UINT32_C(0x80000000)) == 0) + if ((n & 0x80000000) == 0) ++i; return i; @@ -487,42 +695,42 @@ ctz32(uint32_t n) return _bit_scan_forward(n); #elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX - return __builtin_ctz(n); + return (uint32_t)__builtin_ctz(n); #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) uint32_t i; __asm__("bsfl %1, %0" : "=r" (i) : "rm" (n)); return i; -#elif defined(_MSC_VER) && _MSC_VER >= 1400 - uint32_t i; - _BitScanForward((DWORD *)&i, n); +#elif defined(_MSC_VER) + unsigned long i; + _BitScanForward(&i, n); return i; #else uint32_t i = 0; - if ((n & UINT32_C(0x0000FFFF)) == 0) { + if ((n & 0x0000FFFF) == 0) { n >>= 16; i = 16; } - if ((n & UINT32_C(0x000000FF)) == 0) { + if ((n & 0x000000FF) == 0) { n >>= 8; i += 8; } - if ((n & UINT32_C(0x0000000F)) == 0) { + if ((n & 0x0000000F) == 0) { n >>= 4; i += 4; } - if ((n & UINT32_C(0x00000003)) == 0) { + if ((n & 0x00000003) == 0) { n >>= 2; i += 2; } - if ((n & UINT32_C(0x00000001)) == 0) + if ((n & 0x00000001) == 0) ++i; return i; diff --git a/liblzma/api/lzma.h b/liblzma/api/lzma.h index aa88e4243a2..122dab80d35 100644 --- a/liblzma/api/lzma.h +++ b/liblzma/api/lzma.h @@ -224,7 +224,8 @@ # else # define lzma_nothrow throw() # endif -# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +# elif defined(__GNUC__) && (__GNUC__ > 3 \ + || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) # define lzma_nothrow __attribute__((__nothrow__)) # else # define lzma_nothrow @@ -241,7 +242,7 @@ * break anything if these are sometimes enabled and sometimes not, only * affects warnings and optimizations. */ -#if __GNUC__ >= 3 +#if defined(__GNUC__) && __GNUC__ >= 3 # ifndef lzma_attribute # define lzma_attribute(attr) __attribute__(attr) # endif diff --git a/liblzma/api/lzma/block.h b/liblzma/api/lzma/block.h index 7bdcfd7cbe0..962f38779cc 100644 --- a/liblzma/api/lzma/block.h +++ b/liblzma/api/lzma/block.h @@ -448,7 +448,7 @@ extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block) * - LZMA_MEM_ERROR * - LZMA_OPTIONS_ERROR * - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID - * that is not supported by this buid of liblzma. Initializing + * that is not supported by this build of liblzma. Initializing * the encoder failed. * - LZMA_PROG_ERROR */ diff --git a/liblzma/api/lzma/filter.h b/liblzma/api/lzma/filter.h index 4e78752b8f7..8c859314765 100644 --- a/liblzma/api/lzma/filter.h +++ b/liblzma/api/lzma/filter.h @@ -341,9 +341,10 @@ extern LZMA_API(lzma_ret) lzma_properties_encode( * \param filter filter->id must have been set to the correct * Filter ID. filter->options doesn't need to be * initialized (it's not freed by this function). The - * decoded options will be stored to filter->options. - * filter->options is set to NULL if there are no - * properties or if an error occurs. + * decoded options will be stored in filter->options; + * it's application's responsibility to free it when + * appropriate. filter->options is set to NULL if + * there are no properties or if an error occurs. * \param allocator Custom memory allocator used to allocate the * options. Set to NULL to use the default malloc(), * and in case of an error, also free(). diff --git a/liblzma/api/lzma/hardware.h b/liblzma/api/lzma/hardware.h index 5321d9af8e4..47481f2581f 100644 --- a/liblzma/api/lzma/hardware.h +++ b/liblzma/api/lzma/hardware.h @@ -6,7 +6,7 @@ * ways to limit the resource usage. Applications linking against liblzma * need to do the actual decisions how much resources to let liblzma to use. * To ease making these decisions, liblzma provides functions to find out - * the relevant capabilities of the underlaying hardware. Currently there + * the relevant capabilities of the underlying hardware. Currently there * is only a function to find out the amount of RAM, but in the future there * will be also a function to detect how many concurrent threads the system * can run. diff --git a/liblzma/api/lzma/lzma12.h b/liblzma/api/lzma/lzma12.h index 4e32fa3a214..df5f23b61a4 100644 --- a/liblzma/api/lzma/lzma12.h +++ b/liblzma/api/lzma/lzma12.h @@ -301,7 +301,7 @@ typedef struct { * (2^ pb =2^2=4), which is often a good choice when there's * no better guess. * - * When the aligment is known, setting pb accordingly may reduce + * When the alignment is known, setting pb accordingly may reduce * the file size a little. E.g. with text files having one-byte * alignment (US-ASCII, ISO-8859-*, UTF-8), setting pb=0 can * improve compression slightly. For UTF-16 text, pb=1 is a good diff --git a/liblzma/api/lzma/version.h b/liblzma/api/lzma/version.h index 143c7dea69f..2bf3eaed24f 100644 --- a/liblzma/api/lzma/version.h +++ b/liblzma/api/lzma/version.h @@ -22,7 +22,7 @@ */ #define LZMA_VERSION_MAJOR 5 #define LZMA_VERSION_MINOR 2 -#define LZMA_VERSION_PATCH 4 +#define LZMA_VERSION_PATCH 5 #define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE #ifndef LZMA_VERSION_COMMIT diff --git a/liblzma/api/lzma/vli.h b/liblzma/api/lzma/vli.h index 9ad13f2e2fc..1b7a952a406 100644 --- a/liblzma/api/lzma/vli.h +++ b/liblzma/api/lzma/vli.h @@ -54,7 +54,7 @@ * * Valid VLI values are in the range [0, LZMA_VLI_MAX]. Unknown value is * indicated with LZMA_VLI_UNKNOWN, which is the maximum value of the - * underlaying integer type. + * underlying integer type. * * lzma_vli will be uint64_t for the foreseeable future. If a bigger size * is needed in the future, it is guaranteed that 2 * LZMA_VLI_MAX will diff --git a/liblzma/check/crc32_fast.c b/liblzma/check/crc32_fast.c index 3de02638d77..eed7350582e 100644 --- a/liblzma/check/crc32_fast.c +++ b/liblzma/check/crc32_fast.c @@ -49,7 +49,7 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) // Calculate the CRC32 using the slice-by-eight algorithm. while (buf < limit) { - crc ^= *(const uint32_t *)(buf); + crc ^= aligned_read32ne(buf); buf += 4; crc = lzma_crc32_table[7][A(crc)] @@ -57,7 +57,7 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) ^ lzma_crc32_table[5][C(crc)] ^ lzma_crc32_table[4][D(crc)]; - const uint32_t tmp = *(const uint32_t *)(buf); + const uint32_t tmp = aligned_read32ne(buf); buf += 4; // At least with some compilers, it is critical for diff --git a/liblzma/check/crc32_table.c b/liblzma/check/crc32_table.c index 368874eb79d..b11762ae0ac 100644 --- a/liblzma/check/crc32_table.c +++ b/liblzma/check/crc32_table.c @@ -12,6 +12,9 @@ #include "common.h" +// Having the declaration here silences clang -Wmissing-variable-declarations. +extern const uint32_t lzma_crc32_table[8][256]; + #ifdef WORDS_BIGENDIAN # include "crc32_table_be.h" #else diff --git a/liblzma/check/crc64_fast.c b/liblzma/check/crc64_fast.c index 52af29ed48d..8af54cda7b5 100644 --- a/liblzma/check/crc64_fast.c +++ b/liblzma/check/crc64_fast.c @@ -47,9 +47,9 @@ lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) while (buf < limit) { #ifdef WORDS_BIGENDIAN const uint32_t tmp = (crc >> 32) - ^ *(const uint32_t *)(buf); + ^ aligned_read32ne(buf); #else - const uint32_t tmp = crc ^ *(const uint32_t *)(buf); + const uint32_t tmp = crc ^ aligned_read32ne(buf); #endif buf += 4; diff --git a/liblzma/check/crc64_table.c b/liblzma/check/crc64_table.c index 1fbcd94703c..7560eb0a3b1 100644 --- a/liblzma/check/crc64_table.c +++ b/liblzma/check/crc64_table.c @@ -12,6 +12,9 @@ #include "common.h" +// Having the declaration here silences clang -Wmissing-variable-declarations. +extern const uint64_t lzma_crc64_table[4][256]; + #ifdef WORDS_BIGENDIAN # include "crc64_table_be.h" #else diff --git a/liblzma/common/alone_decoder.c b/liblzma/common/alone_decoder.c index 77d0a9b1002..239b230ef19 100644 --- a/liblzma/common/alone_decoder.c +++ b/liblzma/common/alone_decoder.c @@ -50,8 +50,7 @@ typedef struct { static lzma_ret -alone_decode(void *coder_ptr, - const lzma_allocator *allocator lzma_attribute((__unused__)), +alone_decode(void *coder_ptr, const lzma_allocator *allocator, const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, diff --git a/liblzma/common/alone_encoder.c b/liblzma/common/alone_encoder.c index 4853cfd1d64..96c1db70cc6 100644 --- a/liblzma/common/alone_encoder.c +++ b/liblzma/common/alone_encoder.c @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file alone_decoder.c -/// \brief Decoder for LZMA_Alone files +/// \file alone_encoder.c +/// \brief Encoder for LZMA_Alone files // // Author: Lasse Collin // @@ -31,8 +31,7 @@ typedef struct { static lzma_ret -alone_encode(void *coder_ptr, - const lzma_allocator *allocator lzma_attribute((__unused__)), +alone_encode(void *coder_ptr, const lzma_allocator *allocator, const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, @@ -122,7 +121,7 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, if (d != UINT32_MAX) ++d; - unaligned_write32le(coder->header + 1, d); + write32le(coder->header + 1, d); // - Uncompressed size (always unknown and using EOPM) memset(coder->header + 1 + 4, 0xFF, 8); diff --git a/liblzma/common/block_header_decoder.c b/liblzma/common/block_header_decoder.c index 1dd982f6bd6..2e1135dd639 100644 --- a/liblzma/common/block_header_decoder.c +++ b/liblzma/common/block_header_decoder.c @@ -67,7 +67,7 @@ lzma_block_header_decode(lzma_block *block, const size_t in_size = block->header_size - 4; // Verify CRC32 - if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size)) + if (lzma_crc32(in, in_size, 0) != read32le(in + in_size)) return LZMA_DATA_ERROR; // Check for unsupported flags. @@ -98,7 +98,7 @@ lzma_block_header_decode(lzma_block *block, block->uncompressed_size = LZMA_VLI_UNKNOWN; // Filter Flags - const size_t filter_count = (in[1] & 3) + 1; + const size_t filter_count = (in[1] & 3U) + 1; for (size_t i = 0; i < filter_count; ++i) { const lzma_ret ret = lzma_filter_flags_decode( &block->filters[i], allocator, diff --git a/liblzma/common/block_header_encoder.c b/liblzma/common/block_header_encoder.c index 5c5f5424ae8..160425d27a3 100644 --- a/liblzma/common/block_header_encoder.c +++ b/liblzma/common/block_header_encoder.c @@ -126,7 +126,7 @@ lzma_block_header_encode(const lzma_block *block, uint8_t *out) memzero(out + out_pos, out_size - out_pos); // CRC32 - unaligned_write32le(out + out_size, lzma_crc32(out, out_size, 0)); + write32le(out + out_size, lzma_crc32(out, out_size, 0)); return LZMA_OK; } diff --git a/liblzma/common/block_util.c b/liblzma/common/block_util.c index 00c7fe8d519..acb311142c2 100644 --- a/liblzma/common/block_util.c +++ b/liblzma/common/block_util.c @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file block_header.c +/// \file block_util.c /// \brief Utility functions to handle lzma_block // // Author: Lasse Collin diff --git a/liblzma/common/common.c b/liblzma/common/common.c index 57e3f8ebd62..cf714e5e43b 100644 --- a/liblzma/common/common.c +++ b/liblzma/common/common.c @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file common.h +/// \file common.c /// \brief Common functions needed in many places in liblzma // // Author: Lasse Collin @@ -99,7 +99,11 @@ lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, const size_t out_avail = out_size - *out_pos; const size_t copy_size = my_min(in_avail, out_avail); - memcpy(out + *out_pos, in + *in_pos, copy_size); + // Call memcpy() only if there is something to copy. If there is + // nothing to copy, in or out might be NULL and then the memcpy() + // call would trigger undefined behavior. + if (copy_size > 0) + memcpy(out + *out_pos, in + *in_pos, copy_size); *in_pos += copy_size; *out_pos += copy_size; diff --git a/liblzma/common/filter_common.h b/liblzma/common/filter_common.h index 42a26a24a47..9390305c26c 100644 --- a/liblzma/common/filter_common.h +++ b/liblzma/common/filter_common.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file filter_common.c +/// \file filter_common.h /// \brief Filter-specific stuff common for both encoder and decoder // // Author: Lasse Collin diff --git a/liblzma/common/filter_decoder.h b/liblzma/common/filter_decoder.h index a2e255fe5f0..2dac6028282 100644 --- a/liblzma/common/filter_decoder.h +++ b/liblzma/common/filter_decoder.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file filter_decoder.c +/// \file filter_decoder.h /// \brief Filter ID mapping to filter-specific functions // // Author: Lasse Collin diff --git a/liblzma/common/filter_flags_encoder.c b/liblzma/common/filter_flags_encoder.c index d110566de99..b57b9fd80b0 100644 --- a/liblzma/common/filter_flags_encoder.c +++ b/liblzma/common/filter_flags_encoder.c @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // /// \file filter_flags_encoder.c -/// \brief Decodes a Filter Flags field +/// \brief Encodes a Filter Flags field // // Author: Lasse Collin // diff --git a/liblzma/common/hardware_physmem.c b/liblzma/common/hardware_physmem.c index 7405b658af7..a2bbbe29d4b 100644 --- a/liblzma/common/hardware_physmem.c +++ b/liblzma/common/hardware_physmem.c @@ -19,7 +19,7 @@ extern LZMA_API(uint64_t) lzma_physmem(void) { // It is simpler to make lzma_physmem() a wrapper for - // tuklib_physmem() than to hack appropriate symbol visiblity + // tuklib_physmem() than to hack appropriate symbol visibility // support for the tuklib modules. return tuklib_physmem(); } diff --git a/liblzma/common/index.c b/liblzma/common/index.c index 26e4e519bc8..a41e8f33083 100644 --- a/liblzma/common/index.c +++ b/liblzma/common/index.c @@ -105,7 +105,7 @@ typedef struct { typedef struct { - /// Every index_stream is a node in the tree of Sreams. + /// Every index_stream is a node in the tree of Streams. index_tree_node node; /// Number of this Stream (first one is 1) @@ -166,7 +166,7 @@ struct lzma_index_s { lzma_vli index_list_size; /// How many Records to allocate at once in lzma_index_append(). - /// This defaults to INDEX_GROUP_SIZE but can be overriden with + /// This defaults to INDEX_GROUP_SIZE but can be overridden with /// lzma_index_prealloc(). size_t prealloc; @@ -825,8 +825,8 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src, s->groups.root = &newg->node; } - if (s->groups.rightmost == &g->node) - s->groups.rightmost = &newg->node; + assert(s->groups.rightmost == &g->node); + s->groups.rightmost = &newg->node; lzma_free(g, allocator); diff --git a/liblzma/common/memcmplen.h b/liblzma/common/memcmplen.h index c1efc9e28b7..dcfd8d6f89d 100644 --- a/liblzma/common/memcmplen.h +++ b/liblzma/common/memcmplen.h @@ -61,8 +61,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2, // to __builtin_clzll(). #define LZMA_MEMCMPLEN_EXTRA 8 while (len < limit) { - const uint64_t x = *(const uint64_t *)(buf1 + len) - - *(const uint64_t *)(buf2 + len); + const uint64_t x = read64ne(buf1 + len) - read64ne(buf2 + len); if (x != 0) { # if defined(_M_X64) // MSVC or Intel C compiler on Windows unsigned long tmp; @@ -99,15 +98,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2, _mm_loadu_si128((const __m128i *)(buf2 + len)))); if (x != 0) { -# if defined(__INTEL_COMPILER) - len += _bit_scan_forward(x); -# elif defined(_MSC_VER) - unsigned long tmp; - _BitScanForward(&tmp, x); - len += tmp; -# else - len += __builtin_ctz(x); -# endif + len += ctz32(x); return my_min(len, limit); } @@ -120,8 +111,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2, // Generic 32-bit little endian method # define LZMA_MEMCMPLEN_EXTRA 4 while (len < limit) { - uint32_t x = *(const uint32_t *)(buf1 + len) - - *(const uint32_t *)(buf2 + len); + uint32_t x = read32ne(buf1 + len) - read32ne(buf2 + len); if (x != 0) { if ((x & 0xFFFF) == 0) { len += 2; @@ -143,8 +133,7 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2, // Generic 32-bit big endian method # define LZMA_MEMCMPLEN_EXTRA 4 while (len < limit) { - uint32_t x = *(const uint32_t *)(buf1 + len) - ^ *(const uint32_t *)(buf2 + len); + uint32_t x = read32ne(buf1 + len) ^ read32ne(buf2 + len); if (x != 0) { if ((x & 0xFFFF0000) == 0) { len += 2; diff --git a/liblzma/common/stream_encoder_mt.c b/liblzma/common/stream_encoder_mt.c index 2efe44c2534..01e40339750 100644 --- a/liblzma/common/stream_encoder_mt.c +++ b/liblzma/common/stream_encoder_mt.c @@ -700,7 +700,7 @@ stream_encode_mt(void *coder_ptr, const lzma_allocator *allocator, ret = coder->thread_error; if (ret != LZMA_OK) { assert(ret != LZMA_STREAM_END); - break; + break; // Break out of mythread_sync. } // Try to read compressed data to out[]. @@ -958,7 +958,7 @@ stream_encoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator, // Validate the filter chain so that we can give an error in this // function instead of delaying it to the first call to lzma_code(). // The memory usage calculation verifies the filter chain as - // a side effect so we take advatange of that. + // a side effect so we take advantage of that. if (lzma_raw_encoder_memusage(filters) == UINT64_MAX) return LZMA_OPTIONS_ERROR; diff --git a/liblzma/common/stream_flags_decoder.c b/liblzma/common/stream_flags_decoder.c index 1bc2f97c519..4e43e359e1e 100644 --- a/liblzma/common/stream_flags_decoder.c +++ b/liblzma/common/stream_flags_decoder.c @@ -38,7 +38,7 @@ lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in) // and unsupported files. const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic), LZMA_STREAM_FLAGS_SIZE, 0); - if (crc != unaligned_read32le(in + sizeof(lzma_header_magic) + if (crc != read32le(in + sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE)) return LZMA_DATA_ERROR; @@ -67,7 +67,7 @@ lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in) // CRC32 const uint32_t crc = lzma_crc32(in + sizeof(uint32_t), sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0); - if (crc != unaligned_read32le(in)) + if (crc != read32le(in)) return LZMA_DATA_ERROR; // Stream Flags @@ -75,7 +75,7 @@ lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in) return LZMA_OPTIONS_ERROR; // Backward Size - options->backward_size = unaligned_read32le(in + sizeof(uint32_t)); + options->backward_size = read32le(in + sizeof(uint32_t)); options->backward_size = (options->backward_size + 1) * 4; return LZMA_OK; diff --git a/liblzma/common/stream_flags_encoder.c b/liblzma/common/stream_flags_encoder.c index 4e717159f1e..b98ab17c456 100644 --- a/liblzma/common/stream_flags_encoder.c +++ b/liblzma/common/stream_flags_encoder.c @@ -46,8 +46,8 @@ lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out) const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic), LZMA_STREAM_FLAGS_SIZE, 0); - unaligned_write32le(out + sizeof(lzma_header_magic) - + LZMA_STREAM_FLAGS_SIZE, crc); + write32le(out + sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE, + crc); return LZMA_OK; } @@ -66,7 +66,7 @@ lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out) if (!is_backward_size_valid(options)) return LZMA_PROG_ERROR; - unaligned_write32le(out + 4, options->backward_size / 4 - 1); + write32le(out + 4, options->backward_size / 4 - 1); // Stream Flags if (stream_flags_encode(options, out + 2 * 4)) @@ -76,7 +76,7 @@ lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out) const uint32_t crc = lzma_crc32( out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0); - unaligned_write32le(out, crc); + write32le(out, crc); // Magic memcpy(out + 2 * 4 + LZMA_STREAM_FLAGS_SIZE, diff --git a/liblzma/common/vli_decoder.c b/liblzma/common/vli_decoder.c index c181828bf56..af2799d1fb9 100644 --- a/liblzma/common/vli_decoder.c +++ b/liblzma/common/vli_decoder.c @@ -72,7 +72,7 @@ lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos, // corrupt. // // If we need bigger integers in future, old versions liblzma - // will confusingly indicate the file being corrupt istead of + // will confusingly indicate the file being corrupt instead of // unsupported. I suppose it's still better this way, because // in the foreseeable future (writing this in 2008) the only // reason why files would appear having over 63-bit integers diff --git a/liblzma/delta/delta_decoder.c b/liblzma/delta/delta_decoder.c index 6859afa5cd7..13d8a28f0df 100644 --- a/liblzma/delta/delta_decoder.c +++ b/liblzma/delta/delta_decoder.c @@ -70,7 +70,7 @@ lzma_delta_props_decode(void **options, const lzma_allocator *allocator, return LZMA_MEM_ERROR; opt->type = LZMA_DELTA_TYPE_BYTE; - opt->dist = props[0] + 1; + opt->dist = props[0] + 1U; *options = opt; diff --git a/liblzma/lz/lz_decoder.c b/liblzma/lz/lz_decoder.c index c7086440bfa..09b574388f5 100644 --- a/liblzma/lz/lz_decoder.c +++ b/liblzma/lz/lz_decoder.c @@ -91,11 +91,17 @@ decode_buffer(lzma_coder *coder, in, in_pos, in_size); // Copy the decoded data from the dictionary to the out[] - // buffer. + // buffer. Do it conditionally because out can be NULL + // (in which case copy_size is always 0). Calling memcpy() + // with a null-pointer is undefined even if the third + // argument is 0. const size_t copy_size = coder->dict.pos - dict_start; assert(copy_size <= out_size - *out_pos); - memcpy(out + *out_pos, coder->dict.buf + dict_start, - copy_size); + + if (copy_size > 0) + memcpy(out + *out_pos, coder->dict.buf + dict_start, + copy_size); + *out_pos += copy_size; // Reset the dictionary if so requested by coder->lz.code(). @@ -125,8 +131,7 @@ decode_buffer(lzma_coder *coder, static lzma_ret -lz_decode(void *coder_ptr, - const lzma_allocator *allocator lzma_attribute((__unused__)), +lz_decode(void *coder_ptr, const lzma_allocator *allocator, const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, @@ -241,7 +246,7 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, if (lz_options.dict_size < 4096) lz_options.dict_size = 4096; - // Make dictionary size a multipe of 16. Some LZ-based decoders like + // Make dictionary size a multiple of 16. Some LZ-based decoders like // LZMA use the lowest bits lzma_dict.pos to know the alignment of the // data. Aligned buffer is also good when memcpying from the // dictionary to the output buffer, since applications are diff --git a/liblzma/lz/lz_encoder_hash.h b/liblzma/lz/lz_encoder_hash.h index 342a333d168..fb15c58146d 100644 --- a/liblzma/lz/lz_encoder_hash.h +++ b/liblzma/lz/lz_encoder_hash.h @@ -39,7 +39,7 @@ // Endianness doesn't matter in hash_2_calc() (no effect on the output). #ifdef TUKLIB_FAST_UNALIGNED_ACCESS # define hash_2_calc() \ - const uint32_t hash_value = *(const uint16_t *)(cur) + const uint32_t hash_value = read16ne(cur) #else # define hash_2_calc() \ const uint32_t hash_value \ diff --git a/liblzma/lz/lz_encoder_mf.c b/liblzma/lz/lz_encoder_mf.c index 78520779f1b..d03657a7c93 100644 --- a/liblzma/lz/lz_encoder_mf.c +++ b/liblzma/lz/lz_encoder_mf.c @@ -113,7 +113,7 @@ normalize(lzma_mf *mf) // may be match finders that use larger resolution than one byte. const uint32_t subvalue = (MUST_NORMALIZE_POS - mf->cyclic_size); - // & (~(UINT32_C(1) << 10) - 1); + // & ~((UINT32_C(1) << 10) - 1); for (uint32_t i = 0; i < mf->hash_count; ++i) { // If the distance is greater than the dictionary size, diff --git a/liblzma/lzma/fastpos.h b/liblzma/lzma/fastpos.h index a3feea58d8d..cba442c27e5 100644 --- a/liblzma/lzma/fastpos.h +++ b/liblzma/lzma/fastpos.h @@ -101,7 +101,7 @@ extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS]; (UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n))) #define fastpos_result(dist, extra, n) \ - lzma_fastpos[(dist) >> fastpos_shift(extra, n)] \ + (uint32_t)(lzma_fastpos[(dist) >> fastpos_shift(extra, n)]) \ + 2 * fastpos_shift(extra, n) diff --git a/liblzma/lzma/fastpos_tablegen.c b/liblzma/lzma/fastpos_tablegen.c index c97e6f411c2..d4484c82d0b 100644 --- a/liblzma/lzma/fastpos_tablegen.c +++ b/liblzma/lzma/fastpos_tablegen.c @@ -11,7 +11,6 @@ // /////////////////////////////////////////////////////////////////////////////// -#include #include #include #include "fastpos.h" diff --git a/liblzma/lzma/lzma2_decoder.c b/liblzma/lzma/lzma2_decoder.c index 878c870ae1a..cf1b5110aca 100644 --- a/liblzma/lzma/lzma2_decoder.c +++ b/liblzma/lzma/lzma2_decoder.c @@ -136,7 +136,7 @@ lzma2_decode(void *coder_ptr, lzma_dict *restrict dict, break; case SEQ_UNCOMPRESSED_2: - coder->uncompressed_size += in[(*in_pos)++] + 1; + coder->uncompressed_size += in[(*in_pos)++] + 1U; coder->sequence = SEQ_COMPRESSED_0; coder->lzma.set_uncompressed(coder->lzma.coder, coder->uncompressed_size); @@ -148,7 +148,7 @@ lzma2_decode(void *coder_ptr, lzma_dict *restrict dict, break; case SEQ_COMPRESSED_1: - coder->compressed_size += in[(*in_pos)++] + 1; + coder->compressed_size += in[(*in_pos)++] + 1U; coder->sequence = coder->next_sequence; break; @@ -297,8 +297,8 @@ lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator, if (props[0] == 40) { opt->dict_size = UINT32_MAX; } else { - opt->dict_size = 2 | (props[0] & 1); - opt->dict_size <<= props[0] / 2 + 11; + opt->dict_size = 2 | (props[0] & 1U); + opt->dict_size <<= props[0] / 2U + 11; } opt->preset_dict = NULL; diff --git a/liblzma/lzma/lzma_common.h b/liblzma/lzma/lzma_common.h index 09efd387291..9d040d95bb2 100644 --- a/liblzma/lzma/lzma_common.h +++ b/liblzma/lzma/lzma_common.h @@ -122,7 +122,8 @@ typedef enum { /// byte; and /// - the highest literal_context_bits bits of the previous byte. #define literal_subcoder(probs, lc, lp_mask, pos, prev_byte) \ - ((probs)[(((pos) & lp_mask) << lc) + ((prev_byte) >> (8 - lc))]) + ((probs)[(((pos) & (lp_mask)) << (lc)) \ + + ((uint32_t)(prev_byte) >> (8U - (lc)))]) static inline void diff --git a/liblzma/lzma/lzma_decoder.c b/liblzma/lzma/lzma_decoder.c index d0f29b763a3..e605a0a916b 100644 --- a/liblzma/lzma/lzma_decoder.c +++ b/liblzma/lzma/lzma_decoder.c @@ -398,7 +398,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr, // ("match byte") to "len" to minimize the // number of variables we need to store // between decoder calls. - len = dict_get(&dict, rep0) << 1; + len = (uint32_t)(dict_get(&dict, rep0)) << 1; // The usage of "offset" allows omitting some // branches, which should give tiny speed @@ -569,7 +569,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr, #ifdef HAVE_SMALL do { rc_bit(probs[symbol], , - rep0 += 1 << offset, + rep0 += 1U << offset, SEQ_DIST_MODEL); } while (++offset < limit); #else @@ -577,25 +577,25 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr, case 5: assert(offset == 0); rc_bit(probs[symbol], , - rep0 += 1, + rep0 += 1U, SEQ_DIST_MODEL); ++offset; --limit; case 4: rc_bit(probs[symbol], , - rep0 += 1 << offset, + rep0 += 1U << offset, SEQ_DIST_MODEL); ++offset; --limit; case 3: rc_bit(probs[symbol], , - rep0 += 1 << offset, + rep0 += 1U << offset, SEQ_DIST_MODEL); ++offset; --limit; case 2: rc_bit(probs[symbol], , - rep0 += 1 << offset, + rep0 += 1U << offset, SEQ_DIST_MODEL); ++offset; --limit; @@ -607,7 +607,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr, // the unneeded updating of // "symbol". rc_bit_last(probs[symbol], , - rep0 += 1 << offset, + rep0 += 1U << offset, SEQ_DIST_MODEL); } #endif @@ -635,7 +635,7 @@ lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr, do { rc_bit(coder->pos_align[ symbol], , - rep0 += 1 << offset, + rep0 += 1U << offset, SEQ_ALIGN); } while (++offset < ALIGN_BITS); #else @@ -1049,7 +1049,7 @@ lzma_lzma_props_decode(void **options, const lzma_allocator *allocator, // All dictionary sizes are accepted, including zero. LZ decoder // will automatically use a dictionary at least a few KiB even if // a smaller dictionary is requested. - opt->dict_size = unaligned_read32le(props + 1); + opt->dict_size = read32le(props + 1); opt->preset_dict = NULL; opt->preset_dict_size = 0; diff --git a/liblzma/lzma/lzma_encoder.c b/liblzma/lzma/lzma_encoder.c index ba9ce6989c0..07d2b87bc65 100644 --- a/liblzma/lzma/lzma_encoder.c +++ b/liblzma/lzma/lzma_encoder.c @@ -663,7 +663,7 @@ lzma_lzma_props_encode(const void *options, uint8_t *out) if (lzma_lzma_lclppb_encode(opt, out)) return LZMA_PROG_ERROR; - unaligned_write32le(out + 1, opt->dict_size); + write32le(out + 1, opt->dict_size); return LZMA_OK; } diff --git a/liblzma/lzma/lzma_encoder_optimum_normal.c b/liblzma/lzma/lzma_encoder_optimum_normal.c index 59f77343ed7..101c8d47900 100644 --- a/liblzma/lzma/lzma_encoder_optimum_normal.c +++ b/liblzma/lzma/lzma_encoder_optimum_normal.c @@ -636,9 +636,10 @@ helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf, uint32_t len_test_2 = len_test + 1; const uint32_t limit = my_min(buf_avail_full, len_test_2 + nice_len); - for (; len_test_2 < limit - && buf[len_test_2] == buf_back[len_test_2]; - ++len_test_2) ; + // NOTE: len_test_2 may be greater than limit so the call to + // lzma_memcmplen() must be done conditionally. + if (len_test_2 < limit) + len_test_2 = lzma_memcmplen(buf, buf_back, len_test_2, limit); len_test_2 -= len_test + 1; @@ -732,9 +733,12 @@ helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf, const uint32_t limit = my_min(buf_avail_full, len_test_2 + nice_len); - for (; len_test_2 < limit && - buf[len_test_2] == buf_back[len_test_2]; - ++len_test_2) ; + // NOTE: len_test_2 may be greater than limit + // so the call to lzma_memcmplen() must be + // done conditionally. + if (len_test_2 < limit) + len_test_2 = lzma_memcmplen(buf, buf_back, + len_test_2, limit); len_test_2 -= len_test + 1; diff --git a/liblzma/lzma/lzma_encoder_private.h b/liblzma/lzma/lzma_encoder_private.h index a2da969f495..2e34aace16e 100644 --- a/liblzma/lzma/lzma_encoder_private.h +++ b/liblzma/lzma/lzma_encoder_private.h @@ -25,8 +25,7 @@ // MATCH_LEN_MIN bytes. Unaligned access gives tiny gain so there's no // reason to not use it when it is supported. #ifdef TUKLIB_FAST_UNALIGNED_ACCESS -# define not_equal_16(a, b) \ - (*(const uint16_t *)(a) != *(const uint16_t *)(b)) +# define not_equal_16(a, b) (read16ne(a) != read16ne(b)) #else # define not_equal_16(a, b) \ ((a)[0] != (b)[0] || (a)[1] != (b)[1]) diff --git a/liblzma/simple/arm.c b/liblzma/simple/arm.c index 181d0e3b223..ff5073ae58f 100644 --- a/liblzma/simple/arm.c +++ b/liblzma/simple/arm.c @@ -22,9 +22,9 @@ arm_code(void *simple lzma_attribute((__unused__)), size_t i; for (i = 0; i + 4 <= size; i += 4) { if (buffer[i + 3] == 0xEB) { - uint32_t src = (buffer[i + 2] << 16) - | (buffer[i + 1] << 8) - | (buffer[i + 0]); + uint32_t src = ((uint32_t)(buffer[i + 2]) << 16) + | ((uint32_t)(buffer[i + 1]) << 8) + | (uint32_t)(buffer[i + 0]); src <<= 2; uint32_t dest; diff --git a/liblzma/simple/armthumb.c b/liblzma/simple/armthumb.c index eab4862dd76..a8da334a04f 100644 --- a/liblzma/simple/armthumb.c +++ b/liblzma/simple/armthumb.c @@ -23,10 +23,10 @@ armthumb_code(void *simple lzma_attribute((__unused__)), for (i = 0; i + 4 <= size; i += 2) { if ((buffer[i + 1] & 0xF8) == 0xF0 && (buffer[i + 3] & 0xF8) == 0xF8) { - uint32_t src = ((buffer[i + 1] & 0x7) << 19) - | (buffer[i + 0] << 11) - | ((buffer[i + 3] & 0x7) << 8) - | (buffer[i + 2]); + uint32_t src = (((uint32_t)(buffer[i + 1]) & 7) << 19) + | ((uint32_t)(buffer[i + 0]) << 11) + | (((uint32_t)(buffer[i + 3]) & 7) << 8) + | (uint32_t)(buffer[i + 2]); src <<= 1; diff --git a/liblzma/simple/ia64.c b/liblzma/simple/ia64.c index 580529e8086..6492d0a3846 100644 --- a/liblzma/simple/ia64.c +++ b/liblzma/simple/ia64.c @@ -70,7 +70,7 @@ ia64_code(void *simple lzma_attribute((__unused__)), inst_norm |= (uint64_t)(dest & 0x100000) << (36 - 20); - instruction &= (1 << bit_res) - 1; + instruction &= (1U << bit_res) - 1; instruction |= (inst_norm << bit_res); for (size_t j = 0; j < 6; j++) diff --git a/liblzma/simple/powerpc.c b/liblzma/simple/powerpc.c index 54dfbf10287..0b60e9b3fe3 100644 --- a/liblzma/simple/powerpc.c +++ b/liblzma/simple/powerpc.c @@ -25,10 +25,11 @@ powerpc_code(void *simple lzma_attribute((__unused__)), if ((buffer[i] >> 2) == 0x12 && ((buffer[i + 3] & 3) == 1)) { - const uint32_t src = ((buffer[i + 0] & 3) << 24) - | (buffer[i + 1] << 16) - | (buffer[i + 2] << 8) - | (buffer[i + 3] & (~3)); + const uint32_t src + = (((uint32_t)(buffer[i + 0]) & 3) << 24) + | ((uint32_t)(buffer[i + 1]) << 16) + | ((uint32_t)(buffer[i + 2]) << 8) + | ((uint32_t)(buffer[i + 3]) & ~UINT32_C(3)); uint32_t dest; if (is_encoder) diff --git a/liblzma/simple/simple_coder.c b/liblzma/simple/simple_coder.c index 13ebabc76dc..4f499befe95 100644 --- a/liblzma/simple/simple_coder.c +++ b/liblzma/simple/simple_coder.c @@ -118,7 +118,15 @@ simple_code(void *coder_ptr, const lzma_allocator *allocator, // coder->pos and coder->size yet. This way the coder can be // restarted if the next filter in the chain returns e.g. // LZMA_MEM_ERROR. - memcpy(out + *out_pos, coder->buffer + coder->pos, buf_avail); + // + // Do the memcpy() conditionally because out can be NULL + // (in which case buf_avail is always 0). Calling memcpy() + // with a null-pointer is undefined even if the third + // argument is 0. + if (buf_avail > 0) + memcpy(out + *out_pos, coder->buffer + coder->pos, + buf_avail); + *out_pos += buf_avail; // Copy/Encode/Decode more data to out[]. diff --git a/liblzma/simple/simple_decoder.c b/liblzma/simple/simple_decoder.c index 1d864f2bf78..dc4d2415110 100644 --- a/liblzma/simple/simple_decoder.c +++ b/liblzma/simple/simple_decoder.c @@ -28,7 +28,7 @@ lzma_simple_props_decode(void **options, const lzma_allocator *allocator, if (opt == NULL) return LZMA_MEM_ERROR; - opt->start_offset = unaligned_read32le(props); + opt->start_offset = read32le(props); // Don't leave an options structure allocated if start_offset is zero. if (opt->start_offset == 0) diff --git a/liblzma/simple/simple_encoder.c b/liblzma/simple/simple_encoder.c index 8aa463bed22..d2cc03e58b8 100644 --- a/liblzma/simple/simple_encoder.c +++ b/liblzma/simple/simple_encoder.c @@ -32,7 +32,7 @@ lzma_simple_props_encode(const void *options, uint8_t *out) if (opt == NULL || opt->start_offset == 0) return LZMA_OK; - unaligned_write32le(out, opt->start_offset); + write32le(out, opt->start_offset); return LZMA_OK; } diff --git a/liblzma/simple/x86.c b/liblzma/simple/x86.c index 0b14807e900..0e78909ccc0 100644 --- a/liblzma/simple/x86.c +++ b/liblzma/simple/x86.c @@ -97,7 +97,7 @@ x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder, if (!Test86MSByte(b)) break; - src = dest ^ ((1 << (32 - i * 8)) - 1); + src = dest ^ ((1U << (32 - i * 8)) - 1); } buffer[buffer_pos + 4] From 5380d858ff4cb21ae1a8777a9b721af97f598c37 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Fri, 16 Apr 2021 18:03:22 +0200 Subject: [PATCH 0287/1519] liblzma: Enable multi threaded stream encoding support --- CMakeLists.txt | 1 + Help/cpack_gen/archive.rst | 7 ++++--- Help/release/dev/lzma-threads.rst | 7 +++++++ Modules/CPack.cmake | 7 ++++--- Utilities/cmliblzma/CMakeLists.txt | 12 ++++++++++++ Utilities/cmliblzma/liblzma/common/common.h | 1 + 6 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/lzma-threads.rst diff --git a/CMakeLists.txt b/CMakeLists.txt index 045a283fa57..4f03c39cbf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -579,6 +579,7 @@ macro (CMAKE_BUILD_UTILITIES) set(LIBLZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") set(LIBLZMA_LIBRARY cmliblzma) + set(HAVE_LZMA_STREAM_ENCODER_MT 1) endif() endif() diff --git a/Help/cpack_gen/archive.rst b/Help/cpack_gen/archive.rst index b9418126f82..47e8e135466 100644 --- a/Help/cpack_gen/archive.rst +++ b/Help/cpack_gen/archive.rst @@ -82,7 +82,8 @@ CPack generators which are essentially archives at their core. These include: See also the :variable:`CPACK_THREADS` variable. -.. note:: + .. versionadded:: 3.21 - Official CMake binaries available on ``cmake.org`` ship with a ``liblzma`` - that does not support parallel compression. + Official CMake binaries available on ``cmake.org`` now ship + with a ``liblzma`` that supports parallel compression. + Older versions did not. diff --git a/Help/release/dev/lzma-threads.rst b/Help/release/dev/lzma-threads.rst new file mode 100644 index 00000000000..a481cfa684c --- /dev/null +++ b/Help/release/dev/lzma-threads.rst @@ -0,0 +1,7 @@ +lzma-threads +------------ + +* The precompiled binaries provided on + `cmake.org `_ now support + ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and + :variable:`CPACK_ARCHIVE_THREADS` variables. diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index ef5a7d5b1a9..3b29ede644d 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -299,10 +299,11 @@ installers. The most commonly-used variables are: Currently only ``xz`` compression *may* take advantage of multiple cores. Other compression methods ignore this value and use only one thread. - .. note:: + .. versionadded:: 3.21 - Official CMake binaries available on ``cmake.org`` ship with a ``liblzma`` - that does not support parallel compression. + Official CMake binaries available on ``cmake.org`` now ship + with a ``liblzma`` that supports parallel compression. + Older versions did not. Variables for Source Package Generators ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt index 5dd7035da3c..4820a8fd01f 100644 --- a/Utilities/cmliblzma/CMakeLists.txt +++ b/Utilities/cmliblzma/CMakeLists.txt @@ -6,6 +6,12 @@ include(CheckSymbolExists) include(CheckTypeSize) include(TestBigEndian) +if(WIN32) + add_definitions(-DMYTHREAD_VISTA) +else() + add_definitions(-DMYTHREAD_POSIX) +endif() + CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H) CHECK_INCLUDE_FILE(limits.h HAVE_LIMITS_H) CHECK_INCLUDE_FILE(memory.h HAVE_MEMORY_H) @@ -60,7 +66,10 @@ set(HAVE_MF_HC3 1) set(HAVE_MF_HC4 1) SET(LZMA_SRCS + common/mythread.h common/sysdefs.h + common/tuklib_cpucores.c + common/tuklib_cpucores.h common/tuklib_integer.h liblzma/check/check.c liblzma/check/crc32_fast.c @@ -91,14 +100,17 @@ SET(LZMA_SRCS liblzma/common/filter_encoder.c liblzma/common/filter_flags_decoder.c liblzma/common/filter_flags_encoder.c + liblzma/common/hardware_cputhreads.c liblzma/common/index.c liblzma/common/index_decoder.c liblzma/common/index_encoder.c liblzma/common/index_hash.c + liblzma/common/outqueue.c liblzma/common/stream_buffer_decoder.c liblzma/common/stream_buffer_encoder.c liblzma/common/stream_decoder.c liblzma/common/stream_encoder.c + liblzma/common/stream_encoder_mt.c liblzma/common/stream_flags_common.c liblzma/common/stream_flags_decoder.c liblzma/common/stream_flags_encoder.c diff --git a/Utilities/cmliblzma/liblzma/common/common.h b/Utilities/cmliblzma/liblzma/common/common.h index dde3ae0eca4..b3d3b7a059b 100644 --- a/Utilities/cmliblzma/liblzma/common/common.h +++ b/Utilities/cmliblzma/liblzma/common/common.h @@ -14,6 +14,7 @@ #define LZMA_COMMON_H #include "sysdefs.h" +#include "mythread.h" #include "tuklib_integer.h" #if defined(_WIN32) || defined(__CYGWIN__) From c5c130e675624eef03f5bcaf848810659e205ed2 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Mon, 19 Apr 2021 19:37:57 +0200 Subject: [PATCH 0288/1519] cmArchiveWrite: Consolidate multiple ways to set thread count Merge use of SetFilterOption() into more abstract thread count in cmArchiveWrite constructor. libarchive defaulting of threads for threads == 0 seems to be configuration dependent. Preemptively default thread count via std::thread::hardware_concurrency(). Also allow negative values for the thread count in which case the detected hardware concurrency is also used but the given absolute thread count is used as an upper limit. --- Modules/CPack.cmake | 18 +++++-- Source/CPack/cmCPackArchiveGenerator.cxx | 39 +++++---------- Source/CPack/cmCPackArchiveGenerator.h | 2 +- Source/CPack/cmCPackDebGenerator.cxx | 5 -- Source/cmArchiveWrite.cxx | 48 ++++++++++++------- Source/cmArchiveWrite.h | 3 -- .../CPack/tests/THREADED_ALL/test.cmake | 2 +- 7 files changed, 56 insertions(+), 61 deletions(-) diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 3b29ede644d..373a707308e 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -291,13 +291,21 @@ installers. The most commonly-used variables are: Some compression methods used by CPack generators such as Debian or Archive may take advantage of multiple CPU cores to speed up compression. - ``CPACK_THREADS`` can be set to positive integer to specify how many threads - will be used for compression. If it is set to 0, CPack will set it so that - all available CPU cores are used. + ``CPACK_THREADS`` can be set to specify how many threads will be + used for compression. + + A positive integer can be used to specify an exact desired thread count. + + When given a negative integer CPack will use the absolute value + as the upper limit but may choose a lower value based on + the available hardware concurrency. + + Given 0 CPack will try to use all available CPU cores. + By default ``CPACK_THREADS`` is set to ``1``. - Currently only ``xz`` compression *may* take advantage of multiple cores. Other - compression methods ignore this value and use only one thread. + Currently only ``xz`` compression *may* take advantage of multiple cores. + Other compression methods ignore this value and use only one thread. .. versionadded:: 3.21 diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 7fd12dd4c12..d9234e66699 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -2,14 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackArchiveGenerator.h" +#include #include #include #include #include #include -#include - #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" @@ -154,15 +153,9 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( << (filename) << ">." << std::endl); \ return 0; \ } \ - cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \ + cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat, 0, \ + this->GetThreadCount()); \ do { \ - if (!this->SetArchiveOptions(&archive)) { \ - cmCPackLogger(cmCPackLog::LOG_ERROR, \ - "Problem to set archive options <" \ - << (filename) << ">, ERROR = " << (archive).GetError() \ - << std::endl); \ - return 0; \ - } \ if (!archive.Open()) { \ cmCPackLogger(cmCPackLog::LOG_ERROR, \ "Problem to open archive <" \ @@ -346,26 +339,16 @@ bool cmCPackArchiveGenerator::SupportsComponentInstallation() const return this->IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL"); } -bool cmCPackArchiveGenerator::SetArchiveOptions(cmArchiveWrite* archive) +int cmCPackArchiveGenerator::GetThreadCount() const { -#if ARCHIVE_VERSION_NUMBER >= 3004000 - // Upstream fixed an issue with their integer parsing in 3.4.0 which would - // cause spurious errors to be raised from `strtoull`. - if (this->Compress == cmArchiveWrite::CompressXZ) { - const char* threads = "1"; - - // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS - if (this->IsSet("CPACK_ARCHIVE_THREADS")) { - threads = this->GetOption("CPACK_ARCHIVE_THREADS"); - } else if (this->IsSet("CPACK_THREADS")) { - threads = this->GetOption("CPACK_THREADS"); - } + int threads = 1; - if (!archive->SetFilterOption("xz", "threads", threads)) { - return false; - } + // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS + if (this->IsSet("CPACK_ARCHIVE_THREADS")) { + threads = std::atoi(this->GetOption("CPACK_ARCHIVE_THREADS")); + } else if (this->IsSet("CPACK_THREADS")) { + threads = std::atoi(this->GetOption("CPACK_THREADS")); } -#endif - return true; + return threads; } diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h index 5b40013b4a7..8a9bbc66b59 100644 --- a/Source/CPack/cmCPackArchiveGenerator.h +++ b/Source/CPack/cmCPackArchiveGenerator.h @@ -85,7 +85,7 @@ class cmCPackArchiveGenerator : public cmCPackGenerator return this->OutputExtension.c_str(); } - bool SetArchiveOptions(cmArchiveWrite* archive); + int GetThreadCount() const; private: cmArchiveWrite::Compress Compress; diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index e7bcfaca4fa..0fafd856ce3 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -130,11 +130,6 @@ DebGenerator::DebGenerator( "Unrecognized number of threads: " << numThreads << std::endl); } - - if (this->NumThreads < 0) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Number of threads cannot be negative" << std::endl); - } } bool DebGenerator::generate() const diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index b685b73af8e..54b29982468 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -2,11 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmArchiveWrite.h" -#include +#include #include #include #include +#include #include +#include +#include + +#include #include #include @@ -144,16 +149,36 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, cm_archive_error_string(this->Archive)); return; } + { - char sNumThreads[8]; - snprintf(sNumThreads, sizeof(sNumThreads), "%d", numThreads); - sNumThreads[7] = '\0'; // for safety +#if ARCHIVE_VERSION_NUMBER >= 3004000 + // Upstream fixed an issue with their integer parsing in 3.4.0 + // which would cause spurious errors to be raised from `strtoull`. + + if (numThreads < 1) { + int upperLimit = (numThreads == 0) ? std::numeric_limits::max() + : std::abs(numThreads); + + numThreads = + cm::clamp(std::thread::hardware_concurrency(), 1, upperLimit); + } + +# ifdef _AIX + // FIXME: Using more than 2 threads creates an empty archive. + // Enforce this limit pending further investigation. + numThreads = std::min(numThreads, 2); +# endif + + std::string sNumThreads = std::to_string(numThreads); + if (archive_write_set_filter_option(this->Archive, "xz", "threads", - sNumThreads) != ARCHIVE_OK) { + sNumThreads.c_str()) != + ARCHIVE_OK) { this->Error = cmStrCat("archive_compressor_xz_options: ", cm_archive_error_string(this->Archive)); return; } +#endif } break; @@ -425,16 +450,3 @@ bool cmArchiveWrite::AddData(const char* file, size_t size) } return true; } - -bool cmArchiveWrite::SetFilterOption(const char* module, const char* key, - const char* value) -{ - if (archive_write_set_filter_option(this->Archive, module, key, value) != - ARCHIVE_OK) { - this->Error = "archive_write_set_filter_option: "; - this->Error += cm_archive_error_string(this->Archive); - return false; - } - - return true; -} diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 34aafe905cd..260bd20caae 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -141,9 +141,6 @@ class cmArchiveWrite this->Gname = ""; } - //! Set an option on a filter; - bool SetFilterOption(const char* module, const char* key, const char* value); - private: bool Okay() const { return this->Error.empty(); } bool AddPath(const char* path, size_t skip, const char* prefix, diff --git a/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake b/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake index 6f372013118..af39e5f2c91 100644 --- a/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake +++ b/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake @@ -1,6 +1,6 @@ install(FILES CMakeLists.txt DESTINATION foo COMPONENT test) -set(CPACK_THREADS 0) +set(CPACK_THREADS "-4") if(PACKAGING_TYPE STREQUAL "COMPONENT") set(CPACK_COMPONENTS_ALL test) From 15a148dec63d04f302b6c0b951104f8eb470ce1c Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 23 Apr 2021 00:01:09 -0400 Subject: [PATCH 0289/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 970dfaade10..f9bde6dd017 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210422) +set(CMake_VERSION_PATCH 20210423) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 5b0ea5874a3322e57156b329b340bf283673c207 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 20 Apr 2021 21:17:50 +0200 Subject: [PATCH 0290/1519] AutoGen: Retrieve Qt version from moc as fallback Consider the case where the find_package call for QtCore is wrapped in a function call. Then AutoGen cannot determine the Qt version, because it only looks at variables and directory properties. The former don't leave the function scope and the latter are not set by default. As a fallback, locate the moc executable via its target and call it with the --version argument to determine the Qt version. Issue: #22028 --- Source/cmQtAutoGenGlobalInitializer.cxx | 3 +- Source/cmQtAutoGenInitializer.cxx | 74 ++++++++++++++++++- Source/cmQtAutoGenInitializer.h | 6 +- Tests/QtAutogen/Tests.cmake | 1 + .../WrappedFindPackage/CMakeLists.txt | 16 ++++ Tests/QtAutogen/WrappedFindPackage/main.cpp | 19 +++++ 6 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt create mode 100644 Tests/QtAutogen/WrappedFindPackage/main.cpp diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index f79ffd4a0f8..5896bb2c4bd 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -114,7 +114,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( target->GetSafeProperty(this->kw().AUTORCC_EXECUTABLE); // We support Qt4, Qt5 and Qt6 - auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target.get()); + auto qtVersion = + cmQtAutoGenInitializer::GetQtVersion(target.get(), mocExec); bool const validQt = (qtVersion.first.Major == 4) || (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 3adeb1aee0c..148591ce271 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include // for basic_ios, istringstream #include #include #include @@ -1833,8 +1833,63 @@ void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString) } } +static cmQtAutoGen::IntegerVersion parseMocVersion(std::string str) +{ + cmQtAutoGen::IntegerVersion result; + + static const std::string prelude = "moc "; + size_t pos = str.find(prelude); + if (pos == std::string::npos) { + return result; + } + + str.erase(0, prelude.size() + pos); + std::istringstream iss(str); + std::string major; + std::string minor; + if (!std::getline(iss, major, '.') || !std::getline(iss, minor, '.')) { + return result; + } + + result.Major = static_cast(std::stoi(major)); + result.Minor = static_cast(std::stoi(minor)); + return result; +} + +static cmQtAutoGen::IntegerVersion GetMocVersion( + const std::string& mocExecutablePath) +{ + std::string capturedStdOut; + int exitCode; + if (!cmSystemTools::RunSingleCommand({ mocExecutablePath, "--version" }, + &capturedStdOut, nullptr, &exitCode, + nullptr, cmSystemTools::OUTPUT_NONE)) { + return {}; + } + + if (exitCode != 0) { + return {}; + } + + return parseMocVersion(capturedStdOut); +} + +static std::string FindMocExecutableFromMocTarget(cmMakefile* makefile, + unsigned int qtMajorVersion) +{ + std::string result; + const std::string mocTargetName = + "Qt" + std::to_string(qtMajorVersion) + "::moc"; + cmTarget* mocTarget = makefile->FindTargetToUse(mocTargetName); + if (mocTarget) { + result = mocTarget->GetSafeProperty("IMPORTED_LOCATION"); + } + return result; +} + std::pair -cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) +cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target, + std::string mocExecutable) { // Converts a char ptr to an unsigned int value auto toUInt = [](const char* const input) -> unsigned int { @@ -1909,6 +1964,21 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) } } } + + if (res.first.Major == 0) { + // We could not get the version number from variables or directory + // properties. This might happen if the find_package call for Qt is wrapped + // in a function. Try to find the moc executable path from the available + // targets and call "moc --version" to get the Qt version. + if (mocExecutable.empty()) { + mocExecutable = + FindMocExecutableFromMocTarget(target->Makefile, res.second); + } + if (!mocExecutable.empty()) { + res.first = GetMocVersion(mocExecutable); + } + } + return res; } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 8a6d8f924fa..e76817b9c43 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -98,9 +98,11 @@ class cmQtAutoGenInitializer : public cmQtAutoGen , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){}; }; - /** @return The detected Qt version and the required Qt major version. */ + /** @param mocExecutable The file path to the moc executable. Will be used as + fallback to query the version + @return The detected Qt version and the required Qt major version. */ static std::pair GetQtVersion( - cmGeneratorTarget const* genTarget); + cmGeneratorTarget const* genTarget, std::string mocExecutable); cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* genTarget, diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake index ab5686af656..a3c57a58717 100644 --- a/Tests/QtAutogen/Tests.cmake +++ b/Tests/QtAutogen/Tests.cmake @@ -49,6 +49,7 @@ if(QT_TEST_VERSION GREATER 4) ADD_AUTOGEN_TEST(MocMacroName mocMacroName) ADD_AUTOGEN_TEST(MocOsMacros) ADD_AUTOGEN_TEST(RerunMocPlugin) + ADD_AUTOGEN_TEST(WrappedFindPackage) if(APPLE) ADD_AUTOGEN_TEST(MacOsFW) endif() diff --git a/Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt b/Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt new file mode 100644 index 00000000000..e8f50d56e7f --- /dev/null +++ b/Tests/QtAutogen/WrappedFindPackage/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.20) +project(WrappedFindPackage) + +# Wrap the find_package call in a function. +# Test whether AutoMoc can retrieve the Qt version from the moc executable. +function(find_qt_package) + include("../AutogenCoreTest.cmake") + set(QT_LIBRARIES "${QT_LIBRARIES}" PARENT_SCOPE) +endfunction() + +find_qt_package() + +set(CMAKE_AUTOMOC ON) + +add_executable(wrappedFindPackage main.cpp) +target_link_libraries(wrappedFindPackage PRIVATE ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/WrappedFindPackage/main.cpp b/Tests/QtAutogen/WrappedFindPackage/main.cpp new file mode 100644 index 00000000000..1e2c63fab33 --- /dev/null +++ b/Tests/QtAutogen/WrappedFindPackage/main.cpp @@ -0,0 +1,19 @@ +#include + +class MyObject : public QObject +{ + Q_OBJECT +public: + MyObject(QObject* parent = 0) + : QObject(parent) + { + } +}; + +int main() +{ + MyObject obj; + return 0; +} + +#include "main.moc" From e3e005dbd8bcb64b20a0923078c3fed0e58cff2c Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 23 Apr 2021 17:09:12 +0200 Subject: [PATCH 0291/1519] UseSWIG: use swig dependencies for Xcode generator --- Help/release/dev/UseSWIG-dependencies.rst | 6 ++++++ Modules/UseSWIG.cmake | 23 ++++++++++++++++------- Tests/UseSWIG/CMakeLists.txt | 3 ++- 3 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 Help/release/dev/UseSWIG-dependencies.rst diff --git a/Help/release/dev/UseSWIG-dependencies.rst b/Help/release/dev/UseSWIG-dependencies.rst new file mode 100644 index 00000000000..b5a38c3eeb0 --- /dev/null +++ b/Help/release/dev/UseSWIG-dependencies.rst @@ -0,0 +1,6 @@ +UseSWIG-dependencies +-------------------- + +* :module:`UseSWIG` module gained the capability, for + :generator:`Xcode` generator, to use `swig` tool to generate implicit + dependencies. diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 8852df86627..269fa987ece 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -191,8 +191,12 @@ ensure generated files will receive the required settings. If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool itself. This property is only meaningful for - :ref:`Makefile ` and - :ref:`Ninja ` generators. Default value is ``FALSE``. + :ref:`Makefile `, + :ref:`Ninja ` and :generator:`Xcode` generators. Default + value is ``FALSE``. + + .. versionadded:: 3.21 + Added the support of :generator:`Xcode` generator. ``SWIG_MODULE_NAME`` Specify the actual import name of the module in the target language. @@ -336,12 +340,17 @@ as well as ``SWIG``: .. versionadded:: 3.20 If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool - itself. This property is only meaningful for - :ref:`Makefile ` and - :ref:`Ninja ` generators. Default value is ``FALSE``. + itself. This variable is only meaningful for + :ref:`Makefile `, + :ref:`Ninja ` and :generator:`Xcode` generators. Default + value is ``FALSE``. Source file property ``USE_SWIG_DEPENDENCIES``, if not defined, will be initialized with the value of this variable. + + .. versionadded:: 3.21 + Added the support of :generator:`Xcode` generator. + #]=======================================================================] cmake_policy(PUSH) @@ -506,7 +515,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) endif() set (use_swig_dependencies ${SWIG_USE_SWIG_DEPENDENCIES}) - if (CMAKE_GENERATOR MATCHES "Make|Ninja") + if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode") get_property(use_swig_dependencies_set SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES SET) if (use_swig_dependencies_set) get_property(use_swig_dependencies SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES) @@ -831,7 +840,7 @@ function(SWIG_ADD_LIBRARY name) set(SWIG_SOURCE_FILE_EXTENSIONS ".i") endif() - if (CMAKE_GENERATOR MATCHES "Make|Ninja") + if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode") # For Makefiles and Ninja generators, use SWIG generated dependencies if (NOT DEFINED SWIG_USE_SWIG_DEPENDENCIES) set (SWIG_USE_SWIG_DEPENDENCIES OFF) diff --git a/Tests/UseSWIG/CMakeLists.txt b/Tests/UseSWIG/CMakeLists.txt index d08c59ca367..f1b2f321484 100644 --- a/Tests/UseSWIG/CMakeLists.txt +++ b/Tests/UseSWIG/CMakeLists.txt @@ -66,7 +66,8 @@ add_test(NAME UseSWIG.BasicPerl COMMAND --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) -if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2") +if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2" + AND CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode") add_test(NAME UseSWIG.Depfile.BasicPython COMMAND ${CMAKE_CTEST_COMMAND} -C $ --build-and-test From 88f5d4b24ffce8698c45a61b59ab6cde1bc00a15 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 24 Apr 2021 00:01:09 -0400 Subject: [PATCH 0292/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f9bde6dd017..c066b4e3714 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210423) +set(CMake_VERSION_PATCH 20210424) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 5f90a93fd71c5951897c7f9acc64cd970e2a06b9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 25 Apr 2021 00:01:06 -0400 Subject: [PATCH 0293/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c066b4e3714..c7aaefc02cf 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210424) +set(CMake_VERSION_PATCH 20210425) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From eeb771e4d6b9a1127a0818a211cafb722a2dc387 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 26 Apr 2021 00:01:07 -0400 Subject: [PATCH 0294/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c7aaefc02cf..e7ac9a49ba5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210425) +set(CMake_VERSION_PATCH 20210426) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 25bf514447501963a31934b5b03c65aeb53a351f Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Fri, 23 Apr 2021 09:38:43 +1000 Subject: [PATCH 0295/1519] ctest: Add support for writing test results in JUnit XML format Addresses #18654 --- Help/command/ctest_test.rst | 10 ++ Help/manual/ctest.1.rst | 6 + Help/release/dev/ctest-output-junit.rst | 5 + Source/CTest/cmCTestMemCheckCommand.cxx | 2 +- Source/CTest/cmCTestMemCheckCommand.h | 3 +- Source/CTest/cmCTestTestCommand.cxx | 10 +- Source/CTest/cmCTestTestCommand.h | 4 +- Source/CTest/cmCTestTestHandler.cxx | 130 ++++++++++++++++++ Source/CTest/cmCTestTestHandler.h | 10 ++ Source/cmCTest.cxx | 11 ++ Source/ctest.cxx | 1 + .../CTestCommandLine/RunCMakeTest.cmake | 19 +++ .../CTestCommandLine/output-junit-check.cmake | 36 +++++ .../CTestCommandLine/output-junit-result.txt | 1 + .../CTestCommandLine/output-junit-stderr.txt | 1 + .../ctest_test/OutputJUnit-check.cmake | 24 ++++ Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 3 + Utilities/IWYU/mapping.imp | 1 + 18 files changed, 271 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/ctest-output-junit.rst create mode 100644 Tests/RunCMake/CTestCommandLine/output-junit-check.cmake create mode 100644 Tests/RunCMake/CTestCommandLine/output-junit-result.txt create mode 100644 Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt create mode 100644 Tests/RunCMake/ctest_test/OutputJUnit-check.cmake diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index b4493a03dd7..9081b3f4b17 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -25,6 +25,7 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`. [RETURN_VALUE ] [CAPTURE_CMAKE_ERROR ] [REPEAT :] + [OUTPUT_JUNIT ] [QUIET] ) @@ -150,6 +151,15 @@ The options are: Store in the ```` variable -1 if there are any errors running the command and prevent ctest from returning non-zero if an error occurs. +``OUTPUT_JUNIT`` + .. versionadded:: 3.21 + + Write test results to ```` in JUnit XML format. If ```` is a + relative path it will be placed in the build directory. If ``>`` + already exists it will be overwritten. Note that the resulting JUnit XML + file is **not** uploaded to CDash because it would be redundant with + CTest's ``Test.xml`` file. + ``QUIET`` .. versionadded:: 3.3 diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 68409e1ed93..3d80cece288 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -134,6 +134,12 @@ Options This option tells CTest to write all its output to a ```` log file. +``--output-junit `` + Write test results in JUnit format. + + This option tells CTest to write test results to a ```` JUnit XML file. + If ```` already exists it will be overwritten. + ``-N,--show-only[=]`` Disable actual execution of tests. diff --git a/Help/release/dev/ctest-output-junit.rst b/Help/release/dev/ctest-output-junit.rst new file mode 100644 index 00000000000..66df19d6e47 --- /dev/null +++ b/Help/release/dev/ctest-output-junit.rst @@ -0,0 +1,5 @@ +ctest-output-junit +------------------ + +* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results + to a JUnit XML file. diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index d0e2974524f..37b36287204 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -14,7 +14,7 @@ void cmCTestMemCheckCommand::BindArguments() this->Bind("DEFECT_COUNT"_s, this->DefectCount); } -cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() +cmCTestTestHandler* cmCTestMemCheckCommand::InitializeActualHandler() { cmCTestMemCheckHandler* handler = this->CTest->GetMemCheckHandler(); handler->Initialize(); diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index 6544f16cfde..ee39e49a92c 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -13,6 +13,7 @@ #include "cmCommand.h" class cmCTestGenericHandler; +class cmCTestTestHandler; /** \class cmCTestMemCheck * \brief Run a ctest script @@ -36,7 +37,7 @@ class cmCTestMemCheckCommand : public cmCTestTestCommand protected: void BindArguments() override; - cmCTestGenericHandler* InitializeActualHandler() override; + cmCTestTestHandler* InitializeActualHandler() override; void ProcessAdditionalValues(cmCTestGenericHandler* handler) override; diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 886c2630679..67f49860863 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -9,7 +9,6 @@ #include #include "cmCTest.h" -#include "cmCTestGenericHandler.h" #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmMakefile.h" @@ -36,6 +35,7 @@ void cmCTestTestCommand::BindArguments() this->Bind("TEST_LOAD"_s, this->TestLoad); this->Bind("RESOURCE_SPEC_FILE"_s, this->ResourceSpecFile); this->Bind("STOP_ON_FAILURE"_s, this->StopOnFailure); + this->Bind("OUTPUT_JUNIT"_s, this->OutputJUnit); } cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() @@ -60,7 +60,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() this->ResourceSpecFile = *resourceSpecFile; } - cmCTestGenericHandler* handler = this->InitializeActualHandler(); + cmCTestTestHandler* handler = this->InitializeActualHandler(); if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) { handler->SetOption( "TestsToRunInformation", @@ -140,11 +140,15 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() *labelsForSubprojects, this->Quiet); } + if (!this->OutputJUnit.empty()) { + handler->SetJUnitXMLFileName(this->OutputJUnit); + } + handler->SetQuiet(this->Quiet); return handler; } -cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler() +cmCTestTestHandler* cmCTestTestCommand::InitializeActualHandler() { cmCTestTestHandler* handler = this->CTest->GetTestHandler(); handler->Initialize(); diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 624cd91fefe..24e74e2baa5 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -13,6 +13,7 @@ #include "cmCommand.h" class cmCTestGenericHandler; +class cmCTestTestHandler; /** \class cmCTestTest * \brief Run a ctest script @@ -40,7 +41,7 @@ class cmCTestTestCommand : public cmCTestHandlerCommand protected: void BindArguments() override; - virtual cmCTestGenericHandler* InitializeActualHandler(); + virtual cmCTestTestHandler* InitializeActualHandler(); cmCTestGenericHandler* InitializeHandler() override; std::string Start; @@ -59,5 +60,6 @@ class cmCTestTestCommand : public cmCTestHandlerCommand std::string StopTime; std::string TestLoad; std::string ResourceSpecFile; + std::string OutputJUnit; bool StopOnFailure = false; }; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index db5cb9c2bef..1596d4ac32b 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -42,6 +42,7 @@ #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTimestamp.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -299,6 +300,9 @@ cmCTestTestHandler::cmCTestTestHandler() this->LogFile = nullptr; + // Support for JUnit XML output. + this->JUnitXMLFileName = ""; + // regex to detect ... this->DartStuff.compile("()"); // regex to detect each individual ... @@ -456,6 +460,10 @@ int cmCTestTestHandler::ProcessHandler() return 1; } + if (!this->WriteJUnitXML()) { + return 1; + } + if (!this->PostProcessHandler()) { this->LogFile = nullptr; return -1; @@ -2457,3 +2465,125 @@ bool cmCTestTestHandler::cmCTestTestResourceRequirement::operator!=( { return !(*this == other); } + +void cmCTestTestHandler::SetJUnitXMLFileName(const std::string& filename) +{ + this->JUnitXMLFileName = filename; +} + +bool cmCTestTestHandler::WriteJUnitXML() +{ + if (this->JUnitXMLFileName.empty()) { + return true; + } + + // Open new XML file for writing. + cmGeneratedFileStream xmlfile; + xmlfile.SetTempExt("tmp"); + xmlfile.Open(this->JUnitXMLFileName); + if (!xmlfile) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Problem opening file: " << this->JUnitXMLFileName + << std::endl); + return false; + } + cmXMLWriter xml(xmlfile); + + // Iterate over the test results to get the number of tests that + // passed, failed, etc. + auto num_tests = 0; + auto num_passed = 0; + auto num_failed = 0; + auto num_notrun = 0; + auto num_disabled = 0; + SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end()); + for (cmCTestTestResult const& result : resultsSet) { + num_tests++; + if (result.Status == cmCTestTestHandler::COMPLETED) { + num_passed++; + } else if (result.Status == cmCTestTestHandler::NOT_RUN) { + if (result.CompletionStatus == "Disabled") { + num_disabled++; + } else { + num_notrun++; + } + } else { + num_failed++; + } + } + + // Write element. + xml.StartDocument(); + xml.StartElement("testsuite"); + + xml.Attribute("name", + cmCTest::SafeBuildIdField( + this->CTest->GetCTestConfiguration("BuildName"))); + xml.BreakAttributes(); + + xml.Attribute("tests", num_tests); + xml.Attribute("failures", num_failed); + + // CTest disabled => JUnit disabled + xml.Attribute("disabled", num_disabled); + + // Otherwise, CTest notrun => JUnit skipped. + // The distinction between JUnit disabled vs. skipped is that + // skipped tests can have a message associated with them + // (why the test was skipped). + xml.Attribute("skipped", num_notrun); + + xml.Attribute("hostname", this->CTest->GetCTestConfiguration("Site")); + xml.Attribute( + "time", + std::chrono::duration_cast(this->ElapsedTestingTime) + .count()); + const std::time_t start_test_time_t = + std::chrono::system_clock::to_time_t(this->StartTestTime); + cmTimestamp cmts; + xml.Attribute("timestamp", + cmts.CreateTimestampFromTimeT(start_test_time_t, + "%Y-%m-%dT%H:%M:%S", false)); + + // Write elements. + for (cmCTestTestResult const& result : resultsSet) { + xml.StartElement("testcase"); + xml.Attribute("name", result.Name); + xml.Attribute("classname", result.Name); + xml.Attribute("time", result.ExecutionTime.count()); + + std::string status; + if (result.Status == cmCTestTestHandler::COMPLETED) { + status = "run"; + } else if (result.Status == cmCTestTestHandler::NOT_RUN) { + if (result.CompletionStatus == "Disabled") { + status = "disabled"; + } else { + status = "notrun"; + } + } else { + status = "fail"; + } + xml.Attribute("status", status); + + if (status == "notrun") { + xml.StartElement("skipped"); + xml.Attribute("message", result.CompletionStatus); + xml.EndElement(); // + } else if (status == "fail") { + xml.StartElement("failure"); + xml.Attribute("message", result.Reason); + xml.EndElement(); // + } + + // Note: compressed test output is unconditionally disabled when + // --output-junit is specified. + xml.Element("system-out", result.Output); + xml.EndElement(); // + } + + xml.EndElement(); // + xml.EndDocument(); + + return true; +} diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 6fa18a900f0..68416246f8a 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -209,6 +209,9 @@ class cmCTestTestHandler : public cmCTestGenericHandler using ListOfTests = std::vector; + // Support for writing test results in JUnit XML format. + void SetJUnitXMLFileName(const std::string& id); + protected: using SetOfTests = std::set; @@ -274,6 +277,11 @@ class cmCTestTestHandler : public cmCTestGenericHandler */ virtual void GenerateDartOutput(cmXMLWriter& xml); + /** + * Write test results in JUnit XML format + */ + bool WriteJUnitXML(); + void PrintLabelOrSubprojectSummary(bool isSubProject); /** @@ -354,4 +362,6 @@ class cmCTestTestHandler : public cmCTestGenericHandler cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; int RepeatCount = 1; bool RerunFailed; + + std::string JUnitXMLFileName; }; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 643b43f6dd0..79a39255090 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2069,6 +2069,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } i++; this->Impl->TestDir = std::string(args[i]); + } else if (this->CheckArgument(arg, "--output-junit"_s)) { + if (i >= args.size() - 1) { + errormsg = "'--output-junit' requires an argument"; + return false; + } + i++; + this->Impl->TestHandler.SetJUnitXMLFileName(std::string(args[i])); + // Turn test output compression off. + // This makes it easier to include test output in the resulting + // JUnit XML report. + this->Impl->CompressTestOutput = false; } cm::string_view noTestsPrefix = "--no-tests="; diff --git a/Source/ctest.cxx b/Source/ctest.cxx index a4b85ae310c..cad27fac467 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -50,6 +50,7 @@ static const char* cmDocumentationOptions[][2] = { "given number of jobs." }, { "-Q,--quiet", "Make ctest quiet." }, { "-O , --output-log ", "Output to log file" }, + { "--output-junit ", "Output test results to JUnit XML file." }, { "-N,--show-only[=format]", "Disable actual execution of tests. The optional 'format' defines the " "format of the test information and can be 'human' for the current text " diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index 2f4d731f067..afec0114aa4 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -397,3 +397,22 @@ function(run_testDir) run_cmake_command(testDir ${CMAKE_CTEST_COMMAND} --test-dir "${RunCMake_TEST_BINARY_DIR}/sub") endfunction() run_testDir() + +# Test --output-junit +function(run_output_junit) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/output-junit) + 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(test1 \"${CMAKE_COMMAND}\" -E false) +add_test(test2 \"${CMAKE_COMMAND}\" -E echo \"hello world\") +add_test(test3 \"${CMAKE_COMMAND}\" -E true) +set_tests_properties(test3 PROPERTIES DISABLED \"ON\") +add_test(test4 \"${CMAKE_COMMAND}/doesnt_exist\") +add_test(test5 \"${CMAKE_COMMAND}\" -E echo \"please skip\") +set_tests_properties(test5 PROPERTIES SKIP_REGULAR_EXPRESSION \"please skip\") +") + run_cmake_command(output-junit ${CMAKE_CTEST_COMMAND} --output-junit "${RunCMake_TEST_BINARY_DIR}/junit.xml") +endfunction() +run_output_junit() diff --git a/Tests/RunCMake/CTestCommandLine/output-junit-check.cmake b/Tests/RunCMake/CTestCommandLine/output-junit-check.cmake new file mode 100644 index 00000000000..b270fdf6a87 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/output-junit-check.cmake @@ -0,0 +1,36 @@ +file(GLOB junit_xml_file "${RunCMake_TEST_BINARY_DIR}/junit.xml") +if(junit_xml_file) + file(READ "${junit_xml_file}" junit_xml LIMIT 4096) + if(NOT "${junit_xml}" MATCHES "tests=\"5\"") + set(RunCMake_TEST_FAILED "tests=\"5\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "failures=\"1\"") + set(RunCMake_TEST_FAILED "failures=\"1\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "disabled=\"1\"") + set(RunCMake_TEST_FAILED "disabled=\"1\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "skipped=\"2\"") + set(RunCMake_TEST_FAILED "skipped=\"2\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "hello world") + set(RunCMake_TEST_FAILED "hello world not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "Disabled") + set(RunCMake_TEST_FAILED "Disabled not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "") + set(RunCMake_TEST_FAILED " not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "Unable to find executable:") + set(RunCMake_TEST_FAILED "Unable to find executable: not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "") + set(RunCMake_TEST_FAILED " not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "please skip") + set(RunCMake_TEST_FAILED "please skip not found when expected") + endif() +else() + set(RunCMake_TEST_FAILED "junit.xml not found") +endif() diff --git a/Tests/RunCMake/CTestCommandLine/output-junit-result.txt b/Tests/RunCMake/CTestCommandLine/output-junit-result.txt new file mode 100644 index 00000000000..45a4fb75db8 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/output-junit-result.txt @@ -0,0 +1 @@ +8 diff --git a/Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt b/Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt new file mode 100644 index 00000000000..ce30dc80d86 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/output-junit-stderr.txt @@ -0,0 +1 @@ +Unable to find executable: .*doesnt_exist diff --git a/Tests/RunCMake/ctest_test/OutputJUnit-check.cmake b/Tests/RunCMake/ctest_test/OutputJUnit-check.cmake new file mode 100644 index 00000000000..00310a4f869 --- /dev/null +++ b/Tests/RunCMake/ctest_test/OutputJUnit-check.cmake @@ -0,0 +1,24 @@ +file(GLOB junit_xml_file "${RunCMake_TEST_BINARY_DIR}/junit.xml") +if(junit_xml_file) + file(READ "${junit_xml_file}" junit_xml LIMIT 4096) + if(NOT "${junit_xml}" MATCHES "tests=\"1\"") + set(RunCMake_TEST_FAILED "tests=\"1\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "failures=\"0\"") + set(RunCMake_TEST_FAILED "failures=\"0\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "disabled=\"0\"") + set(RunCMake_TEST_FAILED "disabled=\"0\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "skipped=\"0\"") + set(RunCMake_TEST_FAILED "skipped=\"0\" not found when expected") + endif() + if(NOT "${junit_xml}" MATCHES "cmake version") + set(RunCMake_TEST_FAILED "cmake version not found when expected") + endif() +else() + set(RunCMake_TEST_FAILED "junit.xml not found") +endif() diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index 8cf6a61415c..901ac112361 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -146,3 +146,6 @@ set_property(TEST RunCMakeVersion PROPERTY ENVIRONMENT "ENV1=env1;ENV2=env2") run_ctest(TestEnvironment) endfunction() run_environment() + +# test for OUTPUT_JUNIT +run_ctest_test(OutputJUnit OUTPUT_JUNIT junit.xml REPEAT UNTIL_FAIL:2) diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index f2aef3ecac7..f1bdcc4cad2 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -21,6 +21,7 @@ { include: [ "", public, "", public ] }, # HACK: check whether this can be removed with next iwyu release. + { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, From 8b30e7adfb1b5ede0d7ba7103a856b8989067484 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Apr 2021 13:00:06 -0400 Subject: [PATCH 0296/1519] FindIntl: Use explicit find_library signature NAMES keyword --- Modules/FindIntl.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake index 038f4dacf1e..95eeabda83e 100644 --- a/Modules/FindIntl.cmake +++ b/Modules/FindIntl.cmake @@ -129,7 +129,9 @@ else() DOC "libintl include directory") mark_as_advanced(Intl_INCLUDE_DIR) - find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR + find_library(Intl_LIBRARY + NAMES "intl" "libintl" + NAMES_PER_DIR DOC "libintl libraries (if not in the C library)") mark_as_advanced(Intl_LIBRARY) endif() From 1ba07ff0f87101da9c7b35eee3f91a2c1cb0f86f Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Mon, 26 Apr 2021 10:27:48 -0400 Subject: [PATCH 0297/1519] KWSys 2021-04-26 (642ddfcc) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 642ddfccfea808632f8d4b3be03971903e3d359d (master). Upstream Shortlog ----------------- Rolf Eike Beer (1): 7b0f5c20 SystemInformation: improve CPU counting on non-standard architectures --- SystemInformation.cxx | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 7743eabe952..117ff8d1ecf 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -3472,6 +3472,10 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() // We want to record the total number of cores in this->NumberOfPhysicalCPU // (checking only the first proc) std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); + if (Cores.empty()) { + // Linux Sparc is different + Cores = this->ExtractValueFromCpuInfoFile(buffer, "ncpus probed"); + } auto NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str()); NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u); this->NumberOfPhysicalCPU = @@ -3490,6 +3494,9 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if (this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; } + if (this->NumberOfLogicalCPU == 0) { + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + } // LogicalProcessorsPerPhysical>1 => SMT. this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU; @@ -3503,8 +3510,18 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() else { // Linux Sparc: CPU speed is in Hz and encoded in hexadecimal CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "Cpu0ClkTck"); - this->CPUSpeedInMHz = - static_cast(strtoull(CPUSpeed.c_str(), nullptr, 16)) / 1000000.0f; + if (!CPUSpeed.empty()) { + this->CPUSpeedInMHz = + static_cast(strtoull(CPUSpeed.c_str(), nullptr, 16)) / + 1000000.0f; + } else { + // if the kernel is build as Sparc32 it's in decimal, note the different + // case + CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer, "CPU0ClkTck"); + this->CPUSpeedInMHz = + static_cast(strtoull(CPUSpeed.c_str(), nullptr, 10)) / + 1000000.0f; + } } #endif From 7fce2d372ed8ff70c8e3c3cb49ecaef977f66fe1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Apr 2021 14:14:09 -0400 Subject: [PATCH 0298/1519] VS: Revert "Add support for ASAN -fsanitize=address flag" Revert commit 1b37305b0f (VS: Add support for ASAN -fsanitize=address flag, 2021-04-21). The tag `EnableASAN` is created in `ItemDefinitionGroup` but it needs to be in `PropertyGroup`. Revert the mapping pending an implementation in the generator. Issue: #21081 --- Templates/MSBuild/FlagTables/v142_CL.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 9f079612963..7c2d291f9a1 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -1222,12 +1222,5 @@ "UserValue", "UserRequired" ] - }, - { - "name": "EnableASAN", - "switch": "fsanitize=address", - "comment": "Enable Address Sanitizer", - "value": "true", - "flags": [] } ] From c9aec3d4a97e8390756ea7004b9d2b065714b875 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 20 Apr 2021 13:52:07 -0400 Subject: [PATCH 0299/1519] FindCurses: Do not assume ncurses is installed on CYGWIN --- Modules/FindCurses.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindCurses.cmake b/Modules/FindCurses.cmake index 5e25deb68e5..bfa1d6fb443 100644 --- a/Modules/FindCurses.cmake +++ b/Modules/FindCurses.cmake @@ -76,7 +76,7 @@ endif() # cygwin ncurses stopped providing curses.h symlinks see above # message. Cygwin is an ncurses package, so force ncurses on # cygwin if the curses.h is missing -if(CYGWIN) +if(CURSES_NCURSES_LIBRARY AND CYGWIN) if (CURSES_NEED_WIDE) if(NOT EXISTS /usr/include/ncursesw/curses.h) set(CURSES_USE_NCURSES TRUE) From b3ca4f9ad18220b2f56cd6af7df5cf1e671d39a8 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 22 Apr 2021 14:06:48 -0400 Subject: [PATCH 0300/1519] cm/filesystem: Work around crash when compiled for CYGWIN/MSYS runtime Issue: #22090 --- Utilities/std/cm/filesystem | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Utilities/std/cm/filesystem b/Utilities/std/cm/filesystem index 6cbdea98a7b..ce52fbf3b3b 100644 --- a/Utilities/std/cm/filesystem +++ b/Utilities/std/cm/filesystem @@ -809,6 +809,10 @@ public: path& remove_filename() { +# if defined(__CYGWIN__) + // FIXME: Avoid crash due to CYGWIN/MSYS bug(?). See CMake Issue 22090. + static_cast(this->path_.data()); +# endif auto fname = this->get_filename(); if (!fname.empty()) { this->path_.erase(fname.data() - this->path_.data()); @@ -825,6 +829,10 @@ public: path& replace_extension(const path& replacement = path()) { +# if defined(__CYGWIN__) + // FIXME: Avoid crash due to CYGWIN/MSYS bug(?). See CMake Issue 22090. + static_cast(this->path_.data()); +# endif auto ext = this->get_filename_fragment(filename_fragment::extension); if (!ext.empty()) { this->path_.erase(ext.data() - this->path_.data()); From ddcd1469e8377fe258913a20aa47e65f71f8695b Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 1 Apr 2021 20:03:52 +0300 Subject: [PATCH 0301/1519] MSYS: Add support for running under MSYS runtime environment Detect MSYS as CYGWIN, with the required adaptations. --- Modules/CMakeDetermineSystem.cmake | 3 ++- Modules/CMakePlatformId.h.in | 3 +++ Modules/CMakeSystemSpecificInformation.cmake | 1 + Modules/FindThreads.cmake | 2 +- Modules/Platform/CYGWIN.cmake | 4 ++-- Modules/Platform/MSYS-Clang-C.cmake | 1 + Modules/Platform/MSYS-Clang-CXX.cmake | 1 + Modules/Platform/MSYS-Determine-CXX.cmake | 1 + Modules/Platform/MSYS-GNU-C.cmake | 1 + Modules/Platform/MSYS-GNU-CXX.cmake | 1 + Modules/Platform/MSYS-GNU-Fortran.cmake | 1 + Modules/Platform/MSYS-GNU.cmake | 1 + Modules/Platform/MSYS-windres.cmake | 1 + Modules/Platform/MSYS.cmake | 4 ++++ Source/CMakeLists.txt | 2 +- Source/Checks/cm_cxx_features.cmake | 4 +++- Source/Modules/FindLibUUID.cmake | 9 ++++++- Source/cmExtraEclipseCDT4Generator.cxx | 2 +- Source/cmSystemTools.cxx | 6 ++++- Tests/CMakeLists.txt | 2 +- .../CheckCXXCompilerFlag/CMakeLists.txt | 2 +- .../CMakeTests/ImplicitLinkInfoTest.cmake.in | 23 +++++++++++++++++- Tests/FindPackageTest/CMakeLists.txt | 4 +++- Tests/RunCMake/CMakeLists.txt | 21 +++++++++------- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 4 ++-- .../codemodel-v2-data/directories/top.json | 4 ++-- .../targets/c_shared_lib.json | 6 ++--- .../targets/cxx_shared_lib.json | 6 ++--- .../File_Generate/CustomFilePermissions.cmake | 1 + .../CustomFilePermissionsVerify.cmake | 2 +- .../NoSourcePermissionsVerify.cmake | 2 +- ...ARGET_FILE_BASE_NAME-imported-target.cmake | 8 +++---- .../TARGET_FILE_BASE_NAME.cmake | 8 +++---- .../TARGET_FILE_PREFIX-imported-target.cmake | 2 +- .../TARGET_FILE_PREFIX.cmake | 2 +- .../TARGET_FILE_SUFFIX-imported-target.cmake | 2 +- .../TARGET_FILE_SUFFIX.cmake | 2 +- .../exportheader_test.cpp | 24 ++++++++++++------- Tests/RunCMake/RunCMake.cmake | 5 +++- .../configure_file/NoSourcePermissions.cmake | 2 +- .../configure_file/SourcePermissions.cmake | 2 +- Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake | 2 +- Tests/RunCMake/file/RunCMakeTest.cmake | 8 +++++-- .../find_file/FromPATHEnv-stdout-msys.txt | 9 +++++++ .../find_file/PrefixInPATH-stdout-msys.txt | 4 ++++ .../find_library/FromPATHEnv-stdout-msys.txt | 6 +++++ .../find_library/PrefixInPATH-stdout-msys.txt | 4 ++++ .../RunCMake/find_package/RunCMakeTest.cmake | 4 +++- .../find_path/FromPATHEnv-stdout-msys.txt | 9 +++++++ .../find_path/PrefixInPATH-stdout-msys.txt | 4 ++++ .../RunCMake/find_program/RunCMakeTest.cmake | 2 +- .../TARGETS-Defaults-Cache-all-check.cmake | 15 ++++++++++++ .../install/TARGETS-Defaults-all-check.cmake | 17 +++++++++++++ ...TARGETS-NAMELINK_COMPONENT-all-check.cmake | 10 ++++++++ ...TARGETS-NAMELINK_COMPONENT-lib-check.cmake | 8 +++++++ ...TARGETS-NAMELINK_COMPONENT-uns-check.cmake | 6 +++++ .../TARGETS-OUTPUT_NAME-all-check.cmake | 2 ++ Tests/SetLang/CMakeLists.txt | 4 ++++ Utilities/cmlibuv/CMakeLists.txt | 2 +- bootstrap | 14 +++++++++-- 60 files changed, 246 insertions(+), 66 deletions(-) create mode 100644 Modules/Platform/MSYS-Clang-C.cmake create mode 100644 Modules/Platform/MSYS-Clang-CXX.cmake create mode 100644 Modules/Platform/MSYS-Determine-CXX.cmake create mode 100644 Modules/Platform/MSYS-GNU-C.cmake create mode 100644 Modules/Platform/MSYS-GNU-CXX.cmake create mode 100644 Modules/Platform/MSYS-GNU-Fortran.cmake create mode 100644 Modules/Platform/MSYS-GNU.cmake create mode 100644 Modules/Platform/MSYS-windres.cmake create mode 100644 Modules/Platform/MSYS.cmake create mode 100644 Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt create mode 100644 Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt create mode 100644 Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt create mode 100644 Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt create mode 100644 Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt create mode 100644 Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index c3f2b740058..8c7af067d37 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -27,6 +27,7 @@ # Tru64 Tru64 # Ultrix ULTRIX # cygwin CYGWIN_NT-5.1 +# MSYS MSYS_NT-6.1 # MacOSX Darwin @@ -43,7 +44,7 @@ if(CMAKE_HOST_UNIX) else() exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) endif() - if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|^GNU$|Android") + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|MSYS.*|^GNU$|Android") exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 2643874d194..59195f8e50d 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -5,6 +5,9 @@ #if defined(__linux) || defined(__linux__) || defined(linux) # define PLATFORM_ID "Linux" +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + #elif defined(__CYGWIN__) # define PLATFORM_ID "Cygwin" diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake index ea3a445b6e1..0ded568835e 100644 --- a/Modules/CMakeSystemSpecificInformation.cmake +++ b/Modules/CMakeSystemSpecificInformation.cmake @@ -14,6 +14,7 @@ set(APPLE ) set(UNIX ) set(CYGWIN ) +set(MSYS ) set(WIN32 ) diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index 28dffc0aad7..c6a3451f7be 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -225,7 +225,7 @@ if(CMAKE_USE_PTHREADS_INIT) set(CMAKE_THREAD_LIBS_INIT ) endif() - if(CMAKE_SYSTEM MATCHES "CYGWIN_NT") + if(CMAKE_SYSTEM MATCHES "CYGWIN_NT" OR CMAKE_SYSTEM MATCHES "MSYS_NT") set(CMAKE_USE_PTHREADS_INIT 1) set(Threads_FOUND TRUE) set(CMAKE_THREAD_LIBS_INIT ) diff --git a/Modules/Platform/CYGWIN.cmake b/Modules/Platform/CYGWIN.cmake index 9b897bd4738..fc4ea2ed53c 100644 --- a/Modules/Platform/CYGWIN.cmake +++ b/Modules/Platform/CYGWIN.cmake @@ -1,7 +1,7 @@ -if("${CMAKE_MINIMUM_REQUIRED_VERSION}" VERSION_LESS "2.8.3.20101214") +if("${CMAKE_MINIMUM_REQUIRED_VERSION}" VERSION_LESS "2.8.3.20101214" AND NOT MSYS) set(__USE_CMAKE_LEGACY_CYGWIN_WIN32 1) endif() -if(NOT DEFINED WIN32) +if(NOT DEFINED WIN32 AND NOT MSYS) set(WIN32 0) if(DEFINED __USE_CMAKE_LEGACY_CYGWIN_WIN32) if(NOT DEFINED CMAKE_LEGACY_CYGWIN_WIN32 diff --git a/Modules/Platform/MSYS-Clang-C.cmake b/Modules/Platform/MSYS-Clang-C.cmake new file mode 100644 index 00000000000..f025b33fab1 --- /dev/null +++ b/Modules/Platform/MSYS-Clang-C.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-Clang-C) diff --git a/Modules/Platform/MSYS-Clang-CXX.cmake b/Modules/Platform/MSYS-Clang-CXX.cmake new file mode 100644 index 00000000000..e509eaad951 --- /dev/null +++ b/Modules/Platform/MSYS-Clang-CXX.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-Clang-CXX) diff --git a/Modules/Platform/MSYS-Determine-CXX.cmake b/Modules/Platform/MSYS-Determine-CXX.cmake new file mode 100644 index 00000000000..dec17f03a1d --- /dev/null +++ b/Modules/Platform/MSYS-Determine-CXX.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-Determine-CXX) diff --git a/Modules/Platform/MSYS-GNU-C.cmake b/Modules/Platform/MSYS-GNU-C.cmake new file mode 100644 index 00000000000..e8343a442ff --- /dev/null +++ b/Modules/Platform/MSYS-GNU-C.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-GNU-C) diff --git a/Modules/Platform/MSYS-GNU-CXX.cmake b/Modules/Platform/MSYS-GNU-CXX.cmake new file mode 100644 index 00000000000..67775deabfc --- /dev/null +++ b/Modules/Platform/MSYS-GNU-CXX.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-GNU-CXX) diff --git a/Modules/Platform/MSYS-GNU-Fortran.cmake b/Modules/Platform/MSYS-GNU-Fortran.cmake new file mode 100644 index 00000000000..b0b7d8ed439 --- /dev/null +++ b/Modules/Platform/MSYS-GNU-Fortran.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-GNU-Fortran) diff --git a/Modules/Platform/MSYS-GNU.cmake b/Modules/Platform/MSYS-GNU.cmake new file mode 100644 index 00000000000..012c1120aea --- /dev/null +++ b/Modules/Platform/MSYS-GNU.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-GNU) diff --git a/Modules/Platform/MSYS-windres.cmake b/Modules/Platform/MSYS-windres.cmake new file mode 100644 index 00000000000..faaccc2ec77 --- /dev/null +++ b/Modules/Platform/MSYS-windres.cmake @@ -0,0 +1 @@ +include(Platform/CYGWIN-windres) diff --git a/Modules/Platform/MSYS.cmake b/Modules/Platform/MSYS.cmake new file mode 100644 index 00000000000..96fa36f580e --- /dev/null +++ b/Modules/Platform/MSYS.cmake @@ -0,0 +1,4 @@ +set(MSYS 1) +include(Platform/CYGWIN) +set(CMAKE_SHARED_LIBRARY_PREFIX "msys-") +set(CMAKE_SHARED_MODULE_PREFIX "msys-") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 938745c489f..c19c1546228 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -44,7 +44,7 @@ endif() if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) set(CMake_DEFAULT_RECURSION_LIMIT 100) - elseif(MINGW) + elseif(MINGW OR MSYS) set(CMake_DEFAULT_RECURSION_LIMIT 400) elseif(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM") set(CMake_DEFAULT_RECURSION_LIMIT 600) diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index 7917d41fafd..f20572e06c2 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -80,7 +80,9 @@ if(CMake_HAVE_CXX_MAKE_UNIQUE) set(CMake_HAVE_CXX_UNIQUE_PTR 1) endif() cm_check_cxx_feature(unique_ptr) -if (NOT CMAKE_CXX_STANDARD LESS "17") +if (NOT CMAKE_CXX_STANDARD LESS "17" + AND NOT MSYS # FIXME: RunCMake.cmake_path cases crash with MSYS std::filesystem + ) if (NOT CMAKE_CROSSCOMPILING OR CMAKE_CROSSCOMPILING_EMULATOR) cm_check_cxx_feature(filesystem TRY_RUN) else() diff --git a/Source/Modules/FindLibUUID.cmake b/Source/Modules/FindLibUUID.cmake index 17f11c1f5e1..ca5b61d1c88 100644 --- a/Source/Modules/FindLibUUID.cmake +++ b/Source/Modules/FindLibUUID.cmake @@ -40,7 +40,14 @@ They may be set by end users to point at LibUUID components. #]=======================================================================] #----------------------------------------------------------------------------- -if(CYGWIN) +if(MSYS) + # Note: on current version of MSYS2, linking to libuuid.dll.a doesn't + # import the right symbols sometimes. Fix this by linking directly + # to the DLL that provides the symbols, instead. + find_library(LibUUID_LIBRARY + NAMES msys-uuid-1.dll + ) +elseif(CYGWIN) # Note: on current version of Cygwin, linking to libuuid.dll.a doesn't # import the right symbols sometimes. Fix this by linking directly # to the DLL that provides the symbols, instead. diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index ccfd72798a0..5fbbef7ac4c 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -655,7 +655,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.EndElement(); // extension } else { std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); - if (systemName == "CYGWIN") { + if (systemName == "CYGWIN" || systemName == "MSYS") { xml.StartElement("extension"); xml.Attribute("id", "org.eclipse.cdt.core.Cygwin_PE"); xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser"); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 5382fac250a..aad55330de9 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -3239,10 +3239,14 @@ cm::string_view cmSystemTools::GetSystemName() systemName = "kFreeBSD"; } - // fix for CYGWIN which has windows version in it + // fix for CYGWIN and MSYS which have windows version in them if (systemName.find("CYGWIN") != cm::string_view::npos) { systemName = "CYGWIN"; } + + if (systemName.find("MSYS") != cm::string_view::npos) { + systemName = "MSYS"; + } return systemName; } return ""; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index d6a20bc3e99..ff9e9ec6cea 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -460,7 +460,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(OutName exe.OutName.exe) ADD_TEST_MACRO(ObjectLibrary UseCshared) ADD_TEST_MACRO(NewlineArgs NewlineArgs) - ADD_TEST_MACRO(SetLang SetLang) + ADD_TEST_MACRO(SetLang SetLangX) ADD_TEST_MACRO(EmptyProperty EmptyProperty) ADD_TEST_MACRO(ExternalOBJ ExternalOBJ) if(NOT CMake_TEST_EXTERNAL_CMAKE) diff --git a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt index 7ca68ecf44f..aca99ceff74 100644 --- a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt +++ b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt @@ -36,7 +36,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES Intel) string (REGEX REPLACE ".*Version ([0-9]+(\\.[0-9]+)+).*" "\\1" _intel_version "${_intel_version_info}") endif() -message("Platform:\n WIN32: ${WIN32}\n UNIX: ${UNIX}\n APPLE: ${APPLE}\n MINGW: ${MINGW}\n CYGWIN: ${CYGWIN}\n" +message("Platform:\n WIN32: ${WIN32}\n UNIX: ${UNIX}\n APPLE: ${APPLE}\n MINGW: ${MINGW}\n CYGWIN: ${CYGWIN}\n MSYS: ${MSYS}\n" " MSVC: ${MSVC}\n MSVC60: ${MSVC60}\n MSVC70: ${MSVC70}\n MSVC71: ${MSVC71}\n MSVC80: ${MSVC80}\n MSVC90: ${MSVC90}\n MSVC10: ${MSVC10}\n" " GCC: ${_gcc_version}\n" " Clang: ${_clang_version}\n" diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index f01e616f010..1254ff96244 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -459,7 +459,28 @@ set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/so list(APPEND platforms msys_g77) #----------------------------------------------------------------------------- -# MSYS2 +# MSYS2-runtime + +# gcc dummy.c -v +set(msys2rt_gcc_text " /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/cczg1Arh.o -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc") +set(msys2rt_gcc_libs "msys-2.0;user32;kernel32;advapi32;shell32") +set(msys2rt_gcc_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib") +list(APPEND platforms msysrt_gcc) + +# g++ dummy.cxx -v +set(msys2rt_g++_text " /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc") +set(msys2rt_g++_libs "stdc++;msys-2.0;user32;kernel32;advapi32;shell32") +set(msys2rt_g++_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib") +list(APPEND platforms msysrt_g++) + +# g77 dummy.f -v +set(msys2rt_g77_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- -u ___register_frame_info -u ___deregister_frame_info /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o /usr/lib/gcc/i686-pc-msys/6.4.0/crtbegin.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/ccqRWKWg.o -lgfortranbegin -lgfortran -lgcc_s -lgcc_s -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc_s -lgcc_s -lgcc /usr/lib/gcc/i686-pc-msys/6.4.0/crtend.o") +set(msys2rt_g77_libs "stdc++;msys-2.0;user32;kernel32;advapi32;shell32") +set(msys2rt_g77_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib") +list(APPEND platforms msysrt_g77) + +#----------------------------------------------------------------------------- +# MSYS2-mingw # gcc dummy.c -v set(msys2_gcc_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/collect2.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/lto-wrapper.exe -plugin-opt=-fresolution=C:/msys64/tmp/ccikz9Wf.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../.. C:/msys64/tmp/ccK0dTUv.o -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtend.o") diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index 7217f43b611..7ec41f35f3c 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -189,7 +189,9 @@ find_package(ArchD 4.0 EXACT NAMES zot) unset(CMAKE_LIBRARY_ARCHITECTURE) # Test find_package() with CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS enabled -if(UNIX) +if(UNIX + AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS + ) # Create ./symlink pointing back here. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink . "${CMAKE_CURRENT_SOURCE_DIR}/symlink") diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 5e16de0f6a3..db90a817320 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -165,7 +165,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja") endif() add_RunCMake_test(Ninja) set(NinjaMultiConfig_ARGS - -DCYGWIN=${CYGWIN} + -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} ) if(CMake_TEST_Qt5 AND Qt5Core_FOUND) list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION}) @@ -346,7 +346,7 @@ add_RunCMake_test(export) add_RunCMake_test(cmake_language) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(cmake_parse_arguments) -add_RunCMake_test(cmake_path) +add_RunCMake_test(cmake_path -DMSYS=${MSYS}) add_RunCMake_test(continue) add_executable(color_warning color_warning.c) add_executable(fake_build_command fake_build_command.c) @@ -367,14 +367,14 @@ add_RunCMake_test(ctest_skipped_test) add_RunCMake_test(ctest_update) add_RunCMake_test(ctest_upload) add_RunCMake_test(ctest_fixtures) -add_RunCMake_test(file) -add_RunCMake_test(file-CHMOD) +add_RunCMake_test(file -DMSYS=${MSYS}) +add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) if(HAVE_ELF_H OR CMAKE_SYSTEM_NAME STREQUAL "AIX") add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DHAVE_ELF_H=${HAVE_ELF_H}) endif() add_RunCMake_test(find_file) -add_RunCMake_test(find_library -DCYGWIN=${CYGWIN}) -add_RunCMake_test(find_package) +add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) +add_RunCMake_test(find_package -DMSYS=${MSYS}) add_RunCMake_test(find_path) add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(foreach) @@ -512,7 +512,9 @@ else() message(STATUS "Could not find ctresalloc") endif() -if(NOT WIN32) +if(NOT WIN32 + AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS + ) add_RunCMake_test(SymlinkTrees) endif () @@ -616,7 +618,8 @@ endif() add_executable(pseudo_llvm-rc pseudo_llvm-rc.c) -add_RunCMake_test(CommandLine -DLLVM_RC=$ -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}) +add_RunCMake_test(CommandLine -DLLVM_RC=$ -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}) add_RunCMake_test(CommandLineTar) if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG)) @@ -625,7 +628,7 @@ else() set(NO_NAMELINK 0) endif() -add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} +add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} -DCMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN=${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN} -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG} diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index bf5a96e54b5..78c35087137 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -562,7 +562,7 @@ file(MAKE_DIRECTORY ${out}) run_cmake_command(E_cat_non_existing_file ${CMAKE_COMMAND} -E cat ${out}/non-existing-file.txt) -if(UNIX) +if(UNIX AND NOT MSYS) # test non readable file only if not root execute_process( COMMAND id -u $ENV{USER} @@ -801,7 +801,7 @@ function(reject_fifo) run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) endif() endfunction() -if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") +if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN" AND NOT CMAKE_SYSTEM_NAME STREQUAL "MSYS") reject_fifo() run_cmake_command(closed_stdin sh -c "\"${CMAKE_COMMAND}\" --version <&-") run_cmake_command(closed_stdout sh -c "\"${CMAKE_COMMAND}\" --version >&-") diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json index ce459472414..472760703df 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json @@ -119,7 +119,7 @@ "type": "target", "destination": "lib", "paths": [ - "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg)?c_shared_lib(-1)?\\.(dll|so)$" + "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?c_shared_lib(-1)?\\.(dll|so)$" ], "pathsNamelink": [ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1\\.2\\.3|1\\.2\\.3\\.dylib)$", @@ -210,7 +210,7 @@ "type": "target", "destination": "lib", "paths": [ - "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg)?cxx_shared_lib\\.(dll|so|dylib)$" + "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(dll|so|dylib)$" ], "isExcludeFromAll": null, "isOptional": null, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json index 5588bd53d2f..e3a8d0b2dee 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json @@ -90,10 +90,10 @@ } ], "folder": null, - "nameOnDisk": "^(lib|cyg)?c_shared_lib(-1)?\\.(so|dylib|dll)$", + "nameOnDisk": "^(lib|cyg|msys-)?c_shared_lib(-1)?\\.(so|dylib|dll)$", "artifacts": [ { - "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib(-1)?\\.(so|dylib|dll)$", + "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?c_shared_lib(-1)?\\.(so|dylib|dll)$", "_dllExtra": false }, { @@ -101,7 +101,7 @@ "_dllExtra": true }, { - "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib(-1)?\\.pdb$", + "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?c_shared_lib(-1)?\\.pdb$", "_dllExtra": true } ], diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json index e5e1d0de244..73e8e127b82 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json @@ -66,10 +66,10 @@ } ], "folder": null, - "nameOnDisk": "^(lib|cyg)?cxx_shared_lib\\.(so|dylib|dll)$", + "nameOnDisk": "^(lib|cyg|msys-)?cxx_shared_lib\\.(so|dylib|dll)$", "artifacts": [ { - "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?cxx_shared_lib\\.(so|dylib|dll)$", + "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(so|dylib|dll)$", "_dllExtra": false }, { @@ -77,7 +77,7 @@ "_dllExtra": true }, { - "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?cxx_shared_lib\\.pdb$", + "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?cxx_shared_lib\\.pdb$", "_dllExtra": true } ], diff --git a/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake b/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake index 0000ef971fc..a5e66dc3a73 100644 --- a/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake +++ b/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake @@ -11,5 +11,6 @@ file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$>/custom add_custom_target(checkCustomFilePermissions ALL COMMAND ${CMAKE_COMMAND} -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$>/customfilepermissions.txt + -DMSYS=${MSYS} -P "${CMAKE_CURRENT_SOURCE_DIR}/CustomFilePermissionsVerify.cmake" ) diff --git a/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake index a87e916d50f..2ef32815f1b 100644 --- a/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake +++ b/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake @@ -2,7 +2,7 @@ if(NOT EXISTS "${generatedFile}") message(SEND_ERROR "Missing file:\n ${generatedFile}") endif() -if (UNIX) +if (UNIX AND NOT MSYS) find_program(STAT_EXECUTABLE NAMES stat) if(NOT STAT_EXECUTABLE) return() diff --git a/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake index 7981ccce1e2..5e5b16afcbe 100644 --- a/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake +++ b/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake @@ -2,7 +2,7 @@ if(NOT EXISTS "${generatedFile}") message(SEND_ERROR "Missing generated file:\n ${generatedFile}") endif() -if (UNIX) +if (UNIX AND NOT MSYS) find_program(STAT_EXECUTABLE NAMES stat) if(NOT STAT_EXECUTABLE) return() diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake index 40f7c66f2a5..7eec527c8fd 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME-imported-target.cmake @@ -58,8 +58,8 @@ set_property (TARGET static3 PROPERTY ARCHIVE_OUTPUT_NAME static3_archive) string (APPEND GENERATE_CONTENT [[ check_value ("TARGET_FILE_BASE_NAME executable all properties" "$" "exec3_runtime") -check_value ("TARGET_FILE_BASE_NAME shared all properties" "$" "$,Windows$CYGWIN>,shared3_runtime,shared3_library>") -check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$" "$,Windows$CYGWIN>,shared3_archive,shared3_library>") +check_value ("TARGET_FILE_BASE_NAME shared all properties" "$" "$,Windows$CYGWIN$MSYS>,shared3_runtime,shared3_library>") +check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$" "$,Windows$CYGWIN$MSYS>,shared3_archive,shared3_library>") check_value ("TARGET_FILE_BASE_NAME static all properties" "$" "static3_archive") check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties" "$" "static3_archive") ]]) @@ -95,8 +95,8 @@ set_property (TARGET static4 PROPERTY ${FIRST_CONFIG}_POSTFIX _postfix) string (APPEND GENERATE_CONTENT [[ check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$" "exec4_runtime_postfix") -check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$" "$,Windows$CYGWIN>,shared4_runtime,shared4_library>_postfix") -check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$" "$,Windows$CYGWIN>,shared4_archive,shared4_library>_postfix") +check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$" "$,Windows$CYGWIN$MSYS>,shared4_runtime,shared4_library>_postfix") +check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$" "$,Windows$CYGWIN$MSYS>,shared4_archive,shared4_library>_postfix") check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$" "static4_archive_postfix") check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$" "static4_archive_postfix") ]]) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake index f88d7109aea..1963244faed 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_BASE_NAME.cmake @@ -72,8 +72,8 @@ set_property (TARGET static3 PROPERTY PDB_NAME static3_pdb) string (APPEND GENERATE_CONTENT [[ check_value ("TARGET_FILE_BASE_NAME executable all properties" "$" "exec3_runtime") -check_value ("TARGET_FILE_BASE_NAME shared all properties" "$" "$,Windows$CYGWIN>,shared3_runtime,shared3_library>") -check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$" "$,Windows$CYGWIN>,shared3_archive,shared3_library>") +check_value ("TARGET_FILE_BASE_NAME shared all properties" "$" "$,Windows$CYGWIN$MSYS>,shared3_runtime,shared3_library>") +check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties" "$" "$,Windows$CYGWIN$MSYS>,shared3_archive,shared3_library>") check_value ("TARGET_FILE_BASE_NAME static all properties" "$" "static3_archive") check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties" "$" "static3_archive") ]]) @@ -118,8 +118,8 @@ set_property (TARGET static4 PROPERTY ${FIRST_CONFIG}_POSTFIX _postfix) string (APPEND GENERATE_CONTENT [[ check_value ("TARGET_FILE_BASE_NAME executable all properties + postfix" "$" "exec4_runtime_postfix") -check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$" "$,Windows$CYGWIN>,shared4_runtime,shared4_library>_postfix") -check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$" "$,Windows$CYGWIN>,shared4_archive,shared4_library>_postfix") +check_value ("TARGET_FILE_BASE_NAME shared all properties + postfix" "$" "$,Windows$CYGWIN$MSYS>,shared4_runtime,shared4_library>_postfix") +check_value ("TARGET_LINKER_FILE_BASE_NAME shared linker all properties + postfix" "$" "$,Windows$CYGWIN$MSYS>,shared4_archive,shared4_library>_postfix") check_value ("TARGET_FILE_BASE_NAME static all properties + postfix" "$" "static4_archive_postfix") check_value ("TARGET_LINKER_FILE_BASE_NAME static linker all properties + postfix" "$" "static4_archive_postfix") ]]) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake index f52776e9802..cc9cd5a8f82 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX-imported-target.cmake @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) enable_language (C) -set (win_platforms Windows CYGWIN) +set (win_platforms Windows CYGWIN MSYS) set (GENERATE_CONTENT [[ macro (CHECK_VALUE test_msg value expected) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake index bef7bbf5c41..edfb40c53b6 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_PREFIX.cmake @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) enable_language (C) -set (win_platforms Windows CYGWIN) +set (win_platforms Windows CYGWIN MSYS) set (GENERATE_CONTENT [[ macro (CHECK_VALUE test_msg value expected) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake index cefeb86f188..3ee42a5c129 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX-imported-target.cmake @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) enable_language (C) -set (win_platforms Windows CYGWIN) +set (win_platforms Windows CYGWIN MSYS) set (GENERATE_CONTENT [[ macro (CHECK_VALUE test_msg value expected) diff --git a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake index 39e39fd5b23..1fe75d95166 100644 --- a/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake +++ b/Tests/RunCMake/GenEx-TARGET_FILE/TARGET_FILE_SUFFIX.cmake @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) enable_language (C) -set (win_platforms Windows CYGWIN) +set (win_platforms Windows CYGWIN MSYS) set (GENERATE_CONTENT [[ macro (CHECK_VALUE test_msg value expected) diff --git a/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp b/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp index dcaa4f2d165..ed8c35e19d3 100644 --- a/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp +++ b/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp @@ -8,6 +8,14 @@ #include "libshared.h" #include "libstatic.h" +static void rtrim(std::string& str, char byte) +{ + const std::size_t size = str.size(); + if (size && str[size - 1] == byte) { + str.resize(size - 1); + } +} + void compare(const char* refName, const char* testName) { std::ifstream ref; @@ -31,16 +39,14 @@ void compare(const char* refName, const char* testName) // Some very old Borland runtimes (C++ Builder 5 WITHOUT Update 1) add a // trailing null to the string that we need to strip before testing for a // trailing space. - if (refLine.size() && refLine[refLine.size() - 1] == 0) { - refLine.resize(refLine.size() - 1); - } - if (testLine.size() && testLine[testLine.size() - 1] == 0) { - testLine.resize(testLine.size() - 1); - } + rtrim(refLine, 0); + rtrim(testLine, 0); // The reference files never have trailing spaces: - if (testLine.size() && testLine[testLine.size() - 1] == ' ') { - testLine.resize(testLine.size() - 1); - } + rtrim(testLine, ' '); + // Strip trailing CR. LF is not returned by getline, but CR is returned + // on some platforms. + rtrim(refLine, '\r'); + rtrim(testLine, '\r'); if (refLine != testLine) { std::cout << "Ref and test are not the same:\n Ref: \"" << refLine << "\"\n Test: \"" << testLine << "\"\n"; diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 7994fc2a9bc..b4a57b209ba 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -23,10 +23,13 @@ function(run_cmake test) endif() string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} platform_name) + #remove all additional bits from cygwin/msys name if(platform_name MATCHES cygwin) - #remove all additional bits from cygwin name set(platform_name cygwin) endif() + if(platform_name MATCHES msys) + set(platform_name msys) + endif() foreach(o out err) if(RunCMake-std${o}-file AND EXISTS ${top_src}/${RunCMake-std${o}-file}) diff --git a/Tests/RunCMake/configure_file/NoSourcePermissions.cmake b/Tests/RunCMake/configure_file/NoSourcePermissions.cmake index c6ad1311eab..85533c40c40 100644 --- a/Tests/RunCMake/configure_file/NoSourcePermissions.cmake +++ b/Tests/RunCMake/configure_file/NoSourcePermissions.cmake @@ -1,7 +1,7 @@ configure_file(NoSourcePermissions.sh NoSourcePermissions.sh.out NO_SOURCE_PERMISSIONS) -if (UNIX) +if (UNIX AND NOT MSYS) execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/NoSourcePermissions.sh.out RESULT_VARIABLE result) if (result EQUAL "0") diff --git a/Tests/RunCMake/configure_file/SourcePermissions.cmake b/Tests/RunCMake/configure_file/SourcePermissions.cmake index c4d3d6131d3..f8c506ab3b1 100644 --- a/Tests/RunCMake/configure_file/SourcePermissions.cmake +++ b/Tests/RunCMake/configure_file/SourcePermissions.cmake @@ -6,7 +6,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt WORLD_READ ) -if (CMAKE_HOST_UNIX) +if (CMAKE_HOST_UNIX AND NOT MSYS) find_program(STAT_EXECUTABLE NAMES stat) if(NOT STAT_EXECUTABLE) return() diff --git a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake index c7bff15c2f4..18deb895177 100644 --- a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake @@ -14,6 +14,6 @@ if(UNIX) OUTPUT_STRIP_TRAILING_WHITESPACE) endif() -if(NOT WIN32 AND NOT "${uid}" STREQUAL "0") +if(NOT WIN32 AND NOT MSYS AND NOT "${uid}" STREQUAL "0") run_cmake(CHMOD-write-only) endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 6d1109a10de..9efd3f49337 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -87,7 +87,9 @@ run_cmake(GLOB-noexp-RELATIVE) run_cmake_command(GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake) -if(NOT WIN32 OR CYGWIN) +if(NOT WIN32 + AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS + ) run_cmake(CREATE_LINK-SYMBOLIC) run_cmake(CREATE_LINK-SYMBOLIC-noexist) run_cmake(GLOB_RECURSE-cyclic-recursion) @@ -162,7 +164,9 @@ else() run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second ${CMAKE_COMMAND} --build .) run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-nowork ${CMAKE_COMMAND} --build .) - if(NOT WIN32 OR CYGWIN) + if(NOT WIN32 + AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS + ) message(STATUS "GLOB-CONFIGURE_DEPENDS-CMP0009-RerunCMake: link the first test directory into a new directory...") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test2") execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${RunCMake_TEST_BINARY_DIR}/test" "${RunCMake_TEST_BINARY_DIR}/test2/test_folder_symlink") diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt new file mode 100644 index 00000000000..6912bdfac7a --- /dev/null +++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout-msys.txt @@ -0,0 +1,9 @@ +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt new file mode 100644 index 00000000000..d73bc1dfdc7 --- /dev/null +++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout-msys.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt new file mode 100644 index 00000000000..01e272050a2 --- /dev/null +++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout-msys.txt @@ -0,0 +1,6 @@ +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt new file mode 100644 index 00000000000..1ab884cb78e --- /dev/null +++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout-msys.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index a899f46ad2d..72ffcce6ccd 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -40,6 +40,8 @@ run_cmake(VersionRangeConfig) run_cmake(VersionRangeConfig2) run_cmake(VersionRangeConfigStd) run_cmake(VersionRangeConfigStd2) -if(UNIX) +if(UNIX + AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS + ) run_cmake(SetFoundResolved) endif() diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt new file mode 100644 index 00000000000..8f3e7ca5f37 --- /dev/null +++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout-msys.txt @@ -0,0 +1,9 @@ +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt new file mode 100644 index 00000000000..bb2ceb725bb --- /dev/null +++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout-msys.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake index 3e239203176..77c021d185e 100644 --- a/Tests/RunCMake/find_program/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake @@ -6,7 +6,7 @@ run_cmake(NamesPerDir) run_cmake(RelAndAbsPath) run_cmake(Required) -if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN)$") +if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$") run_cmake(WindowsCom) run_cmake(WindowsExe) else() diff --git a/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake b/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake index 4a55cd6f0f5..d0994694d3c 100644 --- a/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake +++ b/Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake @@ -13,6 +13,21 @@ if(WIN32) [[mylib/(lib)?lib1\.(dll\.a|lib)]] [[mylib/(lib)?lib2\.(a|lib)]] ) +elseif(MSYS) + set(_check_files + [[lib3]] + [[lib3/liblib3\.dll\.a]] + [[lib4]] + [[lib4/msys-lib4\.dll]] + [[mybin]] + [[mybin/exe\.exe]] + [[mybin/msys-lib1\.dll]] + [[myinclude]] + [[myinclude/obj3\.h]] + [[mylib]] + [[mylib/liblib1\.dll\.a]] + [[mylib/liblib2\.a]] + ) elseif(CYGWIN) set(_check_files [[lib3]] diff --git a/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake b/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake index 30f2266d18c..6e13b84c21a 100644 --- a/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake +++ b/Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake @@ -15,6 +15,23 @@ if(WIN32) [[lib4]] [[lib4/(lib)?lib4\.dll]] ) +elseif(MSYS) + set(_check_files + [[bin]] + [[bin/exe\.exe]] + [[bin/msys-lib1\.dll]] + [[include]] + [[include/obj1\.h]] + [[include/obj2\.h]] + [[include/obj3\.h]] + [[lib]] + [[lib/liblib1\.dll\.a]] + [[lib/liblib2\.a]] + [[lib3]] + [[lib3/liblib3\.dll\.a]] + [[lib4]] + [[lib4/msys-lib4\.dll]] + ) elseif(CYGWIN) set(_check_files [[bin]] diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake index bc9ebd192f3..e602af9b73d 100644 --- a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-all-check.cmake @@ -8,6 +8,16 @@ if(WIN32) [[lib/(lib)?namelink-uns-dev\.dll]] [[lib/(lib)?namelink-uns\.dll]] ) +elseif(MSYS) + set(_check_files + [[lib]] + [[lib/msys-namelink-none\.dll]] + [[lib/msys-namelink-same-1\.dll]] + [[lib/msys-namelink-sep-1\.dll]] + [[lib/msys-namelink-skip-1\.dll]] + [[lib/msys-namelink-uns-1\.dll]] + [[lib/msys-namelink-uns-dev-1\.dll]] + ) elseif(CYGWIN) set(_check_files [[lib]] diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake index 3f6be686c79..cd579eb5642 100644 --- a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-lib-check.cmake @@ -6,6 +6,14 @@ if(WIN32) [[lib/(lib)?namelink-sep\.dll]] [[lib/(lib)?namelink-skip\.dll]] ) +elseif(MSYS) + set(_check_files + [[lib]] + [[lib/msys-namelink-none\.dll]] + [[lib/msys-namelink-same-1\.dll]] + [[lib/msys-namelink-sep-1\.dll]] + [[lib/msys-namelink-skip-1\.dll]] + ) elseif(CYGWIN) set(_check_files [[lib]] diff --git a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake index 0033c88e473..ea68f4abc86 100644 --- a/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake +++ b/Tests/RunCMake/install/TARGETS-NAMELINK_COMPONENT-uns-check.cmake @@ -4,6 +4,12 @@ if(WIN32) [[lib/(lib)?namelink-uns-dev\.dll]] [[lib/(lib)?namelink-uns\.dll]] ) +elseif(MSYS) + set(_check_files + [[lib]] + [[lib/msys-namelink-uns-1\.dll]] + [[lib/msys-namelink-uns-dev-1\.dll]] + ) elseif(CYGWIN) set(_check_files [[lib]] diff --git a/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake b/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake index 5daecc815d0..91d5ef09259 100644 --- a/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake +++ b/Tests/RunCMake/install/TARGETS-OUTPUT_NAME-all-check.cmake @@ -4,6 +4,8 @@ if(WIN32) set(test45 [[bin/test4\.dll;bin/test4\.lib;bin/test5ar\.lib]]) check_installed("^bin;(${libtest45};${test123})|(${test123};${test45})\$") +elseif(MSYS) + check_installed([[^bin;bin/libtest4\.dll\.a;bin/libtest5ar\.a;bin/msys-test4\.dll;bin/test1out\.exe;bin/test2deb\.exe;bin/test3exc\.exe$]]) elseif(CYGWIN) check_installed([[^bin;bin/cygtest4\.dll;bin/libtest4\.dll\.a;bin/libtest5ar\.a;bin/test1out\.exe;bin/test2deb\.exe;bin/test3exc\.exe$]]) elseif(APPLE) diff --git a/Tests/SetLang/CMakeLists.txt b/Tests/SetLang/CMakeLists.txt index 3eb918542dd..80348ab9241 100644 --- a/Tests/SetLang/CMakeLists.txt +++ b/Tests/SetLang/CMakeLists.txt @@ -9,6 +9,10 @@ set_source_files_properties(foo.c bar.c PROPERTIES LANGUAGE CXX) target_link_libraries(SetLang foo) set_target_properties(SetLang PROPERTIES LINKER_LANGUAGE CXX) +# Windows defender blocks SetLang executable (https://cygwin.com/pipermail/cygwin/2021-January/247508.html) +# Coordinate this name with 'Tests/CMakeLists.txt'. +set_target_properties(SetLang PROPERTIES OUTPUT_NAME "SetLangX") + # VS generators historically tolerated target-wide -TP flags added # by project code, so cover that case to preserve the behavior. if(CMAKE_GENERATOR MATCHES "^Visual Studio" AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC") diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index a4f014865c5..086345c8b94 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -156,7 +156,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS400") ) endif() -if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") +if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS") list(APPEND uv_libraries ) list(APPEND uv_headers diff --git a/bootstrap b/bootstrap index 2a81ef2c073..aefd210e7ca 100755 --- a/bootstrap +++ b/bootstrap @@ -97,8 +97,17 @@ else cmake_system_cygwin=false fi +# Determine whether this is a MSYS environment. +if echo "${cmake_system}" | grep MSYS >/dev/null 2>&1; then + cmake_system_msys=true + cmake_doc_dir_keyword="MSYS" + cmake_man_dir_keyword="MSYS" +else + cmake_system_msys=false +fi + # Determine whether this is a MinGW environment. -if echo "${cmake_system}" | grep 'MINGW\|MSYS' >/dev/null 2>&1; then +if echo "${cmake_system}" | grep 'MINGW' >/dev/null 2>&1; then cmake_system_mingw=true else cmake_system_mingw=false @@ -1071,7 +1080,7 @@ else fi # Add Cygwin-specific flags -if ${cmake_system_cygwin}; then +if ${cmake_system_cygwin} || ${cmake_system_msys}; then cmake_ld_flags="${LDFLAGS} -Wl,--enable-auto-import" fi @@ -1096,6 +1105,7 @@ cmake_toolchains='' case "${cmake_system}" in *AIX*) cmake_toolchains='XL GNU' ;; *CYGWIN*) cmake_toolchains='GNU' ;; + *MSYS*) cmake_toolchains='GNU' ;; *Darwin*) cmake_toolchains='Clang GNU' ;; *Linux*) cmake_toolchains='GNU Clang XL PGI PathScale' ;; *MINGW*) cmake_toolchains='GNU' ;; From 231df230d5894649dc7e85d0204226e9e87973c2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 21 Apr 2021 12:59:40 -0400 Subject: [PATCH 0302/1519] Help: Add release note for MSYS runtime support --- Help/release/dev/msys.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Help/release/dev/msys.rst diff --git a/Help/release/dev/msys.rst b/Help/release/dev/msys.rst new file mode 100644 index 00000000000..ece5de74fc3 --- /dev/null +++ b/Help/release/dev/msys.rst @@ -0,0 +1,4 @@ +msys +---- + +* CMake now supports the MSYS runtime environment, much like CYGWIN. From 404025b00cc3f913c5e8f04412cd6a5a26ebdfb7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Apr 2021 13:00:37 -0400 Subject: [PATCH 0303/1519] FindIconv: Avoid explicitly finding C runtime library If `iconv` functionality is built into the C runtime library, we do not need to link any libraries. Do not find `libc`. Fixes: #22114 --- Modules/FindIconv.cmake | 50 ++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/Modules/FindIconv.cmake b/Modules/FindIconv.cmake index 5ec12b2c7a6..566330f40db 100644 --- a/Modules/FindIconv.cmake +++ b/Modules/FindIconv.cmake @@ -122,26 +122,28 @@ if(NOT DEFINED Iconv_IS_BUILT_IN) endif() endif() -if(NOT Iconv_IS_BUILT_IN) +set(_Iconv_REQUIRED_VARS) +if(Iconv_IS_BUILT_IN) + set(_Iconv_REQUIRED_VARS _Iconv_IS_BUILT_IN_MSG) + set(_Iconv_IS_BUILT_IN_MSG "built in to C library") +else() + set(_Iconv_REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR) + find_path(Iconv_INCLUDE_DIR NAMES "iconv.h" DOC "iconv include directory") set(Iconv_LIBRARY_NAMES "iconv" "libiconv") -else() - set(Iconv_INCLUDE_DIR "" CACHE FILEPATH "iconv include directory") - set(Iconv_LIBRARY_NAMES "c") -endif() - -find_library(Iconv_LIBRARY - NAMES ${Iconv_LIBRARY_NAMES} - NAMES_PER_DIR - DOC "iconv library (potentially the C library)") + mark_as_advanced(Iconv_INCLUDE_DIR) -mark_as_advanced(Iconv_INCLUDE_DIR) -mark_as_advanced(Iconv_LIBRARY) + find_library(Iconv_LIBRARY + NAMES iconv libiconv + NAMES_PER_DIR + DOC "iconv library (if not in the C library)") + mark_as_advanced(Iconv_LIBRARY) +endif() # NOTE: glibc's iconv.h does not define _LIBICONV_VERSION -if(Iconv_INCLUDE_DIR AND NOT Iconv_IS_BUILT_IN) +if(Iconv_INCLUDE_DIR AND EXISTS "${Iconv_INCLUDE_DIR}/iconv.h") file(STRINGS ${Iconv_INCLUDE_DIR}/iconv.h Iconv_VERSION_DEFINE REGEX "_LIBICONV_VERSION (.*)") if(Iconv_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)") @@ -160,19 +162,21 @@ if(Iconv_INCLUDE_DIR AND NOT Iconv_IS_BUILT_IN) endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -if(NOT Iconv_IS_BUILT_IN) - find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR - VERSION_VAR Iconv_VERSION) -else() - find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY) -endif() +find_package_handle_standard_args(Iconv + REQUIRED_VARS ${_Iconv_REQUIRED_VARS} + VERSION_VAR Iconv_VERSION) if(Iconv_FOUND) - set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}") - set(Iconv_LIBRARIES "${Iconv_LIBRARY}") + if(Iconv_IS_BUILT_IN) + set(Iconv_INCLUDE_DIRS "") + set(Iconv_LIBRARIES "") + else() + set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}") + set(Iconv_LIBRARIES "${Iconv_LIBRARY}") + endif() if(NOT TARGET Iconv::Iconv) add_library(Iconv::Iconv INTERFACE IMPORTED) + set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}") + set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}") endif() - set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}") - set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}") endif() From 0eb42defc222372b660983ac46ea1266543af7e0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 27 Apr 2021 00:01:07 -0400 Subject: [PATCH 0304/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e7ac9a49ba5..ee4e69dd8bb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210426) +set(CMake_VERSION_PATCH 20210427) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 306db0fdb80ad59127372bad51f44b86e43d3120 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 27 Apr 2021 09:09:30 -0400 Subject: [PATCH 0305/1519] cmake-presets: Remove incorrect documentation for `installDir` --- Help/manual/presets/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index e0663626977..a69d2706951 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -89,7 +89,7 @@ }, "installDir": { "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)." + "description": "An optional string representing the path to the installation directory. This field supports macro expansion. If a relative path is specified, it is calculated relative to the source directory." }, "condition": { "$ref": "#/definitions/topCondition" } } From 0078db3888e01343d26c1f695b250663bbcb7ac2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 27 Apr 2021 13:56:32 -0400 Subject: [PATCH 0306/1519] ARMClang: Separate cpu/arch flags from preceding flags Suggested-by: Kim Kryger --- Modules/Compiler/ARMClang.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake index da7a43c90ad..66b7c2ed3e5 100644 --- a/Modules/Compiler/ARMClang.cmake +++ b/Modules/Compiler/ARMClang.cmake @@ -89,12 +89,12 @@ macro(__compiler_armclang lang) else() __armclang_check_processor("${CMAKE_SYSTEM_ARCH}" "${CMAKE_${lang}_COMPILER_ARCH_LIST}" _CMAKE_${lang}_CHECK_ARCH_RESULT) if( _CMAKE_${lang}_CHECK_ARCH_RESULT) - string(APPEND CMAKE_${lang}_FLAGS_INIT "-march=${CMAKE_SYSTEM_ARCH}") + string(APPEND CMAKE_${lang}_FLAGS_INIT " -march=${CMAKE_SYSTEM_ARCH}") set(__march_flag_set TRUE) endif() __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_PROCESSOR_RESULT) if(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT) - string(APPEND CMAKE_${lang}_FLAGS_INIT "-mcpu=${CMAKE_SYSTEM_PROCESSOR}") + string(APPEND CMAKE_${lang}_FLAGS_INIT " -mcpu=${CMAKE_SYSTEM_PROCESSOR}") set(__mcpu_flag_set TRUE) endif() if(NOT __march_flag_set AND NOT __mcpu_flag_set) @@ -111,7 +111,7 @@ macro(__compiler_armclang lang) list(TRANSFORM CMAKE_LINKER_CPU_LIST TOLOWER) __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_LINKER_CPU_LIST}" _CMAKE_CHECK_LINK_CPU_RESULT) if(_CMAKE_CHECK_LINK_CPU_RESULT) - string(APPEND CMAKE_${lang}_LINK_FLAGS "--cpu=${CMAKE_SYSTEM_PROCESSOR}") + string(APPEND CMAKE_${lang}_LINK_FLAGS " --cpu=${CMAKE_SYSTEM_PROCESSOR}") endif() if(__CMAKE_ARMClang_USING_armlink) From c4941b7e66cd3a0a9de5ed8189ef025fcd6f3122 Mon Sep 17 00:00:00 2001 From: Lingkai Dong Date: Wed, 21 Apr 2021 17:07:22 +0100 Subject: [PATCH 0307/1519] ARMClang: Do not automatically add cpu/arch compile or link options The compile options `--march=` and `--mcpu=` and the link option `--cpu=` are automatically added by CMake based on `CMAKE_SYSTEM_PROCESSOR` or `CMAKE_SYSTEM_ARCH`. But this is not sufficient, because armclang also supports enabling or disabling features using `+`: -mcpu=[+[no]+...] For example: -mcpu=cortex-a57+nocrypto+nofp+nosimd+crc (Reference: https://developer.arm.com/documentation/dui0774/k/Compiler-Command-line-Options/-mcpu?lang=en) The problem is, even if a project adds a flag with features it needs, CMake still adds flags, resulting in code that is compiled with wrong CPU features and unable to run. Add policy `CMP0123` to not automatically add compile or link options, and let projects set them instead. Co-Author: Brad King Fixes: #21173 --- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0123.rst | 32 +++++++++ Help/release/dev/ARMClang-cpu-arch-flags.rst | 7 ++ Modules/Compiler/ARMClang.cmake | 72 +++++++++++++------- Source/cmCoreTryCompile.cxx | 9 +++ Source/cmPolicies.h | 5 +- 6 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 Help/policy/CMP0123.rst create mode 100644 Help/release/dev/ARMClang-cpu-arch-flags.rst diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 5dfa89492fd..b41ce59fd15 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.21 .. toctree:: :maxdepth: 1 + CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. CMP0122: UseSWIG use standard library name conventions for csharp language. CMP0121: The list command detects invalid indicies. diff --git a/Help/policy/CMP0123.rst b/Help/policy/CMP0123.rst new file mode 100644 index 00000000000..e09b5ec9788 --- /dev/null +++ b/Help/policy/CMP0123.rst @@ -0,0 +1,32 @@ +CMP0123 +------- + +.. versionadded:: 3.21 + +``ARMClang`` cpu/arch compile and link flags must be set explicitly. + +CMake 3.20 and lower automatically maps the :variable:`CMAKE_SYSTEM_PROCESSOR` +variable and an undocumented ``CMAKE_SYSTEM_ARCH`` to compile and link options +for ``ARMClang``. For example, the ``-mcpu=cortex-m33`` flag is added when +:variable:`CMAKE_SYSTEM_PROCESSOR` equals ``cortex-m33``. CMake requires +projects to set either variable or it raises a fatal error. However, the +project may need to additionally specify CPU features using e.g. +``-mcpu=cortex-m33+nodsp``, conflicting with the ``-mcpu=cortex-m33`` added +by CMake. This results in either link errors or unusable binaries. + +CMake 3.21 and above prefer instead to not add any cpu/arch compile and link +flags automatically. Instead, projects must specify them explicitly. +This policy provides compatibility for projects that have not been updated. + +The ``OLD`` behavior of this policy requires projects that use ``ARMClang`` +to set either :variable:`CMAKE_SYSTEM_PROCESSOR` or ``CMAKE_SYSTEM_ARCH`` +and it automatically adds a compile option ``-mcpu=`` or ``-march=`` and +a link option ``--cpu=`` based on those variables. The ``NEW`` behavior +does not add compile or link options, and projects are responsible for +setting correct options. + +This policy was introduced in CMake version 3.21. CMake version |release| +warns when the policy is not set and uses ``OLD`` behavior. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/ARMClang-cpu-arch-flags.rst b/Help/release/dev/ARMClang-cpu-arch-flags.rst new file mode 100644 index 00000000000..5e885fe4ff0 --- /dev/null +++ b/Help/release/dev/ARMClang-cpu-arch-flags.rst @@ -0,0 +1,7 @@ +ARMClang-cpu-arch-flags +----------------------- + +* ``ARMClang`` cpu/arch compile and link flags are no longer added + automatically based on the :variable:`CMAKE_SYSTEM_PROCESSOR` + variable or the undocumented ``CMAKE_SYSTEM_ARCH`` variable. + They must be specified explicitly. See policy :policy:`CMP0123`. diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake index 66b7c2ed3e5..354c11ddbf2 100644 --- a/Modules/Compiler/ARMClang.cmake +++ b/Modules/Compiler/ARMClang.cmake @@ -3,6 +3,9 @@ if(_ARMClang_CMAKE_LOADED) endif() set(_ARMClang_CMAKE_LOADED TRUE) +# Save the CMP0123 setting in a variable used both below and by try_compile. +cmake_policy(GET CMP0123 CMAKE_ARMClang_CMP0123) + cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST @@ -82,36 +85,53 @@ macro(__compiler_armclang lang) if(NOT CMAKE_${lang}_COMPILER_ARCH_LIST) __armclang_set_arch_list(${lang} CMAKE_${lang}_COMPILER_ARCH_LIST) endif() - if(NOT CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_ARCH) - message(FATAL_ERROR " CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n" - " Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n" - " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}") - else() - __armclang_check_processor("${CMAKE_SYSTEM_ARCH}" "${CMAKE_${lang}_COMPILER_ARCH_LIST}" _CMAKE_${lang}_CHECK_ARCH_RESULT) - if( _CMAKE_${lang}_CHECK_ARCH_RESULT) - string(APPEND CMAKE_${lang}_FLAGS_INIT " -march=${CMAKE_SYSTEM_ARCH}") - set(__march_flag_set TRUE) + + # CMAKE_SYSTEM_PROCESSOR and CMAKE_SYSTEM_ARCH are not sufficient because they provide no + # information of additional CPU features needed in `-mcpu=[+[no]+...]`. + # The automatic setting of compile and link options is deprecated and projects should specify their own. + cmake_policy(GET CMP0123 policy_CMP0123) + if(NOT "x${CMAKE_ARMClang_CMP0123}x" STREQUAL "xNEWx") + if(NOT "x${CMAKE_ARMClang_CMP0123}x" STREQUAL "xOLDx") + cmake_policy(GET_WARNING CMP0123 _cmp0123_warning) + message(AUTHOR_WARNING + "${_cmp0123_warning}\n" + "For compatibility, CMake will automatically add cpu/arch flags based " + "on the CMAKE_SYSTEM_PROCESSOR and/or CMAKE_SYSTEM_ARCH variables." + ) endif() - __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_PROCESSOR_RESULT) - if(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT) - string(APPEND CMAKE_${lang}_FLAGS_INIT " -mcpu=${CMAKE_SYSTEM_PROCESSOR}") - set(__mcpu_flag_set TRUE) + + if(NOT CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_ARCH) + message(FATAL_ERROR " CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n" + " Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n" + " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}") + else() + __armclang_check_processor("${CMAKE_SYSTEM_ARCH}" "${CMAKE_${lang}_COMPILER_ARCH_LIST}" _CMAKE_${lang}_CHECK_ARCH_RESULT) + if( _CMAKE_${lang}_CHECK_ARCH_RESULT) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -march=${CMAKE_SYSTEM_ARCH}") + set(__march_flag_set TRUE) + endif() + __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}" _CMAKE_${lang}_CHECK_PROCESSOR_RESULT) + if(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -mcpu=${CMAKE_SYSTEM_PROCESSOR}") + set(__mcpu_flag_set TRUE) + endif() + if(NOT __march_flag_set AND NOT __mcpu_flag_set) + message(FATAL_ERROR "At least one of the variables CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n" + "Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n" + " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}") + endif() + unset(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT) + unset(_CMAKE_${lang}_CHECK_ARCH_RESULT) endif() - if(NOT __march_flag_set AND NOT __mcpu_flag_set) - message(FATAL_ERROR "At least one of the variables CMAKE_SYSTEM_PROCESSOR or CMAKE_SYSTEM_ARCH must be set for ARMClang\n" - "Supported processor: ${CMAKE_${lang}_COMPILER_PROCESSOR_LIST}\n" - " Supported Architecture: ${CMAKE_${lang}_COMPILER_ARCH_LIST}") + + #check if CMAKE_SYSTEM_PROCESSOR belongs to supported cpu list for armlink + __armlink_set_cpu_list( ${lang} CMAKE_LINKER_CPU_LIST) + list(TRANSFORM CMAKE_LINKER_CPU_LIST TOLOWER) + __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_LINKER_CPU_LIST}" _CMAKE_CHECK_LINK_CPU_RESULT) + if(_CMAKE_CHECK_LINK_CPU_RESULT) + string(APPEND CMAKE_${lang}_LINK_FLAGS " --cpu=${CMAKE_SYSTEM_PROCESSOR}") endif() - unset(_CMAKE_${lang}_CHECK_PROCESSOR_RESULT) - unset(_CMAKE_${lang}_CHECK_ARCH_RESULT) - endif() - #check if CMAKE_SYSTEM_PROCESSOR belongs to supported cpu list for armlink - __armlink_set_cpu_list( ${lang} CMAKE_LINKER_CPU_LIST) - list(TRANSFORM CMAKE_LINKER_CPU_LIST TOLOWER) - __armclang_check_processor("${CMAKE_SYSTEM_PROCESSOR}" "${CMAKE_LINKER_CPU_LIST}" _CMAKE_CHECK_LINK_CPU_RESULT) - if(_CMAKE_CHECK_LINK_CPU_RESULT) - string(APPEND CMAKE_${lang}_LINK_FLAGS " --cpu=${CMAKE_SYSTEM_PROCESSOR}") endif() if(__CMAKE_ARMClang_USING_armlink) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index cb84d1d9f45..5399fd0f415 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -8,6 +8,7 @@ #include #include +#include #include #include "cmsys/Directory.hxx" @@ -217,6 +218,7 @@ std::string const kCMAKE_POSITION_INDEPENDENT_CODE = std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE"; std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK"; +std::string const kCMAKE_ARMClang_CMP0123 = "CMAKE_ARMClang_CMP0123"; std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES"; std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = @@ -552,6 +554,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, fprintf(fout, "cmake_policy(SET CMP0104 OLD)\n"); } + /* Set ARMClang cpu/arch policy to match outer project. */ + if (cmProp cmp0123 = + this->Makefile->GetDefinition(kCMAKE_ARMClang_CMP0123)) { + fprintf(fout, "cmake_policy(SET CMP0123 %s)\n", + *cmp0123 == "NEW"_s ? "NEW" : "OLD"); + } + std::string projectLangs; for (std::string const& li : testLangs) { projectLangs += " " + li; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index d546b6e937a..0a5bb4b1000 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -366,7 +366,10 @@ class cmMakefile; SELECT( \ POLICY, CMP0122, \ "UseSWIG use standard library name conventions for csharp language.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0123, \ + "ARMClang cpu/arch compile and link flags must be set explicitly.", \ + 3, 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ From 52eac4573d8e10c124aa92e8f12866c16e556d5b Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Wed, 21 Apr 2021 14:04:51 -0400 Subject: [PATCH 0308/1519] Help: Fix link to cdash.org from CTest manual --- Help/manual/ctest.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 3d80cece288..e35e162d8be 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -1671,4 +1671,4 @@ See Also .. include:: LINKS.txt -.. _`CDash`: http://cdash.org/ +_`CDash`: https://cdash.org From 79f48da5c23dd8335cc36f3f7d7b3b7d36c82dd2 Mon Sep 17 00:00:00 2001 From: Markus Israelsson Date: Mon, 26 Apr 2021 16:21:12 +0200 Subject: [PATCH 0309/1519] CPack/NSIS: Fix CPACK_NSIS_UNINSTALL_NAME when not Uninstall.exe If a previous installation was detected by the NSIS script the uninstaller was not correctly run unless it was still named `Uninstall.exe`. This meant that using `CPACK_NSIS_UNINSTALL_NAME` was simply broken. Fixes: #22103 --- Modules/Internal/CPack/NSIS.template.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index e6439ad7e00..0a9c4877da4 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -919,8 +919,8 @@ Function .onInit ;Run the uninstaller uninst: ClearErrors - StrLen $2 "\Uninstall.exe" - StrCpy $3 $0 -$2 # remove "\Uninstall.exe" from UninstallString to get path + StrLen $2 "\@CPACK_NSIS_UNINSTALL_NAME@.exe" + StrCpy $3 $0 -$2 # remove "\@CPACK_NSIS_UNINSTALL_NAME@.exe" from UninstallString to get path ExecWait '"$0" /S _?=$3' ;Do not copy the uninstaller to a temp file IfErrors uninst_failed inst From 63b5ddcce2acff2a6496e6bed737cf6e2788bfce Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Wed, 21 Apr 2021 14:05:00 -0400 Subject: [PATCH 0310/1519] Tests: Add cases for CTest extra measurements from tests --- Tests/RunCMake/CMakeLists.txt | 4 +++- Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 16 ++++++++++++++++ .../ctest_test/TestMeasurements-check.cmake | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/ctest_test/TestMeasurements-check.cmake diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index db90a817320..9bc41316cec 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -361,7 +361,9 @@ if(COVERAGE_COMMAND) endif() add_RunCMake_test(ctest_start) add_RunCMake_test(ctest_submit) -add_RunCMake_test(ctest_test) +add_RunCMake_test(ctest_test + -DIMAGE_DIR=${CMAKE_SOURCE_DIR}/Utilities/Sphinx/static +) add_RunCMake_test(ctest_disabled_test) add_RunCMake_test(ctest_skipped_test) add_RunCMake_test(ctest_update) diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index 901ac112361..b559e899f13 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -149,3 +149,19 @@ run_environment() # test for OUTPUT_JUNIT run_ctest_test(OutputJUnit OUTPUT_JUNIT junit.xml REPEAT UNTIL_FAIL:2) + +# Verify that extra measurements get reported. +function(run_measurements) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test( + NAME double_measurement + COMMAND ${CMAKE_COMMAND} -E + echo 1.4847) +add_test( + NAME img_measurement + COMMAND ${CMAKE_COMMAND} -E + echo ]] ${IMAGE_DIR}/cmake-logo-16.png [[) + ]]) + run_ctest(TestMeasurements) +endfunction() +run_measurements() diff --git a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake new file mode 100644 index 00000000000..9ff9447009a --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake @@ -0,0 +1,17 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/TAG" _tag) +string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}") +file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents) + +# Check double measurement. +if(NOT _test_contents MATCHES [[NamedMeasurement type="numeric/double" name="my_custom_value"]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected tag for type='numeric/double' in Test.xml") +endif() +if(NOT _test_contents MATCHES "1.4847") + string(APPEND RunCMake_TEST_FAILED "Could not find expected measurement value in Test.xml") +endif() +# Check img measurement. +if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage" type="image/png" encoding="base64"]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected tag for type='image/png' in Test.xml") +endif() From 3db61cf9851ae7df1685ec2c8525f5d45bc52d82 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 27 Apr 2021 14:36:01 -0400 Subject: [PATCH 0311/1519] VS: Fix VCTargetsPath detection when cross-compiling Tell `MSBuild` to use the same `Platform` that we generate into the `VCTargetsPath` detection project. Fixes: #22068 --- Source/cmGlobalVisualStudio10Generator.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 93fbe37d6bc..6c52ce0bc8b 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1036,6 +1036,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) cmd.push_back(this->GetMSBuildCommand()); cmd.push_back(vcxproj); cmd.push_back("/p:Configuration=Debug"); + cmd.push_back(cmStrCat("/p:Platform=", this->GetPlatformName())); cmd.push_back(std::string("/p:VisualStudioVersion=") + this->GetIDEVersion()); std::string out; From b60789a758ddd755be635ae60b24364ecf7fdd34 Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Wed, 21 Apr 2021 14:05:11 -0400 Subject: [PATCH 0312/1519] Help: Document CTest custom test measurements --- Help/command/ctest_test.rst | 80 +++++++++++++++++++++++++++++++++++++ Help/manual/ctest.1.rst | 2 + 2 files changed, 82 insertions(+) diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 9081b3f4b17..c61d01e5d16 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -170,3 +170,83 @@ The options are: See also the :variable:`CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE` and :variable:`CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE` variables. + +.. _`Additional Test Measurements`: + +Additional Test Measurements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +CTest can parse the output of your tests for extra measurements to report +to CDash. + +When run as a :ref:`Dashboard Client`, CTest will include these custom +measurements in the ``Test.xml`` file that gets uploaded to CDash. + +Check the `CDash test measurement documentation +`_ +for more information on the types of test measurements that CDash recognizes. + +The following example demonstrates how to output a variety of custom test +measurements. + +.. code-block:: c++ + + std::cout << + "28.3" + << std::endl; + + std::cout << + "red" + << std::endl; + + std::cout << + "https://cmake.org" + << std::endl; + + std::cout << + "" << + "line 1.\n" << + " \033[31;1m line 2. Bold red, and indented!\033[0;0ml\n" << + "line 3. Not bold or indented...\n" << + "" << std::endl; + +Image Measurements +"""""""""""""""""" + +The following example demonstrates how to upload test images to CDash. + +.. code-block:: c++ + + std::cout << + "" << + "/dir/to/test_img.jpg" << std::endl; + + std::cout << + "" << + "/dir/to/valid_img.gif" << std::endl; + + std::cout << + " << + "/dir/to/img.png" + << std::endl; + +Images will be displayed together in an interactive comparison mode on CDash +if they are provided with two or more of the following names. + +* ``TestImage`` +* ``ValidImage`` +* ``BaselineImage`` +* ``DifferenceImage2`` + +By convention, ``TestImage`` is the image generated by your test, and +``ValidImage`` (or ``BaselineImage``) is basis of comparison used to determine +if the test passed or failed. + +If another image name is used it will be displayed by CDash as a static image +separate from the interactive comparison UI. + +Attached Files +"""""""""""""" + +To associate other types of files with a test, use the +:prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index e35e162d8be..811997c5548 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -1095,6 +1095,8 @@ Configuration settings include: * `CTest Script`_ variable: :variable:`CTEST_TEST_TIMEOUT` * :module:`CTest` module variable: ``DART_TESTING_TIMEOUT`` +To report extra test values to CDash, see :ref:`Additional Test Measurements`. + .. _`CTest Coverage Step`: CTest Coverage Step From 9f2c3928cdf7e2b34423b655fc719a72c895f729 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Wed, 28 Apr 2021 09:26:31 +1000 Subject: [PATCH 0313/1519] Help: Convert CMAKE_LINK_DEPENDS_NO_SHARED to cross-reference link --- Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst b/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst index 5c6778d2454..dc2dc9e320e 100644 --- a/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst +++ b/Help/prop_tgt/LINK_DEPENDS_NO_SHARED.rst @@ -10,5 +10,6 @@ to re-link this target. Logical target-level dependencies will not be affected so the linked shared libraries will still be brought up to date before this target is built. -This property is initialized by the value of the variable -CMAKE_LINK_DEPENDS_NO_SHARED if it is set when a target is created. +This property is initialized by the value of the +:variable:`CMAKE_LINK_DEPENDS_NO_SHARED` variable if it is set when a +target is created. From 857373c53c6f45401a89d910634c4a21958bd7d9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 28 Apr 2021 00:01:11 -0400 Subject: [PATCH 0314/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ee4e69dd8bb..96f70b9cb62 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210427) +set(CMake_VERSION_PATCH 20210428) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a3aa5596a11b67c0de860b9cb366038c3da2a4e2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 27 Apr 2021 14:13:57 -0400 Subject: [PATCH 0315/1519] Tests: Isolate TestDriver build directories --- Tests/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index d6a20bc3e99..cd1b465370d 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1742,33 +1742,35 @@ if(BUILD_TESTING) add_test(testdriver1 ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/TestDriver" - "${CMake_BINARY_DIR}/Tests/TestDriver" + "${CMake_BINARY_DIR}/Tests/TestDriver1" ${build_generator_args} --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" --build-project TestDriverTest --test-command TestDriverTest test1 ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver1") add_test(testdriver2 ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/TestDriver" - "${CMake_BINARY_DIR}/Tests/TestDriver" + "${CMake_BINARY_DIR}/Tests/TestDriver2" ${build_generator_args} --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" --build-project TestDriverTest --test-command TestDriverTest test2 ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver2") add_test(testdriver3 ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/TestDriver" - "${CMake_BINARY_DIR}/Tests/TestDriver" + "${CMake_BINARY_DIR}/Tests/TestDriver3" ${build_generator_args} --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" --build-project TestDriverTest --test-command TestDriverTest subdir/test3 ) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver") + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver3") add_test(Dependency ${CMAKE_CTEST_COMMAND} --build-and-test From 3f6ff4b5dba01f2f58dca75546ebefd0830110a5 Mon Sep 17 00:00:00 2001 From: Sergey Bronnikov Date: Tue, 27 Apr 2021 11:01:21 +0300 Subject: [PATCH 0316/1519] create_test_sourcelist: add test driver option to run all tests New option `-A` passed to test binary allows to run all testcases at once and prints a report in a standard format - TestAnythingProtocol v.13 [1]. Execution of test whose names will be passed after an option will be skipped. Sample of output: TAP version 13 1..6 ok 1 TestCryptoHash # 0.030000 ok 2 TestCryptoRand # 0.008000 not ok 3 TestCryptoCipher # 0.005000 ok 4 TestCryptoProtectData # 0.000000 cbPlainText: 21 cbCipherText: 32 PlainText: MySecretPassword123! (cbPlainText = 21, cbCipherText = 32) Decrypted CipherText: MySecretPassword123! ok 5 TestCryptoProtectMemory # 0.014000 ok 6 TestCryptoCertEnumCertificatesInStore # 0.000000 1. https://testanything.org/ Fixes: #19367 --- Templates/TestDriver.cxx.in | 43 ++++++++++++++++++++++++++++++++++++- Tests/CMakeLists.txt | 26 ++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index 3e47d6a0d2a..e3efa794d15 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -2,6 +2,7 @@ #include /* NOLINT */ #include /* NOLINT */ #include /* NOLINT */ +#include #if defined(_MSC_VER) #pragma warning(disable : 4996) /* deprecation */ @@ -62,11 +63,23 @@ static char* lowercase(const char* string) return new_string; } +int isTestSkipped(const char *name, int n_skipped_tests, char *skipped_tests[]) { + int i; + for (i = 0; i < n_skipped_tests; i++) { + if (strcmp(name, skipped_tests[i]) == 0) { + return 1; + } + } + + return 0; +} + int main(int ac, char* av[]) { int i; int testNum = 0; int partial_match; + int run_all; char *arg; int testToRun = -1; @@ -95,15 +108,43 @@ int main(int ac, char* av[]) av++; } partial_match = 0; + run_all = 0; arg = CM_NULL; /* NOLINT */ - /* If partial match is requested. */ + /* If partial match or running all tests are requested. */ if (testToRun == -1 && ac > 1) { partial_match = (strcmp(av[1], "-R") == 0) ? 1 : 0; + run_all = (strcmp(av[1], "-A") == 0) ? 1 : 0; } if (partial_match != 0 && ac < 3) { printf("-R needs an additional parameter.\n"); return -1; } + if (run_all == 1) { + clock_t t; + int status = 0; + const char* status_message = NULL; + printf("TAP version 13\n"); + printf("1..%d\n", NumTests); + for (i = 0; i < NumTests; ++i) { + const char *name = cmakeGeneratedFunctionMapEntries[i].name; + if (ac > 2) { + if (isTestSkipped(name, ac - 2, av + 2) == 1) { + printf("ok %d %s # SKIP\n", i + 1, name); + continue; + } + } + t = clock(); + status = (*cmakeGeneratedFunctionMapEntries[i].func)(ac, av); + t = clock() - t; + double time_taken = ((double)t) / CLOCKS_PER_SEC; + status_message = (status == -1) ? "not ok" : "ok"; + printf("%s %d %s # %f\n", status_message, i + 1, name, time_taken); + } + printf("All tests finished.\n"); + + return 0; + } + if (testToRun == -1) { arg = lowercase(av[1 + partial_match]); } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index cd1b465370d..f9df95ae029 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1772,6 +1772,32 @@ if(BUILD_TESTING) ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver3") + add_test(testdriver4 ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/TestDriver" + "${CMake_BINARY_DIR}/Tests/TestDriver4" + ${build_generator_args} + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" + --build-project TestDriverTest + --test-command TestDriverTest -A test2 + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver4") + + add_test(testdriver5 ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/TestDriver" + "${CMake_BINARY_DIR}/Tests/TestDriver5" + ${build_generator_args} + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" + --build-project TestDriverTest + --test-command TestDriverTest -A test2 + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver5") + set_tests_properties(testdriver5 PROPERTIES + PASS_REGULAR_EXPRESSION + "TAP version 13\n1\\.\\.3.+ok 1 test1 # [0-9]+\\.[0-9]+.*All tests finished." + ) + add_test(Dependency ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Dependency" From d59afbd92eb0bee30adc9f3150fcbe9872742daa Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 09:42:16 -0400 Subject: [PATCH 0317/1519] Tests: Fix RunCMake.GenerateExportHeader use of size_t Since commit ddcd1469e8 (MSYS: Add support for running under MSYS runtime environment, 2021-04-01) the test uses `std::size_t` without including ``. Also, the type does not exist under `std::` on VS 6. Use just `size_t` instead. --- Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp b/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp index ed8c35e19d3..2cfcd8deafc 100644 --- a/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp +++ b/Tests/RunCMake/GenerateExportHeader/exportheader_test.cpp @@ -10,7 +10,7 @@ static void rtrim(std::string& str, char byte) { - const std::size_t size = str.size(); + size_t const size = str.size(); if (size && str[size - 1] == byte) { str.resize(size - 1); } From 82470e24aebb1ab58e93cca89950d8f1dc02e92e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 09:32:46 -0400 Subject: [PATCH 0318/1519] Tests: Fix FortranOnly test with Intel compiler on Windows The test regularly fails updating the `vc*.pdb` compiler-generated PDB file. Add the `/Z7` flag as the compiler suggests for this. --- Tests/FortranOnly/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt index cdf8ed6228b..ee47da455e7 100644 --- a/Tests/FortranOnly/CMakeLists.txt +++ b/Tests/FortranOnly/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 2.8.12) project(FortranOnly Fortran) message("CTEST_FULL_OUTPUT ") +if("${CMAKE_Fortran_COMPILER_ID};${CMAKE_Fortran_SIMULATE_ID}" MATCHES "^Intel(LLVM)?;MSVC$") + string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -Z7") + string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO " -Z7") +endif() + # create a library with hello and world functions add_library(FortranOnlylib hello.f world.f) set_property(TARGET FortranOnlylib PROPERTY Fortran_FORMAT FIXED) From cefda16d357b6d75ffb70fd9036ca62da87432d7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 10:07:44 -0400 Subject: [PATCH 0319/1519] LexerParser: Regenerate parsers with bison 3.7.5 --- .../LexerParser/cmCommandArgumentParser.cxx | 86 ++- .../cmCommandArgumentParserTokens.h | 4 +- Source/LexerParser/cmDependsJavaParser.cxx | 716 +++++++++--------- .../LexerParser/cmDependsJavaParserTokens.h | 4 +- Source/LexerParser/cmExprParser.cxx | 86 ++- Source/LexerParser/cmExprParserTokens.h | 4 +- Source/LexerParser/cmFortranParser.cxx | 86 ++- Source/LexerParser/cmFortranParserTokens.h | 4 +- 8 files changed, 519 insertions(+), 471 deletions(-) diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index b8bc82cd7cd..5727992aa8f 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -228,6 +228,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -325,9 +337,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -635,7 +647,7 @@ static const yytype_int8 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 11, 12, 13, 14, 15, 19, 20, 21, 22 + 0, 11, 12, 13, 14, 15, 19, 20, 21, 22 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -761,8 +773,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -770,7 +782,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1151,14 +1163,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1433,7 +1445,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1437 "cmCommandArgumentParser.cxx" +#line 1449 "cmCommandArgumentParser.cxx" break; case 3: /* GoalWithOptionalBackSlash: Goal */ @@ -1441,7 +1453,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1445 "cmCommandArgumentParser.cxx" +#line 1457 "cmCommandArgumentParser.cxx" break; case 4: /* GoalWithOptionalBackSlash: Goal "\\" */ @@ -1449,7 +1461,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1453 "cmCommandArgumentParser.cxx" +#line 1465 "cmCommandArgumentParser.cxx" break; case 5: /* Goal: %empty */ @@ -1457,7 +1469,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = 0; } -#line 1461 "cmCommandArgumentParser.cxx" +#line 1473 "cmCommandArgumentParser.cxx" break; case 6: /* Goal: String Goal */ @@ -1465,7 +1477,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1469 "cmCommandArgumentParser.cxx" +#line 1481 "cmCommandArgumentParser.cxx" break; case 7: /* String: OuterText */ @@ -1473,7 +1485,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1477 "cmCommandArgumentParser.cxx" +#line 1489 "cmCommandArgumentParser.cxx" break; case 8: /* String: Variable */ @@ -1481,7 +1493,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1485 "cmCommandArgumentParser.cxx" +#line 1497 "cmCommandArgumentParser.cxx" break; case 9: /* OuterText: cal_NAME */ @@ -1489,7 +1501,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1493 "cmCommandArgumentParser.cxx" +#line 1505 "cmCommandArgumentParser.cxx" break; case 10: /* OuterText: "@" */ @@ -1497,7 +1509,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1501 "cmCommandArgumentParser.cxx" +#line 1513 "cmCommandArgumentParser.cxx" break; case 11: /* OuterText: "$" */ @@ -1505,7 +1517,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1509 "cmCommandArgumentParser.cxx" +#line 1521 "cmCommandArgumentParser.cxx" break; case 12: /* OuterText: "{" */ @@ -1513,7 +1525,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1517 "cmCommandArgumentParser.cxx" +#line 1529 "cmCommandArgumentParser.cxx" break; case 13: /* OuterText: "}" */ @@ -1521,7 +1533,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1525 "cmCommandArgumentParser.cxx" +#line 1537 "cmCommandArgumentParser.cxx" break; case 14: /* OuterText: cal_SYMBOL */ @@ -1529,7 +1541,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1533 "cmCommandArgumentParser.cxx" +#line 1545 "cmCommandArgumentParser.cxx" break; case 15: /* Variable: cal_ENVCURLY EnvVarName "}" */ @@ -1537,7 +1549,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1541 "cmCommandArgumentParser.cxx" +#line 1553 "cmCommandArgumentParser.cxx" break; case 16: /* Variable: cal_NCURLY MultipleIds "}" */ @@ -1545,7 +1557,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1549 "cmCommandArgumentParser.cxx" +#line 1561 "cmCommandArgumentParser.cxx" break; case 17: /* Variable: cal_DCURLY MultipleIds "}" */ @@ -1553,7 +1565,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1557 "cmCommandArgumentParser.cxx" +#line 1569 "cmCommandArgumentParser.cxx" break; case 18: /* Variable: cal_ATNAME */ @@ -1561,7 +1573,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1565 "cmCommandArgumentParser.cxx" +#line 1577 "cmCommandArgumentParser.cxx" break; case 19: /* EnvVarName: MultipleIds */ @@ -1569,7 +1581,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1573 "cmCommandArgumentParser.cxx" +#line 1585 "cmCommandArgumentParser.cxx" break; case 20: /* EnvVarName: cal_SYMBOL EnvVarName */ @@ -1577,7 +1589,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[-1].str); } -#line 1581 "cmCommandArgumentParser.cxx" +#line 1593 "cmCommandArgumentParser.cxx" break; case 21: /* MultipleIds: %empty */ @@ -1585,7 +1597,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = 0; } -#line 1589 "cmCommandArgumentParser.cxx" +#line 1601 "cmCommandArgumentParser.cxx" break; case 22: /* MultipleIds: ID MultipleIds */ @@ -1593,7 +1605,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1597 "cmCommandArgumentParser.cxx" +#line 1609 "cmCommandArgumentParser.cxx" break; case 23: /* ID: cal_NAME */ @@ -1601,7 +1613,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1605 "cmCommandArgumentParser.cxx" +#line 1617 "cmCommandArgumentParser.cxx" break; case 24: /* ID: Variable */ @@ -1609,11 +1621,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.str) = (yyvsp[0].str); } -#line 1613 "cmCommandArgumentParser.cxx" +#line 1625 "cmCommandArgumentParser.cxx" break; -#line 1617 "cmCommandArgumentParser.cxx" +#line 1629 "cmCommandArgumentParser.cxx" default: break; } diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h index 578f7937c4f..414c6dd6b54 100644 --- a/Source/LexerParser/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index 27cc177e69c..e6b3a7ee25c 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -456,6 +456,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -553,9 +565,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -1108,7 +1120,7 @@ static const yytype_int16 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 2, 156, 157, 158, 229, 112, 113, 75, 78, + 0, 2, 156, 157, 158, 229, 112, 113, 75, 78, 230, 231, 19, 20, 21, 22, 3, 4, 24, 30, 5, 31, 32, 33, 51, 52, 53, 54, 163, 164, 65, 66, 79, 67, 80, 96, 97, 98, 208, 209, @@ -1803,8 +1815,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -1812,7 +1824,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2193,14 +2205,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2477,7 +2489,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2481 "cmDependsJavaParser.cxx" +#line 2493 "cmDependsJavaParser.cxx" break; case 3: /* Literal: IntegerLiteral */ @@ -2488,7 +2500,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2492 "cmDependsJavaParser.cxx" +#line 2504 "cmDependsJavaParser.cxx" break; case 4: /* Literal: jp_FLOATINGPOINTLITERAL */ @@ -2499,7 +2511,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2503 "cmDependsJavaParser.cxx" +#line 2515 "cmDependsJavaParser.cxx" break; case 5: /* Literal: jp_BOOLEANLITERAL */ @@ -2510,7 +2522,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2514 "cmDependsJavaParser.cxx" +#line 2526 "cmDependsJavaParser.cxx" break; case 6: /* Literal: jp_CHARACTERLITERAL */ @@ -2521,7 +2533,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2525 "cmDependsJavaParser.cxx" +#line 2537 "cmDependsJavaParser.cxx" break; case 7: /* Literal: jp_STRINGLITERAL */ @@ -2532,7 +2544,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2536 "cmDependsJavaParser.cxx" +#line 2548 "cmDependsJavaParser.cxx" break; case 8: /* Literal: jp_NULLLITERAL */ @@ -2543,7 +2555,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2547 "cmDependsJavaParser.cxx" +#line 2559 "cmDependsJavaParser.cxx" break; case 9: /* IntegerLiteral: jp_DECIMALINTEGERLITERAL */ @@ -2554,7 +2566,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2558 "cmDependsJavaParser.cxx" +#line 2570 "cmDependsJavaParser.cxx" break; case 10: /* IntegerLiteral: jp_HEXINTEGERLITERAL */ @@ -2565,7 +2577,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2569 "cmDependsJavaParser.cxx" +#line 2581 "cmDependsJavaParser.cxx" break; case 11: /* Type: PrimitiveType */ @@ -2576,7 +2588,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2580 "cmDependsJavaParser.cxx" +#line 2592 "cmDependsJavaParser.cxx" break; case 12: /* Type: ReferenceType */ @@ -2587,7 +2599,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2591 "cmDependsJavaParser.cxx" +#line 2603 "cmDependsJavaParser.cxx" break; case 13: /* PrimitiveType: jp_BYTE_TYPE */ @@ -2595,7 +2607,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2599 "cmDependsJavaParser.cxx" +#line 2611 "cmDependsJavaParser.cxx" break; case 14: /* PrimitiveType: jp_SHORT_TYPE */ @@ -2603,7 +2615,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2607 "cmDependsJavaParser.cxx" +#line 2619 "cmDependsJavaParser.cxx" break; case 15: /* PrimitiveType: jp_INT_TYPE */ @@ -2611,7 +2623,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2615 "cmDependsJavaParser.cxx" +#line 2627 "cmDependsJavaParser.cxx" break; case 16: /* PrimitiveType: jp_LONG_TYPE */ @@ -2619,7 +2631,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2623 "cmDependsJavaParser.cxx" +#line 2635 "cmDependsJavaParser.cxx" break; case 17: /* PrimitiveType: jp_CHAR_TYPE */ @@ -2627,7 +2639,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2631 "cmDependsJavaParser.cxx" +#line 2643 "cmDependsJavaParser.cxx" break; case 18: /* PrimitiveType: jp_FLOAT_TYPE */ @@ -2635,7 +2647,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2639 "cmDependsJavaParser.cxx" +#line 2651 "cmDependsJavaParser.cxx" break; case 19: /* PrimitiveType: jp_DOUBLE_TYPE */ @@ -2643,7 +2655,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2647 "cmDependsJavaParser.cxx" +#line 2659 "cmDependsJavaParser.cxx" break; case 20: /* PrimitiveType: jp_BOOLEAN_TYPE */ @@ -2651,7 +2663,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(0); } -#line 2655 "cmDependsJavaParser.cxx" +#line 2667 "cmDependsJavaParser.cxx" break; case 21: /* ReferenceType: ClassOrInterfaceType */ @@ -2662,7 +2674,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2666 "cmDependsJavaParser.cxx" +#line 2678 "cmDependsJavaParser.cxx" break; case 22: /* ReferenceType: ArrayType */ @@ -2673,7 +2685,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2677 "cmDependsJavaParser.cxx" +#line 2689 "cmDependsJavaParser.cxx" break; case 23: /* ClassOrInterfaceType: Name */ @@ -2685,7 +2697,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2689 "cmDependsJavaParser.cxx" +#line 2701 "cmDependsJavaParser.cxx" break; case 24: /* ClassType: ClassOrInterfaceType */ @@ -2696,7 +2708,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2700 "cmDependsJavaParser.cxx" +#line 2712 "cmDependsJavaParser.cxx" break; case 25: /* InterfaceType: ClassOrInterfaceType */ @@ -2707,7 +2719,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2711 "cmDependsJavaParser.cxx" +#line 2723 "cmDependsJavaParser.cxx" break; case 26: /* ArrayType: PrimitiveType Dims */ @@ -2718,7 +2730,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2722 "cmDependsJavaParser.cxx" +#line 2734 "cmDependsJavaParser.cxx" break; case 27: /* ArrayType: Name Dims */ @@ -2730,7 +2742,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2734 "cmDependsJavaParser.cxx" +#line 2746 "cmDependsJavaParser.cxx" break; case 28: /* Name: SimpleName */ @@ -2739,7 +2751,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2743 "cmDependsJavaParser.cxx" +#line 2755 "cmDependsJavaParser.cxx" break; case 29: /* Name: QualifiedName */ @@ -2748,7 +2760,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2752 "cmDependsJavaParser.cxx" +#line 2764 "cmDependsJavaParser.cxx" break; case 30: /* SimpleName: Identifier */ @@ -2757,7 +2769,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2761 "cmDependsJavaParser.cxx" +#line 2773 "cmDependsJavaParser.cxx" break; case 31: /* Identifier: jp_NAME */ @@ -2766,7 +2778,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2770 "cmDependsJavaParser.cxx" +#line 2782 "cmDependsJavaParser.cxx" break; case 32: /* Identifier: jp_DOLLAR jp_NAME */ @@ -2775,7 +2787,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2779 "cmDependsJavaParser.cxx" +#line 2791 "cmDependsJavaParser.cxx" break; case 33: /* QualifiedName: Name jp_DOT Identifier */ @@ -2787,7 +2799,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast(yyGetParser->GetCurrentCombine()); } -#line 2791 "cmDependsJavaParser.cxx" +#line 2803 "cmDependsJavaParser.cxx" break; case 34: /* QualifiedName: Name jp_DOT jp_CLASS */ @@ -2800,7 +2812,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2804 "cmDependsJavaParser.cxx" +#line 2816 "cmDependsJavaParser.cxx" break; case 35: /* QualifiedName: Name jp_DOT jp_THIS */ @@ -2813,7 +2825,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2817 "cmDependsJavaParser.cxx" +#line 2829 "cmDependsJavaParser.cxx" break; case 36: /* QualifiedName: SimpleType jp_DOT jp_CLASS */ @@ -2824,7 +2836,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2828 "cmDependsJavaParser.cxx" +#line 2840 "cmDependsJavaParser.cxx" break; case 37: /* SimpleType: PrimitiveType */ @@ -2835,7 +2847,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2839 "cmDependsJavaParser.cxx" +#line 2851 "cmDependsJavaParser.cxx" break; case 38: /* SimpleType: jp_VOID */ @@ -2846,7 +2858,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2850 "cmDependsJavaParser.cxx" +#line 2862 "cmDependsJavaParser.cxx" break; case 39: /* CompilationUnit: PackageDeclarationopt ImportDeclarations TypeDeclarations */ @@ -2857,7 +2869,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2861 "cmDependsJavaParser.cxx" +#line 2873 "cmDependsJavaParser.cxx" break; case 40: /* PackageDeclarationopt: %empty */ @@ -2867,7 +2879,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2871 "cmDependsJavaParser.cxx" +#line 2883 "cmDependsJavaParser.cxx" break; case 41: /* PackageDeclarationopt: PackageDeclaration */ @@ -2878,7 +2890,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2882 "cmDependsJavaParser.cxx" +#line 2894 "cmDependsJavaParser.cxx" break; case 42: /* ImportDeclarations: %empty */ @@ -2888,7 +2900,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2892 "cmDependsJavaParser.cxx" +#line 2904 "cmDependsJavaParser.cxx" break; case 43: /* ImportDeclarations: ImportDeclarations ImportDeclaration */ @@ -2899,7 +2911,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2903 "cmDependsJavaParser.cxx" +#line 2915 "cmDependsJavaParser.cxx" break; case 44: /* TypeDeclarations: %empty */ @@ -2909,7 +2921,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2913 "cmDependsJavaParser.cxx" +#line 2925 "cmDependsJavaParser.cxx" break; case 45: /* TypeDeclarations: TypeDeclarations TypeDeclaration */ @@ -2920,7 +2932,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2924 "cmDependsJavaParser.cxx" +#line 2936 "cmDependsJavaParser.cxx" break; case 46: /* PackageDeclaration: jp_PACKAGE Name jp_SEMICOL */ @@ -2934,7 +2946,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2938 "cmDependsJavaParser.cxx" +#line 2950 "cmDependsJavaParser.cxx" break; case 47: /* ImportDeclaration: SingleTypeImportDeclaration */ @@ -2945,7 +2957,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2949 "cmDependsJavaParser.cxx" +#line 2961 "cmDependsJavaParser.cxx" break; case 48: /* ImportDeclaration: TypeImportOnDemandDeclaration */ @@ -2956,7 +2968,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2960 "cmDependsJavaParser.cxx" +#line 2972 "cmDependsJavaParser.cxx" break; case 49: /* SingleTypeImportDeclaration: jp_IMPORT Name jp_SEMICOL */ @@ -2970,7 +2982,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2974 "cmDependsJavaParser.cxx" +#line 2986 "cmDependsJavaParser.cxx" break; case 50: /* TypeImportOnDemandDeclaration: jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL */ @@ -2985,7 +2997,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2989 "cmDependsJavaParser.cxx" +#line 3001 "cmDependsJavaParser.cxx" break; case 51: /* TypeDeclaration: ClassDeclaration */ @@ -2996,7 +3008,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3000 "cmDependsJavaParser.cxx" +#line 3012 "cmDependsJavaParser.cxx" break; case 52: /* TypeDeclaration: InterfaceDeclaration */ @@ -3007,7 +3019,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3011 "cmDependsJavaParser.cxx" +#line 3023 "cmDependsJavaParser.cxx" break; case 53: /* TypeDeclaration: jp_SEMICOL */ @@ -3018,7 +3030,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3022 "cmDependsJavaParser.cxx" +#line 3034 "cmDependsJavaParser.cxx" break; case 54: /* Modifiers: Modifier */ @@ -3029,7 +3041,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3033 "cmDependsJavaParser.cxx" +#line 3045 "cmDependsJavaParser.cxx" break; case 55: /* Modifiers: Modifiers Modifier */ @@ -3040,7 +3052,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3044 "cmDependsJavaParser.cxx" +#line 3056 "cmDependsJavaParser.cxx" break; case 67: /* ClassHeader: Modifiersopt jp_CLASS Identifier */ @@ -3051,7 +3063,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3055 "cmDependsJavaParser.cxx" +#line 3067 "cmDependsJavaParser.cxx" break; case 68: /* ClassDeclaration: ClassHeader ClassBody */ @@ -3063,7 +3075,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3067 "cmDependsJavaParser.cxx" +#line 3079 "cmDependsJavaParser.cxx" break; case 69: /* ClassDeclaration: ClassHeader Interfaces ClassBody */ @@ -3075,7 +3087,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3079 "cmDependsJavaParser.cxx" +#line 3091 "cmDependsJavaParser.cxx" break; case 70: /* ClassDeclaration: ClassHeader Super ClassBody */ @@ -3087,7 +3099,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3091 "cmDependsJavaParser.cxx" +#line 3103 "cmDependsJavaParser.cxx" break; case 71: /* ClassDeclaration: ClassHeader Super Interfaces ClassBody */ @@ -3099,7 +3111,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3103 "cmDependsJavaParser.cxx" +#line 3115 "cmDependsJavaParser.cxx" break; case 72: /* Modifiersopt: %empty */ @@ -3109,7 +3121,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3113 "cmDependsJavaParser.cxx" +#line 3125 "cmDependsJavaParser.cxx" break; case 73: /* Modifiersopt: Modifiers */ @@ -3120,7 +3132,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3124 "cmDependsJavaParser.cxx" +#line 3136 "cmDependsJavaParser.cxx" break; case 74: /* Super: jp_EXTENDS ClassType */ @@ -3131,7 +3143,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3135 "cmDependsJavaParser.cxx" +#line 3147 "cmDependsJavaParser.cxx" break; case 75: /* Interfaces: jp_IMPLEMENTS InterfaceTypeList */ @@ -3142,7 +3154,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3146 "cmDependsJavaParser.cxx" +#line 3158 "cmDependsJavaParser.cxx" break; case 76: /* InterfaceTypeList: InterfaceType */ @@ -3153,7 +3165,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3157 "cmDependsJavaParser.cxx" +#line 3169 "cmDependsJavaParser.cxx" break; case 77: /* InterfaceTypeList: InterfaceTypeList jp_COMMA InterfaceType */ @@ -3164,7 +3176,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3168 "cmDependsJavaParser.cxx" +#line 3180 "cmDependsJavaParser.cxx" break; case 78: /* ClassBody: jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND */ @@ -3175,7 +3187,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3179 "cmDependsJavaParser.cxx" +#line 3191 "cmDependsJavaParser.cxx" break; case 79: /* ClassBodyDeclarations: %empty */ @@ -3185,7 +3197,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3189 "cmDependsJavaParser.cxx" +#line 3201 "cmDependsJavaParser.cxx" break; case 80: /* ClassBodyDeclarations: ClassBodyDeclarations ClassBodyDeclaration */ @@ -3196,7 +3208,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3200 "cmDependsJavaParser.cxx" +#line 3212 "cmDependsJavaParser.cxx" break; case 81: /* ClassBodyDeclaration: ClassMemberDeclaration */ @@ -3207,7 +3219,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3211 "cmDependsJavaParser.cxx" +#line 3223 "cmDependsJavaParser.cxx" break; case 82: /* ClassBodyDeclaration: StaticInitializer */ @@ -3218,7 +3230,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3222 "cmDependsJavaParser.cxx" +#line 3234 "cmDependsJavaParser.cxx" break; case 83: /* ClassBodyDeclaration: ConstructorDeclaration */ @@ -3229,7 +3241,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3233 "cmDependsJavaParser.cxx" +#line 3245 "cmDependsJavaParser.cxx" break; case 84: /* ClassBodyDeclaration: TypeDeclaration */ @@ -3240,7 +3252,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3244 "cmDependsJavaParser.cxx" +#line 3256 "cmDependsJavaParser.cxx" break; case 85: /* ClassMemberDeclaration: FieldDeclaration */ @@ -3251,7 +3263,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3255 "cmDependsJavaParser.cxx" +#line 3267 "cmDependsJavaParser.cxx" break; case 86: /* ClassMemberDeclaration: MethodDeclaration */ @@ -3262,7 +3274,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3266 "cmDependsJavaParser.cxx" +#line 3278 "cmDependsJavaParser.cxx" break; case 87: /* FieldDeclaration: Modifiersopt Type VariableDeclarators jp_SEMICOL */ @@ -3270,7 +3282,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { jpElementStart(4); } -#line 3274 "cmDependsJavaParser.cxx" +#line 3286 "cmDependsJavaParser.cxx" break; case 88: /* VariableDeclarators: VariableDeclarator */ @@ -3281,7 +3293,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3285 "cmDependsJavaParser.cxx" +#line 3297 "cmDependsJavaParser.cxx" break; case 89: /* VariableDeclarators: VariableDeclarators jp_COMMA VariableDeclarator */ @@ -3292,7 +3304,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3296 "cmDependsJavaParser.cxx" +#line 3308 "cmDependsJavaParser.cxx" break; case 90: /* VariableDeclarator: VariableDeclaratorId */ @@ -3303,7 +3315,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3307 "cmDependsJavaParser.cxx" +#line 3319 "cmDependsJavaParser.cxx" break; case 91: /* VariableDeclarator: VariableDeclaratorId jp_EQUALS VariableInitializer */ @@ -3314,7 +3326,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3318 "cmDependsJavaParser.cxx" +#line 3330 "cmDependsJavaParser.cxx" break; case 92: /* VariableDeclaratorId: Identifier */ @@ -3326,7 +3338,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3330 "cmDependsJavaParser.cxx" +#line 3342 "cmDependsJavaParser.cxx" break; case 93: /* VariableDeclaratorId: VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND */ @@ -3337,7 +3349,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3341 "cmDependsJavaParser.cxx" +#line 3353 "cmDependsJavaParser.cxx" break; case 94: /* VariableInitializer: Expression */ @@ -3348,7 +3360,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3352 "cmDependsJavaParser.cxx" +#line 3364 "cmDependsJavaParser.cxx" break; case 95: /* VariableInitializer: ArrayInitializer */ @@ -3359,7 +3371,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3363 "cmDependsJavaParser.cxx" +#line 3375 "cmDependsJavaParser.cxx" break; case 96: /* MethodDeclaration: MethodHeader jp_SEMICOL */ @@ -3370,7 +3382,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3374 "cmDependsJavaParser.cxx" +#line 3386 "cmDependsJavaParser.cxx" break; case 97: /* MethodDeclaration: MethodHeader MethodBody */ @@ -3381,7 +3393,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3385 "cmDependsJavaParser.cxx" +#line 3397 "cmDependsJavaParser.cxx" break; case 98: /* MethodDeclaration: MethodHeader MethodBody jp_SEMICOL */ @@ -3392,7 +3404,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3396 "cmDependsJavaParser.cxx" +#line 3408 "cmDependsJavaParser.cxx" break; case 99: /* MethodHeader: Modifiersopt Type MethodDeclarator Throwsopt */ @@ -3404,7 +3416,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3408 "cmDependsJavaParser.cxx" +#line 3420 "cmDependsJavaParser.cxx" break; case 100: /* MethodHeader: Modifiersopt jp_VOID MethodDeclarator Throwsopt */ @@ -3416,7 +3428,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3420 "cmDependsJavaParser.cxx" +#line 3432 "cmDependsJavaParser.cxx" break; case 101: /* Throwsopt: %empty */ @@ -3427,7 +3439,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3431 "cmDependsJavaParser.cxx" +#line 3443 "cmDependsJavaParser.cxx" break; case 102: /* Throwsopt: Throws */ @@ -3439,7 +3451,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3443 "cmDependsJavaParser.cxx" +#line 3455 "cmDependsJavaParser.cxx" break; case 103: /* MethodDeclarator: Identifier jp_PARESTART FormalParameterListopt jp_PAREEND */ @@ -3452,7 +3464,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3456 "cmDependsJavaParser.cxx" +#line 3468 "cmDependsJavaParser.cxx" break; case 104: /* MethodDeclarator: MethodDeclarator jp_BRACKETSTART jp_BRACKETEND */ @@ -3461,7 +3473,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(3); } -#line 3465 "cmDependsJavaParser.cxx" +#line 3477 "cmDependsJavaParser.cxx" break; case 105: /* FormalParameterListopt: %empty */ @@ -3472,7 +3484,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3476 "cmDependsJavaParser.cxx" +#line 3488 "cmDependsJavaParser.cxx" break; case 107: /* FormalParameterList: FormalParameter */ @@ -3481,7 +3493,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); } -#line 3485 "cmDependsJavaParser.cxx" +#line 3497 "cmDependsJavaParser.cxx" break; case 108: /* FormalParameterList: FormalParameterList jp_COMMA FormalParameter */ @@ -3493,7 +3505,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3497 "cmDependsJavaParser.cxx" +#line 3509 "cmDependsJavaParser.cxx" break; case 109: /* FormalParameter: Modifiersopt Type VariableDeclaratorId */ @@ -3505,7 +3517,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3509 "cmDependsJavaParser.cxx" +#line 3521 "cmDependsJavaParser.cxx" break; case 110: /* Throws: jp_THROWS ClassTypeList */ @@ -3517,7 +3529,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3521 "cmDependsJavaParser.cxx" +#line 3533 "cmDependsJavaParser.cxx" break; case 111: /* ClassTypeList: ClassType */ @@ -3526,7 +3538,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); } -#line 3530 "cmDependsJavaParser.cxx" +#line 3542 "cmDependsJavaParser.cxx" break; case 112: /* ClassTypeList: ClassTypeList jp_COMMA ClassType */ @@ -3538,7 +3550,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3542 "cmDependsJavaParser.cxx" +#line 3554 "cmDependsJavaParser.cxx" break; case 113: /* MethodBody: Block */ @@ -3550,7 +3562,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3554 "cmDependsJavaParser.cxx" +#line 3566 "cmDependsJavaParser.cxx" break; case 114: /* StaticInitializer: jp_STATIC Block */ @@ -3562,7 +3574,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3566 "cmDependsJavaParser.cxx" +#line 3578 "cmDependsJavaParser.cxx" break; case 115: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody */ @@ -3574,7 +3586,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3578 "cmDependsJavaParser.cxx" +#line 3590 "cmDependsJavaParser.cxx" break; case 116: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL */ @@ -3586,7 +3598,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3590 "cmDependsJavaParser.cxx" +#line 3602 "cmDependsJavaParser.cxx" break; case 117: /* ConstructorDeclarator: SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND */ @@ -3599,7 +3611,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3603 "cmDependsJavaParser.cxx" +#line 3615 "cmDependsJavaParser.cxx" break; case 118: /* ConstructorBody: jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND */ @@ -3611,7 +3623,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3615 "cmDependsJavaParser.cxx" +#line 3627 "cmDependsJavaParser.cxx" break; case 119: /* ExplicitConstructorInvocationopt: %empty */ @@ -3622,7 +3634,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3626 "cmDependsJavaParser.cxx" +#line 3638 "cmDependsJavaParser.cxx" break; case 120: /* ExplicitConstructorInvocationopt: ExplicitConstructorInvocationopt ExplicitConstructorInvocation */ @@ -3634,7 +3646,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3638 "cmDependsJavaParser.cxx" +#line 3650 "cmDependsJavaParser.cxx" break; case 121: /* ExplicitConstructorInvocation: jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */ @@ -3646,7 +3658,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3650 "cmDependsJavaParser.cxx" +#line 3662 "cmDependsJavaParser.cxx" break; case 122: /* ExplicitConstructorInvocation: jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */ @@ -3658,7 +3670,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3662 "cmDependsJavaParser.cxx" +#line 3674 "cmDependsJavaParser.cxx" break; case 123: /* InterfaceHeader: Modifiersopt jp_INTERFACE Identifier */ @@ -3669,7 +3681,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3673 "cmDependsJavaParser.cxx" +#line 3685 "cmDependsJavaParser.cxx" break; case 124: /* InterfaceDeclaration: InterfaceHeader ExtendsInterfacesopt InterfaceBody */ @@ -3681,7 +3693,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3685 "cmDependsJavaParser.cxx" +#line 3697 "cmDependsJavaParser.cxx" break; case 125: /* ExtendsInterfacesopt: %empty */ @@ -3691,7 +3703,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3695 "cmDependsJavaParser.cxx" +#line 3707 "cmDependsJavaParser.cxx" break; case 126: /* ExtendsInterfacesopt: ExtendsInterfaces */ @@ -3703,7 +3715,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3707 "cmDependsJavaParser.cxx" +#line 3719 "cmDependsJavaParser.cxx" break; case 127: /* ExtendsInterfaces: jp_EXTENDS InterfaceType */ @@ -3715,7 +3727,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3719 "cmDependsJavaParser.cxx" +#line 3731 "cmDependsJavaParser.cxx" break; case 128: /* ExtendsInterfaces: ExtendsInterfaces jp_COMMA InterfaceType */ @@ -3727,7 +3739,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3731 "cmDependsJavaParser.cxx" +#line 3743 "cmDependsJavaParser.cxx" break; case 129: /* InterfaceBody: jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND */ @@ -3739,7 +3751,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3743 "cmDependsJavaParser.cxx" +#line 3755 "cmDependsJavaParser.cxx" break; case 130: /* InterfaceMemberDeclarations: %empty */ @@ -3750,7 +3762,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3754 "cmDependsJavaParser.cxx" +#line 3766 "cmDependsJavaParser.cxx" break; case 131: /* InterfaceMemberDeclarations: InterfaceMemberDeclarations InterfaceMemberDeclaration */ @@ -3761,7 +3773,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3765 "cmDependsJavaParser.cxx" +#line 3777 "cmDependsJavaParser.cxx" break; case 132: /* InterfaceMemberDeclaration: ConstantDeclaration */ @@ -3773,7 +3785,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3777 "cmDependsJavaParser.cxx" +#line 3789 "cmDependsJavaParser.cxx" break; case 133: /* InterfaceMemberDeclaration: AbstractMethodDeclaration */ @@ -3785,7 +3797,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3789 "cmDependsJavaParser.cxx" +#line 3801 "cmDependsJavaParser.cxx" break; case 134: /* InterfaceMemberDeclaration: ClassDeclaration */ @@ -3797,7 +3809,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3801 "cmDependsJavaParser.cxx" +#line 3813 "cmDependsJavaParser.cxx" break; case 135: /* InterfaceMemberDeclaration: ClassDeclaration jp_SEMICOL */ @@ -3808,7 +3820,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3812 "cmDependsJavaParser.cxx" +#line 3824 "cmDependsJavaParser.cxx" break; case 136: /* InterfaceMemberDeclaration: InterfaceDeclaration */ @@ -3820,7 +3832,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3824 "cmDependsJavaParser.cxx" +#line 3836 "cmDependsJavaParser.cxx" break; case 137: /* InterfaceMemberDeclaration: InterfaceDeclaration jp_SEMICOL */ @@ -3831,7 +3843,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3835 "cmDependsJavaParser.cxx" +#line 3847 "cmDependsJavaParser.cxx" break; case 138: /* ConstantDeclaration: FieldDeclaration */ @@ -3843,7 +3855,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3847 "cmDependsJavaParser.cxx" +#line 3859 "cmDependsJavaParser.cxx" break; case 139: /* AbstractMethodDeclaration: MethodHeader Semicols */ @@ -3855,7 +3867,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3859 "cmDependsJavaParser.cxx" +#line 3871 "cmDependsJavaParser.cxx" break; case 140: /* Semicols: jp_SEMICOL */ @@ -3867,7 +3879,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3871 "cmDependsJavaParser.cxx" +#line 3883 "cmDependsJavaParser.cxx" break; case 141: /* Semicols: Semicols jp_SEMICOL */ @@ -3879,7 +3891,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3883 "cmDependsJavaParser.cxx" +#line 3895 "cmDependsJavaParser.cxx" break; case 142: /* ArrayInitializer: jp_CURLYSTART VariableInitializersOptional jp_CURLYEND */ @@ -3891,7 +3903,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3895 "cmDependsJavaParser.cxx" +#line 3907 "cmDependsJavaParser.cxx" break; case 143: /* VariableInitializersOptional: %empty */ @@ -3902,7 +3914,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3906 "cmDependsJavaParser.cxx" +#line 3918 "cmDependsJavaParser.cxx" break; case 144: /* VariableInitializersOptional: VariableInitializers */ @@ -3914,7 +3926,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3918 "cmDependsJavaParser.cxx" +#line 3930 "cmDependsJavaParser.cxx" break; case 145: /* VariableInitializersOptional: VariableInitializers jp_COMMA */ @@ -3926,7 +3938,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3930 "cmDependsJavaParser.cxx" +#line 3942 "cmDependsJavaParser.cxx" break; case 146: /* VariableInitializers: VariableInitializer */ @@ -3938,7 +3950,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3942 "cmDependsJavaParser.cxx" +#line 3954 "cmDependsJavaParser.cxx" break; case 147: /* VariableInitializers: VariableInitializers jp_COMMA VariableInitializer */ @@ -3950,7 +3962,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3954 "cmDependsJavaParser.cxx" +#line 3966 "cmDependsJavaParser.cxx" break; case 148: /* Block: jp_CURLYSTART BlockStatementsopt jp_CURLYEND */ @@ -3961,7 +3973,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3965 "cmDependsJavaParser.cxx" +#line 3977 "cmDependsJavaParser.cxx" break; case 149: /* BlockStatementsopt: %empty */ @@ -3972,7 +3984,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3976 "cmDependsJavaParser.cxx" +#line 3988 "cmDependsJavaParser.cxx" break; case 150: /* BlockStatementsopt: BlockStatements */ @@ -3984,7 +3996,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 3988 "cmDependsJavaParser.cxx" +#line 4000 "cmDependsJavaParser.cxx" break; case 151: /* BlockStatements: BlockStatement */ @@ -3996,7 +4008,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4000 "cmDependsJavaParser.cxx" +#line 4012 "cmDependsJavaParser.cxx" break; case 152: /* BlockStatements: BlockStatements BlockStatement */ @@ -4008,7 +4020,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4012 "cmDependsJavaParser.cxx" +#line 4024 "cmDependsJavaParser.cxx" break; case 153: /* BlockStatement: LocalVariableDeclarationStatement */ @@ -4020,7 +4032,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4024 "cmDependsJavaParser.cxx" +#line 4036 "cmDependsJavaParser.cxx" break; case 154: /* BlockStatement: Statement */ @@ -4032,7 +4044,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4036 "cmDependsJavaParser.cxx" +#line 4048 "cmDependsJavaParser.cxx" break; case 155: /* BlockStatement: ClassDeclaration */ @@ -4044,7 +4056,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4048 "cmDependsJavaParser.cxx" +#line 4060 "cmDependsJavaParser.cxx" break; case 156: /* LocalVariableDeclarationStatement: LocalVariableDeclaration jp_SEMICOL */ @@ -4056,7 +4068,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4060 "cmDependsJavaParser.cxx" +#line 4072 "cmDependsJavaParser.cxx" break; case 157: /* LocalVariableDeclaration: Modifiers Type VariableDeclarators */ @@ -4068,7 +4080,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4072 "cmDependsJavaParser.cxx" +#line 4084 "cmDependsJavaParser.cxx" break; case 158: /* LocalVariableDeclaration: Type VariableDeclarators */ @@ -4080,7 +4092,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4084 "cmDependsJavaParser.cxx" +#line 4096 "cmDependsJavaParser.cxx" break; case 159: /* Statement: StatementWithoutTrailingSubstatement */ @@ -4092,7 +4104,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4096 "cmDependsJavaParser.cxx" +#line 4108 "cmDependsJavaParser.cxx" break; case 160: /* Statement: LabeledStatement */ @@ -4104,7 +4116,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4108 "cmDependsJavaParser.cxx" +#line 4120 "cmDependsJavaParser.cxx" break; case 161: /* Statement: IfThenStatement */ @@ -4116,7 +4128,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4120 "cmDependsJavaParser.cxx" +#line 4132 "cmDependsJavaParser.cxx" break; case 162: /* Statement: IfThenElseStatement */ @@ -4128,7 +4140,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4132 "cmDependsJavaParser.cxx" +#line 4144 "cmDependsJavaParser.cxx" break; case 163: /* Statement: WhileStatement */ @@ -4140,7 +4152,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4144 "cmDependsJavaParser.cxx" +#line 4156 "cmDependsJavaParser.cxx" break; case 164: /* Statement: ForStatement */ @@ -4152,7 +4164,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4156 "cmDependsJavaParser.cxx" +#line 4168 "cmDependsJavaParser.cxx" break; case 165: /* StatementNoShortIf: StatementWithoutTrailingSubstatement */ @@ -4164,7 +4176,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4168 "cmDependsJavaParser.cxx" +#line 4180 "cmDependsJavaParser.cxx" break; case 166: /* StatementNoShortIf: LabeledStatementNoShortIf */ @@ -4176,7 +4188,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4180 "cmDependsJavaParser.cxx" +#line 4192 "cmDependsJavaParser.cxx" break; case 167: /* StatementNoShortIf: IfThenElseStatementNoShortIf */ @@ -4188,7 +4200,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4192 "cmDependsJavaParser.cxx" +#line 4204 "cmDependsJavaParser.cxx" break; case 168: /* StatementNoShortIf: WhileStatementNoShortIf */ @@ -4200,7 +4212,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4204 "cmDependsJavaParser.cxx" +#line 4216 "cmDependsJavaParser.cxx" break; case 169: /* StatementNoShortIf: ForStatementNoShortIf */ @@ -4212,7 +4224,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4216 "cmDependsJavaParser.cxx" +#line 4228 "cmDependsJavaParser.cxx" break; case 170: /* StatementWithoutTrailingSubstatement: Block */ @@ -4224,7 +4236,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4228 "cmDependsJavaParser.cxx" +#line 4240 "cmDependsJavaParser.cxx" break; case 171: /* StatementWithoutTrailingSubstatement: EmptyStatement */ @@ -4236,7 +4248,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4240 "cmDependsJavaParser.cxx" +#line 4252 "cmDependsJavaParser.cxx" break; case 172: /* StatementWithoutTrailingSubstatement: ExpressionStatement */ @@ -4248,7 +4260,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4252 "cmDependsJavaParser.cxx" +#line 4264 "cmDependsJavaParser.cxx" break; case 173: /* StatementWithoutTrailingSubstatement: SwitchStatement */ @@ -4260,7 +4272,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4264 "cmDependsJavaParser.cxx" +#line 4276 "cmDependsJavaParser.cxx" break; case 174: /* StatementWithoutTrailingSubstatement: DoStatement */ @@ -4272,7 +4284,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4276 "cmDependsJavaParser.cxx" +#line 4288 "cmDependsJavaParser.cxx" break; case 175: /* StatementWithoutTrailingSubstatement: BreakStatement */ @@ -4284,7 +4296,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4288 "cmDependsJavaParser.cxx" +#line 4300 "cmDependsJavaParser.cxx" break; case 176: /* StatementWithoutTrailingSubstatement: ContinueStatement */ @@ -4296,7 +4308,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4300 "cmDependsJavaParser.cxx" +#line 4312 "cmDependsJavaParser.cxx" break; case 177: /* StatementWithoutTrailingSubstatement: ReturnStatement */ @@ -4308,7 +4320,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4312 "cmDependsJavaParser.cxx" +#line 4324 "cmDependsJavaParser.cxx" break; case 178: /* StatementWithoutTrailingSubstatement: SynchronizedStatement */ @@ -4320,7 +4332,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4324 "cmDependsJavaParser.cxx" +#line 4336 "cmDependsJavaParser.cxx" break; case 179: /* StatementWithoutTrailingSubstatement: ThrowStatement */ @@ -4332,7 +4344,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4336 "cmDependsJavaParser.cxx" +#line 4348 "cmDependsJavaParser.cxx" break; case 180: /* StatementWithoutTrailingSubstatement: TryStatement */ @@ -4344,7 +4356,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4348 "cmDependsJavaParser.cxx" +#line 4360 "cmDependsJavaParser.cxx" break; case 181: /* StatementWithoutTrailingSubstatement: AssertStatement */ @@ -4356,7 +4368,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4360 "cmDependsJavaParser.cxx" +#line 4372 "cmDependsJavaParser.cxx" break; case 182: /* EmptyStatement: jp_SEMICOL */ @@ -4368,7 +4380,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4372 "cmDependsJavaParser.cxx" +#line 4384 "cmDependsJavaParser.cxx" break; case 183: /* LabeledStatement: Identifier jp_COLON Statement */ @@ -4381,7 +4393,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4385 "cmDependsJavaParser.cxx" +#line 4397 "cmDependsJavaParser.cxx" break; case 184: /* LabeledStatementNoShortIf: Identifier jp_COLON StatementNoShortIf */ @@ -4393,7 +4405,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4397 "cmDependsJavaParser.cxx" +#line 4409 "cmDependsJavaParser.cxx" break; case 185: /* ExpressionStatement: StatementExpression jp_SEMICOL */ @@ -4405,7 +4417,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4409 "cmDependsJavaParser.cxx" +#line 4421 "cmDependsJavaParser.cxx" break; case 186: /* StatementExpression: Assignment */ @@ -4417,7 +4429,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4421 "cmDependsJavaParser.cxx" +#line 4433 "cmDependsJavaParser.cxx" break; case 187: /* StatementExpression: PreIncrementExpression */ @@ -4429,7 +4441,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4433 "cmDependsJavaParser.cxx" +#line 4445 "cmDependsJavaParser.cxx" break; case 188: /* StatementExpression: PreDecrementExpression */ @@ -4441,7 +4453,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4445 "cmDependsJavaParser.cxx" +#line 4457 "cmDependsJavaParser.cxx" break; case 189: /* StatementExpression: PostIncrementExpression */ @@ -4453,7 +4465,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4457 "cmDependsJavaParser.cxx" +#line 4469 "cmDependsJavaParser.cxx" break; case 190: /* StatementExpression: PostDecrementExpression */ @@ -4465,7 +4477,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4469 "cmDependsJavaParser.cxx" +#line 4481 "cmDependsJavaParser.cxx" break; case 191: /* StatementExpression: MethodInvocation */ @@ -4477,7 +4489,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4481 "cmDependsJavaParser.cxx" +#line 4493 "cmDependsJavaParser.cxx" break; case 192: /* StatementExpression: ClassInstanceCreationExpression */ @@ -4489,7 +4501,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4493 "cmDependsJavaParser.cxx" +#line 4505 "cmDependsJavaParser.cxx" break; case 193: /* IfThenStatement: jp_IF jp_PARESTART Expression jp_PAREEND Statement */ @@ -4501,7 +4513,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4505 "cmDependsJavaParser.cxx" +#line 4517 "cmDependsJavaParser.cxx" break; case 194: /* IfThenElseStatement: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement */ @@ -4513,7 +4525,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4517 "cmDependsJavaParser.cxx" +#line 4529 "cmDependsJavaParser.cxx" break; case 195: /* IfThenElseStatementNoShortIf: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf */ @@ -4525,7 +4537,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4529 "cmDependsJavaParser.cxx" +#line 4541 "cmDependsJavaParser.cxx" break; case 196: /* SwitchStatement: jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock */ @@ -4534,7 +4546,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(5); } -#line 4538 "cmDependsJavaParser.cxx" +#line 4550 "cmDependsJavaParser.cxx" break; case 197: /* SwitchBlock: jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND */ @@ -4543,7 +4555,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(4); } -#line 4547 "cmDependsJavaParser.cxx" +#line 4559 "cmDependsJavaParser.cxx" break; case 198: /* SwitchLabelsopt: %empty */ @@ -4554,7 +4566,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4558 "cmDependsJavaParser.cxx" +#line 4570 "cmDependsJavaParser.cxx" break; case 199: /* SwitchLabelsopt: SwitchLabels */ @@ -4566,7 +4578,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4570 "cmDependsJavaParser.cxx" +#line 4582 "cmDependsJavaParser.cxx" break; case 200: /* SwitchBlockStatementGroups: %empty */ @@ -4577,7 +4589,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4581 "cmDependsJavaParser.cxx" +#line 4593 "cmDependsJavaParser.cxx" break; case 201: /* SwitchBlockStatementGroups: SwitchBlockStatementGroups SwitchBlockStatementGroup */ @@ -4589,7 +4601,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4593 "cmDependsJavaParser.cxx" +#line 4605 "cmDependsJavaParser.cxx" break; case 202: /* SwitchBlockStatementGroup: SwitchLabels BlockStatements */ @@ -4601,7 +4613,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4605 "cmDependsJavaParser.cxx" +#line 4617 "cmDependsJavaParser.cxx" break; case 203: /* SwitchLabels: SwitchLabel */ @@ -4613,7 +4625,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4617 "cmDependsJavaParser.cxx" +#line 4629 "cmDependsJavaParser.cxx" break; case 204: /* SwitchLabels: SwitchLabels SwitchLabel */ @@ -4625,7 +4637,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4629 "cmDependsJavaParser.cxx" +#line 4641 "cmDependsJavaParser.cxx" break; case 205: /* SwitchLabel: jp_CASE ConstantExpression jp_COLON */ @@ -4637,7 +4649,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4641 "cmDependsJavaParser.cxx" +#line 4653 "cmDependsJavaParser.cxx" break; case 206: /* SwitchLabel: jp_DEFAULT jp_COLON */ @@ -4649,7 +4661,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4653 "cmDependsJavaParser.cxx" +#line 4665 "cmDependsJavaParser.cxx" break; case 207: /* WhileStatement: jp_WHILE jp_PARESTART Expression jp_PAREEND Statement */ @@ -4658,7 +4670,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(5); } -#line 4662 "cmDependsJavaParser.cxx" +#line 4674 "cmDependsJavaParser.cxx" break; case 208: /* WhileStatementNoShortIf: jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf */ @@ -4667,7 +4679,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(5); } -#line 4671 "cmDependsJavaParser.cxx" +#line 4683 "cmDependsJavaParser.cxx" break; case 209: /* DoStatement: jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL */ @@ -4676,7 +4688,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(7); } -#line 4680 "cmDependsJavaParser.cxx" +#line 4692 "cmDependsJavaParser.cxx" break; case 210: /* ForStatement: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND Statement */ @@ -4685,7 +4697,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(9); } -#line 4689 "cmDependsJavaParser.cxx" +#line 4701 "cmDependsJavaParser.cxx" break; case 211: /* ForUpdateopt: %empty */ @@ -4696,7 +4708,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4700 "cmDependsJavaParser.cxx" +#line 4712 "cmDependsJavaParser.cxx" break; case 212: /* ForUpdateopt: ForUpdate */ @@ -4708,7 +4720,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4712 "cmDependsJavaParser.cxx" +#line 4724 "cmDependsJavaParser.cxx" break; case 213: /* ForInitopt: %empty */ @@ -4719,7 +4731,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4723 "cmDependsJavaParser.cxx" +#line 4735 "cmDependsJavaParser.cxx" break; case 214: /* ForInitopt: ForInit */ @@ -4731,7 +4743,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4735 "cmDependsJavaParser.cxx" +#line 4747 "cmDependsJavaParser.cxx" break; case 215: /* ForStatementNoShortIf: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND StatementNoShortIf */ @@ -4742,7 +4754,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4746 "cmDependsJavaParser.cxx" +#line 4758 "cmDependsJavaParser.cxx" break; case 216: /* Expressionopt: %empty */ @@ -4753,7 +4765,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4757 "cmDependsJavaParser.cxx" +#line 4769 "cmDependsJavaParser.cxx" break; case 217: /* Expressionopt: Expression */ @@ -4765,7 +4777,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4769 "cmDependsJavaParser.cxx" +#line 4781 "cmDependsJavaParser.cxx" break; case 218: /* ForInit: StatementExpressionList */ @@ -4777,7 +4789,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4781 "cmDependsJavaParser.cxx" +#line 4793 "cmDependsJavaParser.cxx" break; case 219: /* ForInit: LocalVariableDeclaration */ @@ -4789,7 +4801,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4793 "cmDependsJavaParser.cxx" +#line 4805 "cmDependsJavaParser.cxx" break; case 220: /* ForUpdate: StatementExpressionList */ @@ -4801,7 +4813,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4805 "cmDependsJavaParser.cxx" +#line 4817 "cmDependsJavaParser.cxx" break; case 221: /* StatementExpressionList: StatementExpression */ @@ -4813,7 +4825,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4817 "cmDependsJavaParser.cxx" +#line 4829 "cmDependsJavaParser.cxx" break; case 222: /* StatementExpressionList: StatementExpressionList jp_COMMA StatementExpression */ @@ -4825,7 +4837,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4829 "cmDependsJavaParser.cxx" +#line 4841 "cmDependsJavaParser.cxx" break; case 223: /* AssertStatement: jp_ASSERT Expression jp_SEMICOL */ @@ -4837,7 +4849,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4841 "cmDependsJavaParser.cxx" +#line 4853 "cmDependsJavaParser.cxx" break; case 224: /* AssertStatement: jp_ASSERT Expression jp_COLON Expression jp_SEMICOL */ @@ -4849,7 +4861,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4853 "cmDependsJavaParser.cxx" +#line 4865 "cmDependsJavaParser.cxx" break; case 225: /* BreakStatement: jp_BREAK Identifieropt jp_SEMICOL */ @@ -4862,7 +4874,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4866 "cmDependsJavaParser.cxx" +#line 4878 "cmDependsJavaParser.cxx" break; case 226: /* Identifieropt: %empty */ @@ -4873,7 +4885,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4877 "cmDependsJavaParser.cxx" +#line 4889 "cmDependsJavaParser.cxx" break; case 227: /* Identifieropt: Identifier */ @@ -4882,7 +4894,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); } -#line 4886 "cmDependsJavaParser.cxx" +#line 4898 "cmDependsJavaParser.cxx" break; case 228: /* ContinueStatement: jp_CONTINUE Identifieropt jp_SEMICOL */ @@ -4895,7 +4907,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4899 "cmDependsJavaParser.cxx" +#line 4911 "cmDependsJavaParser.cxx" break; case 229: /* ReturnStatement: jp_RETURN Expressionopt jp_SEMICOL */ @@ -4907,7 +4919,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4911 "cmDependsJavaParser.cxx" +#line 4923 "cmDependsJavaParser.cxx" break; case 230: /* ThrowStatement: jp_THROW Expression jp_SEMICOL */ @@ -4919,7 +4931,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4923 "cmDependsJavaParser.cxx" +#line 4935 "cmDependsJavaParser.cxx" break; case 231: /* SynchronizedStatement: jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block */ @@ -4931,7 +4943,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4935 "cmDependsJavaParser.cxx" +#line 4947 "cmDependsJavaParser.cxx" break; case 232: /* TryStatement: jp_TRY Block Catches */ @@ -4943,7 +4955,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4947 "cmDependsJavaParser.cxx" +#line 4959 "cmDependsJavaParser.cxx" break; case 233: /* TryStatement: jp_TRY Block Catchesopt Finally */ @@ -4955,7 +4967,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4959 "cmDependsJavaParser.cxx" +#line 4971 "cmDependsJavaParser.cxx" break; case 234: /* Catchesopt: %empty */ @@ -4966,7 +4978,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4970 "cmDependsJavaParser.cxx" +#line 4982 "cmDependsJavaParser.cxx" break; case 235: /* Catchesopt: Catches */ @@ -4978,7 +4990,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4982 "cmDependsJavaParser.cxx" +#line 4994 "cmDependsJavaParser.cxx" break; case 236: /* Catches: CatchClause */ @@ -4990,7 +5002,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 4994 "cmDependsJavaParser.cxx" +#line 5006 "cmDependsJavaParser.cxx" break; case 237: /* Catches: Catches CatchClause */ @@ -5002,7 +5014,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5006 "cmDependsJavaParser.cxx" +#line 5018 "cmDependsJavaParser.cxx" break; case 238: /* CatchClause: jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block */ @@ -5011,7 +5023,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(5); } -#line 5015 "cmDependsJavaParser.cxx" +#line 5027 "cmDependsJavaParser.cxx" break; case 239: /* Finally: jp_FINALLY Block */ @@ -5023,7 +5035,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5027 "cmDependsJavaParser.cxx" +#line 5039 "cmDependsJavaParser.cxx" break; case 240: /* Primary: PrimaryNoNewArray */ @@ -5035,7 +5047,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5039 "cmDependsJavaParser.cxx" +#line 5051 "cmDependsJavaParser.cxx" break; case 241: /* Primary: ArrayCreationExpression */ @@ -5047,7 +5059,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5051 "cmDependsJavaParser.cxx" +#line 5063 "cmDependsJavaParser.cxx" break; case 242: /* PrimaryNoNewArray: Literal */ @@ -5059,7 +5071,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5063 "cmDependsJavaParser.cxx" +#line 5075 "cmDependsJavaParser.cxx" break; case 243: /* PrimaryNoNewArray: jp_THIS */ @@ -5068,7 +5080,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(1); } -#line 5072 "cmDependsJavaParser.cxx" +#line 5084 "cmDependsJavaParser.cxx" break; case 244: /* PrimaryNoNewArray: jp_PARESTART Expression jp_PAREEND */ @@ -5080,7 +5092,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5084 "cmDependsJavaParser.cxx" +#line 5096 "cmDependsJavaParser.cxx" break; case 245: /* PrimaryNoNewArray: ClassInstanceCreationExpression */ @@ -5092,7 +5104,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5096 "cmDependsJavaParser.cxx" +#line 5108 "cmDependsJavaParser.cxx" break; case 246: /* PrimaryNoNewArray: FieldAccess */ @@ -5104,7 +5116,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5108 "cmDependsJavaParser.cxx" +#line 5120 "cmDependsJavaParser.cxx" break; case 247: /* PrimaryNoNewArray: MethodInvocation */ @@ -5116,7 +5128,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5120 "cmDependsJavaParser.cxx" +#line 5132 "cmDependsJavaParser.cxx" break; case 248: /* PrimaryNoNewArray: ArrayAccess */ @@ -5128,7 +5140,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5132 "cmDependsJavaParser.cxx" +#line 5144 "cmDependsJavaParser.cxx" break; case 249: /* ClassInstanceCreationExpression: New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt */ @@ -5140,7 +5152,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5144 "cmDependsJavaParser.cxx" +#line 5156 "cmDependsJavaParser.cxx" break; case 250: /* ClassBodyOpt: %empty */ @@ -5151,7 +5163,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5155 "cmDependsJavaParser.cxx" +#line 5167 "cmDependsJavaParser.cxx" break; case 251: /* ClassBodyOpt: ClassBody */ @@ -5163,7 +5175,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5167 "cmDependsJavaParser.cxx" +#line 5179 "cmDependsJavaParser.cxx" break; case 252: /* ArgumentListopt: %empty */ @@ -5174,7 +5186,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5178 "cmDependsJavaParser.cxx" +#line 5190 "cmDependsJavaParser.cxx" break; case 253: /* ArgumentListopt: ArgumentList */ @@ -5186,7 +5198,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5190 "cmDependsJavaParser.cxx" +#line 5202 "cmDependsJavaParser.cxx" break; case 254: /* ArgumentList: Expression */ @@ -5198,7 +5210,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5202 "cmDependsJavaParser.cxx" +#line 5214 "cmDependsJavaParser.cxx" break; case 255: /* ArgumentList: ArgumentList jp_COMMA Expression */ @@ -5210,7 +5222,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5214 "cmDependsJavaParser.cxx" +#line 5226 "cmDependsJavaParser.cxx" break; case 256: /* ArrayCreationExpression: New PrimitiveType DimExprs Dimsopt */ @@ -5222,7 +5234,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5226 "cmDependsJavaParser.cxx" +#line 5238 "cmDependsJavaParser.cxx" break; case 257: /* ArrayCreationExpression: New ClassOrInterfaceType DimExprs Dimsopt */ @@ -5234,7 +5246,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5238 "cmDependsJavaParser.cxx" +#line 5250 "cmDependsJavaParser.cxx" break; case 258: /* ArrayCreationExpression: New PrimitiveType Dims ArrayInitializer */ @@ -5246,7 +5258,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5250 "cmDependsJavaParser.cxx" +#line 5262 "cmDependsJavaParser.cxx" break; case 259: /* ArrayCreationExpression: New ClassOrInterfaceType Dims ArrayInitializer */ @@ -5258,7 +5270,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5262 "cmDependsJavaParser.cxx" +#line 5274 "cmDependsJavaParser.cxx" break; case 260: /* Dimsopt: %empty */ @@ -5269,7 +5281,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5273 "cmDependsJavaParser.cxx" +#line 5285 "cmDependsJavaParser.cxx" break; case 261: /* Dimsopt: Dims */ @@ -5281,7 +5293,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5285 "cmDependsJavaParser.cxx" +#line 5297 "cmDependsJavaParser.cxx" break; case 262: /* DimExprs: DimExpr */ @@ -5293,7 +5305,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5297 "cmDependsJavaParser.cxx" +#line 5309 "cmDependsJavaParser.cxx" break; case 263: /* DimExprs: DimExprs DimExpr */ @@ -5305,7 +5317,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5309 "cmDependsJavaParser.cxx" +#line 5321 "cmDependsJavaParser.cxx" break; case 264: /* DimExpr: jp_BRACKETSTART Expression jp_BRACKETEND */ @@ -5317,7 +5329,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5321 "cmDependsJavaParser.cxx" +#line 5333 "cmDependsJavaParser.cxx" break; case 265: /* Dims: jp_BRACKETSTART jp_BRACKETEND */ @@ -5326,7 +5338,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(2); } -#line 5330 "cmDependsJavaParser.cxx" +#line 5342 "cmDependsJavaParser.cxx" break; case 266: /* Dims: Dims jp_BRACKETSTART jp_BRACKETEND */ @@ -5335,7 +5347,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(3); } -#line 5339 "cmDependsJavaParser.cxx" +#line 5351 "cmDependsJavaParser.cxx" break; case 267: /* FieldAccess: Primary jp_DOT Identifier */ @@ -5348,7 +5360,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5352 "cmDependsJavaParser.cxx" +#line 5364 "cmDependsJavaParser.cxx" break; case 268: /* FieldAccess: jp_SUPER jp_DOT Identifier */ @@ -5361,7 +5373,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5365 "cmDependsJavaParser.cxx" +#line 5377 "cmDependsJavaParser.cxx" break; case 269: /* FieldAccess: jp_THIS jp_DOT Identifier */ @@ -5374,7 +5386,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5378 "cmDependsJavaParser.cxx" +#line 5390 "cmDependsJavaParser.cxx" break; case 270: /* FieldAccess: Primary jp_DOT jp_THIS */ @@ -5387,7 +5399,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5391 "cmDependsJavaParser.cxx" +#line 5403 "cmDependsJavaParser.cxx" break; case 271: /* MethodInvocation: Name jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5400,7 +5412,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5404 "cmDependsJavaParser.cxx" +#line 5416 "cmDependsJavaParser.cxx" break; case 272: /* MethodInvocation: Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5414,7 +5426,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5418 "cmDependsJavaParser.cxx" +#line 5430 "cmDependsJavaParser.cxx" break; case 273: /* MethodInvocation: jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5427,7 +5439,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5431 "cmDependsJavaParser.cxx" +#line 5443 "cmDependsJavaParser.cxx" break; case 274: /* MethodInvocation: jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */ @@ -5440,7 +5452,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5444 "cmDependsJavaParser.cxx" +#line 5456 "cmDependsJavaParser.cxx" break; case 275: /* ArrayAccess: Name jp_BRACKETSTART Expression jp_BRACKETEND */ @@ -5453,7 +5465,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5457 "cmDependsJavaParser.cxx" +#line 5469 "cmDependsJavaParser.cxx" break; case 276: /* ArrayAccess: PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND */ @@ -5465,7 +5477,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5469 "cmDependsJavaParser.cxx" +#line 5481 "cmDependsJavaParser.cxx" break; case 277: /* PostfixExpression: Primary */ @@ -5477,7 +5489,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5481 "cmDependsJavaParser.cxx" +#line 5493 "cmDependsJavaParser.cxx" break; case 278: /* PostfixExpression: Name */ @@ -5489,7 +5501,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5493 "cmDependsJavaParser.cxx" +#line 5505 "cmDependsJavaParser.cxx" break; case 279: /* PostfixExpression: ArrayType jp_DOT jp_CLASS */ @@ -5501,7 +5513,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5505 "cmDependsJavaParser.cxx" +#line 5517 "cmDependsJavaParser.cxx" break; case 280: /* PostfixExpression: PostIncrementExpression */ @@ -5513,7 +5525,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5517 "cmDependsJavaParser.cxx" +#line 5529 "cmDependsJavaParser.cxx" break; case 281: /* PostfixExpression: PostDecrementExpression */ @@ -5525,7 +5537,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5529 "cmDependsJavaParser.cxx" +#line 5541 "cmDependsJavaParser.cxx" break; case 282: /* PostIncrementExpression: PostfixExpression jp_PLUSPLUS */ @@ -5537,7 +5549,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5541 "cmDependsJavaParser.cxx" +#line 5553 "cmDependsJavaParser.cxx" break; case 283: /* PostDecrementExpression: PostfixExpression jp_MINUSMINUS */ @@ -5549,7 +5561,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5553 "cmDependsJavaParser.cxx" +#line 5565 "cmDependsJavaParser.cxx" break; case 284: /* UnaryExpression: PreIncrementExpression */ @@ -5561,7 +5573,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5565 "cmDependsJavaParser.cxx" +#line 5577 "cmDependsJavaParser.cxx" break; case 285: /* UnaryExpression: PreDecrementExpression */ @@ -5573,7 +5585,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5577 "cmDependsJavaParser.cxx" +#line 5589 "cmDependsJavaParser.cxx" break; case 286: /* UnaryExpression: jp_PLUS UnaryExpression */ @@ -5585,7 +5597,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5589 "cmDependsJavaParser.cxx" +#line 5601 "cmDependsJavaParser.cxx" break; case 287: /* UnaryExpression: jp_MINUS UnaryExpression */ @@ -5597,7 +5609,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5601 "cmDependsJavaParser.cxx" +#line 5613 "cmDependsJavaParser.cxx" break; case 288: /* UnaryExpression: UnaryExpressionNotPlusMinus */ @@ -5609,7 +5621,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5613 "cmDependsJavaParser.cxx" +#line 5625 "cmDependsJavaParser.cxx" break; case 289: /* PreIncrementExpression: jp_PLUSPLUS UnaryExpression */ @@ -5621,7 +5633,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5625 "cmDependsJavaParser.cxx" +#line 5637 "cmDependsJavaParser.cxx" break; case 290: /* PreDecrementExpression: jp_MINUSMINUS UnaryExpression */ @@ -5633,7 +5645,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5637 "cmDependsJavaParser.cxx" +#line 5649 "cmDependsJavaParser.cxx" break; case 291: /* UnaryExpressionNotPlusMinus: PostfixExpression */ @@ -5645,7 +5657,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5649 "cmDependsJavaParser.cxx" +#line 5661 "cmDependsJavaParser.cxx" break; case 292: /* UnaryExpressionNotPlusMinus: jp_TILDE UnaryExpression */ @@ -5657,7 +5669,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5661 "cmDependsJavaParser.cxx" +#line 5673 "cmDependsJavaParser.cxx" break; case 293: /* UnaryExpressionNotPlusMinus: jp_EXCLAMATION UnaryExpression */ @@ -5669,7 +5681,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5673 "cmDependsJavaParser.cxx" +#line 5685 "cmDependsJavaParser.cxx" break; case 294: /* UnaryExpressionNotPlusMinus: CastExpression */ @@ -5681,7 +5693,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5685 "cmDependsJavaParser.cxx" +#line 5697 "cmDependsJavaParser.cxx" break; case 295: /* CastExpression: jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression */ @@ -5693,7 +5705,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5697 "cmDependsJavaParser.cxx" +#line 5709 "cmDependsJavaParser.cxx" break; case 296: /* CastExpression: jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus */ @@ -5705,7 +5717,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5709 "cmDependsJavaParser.cxx" +#line 5721 "cmDependsJavaParser.cxx" break; case 297: /* CastExpression: jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus */ @@ -5714,7 +5726,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); jpElementStart(5); } -#line 5718 "cmDependsJavaParser.cxx" +#line 5730 "cmDependsJavaParser.cxx" break; case 298: /* MultiplicativeExpression: UnaryExpression */ @@ -5726,7 +5738,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5730 "cmDependsJavaParser.cxx" +#line 5742 "cmDependsJavaParser.cxx" break; case 299: /* MultiplicativeExpression: MultiplicativeExpression jp_TIMES UnaryExpression */ @@ -5738,7 +5750,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5742 "cmDependsJavaParser.cxx" +#line 5754 "cmDependsJavaParser.cxx" break; case 300: /* MultiplicativeExpression: MultiplicativeExpression jp_DIVIDE UnaryExpression */ @@ -5750,7 +5762,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5754 "cmDependsJavaParser.cxx" +#line 5766 "cmDependsJavaParser.cxx" break; case 301: /* MultiplicativeExpression: MultiplicativeExpression jp_PERCENT UnaryExpression */ @@ -5762,7 +5774,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5766 "cmDependsJavaParser.cxx" +#line 5778 "cmDependsJavaParser.cxx" break; case 302: /* AdditiveExpression: MultiplicativeExpression */ @@ -5774,7 +5786,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5778 "cmDependsJavaParser.cxx" +#line 5790 "cmDependsJavaParser.cxx" break; case 303: /* AdditiveExpression: AdditiveExpression jp_PLUS MultiplicativeExpression */ @@ -5786,7 +5798,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5790 "cmDependsJavaParser.cxx" +#line 5802 "cmDependsJavaParser.cxx" break; case 304: /* AdditiveExpression: AdditiveExpression jp_MINUS MultiplicativeExpression */ @@ -5798,7 +5810,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5802 "cmDependsJavaParser.cxx" +#line 5814 "cmDependsJavaParser.cxx" break; case 305: /* ShiftExpression: AdditiveExpression */ @@ -5810,7 +5822,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5814 "cmDependsJavaParser.cxx" +#line 5826 "cmDependsJavaParser.cxx" break; case 306: /* ShiftExpression: ShiftExpression jp_LTLT AdditiveExpression */ @@ -5822,7 +5834,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5826 "cmDependsJavaParser.cxx" +#line 5838 "cmDependsJavaParser.cxx" break; case 307: /* ShiftExpression: ShiftExpression jp_GTGT AdditiveExpression */ @@ -5834,7 +5846,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5838 "cmDependsJavaParser.cxx" +#line 5850 "cmDependsJavaParser.cxx" break; case 308: /* ShiftExpression: ShiftExpression jp_GTGTGT AdditiveExpression */ @@ -5846,7 +5858,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5850 "cmDependsJavaParser.cxx" +#line 5862 "cmDependsJavaParser.cxx" break; case 309: /* RelationalExpression: ShiftExpression */ @@ -5858,7 +5870,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5862 "cmDependsJavaParser.cxx" +#line 5874 "cmDependsJavaParser.cxx" break; case 310: /* RelationalExpression: RelationalExpression jp_LESSTHAN ShiftExpression */ @@ -5870,7 +5882,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5874 "cmDependsJavaParser.cxx" +#line 5886 "cmDependsJavaParser.cxx" break; case 311: /* RelationalExpression: RelationalExpression jp_GREATER ShiftExpression */ @@ -5882,7 +5894,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5886 "cmDependsJavaParser.cxx" +#line 5898 "cmDependsJavaParser.cxx" break; case 312: /* RelationalExpression: RelationalExpression jp_LTEQUALS ShiftExpression */ @@ -5894,7 +5906,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5898 "cmDependsJavaParser.cxx" +#line 5910 "cmDependsJavaParser.cxx" break; case 313: /* RelationalExpression: RelationalExpression jp_GTEQUALS ShiftExpression */ @@ -5906,7 +5918,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5910 "cmDependsJavaParser.cxx" +#line 5922 "cmDependsJavaParser.cxx" break; case 314: /* RelationalExpression: RelationalExpression jp_INSTANCEOF ReferenceType */ @@ -5918,7 +5930,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5922 "cmDependsJavaParser.cxx" +#line 5934 "cmDependsJavaParser.cxx" break; case 315: /* EqualityExpression: RelationalExpression */ @@ -5930,7 +5942,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5934 "cmDependsJavaParser.cxx" +#line 5946 "cmDependsJavaParser.cxx" break; case 316: /* EqualityExpression: EqualityExpression jp_EQUALSEQUALS RelationalExpression */ @@ -5942,7 +5954,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5946 "cmDependsJavaParser.cxx" +#line 5958 "cmDependsJavaParser.cxx" break; case 317: /* EqualityExpression: EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression */ @@ -5954,7 +5966,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5958 "cmDependsJavaParser.cxx" +#line 5970 "cmDependsJavaParser.cxx" break; case 318: /* AndExpression: EqualityExpression */ @@ -5966,7 +5978,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5970 "cmDependsJavaParser.cxx" +#line 5982 "cmDependsJavaParser.cxx" break; case 319: /* AndExpression: AndExpression jp_AND EqualityExpression */ @@ -5978,7 +5990,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5982 "cmDependsJavaParser.cxx" +#line 5994 "cmDependsJavaParser.cxx" break; case 320: /* ExclusiveOrExpression: AndExpression */ @@ -5990,7 +6002,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 5994 "cmDependsJavaParser.cxx" +#line 6006 "cmDependsJavaParser.cxx" break; case 321: /* ExclusiveOrExpression: ExclusiveOrExpression jp_CARROT AndExpression */ @@ -6002,7 +6014,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6006 "cmDependsJavaParser.cxx" +#line 6018 "cmDependsJavaParser.cxx" break; case 322: /* InclusiveOrExpression: ExclusiveOrExpression */ @@ -6014,7 +6026,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6018 "cmDependsJavaParser.cxx" +#line 6030 "cmDependsJavaParser.cxx" break; case 323: /* InclusiveOrExpression: InclusiveOrExpression jp_PIPE ExclusiveOrExpression */ @@ -6026,7 +6038,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6030 "cmDependsJavaParser.cxx" +#line 6042 "cmDependsJavaParser.cxx" break; case 324: /* ConditionalAndExpression: InclusiveOrExpression */ @@ -6038,7 +6050,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6042 "cmDependsJavaParser.cxx" +#line 6054 "cmDependsJavaParser.cxx" break; case 325: /* ConditionalAndExpression: ConditionalAndExpression jp_ANDAND InclusiveOrExpression */ @@ -6050,7 +6062,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6054 "cmDependsJavaParser.cxx" +#line 6066 "cmDependsJavaParser.cxx" break; case 326: /* ConditionalOrExpression: ConditionalAndExpression */ @@ -6062,7 +6074,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6066 "cmDependsJavaParser.cxx" +#line 6078 "cmDependsJavaParser.cxx" break; case 327: /* ConditionalOrExpression: ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression */ @@ -6074,7 +6086,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6078 "cmDependsJavaParser.cxx" +#line 6090 "cmDependsJavaParser.cxx" break; case 328: /* ConditionalExpression: ConditionalOrExpression */ @@ -6086,7 +6098,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6090 "cmDependsJavaParser.cxx" +#line 6102 "cmDependsJavaParser.cxx" break; case 329: /* ConditionalExpression: ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression */ @@ -6098,7 +6110,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6102 "cmDependsJavaParser.cxx" +#line 6114 "cmDependsJavaParser.cxx" break; case 330: /* AssignmentExpression: ConditionalExpression */ @@ -6110,7 +6122,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6114 "cmDependsJavaParser.cxx" +#line 6126 "cmDependsJavaParser.cxx" break; case 331: /* AssignmentExpression: Assignment */ @@ -6122,7 +6134,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6126 "cmDependsJavaParser.cxx" +#line 6138 "cmDependsJavaParser.cxx" break; case 332: /* Assignment: LeftHandSide AssignmentOperator AssignmentExpression */ @@ -6134,7 +6146,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6138 "cmDependsJavaParser.cxx" +#line 6150 "cmDependsJavaParser.cxx" break; case 333: /* LeftHandSide: Name */ @@ -6147,7 +6159,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6151 "cmDependsJavaParser.cxx" +#line 6163 "cmDependsJavaParser.cxx" break; case 334: /* LeftHandSide: FieldAccess */ @@ -6159,7 +6171,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6163 "cmDependsJavaParser.cxx" +#line 6175 "cmDependsJavaParser.cxx" break; case 335: /* LeftHandSide: ArrayAccess */ @@ -6171,7 +6183,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6175 "cmDependsJavaParser.cxx" +#line 6187 "cmDependsJavaParser.cxx" break; case 336: /* AssignmentOperator: jp_EQUALS */ @@ -6183,7 +6195,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6187 "cmDependsJavaParser.cxx" +#line 6199 "cmDependsJavaParser.cxx" break; case 337: /* AssignmentOperator: jp_TIMESEQUALS */ @@ -6195,7 +6207,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6199 "cmDependsJavaParser.cxx" +#line 6211 "cmDependsJavaParser.cxx" break; case 338: /* AssignmentOperator: jp_DIVIDEEQUALS */ @@ -6207,7 +6219,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6211 "cmDependsJavaParser.cxx" +#line 6223 "cmDependsJavaParser.cxx" break; case 339: /* AssignmentOperator: jp_PERCENTEQUALS */ @@ -6219,7 +6231,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6223 "cmDependsJavaParser.cxx" +#line 6235 "cmDependsJavaParser.cxx" break; case 340: /* AssignmentOperator: jp_PLUSEQUALS */ @@ -6231,7 +6243,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6235 "cmDependsJavaParser.cxx" +#line 6247 "cmDependsJavaParser.cxx" break; case 341: /* AssignmentOperator: jp_MINUSEQUALS */ @@ -6243,7 +6255,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6247 "cmDependsJavaParser.cxx" +#line 6259 "cmDependsJavaParser.cxx" break; case 342: /* AssignmentOperator: jp_LESLESEQUALS */ @@ -6255,7 +6267,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6259 "cmDependsJavaParser.cxx" +#line 6271 "cmDependsJavaParser.cxx" break; case 343: /* AssignmentOperator: jp_GTGTEQUALS */ @@ -6267,7 +6279,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6271 "cmDependsJavaParser.cxx" +#line 6283 "cmDependsJavaParser.cxx" break; case 344: /* AssignmentOperator: jp_GTGTGTEQUALS */ @@ -6279,7 +6291,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6283 "cmDependsJavaParser.cxx" +#line 6295 "cmDependsJavaParser.cxx" break; case 345: /* AssignmentOperator: jp_ANDEQUALS */ @@ -6291,7 +6303,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6295 "cmDependsJavaParser.cxx" +#line 6307 "cmDependsJavaParser.cxx" break; case 346: /* AssignmentOperator: jp_CARROTEQUALS */ @@ -6303,7 +6315,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6307 "cmDependsJavaParser.cxx" +#line 6319 "cmDependsJavaParser.cxx" break; case 347: /* AssignmentOperator: jp_PIPEEQUALS */ @@ -6315,7 +6327,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6319 "cmDependsJavaParser.cxx" +#line 6331 "cmDependsJavaParser.cxx" break; case 348: /* Expression: AssignmentExpression */ @@ -6327,7 +6339,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6331 "cmDependsJavaParser.cxx" +#line 6343 "cmDependsJavaParser.cxx" break; case 349: /* ConstantExpression: Expression */ @@ -6339,7 +6351,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6343 "cmDependsJavaParser.cxx" +#line 6355 "cmDependsJavaParser.cxx" break; case 350: /* New: jp_NEW */ @@ -6351,7 +6363,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6355 "cmDependsJavaParser.cxx" +#line 6367 "cmDependsJavaParser.cxx" break; case 351: /* New: Name jp_DOT jp_NEW */ @@ -6364,11 +6376,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yyGetParser->SetCurrentCombine(""); } -#line 6368 "cmDependsJavaParser.cxx" +#line 6380 "cmDependsJavaParser.cxx" break; -#line 6372 "cmDependsJavaParser.cxx" +#line 6384 "cmDependsJavaParser.cxx" default: break; } diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h index 4ae55fa3bcb..885cc66e749 100644 --- a/Source/LexerParser/cmDependsJavaParserTokens.h +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index b747d8b13ec..38b449fe73a 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -218,6 +218,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -315,9 +327,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -629,7 +641,7 @@ static const yytype_int8 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 6, 7, 8, 9, 10, 11, 12, 13, 14 + 0, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -754,8 +766,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -763,7 +775,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1144,14 +1156,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1425,7 +1437,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1429 "cmExprParser.cxx" +#line 1441 "cmExprParser.cxx" break; case 3: /* exp: bitwiseor */ @@ -1433,7 +1445,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1437 "cmExprParser.cxx" +#line 1449 "cmExprParser.cxx" break; case 4: /* exp: exp exp_OR bitwiseor */ @@ -1441,7 +1453,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1445 "cmExprParser.cxx" +#line 1457 "cmExprParser.cxx" break; case 5: /* bitwiseor: bitwisexor */ @@ -1449,7 +1461,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1453 "cmExprParser.cxx" +#line 1465 "cmExprParser.cxx" break; case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */ @@ -1457,7 +1469,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1461 "cmExprParser.cxx" +#line 1473 "cmExprParser.cxx" break; case 7: /* bitwisexor: bitwiseand */ @@ -1465,7 +1477,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1469 "cmExprParser.cxx" +#line 1481 "cmExprParser.cxx" break; case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */ @@ -1473,7 +1485,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1477 "cmExprParser.cxx" +#line 1489 "cmExprParser.cxx" break; case 9: /* bitwiseand: shift */ @@ -1481,7 +1493,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1485 "cmExprParser.cxx" +#line 1497 "cmExprParser.cxx" break; case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */ @@ -1489,7 +1501,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1493 "cmExprParser.cxx" +#line 1505 "cmExprParser.cxx" break; case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */ @@ -1497,7 +1509,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1501 "cmExprParser.cxx" +#line 1513 "cmExprParser.cxx" break; case 12: /* shift: term */ @@ -1505,7 +1517,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1509 "cmExprParser.cxx" +#line 1521 "cmExprParser.cxx" break; case 13: /* shift: shift exp_PLUS term */ @@ -1513,7 +1525,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1517 "cmExprParser.cxx" +#line 1529 "cmExprParser.cxx" break; case 14: /* shift: shift exp_MINUS term */ @@ -1521,7 +1533,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1525 "cmExprParser.cxx" +#line 1537 "cmExprParser.cxx" break; case 15: /* term: unary */ @@ -1529,7 +1541,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1533 "cmExprParser.cxx" +#line 1545 "cmExprParser.cxx" break; case 16: /* term: term exp_TIMES unary */ @@ -1537,7 +1549,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1541 "cmExprParser.cxx" +#line 1553 "cmExprParser.cxx" break; case 17: /* term: term exp_DIVIDE unary */ @@ -1548,7 +1560,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1552 "cmExprParser.cxx" +#line 1564 "cmExprParser.cxx" break; case 18: /* term: term exp_MOD unary */ @@ -1556,7 +1568,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1560 "cmExprParser.cxx" +#line 1572 "cmExprParser.cxx" break; case 19: /* unary: factor */ @@ -1564,7 +1576,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1568 "cmExprParser.cxx" +#line 1580 "cmExprParser.cxx" break; case 20: /* unary: exp_PLUS unary */ @@ -1572,7 +1584,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = + (yyvsp[0].Number); } -#line 1576 "cmExprParser.cxx" +#line 1588 "cmExprParser.cxx" break; case 21: /* unary: exp_MINUS unary */ @@ -1580,7 +1592,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = - (yyvsp[0].Number); } -#line 1584 "cmExprParser.cxx" +#line 1596 "cmExprParser.cxx" break; case 22: /* unary: exp_NOT unary */ @@ -1588,7 +1600,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1592 "cmExprParser.cxx" +#line 1604 "cmExprParser.cxx" break; case 23: /* factor: exp_NUMBER */ @@ -1596,7 +1608,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[0].Number); } -#line 1600 "cmExprParser.cxx" +#line 1612 "cmExprParser.cxx" break; case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */ @@ -1604,11 +1616,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); { (yyval.Number) = (yyvsp[-1].Number); } -#line 1608 "cmExprParser.cxx" +#line 1620 "cmExprParser.cxx" break; -#line 1612 "cmExprParser.cxx" +#line 1624 "cmExprParser.cxx" default: break; } diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h index 2eb1fe928ab..67b03def95a 100644 --- a/Source/LexerParser/cmExprParserTokens.h +++ b/Source/LexerParser/cmExprParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index dba2cac13b1..0ea3d971e6a 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -46,10 +46,10 @@ USER NAME SPACE" below. */ /* Identify Bison output, and Bison version. */ -#define YYBISON 30704 +#define YYBISON 30705 /* Bison version string. */ -#define YYBISON_VERSION "3.7.4" +#define YYBISON_VERSION "3.7.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -259,6 +259,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -356,9 +368,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -701,7 +713,7 @@ static const yytype_int8 yypgoto[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 1, 32, 33, 34, 35, 36, 37, 38, 39, + 0, 1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 82 }; @@ -955,8 +967,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yyscanner); + YY_USE (yyoutput); + YY_USE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT @@ -964,7 +976,7 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1345,14 +1357,14 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yyscanner); + YY_USE (yyvaluep); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1627,7 +1639,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1631 "cmFortranParser.cxx" +#line 1643 "cmFortranParser.cxx" break; case 5: /* stmt: USE WORD other EOSTMT */ @@ -1637,7 +1649,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1641 "cmFortranParser.cxx" +#line 1653 "cmFortranParser.cxx" break; case 6: /* stmt: MODULE WORD other EOSTMT */ @@ -1651,7 +1663,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); } free((yyvsp[-2].string)); } -#line 1655 "cmFortranParser.cxx" +#line 1667 "cmFortranParser.cxx" break; case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */ @@ -1662,7 +1674,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1666 "cmFortranParser.cxx" +#line 1678 "cmFortranParser.cxx" break; case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */ @@ -1674,7 +1686,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1678 "cmFortranParser.cxx" +#line 1690 "cmFortranParser.cxx" break; case 9: /* stmt: INTERFACE WORD other EOSTMT */ @@ -1684,7 +1696,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1688 "cmFortranParser.cxx" +#line 1700 "cmFortranParser.cxx" break; case 10: /* stmt: END INTERFACE other EOSTMT */ @@ -1693,7 +1705,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1697 "cmFortranParser.cxx" +#line 1709 "cmFortranParser.cxx" break; case 11: /* stmt: USE DCOLON WORD other EOSTMT */ @@ -1703,7 +1715,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1707 "cmFortranParser.cxx" +#line 1719 "cmFortranParser.cxx" break; case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */ @@ -1716,7 +1728,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1720 "cmFortranParser.cxx" +#line 1732 "cmFortranParser.cxx" break; case 13: /* stmt: INCLUDE STRING other EOSTMT */ @@ -1726,7 +1738,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1730 "cmFortranParser.cxx" +#line 1742 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ @@ -1736,7 +1748,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1740 "cmFortranParser.cxx" +#line 1752 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ @@ -1746,7 +1758,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1750 "cmFortranParser.cxx" +#line 1762 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ @@ -1756,7 +1768,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1760 "cmFortranParser.cxx" +#line 1772 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ @@ -1766,7 +1778,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1770 "cmFortranParser.cxx" +#line 1782 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ @@ -1776,7 +1788,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1780 "cmFortranParser.cxx" +#line 1792 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ @@ -1786,7 +1798,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1790 "cmFortranParser.cxx" +#line 1802 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ @@ -1796,7 +1808,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1800 "cmFortranParser.cxx" +#line 1812 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ @@ -1805,7 +1817,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1809 "cmFortranParser.cxx" +#line 1821 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ @@ -1814,7 +1826,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1818 "cmFortranParser.cxx" +#line 1830 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ @@ -1823,7 +1835,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1827 "cmFortranParser.cxx" +#line 1839 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ @@ -1832,23 +1844,23 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1836 "cmFortranParser.cxx" +#line 1848 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ #line 229 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1842 "cmFortranParser.cxx" +#line 1854 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ #line 236 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1848 "cmFortranParser.cxx" +#line 1860 "cmFortranParser.cxx" break; -#line 1852 "cmFortranParser.cxx" +#line 1864 "cmFortranParser.cxx" default: break; } diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index e250110c0c5..3a19cfb1d93 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.7.4. */ +/* A Bison parser, made by GNU Bison 3.7.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify From 16275c7f82180b2c6f207d2dc9a6f4187ae2e486 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 27 Apr 2021 10:02:30 -0400 Subject: [PATCH 0320/1519] LexerParser: Suppress NVHPC warnings in generated code --- Source/LexerParser/cmExprParser.cxx | 108 ++++++++++++++-------------- Source/LexerParser/cmExprParser.y | 4 ++ Source/cmStandardLexer.h | 5 ++ 3 files changed, 65 insertions(+), 52 deletions(-) diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index 38b449fe73a..d9b0ae3ca1a 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -120,7 +120,11 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # endif #endif -#line 124 "cmExprParser.cxx" +#if defined(__NVCOMPILER) +# pragma diag_suppress 550 /* variable set but never used */ +#endif + +#line 128 "cmExprParser.cxx" # ifndef YY_CAST # ifdef __cplusplus @@ -556,9 +560,9 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 81, 81, 86, 89, 94, 97, 102, 105, 110, - 113, 116, 121, 124, 127, 132, 135, 138, 144, 149, - 152, 155, 158, 163, 166 + 0, 85, 85, 90, 93, 98, 101, 106, 109, 114, + 117, 120, 125, 128, 131, 136, 139, 142, 148, 153, + 156, 159, 162, 167, 170 }; #endif @@ -1433,194 +1437,194 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); switch (yyn) { case 2: /* start: exp */ -#line 81 "cmExprParser.y" +#line 85 "cmExprParser.y" { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1441 "cmExprParser.cxx" +#line 1445 "cmExprParser.cxx" break; case 3: /* exp: bitwiseor */ -#line 86 "cmExprParser.y" +#line 90 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1449 "cmExprParser.cxx" +#line 1453 "cmExprParser.cxx" break; case 4: /* exp: exp exp_OR bitwiseor */ -#line 89 "cmExprParser.y" +#line 93 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1457 "cmExprParser.cxx" +#line 1461 "cmExprParser.cxx" break; case 5: /* bitwiseor: bitwisexor */ -#line 94 "cmExprParser.y" +#line 98 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1465 "cmExprParser.cxx" +#line 1469 "cmExprParser.cxx" break; case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */ -#line 97 "cmExprParser.y" +#line 101 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1473 "cmExprParser.cxx" +#line 1477 "cmExprParser.cxx" break; case 7: /* bitwisexor: bitwiseand */ -#line 102 "cmExprParser.y" +#line 106 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1481 "cmExprParser.cxx" +#line 1485 "cmExprParser.cxx" break; case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */ -#line 105 "cmExprParser.y" +#line 109 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1489 "cmExprParser.cxx" +#line 1493 "cmExprParser.cxx" break; case 9: /* bitwiseand: shift */ -#line 110 "cmExprParser.y" +#line 114 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1497 "cmExprParser.cxx" +#line 1501 "cmExprParser.cxx" break; case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */ -#line 113 "cmExprParser.y" +#line 117 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1505 "cmExprParser.cxx" +#line 1509 "cmExprParser.cxx" break; case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */ -#line 116 "cmExprParser.y" +#line 120 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1513 "cmExprParser.cxx" +#line 1517 "cmExprParser.cxx" break; case 12: /* shift: term */ -#line 121 "cmExprParser.y" +#line 125 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1521 "cmExprParser.cxx" +#line 1525 "cmExprParser.cxx" break; case 13: /* shift: shift exp_PLUS term */ -#line 124 "cmExprParser.y" +#line 128 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1529 "cmExprParser.cxx" +#line 1533 "cmExprParser.cxx" break; case 14: /* shift: shift exp_MINUS term */ -#line 127 "cmExprParser.y" +#line 131 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1537 "cmExprParser.cxx" +#line 1541 "cmExprParser.cxx" break; case 15: /* term: unary */ -#line 132 "cmExprParser.y" +#line 136 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1545 "cmExprParser.cxx" +#line 1549 "cmExprParser.cxx" break; case 16: /* term: term exp_TIMES unary */ -#line 135 "cmExprParser.y" +#line 139 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1553 "cmExprParser.cxx" +#line 1557 "cmExprParser.cxx" break; case 17: /* term: term exp_DIVIDE unary */ -#line 138 "cmExprParser.y" +#line 142 "cmExprParser.y" { if (yyvsp[0].Number == 0) { throw std::overflow_error("divide by zero"); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1564 "cmExprParser.cxx" +#line 1568 "cmExprParser.cxx" break; case 18: /* term: term exp_MOD unary */ -#line 144 "cmExprParser.y" +#line 148 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1572 "cmExprParser.cxx" +#line 1576 "cmExprParser.cxx" break; case 19: /* unary: factor */ -#line 149 "cmExprParser.y" +#line 153 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1580 "cmExprParser.cxx" +#line 1584 "cmExprParser.cxx" break; case 20: /* unary: exp_PLUS unary */ -#line 152 "cmExprParser.y" +#line 156 "cmExprParser.y" { (yyval.Number) = + (yyvsp[0].Number); } -#line 1588 "cmExprParser.cxx" +#line 1592 "cmExprParser.cxx" break; case 21: /* unary: exp_MINUS unary */ -#line 155 "cmExprParser.y" +#line 159 "cmExprParser.y" { (yyval.Number) = - (yyvsp[0].Number); } -#line 1596 "cmExprParser.cxx" +#line 1600 "cmExprParser.cxx" break; case 22: /* unary: exp_NOT unary */ -#line 158 "cmExprParser.y" +#line 162 "cmExprParser.y" { (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1604 "cmExprParser.cxx" +#line 1608 "cmExprParser.cxx" break; case 23: /* factor: exp_NUMBER */ -#line 163 "cmExprParser.y" +#line 167 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1612 "cmExprParser.cxx" +#line 1616 "cmExprParser.cxx" break; case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */ -#line 166 "cmExprParser.y" +#line 170 "cmExprParser.y" { (yyval.Number) = (yyvsp[-1].Number); } -#line 1620 "cmExprParser.cxx" +#line 1624 "cmExprParser.cxx" break; -#line 1624 "cmExprParser.cxx" +#line 1628 "cmExprParser.cxx" default: break; } @@ -1845,7 +1849,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); return yyresult; } -#line 171 "cmExprParser.y" +#line 175 "cmExprParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y index b49f48212c7..fda2395b0d8 100644 --- a/Source/LexerParser/cmExprParser.y +++ b/Source/LexerParser/cmExprParser.y @@ -44,6 +44,10 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma clang diagnostic ignored "-Wused-but-marked-unused" # endif #endif + +#if defined(__NVCOMPILER) +# pragma diag_suppress 550 /* variable set but never used */ +#endif %} /* Generate a reentrant parser object. */ diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h index b871f5fca56..417f14d810b 100644 --- a/Source/cmStandardLexer.h +++ b/Source/cmStandardLexer.h @@ -50,6 +50,11 @@ # endif #endif +#if defined(__NVCOMPILER) +# pragma diag_suppress 111 /* statement is unreachable */ +# pragma diag_suppress 550 /* variable set but never used */ +#endif + /* Make sure isatty is available. */ #if defined(_WIN32) && !defined(__CYGWIN__) # include From 6a003c6f355776343157f2437b8cabbc003c2adf Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Apr 2021 11:18:46 -0400 Subject: [PATCH 0321/1519] cmSystemTools: Avoid unreachable code warning on NVHPC --- Source/cmSystemTools.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 5382fac250a..281f6c9b350 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1797,7 +1797,7 @@ bool copy_data(struct archive* ar, struct archive* aw) return false; } } -# if !defined(__clang__) && !defined(__HP_aCC) +# if !defined(__clang__) && !defined(__NVCOMPILER) && !defined(__HP_aCC) return false; /* this should not happen but it quiets some compilers */ # endif } From 1898f9dd827fc6d74b4689c1ea6e59e9344ae415 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Apr 2021 11:20:53 -0400 Subject: [PATCH 0322/1519] cmFileCommand: Remove unused local variable --- Source/cmFileCommand.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index a94325834dc..1088347f103 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1490,9 +1490,6 @@ bool HandleCopyFile(std::vector const& args, bool HandleRemoveImpl(std::vector const& args, bool recurse, cmExecutionStatus& status) { - - std::string message; - for (std::string const& arg : cmMakeRange(args).advance(1)) // Get rid of subcommand { From 5ad88623180d0a031512c813936f6a6bae49740c Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Apr 2021 11:23:12 -0400 Subject: [PATCH 0323/1519] Source: Convince NVHPC that RAII variables are used --- Source/cmLoadCommandCommand.cxx | 9 +++++++++ Source/cmQtAutoMocUic.cxx | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 2981ef877e0..2456db9fe83 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -90,6 +90,9 @@ struct LoadedCommandImpl : cmLoadedCommandInfo { if (this->Destructor) { SignalHandlerGuard guard(this->Name); +#if defined(__NVCOMPILER) + static_cast(guard); // convince compiler var is used +#endif this->Destructor(this); } if (this->Error != nullptr) { @@ -103,12 +106,18 @@ struct LoadedCommandImpl : cmLoadedCommandInfo int DoInitialPass(cmMakefile* mf, int argc, char* argv[]) { SignalHandlerGuard guard(this->Name); +#if defined(__NVCOMPILER) + static_cast(guard); // convince compiler var is used +#endif return this->InitialPass(this, mf, argc, argv); } void DoFinalPass(cmMakefile* mf) { SignalHandlerGuard guard(this->Name); +#if defined(__NVCOMPILER) + static_cast(guard); // convince compiler var is used +#endif this->FinalPass(this, mf); } }; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index e2b1ae1a108..f5c195fd1d2 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -2723,6 +2723,9 @@ void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap) std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const { std::lock_guard guard(this->CMakeLibMutex_); +#if defined(__NVCOMPILER) + static_cast(guard); // convince compiler var is used +#endif return cmSystemTools::CollapseFullPath(path, this->ProjectDirs().CurrentSource); } @@ -2962,6 +2965,9 @@ std::vector cmQtAutoMocUicT::dependenciesFromDepFile( const char* filePath) { std::lock_guard guard(this->CMakeLibMutex_); +#if defined(__NVCOMPILER) + static_cast(guard); // convince compiler var is used +#endif auto const content = cmReadGccDepfile(filePath); if (!content || content->empty()) { return {}; From f881b4e4ccbab9aa7f3af3c610a72ad0422e90f9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 27 Apr 2021 09:58:59 -0400 Subject: [PATCH 0324/1519] cmCPackDebGenerator: Remove unused local variable --- Source/CPack/cmCPackDebGenerator.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 0fafd856ce3..006d66d3b13 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -167,7 +167,6 @@ void DebGenerator::generateControlFile() const unsigned long totalSize = 0; { - std::string dirName = cmStrCat(this->TemporaryDir, '/'); for (std::string const& file : this->PackageFiles) { totalSize += cmSystemTools::FileLength(file); } From 990b370401a26e43ddc3371ec056c6a8e2adfaec Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Wed, 28 Apr 2021 14:18:05 +0300 Subject: [PATCH 0325/1519] FindMsys: Add a module to find MSYS and some bundled packages --- Help/manual/cmake-modules.7.rst | 1 + Help/module/FindMsys.rst | 1 + Help/release/dev/FindMsys.rst | 6 ++++++ Modules/FindGnuplot.cmake | 2 ++ Modules/FindMsys.cmake | 31 +++++++++++++++++++++++++++++++ Modules/FindPerl.cmake | 2 ++ Modules/FindSelfPackers.cmake | 3 +++ Modules/FindUnixCommands.cmake | 7 +++++++ Modules/FindWget.cmake | 2 ++ 9 files changed, 55 insertions(+) create mode 100644 Help/module/FindMsys.rst create mode 100644 Help/release/dev/FindMsys.rst create mode 100644 Modules/FindMsys.cmake diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 17c1a1e5c35..141eeaa76ca 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -185,6 +185,7 @@ They are normally called through the :command:`find_package` command. /module/FindMPEG /module/FindMPEG2 /module/FindMPI + /module/FindMsys /module/FindODBC /module/FindOpenACC /module/FindOpenAL diff --git a/Help/module/FindMsys.rst b/Help/module/FindMsys.rst new file mode 100644 index 00000000000..fc5495ce703 --- /dev/null +++ b/Help/module/FindMsys.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindMsys.cmake diff --git a/Help/release/dev/FindMsys.rst b/Help/release/dev/FindMsys.rst new file mode 100644 index 00000000000..d237c4eaea5 --- /dev/null +++ b/Help/release/dev/FindMsys.rst @@ -0,0 +1,6 @@ +FindMsys +-------- + +* The :module:`FindMsys` module was added to find MSYS installations. + Like :module:`FindCygwin`, it is used automatically by some other + find modules to locate UNIX-style tools on Windows. diff --git a/Modules/FindGnuplot.cmake b/Modules/FindGnuplot.cmake index ca2467d6870..b4ea6ab3f39 100644 --- a/Modules/FindGnuplot.cmake +++ b/Modules/FindGnuplot.cmake @@ -23,6 +23,7 @@ GNUPLOT_VERSION_STRING will not work for old versions like 3.7.1. #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake) find_program(GNUPLOT_EXECUTABLE NAMES @@ -31,6 +32,7 @@ find_program(GNUPLOT_EXECUTABLE wgnupl32 PATHS ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) if (GNUPLOT_EXECUTABLE) diff --git a/Modules/FindMsys.cmake b/Modules/FindMsys.cmake new file mode 100644 index 00000000000..b4796d2950b --- /dev/null +++ b/Modules/FindMsys.cmake @@ -0,0 +1,31 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindMsys +-------- + +.. versionadded:: 3.21 + +Find MSYS, a POSIX-compatible environment that runs natively +on Microsoft Windows +#]=======================================================================] + +if (WIN32) + if(MSYS_INSTALL_PATH) + set(MSYS_CMD "${MSYS_INSTALL_PATH}/msys2_shell.cmd") + endif() + + find_program(MSYS_CMD + NAMES msys2_shell.cmd + PATHS + "C:/msys64" + "C:/msys32" + "C:/MSYS" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MSYS\\setup;rootdir]" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Cygnus Solutions\\MSYS\\mounts v2\\/;native]" + ) + get_filename_component(MSYS_INSTALL_PATH "${MSYS_CMD}" DIRECTORY) + mark_as_advanced(MSYS_CMD) + +endif () diff --git a/Modules/FindPerl.cmake b/Modules/FindPerl.cmake index c14e059e99b..26962dff71a 100644 --- a/Modules/FindPerl.cmake +++ b/Modules/FindPerl.cmake @@ -17,9 +17,11 @@ this module looks for Perl #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake) set(PERL_POSSIBLE_BIN_PATHS ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) if(WIN32) diff --git a/Modules/FindSelfPackers.cmake b/Modules/FindSelfPackers.cmake index 1abbcbd7ac5..a6eb6e5f0c8 100644 --- a/Modules/FindSelfPackers.cmake +++ b/Modules/FindSelfPackers.cmake @@ -17,15 +17,18 @@ executables or shared libs. Examples: #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake) find_program(SELF_PACKER_FOR_EXECUTABLE upx ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) find_program(SELF_PACKER_FOR_SHARED_LIB upx ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( diff --git a/Modules/FindUnixCommands.cmake b/Modules/FindUnixCommands.cmake index 2513f5c2903..97739fa1460 100644 --- a/Modules/FindUnixCommands.cmake +++ b/Modules/FindUnixCommands.cmake @@ -13,10 +13,12 @@ This module looks for the Unix commands ``bash``, ``cp``, ``gzip``, #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake) find_program(BASH bash ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( BASH @@ -25,6 +27,7 @@ mark_as_advanced( find_program(CP cp ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( CP @@ -33,6 +36,7 @@ mark_as_advanced( find_program(GZIP gzip ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( GZIP @@ -41,6 +45,7 @@ mark_as_advanced( find_program(MV mv ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( MV @@ -49,6 +54,7 @@ mark_as_advanced( find_program(RM rm ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( RM @@ -60,6 +66,7 @@ find_program(TAR gtar PATH ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) mark_as_advanced( TAR diff --git a/Modules/FindWget.cmake b/Modules/FindWget.cmake index bd01ec20180..d0b6fdf4483 100644 --- a/Modules/FindWget.cmake +++ b/Modules/FindWget.cmake @@ -16,10 +16,12 @@ This module looks for wget. This module defines the following values: #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindCygwin.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindMsys.cmake) find_program(WGET_EXECUTABLE wget ${CYGWIN_INSTALL_PATH}/bin + ${MSYS_INSTALL_PATH}/usr/bin ) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) From 46896d98bb8ed8a1068da70220581f8bbc3847fc Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sun, 25 Apr 2021 14:22:09 +0200 Subject: [PATCH 0326/1519] foreach(): loop variables are only available in the loop scope Fixes: #20553 --- Help/command/foreach.rst | 5 +- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0124.rst | 20 +++++++ Help/release/dev/foreach-variable-scope.rst | 5 ++ Source/cmForEachCommand.cxx | 37 +++++++++---- Source/cmMakefile.cxx | 14 +++++ Source/cmMakefile.h | 1 + Source/cmPolicies.h | 5 +- Tests/RunCMake/foreach/RunCMakeTest.cmake | 2 + .../foreach-var-scope-CMP0124-NEW.cmake | 51 ++++++++++++++++++ .../foreach-var-scope-CMP0124-OLD.cmake | 53 +++++++++++++++++++ 11 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 Help/policy/CMP0124.rst create mode 100644 Help/release/dev/foreach-variable-scope.rst create mode 100644 Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake create mode 100644 Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst index 8de6debae42..d9f54ca7502 100644 --- a/Help/command/foreach.rst +++ b/Help/command/foreach.rst @@ -14,9 +14,12 @@ semicolon or whitespace. All commands between ``foreach`` and the matching ``endforeach`` are recorded without being invoked. Once the ``endforeach`` is evaluated, the recorded list of commands is invoked once for each item in ````. -At the beginning of each iteration the variable ``loop_var`` will be set +At the beginning of each iteration the variable ```` will be set to the value of the current item. +The scope of ```` is restricted to the loop scope. See policy +:policy:`CMP0124` for details. + The commands :command:`break` and :command:`continue` provide means to escape from the normal control flow. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index b41ce59fd15..08449a71596 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.21 .. toctree:: :maxdepth: 1 + CMP0124: foreach() loop variables are only available in the loop scope. CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. CMP0122: UseSWIG use standard library name conventions for csharp language. CMP0121: The list command detects invalid indicies. diff --git a/Help/policy/CMP0124.rst b/Help/policy/CMP0124.rst new file mode 100644 index 00000000000..88d03e35dda --- /dev/null +++ b/Help/policy/CMP0124.rst @@ -0,0 +1,20 @@ +CMP0124 +------- + +.. versionadded:: 3.21 + +The loop variables created by :command:`foreach` command have now their scope +restricted to the loop scope. + +Starting with CMake 3.21, the :command:`foreach` command ensures that the loop +variables have their scope restricted to the loop scope. + +The ``OLD`` behavior for this policy let the loop variables to exist, with an +empty value, in the outer scope of loop scope. + +This policy was introduced in CMake version 3.21. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn when the policy +is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/foreach-variable-scope.rst b/Help/release/dev/foreach-variable-scope.rst new file mode 100644 index 00000000000..29a57bbc5fb --- /dev/null +++ b/Help/release/dev/foreach-variable-scope.rst @@ -0,0 +1,5 @@ +foreach-variable-scope +---------------------- + +* The :command:`foreach` command restrict loop variables to the loop scope. + See policy :policy:`CMP0124` for details. diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index bcacb15f9cb..4845a6d0912 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -25,7 +26,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" +#include "cmPolicies.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -113,9 +114,11 @@ bool cmForEachFunctionBlocker::ReplayItems( // At end of for each execute recorded commands // store the old value - std::string oldDef; - if (cmProp d = mf.GetDefinition(this->Args.front())) { - oldDef = *d; + cm::optional oldDef; + if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) { + oldDef = mf.GetSafeDefinition(this->Args.front()); + } else if (mf.IsNormalDefinitionSet(this->Args.front())) { + oldDef = *mf.GetDefinition(this->Args.front()); } auto restore = false; @@ -131,9 +134,14 @@ bool cmForEachFunctionBlocker::ReplayItems( } if (restore) { - // restore the variable to its prior value - mf.AddDefinition(this->Args.front(), oldDef); + if (oldDef) { + // restore the variable to its prior value + mf.AddDefinition(this->Args.front(), *oldDef); + } else { + mf.RemoveDefinition(this->Args.front()); + } } + return true; } @@ -185,10 +193,15 @@ bool cmForEachFunctionBlocker::ReplayZipLists( assert("Sanity check" && iterationVars.size() == values.size()); // Store old values for iteration variables - std::map oldDefs; + std::map> oldDefs; for (auto i = 0u; i < values.size(); ++i) { - if (cmProp d = mf.GetDefinition(iterationVars[i])) { - oldDefs.emplace(iterationVars[i], *d); + const auto& varName = iterationVars[i]; + if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) { + oldDefs.emplace(varName, mf.GetSafeDefinition(varName)); + } else if (mf.IsNormalDefinitionSet(varName)) { + oldDefs.emplace(varName, *mf.GetDefinition(varName)); + } else { + oldDefs.emplace(varName, cm::nullopt); } } @@ -226,7 +239,11 @@ bool cmForEachFunctionBlocker::ReplayZipLists( // Restore the variables to its prior value if (restore) { for (auto const& p : oldDefs) { - mf.AddDefinition(p.first, p.second); + if (p.second) { + mf.AddDefinition(p.first, *p.second); + } else { + mf.RemoveDefinition(p.first); + } } } return true; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 40a67a399d2..dba856037fb 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2507,6 +2507,20 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const return def != nullptr; } +bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const +{ + cmProp def = this->StateSnapshot.GetDefinition(name); +#ifndef CMAKE_BOOTSTRAP + if (cmVariableWatch* vv = this->GetVariableWatch()) { + if (!def) { + vv->VariableAccessed( + name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this); + } + } +#endif + return def != nullptr; +} + cmProp cmMakefile::GetDefinition(const std::string& name) const { cmProp def = this->StateSnapshot.GetDefinition(name); diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 71d765c71f9..3c07808170a 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -486,6 +486,7 @@ class cmMakefile const std::string& GetSafeDefinition(const std::string&) const; const std::string& GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; + bool IsNormalDefinitionSet(const std::string&) const; bool GetDefExpandList(const std::string& name, std::vector& out, bool emptyArgs = false) const; /** diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 0a5bb4b1000..0ff12d57b17 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -369,7 +369,10 @@ class cmMakefile; 21, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0123, \ "ARMClang cpu/arch compile and link flags must be set explicitly.", \ - 3, 21, 0, cmPolicies::WARN) + 3, 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0124, \ + "foreach() loop variables are only available in the loop scope.", 3, \ + 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake index d3f7c231c66..15ca477043f 100644 --- a/Tests/RunCMake/foreach/RunCMakeTest.cmake +++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake @@ -20,3 +20,5 @@ run_cmake(foreach-RANGE-non-int-test-3-2) run_cmake(foreach-RANGE-non-int-test-3-3) run_cmake(foreach-RANGE-invalid-test) run_cmake(foreach-RANGE-out-of-range-test) +run_cmake(foreach-var-scope-CMP0124-OLD) +run_cmake(foreach-var-scope-CMP0124-NEW) diff --git a/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake new file mode 100644 index 00000000000..7e2eee0fa90 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-NEW.cmake @@ -0,0 +1,51 @@ + +cmake_policy(SET CMP0124 NEW) + +foreach(VAR a b c) +endforeach() +if (DEFINED VAR) + message(SEND_ERROR "Variable 'VAR' unexpectedly defined.") +endif() + +set(LIST1 a b c) +set(LIST2 x y z) +foreach(VAR1_1 VAR1_2 IN ZIP_LISTS LIST1 LIST2) +endforeach() +if (DEFINED VAR1_1 OR DEFINED VAR1_2) + message(SEND_ERROR "Variables 'VAR1_1' or 'VAR1_2' unexpectedly defined.") +endif() + + +set (VAR2 OLD) +foreach(VAR2 a b c) +endforeach() +if (NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OLD") + message(SEND_ERROR "Variable 'VAR2' not defined or wrong value.") +endif() + +set (VAR2_2 OLD) +foreach(VAR2_1 VAR2_2 IN ZIP_LISTS LIST1 LIST2) +endforeach() +if (DEFINED VAR2_1 OR NOT DEFINED VAR2_2) + message(SEND_ERROR "Variable 'VAR2_1' unexpectedly defined or variable 'VAR2_2' not defined.") +endif() + + +set (VAR3 OLD CACHE STRING "") +foreach(VAR3 a b c) +endforeach() +# check that only cache variable is defined +set(OLD_VALUE "${VAR3}") +unset(VAR3 CACHE) +if (DEFINED VAR3 OR NOT OLD_VALUE STREQUAL "OLD") + message(SEND_ERROR "Variable 'VAR3' wrongly defined or wrong value.") +endif() + +set (VAR3_2 OLD CACHE STRING "") +foreach(VAR3_1 VAR3_2 IN ZIP_LISTS LIST1 LIST2) +endforeach() +set(OLD_VALUE "${VAR3_2}") +unset(VAR3_2 CACHE) +if (DEFINED VAR3_1 OR DEFINED VAR3_2 OR NOT OLD_VALUE STREQUAL "OLD") + message(SEND_ERROR "Variable 'VAR3_1' unexpectedly defined or variable 'VAR2_2' wrongly defined or wrong value.") +endif() diff --git a/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake new file mode 100644 index 00000000000..f95598215f7 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-var-scope-CMP0124-OLD.cmake @@ -0,0 +1,53 @@ + +cmake_policy(SET CMP0124 OLD) + +foreach(VAR a b c) +endforeach() +if (NOT DEFINED VAR OR NOT VAR STREQUAL "") + message(SEND_ERROR "Variable 'VAR' not defined or wrong value.") +endif() + +set(LIST1 a b c) +set(LIST2 x y z) +foreach(VAR1_1 VAR1_2 IN ZIP_LISTS LIST1 LIST2) +endforeach() +if (NOT DEFINED VAR1_1 OR NOT VAR1_1 STREQUAL "" + OR NOT DEFINED VAR1_2 OR NOT VAR1_2 STREQUAL "") + message(SEND_ERROR "Variables 'VAR1_1' or 'VAR1_2' not defined or wrong value.") +endif() + + +set (VAR2 OLD) +foreach(VAR2 a b c) +endforeach() +if (NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OLD") + message(SEND_ERROR "Variable 'VAR2' not defined or wrong value.") +endif() + +set (VAR2_2 OLD) +foreach(VAR2_1 VAR2_2 IN ZIP_LISTS LIST1 LIST2) +endforeach() +if (NOT DEFINED VAR2_1 OR NOT VAR2_1 STREQUAL "" + OR NOT DEFINED VAR2_2 OR NOT VAR2_2 STREQUAL "OLD") + message(SEND_ERROR "Variables 'VAR2_1' or 'VAR2_2' not defined or wrong value.") +endif() + + +set (VAR3 OLD CACHE STRING "") +foreach(VAR3 a b c) +endforeach() +# a normal variable is defined, holding cache variable value +unset(VAR3 CACHE) +if (NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "OLD") + message(SEND_ERROR "Variable 'VAR3' not defined or wrong value.") +endif() + +set (VAR3_2 OLD CACHE STRING "") +foreach(VAR3_1 VAR3_2 IN ZIP_LISTS LIST1 LIST2) +endforeach() +# a normal variable is defined, holding cache variable value +unset(VAR3_2 CACHE) +if (NOT DEFINED VAR3_1 OR NOT VAR3_1 STREQUAL "" + OR NOT DEFINED VAR3_2 OR NOT VAR3_2 STREQUAL "OLD") + message(SEND_ERROR "Variables 'VAR3_1' or 'VAR3_2' not defined or wrong value.") +endif() From a9b968bb9894902e2183a4aea4c23701d5666733 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 26 Apr 2021 11:51:27 -0400 Subject: [PATCH 0327/1519] cmake-presets: Introduce `toolchainFile` preset option In v3 of the presets, the `--toolchain` command line argument now has a preset mapping. --- Help/manual/cmake-presets.7.rst | 8 +++++ Help/manual/presets/schema.json | 5 +++ Source/cmCMakePresetsFile.cxx | 10 ++++++ Source/cmCMakePresetsFile.h | 2 ++ Source/cmCMakePresetsFileReadJSON.cxx | 7 ++++ Source/cmake.cxx | 7 ++++ .../FuturePresetToolchainField-result.txt | 1 + .../FuturePresetToolchainField-stderr.txt | 2 ++ .../FuturePresetToolchainField.json.in | 11 ++++++ .../CMakePresets/GoodToolchain.json.in | 30 ++++++++++++++++ .../GoodToolchainCommandLine.cmake | 3 ++ .../CMakePresets/GoodToolchainDefault.cmake | 3 ++ .../CMakePresets/GoodToolchainInherit.cmake | 3 ++ .../CMakePresets/GoodToolchainOverride.cmake | 3 ++ .../RunCMake/CMakePresets/RunCMakeTest.cmake | 36 +++++++++++++++++-- 15 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt create mode 100644 Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in create mode 100644 Tests/RunCMake/CMakePresets/GoodToolchain.json.in create mode 100644 Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake create mode 100644 Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake create mode 100644 Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake create mode 100644 Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 3714004a5df..57c8ccf3d08 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -182,6 +182,14 @@ that may contain the following fields: ignore the field, but the IDE can use them to set up the environment before invoking CMake. +``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. Takes precedence over any `CMAKE_TOOLCHAIN_FILE` + value. This is allowed in preset files specifying version ``3`` or above. + ``binaryDir`` An optional string representing the path to the output binary directory. diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index e0663626977..0d51b1f58d4 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -87,6 +87,10 @@ "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." }, + "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 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)." @@ -360,6 +364,7 @@ "generator": {}, "architecture": {}, "toolset": {}, + "toolchainFile": {}, "binaryDir": {}, "installDir": {}, "cmakeExecutable": {}, diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index 39cce9818b2..2f9972c381c 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -214,6 +214,12 @@ bool ExpandMacros(const cmCMakePresetsFile& file, cmSystemTools::ConvertToUnixSlashes(out->InstallDir); } + if (!preset.ToolchainFile.empty()) { + std::string toolchain = preset.ToolchainFile; + CHECK_EXPAND(out, toolchain, macroExpanders, file.GetVersion(preset)) + out->ToolchainFile = toolchain; + } + for (auto& variable : out->CacheVariables) { if (variable.second) { CHECK_EXPAND(out, variable.second->Value, macroExpanders, @@ -643,6 +649,7 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit( } InheritString(preset.BinaryDir, parent.BinaryDir); InheritString(preset.InstallDir, parent.InstallDir); + InheritString(preset.ToolchainFile, parent.ToolchainFile); InheritOptionalValue(preset.WarnDev, parent.WarnDev); InheritOptionalValue(preset.ErrorDev, parent.ErrorDev); InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated); @@ -989,6 +996,9 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result) return "Invalid preset condition"; case ReadFileResult::CONDITION_UNSUPPORTED: return "File version must be 3 or higher for condition support"; + case ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED: + return "File version must be 3 or higher for toolchainFile preset " + "support."; } return "Unknown error"; diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h index fc14830f48c..7aa9b6acc73 100644 --- a/Source/cmCMakePresetsFile.h +++ b/Source/cmCMakePresetsFile.h @@ -39,6 +39,7 @@ class cmCMakePresetsFile INSTALL_PREFIX_UNSUPPORTED, INVALID_CONDITION, CONDITION_UNSUPPORTED, + TOOLCHAIN_FILE_UNSUPPORTED, }; enum class ArchToolsetStrategy @@ -113,6 +114,7 @@ class cmCMakePresetsFile cm::optional ArchitectureStrategy; std::string Toolset; cm::optional ToolsetStrategy; + std::string ToolchainFile; std::string BinaryDir; std::string InstallDir; diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx index 403fac6a7fd..909a78b5ee2 100644 --- a/Source/cmCMakePresetsFileReadJSON.cxx +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -491,6 +491,8 @@ auto const ConfigurePresetHelper = false) .Bind("architecture"_s, ArchitectureHelper, false) .Bind("toolset"_s, ToolsetHelper, false) + .Bind("toolchainFile"_s, &ConfigurePreset::ToolchainFile, + PresetStringHelper, false) .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper, false) .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper, @@ -973,6 +975,11 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile( return ReadFileResult::CONDITION_UNSUPPORTED; } + // Support for toolchainFile presets added in version 3. + if (v < 3 && !preset.ToolchainFile.empty()) { + return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED; + } + this->ConfigurePresetOrder.push_back(preset.Name); } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index d24e268d450..4130f5fbf2a 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1257,6 +1257,13 @@ void cmake::SetArgs(const std::vector& args) "PATH", expandedPreset->InstallDir }; } + if (!expandedPreset->ToolchainFile.empty() && + this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE") == + nullptr) { + this->UnprocessedPresetVariables["CMAKE_TOOLCHAIN_FILE"] = { + "FILEPATH", expandedPreset->ToolchainFile + }; + } if (!expandedPreset->ArchitectureStrategy || expandedPreset->ArchitectureStrategy == diff --git a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt new file mode 100644 index 00000000000..9382423a354 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/FuturePresetToolchainField: File version must be 3 or higher for toolchainFile preset support.$ diff --git a/Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in new file mode 100644 index 00000000000..646ee0f089a --- /dev/null +++ b/Tests/RunCMake/CMakePresets/FuturePresetToolchainField.json.in @@ -0,0 +1,11 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "FuturePresetToolchainField", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "toolchainFile": "${sourceDir}/toolchain.cmake" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/GoodToolchain.json.in b/Tests/RunCMake/CMakePresets/GoodToolchain.json.in new file mode 100644 index 00000000000..69dafcf1198 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodToolchain.json.in @@ -0,0 +1,30 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "GoodToolchainDefault", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build/${presetName}", + "toolchainFile": "${sourceDir}/toolchain.cmake" + }, + { + "name": "GoodToolchainInherit", + "inherits": "GoodToolchainDefault", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/toolchain_bad.cmake" + } + } + }, + { + "name": "GoodToolchainOverride", + "inherits": "GoodToolchainInherit", + "toolchainFile": "override_toolchain.cmake" + }, + { + "name": "GoodToolchainCommandLine", + "inherits": "GoodToolchainOverride" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake new file mode 100644 index 00000000000..c37421c3979 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodToolchainCommandLine.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/cmd_line_toolchain.cmake") diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake new file mode 100644 index 00000000000..53c938b47db --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodToolchainDefault.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/toolchain.cmake") diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake new file mode 100644 index 00000000000..53c938b47db --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodToolchainInherit.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/toolchain.cmake") diff --git a/Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake b/Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake new file mode 100644 index 00000000000..558134ca2f8 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/GoodToolchainOverride.cmake @@ -0,0 +1,3 @@ +include("${RunCMake_SOURCE_DIR}/TestVariable.cmake") + +test_variable("CMAKE_TOOLCHAIN_FILE" "FILEPATH" "${CMAKE_SOURCE_DIR}/override_toolchain.cmake") diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index bcbd177f8e7..02051d916f8 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -11,14 +11,23 @@ set(RunCMake-check-file check.cmake) include("${RunCMake_SOURCE_DIR}/validate_schema.cmake") +function(reset_cmake_presets_directory name) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}") + file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") +endfunction() + function(run_cmake_presets name) set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}") set(_source_arg "${RunCMake_TEST_SOURCE_DIR}") if(CMakePresets_SOURCE_ARG) set(_source_arg "${CMakePresets_SOURCE_ARG}") endif() - file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}") - file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + + if(NOT RunCMake_TEST_SOURCE_DIR_NO_CLEAN) + file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + endif() configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY) if(NOT CMakePresets_FILE) @@ -95,6 +104,7 @@ run_cmake_presets(ExtraRootField) run_cmake_presets(ExtraPresetField) run_cmake_presets(ExtraVariableField) run_cmake_presets(FuturePresetInstallDirField) +run_cmake_presets(FuturePresetToolchainField) run_cmake_presets(InvalidPresetVendor) set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) run_cmake_presets(DuplicatePresets) @@ -191,6 +201,28 @@ run_cmake_presets(GoodInstallInherit) run_cmake_presets(GoodInstallOverride) run_cmake_presets(GoodInstallCommandLine "--install-prefix=${RunCMake_SOURCE_DIR}/path/passed/on/command_line") +set(RunCMake_TEST_SOURCE_DIR_NO_CLEAN 1) +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/GoodToolchain.json.in") + +reset_cmake_presets_directory(GoodToolchainInherit) +file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainDefault/toolchain.cmake" "") +run_cmake_presets(GoodToolchainDefault) + +reset_cmake_presets_directory(GoodToolchainInherit) +file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainInherit/toolchain.cmake" "") +run_cmake_presets(GoodToolchainInherit) + +reset_cmake_presets_directory(GoodToolchainOverride) +file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainOverride/override_toolchain.cmake" "") +run_cmake_presets(GoodToolchainOverride) + +reset_cmake_presets_directory(GoodToolchainCommandLine) +file(WRITE "${RunCMake_BINARY_DIR}/GoodToolchainCommandLine/cmd_line_toolchain.cmake" "") +run_cmake_presets(GoodToolchainCommandLine "--toolchain=${RunCMake_BINARY_DIR}/GoodToolchainCommandLine/cmd_line_toolchain.cmake") + +unset(RunCMake_TEST_SOURCE_DIR_NO_CLEAN) + + set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/CMakePresets.json.in") # Test bad preset arguments run_cmake_presets(VendorMacro) From 60288129db444cf0fee4112e87b30e3ad2a0e007 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 29 Apr 2021 00:04:13 -0400 Subject: [PATCH 0328/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 96f70b9cb62..c2caa2ab3b3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210428) +set(CMake_VERSION_PATCH 20210429) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 18513fa1185f3f2b28f3c4de5ae3f69c9ec9e5cb Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Thu, 29 Apr 2021 09:09:55 -0400 Subject: [PATCH 0329/1519] KWSys 2021-04-29 (5655d533) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 5655d533a9a4fb59b87d364c896339f1d454d420 (master). Upstream Shortlog ----------------- Brad King (1): 6e59fd94 Process: Suppress NVHPC warning in FD_ZERO --- ProcessUNIX.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ProcessUNIX.c b/ProcessUNIX.c index e1e7721b41a..5ae846aeee6 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -122,6 +122,10 @@ static inline void kwsysProcess_usleep(unsigned int msec) /* The maximum amount to read from a pipe at a time. */ #define KWSYSPE_PIPE_BUFFER_SIZE 1024 +#if defined(__NVCOMPILER) +# pragma diag_suppress 550 /* variable set but never used (in FD_ZERO) */ +#endif + /* Keep track of times using a signed representation. Switch to the native (possibly unsigned) representation only when calling native functions. */ From 20ab504591cba354023bd286c90ead8d6b393f28 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima <15070-e-kwsm@users.noreply.gitlab.com> Date: Sun, 11 Apr 2021 15:16:46 +0900 Subject: [PATCH 0330/1519] FindBLAS: Do not statically link against iomp5 in the case of Intel MKL fix #21811 --- Modules/FindBLAS.cmake | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index f3a8b7439b5..024ff14632c 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -333,12 +333,21 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") if(CMAKE_Fortran_COMPILER_LOADED AND CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) set(BLAS_mkl_INTFACE "gf") set(BLAS_mkl_THREADING "gnu") - set(BLAS_mkl_OMP "gomp") else() set(BLAS_mkl_INTFACE "intel") set(BLAS_mkl_THREADING "intel") - set(BLAS_mkl_OMP "iomp5") endif() + + foreach(lang IN ITEMS C CXX Fortran) + if(CMAKE_${lang}_COMPILER_LOADED) + find_package(OpenMP COMPONENTS ${lang}) + if(${OpenMP_${lang}_FOUND}) + set(BLAS_mkl_OMP ${OpenMP_${lang}_LIBRARIES}) + break() + endif() + endif() + endforeach() + set(BLAS_mkl_LM "-lm") set(BLAS_mkl_LDL "-ldl") endif() @@ -403,7 +412,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") + "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All") # old version @@ -412,7 +421,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") + "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All") list(APPEND BLAS_SEARCH_LIBS @@ -468,7 +477,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") + "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All") # old version @@ -477,7 +486,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") + "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All") list(APPEND BLAS_SEARCH_LIBS @@ -540,7 +549,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") ${BLAS_mkl_SEARCH_SYMBOL} "" "${SEARCH_LIBS}" - "${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}" + "${BLAS_mkl_OMP};${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}" "${BLAS_mkl_MKLROOT}" "${BLAS_mkl_LIB_PATH_SUFFIXES}" ) From 4b60072620f51be4c9f3183cd8c5ac58e6865f2f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 30 Apr 2021 00:01:09 -0400 Subject: [PATCH 0331/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c2caa2ab3b3..8728f564c67 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210429) +set(CMake_VERSION_PATCH 20210430) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ad08f93ee40a1cc855c403c1cc738237511224e3 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 30 Apr 2021 14:45:19 -0400 Subject: [PATCH 0332/1519] Ninja Multi-Config: Split long command lines by config Fixes: #22123 --- Source/cmLocalNinjaGenerator.cxx | 17 +++++++---- Source/cmLocalNinjaGenerator.h | 5 +++- Source/cmNinjaNormalTargetGenerator.cxx | 30 ++++++++++++------- Source/cmNinjaTargetGenerator.cxx | 25 +++++++++------- Source/cmNinjaTargetGenerator.h | 3 +- Source/cmNinjaUtilityTargetGenerator.cxx | 4 +-- ...ommandLine-release-config-build-stdout.txt | 2 ++ .../NinjaMultiConfig/LongCommandLine.cmake | 7 +++++ .../NinjaMultiConfig/RunCMakeTest.cmake | 3 ++ 9 files changed, 66 insertions(+), 30 deletions(-) create mode 100644 Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 51ad9938989..081cc41fc37 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -407,7 +407,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps( } std::string cmLocalNinjaGenerator::WriteCommandScript( - std::vector const& cmdLines, std::string const& customStep, + std::vector const& cmdLines, std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep, cmGeneratorTarget const* target) const { std::string scriptPath; @@ -416,9 +417,13 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( } else { scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles"); } + scriptPath += this->GetGlobalNinjaGenerator()->ConfigDirectory(outputConfig); cmSystemTools::MakeDirectory(scriptPath); scriptPath += '/'; scriptPath += customStep; + if (this->GlobalGenerator->IsMultiConfig()) { + scriptPath += cmStrCat('-', commandConfig); + } #ifdef _WIN32 scriptPath += ".bat"; #else @@ -461,7 +466,8 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( } std::string cmLocalNinjaGenerator::BuildCommandLine( - std::vector const& cmdLines, std::string const& customStep, + std::vector const& cmdLines, std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep, cmGeneratorTarget const* target) const { // If we have no commands but we need to build a command anyway, use noop. @@ -480,8 +486,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( cmdLinesTotal += cmd.length() + 6; } if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) { - std::string const scriptPath = - this->WriteCommandScript(cmdLines, customStep, target); + std::string const scriptPath = this->WriteCommandScript( + cmdLines, outputConfig, commandConfig, customStep, target); std::string cmd #ifndef _WIN32 = "/bin/sh " @@ -694,7 +700,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } gg->WriteCustomCommandBuild( - this->BuildCommandLine(cmdLines, customStep), + this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig, + customStep), this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], depfile, cc->GetJobPool(), cc->GetUsesTerminal(), /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig, diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 5b850f3d09f..0734c5cad60 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -60,7 +60,8 @@ class cmLocalNinjaGenerator : public cmLocalCommonGenerator } std::string BuildCommandLine( - std::vector const& cmdLines, + std::vector const& cmdLines, std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep = std::string(), cmGeneratorTarget const* target = nullptr) const; @@ -119,6 +120,8 @@ class cmLocalNinjaGenerator : public cmLocalCommonGenerator std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); std::string WriteCommandScript(std::vector const& cmdLines, + std::string const& outputConfig, + std::string const& commandConfig, std::string const& customStep, cmGeneratorTarget const* target) const; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 49e5e4cc65f..1597d2c19e3 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -287,7 +287,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule( // If there is no ranlib the command will be ":". Skip it. cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config); // Write the linker rule with response file if needed. rule.Comment = @@ -310,7 +311,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( cmNinjaRule rule(this->LanguageLinkerCudaDeviceRule(config)); rule.Command = this->GetLocalGenerator()->BuildCommandLine( { cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"), - " -arch=$ARCH $REGISTER -o=$out $in") }); + " -arch=$ARCH $REGISTER -o=$out $in") }, + config, config); rule.Comment = "Rule for CUDA device linking."; rule.Description = "Linking CUDA $out"; this->GetGlobalGenerator()->AddRule(rule); @@ -336,7 +338,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( compileCmd, vars); rule.Name = this->LanguageLinkerCudaDeviceCompileRule(config); - rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd }); + rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd }, + config, config); rule.Comment = "Rule for compiling CUDA device stubs."; rule.Description = "Compiling CUDA device stub $out"; this->GetGlobalGenerator()->AddRule(rule); @@ -345,7 +348,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( rule.Command = this->GetLocalGenerator()->BuildCommandLine( { cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"), " -64 -cmdline=--compile-only -compress-all -link " - "--embedded-fatbin=$out $PROFILES") }); + "--embedded-fatbin=$out $PROFILES") }, + config, config); rule.Comment = "Rule for CUDA fatbinaries."; rule.Description = "Creating fatbinary $out"; this->GetGlobalGenerator()->AddRule(rule); @@ -475,7 +479,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.emplace_back("$POST_BUILD"); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config); // Write the linker rule with response file if needed. rule.Comment = @@ -500,7 +505,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, std::vector cmd; cmd.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out"); cmd.emplace_back("$POST_BUILD"); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(cmd, config, config); } rule.Description = "Creating executable symlink $out"; rule.Comment = "Rule for creating executable symlink."; @@ -512,7 +518,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, cmd.push_back(cmakeCommand + " -E cmake_symlink_library $in $SONAME $out"); cmd.emplace_back("$POST_BUILD"); - rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(cmd, config, config); } rule.Description = "Creating library symlink $out"; rule.Comment = "Rule for creating library symlink."; @@ -1310,10 +1317,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( preLinkCmdLines.push_back("cd " + homeOutDir); } - vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link", - this->GeneratorTarget); - std::string postBuildCmdLine = localGen.BuildCommandLine( - postBuildCmdLines, "post-build", this->GeneratorTarget); + vars["PRE_LINK"] = localGen.BuildCommandLine( + preLinkCmdLines, config, fileConfig, "pre-link", this->GeneratorTarget); + std::string postBuildCmdLine = + localGen.BuildCommandLine(postBuildCmdLines, config, fileConfig, + "post-build", this->GeneratorTarget); cmNinjaVars symlinkVars; bool const symlinkNeeded = diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 672b5797ed4..b4838d66795 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -537,7 +537,8 @@ cmNinjaRule GetScanRule( cmRulePlaceholderExpander::RuleVariables const& vars, const std::string& responseFlag, const std::string& flags, cmRulePlaceholderExpander* const rulePlaceholderExpander, - cmLocalNinjaGenerator* generator, std::vector scanCmds) + cmLocalNinjaGenerator* generator, std::vector scanCmds, + const std::string& outputConfig) { cmNinjaRule rule(ruleName); // Scanning always uses a depfile for preprocessor dependencies. @@ -578,7 +579,8 @@ cmNinjaRule GetScanRule( for (std::string& scanCmd : scanCmds) { rulePlaceholderExpander->ExpandRuleVariables(generator, scanCmd, scanVars); } - rule.Command = generator->BuildCommandLine(scanCmds); + rule.Command = + generator->BuildCommandLine(scanCmds, outputConfig, outputConfig); return rule; } @@ -670,7 +672,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, auto scanRule = GetScanRule( scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(), - this->GetLocalGenerator(), std::move(scanCommands)); + this->GetLocalGenerator(), std::move(scanCommands), config); scanRule.Comment = cmStrCat("Rule for generating ", lang, " dependencies."); @@ -700,7 +702,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, auto scanRule = GetScanRule( scanRuleName, vars, "", flags, rulePlaceholderExpander.get(), - this->GetLocalGenerator(), std::move(scanCommands)); + this->GetLocalGenerator(), std::move(scanCommands), config); // Write the rule for generating dependencies for the given language. scanRule.Comment = cmStrCat("Rule for generating ", lang, @@ -732,7 +734,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, ddModmapArg, " --dd=$out @", rule.RspFile); ddCmds.emplace_back(std::move(ccmd)); } - rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(ddCmds, config, config); } rule.Comment = cmStrCat("Rule to generate ninja dyndep files for ", lang, '.'); @@ -928,7 +931,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, vars); } - rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds); + rule.Command = + this->GetLocalGenerator()->BuildCommandLine(compileCmds, config, config); // Write the rule for compiling file of the given language. rule.Comment = cmStrCat("Rule for compiling ", lang, " files."); @@ -1246,7 +1250,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->ExportObjectCompileCommand( language, sourceFileName, objectDir, objectFileName, objectFileDir, - vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); + vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config); objBuild.Outputs.push_back(objectFileName); if (firstForConfig) { @@ -1617,7 +1621,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( std::string const& language, std::string const& sourceFileName, std::string const& objectDir, std::string const& objectFileName, std::string const& objectFileDir, std::string const& flags, - std::string const& defines, std::string const& includes) + std::string const& defines, std::string const& includes, + std::string const& outputConfig) { if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) { return; @@ -1679,8 +1684,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( compileObjectVars); } - std::string cmdLine = - this->GetLocalGenerator()->BuildCommandLine(compileCmds); + std::string cmdLine = this->GetLocalGenerator()->BuildCommandLine( + compileCmds, outputConfig, outputConfig); this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName); } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 79dc6227e78..3a28cef94c9 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -162,7 +162,8 @@ class cmNinjaTargetGenerator : public cmCommonTargetGenerator std::string const& language, std::string const& sourceFileName, std::string const& objectDir, std::string const& objectFileName, std::string const& objectFileDir, std::string const& flags, - std::string const& defines, std::string const& includes); + std::string const& defines, std::string const& includes, + std::string const& outputConfig); void AdditionalCleanFiles(const std::string& config); diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 92c5b521ba6..7a04c470bcd 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -139,8 +139,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } } else { - std::string command = - lg->BuildCommandLine(commands, "utility", this->GeneratorTarget); + std::string command = lg->BuildCommandLine( + commands, config, fileConfig, "utility", this->GeneratorTarget); std::string desc; cmProp echoStr = genTarget->GetProperty("EchoString"); if (echoStr) { diff --git a/Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt new file mode 100644 index 00000000000..628b6bc3356 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine-release-config-build-stdout.txt @@ -0,0 +1,2 @@ + +Post-build Debug Release \.*$ diff --git a/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake index 00aa896af2b..de528be4665 100644 --- a/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/LongCommandLine.cmake @@ -14,3 +14,10 @@ add_custom_target( ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gen.txt" ) + +add_executable(exe main.c) + +add_custom_command( + TARGET exe POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "Post-build $ $> ${very_long}" + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index aa427391ea9..e7acbc2845c 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -198,8 +198,11 @@ run_cmake_build(PostBuild release Release Exe) run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LongCommandLine-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all") run_cmake_configure(LongCommandLine) +unset(RunCMake_TEST_OPTIONS) run_cmake_build(LongCommandLine release Release custom) +run_cmake_build(LongCommandLine release-config Release exe:Debug) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build) set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all") From a51ad60687ecc9cb9e5f58099d0c19c8f3db2629 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 1 May 2021 00:01:06 -0400 Subject: [PATCH 0333/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8728f564c67..67afa89345c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210430) +set(CMake_VERSION_PATCH 20210501) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 4dd4e9dd6ce5efd9bb9bbb784816167a8b5873ae Mon Sep 17 00:00:00 2001 From: friendlyanon Date: Sat, 1 May 2021 16:05:19 +0200 Subject: [PATCH 0334/1519] cmGlobalGenerator: Add parallel parameter to GenerateCMakeBuildCommand --- Source/CPack/cmCPackGenerator.cxx | 2 +- Source/CTest/cmCTestBuildCommand.cxx | 4 ++-- Source/cmBuildCommand.cxx | 4 ++-- Source/cmGlobalGenerator.cxx | 7 ++++++- Source/cmGlobalGenerator.h | 6 +++++- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index c512a361584..cd2adaa304b 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -694,7 +694,7 @@ int cmCPackGenerator::RunPreinstallTarget( // Does this generator require pre-install? if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) { std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand( - preinstall, buildConfig, "", false); + preinstall, buildConfig, "", "", false); cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Install command: " << buildCommand << std::endl); cmCPackLogger(cmCPackLog::LOG_OUTPUT, diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 88e2871604b..099d1e2de46 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -98,8 +98,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string buildCommand = this->GlobalGenerator->GenerateCMakeBuildCommand( - cmakeBuildTarget, cmakeBuildConfiguration, cmakeBuildAdditionalFlags, - this->Makefile->IgnoreErrorsCMP0061()); + cmakeBuildTarget, cmakeBuildConfiguration, "", + cmakeBuildAdditionalFlags, this->Makefile->IgnoreErrorsCMP0061()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "SetMakeCommand:" << buildCommand << "\n", this->Quiet); diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 2eaf31561f5..4830343e13c 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -77,7 +77,7 @@ bool MainSignature(std::vector const& args, } std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand( - target, configuration, "", mf.IgnoreErrorsCMP0061()); + target, configuration, "", "", mf.IgnoreErrorsCMP0061()); mf.AddDefinition(variable, makecommand); @@ -104,7 +104,7 @@ bool TwoArgsSignature(std::vector const& args, } std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand( - "", configType, "", mf.IgnoreErrorsCMP0061()); + "", configType, "", "", mf.IgnoreErrorsCMP0061()); if (cacheValue) { return true; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ab76260f958..55fba7978f8 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2077,7 +2077,7 @@ bool cmGlobalGenerator::Open(const std::string& bindir, std::string cmGlobalGenerator::GenerateCMakeBuildCommand( const std::string& target, const std::string& config, - const std::string& native, bool ignoreErrors) + const std::string& parallel, const std::string& native, bool ignoreErrors) { std::string makeCommand = cmSystemTools::GetCMakeCommand(); makeCommand = @@ -2087,6 +2087,11 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand( makeCommand += config; makeCommand += "\""; } + if (!parallel.empty()) { + makeCommand += " --parallel \""; + makeCommand += parallel; + makeCommand += "\""; + } if (!target.empty()) { makeCommand += " --target \""; makeCommand += target; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 590de268cfa..fee0359b344 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -249,9 +249,13 @@ class cmGlobalGenerator virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const; - /** Generate a "cmake --build" call for a given target and config. */ + /** + * Generate a "cmake --build" call for a given target, config and parallel + * level. + */ std::string GenerateCMakeBuildCommand(const std::string& target, const std::string& config, + const std::string& parallel, const std::string& native, bool ignoreErrors); From 4f88cb1675cf2fe50459eb4cc321a0d4b36c6c33 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 2 May 2021 00:01:06 -0400 Subject: [PATCH 0335/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 67afa89345c..e0b5dc27e36 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210501) +set(CMake_VERSION_PATCH 20210502) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d2296cdaab38255c5deb3c830fdefec878beec31 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Sun, 2 May 2021 09:17:57 -0400 Subject: [PATCH 0336/1519] UseSWIG: remove duplicate target includes --- Modules/UseSWIG.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 269fa987ece..5c8f152bb7e 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -530,7 +530,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) endif() set (property "$") list (APPEND swig_source_file_flags "$<$:-I$,$-I>>") - set (property "$") + set (property "$>") get_source_file_property(use_target_include_dirs "${infile}" USE_TARGET_INCLUDE_DIRECTORIES) if (use_target_include_dirs) list (APPEND swig_source_file_flags "$<$:-I$-I>>") From ff6f7b232fbe36d8cb237ca2508ca01632d9d9d2 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Sun, 2 May 2021 10:01:31 -0400 Subject: [PATCH 0337/1519] FindSWIG: reduce calls to SWIG exe, and clean up variables If all SWIG cache variables (EXECUTABLE, DIR, VERSION) are set, there should be no need to invoke the SWIG exe on a reconfigure. This changeset reduces the number of calls to the SWIG executable, and additonially prevents temporary `SWIG_xxx` values from propagating outside the `find_package` call. I also refactored the conditionals to be less nested (and thus more predictable), including changing theh definition of SWIG_USE_FILE to reflect that it's if and only if SWIG_FOUND is trure. --- Modules/FindSWIG.cmake | 92 +++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/Modules/FindSWIG.cmake b/Modules/FindSWIG.cmake index 4c7ad89dcab..73aec893904 100644 --- a/Modules/FindSWIG.cmake +++ b/Modules/FindSWIG.cmake @@ -87,56 +87,68 @@ if (NOT _SWIG_NAMES) endif() find_program(SWIG_EXECUTABLE NAMES ${_SWIG_NAMES} swig) +unset(_SWIG_NAMES) -if(SWIG_EXECUTABLE) +if(SWIG_EXECUTABLE AND NOT SWIG_DIR) + # Find default value for SWIG library directory execute_process(COMMAND ${SWIG_EXECUTABLE} -swiglib - OUTPUT_VARIABLE SWIG_swiglib_output - ERROR_VARIABLE SWIG_swiglib_error - RESULT_VARIABLE SWIG_swiglib_result) + OUTPUT_VARIABLE _swig_output + ERROR_VARIABLE _swig_error + RESULT_VARIABLE _swig_result) - if(SWIG_swiglib_result) + if(_swig_result) + set(_msg "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${_swig_error}") if(SWIG_FIND_REQUIRED) - message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}") + message(SEND_ERROR "${_msg}") else() - message(STATUS "Command \"${SWIG_EXECUTABLE} -swiglib\" failed with output:\n${SWIG_swiglib_error}") + message(STATUS "${_msg}") endif() + unset(_msg) else() - string(REGEX REPLACE "[\n\r]+" ";" SWIG_swiglib_output ${SWIG_swiglib_output}) - find_path(SWIG_DIR swig.swg PATHS ${SWIG_swiglib_output} NO_CMAKE_FIND_ROOT_PATH) - if(SWIG_DIR) - set(SWIG_USE_FILE ${CMAKE_CURRENT_LIST_DIR}/UseSWIG.cmake) - execute_process(COMMAND ${SWIG_EXECUTABLE} -version - OUTPUT_VARIABLE SWIG_version_output - ERROR_VARIABLE SWIG_version_output - RESULT_VARIABLE SWIG_version_result) - if(SWIG_version_result) - message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -version\" failed with output:\n${SWIG_version_output}") - else() - string(REGEX REPLACE ".*SWIG Version[^0-9.]*\([0-9.]+\).*" "\\1" - SWIG_version_output "${SWIG_version_output}") - set(SWIG_VERSION ${SWIG_version_output} CACHE STRING "Swig version" FORCE) - endif() - endif() + string(REGEX REPLACE "[\n\r]+" ";" _SWIGLIB ${_swig_output}) endif() +endif() - if(SWIG_FIND_COMPONENTS) - execute_process(COMMAND ${SWIG_EXECUTABLE} -help - OUTPUT_VARIABLE SWIG_swighelp_output - ERROR_VARIABLE SWIG_swighelp_error - RESULT_VARIABLE SWIG_swighelp_result) - if(SWIG_swighelp_result) - message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -help\" failed with output:\n${SWIG_swiglib_error}") - else() - string(REPLACE "\n" ";" SWIG_swighelp_output "${SWIG_swighelp_output}") - foreach(SWIG_line IN LISTS SWIG_swighelp_output) - if(SWIG_line MATCHES "-([A-Za-z0-9_]+) +- *Generate.*wrappers") - set(SWIG_${CMAKE_MATCH_1}_FOUND TRUE) - endif() - endforeach() - endif() +# Find SWIG library directory +find_path(SWIG_DIR swig.swg PATHS ${_SWIGLIB} NO_CMAKE_FIND_ROOT_PATH) +unset(_SWIGLIB) + +if(SWIG_EXECUTABLE AND SWIG_DIR AND NOT SWIG_VERSION) + # Determine SWIG version + execute_process(COMMAND ${SWIG_EXECUTABLE} -version + OUTPUT_VARIABLE _swig_output + ERROR_VARIABLE _swig_output + RESULT_VARIABLE _swig_result) + if(_swig_result) + message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -version\" failed with output:\n${_swig_output}") + else() + string(REGEX REPLACE ".*SWIG Version[^0-9.]*\([0-9.]+\).*" "\\1" + _swig_output "${_swig_output}") + set(SWIG_VERSION ${_swig_output} CACHE STRING "Swig version" FORCE) endif() endif() +if(SWIG_EXECUTABLE AND SWIG_FIND_COMPONENTS) + execute_process(COMMAND ${SWIG_EXECUTABLE} -help + OUTPUT_VARIABLE _swig_output + ERROR_VARIABLE _swig_error + RESULT_VARIABLE _swig_result) + if(_swig_result) + message(SEND_ERROR "Command \"${SWIG_EXECUTABLE} -help\" failed with output:\n${_swig_error}") + else() + string(REPLACE "\n" ";" _swig_output "${_swig_output}") + foreach(SWIG_line IN LISTS _swig_output) + if(SWIG_line MATCHES "-([A-Za-z0-9_]+) +- *Generate.*wrappers") + set(SWIG_${CMAKE_MATCH_1}_FOUND TRUE) + endif() + endforeach() + endif() +endif() + +unset(_swig_output) +unset(_swig_error) +unset(_swig_result) + include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args( SWIG HANDLE_COMPONENTS @@ -144,4 +156,8 @@ find_package_handle_standard_args( VERSION_VAR SWIG_VERSION HANDLE_VERSION_RANGE) +if(SWIG_FOUND) + set(SWIG_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseSWIG.cmake") +endif() + mark_as_advanced(SWIG_DIR SWIG_VERSION SWIG_EXECUTABLE) From 8095cdd8c0ec6aaf038047562661f18509bfbe62 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 3 May 2021 00:01:14 -0400 Subject: [PATCH 0338/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e0b5dc27e36..48cf63ed9cb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210502) +set(CMake_VERSION_PATCH 20210503) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From bd16a985fcc26a2138e20ed11c248cd716eb5497 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 14:37:51 -0400 Subject: [PATCH 0339/1519] CompilerId/Features: Tolerate variables named for languages If a `CMakeLists.txt` or `CMAKE_TOOLCHAIN_FILE` sets a variable named `C`, `CXX`, or `CUDA`, we were previously comparing each enabled language name to the value of that variable, rather than the name itself. Double-quote the string to take advantage of policy `CMP0054`, but also add "x" prefixes to support projects that do not set the policy. Fixes: #22125 --- Modules/CMakeCompilerIdDetection.cmake | 2 +- Modules/CMakeDetermineCompileFeatures.cmake | 6 +++--- Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake | 2 ++ Tests/RunCMake/ToolchainFile/LangVars.cmake | 7 +++++++ Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake | 1 + 5 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake create mode 100644 Tests/RunCMake/ToolchainFile/LangVars.cmake diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index c79d4239a91..850fc14e044 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -18,7 +18,7 @@ function(compiler_id_detection outvar lang) file(GLOB lang_files "${CMAKE_ROOT}/Modules/Compiler/*-DetermineCompiler.cmake") set(nonlang CXX) - if (lang STREQUAL CXX) + if ("x${lang}" STREQUAL "xCXX") set(nonlang C) endif() diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake index f767847936d..ee7fedba4a4 100644 --- a/Modules/CMakeDetermineCompileFeatures.cmake +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -4,7 +4,7 @@ function(cmake_determine_compile_features lang) - if(lang STREQUAL C AND COMMAND cmake_record_c_compile_features) + if("x${lang}" STREQUAL "xC" AND COMMAND cmake_record_c_compile_features) message(CHECK_START "Detecting ${lang} compile features") set(CMAKE_C90_COMPILE_FEATURES) @@ -54,7 +54,7 @@ function(cmake_determine_compile_features lang) message(CHECK_PASS "done") - elseif(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features) + elseif("x${lang}" STREQUAL "xCXX" AND COMMAND cmake_record_cxx_compile_features) message(CHECK_START "Detecting ${lang} compile features") set(CMAKE_CXX98_COMPILE_FEATURES) @@ -110,7 +110,7 @@ function(cmake_determine_compile_features lang) message(CHECK_PASS "done") - elseif(lang STREQUAL CUDA AND COMMAND cmake_record_cuda_compile_features) + elseif("x${lang}" STREQUAL "xCUDA" AND COMMAND cmake_record_cuda_compile_features) message(CHECK_START "Detecting ${lang} compile features") set(CMAKE_CUDA03_COMPILE_FEATURES) diff --git a/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake b/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake new file mode 100644 index 00000000000..be07dc318da --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/LangVars-toolchain.cmake @@ -0,0 +1,2 @@ +set(C 1) +set(CXX 1) diff --git a/Tests/RunCMake/ToolchainFile/LangVars.cmake b/Tests/RunCMake/ToolchainFile/LangVars.cmake new file mode 100644 index 00000000000..169e639f5a1 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/LangVars.cmake @@ -0,0 +1,7 @@ +foreach(test_language C CXX) + enable_language(${test_language}) + if(DEFINED CMAKE_${test_language}_STANDARD_DEFAULT + AND NOT CMAKE_${test_language}_COMPILE_FEATURES) + message(FATAL_ERROR "Compile features not found for ${test_language}") + endif() +endforeach() diff --git a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake index 659523c4253..304c10525ab 100644 --- a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake +++ b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake @@ -9,6 +9,7 @@ run_cmake_toolchain(CallEnableLanguage) run_cmake_toolchain(CallProject) run_cmake_toolchain(CheckLanguage) run_cmake_toolchain(FlagsInit) +run_cmake_toolchain(LangVars) run_cmake_toolchain(LinkFlagsInit) function(run_IncludeDirectories) From d8786bfa16889f445a37bee7e665948e7a134c13 Mon Sep 17 00:00:00 2001 From: Thomas Vaughan Date: Mon, 3 May 2021 08:53:09 -0400 Subject: [PATCH 0340/1519] VS: Add support for per-config C# sources Fixes: #22108 --- Source/cmVisualStudio10TargetGenerator.cxx | 16 +++++++++++++++- Tests/CSharpOnly/CMakeLists.txt | 7 ++++++- Tests/CSharpOnly/config_specific_main_debug.cs | 10 ++++++++++ .../CSharpOnly/config_specific_main_no_exist.cs | 10 ++++++++++ .../CSharpOnly/config_specific_main_not_debug.cs | 10 ++++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 Tests/CSharpOnly/config_specific_main_debug.cs create mode 100644 Tests/CSharpOnly/config_specific_main_no_exist.cs create mode 100644 Tests/CSharpOnly/config_specific_main_not_debug.cs diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 0255d60cf40..42c3a68d4c0 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2277,6 +2277,20 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) std::back_inserter(exclude_configs)); Elem e2(e1, tool); + bool isCSharp = (si.Source->GetLanguage() == "CSharp"); + if (isCSharp && exclude_configs.size() > 0) { + std::stringstream conditions; + bool firstConditionSet{ false }; + for (const auto& ci : include_configs) { + if (firstConditionSet) { + conditions << " Or "; + } + conditions << "('$(Configuration)|$(Platform)'=='" + + this->Configurations[ci] + "|" + this->Platform + "')"; + firstConditionSet = true; + } + e2.Attribute("Condition", conditions.str()); + } this->WriteSource(e2, si.Source); bool useNativeUnityBuild = false; @@ -2321,7 +2335,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { e2.Element("PrecompiledHeader", "NotUsing"); } - if (!exclude_configs.empty()) { + if (!isCSharp && !exclude_configs.empty()) { this->WriteExcludeFromBuild(e2, exclude_configs); } } diff --git a/Tests/CSharpOnly/CMakeLists.txt b/Tests/CSharpOnly/CMakeLists.txt index 195af05cb4f..f7928b675f9 100644 --- a/Tests/CSharpOnly/CMakeLists.txt +++ b/Tests/CSharpOnly/CMakeLists.txt @@ -9,8 +9,13 @@ source_group(nested FILES nested/lib1.cs) add_library(lib2 SHARED lib2.cs) add_executable(CSharpOnly csharponly.cs) - target_link_libraries(CSharpOnly lib1 lib2) +add_executable(CSharpConfigSpecific + $<$:config_specific_main_debug.cs> + $<$>:config_specific_main_not_debug.cs> + $<$:config_specific_main_no_exist.cs> + ) + add_custom_target(CSharpCustom ALL SOURCES empty.cs) add_custom_target(custom.cs ALL DEPENDS empty.txt) diff --git a/Tests/CSharpOnly/config_specific_main_debug.cs b/Tests/CSharpOnly/config_specific_main_debug.cs new file mode 100644 index 00000000000..b62524b74b3 --- /dev/null +++ b/Tests/CSharpOnly/config_specific_main_debug.cs @@ -0,0 +1,10 @@ +namespace CSharpConfigSpecific +{ + class CSharpConfigSpecific + { + public static void Main(string[] args) + { + return; + } + } +} diff --git a/Tests/CSharpOnly/config_specific_main_no_exist.cs b/Tests/CSharpOnly/config_specific_main_no_exist.cs new file mode 100644 index 00000000000..b62524b74b3 --- /dev/null +++ b/Tests/CSharpOnly/config_specific_main_no_exist.cs @@ -0,0 +1,10 @@ +namespace CSharpConfigSpecific +{ + class CSharpConfigSpecific + { + public static void Main(string[] args) + { + return; + } + } +} diff --git a/Tests/CSharpOnly/config_specific_main_not_debug.cs b/Tests/CSharpOnly/config_specific_main_not_debug.cs new file mode 100644 index 00000000000..b62524b74b3 --- /dev/null +++ b/Tests/CSharpOnly/config_specific_main_not_debug.cs @@ -0,0 +1,10 @@ +namespace CSharpConfigSpecific +{ + class CSharpConfigSpecific + { + public static void Main(string[] args) + { + return; + } + } +} From 31bbcd19055eddef68560b61b6f977dd6f0f17ff Mon Sep 17 00:00:00 2001 From: Kinan Mahdi Date: Thu, 29 Apr 2021 17:35:04 +0200 Subject: [PATCH 0341/1519] VS: Fix CSharp sources inside build directory Fixes: #22104 --- Source/cmVisualStudio10TargetGenerator.cxx | 7 +++++-- .../CSharpSourceGroup/cmake/AssemblyInfo.cs.in | 18 ++++++++++++++++++ .../VsCsharpSourceGroup-check.cmake | 1 + .../VS10Project/VsCsharpSourceGroup.cmake | 8 ++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 0255d60cf40..cc1586d2207 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -5037,7 +5037,9 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( { // For out of source files, we first check if a matching source group // for this file exists, otherwise we check if the path relative to current - // source- or binary-dir is used within the link and return that + // source- or binary-dir is used within the link and return that. + // In case of .cs files we can't do that automatically for files in the + // binary directory, because this leads to compilation errors. std::string link; std::string sourceGroupedFile; std::string const& fullFileName = source->GetFullPath(); @@ -5059,7 +5061,8 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( link = sourceGroupedFile; } else if (cmHasPrefix(fullFileName, srcDir)) { link = fullFileName.substr(srcDir.length() + 1); - } else if (cmHasPrefix(fullFileName, binDir)) { + } else if (!cmHasSuffix(fullFileName, ".cs") && + cmHasPrefix(fullFileName, binDir)) { link = fullFileName.substr(binDir.length() + 1); } else if (cmProp l = source->GetProperty("VS_CSHARP_Link")) { link = *l; diff --git a/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in b/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in new file mode 100644 index 00000000000..63e5a5ce70b --- /dev/null +++ b/Tests/RunCMake/VS10Project/CSharpSourceGroup/cmake/AssemblyInfo.cs.in @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +//General Information about an assembly is controlled through the following +//set of attributes. Change these attribute values to modify the information +//associated with an assembly. + +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake index 80d76e40ca3..9c9409cc4a3 100644 --- a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake +++ b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake @@ -13,6 +13,7 @@ set(SOURCE_GROUPS_TO_FIND "CSharpSourceGroup\\\\nested\\\\baz\\.cs" "CSharpSourceGroup\\\\images\\\\empty\\.bmp" "VsCsharpSourceGroup\\.png" + "AssemblyInfo\\.cs" ) foreach(GROUP_NAME IN LISTS SOURCE_GROUPS_TO_FIND) diff --git a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake index 510d71294bb..b67868f778e 100644 --- a/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake +++ b/Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake @@ -20,3 +20,11 @@ add_library(VsCsharpSourceGroup SHARED ${SRC_FILES} ${IMAGE_FILES} ${RESOURCE_FI source_group("CSharpSourceGroup" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/foo.cs) source_group("CSharpSourceGroup/nested" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/nested/baz.cs) source_group("Images" FILES ${IMAGE_FILES}) + +# Test covering CMake Issue 22104. +# Basically there should not be any link tags for files in the binary directory. +include(CSharpUtilities) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/cmake/AssemblyInfo.cs.in" "Properties/AssemblyInfo.cs") + +target_sources(VsCsharpSourceGroup PRIVATE "Properties/AssemblyInfo.cs") +csharp_set_designer_cs_properties("Properties/AssemblyInfo.cs") From b82052feb861f111b2373b2261dcf30a37c31b65 Mon Sep 17 00:00:00 2001 From: Smit tay Date: Sun, 2 May 2021 14:55:16 +0200 Subject: [PATCH 0342/1519] Help/dev/review: Clarify instructions to update existing merge requests --- Help/dev/review.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Help/dev/review.rst b/Help/dev/review.rst index 10ff87b95dc..198e100a951 100644 --- a/Help/dev/review.rst +++ b/Help/dev/review.rst @@ -20,8 +20,10 @@ creating a *merge request* ("MR"). The new MR will appear on the process is managed by the merge request page for the change. During the review process, the MR submitter should address review comments -or test failures by updating the MR with a (force-)push of the topic -branch. The update initiates a new round of review. +or test failures by updating their local topic branch to fix their commits +(e.g. via ``git commit --amend`` or ``git rebase -i``), and then issuing a +(force-)push of the topic branch to their remote (e.g. ``git push --force``). +This will automatically initiate a new round of review on the existing MR. We recommend that users enable the "Remove source branch when merge request is accepted" option when creating the MR or by editing it. From 229dd4215898ee61c941ed90a3f5175e58f01efb Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 3 May 2021 13:30:32 -0400 Subject: [PATCH 0343/1519] Change find_path scope and add quotes --- Modules/FindSWIG.cmake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/FindSWIG.cmake b/Modules/FindSWIG.cmake index 73aec893904..7c610d97841 100644 --- a/Modules/FindSWIG.cmake +++ b/Modules/FindSWIG.cmake @@ -91,7 +91,7 @@ unset(_SWIG_NAMES) if(SWIG_EXECUTABLE AND NOT SWIG_DIR) # Find default value for SWIG library directory - execute_process(COMMAND ${SWIG_EXECUTABLE} -swiglib + execute_process(COMMAND "${SWIG_EXECUTABLE}" -swiglib OUTPUT_VARIABLE _swig_output ERROR_VARIABLE _swig_error RESULT_VARIABLE _swig_result) @@ -105,17 +105,17 @@ if(SWIG_EXECUTABLE AND NOT SWIG_DIR) endif() unset(_msg) else() - string(REGEX REPLACE "[\n\r]+" ";" _SWIGLIB ${_swig_output}) + string(REGEX REPLACE "[\n\r]+" ";" _SWIG_LIB ${_swig_output}) endif() -endif() -# Find SWIG library directory -find_path(SWIG_DIR swig.swg PATHS ${_SWIGLIB} NO_CMAKE_FIND_ROOT_PATH) -unset(_SWIGLIB) + # Find SWIG library directory + find_path(SWIG_DIR swig.swg PATHS ${_SWIG_LIB} NO_CMAKE_FIND_ROOT_PATH) + unset(_SWIG_LIB) +endif() if(SWIG_EXECUTABLE AND SWIG_DIR AND NOT SWIG_VERSION) # Determine SWIG version - execute_process(COMMAND ${SWIG_EXECUTABLE} -version + execute_process(COMMAND "${SWIG_EXECUTABLE}" -version OUTPUT_VARIABLE _swig_output ERROR_VARIABLE _swig_output RESULT_VARIABLE _swig_result) @@ -129,7 +129,7 @@ if(SWIG_EXECUTABLE AND SWIG_DIR AND NOT SWIG_VERSION) endif() if(SWIG_EXECUTABLE AND SWIG_FIND_COMPONENTS) - execute_process(COMMAND ${SWIG_EXECUTABLE} -help + execute_process(COMMAND "${SWIG_EXECUTABLE}" -help OUTPUT_VARIABLE _swig_output ERROR_VARIABLE _swig_error RESULT_VARIABLE _swig_result) From 8f03c24bfc44ca27642ec70cce4bb8311d91df23 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 May 2021 13:33:25 -0400 Subject: [PATCH 0344/1519] gitlab-ci: add jobs testing Intel 2021.2.0 compilers on Linux --- .gitlab-ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 465dc2caa82..18844d1f024 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -363,6 +363,13 @@ test:intel2021.1.2-makefiles: CMAKE_CI_BUILD_NAME: intel2021.1.2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8 +test: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 + test:oneapi2021.1.1-makefiles: extends: - .cmake_test_linux_inteloneapi_makefiles @@ -377,6 +384,13 @@ test:oneapi2021.1.2-makefiles: CMAKE_CI_BUILD_NAME: oneapi2021.1.2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2021.1.2-el8 +test: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 + build:linux-x86_64-package: extends: - .linux_package From e8f0b75ff9dc564513f01c7b814f06adb6809b82 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 May 2021 14:28:55 -0400 Subject: [PATCH 0345/1519] Windows-GNU: Support duplicate object names when linking shared libraries Extend the change from commit 39d0ade07e (Windows-GNU: Support duplicate object names in large archives (#14874), 2014-04-14, v3.1.0-rc1~629^2~1) to apply to the temporary archive we create for linking shared libraries with MinGW tools. Issue: #21988 --- Modules/Platform/Windows-GNU.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index e50c2150805..d0003803bde 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -121,7 +121,7 @@ macro(__windows_compiler_gnu lang) CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}") set(CMAKE_${lang}_${rule} " -E rm -f /objects.a" - " cr /objects.a " + " qc /objects.a " "${CMAKE_${lang}_${rule}}" ) endforeach() From 3dd776ccfdd52271dc32db2b7495ec3c7449aa22 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 May 2021 14:35:54 -0400 Subject: [PATCH 0346/1519] Windows-Clang: Support duplicate object names in LTO archives Update the archive rules added by commit 6e3655db2c (Clang: add LTO support for GNU-command line clang on windows, 2019-07-08, v3.16.0-rc1~161^2~3) to match the `ar` convention we use for normal archives. Issue: #21988 --- Modules/Platform/Windows-Clang.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 7365ff58971..373be760d8e 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -57,8 +57,8 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) - set(CMAKE_${lang}_ARCHIVE_CREATE_IPO " cr ") - set(CMAKE_${lang}_ARCHIVE_APPEND_IPO " r ") + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO " qc ") + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO " q ") set(CMAKE_${lang}_ARCHIVE_FINISH_IPO " ") # Create archiving rules to support large object file lists for static libraries. From 75dadc45580b772584f5b3184ee78fbe7203f14b Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 3 May 2021 15:21:40 -0400 Subject: [PATCH 0347/1519] Help: Use relative path for IDE Integration guide link to preset schema This allows the integration guide to build as part of a larger set of documentation. --- Help/guide/ide-integration/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/guide/ide-integration/index.rst b/Help/guide/ide-integration/index.rst index addf93215cb..779883b9622 100644 --- a/Help/guide/ide-integration/index.rst +++ b/Help/guide/ide-integration/index.rst @@ -69,9 +69,9 @@ While reading, parsing, and evaluating the contents of ``CMakePresets.json`` is straightforward, it is not trivial. In addition to the documentation, IDE vendors may also wish to refer to the CMake source code and test cases for a better understanding of how to implement the format. -:download:`This file ` provides a machine-readable -JSON schema for the ``CMakePresets.json`` format that IDE vendors may find -useful for validation and providing editing assistance. +:download:`This file <../../manual/presets/schema.json>` provides a +machine-readable JSON schema for the ``CMakePresets.json`` format that IDE +vendors may find useful for validation and providing editing assistance. Configuring =========== From 576a07059ec53dc7f0c5356b5e2f10a92e26724d Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 4 May 2021 00:01:08 -0400 Subject: [PATCH 0348/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 48cf63ed9cb..d740db0ae0d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210503) +set(CMake_VERSION_PATCH 20210504) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 7398993f5b0444d6c7997d5bf14f96c982d07021 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Thu, 29 Apr 2021 10:45:05 -0400 Subject: [PATCH 0349/1519] Help: Document CMAKE_TLS_VERIFY variable explicitly Previously it was mentioned only in the `file` and `ExternalProject` documentation. --- Help/command/file.rst | 2 +- Help/manual/cmake-variables.7.rst | 1 + Help/variable/CMAKE_TLS_VERIFY.rst | 17 +++++++++++++++++ Modules/ExternalProject.cmake | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 Help/variable/CMAKE_TLS_VERIFY.rst diff --git a/Help/command/file.rst b/Help/command/file.rst index e1705263337..f46e55a056c 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -1070,7 +1070,7 @@ If neither ``NETRC`` option is given CMake will check variables For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL`` certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to check certificates. If neither ``TLS`` option is given CMake will check -variables ``CMAKE_TLS_VERIFY`` and ``CMAKE_TLS_CAINFO``, respectively. +variables :variable:`CMAKE_TLS_VERIFY` and ``CMAKE_TLS_CAINFO``, respectively. Additional options to ``DOWNLOAD`` are: diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 37ef053db41..c4aaa5943b9 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -245,6 +245,7 @@ Variables that Change Behavior /variable/CMAKE_SYSTEM_LIBRARY_PATH /variable/CMAKE_SYSTEM_PREFIX_PATH /variable/CMAKE_SYSTEM_PROGRAM_PATH + /variable/CMAKE_TLS_VERIFY /variable/CMAKE_USER_MAKE_RULES_OVERRIDE /variable/CMAKE_WARN_DEPRECATED /variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION diff --git a/Help/variable/CMAKE_TLS_VERIFY.rst b/Help/variable/CMAKE_TLS_VERIFY.rst new file mode 100644 index 00000000000..24f8a256a01 --- /dev/null +++ b/Help/variable/CMAKE_TLS_VERIFY.rst @@ -0,0 +1,17 @@ +CMAKE_TLS_VERIFY +---------------- + +Specify the default value for the :command:`file(DOWNLOAD)` and +:command:`file(UPLOAD)` commands' ``TLS_VERIFY`` options. +If not set, the default is *off*. + +This setting is also used by the :module:`ExternalProject` module +for internal calls to :command:`file(DOWNLOAD)`. + +TLS verification can help provide confidence that one is connecting +to the desired server. When downloading known content, one should +also use file hashes to verify it. + +.. code-block:: cmake + + set(CMAKE_TLS_VERIFY TRUE) diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 56525080cc2..45b6124de06 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -212,7 +212,7 @@ External Project Definition ``TLS_VERIFY `` Specifies whether certificate verification should be performed for https URLs. If this option is not provided, the default behavior is - determined by the ``CMAKE_TLS_VERIFY`` variable (see + determined by the :variable:`CMAKE_TLS_VERIFY` variable (see :command:`file(DOWNLOAD)`). If that is also not set, certificate verification will not be performed. In situations where ``URL_HASH`` cannot be provided, this option can be an alternative verification From c33fb2e664f81f23b3141190dd2476d6599060e6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 4 May 2021 12:44:14 -0400 Subject: [PATCH 0350/1519] BinUtils: Use more-private temporary variable names Since commit 4d786dfcfa (BinUtils: Avoid clobbering a variable named without a private prefix, 2021-04-06, v3.20.1~4^2) we use variables named `_tool` and `_name`, but these may still be common enough to affect project code. Use `_CMAKE_TOOL` and `_CMAKE_TOOL_NAME` instead, and unset them when finished. Fixes: #22140 --- Modules/CMakeFindBinUtils.cmake | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index f32266f5166..4ce45af6d12 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -123,19 +123,19 @@ else() list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE) endif() -foreach(_tool IN LISTS _CMAKE_TOOL_VARS) - foreach(_name IN LISTS _CMAKE_${_tool}_NAMES) +foreach(_CMAKE_TOOL IN LISTS _CMAKE_TOOL_VARS) + foreach(_CMAKE_TOOL_NAME IN LISTS _CMAKE_${_CMAKE_TOOL}_NAMES) if(NOT _CMAKE_TOOLCHAIN_PREFIX STREQUAL "") if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "") - list(PREPEND _CMAKE_${_tool}_NAMES ${_name}${_CMAKE_TOOLCHAIN_SUFFIX}) + list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX}) endif() - list(PREPEND _CMAKE_${_tool}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_name}) + list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}) endif() if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "") - list(PREPEND _CMAKE_${_tool}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_name}${_CMAKE_TOOLCHAIN_SUFFIX}) + list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX}) endif() endforeach() - find_program(CMAKE_${_tool} NAMES ${_CMAKE_${_tool}_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) endforeach() if(NOT CMAKE_RANLIB) @@ -154,12 +154,14 @@ if(CMAKE_PLATFORM_HAS_INSTALLNAME) endif() # Mark any tool cache entries as advanced. -foreach(_tool IN LISTS _CMAKE_TOOL_VARS) - get_property(_CMAKE_TOOL_CACHED CACHE CMAKE_${_tool} PROPERTY TYPE) +foreach(_CMAKE_TOOL IN LISTS _CMAKE_TOOL_VARS) + get_property(_CMAKE_TOOL_CACHED CACHE CMAKE_${_CMAKE_TOOL} PROPERTY TYPE) if(_CMAKE_TOOL_CACHED) - mark_as_advanced(CMAKE_${_tool}) + mark_as_advanced(CMAKE_${_CMAKE_TOOL}) endif() - unset(_CMAKE_${_tool}_NAMES) + unset(_CMAKE_${_CMAKE_TOOL}_NAMES) endforeach() unset(_CMAKE_TOOL_VARS) unset(_CMAKE_TOOL_CACHED) +unset(_CMAKE_TOOL_NAME) +unset(_CMAKE_TOOL) From fc2ac460435df289149e4faaf494e6b287071a8c Mon Sep 17 00:00:00 2001 From: friendlyanon Date: Sat, 1 May 2021 16:10:21 +0200 Subject: [PATCH 0351/1519] build_command: Add the PARALLEL_LEVEL argument Issue: #19712 --- Help/command/build_command.rst | 16 +++++++++++----- .../generate-cmake-build-command-parallel.rst | 4 ++++ Source/cmBuildCommand.cxx | 11 +++++++++-- Tests/RunCMake/build_command/ParallelLevel.cmake | 5 +++++ Tests/RunCMake/build_command/RunCMakeTest.cmake | 2 ++ 5 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/generate-cmake-build-command-parallel.rst create mode 100644 Tests/RunCMake/build_command/ParallelLevel.cmake diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst index 6659005bee2..a03979d10a4 100644 --- a/Help/command/build_command.rst +++ b/Help/command/build_command.rst @@ -8,23 +8,29 @@ This is mainly intended for internal use by the :module:`CTest` module. build_command( [CONFIGURATION ] + [PARALLEL_LEVEL ] [TARGET ] [PROJECT_NAME ] # legacy, causes warning ) Sets the given ```` to a command-line string of the form:: - --build . [--config ] [--target ...] [-- -i] + --build . [--config ] [--parallel ] [--target ...] [-- -i] where ```` is the location of the :manual:`cmake(1)` command-line -tool, and ```` and ```` are the values provided to the -``CONFIGURATION`` and ``TARGET`` options, if any. The trailing ``-- -i`` -option is added for :ref:`Makefile Generators` if policy :policy:`CMP0061` -is not set to ``NEW``. +tool, and ````, ```` and ```` are the values +provided to the ``CONFIGURATION``, ``PARALLEL_LEVEL`` and ``TARGET`` +options, if any. The trailing ``-- -i`` option is added for +:ref:`Makefile Generators` if policy :policy:`CMP0061` is not set to +``NEW``. When invoked, this ``cmake --build`` command line will launch the underlying build system tool. +.. versionadded:: 3.21 + The ``PARALLEL_LEVEL`` argument can be used to set the ``--parallel`` + flag. + .. code-block:: cmake build_command( ) diff --git a/Help/release/dev/generate-cmake-build-command-parallel.rst b/Help/release/dev/generate-cmake-build-command-parallel.rst new file mode 100644 index 00000000000..8d3b7d7949c --- /dev/null +++ b/Help/release/dev/generate-cmake-build-command-parallel.rst @@ -0,0 +1,4 @@ +generate-cmake-build-command-parallel +------------------------------------- + +* The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option. diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 4830343e13c..56b080aa6c3 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -28,12 +28,14 @@ bool MainSignature(std::vector const& args, std::string configuration; std::string project_name; std::string target; + std::string parallel; enum Doing { DoingNone, DoingConfiguration, DoingProjectName, - DoingTarget + DoingTarget, + DoingParallel }; Doing doing = DoingNone; for (unsigned int i = 1; i < args.size(); ++i) { @@ -43,6 +45,8 @@ bool MainSignature(std::vector const& args, doing = DoingProjectName; } else if (args[i] == "TARGET") { doing = DoingTarget; + } else if (args[i] == "PARALLEL_LEVEL") { + doing = DoingParallel; } else if (doing == DoingConfiguration) { doing = DoingNone; configuration = args[i]; @@ -52,6 +56,9 @@ bool MainSignature(std::vector const& args, } else if (doing == DoingTarget) { doing = DoingNone; target = args[i]; + } else if (doing == DoingParallel) { + doing = DoingNone; + parallel = args[i]; } else { status.SetError(cmStrCat("unknown argument \"", args[i], "\"")); return false; @@ -77,7 +84,7 @@ bool MainSignature(std::vector const& args, } std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand( - target, configuration, "", "", mf.IgnoreErrorsCMP0061()); + target, configuration, parallel, "", mf.IgnoreErrorsCMP0061()); mf.AddDefinition(variable, makecommand); diff --git a/Tests/RunCMake/build_command/ParallelLevel.cmake b/Tests/RunCMake/build_command/ParallelLevel.cmake new file mode 100644 index 00000000000..1d1e525f753 --- /dev/null +++ b/Tests/RunCMake/build_command/ParallelLevel.cmake @@ -0,0 +1,5 @@ +cmake_policy(SET CMP0061 NEW) +build_command(cmd PARALLEL_LEVEL 1) +if(NOT cmd MATCHES [[ --parallel "1"]]) + message(FATAL_ERROR "Cannot find the --parallel flag") +endif() diff --git a/Tests/RunCMake/build_command/RunCMakeTest.cmake b/Tests/RunCMake/build_command/RunCMakeTest.cmake index c3bef4c8178..030db0b5c27 100644 --- a/Tests/RunCMake/build_command/RunCMakeTest.cmake +++ b/Tests/RunCMake/build_command/RunCMakeTest.cmake @@ -14,3 +14,5 @@ if(RunCMake_GENERATOR MATCHES "Make") else() run_cmake(CMP0061-OLD-other) endif() + +run_cmake(ParallelLevel) From d2b856bc9219d7176ae8fd394843151e27021a8e Mon Sep 17 00:00:00 2001 From: friendlyanon Date: Sat, 1 May 2021 16:10:43 +0200 Subject: [PATCH 0352/1519] ctest_build: Add the PARALLEL_LEVEL argument Fixes: #19712 --- Help/command/ctest_build.rst | 8 ++++++++ .../dev/generate-cmake-build-command-parallel.rst | 2 ++ Source/CTest/cmCTestBuildCommand.cxx | 3 ++- Source/CTest/cmCTestBuildCommand.h | 1 + Tests/RunCMake/ctest_build/ParallelLevel-check.cmake | 11 +++++++++++ Tests/RunCMake/ctest_build/RunCMakeTest.cmake | 1 + 6 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/ctest_build/ParallelLevel-check.cmake diff --git a/Help/command/ctest_build.rst b/Help/command/ctest_build.rst index 4d6dc5a43a9..e05df1afcd4 100644 --- a/Help/command/ctest_build.rst +++ b/Help/command/ctest_build.rst @@ -7,6 +7,7 @@ Perform the :ref:`CTest Build Step` as a :ref:`Dashboard Client`. ctest_build([BUILD ] [APPEND] [CONFIGURATION ] + [PARALLEL_LEVEL ] [FLAGS ] [PROJECT_NAME ] [TARGET ] @@ -42,6 +43,13 @@ The options are: Otherwise the ``-C `` option given to the :manual:`ctest(1)` command will be used, if any. +``PARALLEL_LEVEL `` + .. versionadded:: 3.21 + + Specify the parallel level of the underlying build system. If not + specified, the :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` environment + variable will be checked. + ``FLAGS `` Pass additional arguments to the underlying build command. If not specified the ``CTEST_BUILD_FLAGS`` variable will be checked. diff --git a/Help/release/dev/generate-cmake-build-command-parallel.rst b/Help/release/dev/generate-cmake-build-command-parallel.rst index 8d3b7d7949c..1b8dd40acbb 100644 --- a/Help/release/dev/generate-cmake-build-command-parallel.rst +++ b/Help/release/dev/generate-cmake-build-command-parallel.rst @@ -2,3 +2,5 @@ generate-cmake-build-command-parallel ------------------------------------- * The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option. + +* The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option. diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 099d1e2de46..483c316a639 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -27,6 +27,7 @@ void cmCTestBuildCommand::BindArguments() this->Bind("CONFIGURATION"_s, this->Configuration); this->Bind("FLAGS"_s, this->Flags); this->Bind("PROJECT_NAME"_s, this->ProjectName); + this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel); } cmCTestBuildCommand::~cmCTestBuildCommand() = default; @@ -98,7 +99,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string buildCommand = this->GlobalGenerator->GenerateCMakeBuildCommand( - cmakeBuildTarget, cmakeBuildConfiguration, "", + cmakeBuildTarget, cmakeBuildConfiguration, this->ParallelLevel, cmakeBuildAdditionalFlags, this->Makefile->IgnoreErrorsCMP0061()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "SetMakeCommand:" << buildCommand << "\n", diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index 00dbcc451b6..1254dad9bbc 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -60,4 +60,5 @@ class cmCTestBuildCommand : public cmCTestHandlerCommand std::string Configuration; std::string Flags; std::string ProjectName; + std::string ParallelLevel; }; diff --git a/Tests/RunCMake/ctest_build/ParallelLevel-check.cmake b/Tests/RunCMake/ctest_build/ParallelLevel-check.cmake new file mode 100644 index 00000000000..f45d2a29f54 --- /dev/null +++ b/Tests/RunCMake/ctest_build/ParallelLevel-check.cmake @@ -0,0 +1,11 @@ +file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml") +if(build_xml_file) + file(STRINGS "${build_xml_file}" build_cmd LIMIT_COUNT 1 REGEX "") + if(NOT build_cmd MATCHES [[ --parallel "1"]]) + set(RunCMake_TEST_FAILED + "Build.xml does not have expected build command with --parallel flag" + ) + endif() +else() + set(RunCMake_TEST_FAILED "Build.xml not found") +endif() diff --git a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake index 072fbac2235..511cd71fbb4 100644 --- a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake @@ -10,6 +10,7 @@ function(run_ctest_build CASE_NAME) endfunction() run_ctest_build(BuildQuiet QUIET) +run_ctest_build(ParallelLevel PARALLEL_LEVEL 1) function(run_BuildFailure) set(CASE_CMAKELISTS_SUFFIX_CODE [[ From de0c8b4d98d71280abd585e17f6bd7b20d4de959 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 5 May 2021 00:01:07 -0400 Subject: [PATCH 0353/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d740db0ae0d..483eff448d6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210504) +set(CMake_VERSION_PATCH 20210505) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From dfaf55fbfd72e9706461592933df8686067b0e5f Mon Sep 17 00:00:00 2001 From: Danny Parker Date: Mon, 3 May 2021 15:10:05 +0100 Subject: [PATCH 0354/1519] Xcode: add extra '$(inherited)' entries using InheritBuildSettingAttribute. These have been added to: GCC_PREPROCESSOR_DEFINITIONS OTHER_CFLAGS OTHER_LDFLAGS This is to allow Cocoapods to work correctly as it uses xcconfig files to alter build settings in Xcode, and requires these build settings to inherit from their parent, not overwrite. --- Source/cmGlobalXCodeGenerator.cxx | 3 ++ .../InheritedParameters-check.cmake | 49 +++++++++++++++++++ .../XcodeProject/InheritedParameters.cmake | 8 +++ .../RunCMake/XcodeProject/RunCMakeTest.cmake | 1 + 4 files changed, 61 insertions(+) create mode 100644 Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake create mode 100644 Tests/RunCMake/XcodeProject/InheritedParameters.cmake diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d6909c3c260..3ed5ee35d43 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -4318,6 +4318,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->InheritBuildSettingAttribute(t, "SYSTEM_FRAMEWORK_SEARCH_PATHS"); this->InheritBuildSettingAttribute(t, "LIBRARY_SEARCH_PATHS"); this->InheritBuildSettingAttribute(t, "LD_RUNPATH_SEARCH_PATHS"); + this->InheritBuildSettingAttribute(t, "GCC_PREPROCESSOR_DEFINITIONS"); + this->InheritBuildSettingAttribute(t, "OTHER_CFLAGS"); + this->InheritBuildSettingAttribute(t, "OTHER_LDFLAGS"); } if (this->XcodeBuildSystem == BuildSystem::One) { diff --git a/Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake b/Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake new file mode 100644 index 00000000000..4fe42acb0ab --- /dev/null +++ b/Tests/RunCMake/XcodeProject/InheritedParameters-check.cmake @@ -0,0 +1,49 @@ +set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/InheritedParameters.xcodeproj/project.pbxproj") +if(NOT EXISTS "${xcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.") + return() +endif() + +set(found_inherited_GCC_PREPROCESSOR_DEFINITIONS 1) +set(found_inherited_OTHER_CFLAGS 1) +set(found_inherited_OTHER_LDFLAGS 1) + +file(STRINGS "${xcProjectFile}" lines) +foreach(line IN LISTS lines) + + if(line MATCHES [[GCC_PREPROCESSOR_DEFINITIONS]]) + if(NOT line MATCHES [["\$\(inherited\)"]]) + string(APPEND relevant_lines " ${line}\n") + set(found_inherited_GCC_PREPROCESSOR_DEFINITIONS 0) + endif() + endif() + + if(line MATCHES [[OTHER_CFLAGS]]) + if(NOT line MATCHES [["\$\(inherited\)"]]) + string(APPEND relevant_lines " ${line}\n") + set(found_inherited_OTHER_CFLAGS 0) + endif() + endif() + + if(line MATCHES [[OTHER_LDFLAGS]]) + if(NOT line MATCHES [["\$\(inherited\)"]]) + string(APPEND relevant_lines " ${line}\n") + set(found_inherited_OTHER_LDFLAGS 0) + endif() + endif() + +endforeach() + +if(NOT found_inherited_GCC_PREPROCESSOR_DEFINITIONS) + string(APPEND RunCMake_TEST_FAILED "Found missing inherited value for GCC_PREPROCESSOR_DEFINITIONS in\n ${xcProjectFile}\n") +endif() +if(NOT found_inherited_OTHER_CFLAGS) + string(APPEND RunCMake_TEST_FAILED "Found missing inherited value for OTHER_CFLAGS in\n ${xcProjectFile}\n") +endif() +if(NOT found_inherited_OTHER_LDFLAGS) + string(APPEND RunCMake_TEST_FAILED "Found missing inherited value for OTHER_LDFLAGS in\n ${xcProjectFile}\n") +endif() + +if(RunCMake_TEST_FAILED) + string(APPEND RunCMake_TEST_FAILED "Relevant lines include\n${relevant_lines}") +endif() diff --git a/Tests/RunCMake/XcodeProject/InheritedParameters.cmake b/Tests/RunCMake/XcodeProject/InheritedParameters.cmake new file mode 100644 index 00000000000..5b8ec7117dd --- /dev/null +++ b/Tests/RunCMake/XcodeProject/InheritedParameters.cmake @@ -0,0 +1,8 @@ +enable_language(C) + +add_compile_definitions(TEST_INHERITTEST) +string(APPEND CMAKE_C_FLAGS " -DTESTFLAG=\\\"TEST_INHERITTEST\\\"") + +add_executable(inherit_test main.c) + +target_link_libraries(inherit_test PRIVATE "TEST_INHERITTEST") diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index c8b75ebe7fe..26714c47f1e 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -4,6 +4,7 @@ run_cmake(ExplicitCMakeLists) run_cmake(ImplicitCMakeLists) run_cmake(InterfaceLibSources) run_cmake_with_options(SearchPaths -DCMAKE_CONFIGURATION_TYPES=Debug) +run_cmake(InheritedParameters) run_cmake(XcodeFileType) run_cmake(XcodeAttributeLocation) From fa16b462f1ac2df9f14596657ae81efc2c934675 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 5 May 2021 09:45:01 -0400 Subject: [PATCH 0355/1519] Tests: Fix RunCMake.CMakePresets example PATH format Since commit 94c955e508 (Tests: Test the CMakePresets.json example in the documentation, 2020-10-09, v3.19.0-rc1~8^2) we transform the documented preset example for testing by replacing the generator. Extend the transformation with a step to fix `PATH` env var syntax. --- Tests/RunCMake/CMakePresets/RunCMakeTest.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 02051d916f8..3b9806ab7ef 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -316,6 +316,9 @@ run_cmake_presets(OptionalGeneratorField -G "${RunCMake_GENERATOR}") # Test the example from the documentation file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example) string(REPLACE "\"generator\": \"Ninja\"" "\"generator\": \"@RunCMake_GENERATOR@\"" _example "${_example}") +if(CMAKE_HOST_WIN32) + string(REPLACE [["PATH": "$env{HOME}/ninja/bin:$penv{PATH}"]] [["PATH": "$env{HOME}/ninja/bin;$penv{PATH}"]] _example "${_example}") +endif() file(WRITE "${RunCMake_BINARY_DIR}/example.json.in" "${_example}") set(CMakePresets_FILE "${RunCMake_BINARY_DIR}/example.json.in") run_cmake_presets(DocumentationExample --preset=default) From 04c6e736f65306f434d99e2f4d6c365a9cc5201b Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Wed, 5 May 2021 09:19:02 -0400 Subject: [PATCH 0356/1519] KWSys 2021-05-05 (e9ca4104) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit e9ca4104e816c28e3fcf94ce69fd75ca9498f4a7 (master). Upstream Shortlog ----------------- Ben Boeckel (1): 99ffa991 cmake: clear some configure checks when the deployment target changes Martin Willers (2): bbf6cdef Terminal: Simplify CLICOLOR_FORCE check f308fcfb Terminal: Disable color output when CLICOLOR is set to 0 --- CMakeLists.txt | 10 ++++++++++ Terminal.c | 11 +++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf8543ec720..ef615b3fee1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,16 @@ foreach(p endif() endforeach() +# Some configure checks depend upon the deployment target. Clear checks when +# the deployment target changes. +if (APPLE) + if (NOT CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL KWSYS_LAST_OSX_DEPLOYMENT_TARGET) + unset(KWSYS_CXX_HAS_UTIMENSAT CACHE) + endif () + set(KWSYS_LAST_OSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}" + CACHE INTERNAL "remember the last deployment target to trigger configure rechecks") +endif () + #----------------------------------------------------------------------------- # If a namespace is not specified, use "kwsys" and enable testing. # This should be the case only when kwsys is not included inside diff --git a/Terminal.c b/Terminal.c index 9409d1b7642..57a68bfdbfd 100644 --- a/Terminal.c +++ b/Terminal.c @@ -167,12 +167,19 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, /* Force color according to http://bixense.com/clicolors/ convention. */ { const char* clicolor_force = getenv("CLICOLOR_FORCE"); - if (clicolor_force && *clicolor_force && - strcmp(clicolor_force, "0") != 0) { + if (clicolor_force && strcmp(clicolor_force, "0") != 0) { return 1; } } + /* Disable color according to http://bixense.com/clicolors/ convention. */ + { + const char* clicolor = getenv("CLICOLOR"); + if (clicolor && strcmp(clicolor, "0") == 0) { + return 0; + } + } + /* GNU make 4.1+ may tell us that its output is destined for a TTY. */ { const char* termout = getenv("MAKE_TERMOUT"); From 597209470809c23167c48e2dc85d6926a8faed16 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 5 May 2021 10:45:01 -0400 Subject: [PATCH 0357/1519] ObjectiveC: Respect OSX_ARCHITECTURES for OBJC Fix a typo from commit 940fc62962 (macOS: Respect OSX_ARCHITECTURES for ASM, 2020-08-21, v3.19.0-rc1~270^2). Fixes: #22152 --- Source/cmLocalGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 73b6fbcf6e0..dcf590a1426 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1877,7 +1877,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, std::vector archs; target->GetAppleArchs(config, archs); if (!archs.empty() && - (lang == "C" || lang == "CXX" || lang == "OBJ" || lang == "OBJCXX" || + (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX" || lang == "ASM")) { for (std::string const& arch : archs) { if (filterArch.empty() || filterArch == arch) { From 8a4f536be664c0ef6d79c2bf7fd547355ae59c81 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 12:51:05 -0400 Subject: [PATCH 0358/1519] NMake: Detect nmake version Run `nmake -?` and extract the version from its output. Use a timeout because Watcom tools come with a `nmake` tool that always waits for user input on `-?`. --- Source/cmGlobalNMakeMakefileGenerator.cxx | 34 +++++++++++++++++++++++ Source/cmGlobalNMakeMakefileGenerator.h | 3 ++ 2 files changed, 37 insertions(+) diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 36f583f0140..cbcd4b33be0 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -2,7 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalNMakeMakefileGenerator.h" +#include "cmsys/RegularExpression.hxx" + #include "cmDocumentationEntry.h" +#include "cmDuration.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmState.h" @@ -34,6 +37,37 @@ void cmGlobalNMakeMakefileGenerator::EnableLanguage( this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } +bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) +{ + if (!this->cmGlobalGenerator::FindMakeProgram(mf)) { + return false; + } + if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { + std::vector command; + command.emplace_back(*nmakeCommand); + command.emplace_back("-?"); + std::string out; + std::string err; + if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr, + cmSystemTools::OUTPUT_NONE, + cmDuration(30))) { + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Running\n '", cmJoin(command, "' '"), + "'\n" + "failed with:\n ", + err)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + cmsys::RegularExpression regex( + "Program Maintenance Utility Version ([1-9][0-9.]+)"); + if (regex.find(err)) { + this->NMakeVersion = regex.match(1); + } + } + return true; +} + void cmGlobalNMakeMakefileGenerator::GetDocumentation( cmDocumentationEntry& entry) { diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index abe64ff9634..c23eef81410 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -55,6 +55,9 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; private: + std::string NMakeVersion; + bool FindMakeProgram(cmMakefile* mf) override; + void PrintCompilerAdvice(std::ostream& os, std::string const& lang, const char* envVar) const override; }; From 186c9bff5342c1e8e73fce9cf361b6de5dda3f28 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 28 Apr 2021 13:14:31 -0400 Subject: [PATCH 0359/1519] NMake: Check nmake version for support of UTF-8 NMake version 9 and above support UTF-8 encoded makefiles with a BOM. --- Source/cmGlobalNMakeMakefileGenerator.cxx | 7 +++++++ Source/cmGlobalNMakeMakefileGenerator.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index cbcd4b33be0..313f39b5e8c 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -63,11 +63,18 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) "Program Maintenance Utility Version ([1-9][0-9.]+)"); if (regex.find(err)) { this->NMakeVersion = regex.match(1); + this->CheckNMakeFeatures(); } } return true; } +void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures() +{ + this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9"); +} + void cmGlobalNMakeMakefileGenerator::GetDocumentation( cmDocumentationEntry& entry) { diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index c23eef81410..ed52378347e 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -55,8 +55,10 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; private: + bool NMakeSupportsUTF8 = false; std::string NMakeVersion; bool FindMakeProgram(cmMakefile* mf) override; + void CheckNMakeFeatures(); void PrintCompilerAdvice(std::ostream& os, std::string const& lang, const char* envVar) const override; From f3f57cc4edd528aaf0b8d8633d5f9990f0d804af Mon Sep 17 00:00:00 2001 From: Amine Najahi Date: Thu, 22 Apr 2021 20:26:30 +0100 Subject: [PATCH 0360/1519] NMake: Use UTF-8 with BOM if supported by nmake Fixes: #21792 --- Help/release/dev/nmake-utf8.rst | 5 +++++ Source/cmGeneratedFileStream.cxx | 5 +++++ Source/cmGlobalNMakeMakefileGenerator.h | 2 +- Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cm_codecvt.cxx | 1 + Source/cm_codecvt.hxx | 1 + 6 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/nmake-utf8.rst diff --git a/Help/release/dev/nmake-utf8.rst b/Help/release/dev/nmake-utf8.rst new file mode 100644 index 00000000000..ebbb45b0189 --- /dev/null +++ b/Help/release/dev/nmake-utf8.rst @@ -0,0 +1,5 @@ +nmake-utf8 +---------- + +* The :generator:`NMake Makefiles` generator now encodes the generated + makefiles as UTF-8 with a BOM when using ``nmake`` from VS 9 or above. diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 43f384ab085..06778b1ebc6 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -42,6 +42,11 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name, #else static_cast(encoding); #endif + if (encoding == codecvt::UTF8_WITH_BOM) { + // Write the BOM encoding header into the file + char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; + this->write(magic, 3); + } } cmGeneratedFileStream::~cmGeneratedFileStream() diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index ed52378347e..402b89fda9e 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -31,7 +31,7 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 /** Get encoding used by generator for makefile files */ codecvt::Encoding GetMakefileEncoding() const override { - return codecvt::ANSI; + return this->NMakeSupportsUTF8 ? codecvt::UTF8_WITH_BOM : codecvt::ANSI; } /** Get the documentation entry for this generator. */ diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index fa469edac3b..5b6c58dfb2a 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -2058,7 +2058,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( // Create the response file. std::string responseFileNameFull = cmStrCat(this->TargetBuildDirectoryFull, '/', name); - cmGeneratedFileStream responseStream(responseFileNameFull); + cmGeneratedFileStream responseStream( + responseFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); responseStream.SetCopyIfDifferent(true); responseStream << options << "\n"; diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index 15f83e0f787..216d3f01752 100644 --- a/Source/cm_codecvt.cxx +++ b/Source/cm_codecvt.cxx @@ -31,6 +31,7 @@ codecvt::codecvt(Encoding e) // We don't know which ANSI encoding to use for other platforms than // Windows so we don't do any conversion there case codecvt::UTF8: + case codecvt::UTF8_WITH_BOM: // Assume internal encoding is UTF-8 case codecvt::None: // No encoding diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index 1860211a15b..b73204f2aa9 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -14,6 +14,7 @@ public: { None, UTF8, + UTF8_WITH_BOM, ANSI }; From 2c9e623e3194519da0714c77cba48592d6658cda Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 5 May 2021 09:33:39 -0400 Subject: [PATCH 0361/1519] Find{BLAS,LAPACK}: Add support for the NVHPC LAPACK library --- Modules/FindBLAS.cmake | 8 +++++++- Modules/FindLAPACK.cmake | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 024ff14632c..0f8360a9ddc 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -57,6 +57,7 @@ The following variables may be set to influence this module's behavior: * ``EML_mt`` * ``Fujitsu_SSL2`` (Fujitsu serial blas / lapack) * ``Fujitsu_SSL2BLAMP`` (Fujitsu parallel blas / lapack) + * ``NVHPC`` * ``Generic`` .. versionadded:: 3.6 @@ -82,6 +83,9 @@ The following variables may be set to influence this module's behavior: Elbrus Math Library support (``EML``, ``EML_mt``). Fujitsu SSL2 Library support (``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``) + .. versionadded:: 3.21 + NVHPC support + ``BLA_F95`` if ``ON`` tries to find the BLAS95 interfaces @@ -1062,7 +1066,9 @@ if(NOT BLAS_LIBRARIES AND endif() # Generic BLAS library? -if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All") +if(BLA_VENDOR STREQUAL "Generic" OR + BLA_VENDOR STREQUAL "NVHPC" OR + BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index ab6214b48d5..fa2300d6b0d 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -47,6 +47,7 @@ The following variables may be set to influence this module's behavior: * ``EML_mt`` * ``Fujitsu_SSL2`` (Fujitsu serial blas / lapack) * ``Fujitsu_SSL2BLAMP`` (Fujitsu parallel blas / lapack) + * ``NVHPC`` * ``Generic`` .. versionadded:: 3.6 @@ -72,6 +73,9 @@ The following variables may be set to influence this module's behavior: Elbrus Math Library support (``EML``, ``EML_mt``). Fujitsu SSL2 Library support (``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``) + .. versionadded:: 3.21 + NVHPC support + ``BLA_F95`` if ``ON`` tries to find the BLAS95/LAPACK95 interfaces @@ -615,6 +619,22 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) unset(_ssl2_suffix) endif() + # NVHPC Library? + if(NOT LAPACK_LIBRARIES + AND BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All") + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "lapack" + "-fortranlibs" + "" + "" + "${BLAS_LIBRARIES}" + ) + endif() + # Generic LAPACK library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "Generic" From 71665c8cb9ab460dccfaf04ce152ad637760361d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 5 May 2021 14:15:04 -0400 Subject: [PATCH 0362/1519] gitlab-ci: Clarify conditions enabling jobs for continuous build of stage --- .gitlab/rules.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/rules.yml b/.gitlab/rules.yml index ac1bf600680..4ac67e82e7a 100644 --- a/.gitlab/rules.yml +++ b/.gitlab/rules.yml @@ -8,7 +8,7 @@ when: on_success - if: '$CMAKE_CI_JOB_NIGHTLY == "true"' when: never - - if: '($CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != "" && $CI_COMMIT_BRANCH == $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH && $CMAKE_CI_JOB_CONTINUOUS == "true")' + - if: '$CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != null && $CI_COMMIT_BRANCH != null && $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH == $CI_COMMIT_BRANCH && $CMAKE_CI_JOB_CONTINUOUS == "true"' when: delayed start_in: 5 minutes - if: '($CMAKE_CI_NO_MR == "true" && $CI_MERGE_REQUEST_ID)' @@ -28,7 +28,7 @@ when: on_success - if: '$CMAKE_CI_JOB_NIGHTLY == "true"' when: never - - if: '($CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != "" && $CI_COMMIT_BRANCH == $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH && $CMAKE_CI_JOB_CONTINUOUS == "true")' + - if: '$CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != null && $CI_COMMIT_BRANCH != null && $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH == $CI_COMMIT_BRANCH && $CMAKE_CI_JOB_CONTINUOUS == "true"' when: on_success - if: '($CMAKE_CI_NO_MR == "true" && $CI_MERGE_REQUEST_ID)' when: never From 4cab7a6fc554672130494bf12cdb877dbcbf7a44 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 6 May 2021 00:01:10 -0400 Subject: [PATCH 0363/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 483eff448d6..840686156a8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210505) +set(CMake_VERSION_PATCH 20210506) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From df0e50d756c4d4187a3b6fa20fc036669ea8c07c Mon Sep 17 00:00:00 2001 From: Martin Willers Date: Sun, 2 May 2021 22:12:51 +0200 Subject: [PATCH 0364/1519] CTest: Add env var CLICOLOR to disable color output Based on the implementation in Terminal.c:kwsysTerminalStreamIsVT100. --- Source/cmCTest.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 79a39255090..7534e37f80f 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2215,6 +2215,10 @@ bool cmCTest::ColoredOutputSupportedByConsole() !clicolor_force.empty() && clicolor_force != "0") { return true; } + std::string clicolor; + if (cmSystemTools::GetEnv("CLICOLOR", clicolor) && clicolor == "0") { + return false; + } return ConsoleIsNotDumb(); #endif } From 760bdfb26ee94569287991d12e988573ab260177 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Thu, 6 May 2021 11:48:52 -0400 Subject: [PATCH 0365/1519] KWSys 2021-05-06 (2fa93cfc) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 2fa93cfca6291e8eaffa2a34d2d7908c93e64a6c (master). Upstream Shortlog ----------------- Brad King (1): 5c6539ca Terminal: Revert "Simplify CLICOLOR_FORCE check" --- Terminal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Terminal.c b/Terminal.c index 57a68bfdbfd..20bb5fe6d0c 100644 --- a/Terminal.c +++ b/Terminal.c @@ -167,7 +167,8 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, /* Force color according to http://bixense.com/clicolors/ convention. */ { const char* clicolor_force = getenv("CLICOLOR_FORCE"); - if (clicolor_force && strcmp(clicolor_force, "0") != 0) { + if (clicolor_force && *clicolor_force && + strcmp(clicolor_force, "0") != 0) { return 1; } } From 5e931c5a97380cea3989084007aed3e797fc4438 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 6 May 2021 11:23:50 -0400 Subject: [PATCH 0366/1519] CUDA: improve regex for CUDA Toolkit root from nvcc verbose output The original regular expression was greedy and would match any environment variable ending with `TOP` (like `DESKTOP`). This is an issue on windows where `nvcc -v` would output all environment variables before the compiler's verbose output. To resolve this issue we use a tighter match algorithm that looks for `#$ TOP=` instead of `TOP=`. Fixes: #22158 --- Modules/CMakeDetermineCUDACompiler.cmake | 2 +- Modules/FindCUDA.cmake | 2 +- Modules/FindCUDAToolkit.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 1ba537a3eb0..e7de9cc9386 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -181,7 +181,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) # itself, allowing us to support numerous different scattered toolkit layouts execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda" OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT) - if(_CUDA_NVCC_OUT MATCHES "TOP=([^\r\n]*)") + if(_CUDA_NVCC_OUT MATCHES "\\#\\$ TOP=([^\r\n]*)") get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_MATCH_1}" ABSOLUTE) else() get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY) diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 620e32af582..16d75711b2b 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -839,7 +839,7 @@ if(NOT CUDA_TOOLKIT_ROOT_DIR AND NOT CMAKE_CROSSCOMPILING) # itself, allowing us to support numerous different scattered toolkit layouts execute_process(COMMAND ${CUDA_TOOLKIT_ROOT_DIR_NVCC} "-v" "__cmake_determine_cuda" OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT) - if(_CUDA_NVCC_OUT MATCHES "TOP=([^\r\n]*)") + if(_CUDA_NVCC_OUT MATCHES "\\#\\$ TOP=([^\r\n]*)") get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CMAKE_MATCH_1}" ABSOLUTE CACHE) else() get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CUDA_TOOLKIT_ROOT_DIR_NVCC}" DIRECTORY) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index de2b0688304..8801cb1bff2 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -524,7 +524,7 @@ else() # NVIDIA HPC SDK, and distro's splayed layouts execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda" OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT) - if(_CUDA_NVCC_OUT MATCHES "TOP=([^\r\n]*)") + if(_CUDA_NVCC_OUT MATCHES "\\#\\$ TOP=([^\r\n]*)") get_filename_component(CUDAToolkit_BIN_DIR "${CMAKE_MATCH_1}/bin" ABSOLUTE) else() get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY) From 284d12a426879a61adc61fb210e35b01f1a1e1ad Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima <15070-e-kwsm@users.noreply.gitlab.com> Date: Tue, 4 May 2021 02:43:34 +0900 Subject: [PATCH 0367/1519] Fujitsu: Make explicit Fortran preprocessing under Ninja more robust Tell the Fortran compiler to write preprocessor output directly to a file, as we do for the GNU compiler. The previous "redirect stdout" approach could break checks using flags that add information to stdout when called with `-###`. Fixes: #22156 --- Modules/Compiler/Fujitsu-Fortran.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Compiler/Fujitsu-Fortran.cmake b/Modules/Compiler/Fujitsu-Fortran.cmake index 0f687bc21b7..face2d68503 100644 --- a/Modules/Compiler/Fujitsu-Fortran.cmake +++ b/Modules/Compiler/Fujitsu-Fortran.cmake @@ -5,7 +5,7 @@ set(CMAKE_Fortran_SUBMODULE_SEP ".") set(CMAKE_Fortran_SUBMODULE_EXT ".smod") set(CMAKE_Fortran_PREPROCESS_SOURCE - " -Cpp -E > ") + " -Cpp -P -o ") set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-Cpp") set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-Fixed") From f2a4b879b1cddce84c56de63809e831aea53d1ba Mon Sep 17 00:00:00 2001 From: Frank Lange Date: Fri, 30 Apr 2021 22:56:39 +0200 Subject: [PATCH 0368/1519] FindProtobuf: Add PLUGIN parameter to protobuf_generate This allows for example reusing the function for generating gRPC code by specifying which grpc plugin to use. --- Modules/FindProtobuf.cmake | 8 ++++++-- Tests/FindProtobuf/CMakeLists.txt | 1 + Tests/FindProtobuf/Test/CMakeLists.txt | 13 +++++++++++++ Tests/FindProtobuf/Test/main-generate-grpc.cxx | 6 ++++++ Tests/FindProtobuf/Test/msgs/example_service.proto | 8 ++++++++ 5 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 Tests/FindProtobuf/Test/main-generate-grpc.cxx create mode 100644 Tests/FindProtobuf/Test/msgs/example_service.proto diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index 4b1e336893a..c73a2d81ab0 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -140,7 +140,7 @@ Example: function(protobuf_generate) set(_options APPEND_PATH DESCRIPTORS) - set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR) + set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN) if(COMMAND target_sources) list(APPEND _singleargs TARGET) endif() @@ -171,6 +171,10 @@ function(protobuf_generate) set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}:") endif() + if(protobuf_generate_PLUGIN) + set(_plugin "--plugin=${protobuf_generate_PLUGIN}") + endif() + if(NOT protobuf_generate_GENERATE_EXTENSIONS) if(protobuf_generate_LANGUAGE STREQUAL cpp) set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc) @@ -245,7 +249,7 @@ function(protobuf_generate) add_custom_command( OUTPUT ${_generated_srcs} COMMAND protobuf::protoc - ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_dll_desc_out} ${_protobuf_include_path} ${_abs_file} + ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_dll_desc_out} ${_protobuf_include_path} ${_abs_file} DEPENDS ${_abs_file} protobuf::protoc COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}" VERBATIM ) diff --git a/Tests/FindProtobuf/CMakeLists.txt b/Tests/FindProtobuf/CMakeLists.txt index 1cdb2ae13be..b4ca29bc73a 100644 --- a/Tests/FindProtobuf/CMakeLists.txt +++ b/Tests/FindProtobuf/CMakeLists.txt @@ -6,5 +6,6 @@ add_test(NAME FindProtobuf.Test COMMAND ${build_generator_args} --build-project TestFindProtobuf --build-options ${build_options} + "-DCMake_TEST_FindProtobuf_gRPC=${CMake_TEST_FindProtobuf_gRPC}" --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) diff --git a/Tests/FindProtobuf/Test/CMakeLists.txt b/Tests/FindProtobuf/Test/CMakeLists.txt index fc6b37e9510..84041eaf4ef 100644 --- a/Tests/FindProtobuf/Test/CMakeLists.txt +++ b/Tests/FindProtobuf/Test/CMakeLists.txt @@ -52,3 +52,16 @@ target_include_directories(test_desc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(test_desc msgs ${Protobuf_LIBRARIES}) target_compile_features(test_desc PRIVATE cxx_std_11) add_test(NAME test_desc COMMAND test_desc ${DESC_PROTO_DESC}) + +if(CMake_TEST_FindProtobuf_gRPC) + find_program(gRPC_CPP_PLUGIN grpc_cpp_plugin) + add_library(msgs_grpc msgs/example_service.proto) + target_include_directories(msgs_grpc PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + target_link_libraries(msgs_grpc PUBLIC ${Protobuf_LIBRARIES}) + protobuf_generate(TARGET msgs_grpc LANGUAGE cpp) + protobuf_generate(TARGET msgs_grpc LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${gRPC_CPP_PLUGIN}") + + add_executable(test_generate_grpc main-generate-grpc.cxx) + target_link_libraries(test_generate_grpc PRIVATE msgs_grpc) + add_test(NAME test_generate_grpc COMMAND test_generate_grpc) +endif() diff --git a/Tests/FindProtobuf/Test/main-generate-grpc.cxx b/Tests/FindProtobuf/Test/main-generate-grpc.cxx new file mode 100644 index 00000000000..070c6b46e7b --- /dev/null +++ b/Tests/FindProtobuf/Test/main-generate-grpc.cxx @@ -0,0 +1,6 @@ +#include + +int main() +{ + return 0; +} diff --git a/Tests/FindProtobuf/Test/msgs/example_service.proto b/Tests/FindProtobuf/Test/msgs/example_service.proto new file mode 100644 index 00000000000..f35eeb53899 --- /dev/null +++ b/Tests/FindProtobuf/Test/msgs/example_service.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package example.msgs; + +import "google/protobuf/empty.proto"; + +service ExampleService { + rpc nothing(google.protobuf.Empty) returns (google.protobuf.Empty) {} +} From d71a7cc19d6e03f89581efdaa8d63db216184d40 Mon Sep 17 00:00:00 2001 From: Jens Carl Date: Thu, 6 May 2021 12:45:56 -0700 Subject: [PATCH 0369/1519] install(FILES): Allow installation of symlinks to directory Allow symbolic links to a directory to be installed via install(FILES ...). Fixes: #22159 --- Source/cmInstallCommand.cxx | 3 ++- Tests/RunCMake/install/FILES-directory-result.txt | 1 + Tests/RunCMake/install/FILES-directory-stderr.txt | 1 + Tests/RunCMake/install/FILES-directory.cmake | 7 +++++++ Tests/RunCMake/install/FILES-symlink-to-directory.cmake | 9 +++++++++ Tests/RunCMake/install/RunCMakeTest.cmake | 4 ++++ 6 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/install/FILES-directory-result.txt create mode 100644 Tests/RunCMake/install/FILES-directory-stderr.txt create mode 100644 Tests/RunCMake/install/FILES-directory.cmake create mode 100644 Tests/RunCMake/install/FILES-symlink-to-directory.cmake diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 7788db3bb86..8a34f91a39f 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1482,7 +1482,8 @@ bool Helper::MakeFilesFullPath(const char* modeName, } // Make sure the file is not a directory. - if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) { + if (gpos == std::string::npos && !cmSystemTools::FileIsSymlink(file) && + cmSystemTools::FileIsDirectory(file)) { this->SetError( cmStrCat(modeName, " given directory \"", relFile, "\" to install.")); return false; diff --git a/Tests/RunCMake/install/FILES-directory-result.txt b/Tests/RunCMake/install/FILES-directory-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/FILES-directory-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/FILES-directory-stderr.txt b/Tests/RunCMake/install/FILES-directory-stderr.txt new file mode 100644 index 00000000000..46990373217 --- /dev/null +++ b/Tests/RunCMake/install/FILES-directory-stderr.txt @@ -0,0 +1 @@ +install FILES given directory diff --git a/Tests/RunCMake/install/FILES-directory.cmake b/Tests/RunCMake/install/FILES-directory.cmake new file mode 100644 index 00000000000..1199cf77cc4 --- /dev/null +++ b/Tests/RunCMake/install/FILES-directory.cmake @@ -0,0 +1,7 @@ +set(dst "${CMAKE_CURRENT_BINARY_DIR}/dst") +set(src "${CMAKE_CURRENT_BINARY_DIR}/src") + +file(MAKE_DIRECTORY "${dst}") +file(MAKE_DIRECTORY "${src}") + +install(FILES "${src}" DESTINATION "${dst}") diff --git a/Tests/RunCMake/install/FILES-symlink-to-directory.cmake b/Tests/RunCMake/install/FILES-symlink-to-directory.cmake new file mode 100644 index 00000000000..ed76470084a --- /dev/null +++ b/Tests/RunCMake/install/FILES-symlink-to-directory.cmake @@ -0,0 +1,9 @@ +set(dst "${CMAKE_CURRENT_BINARY_DIR}/dst") +set(src "${CMAKE_CURRENT_BINARY_DIR}/src") +set(lnk "${CMAKE_CURRENT_BINARY_DIR}/lnk") + +file(MAKE_DIRECTORY "${dst}") +file(MAKE_DIRECTORY "${src}") +file(CREATE_LINK "${src}" "${lnk}" SYMBOLIC) + +install(FILES "${lnk}" DESTINATION "${dst}") diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index efd03df6f36..6fb72fc3fac 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -93,6 +93,10 @@ run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all) run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc) run_cmake(FILES-DESTINATION-TYPE) run_cmake(DIRECTORY-DESTINATION-TYPE) +run_cmake(FILES-directory) +if(NOT WIN32) + run_cmake(FILES-symlink-to-directory) +endif() set(RunCMake_TEST_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=Debug") run_install_test(FILES-RENAME) From f0ecd9130131a72cef3f1d2fd6a9ac762db61aa2 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 7 May 2021 00:01:11 -0400 Subject: [PATCH 0370/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 840686156a8..3cf01e4096e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210506) +set(CMake_VERSION_PATCH 20210507) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d7522b8f864db8df25b99eeabc625e55ad690a3e Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 May 2021 10:39:05 -0400 Subject: [PATCH 0371/1519] cmSystemTools: Improve CreateLink and CreateSymlink error codes In commit 7f89053953 (cmSystemTools: Return KWSys Status from CreateLink and CreateSymlink, 2021-04-15) we just took the `-err` from libuv and treated it as a POSIX error. This is accurate on POSIX, but on Windows does not match the POSIX error codes. Use `uv_fs_get_system_error` to get the actual system error code. This requires libuv 1.38 or higher. Require that for Windows, but fall back to the previous approach on POSIX. --- CMakeLists.txt | 6 +++++- Source/cmSystemTools.cxx | 18 +++++++++++++++--- .../E_create_hardlink-no-directory-stderr.txt | 2 +- ...dlink-unresolved-symlink-prereq-check.cmake | 2 +- .../E_create_symlink-broken-create-check.cmake | 2 +- ...E_create_symlink-broken-replace-check.cmake | 2 +- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 4 ++-- 7 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f03c39cbf0..44b433ac8f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -644,7 +644,11 @@ macro (CMAKE_BUILD_UTILITIES) #--------------------------------------------------------------------- # Build libuv library. if(CMAKE_USE_SYSTEM_LIBUV) - find_package(LibUV 1.10.0) + if(WIN32) + find_package(LibUV 1.38.0) + else() + find_package(LibUV 1.10.0) + endif() if(NOT LIBUV_FOUND) message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!") diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9e46dab2a3f..ab42810feb2 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -3173,9 +3173,15 @@ cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName, flags, nullptr); cmsys::Status status; if (err) { +#if defined(_WIN32) + status = cmsys::Status::Windows(uv_fs_get_system_error(&req)); +#elif UV_VERSION_MAJOR > 1 || (UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR >= 38) + status = cmsys::Status::POSIX(uv_fs_get_system_error(&req)); +#else status = cmsys::Status::POSIX(-err); - std::string e = - "failed to create symbolic link '" + newName + "': " + uv_strerror(err); +#endif + std::string e = cmStrCat("failed to create symbolic link '", newName, + "': ", status.GetString()); if (errorMessage) { *errorMessage = std::move(e); } else { @@ -3194,9 +3200,15 @@ cmsys::Status cmSystemTools::CreateLink(std::string const& origName, uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr); cmsys::Status status; if (err) { +#if defined(_WIN32) + status = cmsys::Status::Windows(uv_fs_get_system_error(&req)); +#elif UV_VERSION_MAJOR > 1 || (UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR >= 38) + status = cmsys::Status::POSIX(uv_fs_get_system_error(&req)); +#else status = cmsys::Status::POSIX(-err); +#endif std::string e = - "failed to create link '" + newName + "': " + uv_strerror(err); + cmStrCat("failed to create link '", newName, "': ", status.GetString()); if (errorMessage) { *errorMessage = std::move(e); } else { diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt index 21e60eec020..63a10d83558 100644 --- a/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt +++ b/Tests/RunCMake/CommandLine/E_create_hardlink-no-directory-stderr.txt @@ -1 +1 @@ -^CMake Error: failed to create link .* no such file or directory +^CMake Error: failed to create link '[^']+': [A-Za-z] diff --git a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake index 5b97aecc0d9..d92554af4d9 100644 --- a/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake +++ b/Tests/RunCMake/CommandLine/E_create_hardlink-unresolved-symlink-prereq-check.cmake @@ -1,3 +1,3 @@ -if(${actual_stderr_var} MATCHES "operation not permitted") +if(${actual_stderr_var} MATCHES "A required privilege is not held by the client") unset(msg) endif() diff --git a/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake b/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake index 5df5f2fb70a..43573bfe9f9 100644 --- a/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake +++ b/Tests/RunCMake/CommandLine/E_create_symlink-broken-create-check.cmake @@ -1,4 +1,4 @@ -if(${actual_stderr_var} MATCHES "operation not permitted") +if(${actual_stderr_var} MATCHES "A required privilege is not held by the client") unset(msg) else() if(NOT IS_SYMLINK ${RunCMake_TEST_BINARY_DIR}/L) diff --git a/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake b/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake index d37df016904..639c2237ee8 100644 --- a/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake +++ b/Tests/RunCMake/CommandLine/E_create_symlink-broken-replace-check.cmake @@ -1,4 +1,4 @@ -if(${actual_stderr_var} MATCHES "operation not permitted") +if(${actual_stderr_var} MATCHES "A required privilege is not held by the client") unset(msg) else() if(NOT IS_DIRECTORY ${RunCMake_TEST_BINARY_DIR}/L) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 78c35087137..a1edbd0f2b4 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -359,7 +359,7 @@ run_cmake_command(E_create_symlink-missing-dir # These tests are special on Windows since it will only fail if the user # running the test does not have the priveldge to create symlinks. If this # happens we clear the msg in the -check.cmake and say that the test passes -set(RunCMake_DEFAULT_stderr "(operation not permitted)?") +set(RunCMake_DEFAULT_stderr "(A required privilege is not held by the client)?") set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/E_create_symlink-broken-build) set(RunCMake_TEST_NO_CLEAN 1) @@ -403,7 +403,7 @@ run_cmake_command(E_create_hardlink-no-directory #On Windows, if the user does not have sufficient privileges #don't fail this test -set(RunCMake_DEFAULT_stderr "(operation not permitted)?") +set(RunCMake_DEFAULT_stderr "(A required privilege is not held by the client)?") run_cmake_command(E_create_hardlink-unresolved-symlink-prereq ${CMAKE_COMMAND} -E create_symlink ${dir}/1 ${dir}/1-symlink ) From 79be37b94e7353ec056e6343ba293ce1b60627d4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 7 May 2021 08:51:40 -0400 Subject: [PATCH 0372/1519] FindBoost: Add support for Boost 1.76 Update the list of known versions. Run the command cmake -DBOOST_DIR=/path/to/boost_1_76_0 \ -P Utilities/Scripts/BoostScanDeps.cmake to extract dependencies from the 1.76.0 source tree. They are the same as 1.75's dependencies, so just update the version check for warning about newer versions. Fixes: #22167 --- Modules/FindBoost.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index f8887ad2bec..d31f925cb60 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -1350,7 +1350,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.76.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) + if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() endif() @@ -1622,7 +1622,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.75.0" "1.75" "1.74.0" "1.74" + "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" From 07727928f9e243fd472767c27596b618ada4b5d4 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Fri, 7 May 2021 09:23:56 -0400 Subject: [PATCH 0373/1519] KWSys 2021-05-07 (979d7db0) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 979d7db0d534b25cc41f5defdc121dce0f9da10b (master). Upstream Shortlog ----------------- Ali Mohammad Pur (1): 1ea48581 ProcessUNIX: Fix kwsysProcessesSignalHandler() if !KWSYSPE_USE_SIGINFO Brad King (1): 8f3c4879 Status: Fix GetWindows return type Georg Schwab (2): fd2ec23d SystemTools: Implement FileIsSymlink using canonical reparse structure 3683e5ab SystemTools: Implement CreateSymlink and ReadSymlink on Windows --- ProcessUNIX.c | 8 +-- Status.hxx.in | 2 +- SystemTools.cxx | 123 ++++++++++++++++++++++++++++++++++++++------ testSystemTools.cxx | 30 +++++++---- 4 files changed, 132 insertions(+), 31 deletions(-) diff --git a/ProcessUNIX.c b/ProcessUNIX.c index 5ae846aeee6..a8a15ddb0a8 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -2894,10 +2894,10 @@ static void kwsysProcessesSignalHandler(int signum /* Re-Install our handler. Repeat call until it is not interrupted. */ { struct sigaction newSigAction; - struct sigaction& oldSigAction; + struct sigaction* oldSigAction; memset(&newSigAction, 0, sizeof(struct sigaction)); - newSigChldAction.sa_handler = kwsysProcessesSignalHandler; - newSigChldAction.sa_flags = SA_NOCLDSTOP; + newSigAction.sa_handler = kwsysProcessesSignalHandler; + newSigAction.sa_flags = SA_NOCLDSTOP; sigemptyset(&newSigAction.sa_mask); switch (signum) { case SIGCHLD: @@ -2912,7 +2912,7 @@ static void kwsysProcessesSignalHandler(int signum oldSigAction = &kwsysProcessesOldSigTermAction; break; default: - return 0; + return; } while ((sigaction(signum, &newSigAction, oldSigAction) < 0) && (errno == EINTR)) diff --git a/Status.hxx.in b/Status.hxx.in index feb5b848b99..ed46d5c2bc8 100644 --- a/Status.hxx.in +++ b/Status.hxx.in @@ -70,7 +70,7 @@ public: #ifdef _WIN32 /** If the kind is "Windows", returns the GetLastError()-style value. Otherwise, returns 0. */ - int GetWindows() const + unsigned int GetWindows() const { return this->Kind_ == Kind::Windows ? this->Windows_ : 0; } diff --git a/SystemTools.cxx b/SystemTools.cxx index 25188454c0f..006495d3cc7 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -93,9 +93,43 @@ # ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) # endif +# ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2) +# endif # if defined(_MSC_VER) && _MSC_VER >= 1800 # define KWSYS_WINDOWS_DEPRECATED_GetVersionEx # endif +// from ntifs.h, which can only be used by drivers +typedef struct _REPARSE_DATA_BUFFER +{ + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union + { + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct + { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; #endif #if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H @@ -3008,7 +3042,7 @@ bool SystemTools::FileIsSymlink(const std::string& name) } CloseHandle(hFile); ULONG reparseTag = - reinterpret_cast(&buffer[0])->ReparseTag; + reinterpret_cast(&buffer[0])->ReparseTag; return (reparseTag == IO_REPARSE_TAG_SYMLINK) || (reparseTag == IO_REPARSE_TAG_MOUNT_POINT); } @@ -3048,31 +3082,90 @@ bool SystemTools::FileIsFIFO(const std::string& name) #endif } -#if defined(_WIN32) && !defined(__CYGWIN__) -Status SystemTools::CreateSymlink(std::string const&, std::string const&) -{ - return Status::Windows(ERROR_NOT_SUPPORTED); -} -#else Status SystemTools::CreateSymlink(std::string const& origName, std::string const& newName) { +#if defined(_WIN32) && !defined(__CYGWIN__) + DWORD flags; + if (FileIsDirectory(origName)) { + flags = SYMBOLIC_LINK_FLAG_DIRECTORY; + } else { + flags = 0; + } + + std::wstring origPath = Encoding::ToWindowsExtendedPath(origName); + std::wstring newPath = Encoding::ToWindowsExtendedPath(newName); + + Status status; + if (!CreateSymbolicLinkW(newPath.c_str(), origPath.c_str(), + flags | + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) { + status = Status::Windows_GetLastError(); + } + // Older Windows versions do not understand + // SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE + if (status.GetWindows() == ERROR_INVALID_PARAMETER) { + status = Status::Success(); + if (!CreateSymbolicLinkW(newPath.c_str(), origPath.c_str(), flags)) { + status = Status::Windows_GetLastError(); + } + } + + return status; +#else if (symlink(origName.c_str(), newName.c_str()) < 0) { return Status::POSIX_errno(); } return Status::Success(); -} #endif - -#if defined(_WIN32) && !defined(__CYGWIN__) -Status SystemTools::ReadSymlink(std::string const&, std::string&) -{ - return Status::Windows(ERROR_NOT_SUPPORTED); } -#else + Status SystemTools::ReadSymlink(std::string const& newName, std::string& origName) { +#if defined(_WIN32) && !defined(__CYGWIN__) + std::wstring newPath = Encoding::ToWindowsExtendedPath(newName); + // FILE_ATTRIBUTE_REPARSE_POINT means: + // * a file or directory that has an associated reparse point, or + // * a file that is a symbolic link. + HANDLE hFile = CreateFileW( + newPath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { + return Status::Windows_GetLastError(); + } + byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + DWORD bytesReturned = 0; + Status status; + if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, + nullptr)) { + status = Status::Windows_GetLastError(); + } + CloseHandle(hFile); + if (!status) { + return status; + } + PREPARSE_DATA_BUFFER data = + reinterpret_cast(&buffer[0]); + USHORT substituteNameLength; + PCWSTR substituteNameData; + if (data->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + substituteNameLength = + data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); + substituteNameData = data->SymbolicLinkReparseBuffer.PathBuffer + + data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); + } else if (data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + substituteNameLength = + data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR); + substituteNameData = data->MountPointReparseBuffer.PathBuffer + + data->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); + } else { + return Status::Windows(ERROR_REPARSE_TAG_MISMATCH); + } + std::wstring substituteName(substituteNameData, substituteNameLength); + origName = Encoding::ToNarrow(substituteName); +#else char buf[KWSYS_SYSTEMTOOLS_MAXPATH + 1]; int count = static_cast( readlink(newName.c_str(), buf, KWSYS_SYSTEMTOOLS_MAXPATH)); @@ -3082,9 +3175,9 @@ Status SystemTools::ReadSymlink(std::string const& newName, // Add null-terminator. buf[count] = 0; origName = buf; +#endif return Status::Success(); } -#endif Status SystemTools::ChangeDirectory(std::string const& dir) { diff --git a/testSystemTools.cxx b/testSystemTools.cxx index 04f66ffcecd..700eaf7ebfc 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -29,6 +29,7 @@ # ifdef _MSC_VER # define umask _umask # endif +# include #endif #include /* umask (POSIX), _S_I* constants (Windows) */ // Visual C++ does not define mode_t. @@ -425,21 +426,28 @@ static bool CheckFileOperations() res = false; } -#if !defined(_WIN32) std::string const testBadSymlink(testNewDir + "/badSymlink.txt"); std::string const testBadSymlinkTgt(testNewDir + "/missing/symlinkTgt.txt"); - if (!kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink)) { - std::cerr << "Problem with CreateSymlink for: " << testBadSymlink << " -> " - << testBadSymlinkTgt << std::endl; - res = false; - } + kwsys::Status const symlinkStatus = + kwsys::SystemTools::CreateSymlink(testBadSymlinkTgt, testBadSymlink); +#if defined(_WIN32) + // Under Windows, the user may not have enough privileges to create symlinks + if (symlinkStatus.GetWindows() != ERROR_PRIVILEGE_NOT_HELD) +#endif + { + if (!symlinkStatus) { + std::cerr << "CreateSymlink for: " << testBadSymlink << " -> " + << testBadSymlinkTgt + << " failed: " << symlinkStatus.GetString() << std::endl; + res = false; + } - if (!kwsys::SystemTools::Touch(testBadSymlink, false)) { - std::cerr << "Problem with Touch (no create) for: " << testBadSymlink - << std::endl; - res = false; + if (!kwsys::SystemTools::Touch(testBadSymlink, false)) { + std::cerr << "Problem with Touch (no create) for: " << testBadSymlink + << std::endl; + res = false; + } } -#endif if (!kwsys::SystemTools::Touch(testNewDir, false)) { std::cerr << "Problem with Touch (no create) for: " << testNewDir From eb7cbb577ef5690717e0bb4a9d7c3c69c0a672c7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 May 2021 14:22:33 -0400 Subject: [PATCH 0374/1519] gitlab-ci: clarify name of rsync upload block for binaries --- .gitlab-ci.yml | 10 +++++----- .gitlab/upload.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 18844d1f024..daec83c34ee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,7 +54,7 @@ prep:doc-package: upload:source-package: extends: - - .rsync_upload + - .rsync_upload_binary - .run_only_for_package dependencies: - prep:source-package @@ -406,7 +406,7 @@ build:linux-x86_64-package: upload:linux-x86_64-package: extends: - - .rsync_upload + - .rsync_upload_binary - .run_only_for_package dependencies: - build:linux-x86_64-package @@ -430,7 +430,7 @@ build:linux-aarch64-package: upload:linux-aarch64-package: extends: - - .rsync_upload + - .rsync_upload_binary - .run_only_for_package dependencies: - build:linux-aarch64-package @@ -542,7 +542,7 @@ build:macos-package: upload:macos-package: extends: - - .rsync_upload + - .rsync_upload_binary - .run_only_for_package dependencies: - build:macos-package @@ -565,7 +565,7 @@ build:macos10.10-package: upload:macos10.10-package: extends: - - .rsync_upload + - .rsync_upload_binary - .run_only_for_package dependencies: - build:macos10.10-package diff --git a/.gitlab/upload.yml b/.gitlab/upload.yml index 8b8daa106ff..92943868201 100644 --- a/.gitlab/upload.yml +++ b/.gitlab/upload.yml @@ -1,6 +1,6 @@ # Steps for uploading artifacts -.rsync_upload: +.rsync_upload_binary: image: "fedora:32" stage: upload tags: From 354ae6fe2e48d15ed205b39b59f553f1e32aa8dd Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 May 2021 14:27:48 -0400 Subject: [PATCH 0375/1519] gitlab-ci: add jobs to build cmake.org/cmake/help/git-{master,stage} docs --- .gitlab-ci.yml | 12 ++++++++++++ .gitlab/artifacts.yml | 9 +++++++++ .gitlab/os-linux.yml | 15 +++++++++++++++ .gitlab/rules.yml | 12 ++++++++++++ 4 files changed, 48 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index daec83c34ee..090012a96fc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -63,6 +63,18 @@ upload:source-package: variables: RSYNC_DESTINATION: dev +# Documentation builds + +build:help:master: + extends: + - .cmake_org_help + - .run_only_for_continuous_master + +build:help:stage: + extends: + - .cmake_org_help + - .run_only_for_continuous_stage + # Lint builds build:debian10-iwyu: diff --git a/.gitlab/artifacts.yml b/.gitlab/artifacts.yml index bf8e8b6d1d3..edd313f5aa9 100644 --- a/.gitlab/artifacts.yml +++ b/.gitlab/artifacts.yml @@ -97,3 +97,12 @@ paths: # Take the install tree. - build/install-doc/ + +.cmake_org_help_artifacts: + artifacts: + expire_in: 1d + paths: + - build/html + exclude: + - build/html/.buildinfo + - build/html/objects.inv diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 81c4d8d0e80..d0ac85e5bb3 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -368,3 +368,18 @@ - .needs_centos6_x86_64 variables: CMAKE_CI_JOB_NIGHTLY: "true" + +### Documentation + +.cmake_org_help: + stage: build + extends: + - .fedora33 + - .linux_builder_tags + - .cmake_org_help_artifacts + script: + - *before_script_linux + - mkdir -p build/ + - cd build/ + - cmake ../Utilities/Sphinx -GNinja -DSPHINX_HTML=ON -DSPHINX_FLAGS="-A versionswitch=1" + - ninja diff --git a/.gitlab/rules.yml b/.gitlab/rules.yml index 4ac67e82e7a..4846fea7648 100644 --- a/.gitlab/rules.yml +++ b/.gitlab/rules.yml @@ -62,3 +62,15 @@ - if: '$CMAKE_CI_PACKAGE == "true"' when: on_success - when: never + +.run_only_for_continuous_master: + rules: + - if: '$CMAKE_CI_PROJECT_MAIN_BRANCH != null && $CI_COMMIT_BRANCH != null && $CMAKE_CI_PROJECT_MAIN_BRANCH == $CI_COMMIT_BRANCH' + when: on_success + - when: never + +.run_only_for_continuous_stage: + rules: + - if: '$CMAKE_CI_PROJECT_CONTINUOUS_BRANCH != null && $CI_COMMIT_BRANCH != null && $CMAKE_CI_PROJECT_CONTINUOUS_BRANCH == $CI_COMMIT_BRANCH' + when: on_success + - when: never From a5a4b0b6ab01a6747a9ee4aed3693836f77c3eef Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 May 2021 14:28:44 -0400 Subject: [PATCH 0376/1519] gitlab-ci: add jobs to upload cmake.org/cmake/help/git-{master,stage} docs --- .gitlab-ci.yml | 22 ++++++++++++++++++++++ .gitlab/upload.yml | 17 +++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 090012a96fc..f8a22a5b359 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -70,11 +70,33 @@ build:help:master: - .cmake_org_help - .run_only_for_continuous_master +upload:help:master: + extends: + - .rsync_upload_help + - .run_only_for_continuous_master + variables: + RSYNC_DESTINATION: git-master + dependencies: + - build:help:master + needs: + - build:help:master + build:help:stage: extends: - .cmake_org_help - .run_only_for_continuous_stage +upload:help:stage: + extends: + - .rsync_upload_help + - .run_only_for_continuous_stage + variables: + RSYNC_DESTINATION: git-stage + dependencies: + - build:help:stage + needs: + - build:help:stage + # Lint builds build:debian10-iwyu: diff --git a/.gitlab/upload.yml b/.gitlab/upload.yml index 92943868201..3253fd3de19 100644 --- a/.gitlab/upload.yml +++ b/.gitlab/upload.yml @@ -16,3 +16,20 @@ - chmod 400 $RSYNC_BINARY_KEY - ssh-keygen -y -f $RSYNC_BINARY_KEY > $RSYNC_BINARY_KEY.pub - rsync -tv --recursive -e "ssh -i $RSYNC_BINARY_KEY -o StrictHostKeyChecking=no -o LogLevel=ERROR" build/ kitware@cmake.org:$RSYNC_DESTINATION/ + +.rsync_upload_help: + stage: upload + image: "fedora:33" + tags: + - docker + - linux + - build + environment: + name: rsync-upload + + script: + - ls build/html/index.html + - dnf install -y --setopt=install_weak_deps=False rsync openssh-clients + - chmod 400 $RSYNC_HELP_KEY + - ssh-keygen -y -f $RSYNC_HELP_KEY > $RSYNC_HELP_KEY.pub + - rsync -tv --recursive --delete -e "ssh -i $RSYNC_HELP_KEY -o StrictHostKeyChecking=no -o LogLevel=ERROR" build/html/ kitware@cmake.org:$RSYNC_DESTINATION/ From 4af7c3de5cff962cdc62ec15a6e0fad5d8e7e0a7 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:27:48 +0200 Subject: [PATCH 0377/1519] codespell: Add configuration file --- .codespellrc | 9 +++++++++ .gitattributes | 1 + 2 files changed, 10 insertions(+) create mode 100644 .codespellrc diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 00000000000..c450ea22463 --- /dev/null +++ b/.codespellrc @@ -0,0 +1,9 @@ +[codespell] +check-filenames = +check-hidden = +count = +# Disable warnings about binary files +quiet-level = 2 +builtin = clear,rare,en-GB_to_en-US +skip = */.git,*/Copyright.txt,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Utilities/cm* +ignore-words-list = aci,ake,ans,ba,cconfiguration,conly,dependees,dne,dum,earch,ect,filetest,fo,helpfull,hiden,isnt,keypair,nd,ned,nin,nknown,ot,pard,seh,ser,te,upto,varn,vas,wee diff --git a/.gitattributes b/.gitattributes index fac38dfd741..79a0f0400ea 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ .git* export-ignore .hooks* export-ignore +.codespellrc export-ignore .editorconfig export-ignore # Custom attribute to mark sources as using our C code style. From eaa860162c5c618833e19a66b36b1ee895a648a3 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:43:04 +0200 Subject: [PATCH 0378/1519] Auxiliary: Fix typos and spelling in comments --- Auxiliary/vim/cmake.vim.in | 2 +- Auxiliary/vim/indent/cmake.vim | 2 +- Auxiliary/vim/syntax/cmake.vim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Auxiliary/vim/cmake.vim.in b/Auxiliary/vim/cmake.vim.in index 3471b5455bd..6edc0407354 100644 --- a/Auxiliary/vim/cmake.vim.in +++ b/Auxiliary/vim/cmake.vim.in @@ -9,7 +9,7 @@ " Former Maintainer: Karthik Krishnan " Last Change: @DATE@ " -" Licence: The CMake license applies to this file. See +" License: The CMake license applies to this file. See " https://cmake.org/licensing " This implies that distribution with Vim is allowed diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim index 33e583d6247..f7ab24a5d02 100644 --- a/Auxiliary/vim/indent/cmake.vim +++ b/Auxiliary/vim/indent/cmake.vim @@ -5,7 +5,7 @@ " Former Maintainer: Karthik Krishnan " Last Change: 2017 Aug 30 " -" Licence: The CMake license applies to this file. See +" License: The CMake license applies to this file. See " https://cmake.org/licensing " This implies that distribution with Vim is allowed diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 067f80d2d9f..611f72a05c0 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -9,7 +9,7 @@ " Former Maintainer: Karthik Krishnan " Last Change: 2020 oct. 28 " -" Licence: The CMake license applies to this file. See +" License: The CMake license applies to this file. See " https://cmake.org/licensing " This implies that distribution with Vim is allowed From 6dd719a4a51be02a5fa870f94743807ac856d10d Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 21:11:40 +0200 Subject: [PATCH 0379/1519] Utilities: Fix typos and spelling in comments --- Utilities/Scripts/BoostScanDeps.cmake | 4 ++-- Utilities/Scripts/update-third-party.bash | 2 +- Utilities/Sphinx/cmake.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Utilities/Scripts/BoostScanDeps.cmake b/Utilities/Scripts/BoostScanDeps.cmake index 5794d03e893..14c7f3cf8e4 100644 --- a/Utilities/Scripts/BoostScanDeps.cmake +++ b/Utilities/Scripts/BoostScanDeps.cmake @@ -20,7 +20,7 @@ # "component". For each component, all the headers will be scanned to # determine the components it depends upon by following all the # possible includes from this component. This is to match the -# behaviour of autolinking. +# behavior of autolinking. # Written by Roger Leigh @@ -86,7 +86,7 @@ function(_Boost_FIND_COMPONENT_DEPENDENCIES component includedir _ret_libs) set(library_component TRUE) set(_boost_unprocessed_headers "${BOOST_DIR}/test/test_exec_monitor.hpp") else() - # Default behaviour where header directory is the same as the library name. + # Default behavior where header directory is the same as the library name. file(GLOB_RECURSE _boost_unprocessed_headers RELATIVE "${includedir}" "${includedir}/boost/${component}/*") diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash index fcab871bdf1..0d0a667c126 100644 --- a/Utilities/Scripts/update-third-party.bash +++ b/Utilities/Scripts/update-third-party.bash @@ -89,7 +89,7 @@ readonly basehash_regex="$name $regex_date ([0-9a-f]*)" # Check for an empty destination directory on disk. By checking on disk and # not in the repo it allows a library to be freshly re-inialized in a single # commit rather than first deleting the old copy in one commit and adding the -# new copy in a seperate commit. +# new copy in a separate commit. if [ ! -d "$(git rev-parse --show-toplevel)/$subtree" ]; then readonly basehash="" else diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index ece4bf56bb0..9fa56cd4b0c 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -20,7 +20,7 @@ # - [\.\+-] are needed for string constants like gtk+-2.0 # - Unix paths are recognized by '/'; support for Windows paths may be added if needed # - (\\.) allows for \-escapes (used in manual/cmake-language.7) -# - $<..$<..$>..> nested occurence in cmake-buildsystem +# - $<..$<..$>..> nested occurrence in cmake-buildsystem # - Nested variable evaluations are only supported in a limited capacity. Only # one level of nesting is supported and at most one nested variable can be present. From 9d0042362007b11ba2ca6c57f677b310cbd77dc5 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:07:07 +0200 Subject: [PATCH 0380/1519] Tests: Fix typos and spelling in comments --- Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake | 2 +- Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake | 2 +- Tests/CustomCommand/CMakeLists.txt | 2 +- Tests/FindPackageTest/CMakeLists.txt | 2 +- Tests/RunCMake/ExternalProject/MultiCommand.cmake | 2 +- Tests/RunCMake/GoogleTest/xml_output.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake index 8f7c19810c4..b61e62dfc73 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake @@ -146,7 +146,7 @@ endfunction() # This function runs dpkg-deb on a .deb and returns its output -# the default behaviour it to run "--info" on the specified Debian package +# the default behavior it to run "--info" on the specified Debian package # ACTION is one of the option accepted by dpkg-deb function(run_dpkgdeb dpkg_deb_output) set(${dpkg_deb_output} "" PARENT_SCOPE) diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake index f3d3ad03f01..31e843a8275 100644 --- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake @@ -404,7 +404,7 @@ if(CPackGen MATCHES "RPM") elseif("${symlink_name}" STREQUAL "symlink_other_relocatable_path" OR "${symlink_name}" STREQUAL "symlink_from_non_relocatable_path" OR "${symlink_name}" STREQUAL "symlink_relocatable_subpath") - # these links were not canged - post install script only - ignore them + # these links were not changed - post install script only - ignore them else() message(FATAL_ERROR "error: unexpected rpm symbolic link '${check_symlink}'") endif() diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index 11d005f78e8..fa06a94fa0b 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -583,6 +583,6 @@ set_target_properties(mac_fw PROPERTIES add_custom_command(OUTPUT mac_fw.txt COMMAND ${CMAKE_COMMAND} -E touch mac_fw.txt DEPENDS mac_fw) add_custom_target(drive_mac_fw ALL DEPENDS mac_fw.txt) -# Test empty COMMANDs are ommited +# Test empty COMMANDs are omitted add_executable(empty_command empty_command.cxx) add_custom_command(TARGET empty_command POST_BUILD COMMAND $<0:date>) diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index 7ec41f35f3c..c25b2c30406 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -24,7 +24,7 @@ find_package(VTK QUIET) add_executable(FindPackageTest FindPackageTest.cxx) -# test behaviour of cmFindBase wrt. the CMAKE_PREFIX_PATH variable +# test behavior of cmFindBase wrt. the CMAKE_PREFIX_PATH variable # foo.h should be found in ${CMAKE_CURRENT_SOURCE_DIR}/include: set(CMAKE_PREFIX_PATH /blub /blah "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/Tests/RunCMake/ExternalProject/MultiCommand.cmake b/Tests/RunCMake/ExternalProject/MultiCommand.cmake index dbf67eb71f3..084965806aa 100644 --- a/Tests/RunCMake/ExternalProject/MultiCommand.cmake +++ b/Tests/RunCMake/ExternalProject/MultiCommand.cmake @@ -1,6 +1,6 @@ include(ExternalProject) -# Verify COMMAND keyword is recognised after various *_COMMAND options +# Verify COMMAND keyword is recognized after various *_COMMAND options ExternalProject_Add(multiCommand DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E echo "download 1" COMMAND "${CMAKE_COMMAND}" -E echo "download 2" diff --git a/Tests/RunCMake/GoogleTest/xml_output.cpp b/Tests/RunCMake/GoogleTest/xml_output.cpp index 82f0d023771..743a472dc27 100644 --- a/Tests/RunCMake/GoogleTest/xml_output.cpp +++ b/Tests/RunCMake/GoogleTest/xml_output.cpp @@ -5,7 +5,7 @@ int main(int argc, char** argv) { // Note: GoogleTestXML.cmake doesn't actually depend on Google Test as such; - // it only mimicks the output file creation using the path passed to this + // it only mimics the output file creation using the path passed to this // test without any content for (int i = 0; i < argc; i++) { std::string param(argv[i]); From 9a862e8837045f27bc55296967f5a2b9fab0f994 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:10:00 +0200 Subject: [PATCH 0381/1519] Tests: Fix typos and spelling in test name --- Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake b/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake index 2b4fc893118..3876cebe9a8 100644 --- a/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExcludeFromAll/RunCMakeTest.cmake @@ -13,7 +13,7 @@ function(run_single_config_test label config exclude_from_all_value expectation) run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config ${config}) endfunction() -run_single_config_test("explictly not excluded" Debug 0 "should_exist") +run_single_config_test("explicitly not excluded" Debug 0 "should_exist") run_single_config_test("excluded" Debug 1 "should_not_exist") if(RunCMake_GENERATOR MATCHES "^(Xcode|Visual Studio)") From e4a856f8b9e4cddbf4784ad1c434aacea4eee2a1 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:10:26 +0200 Subject: [PATCH 0382/1519] Tests: Fix typos and spelling in test error message --- Tests/CMakeLib/testVisualStudioSlnParser.cxx | 2 +- Tests/RunCMake/install/RunCMakeTest.cmake | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/CMakeLib/testVisualStudioSlnParser.cxx b/Tests/CMakeLib/testVisualStudioSlnParser.cxx index 3c069600c8a..7fdba9a2a3a 100644 --- a/Tests/CMakeLib/testVisualStudioSlnParser.cxx +++ b/Tests/CMakeLib/testVisualStudioSlnParser.cxx @@ -33,7 +33,7 @@ int testVisualStudioSlnParser(int, char* []) // Test clean parser if (parser.GetParseResult() != cmVisualStudioSlnParser::ResultOK) { - std::cerr << "cmVisualStudioSlnParser initialisation failed" << std::endl; + std::cerr << "cmVisualStudioSlnParser initialization failed" << std::endl; return 1; } diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index efd03df6f36..7d9d2acb697 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -55,9 +55,9 @@ function(run_cmake_EDIT_RPATH_only case) else() # Sanity check against a platform known to be ELF-based if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - message(FATAL_ERROR "Expected platform Linux to advertize itself as ELF-based, but it did not.") + message(FATAL_ERROR "Expected platform Linux to advertise itself as ELF-based, but it did not.") elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX") - message(FATAL_ERROR "Expected platform AIX to advertize itself as XCOFF-based, but it did not.") + message(FATAL_ERROR "Expected platform AIX to advertise itself as XCOFF-based, but it did not.") else() message(STATUS "${case} - SKIPPED (No ELF-based platform found)") endif() From fa7d307eff842b52d40d7b5283a04466955d35cc Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:49:14 +0200 Subject: [PATCH 0383/1519] Tests: Fix typos and spelling in test strings --- Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt | 2 +- Tests/RunCMake/cmake_language/defer_call_ids.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt b/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt index 2fd194dc9b0..674ff1dd0a5 100644 --- a/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt +++ b/Tests/RunCMake/cmake_language/defer_call_ids-stdout.txt @@ -5,7 +5,7 @@ -- Immediate Message: cancelCall='cmake_language;DEFER;CANCEL_CALL;toBeCancelled' -- Immediate Message: getCallIds2='cmake_language;DEFER;GET_CALL_IDS;ids' -- Immediate Message: messageIds2='cmake_language;EVAL;CODE;message\(STATUS "Deferred Message: ids='\${ids}'"\)' --- Immediate Message: toBeCancelled='message;STATUS;Cancelled Message' +-- Immediate Message: toBeCancelled='message;STATUS;Canceled Message' -- Immediate Message: message3='message;STATUS;Final Deferred Message' -- First Deferred Message -- Deferred Message: ids='messageIds1;cancelCall;getCallIds2;messageIds2;toBeCancelled;message3' diff --git a/Tests/RunCMake/cmake_language/defer_call_ids.cmake b/Tests/RunCMake/cmake_language/defer_call_ids.cmake index 28748941738..fd5bc17927f 100644 --- a/Tests/RunCMake/cmake_language/defer_call_ids.cmake +++ b/Tests/RunCMake/cmake_language/defer_call_ids.cmake @@ -4,7 +4,7 @@ cmake_language(DEFER ID messageIds1 CALL cmake_language EVAL CODE [[message(STAT cmake_language(DEFER ID cancelCall CALL cmake_language DEFER CANCEL_CALL toBeCancelled) cmake_language(DEFER ID getCallIds2 CALL cmake_language DEFER GET_CALL_IDS ids) cmake_language(DEFER ID messageIds2 CALL cmake_language EVAL CODE [[message(STATUS "Deferred Message: ids='${ids}'")]]) -cmake_language(DEFER ID toBeCancelled CALL message STATUS "Cancelled Message") +cmake_language(DEFER ID toBeCancelled CALL message STATUS "Canceled Message") cmake_language(DEFER ID message3 CALL message STATUS "Final Deferred Message") cmake_language(DEFER GET_CALL_IDS ids) message(STATUS "Immediate Message: ids='${ids}'") From dad5b9d8455e4007d1cab1567ebad0eac26330a1 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 22:37:22 +0200 Subject: [PATCH 0384/1519] Modules: Fix typos and spelling in comments --- Modules/CMakeDetermineCompilerId.cmake | 2 +- Modules/FetchContent.cmake | 2 +- Modules/FindFLTK.cmake | 2 +- Modules/FindJNI.cmake | 2 +- Modules/FindMatlab.cmake | 2 +- Modules/GNUInstallDirs.cmake | 2 +- Modules/Platform/ARTOS-GNU-C.cmake | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 519fe6baa32..448f0716e72 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -320,7 +320,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} set(id_cl "$(CLToolExe)") elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") set(id_cl clang.exe) - # Executable names have choosen according documentation + # Executable names have been chosen according documentation # URL: (https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-dpcpp-compiler/top.html#top_GUID-A9B4C91D-97AC-450D-9742-9D895BC8AEE1) elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel") if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "DPC\\+\\+ Compiler") diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 88f7ed682b4..0c21cd934a4 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -1053,7 +1053,7 @@ function(FetchContent_Populate contentName) # Don't set global properties, or record that we did this population, since # this was a direct call outside of the normal declared details form. # We only want to save values in the global properties for content that - # honours the hierarchical details mechanism so that projects are not + # honors the hierarchical details mechanism so that projects are not # robbed of the ability to override details set in nested projects. return() endif() diff --git a/Modules/FindFLTK.cmake b/Modules/FindFLTK.cmake index e1e239a662d..bab72560dfd 100644 --- a/Modules/FindFLTK.cmake +++ b/Modules/FindFLTK.cmake @@ -108,7 +108,7 @@ if(APPLE) set( FLTK_PLATFORM_DEPENDENT_LIBS "-framework Carbon -framework Cocoa -framework ApplicationServices -lz") endif() -# If FLTK_INCLUDE_DIR is already defined we assigne its value to FLTK_DIR +# If FLTK_INCLUDE_DIR is already defined we assign its value to FLTK_DIR. if(FLTK_INCLUDE_DIR) set(FLTK_DIR ${FLTK_INCLUDE_DIR}) endif() diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index 5aa2d601f17..e4f60b3166e 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -80,7 +80,7 @@ macro(java_append_library_directories _var) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") set(_java_libarch "ppc" "ppc64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^sparc") - # Both flavours can run on the same processor + # Both flavors can run on the same processor set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}" "sparc" "sparcv9") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(parisc|hppa)") set(_java_libarch "parisc" "parisc64") diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 2f56d1571d1..502eee005c3 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -1416,7 +1416,7 @@ function(_Matlab_find_instances_from_path matlab_roots) set(_matlab_possible_roots) # At this point, we have no other choice than trying to find it from PATH. - # If set by the user, this wont change + # If set by the user, this won't change. find_program( _matlab_main_tmp NAMES matlab) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index e149f4c5aa5..f7d8c36a266 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -352,7 +352,7 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var) if(GGAID_extra_arg_count GREATER 0) list(GET GGAID_extra_args 0 GGAID_dir) else() - # Historical behaviour: use ${dir} from caller's scope + # Historical behavior: use ${dir} from caller's scope set(GGAID_dir "${dir}") message(AUTHOR_WARNING "GNUInstallDirs_get_absolute_install_dir called without third argument. " diff --git a/Modules/Platform/ARTOS-GNU-C.cmake b/Modules/Platform/ARTOS-GNU-C.cmake index fe8d782e3db..bce461330dc 100644 --- a/Modules/Platform/ARTOS-GNU-C.cmake +++ b/Modules/Platform/ARTOS-GNU-C.cmake @@ -1,4 +1,4 @@ -# Define ARTOS to select proper behaviour and tell preprocessor to accept C++ style comments. +# Define ARTOS to select proper behavior and tell preprocessor to accept C++ style comments. string(APPEND CMAKE_C_FLAGS_INIT " -DARTOS -Xp -+") # ac doesn't support -g properly and doesn't support the normal gcc optimization options. Just use the defaults set by ac. string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " ") From f015c36c5a051d73434d56ba54c12001590756a2 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 22:40:07 +0200 Subject: [PATCH 0385/1519] Modules: Fix typos and spelling in comments of generated code --- Modules/CMakeFortranCompilerId.F.in | 2 +- Modules/Compiler/IntelLLVM-DetermineCompiler.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 7b1d68bd41e..d0e0e46fb14 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -26,7 +26,7 @@ PRINT *, 'INFO:compiler[IntelLLVM]' ! __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and ! later. Look for 6 digit vs. 8 digit version number to decide encoding. -! VVVV is no smaller than the current year when a versio is released. +! VVVV is no smaller than the current year when a version is released. # if __INTEL_LLVM_COMPILER < 1000000 # define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) # define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) diff --git a/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake b/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake index 124dafe69b1..917a364ea72 100644 --- a/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake +++ b/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake @@ -4,7 +4,7 @@ set(_compiler_id_pp_test "(defined(__clang__) && defined(__INTEL_CLANG_COMPILER) set(_compiler_id_version_compute " /* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and * later. Look for 6 digit vs. 8 digit version number to decide encoding. - * VVVV is no smaller than the current year when a versio is released. + * VVVV is no smaller than the current year when a version is released. */ #if __INTEL_LLVM_COMPILER < 1000000L # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__INTEL_LLVM_COMPILER/100) From 15cc39ed7f90331401f53530e4b2d03f8573f0d1 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 22:40:26 +0200 Subject: [PATCH 0386/1519] Modules: Fix typos and spelling in documentation --- Modules/CMakePackageConfigHelpers.cmake | 4 ++-- Modules/FetchContent.cmake | 2 +- Modules/FindGettext.cmake | 4 ++-- Modules/GetPrerequisites.cmake | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index ad719ef5afc..5813956ee4a 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -143,12 +143,12 @@ The ``COMPATIBILITY`` mode ``AnyNewerVersion`` means that the installed package version will be considered compatible if it is newer or exactly the same as the requested version. This mode should be used for packages which are fully backward compatible, also across major versions. -If ``SameMajorVersion`` is used instead, then the behaviour differs from +If ``SameMajorVersion`` is used instead, then the behavior differs from ``AnyNewerVersion`` in that the major version number must be the same as requested, e.g. version 2.0 will not be considered compatible if 1.0 is requested. This mode should be used for packages which guarantee backward compatibility within the same major version. -If ``SameMinorVersion`` is used, the behaviour is the same as +If ``SameMinorVersion`` is used, the behavior is the same as ``SameMajorVersion``, but both major and minor version must be the same as requested, e.g version 0.2 will not be compatible if 0.1 is requested. If ``ExactVersion`` is used, then the package is only considered compatible if diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 0c21cd934a4..f5de93043e4 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -296,7 +296,7 @@ is simpler and provides additional features over the pattern above. The ``FetchContent_Populate()`` command also supports a syntax allowing the content details to be specified directly rather than using any saved details. This is more low-level and use of this form is generally to be - avoided in favour of using saved content details as outlined above. + avoided in favor of using saved content details as outlined above. Nevertheless, in certain situations it can be useful to invoke the content population as an isolated operation (typically as part of implementing some other higher level feature or when using CMake in script mode): diff --git a/Modules/FindGettext.cmake b/Modules/FindGettext.cmake index 252f2aea274..99e2887e984 100644 --- a/Modules/FindGettext.cmake +++ b/Modules/FindGettext.cmake @@ -39,7 +39,7 @@ LANGUAGES ... ) If INSTALL_DESTINATION is given then automatically install rules will be created, the language subdirectory will be taken into account (by default use share/locale/). - If ALL is specified, the pot file is processed when building the all traget. + If ALL is specified, the pot file is processed when building the all target. It creates a custom target "potfile". GETTEXT_PROCESS_PO_FILES( [ALL] [INSTALL_DESTINATION ] @@ -51,7 +51,7 @@ PO_FILES ... ) If INSTALL_DESTINATION is given then automatically install rules will be created, the language subdirectory will be taken into account (by default use share/locale/). - If ALL is specified, the po files are processed when building the all traget. + If ALL is specified, the po files are processed when building the all target. It creates a custom target "pofiles". .. versionadded:: 3.2 diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index ed5c38b054d..e90a9b5b7bc 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -83,7 +83,7 @@ to 1 all prerequisites will be found recursively, if set to 0 only direct prerequisites are listed. must be 0 or 1 indicating whether to include or exclude "system" prerequisites. With set to 0 only the full path names of the prerequisites are -printed, set to 1 extra informatin will be displayed. +printed, set to 1 extra information will be displayed. :: From 87f8843d8b97cf174302858ee5344a737a520c9b Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Fri, 7 May 2021 00:16:22 +0200 Subject: [PATCH 0387/1519] FindMatlab: Fix spelling in warning and documentation --- Modules/FindMatlab.cmake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 502eee005c3..c8df670b1b6 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -52,7 +52,7 @@ The module supports the following components: between the release name and the version. The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give -the path of the desired Matlab version. Otherwise, the behaviour is platform +the path of the desired Matlab version. Otherwise, the behavior is platform specific: * Windows: The installed versions of Matlab/MCR are retrieved from the @@ -83,7 +83,7 @@ Module Input Variables ^^^^^^^^^^^^^^^^^^^^^^ Users or projects may set the following variables to configure the module -behaviour: +behavior: :variable:`Matlab_ROOT_DIR` the root of the Matlab installation. @@ -184,7 +184,7 @@ Known issues **Symbol clash in a MEX target** By default, every symbols inside a MEX file defined with the command :command:`matlab_add_mex` have hidden - visibility, except for the entry point. This is the default behaviour of + visibility, except for the entry point. This is the default behavior of the MEX compiler, which lowers the risk of symbol collision between the libraries shipped with Matlab, and the libraries to which the MEX file is linking to. This is also the default on Windows platforms. @@ -223,7 +223,7 @@ Reference .. variable:: MATLAB_ADDITIONAL_VERSIONS If set, specifies additional versions of Matlab that may be looked for. - The variable should be a list of strings, organised by pairs of release + The variable should be a list of strings, organized by pairs of release name and versions, such as follows:: set(MATLAB_ADDITIONAL_VERSIONS @@ -856,7 +856,7 @@ endfunction() where ``matlab_file_name`` is the ``UNITTEST_FILE`` without the extension. ``UNITTEST_PRECOMMAND`` Matlab script command to be ran before the file - containing the test (eg. GPU device initialisation based on CMake + containing the test (eg. GPU device initialization based on CMake variables). ``TIMEOUT`` the test timeout in seconds. Defaults to 180 seconds as the @@ -1240,7 +1240,7 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve endif() endif() - # UNKNOWN is the default behaviour in case we + # UNKNOWN is the default behavior in case we # - have an erroneous matlab_root # - have an initial 'UNKNOWN' if(matlab_or_mcr STREQUAL "MATLAB" OR matlab_or_mcr STREQUAL "UNKNOWN") @@ -1375,7 +1375,7 @@ function(_Matlab_find_instances_osx matlab_roots) set(_matlab_possible_roots) # on mac, we look for the /Application paths - # this corresponds to the behaviour on Windows. On Linux, we do not have + # this corresponds to the behavior on Windows. On Linux, we do not have # any other guess. matlab_get_supported_releases(_matlab_releases) if(MATLAB_FIND_DEBUG) @@ -1552,7 +1552,7 @@ if(_numbers_of_matlab_roots GREATER 0) # adding a warning in case of ambiguity if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})." - " If this is not the desired behaviour, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line") + " If this is not the desired behavior, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line") endif() endif() endif() From 03b1140ddc6341aec37f55437cdabba8fcdfe906 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 23:46:53 +0200 Subject: [PATCH 0388/1519] CONTRIBUTING: Fix typos and spelling --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 300621405cb..a6a20827dcf 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -38,7 +38,7 @@ To contribute patches: #. Push the topic branch to a personal repository fork on GitLab. #. Create a GitLab Merge Request targeting the upstream ``master`` branch (even if the change is intended for merge to the ``release`` branch). - Check the box labelled "Allow commits from members who can merge to the + Check the box labeled "Allow commits from members who can merge to the target branch". This will allow maintainers to make minor edits on your behalf. From 7072d837720d25bcd1906764e3eb23b940e4e4a4 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 21:24:28 +0200 Subject: [PATCH 0389/1519] Help: Fix typos and spelling in documentation --- Help/command/cmake_language.rst | 4 ++-- Help/command/install.rst | 2 +- Help/command/install_files.rst | 2 +- Help/command/install_programs.rst | 2 +- Help/command/install_targets.rst | 2 +- Help/cpack_gen/deb.rst | 2 +- Help/cpack_gen/dmg.rst | 2 +- Help/generator/VS_TOOLSET_HOST_ARCH.txt | 2 +- Help/guide/importing-exporting/index.rst | 2 +- Help/manual/OPTIONS_BUILD.txt | 2 +- Help/manual/cmake-file-api.7.rst | 2 +- Help/manual/cmake-policies.7.rst | 2 +- Help/manual/cmake.1.rst | 2 +- Help/policy/CMP0110.rst | 2 +- Help/policy/CMP0121.rst | 6 +++--- Help/prop_test/FIXTURES_REQUIRED.rst | 4 ++-- Help/prop_tgt/Swift_MODULE_DIRECTORY.rst | 2 +- Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst | 2 +- Help/release/3.15.rst | 2 +- Help/release/3.16.rst | 2 +- Help/release/3.6.rst | 2 +- Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst | 2 +- Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst | 2 +- Help/variable/EXECUTABLE_OUTPUT_PATH.rst | 2 +- 24 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst index 99f874b197d..2859f6b6d70 100644 --- a/Help/command/cmake_language.rst +++ b/Help/command/cmake_language.rst @@ -190,7 +190,7 @@ For example, the code: .. code-block:: cmake cmake_language(DEFER CALL message "${deferred_message}") - cmake_language(DEFER ID_VAR id CALL message "Cancelled Message") + cmake_language(DEFER ID_VAR id CALL message "Canceled Message") cmake_language(DEFER CANCEL_CALL ${id}) message("Immediate Message") set(deferred_message "Deferred Message") @@ -201,7 +201,7 @@ prints:: Deferred Message The ``Cancelled Message`` is never printed because its command is -cancelled. The ``deferred_message`` variable reference is not evaluated +canceled. The ``deferred_message`` variable reference is not evaluated until the call site, so it can be set after the deferred call is scheduled. In order to evaluate variable references immediately when scheduling a diff --git a/Help/command/install.rst b/Help/command/install.rst index 35207f4c47b..993cf7f3f3c 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -724,7 +724,7 @@ executable from the installation tree using the imported target name ``mp_myexe`` as if the target were built in its own tree. .. note:: - This command supercedes the :command:`install_targets` command and + This command supersedes the :command:`install_targets` command and the :prop_tgt:`PRE_INSTALL_SCRIPT` and :prop_tgt:`POST_INSTALL_SCRIPT` target properties. It also replaces the ``FILES`` forms of the :command:`install_files` and :command:`install_programs` commands. diff --git a/Help/command/install_files.rst b/Help/command/install_files.rst index ff074a8a770..494f3d0ee5a 100644 --- a/Help/command/install_files.rst +++ b/Help/command/install_files.rst @@ -5,7 +5,7 @@ install_files Use the :command:`install(FILES)` command instead. -This command has been superceded by the :command:`install` command. It is +This command has been superseded by the :command:`install` command. It is provided for compatibility with older CMake code. The ``FILES`` form is directly replaced by the ``FILES`` form of the :command:`install` command. The regexp form can be expressed more clearly using the ``GLOB`` diff --git a/Help/command/install_programs.rst b/Help/command/install_programs.rst index fab64820d27..eafae899668 100644 --- a/Help/command/install_programs.rst +++ b/Help/command/install_programs.rst @@ -5,7 +5,7 @@ install_programs Use the :command:`install(PROGRAMS)` command instead. -This command has been superceded by the :command:`install` command. It is +This command has been superseded by the :command:`install` command. It is provided for compatibility with older CMake code. The ``FILES`` form is directly replaced by the ``PROGRAMS`` form of the :command:`install` command. The regexp form can be expressed more clearly using the ``GLOB`` diff --git a/Help/command/install_targets.rst b/Help/command/install_targets.rst index c9efdce6787..9355f8d532a 100644 --- a/Help/command/install_targets.rst +++ b/Help/command/install_targets.rst @@ -5,7 +5,7 @@ install_targets Use the :command:`install(TARGETS)` command instead. -This command has been superceded by the :command:`install` command. It is +This command has been superseded by the :command:`install` command. It is provided for compatibility with older CMake code. :: diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst index 03c4ea8dbc6..d8d53ece362 100644 --- a/Help/cpack_gen/deb.rst +++ b/Help/cpack_gen/deb.rst @@ -289,7 +289,7 @@ List of CPack DEB generator specific variables: * Default : "optional" .. versionadded:: 3.5 - Per-component ``CPACK_DEBIAN__PACKAGE_PRIORITY`` varables. + Per-component ``CPACK_DEBIAN__PACKAGE_PRIORITY`` variables. See https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst index ec2cf1e2d94..64e97699814 100644 --- a/Help/cpack_gen/dmg.rst +++ b/Help/cpack_gen/dmg.rst @@ -51,7 +51,7 @@ on macOS: .. versionadded:: 3.6 - Default behaviour is to include a symlink to ``/Applications`` in the DMG. + Default behavior is to include a symlink to ``/Applications`` in the DMG. Set this option to ``ON`` to avoid adding the symlink. .. variable:: CPACK_DMG_SLA_DIR diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH.txt b/Help/generator/VS_TOOLSET_HOST_ARCH.txt index e3617199904..069638bd2de 100644 --- a/Help/generator/VS_TOOLSET_HOST_ARCH.txt +++ b/Help/generator/VS_TOOLSET_HOST_ARCH.txt @@ -8,4 +8,4 @@ See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. .. versionadded:: 3.14 - Added suport for ``host=x86`` option. + Added support for ``host=x86`` option. diff --git a/Help/guide/importing-exporting/index.rst b/Help/guide/importing-exporting/index.rst index 3e602508ff3..dd3efb8bb9c 100644 --- a/Help/guide/importing-exporting/index.rst +++ b/Help/guide/importing-exporting/index.rst @@ -640,7 +640,7 @@ We can use the :command:`find_package` command: :start-after: # find MathFunctions :end-before: # create executable -Create an exectuable: +Create an executable: .. literalinclude:: Downstream/CMakeLists.txt :language: cmake diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index c4f83f7b630..8e23b7711bd 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -77,7 +77,7 @@ :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. ``--toolchain `` - Specify the cross compiling toolchain file, equivalant to setting + Specify the cross compiling toolchain file, equivalent to setting :variable:`CMAKE_TOOLCHAIN_FILE` variable. ``--install-prefix `` diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index cbc3d6dc673..445ebeb4da6 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -1437,7 +1437,7 @@ The members specific to ``toolchains`` objects are: ``language`` A JSON string specifying the toolchain language, like C or CXX. Language - names are the same as langauge names that can be passed to the + names are the same as language names that can be passed to the :command:`project` command. Because CMake only supports a single toolchain per language, this field can be used as a key. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 08449a71596..a4804733269 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -60,7 +60,7 @@ Policies Introduced by CMake 3.21 CMP0124: foreach() loop variables are only available in the loop scope. CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. CMP0122: UseSWIG use standard library name conventions for csharp language. - CMP0121: The list command detects invalid indicies. + CMP0121: The list command detects invalid indices. Policies Introduced by CMake 3.20 ================================= diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index f416f86283a..74c2a463d5b 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -702,7 +702,7 @@ Available commands are: ``remove [-f] ...`` .. deprecated:: 3.17 - Remove the file(s). The planned behaviour was that if any of the + Remove the file(s). The planned behavior was that if any of the listed files already do not exist, the command returns a non-zero exit code, but no message is logged. The ``-f`` option changes the behavior to return a zero exit code (i.e. success) in such situations instead. diff --git a/Help/policy/CMP0110.rst b/Help/policy/CMP0110.rst index 25a00089f19..6977d41e507 100644 --- a/Help/policy/CMP0110.rst +++ b/Help/policy/CMP0110.rst @@ -8,7 +8,7 @@ CMP0110 :command:`add_test` can now (officially) create tests with whitespace and other special characters in its name. Before CMake version 3.19 that was not allowed, however, it was possible to work around this limitation by explicitly -putting escaped quotes arount the test's name in the ``add_test`` command. +putting escaped quotes around the test's name in the ``add_test`` command. Although never officially supported several projects in the wild found and implemented this workaround. However, the new change which officially allows diff --git a/Help/policy/CMP0121.rst b/Help/policy/CMP0121.rst index 5ef28569e26..326e7d59558 100644 --- a/Help/policy/CMP0121.rst +++ b/Help/policy/CMP0121.rst @@ -3,16 +3,16 @@ CMP0121 .. versionadded:: 3.21 -The :command:`list` command now detects invalid indicies. +The :command:`list` command now detects invalid indices. Prior to CMake version 3.21, the :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and ``REMOVE_AT`` subcommands did not detect invalid index arguments. -The ``OLD`` behavior of this policy is for invalid indicies to be treated as +The ``OLD`` behavior of this policy is for invalid indices to be treated as their integer value (if any) at the start of the string. For example, ``2good4you`` is a ``2`` and ``not_an_integer`` is a ``0``. The ``NEW`` -behavior is for invalid indicies to trigger an error. +behavior is for invalid indices to trigger an error. This policy was introduced in CMake version 3.21. CMake version |release| warns when the policy is not set and uses ``OLD`` behavior. Use the diff --git a/Help/prop_test/FIXTURES_REQUIRED.rst b/Help/prop_test/FIXTURES_REQUIRED.rst index d92808a63d2..f85083069c7 100644 --- a/Help/prop_test/FIXTURES_REQUIRED.rst +++ b/Help/prop_test/FIXTURES_REQUIRED.rst @@ -35,9 +35,9 @@ The concept of a fixture is different to that of a resource specified by set of tests which share setup and cleanup requirements, whereas a resource lock has the effect of ensuring a particular set of tests do not run in parallel. Some situations may need both, such as setting up a database, -serialising test access to that database and deleting the database again at the +serializing test access to that database and deleting the database again at the end. For such cases, tests would populate both ``FIXTURES_REQUIRED`` and -:prop_test:`RESOURCE_LOCK` to combine the two behaviours. Names used for +:prop_test:`RESOURCE_LOCK` to combine the two behaviors. Names used for :prop_test:`RESOURCE_LOCK` have no relationship with names of fixtures, so note that a resource lock does not imply a fixture and vice versa. diff --git a/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst b/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst index a6484f2fd43..619377a11c8 100644 --- a/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst +++ b/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst @@ -9,4 +9,4 @@ If the target contains Swift source files, this specifies the directory in which the modules will be placed. When this property is not set, the modules will be placed in the build directory corresponding to the target's source directory. If the variable :variable:`CMAKE_Swift_MODULE_DIRECTORY` is set when a target is -created its value is used to initialise this property. +created its value is used to initialize this property. diff --git a/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst b/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst index 2c95e027c17..d288dd3b4fb 100644 --- a/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst +++ b/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst @@ -50,6 +50,6 @@ be used to avoid that with code like the following: return MY_UNITY_ID::i; } -The pseudononymous namespace is used within a truly anonymous namespace. +The pseudonymous namespace is used within a truly anonymous namespace. On many platforms, this maintains the invariant that the symbols within do not get external linkage when performing a unity build. diff --git a/Help/release/3.15.rst b/Help/release/3.15.rst index e68e7d38b4b..6b1a8007a06 100644 --- a/Help/release/3.15.rst +++ b/Help/release/3.15.rst @@ -40,7 +40,7 @@ Languages customize the Swift module name. * The :prop_sf:`Swift_DIAGNOSTICS_FILE` source property was added to - indicate where to write the serialised Swift diagnostics. + indicate where to write the serialized Swift diagnostics. The Swift support is experimental, not considered stable, and may change in future releases of CMake. diff --git a/Help/release/3.16.rst b/Help/release/3.16.rst index 84d96cdc8f4..28273a762f8 100644 --- a/Help/release/3.16.rst +++ b/Help/release/3.16.rst @@ -233,7 +233,7 @@ Deprecated and Removed Features instead. * The :module:`GetPrerequisites` module has been deprecated, as it has been - superceded by :command:`file(GET_RUNTIME_DEPENDENCIES)`. + superseded by :command:`file(GET_RUNTIME_DEPENDENCIES)`. * The ``CPACK_INSTALL_SCRIPT`` variable has been deprecated in favor of the new, more accurately named :variable:`CPACK_INSTALL_SCRIPTS` variable. diff --git a/Help/release/3.6.rst b/Help/release/3.6.rst index f0add07ff2b..b798f0d6ecd 100644 --- a/Help/release/3.6.rst +++ b/Help/release/3.6.rst @@ -170,7 +170,7 @@ CPack is used for dependency auto detection. * The :cpack_gen:`CPack DEB Generator` learned how to generate - ``DEBIAN/shlibs`` contorl file when package contains shared libraries. + ``DEBIAN/shlibs`` control file when package contains shared libraries. * The :cpack_gen:`CPack DEB Generator` learned how to generate ``DEBIAN/postinst`` and ``DEBIAN/postrm`` files if the package installs diff --git a/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst b/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst index 6c0c61b112b..0b0b11414a0 100644 --- a/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst +++ b/Help/variable/CMAKE_AUTOMOC_RELAXED_MODE.rst @@ -8,7 +8,7 @@ Switch between strict and relaxed automoc mode. By default, :prop_tgt:`AUTOMOC` behaves exactly as described in the documentation of the :prop_tgt:`AUTOMOC` target property. When set to ``TRUE``, it accepts more input and tries to find the correct input file for -``moc`` even if it differs from the documented behaviour. In this mode it +``moc`` even if it differs from the documented behavior. In this mode it e.g. also checks whether a header file is intended to be processed by moc when a ``"foo.moc"`` file has been included. diff --git a/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst b/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst index 36949739fff..6036c04bb13 100644 --- a/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst +++ b/Help/variable/CMAKE_Swift_MODULE_DIRECTORY.rst @@ -5,6 +5,6 @@ CMAKE_Swift_MODULE_DIRECTORY Swift module output directory. -This variable is used to initialise the :prop_tgt:`Swift_MODULE_DIRECTORY` +This variable is used to initialize the :prop_tgt:`Swift_MODULE_DIRECTORY` property on all the targets. See the target property for additional information. diff --git a/Help/variable/EXECUTABLE_OUTPUT_PATH.rst b/Help/variable/EXECUTABLE_OUTPUT_PATH.rst index 26d3e92a10d..245b9eb2653 100644 --- a/Help/variable/EXECUTABLE_OUTPUT_PATH.rst +++ b/Help/variable/EXECUTABLE_OUTPUT_PATH.rst @@ -3,6 +3,6 @@ EXECUTABLE_OUTPUT_PATH Old executable location variable. -The target property :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY` supercedes this +The target property :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY` supersedes this variable for a target if it is set. Executable targets are otherwise placed in this directory. From 5950e5432554e3cc731006ed452bab5ddfffec23 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 22:28:42 +0200 Subject: [PATCH 0390/1519] Source: Fix typos and spelling in comments --- Source/CPack/cmCPackDragNDropGenerator.cxx | 2 +- Source/cmExtraEclipseCDT4Generator.cxx | 2 +- Source/cmGlobalBorlandMakefileGenerator.cxx | 2 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 2 +- Source/cmLocalGenerator.cxx | 6 +++--- Source/cmMakefile.cxx | 2 +- Source/cmMakefile.h | 2 +- Source/cmOrderDirectories.cxx | 2 +- Source/cmSystemTools.h | 2 +- Source/cmUVHandlePtr.cxx | 2 +- Source/cmake.cxx | 2 +- Source/cmcmd.cxx | 4 ++-- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 0d56e5fd0e7..b71c9698280 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -324,7 +324,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, staging << src_dir; // Add a symlink to /Applications so users can drag-and-drop the bundle - // into it unless this behaviour was disabled + // into it unless this behavior was disabled if (!cpack_dmg_disable_applications_symlink) { std::ostringstream application_link; application_link << staging.str() << "/Applications"; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 5fbbef7ac4c..824f5ed6cc7 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -1097,7 +1097,7 @@ void cmExtraEclipseCDT4Generator::AppendStorageScanners( compiler = "gcc"; } - // the following right now hardcodes gcc behaviour :-/ + // the following right now hardcodes gcc behavior :-/ std::string compilerArgs = "-E -P -v -dD ${plugin_state_location}/${specs_file}"; if (!arg1.empty()) { diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 996fcff1d8e..b7bac9c1306 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -30,7 +30,7 @@ cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator(cmake* cm) /* * Borland Make does not support long line depend rule, as we have tested * generate one source file includes 40000 header files, and generate - * depend.make in one line(use line continued tag), and error occured: + * depend.make in one line(use line continued tag), and error occurred: * ** Fatal CMakeFiles\main.dir\depend.make 1224: Rule line too long ** * we disable long line dependencies rule generation for Borland make */ diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 97384cd5a85..248abffa646 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -147,7 +147,7 @@ void cmGlobalUnixMakefileGenerator3::Generate() // write each target's progress.make this loop is done twice. Basically the // Generate pass counts all the actions, the first loop below determines // how many actions have progress updates for each target and writes to - // corrrect variable values for everything except the all targets. The + // correct variable values for everything except the all targets. The // second loop actually writes out correct values for the all targets as // well. This is because the all targets require more information that is // computed in the first loop. diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 21a9a445464..b83a1876bb4 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1972,7 +1972,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } - // Add VFS Overlay for Clang compiliers + // Add VFS Overlay for Clang compilers if (compiler == "Clang") { if (cmProp vfsOverlay = this->Makefile->GetDefinition("CMAKE_CLANG_VFS_OVERLAY")) { @@ -3931,7 +3931,7 @@ std::string ComputeCustomCommandRuleFileName(cmLocalGenerator& lg, // The output path contains a generator expression, but we must choose // a single source file path to which to attach the custom command. - // Use some heuristics to provie a nice-looking name when possible. + // Use some heuristics to provide a nice-looking name when possible. // If the only genex is $, replace that gracefully. { @@ -4219,7 +4219,7 @@ std::vector ComputeISPCObjectSuffixes(cmGeneratorTarget* target) auto pos = ispcTarget.find('-'); auto target_suffix = ispcTarget.substr(0, pos); if (target_suffix == - "avx1") { // when targetting avx1 ISPC uses the 'avx' output string + "avx1") { // when targeting avx1 ISPC uses the 'avx' output string target_suffix = "avx"; } ispcTarget = target_suffix; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index dba856037fb..5a37bb9be32 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -800,7 +800,7 @@ void cmMakefile::RunListFile(cmListFile const& listFile, for (size_t i = 0; i < defer->Commands.size(); ++i) { DeferCommand& d = defer->Commands[i]; if (d.Id.empty()) { - // Cancelled. + // Canceled. continue; } // Mark as executed. diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 3c07808170a..77e9c740505 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -993,7 +993,7 @@ class cmMakefile struct DeferCommand { - // Id is empty for an already-executed or cancelled operation. + // Id is empty for an already-executed or canceled operation. std::string Id; std::string FilePath; cmListFileFunction Command; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 68f40a9631d..37c4afce0a6 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -512,7 +512,7 @@ void cmOrderDirectories::VisitDirectory(unsigned int i) } // Now that all directories required to come before this one have - // been emmitted, emit this directory. + // been emitted, emit this directory. this->OrderedDirectories.push_back(this->OriginalDirectories[i]); } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 0aecf716fa8..9f9c493a433 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -186,7 +186,7 @@ class cmSystemTools : public cmsys::SystemTools * * Output is controlled with outputflag. If outputflag is OUTPUT_NONE, no * user-viewable output from the program being run will be generated. - * OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged + * OUTPUT_MERGE is the legacy behavior where stdout and stderr are merged * into stdout. OUTPUT_FORWARD copies the output to stdout/stderr as * it was received. OUTPUT_PASSTHROUGH passes through the original handles. * diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx index 8ea19423da9..e05b2d526d1 100644 --- a/Source/cmUVHandlePtr.cxx +++ b/Source/cmUVHandlePtr.cxx @@ -128,7 +128,7 @@ template <> struct uv_handle_deleter { /*** - * Wile uv_async_send is itself thread-safe, there are + * While uv_async_send is itself thread-safe, there are * no strong guarantees that close hasn't already been * called on the handle; and that it might be deleted * as the send call goes through. This mutex guards diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 4130f5fbf2a..a08babe3cd9 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -485,7 +485,7 @@ bool cmake::SetCacheArgs(const std::vector& args) auto ScriptLambda = [&](std::string const& path, cmake* state) -> bool { // Register fake project commands that hint misuse in script mode. GetProjectCommandsInScriptMode(state->GetState()); - // Documented behaviour of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be + // Documented behavior of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be // set to $PWD for -P mode. state->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); state->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 2c2ae4d17a7..30347f23b93 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1936,8 +1936,8 @@ int cmcmd::RunLLVMRC(std::vector const& args) skipNextArg = false; continue; } - // We use ++ as seperator between the preprocessing step definition and - // the rc compilation step becase we need to prepend a -- to seperate the + // We use ++ as separator between the preprocessing step definition and + // the rc compilation step because we need to prepend a -- to separate the // source file properly from other options when using clang-cl for // preprocessing. if (arg == "++") { From fd02f1010398c33854c0d73c781b3b3f770a774e Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 6 May 2021 22:28:08 +0200 Subject: [PATCH 0391/1519] Xcode: Fix typos and spelling in error message --- Source/cmGlobalXCodeGenerator.cxx | 2 +- .../GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d6909c3c260..7a2343a7bd1 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -393,7 +393,7 @@ bool cmGlobalXCodeGenerator::ProcessGeneratorToolsetField( " ", this->GetName(), "\n" "toolset specification field\n" " buildsystem=", value, "\n" - "value is unkonwn. It must be '1' or '12'." + "value is unknown. It must be '1' or '12'." ); /* clang-format on */ mf->IssueMessage(MessageType::FATAL_ERROR, e); diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt index 5e88e3bf11c..ba7a8f311d9 100644 --- a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt @@ -7,4 +7,4 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\): buildsystem=bad - value is unkonwn. It must be '1' or '12'\.$ + value is unknown. It must be '1' or '12'\.$ From 169da7cd81e0141f8797f809d82bf8d14caf8074 Mon Sep 17 00:00:00 2001 From: Mike Achtelik Date: Fri, 7 May 2021 21:08:47 +0200 Subject: [PATCH 0392/1519] Do not show RESOURCE DESTINATION warning for MACOSX_BUNDLE RESOURCE arguments are ignored on Apple platforms because the associated files are installed into the appropriate locations inside the framework folder. So we do not need to show a warning, that no RESOURCE DESTINATION is defined. Fixes #15676 --- Source/cmInstallCommand.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 7788db3bb86..0a8304f0b7f 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -775,7 +775,7 @@ bool HandleTargetsMode(std::vector const& args, if (!resourceArgs.GetDestination().empty()) { resourceGenerator = CreateInstallFilesGenerator( helper.Makefile, absFiles, resourceArgs, false); - } else { + } else if (!target.IsAppBundleOnApple()) { cmSystemTools::Message( cmStrCat("INSTALL TARGETS - target ", target.GetName(), " has RESOURCE files but no RESOURCE DESTINATION."), From 8146fcddc013d7b395f9c4eb9ca48c7de4618e84 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 8 May 2021 00:01:08 -0400 Subject: [PATCH 0393/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3cf01e4096e..5f0a39e229f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210507) +set(CMake_VERSION_PATCH 20210508) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6c657173d806aa81d1508830c10a16236b5358b9 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sat, 8 May 2021 16:19:21 +1000 Subject: [PATCH 0394/1519] cmake-gui: Address deprecation warnings with Qt6 --- Source/QtDialog/CMakeSetup.cxx | 11 +++++++---- Source/QtDialog/CMakeSetupDialog.cxx | 4 ++++ Source/QtDialog/QCMake.cxx | 7 ++++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 5debdb89b51..8ffa3e728db 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -112,7 +112,10 @@ int main(int argc, char** argv) cmAddPluginPath(); #endif -#if QT_VERSION >= 0x050600 +// HighDpiScaling is always enabled starting with Qt6, but will still issue a +// deprecation warning if you try to set the attribute for it +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) && \ + QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif @@ -132,9 +135,9 @@ int main(int argc, char** argv) translationsDir.cd(QString::fromLocal8Bit(".." CMAKE_DATA_DIR)); translationsDir.cd("i18n"); QTranslator translator; - QString transfile = QString("cmake_%1").arg(QLocale::system().name()); - translator.load(transfile, translationsDir.path()); - QApplication::installTranslator(&translator); + if (translator.load(QLocale(), "cmake", "_", translationsDir.path())) { + QApplication::installTranslator(&translator); + } // app setup QApplication::setApplicationName("CMakeSetup"); diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 031308891d6..1785571687b 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -178,7 +178,11 @@ CMakeSetupDialog::CMakeSetupDialog() &CMakeSetupDialog::doOutputErrorNext); a->setShortcut(QKeySequence(Qt::Key_F8)); auto* s = new QShortcut(this); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) s->setKey(QKeySequence(Qt::CTRL + Qt::Key_Period)); +#else + s->setKey(QKeySequence(Qt::CTRL | Qt::Key_Period)); +#endif QObject::connect(s, &QShortcut::activated, this, &CMakeSetupDialog::doOutputErrorNext); // in Eclipse diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 6796e25bb08..a83622afe87 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -334,7 +334,12 @@ void QCMake::setProperties(const QCMakePropertyList& newProps) toremove.append(QString::fromLocal8Bit(key.c_str())); } else { prop = props[idx]; - if (prop.Value.type() == QVariant::Bool) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + const bool isBool = prop.Value.type() == QVariant::Bool; +#else + const bool isBool = prop.Value.metaType() == QMetaType::fromType(); +#endif + if (isBool) { state->SetCacheEntryValue(key, prop.Value.toBool() ? "ON" : "OFF"); } else { state->SetCacheEntryValue(key, From 1aa4f97c9737fa077d2279c422f68ac6facde782 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 28 Mar 2021 12:18:09 +1100 Subject: [PATCH 0395/1519] cmCTestGenericHandler: Remove unused Command member This was causing a cppcheck warning about an uninitialized member in the constructor. Since nothing was using it, remove it. --- Source/CTest/cmCTestGenericHandler.h | 4 ---- Source/CTest/cmCTestUpdateCommand.cxx | 1 - 2 files changed, 5 deletions(-) diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 6f445453be4..e846fd9569d 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -13,7 +13,6 @@ #include "cmCTest.h" #include "cmSystemTools.h" -class cmCTestCommand; class cmGeneratedFileStream; class cmMakefile; @@ -107,8 +106,6 @@ class cmCTestGenericHandler void AddMultiOption(const std::string& optionName, const std::string& value); std::vector GetMultiOption(const std::string& op) const; - void SetCommand(cmCTestCommand* command) { this->Command = command; } - void SetSubmitIndex(int idx) { this->SubmitIndex = idx; } int GetSubmitIndex() { return this->SubmitIndex; } @@ -134,6 +131,5 @@ class cmCTestGenericHandler t_StringToMultiString PersistentMultiOptions; t_StringToString LogFileNames; - cmCTestCommand* Command; int SubmitIndex; }; diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 0ba2c417b6e..797cb014ea7 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -75,7 +75,6 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() cmCTestUpdateHandler* handler = this->CTest->GetUpdateHandler(); handler->Initialize(); - handler->SetCommand(this); if (source_dir.empty()) { this->SetError("source directory not specified. Please use SOURCE tag"); return nullptr; From 5e941a545bf5882ddf101cad383dc815fb651f26 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 9 May 2021 12:33:16 +1000 Subject: [PATCH 0396/1519] ExternalProject: Ensure git fetch if updating to hash we don't have yet In ac6a4d4884 (ExternalProject: Improve robustness of update step, 2020-10-17), the method used to check whether we already have a commit or not was changed from using git rev-list to git rev-parse. The new logic assumed rev-parse would output nothing if given a commit hash it didn't know about, but it simply prints the hash again without raising an error in this scenario. Amend that logic by adding ^{commit} to the ref to ensure we do get an error if that ref is not currently known. Fixes: #22166 --- Modules/ExternalProject-gitupdate.cmake.in | 2 +- ...{FetchGitTags.cmake => FetchGitRefs.cmake} | 21 +++++++++++++++++-- .../CMakeLists.txt | 0 .../ExternalProject/RunCMakeTest.cmake | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) rename Tests/RunCMake/ExternalProject/{FetchGitTags.cmake => FetchGitRefs.cmake} (73%) rename Tests/RunCMake/ExternalProject/{FetchGitTags => FetchGitRefs}/CMakeLists.txt (100%) diff --git a/Modules/ExternalProject-gitupdate.cmake.in b/Modules/ExternalProject-gitupdate.cmake.in index 70339180568..461e3235407 100644 --- a/Modules/ExternalProject-gitupdate.cmake.in +++ b/Modules/ExternalProject-gitupdate.cmake.in @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5) function(get_hash_for_ref ref out_var err_var) execute_process( - COMMAND "@git_EXECUTABLE@" rev-parse "${ref}" + COMMAND "@git_EXECUTABLE@" rev-parse "${ref}^{commit}" WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code OUTPUT_VARIABLE ref_hash diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake b/Tests/RunCMake/ExternalProject/FetchGitRefs.cmake similarity index 73% rename from Tests/RunCMake/ExternalProject/FetchGitTags.cmake rename to Tests/RunCMake/ExternalProject/FetchGitRefs.cmake index 37d1b40889d..a00908b39df 100644 --- a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake +++ b/Tests/RunCMake/ExternalProject/FetchGitRefs.cmake @@ -11,7 +11,7 @@ file(MAKE_DIRECTORY ${srcDir}) file(GLOB entries ${srcRepo}/*) file(REMOVE_RECURSE ${entries} ${binDir}) file(TOUCH ${srcRepo}/firstFile.txt) -configure_file(${CMAKE_CURRENT_LIST_DIR}/FetchGitTags/CMakeLists.txt +configure_file(${CMAKE_CURRENT_LIST_DIR}/FetchGitRefs/CMakeLists.txt ${srcDir}/CMakeLists.txt COPYONLY) function(execGitCommand) @@ -63,5 +63,22 @@ execGitCommand(commit -m "Second file") execGitCommand(tag -a -m "Adding tag" tag_of_interest) execGitCommand(reset --hard HEAD~1) -message(STATUS "Second configure-and-build") +message(STATUS "Configure-and-build, update to tag") configureAndBuild(tag_of_interest) + +# Do the same, but this time for a commit hash +file(TOUCH ${srcRepo}/thirdFile.txt) +execGitCommand(add thirdFile.txt) +execGitCommand(commit -m "Third file") +execGitCommand(tag -a -m "Adding another tag" check_for_hash) +execGitCommand(reset --hard HEAD~1) +execute_process( + WORKING_DIRECTORY ${srcRepo} + COMMAND ${GIT_EXECUTABLE} rev-parse check_for_hash + COMMAND_ERROR_IS_FATAL ANY + OUTPUT_VARIABLE commit_hash + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +message(STATUS "Configure-and-build, update to commit hash ${commit_hash}") +configureAndBuild(${commit_hash}) diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt b/Tests/RunCMake/ExternalProject/FetchGitRefs/CMakeLists.txt similarity index 100% rename from Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt rename to Tests/RunCMake/ExternalProject/FetchGitRefs/CMakeLists.txt diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake index 3205dd54cc1..a4244e364d2 100644 --- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake @@ -185,6 +185,6 @@ if(GIT_EXECUTABLE) # Note that there appear to be differences in where git writes its output to # on some platforms. It may go to stdout or stderr, so force it to be merged. set(RunCMake_TEST_OUTPUT_MERGE TRUE) - run_cmake(FetchGitTags) + run_cmake(FetchGitRefs) set(RunCMake_TEST_OUTPUT_MERGE FALSE) endif() From f22d807df46938ed762e41092fce4f9ddd13925a Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 9 May 2021 00:01:04 -0400 Subject: [PATCH 0397/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5f0a39e229f..4e88e2b0820 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210508) +set(CMake_VERSION_PATCH 20210509) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9a318a6c7a5c32de3646d6facc7586f968cc494f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 10 May 2021 00:01:10 -0400 Subject: [PATCH 0398/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4e88e2b0820..3de1818b6b3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210509) +set(CMake_VERSION_PATCH 20210510) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 05f8c8178dabe3ca8080af0f12ff578cd02971b8 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 8 May 2021 13:38:10 +0300 Subject: [PATCH 0399/1519] GNU: C++17 default version Changed in GCC commit 0801f419440c14f6772b28f763ad7d40f7f7a580, released in 11.1. --- Modules/Compiler/GNU-CXX.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index 758d3c783f7..d7318ea48d1 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -66,4 +66,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0) set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") endif() -__compiler_check_default_language_standard(CXX 3.4 98 6.0 14) +__compiler_check_default_language_standard(CXX 3.4 98 6.0 14 11.1 17) From c9a1e06a18594640d548b1aec31ea9e07b0b5b82 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 8 May 2021 13:45:33 +0300 Subject: [PATCH 0400/1519] GNU: Final C++20 flags Added in GCC commit fb26050409473f5be54465beca114b7e48de43aa, released in 11.1. --- Modules/Compiler/GNU-CXX.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index d7318ea48d1..c8357b24652 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -61,7 +61,10 @@ elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1) set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0) +if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) + set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20") + set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20") +elseif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++2a") set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") endif() From 9fbbebe3d03f2576a8c5d6284c6f122b99e232a9 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 8 May 2021 13:47:18 +0300 Subject: [PATCH 0401/1519] GNU: C++23 support Added in GCC commit 78739c2df788ee5c868d998a6333d453317d8711, released in 11.1. No lettered variant beforehand this time around. Implements #22139. --- Modules/Compiler/GNU-CXX.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index c8357b24652..b35f2541727 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -64,6 +64,8 @@ endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20") set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20") + set(CMAKE_CXX23_STANDARD_COMPILE_OPTION "-std=c++23") + set(CMAKE_CXX23_EXTENSION_COMPILE_OPTION "-std=gnu++23") elseif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++2a") set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") From 66be34853ce0046c132a5713d41e5c3608612bbf Mon Sep 17 00:00:00 2001 From: scheffle Date: Fri, 7 May 2021 15:28:29 +0200 Subject: [PATCH 0402/1519] cmake: add supported platforms to cmake -E capabilties report --- Help/manual/cmake.1.rst | 6 ++++++ Help/release/dev/capabilties-generator-platforms.rst | 6 ++++++ Source/cmake.cxx | 7 +++++++ 3 files changed, 19 insertions(+) create mode 100644 Help/release/dev/capabilties-generator-platforms.rst diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index f416f86283a..55e01e18f73 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -575,6 +575,12 @@ Available commands are: ``true`` if the generator supports toolsets and ``false`` otherwise. ``platformSupport`` ``true`` if the generator supports platforms and ``false`` otherwise. + ``supportedPlatforms`` + .. versionadded:: 3.21 + + Optional member that may be present when the generator supports + platform specification via :variable:`CMAKE_GENERATOR_PLATFORM` + (``-A ...``). The value is a list of platforms known to be supported. ``extraGenerators`` A list of strings with all the extra generators compatible with the generator. diff --git a/Help/release/dev/capabilties-generator-platforms.rst b/Help/release/dev/capabilties-generator-platforms.rst new file mode 100644 index 00000000000..5de2b67ab2e --- /dev/null +++ b/Help/release/dev/capabilties-generator-platforms.rst @@ -0,0 +1,6 @@ +capabilties-generator-platforms +------------------------------- + +* The :manual:`cmake(1)` ``-E capabilities`` output now contains for each + generator a ``supportedPlatforms`` field listing platform known to + be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 4130f5fbf2a..0eede0ae4a9 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -259,6 +259,13 @@ Json::Value cmake::ReportCapabilitiesJson() const gen["name"] = gi.name; gen["toolsetSupport"] = gi.supportsToolset; gen["platformSupport"] = gi.supportsPlatform; + if (!gi.supportedPlatforms.empty()) { + Json::Value supportedPlatforms = Json::arrayValue; + for (std::string const& platform : gi.supportedPlatforms) { + supportedPlatforms.append(platform); + } + gen["supportedPlatforms"] = std::move(supportedPlatforms); + } gen["extraGenerators"] = Json::arrayValue; generatorMap[gi.name] = gen; } else { From 3e03f359a764fe536fe01f28185d71903bdd41ea Mon Sep 17 00:00:00 2001 From: Smit tay Date: Tue, 27 Apr 2021 21:42:41 +0200 Subject: [PATCH 0403/1519] UseJava: Add RESOURCES with NAMESPACE to add_jar() add_jar() currently requires (undocumented) that resources be supplied as relative paths. The resources *may* then end up in a path which does not reflect the original path particularly when performing out-of-source builds. This change adds a RESOURCE (and NAMESPACE) parameter and a function to add the names resources into the named namespace within the jar- and thus address both of these problems. Fixes: #22101 --- .../dev/UseJava-RESOURCES-NAMESPACE.rst | 5 + Modules/UseJava.cmake | 103 ++++++++++++++++-- Tests/Java/CMakeLists.txt | 7 ++ Tests/Java/HelloWorld.txt | 1 + Tests/Java/ResourceNS.java | 48 ++++++++ 5 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst create mode 100644 Tests/Java/HelloWorld.txt create mode 100644 Tests/Java/ResourceNS.java diff --git a/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst b/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst new file mode 100644 index 00000000000..a7bb685937e --- /dev/null +++ b/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst @@ -0,0 +1,5 @@ +UseJava-RESOURCES-NAMESPACE +--------------------------- + +* The :module:`UseJava` module command ``add_jar`` gained option RESOURCES + allow explicit naming of resouces with non-optional namespace. diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 120a54c8457..67478cca3e1 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -18,6 +18,7 @@ Creating And Installing JARs add_jar( [SOURCES] [...] [...] + [RESOURCES NAMESPACE ... [NAMESPACE ...]... ] [INCLUDE_JARS [...]] [ENTRY_POINT ] [VERSION ] @@ -31,7 +32,31 @@ This command creates a ``.jar``. It compiles the given ```` files and adds the given ```` files to the jar file. Source files can be java files or listing files (prefixed by ``@``). If only resource files are given then just a jar file -is created. The list of ``INCLUDE_JARS`` are added to the classpath when +is created. + +The ``RESOURCES`` parameter adds the named ```` files to the jar +by stripping the source file path and placing the file beneath ```` +within the jar. For example:: + + RESOURCES NAMESPACE "/com/my/namespace" "a/path/to/resource.txt" + +results in a resource accessible via ``/com/my/namespace/resource.txt`` +within the jar. + +Resources may be added without adjusting the namespace by adding them to +the list of ``SOURCES`` (original behavior), in this case, resource +paths must be relative to ``CMAKE_CURRENT_SOURCE_DIR``. Adding resources +without using the ``RESOURCES`` parameter in out of source builds will +almost certainly result in confusion. + +.. note:: SOURCES + Adding resources via the ``SOURCES`` parameter relies upon a hard-coded + list of file extensions which are tested to determine compilability + (e.g. File.java). ``SOURCES`` files which match the extensions are compiled. + Files which do not match are treated as resources. To include uncompiled + resources matching those file extensions use the ``RESOURCES`` parameter. + +The list of ``INCLUDE_JARS`` are added to the classpath when compiling the java sources and also to the dependencies of the target. ``INCLUDE_JARS`` also accepts other target names created by ``add_jar()``. For backwards compatibility, jar files listed as sources are ignored (as @@ -449,6 +474,58 @@ function(__java_export_jar VAR TARGET PATH) set(${VAR} "${${VAR}}" PARENT_SCOPE) endfunction() +function(__java_copy_resource_namespaces VAR DEST JAVA_RESOURCE_FILES JAVA_RESOURCE_FILES_RELATIVE) + + set(_ns_ID "") + set(_ns_VAL "") + + foreach(_item IN LISTS VAR) + if(NOT _ns_ID) + if(NOT _item STREQUAL "NAMESPACE") + message(FATAL_ERROR "UseJava: Expecting \"NAMESPACE\", got\t\"${_item}\"") + return() + endif() + endif() + + if(_item STREQUAL "NAMESPACE") + set(_ns_VAL "") # Prepare for next namespace + set(_ns_ID "${_item}") + continue() + endif() + + if( NOT _ns_VAL) + # we're expecting the next token to be a namespace value + # whatever it is, we're treating it like a namespace + set(_ns_VAL "${_item}") + continue() + endif() + + if(_ns_ID AND _ns_VAL) + # We're expecting a file name, check to see if we got one + cmake_path(ABSOLUTE_PATH _item OUTPUT_VARIABLE _test_file_name) + if (NOT EXISTS "${_test_file_name}") + message(FATAL_ERROR "UseJava: File does not exist:\t${_item}") + return() + endif() + endif() + + cmake_path(ABSOLUTE_PATH _item OUTPUT_VARIABLE _abs_file_name) + cmake_path(GET _item FILENAME _resource_file_name) + set(_dest_resource_file_name "${_ns_VAL}/${_resource_file_name}" ) + + __java_copy_file( ${_abs_file_name} + ${DEST}/${_dest_resource_file_name} + "Copying ${_item} to the build directory") + + list(APPEND RESOURCE_FILES_LIST ${DEST}/${_dest_resource_file_name}) + list(APPEND RELATIVE_RESOURCE_FILES_LIST ${_dest_resource_file_name}) + + endforeach() + + set(${JAVA_RESOURCE_FILES} "${RESOURCE_FILES_LIST}" PARENT_SCOPE) + set(${JAVA_RESOURCE_FILES_RELATIVE} "${RELATIVE_RESOURCE_FILES_LIST}" PARENT_SCOPE) +endfunction() + # define helper scripts set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/javaTargets.cmake.in) set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/Symlinks.cmake) @@ -461,12 +538,14 @@ endif() function(add_jar _TARGET_NAME) - cmake_parse_arguments(_add_jar - "" - "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST" - "SOURCES;INCLUDE_JARS;GENERATE_NATIVE_HEADERS" - ${ARGN} - ) + set(options) # currently there are no zero value args (aka: options) + set(oneValueArgs "ENTRY_POINT;MANIFEST;OUTPUT_DIR;;OUTPUT_NAME;VERSION" ) + set(multiValueArgs "GENERATE_NATIVE_HEADERS;INCLUDE_JARS;RESOURCES;SOURCES" ) + + cmake_parse_arguments(PARSE_ARGV 1 _add_jar + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" ) # In CMake < 2.8.12, add_jar used variables which were set prior to calling # add_jar for customizing the behavior of add_jar. In order to be backwards @@ -490,6 +569,9 @@ function(add_jar _TARGET_NAME) set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}") endif() + # This *should* still work if ... are included without a + # named RESOURCES argument. In that case, the old behavior of potentially + # misplacing the within the Jar will behave as previously (incorrectly) set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS}) if (NOT DEFINED _add_jar_OUTPUT_DIR) @@ -639,6 +721,13 @@ function(add_jar _TARGET_NAME) endif () endforeach() + if(_add_jar_RESOURCES) # Process RESOURCES if it exists + __java_copy_resource_namespaces("${_add_jar_RESOURCES}" + ${CMAKE_JAVA_CLASS_OUTPUT_PATH} + _JAVA_RESOURCE_FILES + _JAVA_RESOURCE_FILES_RELATIVE) + endif() + foreach(_JAVA_INCLUDE_JAR IN LISTS _add_jar_INCLUDE_JARS) if (TARGET ${_JAVA_INCLUDE_JAR}) get_target_property(_JAVA_JAR_PATH ${_JAVA_INCLUDE_JAR} JAR_FILE) diff --git a/Tests/Java/CMakeLists.txt b/Tests/Java/CMakeLists.txt index e4f28211c6c..1d8d7ac67bc 100644 --- a/Tests/Java/CMakeLists.txt +++ b/Tests/Java/CMakeLists.txt @@ -17,9 +17,16 @@ add_jar(hello2 @${CMAKE_CURRENT_BINARY_DIR}/java_fileslist) # use listing file to specify sources and specify output directory (issue #17316) add_jar(hello3 @${CMAKE_CURRENT_BINARY_DIR}/java_fileslist OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/hello3") +add_jar(ResourceNS + SOURCES ResourceNS.java + RESOURCES NAMESPACE ns/ns1 HelloWorld.txt + NAMESPACE ns/ns2 HelloWorld.txt) # add a second namespace + add_test (NAME Java.Jar COMMAND "${Java_JAVA_EXECUTABLE}" -classpath hello.jar HelloWorld) add_test (NAME Java.JarSourceList COMMAND "${Java_JAVA_EXECUTABLE}" -classpath hello2.jar HelloWorld) add_test (NAME Java.JarSourceListAndOutput COMMAND "${Java_JAVA_EXECUTABLE}" -classpath "${CMAKE_CURRENT_BINARY_DIR}/hello3/hello3.jar" HelloWorld) +add_test (NAME Java.JarResourceNS + COMMAND "${Java_JAVA_EXECUTABLE}" -classpath ResourceNS.jar ResourceNS) diff --git a/Tests/Java/HelloWorld.txt b/Tests/Java/HelloWorld.txt new file mode 100644 index 00000000000..d7407a1fcb2 --- /dev/null +++ b/Tests/Java/HelloWorld.txt @@ -0,0 +1 @@ +Hello World ! diff --git a/Tests/Java/ResourceNS.java b/Tests/Java/ResourceNS.java new file mode 100644 index 00000000000..7289e6ea355 --- /dev/null +++ b/Tests/Java/ResourceNS.java @@ -0,0 +1,48 @@ +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.IOException; + +class ResourceNS +{ + public static void main(String args[]) + { + ResourceNS res = new ResourceNS(); + res.displayResourceText(); + } + + public void displayResourceText() + { + /* + * Since Java SE 9, invoking getResourceXXX on a class in a named + * module will only locate the resource in that module, it will + * not search the class path as it did in previous release. So when + * you use Class.getClassLoader().getResource() it will attempt to + * locate the resource in the module containing the ClassLoader, + * possibly something like: + * jdk.internal.loader.ClassLoaders.AppClassLoader + * which is probably not the module that your resource is in, so it + * returns null. + * + * You have to make java 9+ search for the file in your module. + * Do that by changing Class to any class defined in your module in + * order to make java use the proper class loader. + */ + + // Namespaces are relative, use leading '/' for full namespace + InputStream is = + ResourceNS.class.getResourceAsStream("/ns/ns1/HelloWorld.txt"); + // C++: cout << is.readline(); // oh, well ! + InputStreamReader isr = new InputStreamReader(is); + BufferedReader reader = new BufferedReader(isr); + String out = ""; + try{ + out = reader.readLine(); + } catch(IOException e) { + e.printStackTrace(); + System.out.println(e); + } + + System.out.println(out); + } +} From 140fe8c3c698687bd42ff98e62c569d3338aadc4 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Mon, 10 May 2021 09:12:52 -0400 Subject: [PATCH 0404/1519] Help: Document CTEST_SCRIPT_DIRECTORY variable --- Help/manual/cmake-variables.7.rst | 1 + Help/variable/CTEST_SCRIPT_DIRECTORY.rst | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 Help/variable/CTEST_SCRIPT_DIRECTORY.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 37ef053db41..da463c5d654 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -646,6 +646,7 @@ Variables for CTest /variable/CTEST_RESOURCE_SPEC_FILE /variable/CTEST_RUN_CURRENT_SCRIPT /variable/CTEST_SCP_COMMAND + /variable/CTEST_SCRIPT_DIRECTORY /variable/CTEST_SITE /variable/CTEST_SUBMIT_URL /variable/CTEST_SOURCE_DIRECTORY diff --git a/Help/variable/CTEST_SCRIPT_DIRECTORY.rst b/Help/variable/CTEST_SCRIPT_DIRECTORY.rst new file mode 100644 index 00000000000..77d4e58c93a --- /dev/null +++ b/Help/variable/CTEST_SCRIPT_DIRECTORY.rst @@ -0,0 +1,5 @@ +CTEST_SCRIPT_DIRECTORY +---------------------- + +The directory containing the top-level CTest script. +The concept is similar to :variable:`CMAKE_SOURCE_DIR`. From d0c31cbff94b86ae00fddac89c6f404cc4229370 Mon Sep 17 00:00:00 2001 From: Georg Schwab Date: Thu, 6 May 2021 11:26:09 +0200 Subject: [PATCH 0405/1519] Windows: Use real artifact versioning symlinks if possible When cross compiling from Windows to a platform that uses SONAMEs, real symlinks are now created for the VERSION and SOVERSION links instead of copies, if the user has the necessary privileges. Fixes: #22128 --- Source/cmcmd.cxx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 30347f23b93..98946b64fba 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1643,10 +1643,21 @@ cmsys::Status cmcmd::SymlinkInternal(std::string const& file, if (cmSystemTools::FileExists(link) || cmSystemTools::FileIsSymlink(link)) { cmSystemTools::RemoveFile(link); } + std::string linktext = cmSystemTools::GetFilenameName(file); #if defined(_WIN32) && !defined(__CYGWIN__) - return cmSystemTools::CopyFileAlways(file, link); + std::string errorMessage; + cmsys::Status status = + cmSystemTools::CreateSymlink(linktext, link, &errorMessage); + // Creating a symlink will fail with ERROR_PRIVILEGE_NOT_HELD if the user + // does not have SeCreateSymbolicLinkPrivilege, or if developer mode is not + // active. In that case, we try to copy the file. + if (status.GetWindows() == ERROR_PRIVILEGE_NOT_HELD) { + status = cmSystemTools::CopyFileAlways(file, link); + } else if (!status) { + cmSystemTools::Error(errorMessage); + } + return status; #else - std::string linktext = cmSystemTools::GetFilenameName(file); return cmSystemTools::CreateSymlink(linktext, link); #endif } From ce97b7909bdd4be78c4be2e2326c5ae3e27a21f0 Mon Sep 17 00:00:00 2001 From: Vitaly Stakhovsky Date: Mon, 10 May 2021 11:00:00 -0400 Subject: [PATCH 0406/1519] Source: Remove unnecessary comparisons to nullptr --- Source/cmExportFileGenerator.cxx | 2 +- Source/cmExtraEclipseCDT4Generator.cxx | 6 ++--- Source/cmExtraKateGenerator.cxx | 2 +- Source/cmGeneratorTarget.cxx | 11 ++++---- Source/cmGhsMultiTargetGenerator.cxx | 2 +- Source/cmLocalGenerator.cxx | 6 ++--- Source/cmLocalVisualStudio7Generator.cxx | 4 +-- Source/cmMakefileTargetGenerator.cxx | 2 +- Source/cmNinjaTargetGenerator.cxx | 2 +- Source/cmQtAutoGenGlobalInitializer.cxx | 2 +- Source/cmQtAutoGenInitializer.cxx | 34 ++++++++++++------------ Source/cmStandardLevelResolver.cxx | 2 +- Source/cmXCodeScheme.cxx | 2 +- Source/cmake.cxx | 6 ++--- 14 files changed, 40 insertions(+), 43 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 0409f97cab7..dd611de6b68 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1229,7 +1229,7 @@ bool cmExportFileGenerator::PopulateExportProperties( return false; } cmProp propertyValue = targetProperties.GetPropertyValue(prop); - if (propertyValue == nullptr) { + if (!propertyValue) { // Asked to export a property that isn't defined on the target. Do not // consider this an error, there's just nothing to export. continue; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 824f5ed6cc7..70d373c41bc 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -248,17 +248,17 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, // now we have both, decide which one to use std::string valueToUse; - if (!envVarSet && cacheValue == nullptr) { + if (!envVarSet && !cacheValue) { // nothing known, do nothing valueToUse.clear(); - } else if (envVarSet && cacheValue == nullptr) { + } else if (envVarSet && !cacheValue) { // The variable is in the env, but not in the cache. Use it and put it // in the cache valueToUse = envVarValue; mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); - } else if (!envVarSet && cacheValue != nullptr) { + } else if (!envVarSet && cacheValue) { // It is already in the cache, but not in the env, so use it from the cache valueToUse = *cacheValue; } else { diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index 54c311452c6..9153119c4bb 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -130,7 +130,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg, if (targetName == "edit_cache") { cmProp editCommand = localGen->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND"); - if (editCommand == nullptr || + if (!editCommand || strstr(editCommand->c_str(), "ccmake") != nullptr) { insertTarget = false; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 365f8b84114..bbc0050d3dc 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -970,7 +970,7 @@ cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( std::string const& lang, const char* suffix) const { cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix)); - if (propertyValue == nullptr) { + if (!propertyValue) { // Check if we should use the value set by another language. if (lang == "OBJC") { propertyValue = this->GetPropertyWithPairedLanguageSupport("C", suffix); @@ -4715,21 +4715,20 @@ bool cmGeneratorTarget::ComputeCompileFeatures( cmStrCat(cmSystemTools::UpperCase(config), '-', language.first); BTs const* standardToCopy = this->GetLanguageStandardProperty(language.second, config); - if (standardToCopy != nullptr) { + if (standardToCopy) { this->LanguageStandardMap[key] = *standardToCopy; generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; } else { cmProp defaultStandard = this->Makefile->GetDefinition( cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT")); - if (defaultStandard != nullptr) { + if (defaultStandard) { this->LanguageStandardMap[key] = BTs(*defaultStandard); generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; } } // Custom updates for the CUDA standard. - if (generatorTargetLanguageStandard != nullptr && - language.first == "CUDA") { + if (generatorTargetLanguageStandard && language.first == "CUDA") { if (generatorTargetLanguageStandard->Value == "98") { this->LanguageStandardMap[key].Value = "03"; } @@ -6771,7 +6770,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( return; } iface.Exists = true; - iface.Explicit = cmp0022NEW || explicitLibraries != nullptr; + iface.Explicit = cmp0022NEW || explicitLibraries; if (explicitLibraries) { // The interface libraries have been explicitly set. diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index ed5bff5ff83..9a17d07d7da 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -710,7 +710,7 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride( std::ostream& fout, const cmSourceFile* sourceFile) { cmProp rawLangProp = sourceFile->GetProperty("LANGUAGE"); - if (nullptr != rawLangProp) { + if (rawLangProp) { std::string sourceLangProp(*rawLangProp); std::string const& extension = sourceFile->GetExtension(); if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index b83a1876bb4..db7357a3aae 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2438,7 +2438,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target) } cmProp ispcHeaderSuffixProp = target->GetProperty("ISPC_HEADER_SUFFIX"); - assert(ispcHeaderSuffixProp != nullptr); + assert(ispcHeaderSuffixProp); std::vector ispcArchSuffixes = detail::ComputeISPCObjectSuffixes(target); @@ -3001,7 +3001,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO"; cmProp rawFlagsList = this->Makefile->GetDefinition(name); - if (rawFlagsList == nullptr) { + if (!rawFlagsList) { return; } @@ -3240,7 +3240,7 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags, { cmProp optionList = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature)); - if (optionList != nullptr) { + if (optionList) { std::vector options = cmExpandedList(*optionList); for (std::string const& o : options) { this->AppendFlagEscape(flags, o); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index a3940ead6cd..cead87b064c 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1214,7 +1214,7 @@ void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool( cmProp additionalFiles = target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES"); - if (dir == nullptr && additionalFiles == nullptr) { + if (!dir && !additionalFiles) { return; } @@ -1228,7 +1228,7 @@ void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool( << GetEscapedPropertyIfValueNotNULL(additionalFiles->c_str()) << "\"/>\n"; - if (dir != nullptr) { + if (dir) { std::string const exe = *dir + "\\" + target->GetFullName(config); fout << "\t\t\tGeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX"); - assert(ispcSuffixProp != nullptr); + assert(ispcSuffixProp); std::string directory = this->GeneratorTarget->GetObjectDirectory(config); if (cmProp prop = diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index f7777fc1200..ce0d8693aad 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1444,7 +1444,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmProp ispcSuffixProp = this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX"); - assert(ispcSuffixProp != nullptr); + assert(ispcSuffixProp); std::string ispcHeaderDirectory = this->GeneratorTarget->GetObjectDirectory(config); diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 153cb6d2902..77fe87e4c31 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -185,7 +185,7 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( { cmProp folder = makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); - if (folder != nullptr) { + if (folder) { target->SetProperty("FOLDER", *folder); } } diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 148591ce271..2894201c9b3 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -114,10 +114,10 @@ bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, // Collect all static_library dependencies from the test target cmLinkImplementationLibraries const* libs = testTarget->GetLinkImplementationLibraries(config); - if (libs != nullptr) { + if (libs) { for (cmLinkItem const& item : libs->Libraries) { cmGeneratorTarget const* depTarget = item.Target; - if ((depTarget != nullptr) && + if (depTarget && (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) && knownLibs.insert(depTarget).second) { testLibs.push_back(depTarget); @@ -357,15 +357,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets() { cmProp folder = this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); - if (folder == nullptr) { + if (!folder) { folder = this->Makefile->GetState()->GetGlobalProperty( "AUTOGEN_TARGETS_FOLDER"); } // Inherit FOLDER property from target (#13688) - if (folder == nullptr) { + if (!folder) { folder = this->GenTarget->GetProperty("FOLDER"); } - if (folder != nullptr) { + if (folder) { this->TargetsFolder = *folder; } } @@ -490,7 +490,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() for (std::string const& depName : cmExpandedList(deps)) { // Allow target and file dependencies auto* depTarget = this->Makefile->FindTargetToUse(depName); - if (depTarget != nullptr) { + if (depTarget) { this->AutogenTarget.DependTargets.insert(depTarget); } else { this->AutogenTarget.DependFiles.insert(depName); @@ -662,7 +662,7 @@ bool cmQtAutoGenInitializer::InitMoc() return false; } // Let the _autogen target depend on the moc executable - if (this->Moc.ExecutableTarget != nullptr) { + if (this->Moc.ExecutableTarget) { this->AutogenTarget.DependTargets.insert( this->Moc.ExecutableTarget->Target); } @@ -710,7 +710,7 @@ bool cmQtAutoGenInitializer::InitUic() return false; } // Let the _autogen target depend on the uic executable - if (this->Uic.ExecutableTarget != nullptr) { + if (this->Uic.ExecutableTarget) { this->AutogenTarget.DependTargets.insert( this->Uic.ExecutableTarget->Target); } @@ -865,7 +865,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() auto constexpr locationKind = cmSourceFileLocationKind::Known; cmSourceFile* sf = this->Makefile->GetSource(fullPath, locationKind); - if (sf != nullptr) { + if (sf) { // Check if we know about this header already if (cm::contains(this->AutogenTarget.Headers, sf)) { continue; @@ -880,7 +880,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() sf = this->Makefile->CreateSource(fullPath, false, locationKind); } - if (sf != nullptr) { + if (sf) { auto eMuf = makeMUFile(sf, fullPath, muf.Configs, true); // Only process moc/uic when the parent is processed as well if (!muf.MocIt) { @@ -1243,10 +1243,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() for (std::string const& config : this->ConfigsList) { cmLinkImplementationLibraries const* libs = this->GenTarget->GetLinkImplementationLibraries(config); - if (libs != nullptr) { + if (libs) { for (cmLinkItem const& item : libs->Libraries) { cmGeneratorTarget const* libTarget = item.Target; - if ((libTarget != nullptr) && + if (libTarget && !StaticLibraryCycle(this->GenTarget, libTarget, config)) { // Increment target config count commonTargets[libTarget]++; @@ -1780,7 +1780,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, // Generate a source group on demand if (!groupName.empty()) { sourceGroup = this->Makefile->GetOrCreateSourceGroup(groupName); - if (sourceGroup == nullptr) { + if (!sourceGroup) { cmSystemTools::Error( cmStrCat(genNameUpper, " error in ", property, ": Could not find or create the source group ", @@ -1788,7 +1788,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, } } } - if (sourceGroup != nullptr) { + if (sourceGroup) { sourceGroup->AddGroupFile(fileName); } } @@ -1894,14 +1894,14 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target, // Converts a char ptr to an unsigned int value auto toUInt = [](const char* const input) -> unsigned int { unsigned long tmp = 0; - if (input != nullptr && cmStrToULong(input, &tmp)) { + if (input && cmStrToULong(input, &tmp)) { return static_cast(tmp); } return 0u; }; auto toUInt2 = [](cmProp input) -> unsigned int { unsigned long tmp = 0; - if (input != nullptr && cmStrToULong(*input, &tmp)) { + if (input && cmStrToULong(*input, &tmp)) { return static_cast(tmp); } return 0u; @@ -2073,7 +2073,7 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, // Find target cmGeneratorTarget* genTarget = this->LocalGen->FindGeneratorTargetToUse(targetName); - if (genTarget != nullptr) { + if (genTarget) { genVars.ExecutableTargetName = targetName; genVars.ExecutableTarget = genTarget; if (genTarget->IsImported()) { diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 280e508d66e..85411e6fe50 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -184,7 +184,7 @@ struct StanardLevelComputer auto needed = this->HighestStandardNeeded(makefile, feature); cmProp existingStandard = currentLangStandardValue; - if (existingStandard == nullptr) { + if (!existingStandard) { cmProp defaultStandard = makefile->GetDefinition( cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); if (cmNonempty(defaultStandard)) { diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index 55e941d947c..e4329afc6cb 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -324,7 +324,7 @@ bool cmXCodeScheme::WriteLaunchActionBooleanAttribute( bool defaultValue) { cmProp property = Target->GetTarget()->GetProperty(varName); - bool isOn = (property == nullptr && defaultValue) || cmIsOn(property); + bool isOn = (!property && defaultValue) || cmIsOn(property); if (isOn) { xout.Attribute(attrName.c_str(), "YES"); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a08babe3cd9..225fa3ce597 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1251,15 +1251,13 @@ void cmake::SetArgs(const std::vector& args) this->UnprocessedPresetEnvironment = expandedPreset->Environment; if (!expandedPreset->InstallDir.empty() && - this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX") == - nullptr) { + !this->State->GetInitializedCacheValue("CMAKE_INSTALL_PREFIX")) { this->UnprocessedPresetVariables["CMAKE_INSTALL_PREFIX"] = { "PATH", expandedPreset->InstallDir }; } if (!expandedPreset->ToolchainFile.empty() && - this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE") == - nullptr) { + !this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) { this->UnprocessedPresetVariables["CMAKE_TOOLCHAIN_FILE"] = { "FILEPATH", expandedPreset->ToolchainFile }; From fdab87312cab30a731b635b22756bf5c3dc942db Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 11 May 2021 00:01:09 -0400 Subject: [PATCH 0407/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3de1818b6b3..4af9474c4a6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210510) +set(CMake_VERSION_PATCH 20210511) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 5e8fa0b7bcdd8f4f1af2a61335df9a1c952dbbdf Mon Sep 17 00:00:00 2001 From: Vitaly Stakhovsky Date: Tue, 11 May 2021 11:20:00 -0400 Subject: [PATCH 0408/1519] Source: Minor code improvements --- Source/CTest/cmCTestBuildHandler.cxx | 5 ++--- Source/cmCMakePathCommand.cxx | 5 +++-- Source/cmCPluginAPI.cxx | 2 +- Source/cmDepends.cxx | 3 +-- Source/cmGlobalGenerator.cxx | 2 +- Source/cmGlobalNMakeMakefileGenerator.cxx | 4 +--- Source/cmLocalGenerator.cxx | 2 +- Source/cmMakefile.cxx | 6 +++--- Source/cmVisualStudio10TargetGenerator.cxx | 2 +- 9 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 103dc1ed851..03caa6372ab 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -3,7 +3,6 @@ #include "cmCTestBuildHandler.h" #include -#include #include #include @@ -657,14 +656,14 @@ bool cmCTestBuildHandler::IsLaunchedErrorFile(const char* fname) { // error-{hash}.xml return (cmHasLiteralPrefix(fname, "error-") && - strcmp(fname + strlen(fname) - 4, ".xml") == 0); + cmHasLiteralSuffix(fname, ".xml")); } bool cmCTestBuildHandler::IsLaunchedWarningFile(const char* fname) { // warning-{hash}.xml return (cmHasLiteralPrefix(fname, "warning-") && - strcmp(fname + strlen(fname) - 4, ".xml") == 0); + cmHasLiteralSuffix(fname, ".xml")); } //###################################################################### diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx index 962fdcc9bba..9a5fa7bfc3e 100644 --- a/Source/cmCMakePathCommand.cxx +++ b/Source/cmCMakePathCommand.cxx @@ -18,6 +18,7 @@ #include "cmCMakePath.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSubcommandTable.h" @@ -149,8 +150,8 @@ class NormalizeParser : public CMakePathArgumentParser bool getInputPath(const std::string& arg, cmExecutionStatus& status, std::string& path) { - const auto* def = status.GetMakefile().GetDefinition(arg); - if (def == nullptr) { + cmProp def = status.GetMakefile().GetDefinition(arg); + if (!def) { status.SetError("undefined variable for input path."); return false; } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 438a0779ab0..ace73825ab9 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -734,7 +734,7 @@ void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir, } sf->SourceName = name; std::string fname = sf->SourceName; - if (ext && strlen(ext)) { + if (cmNonempty(ext)) { fname += "."; fname += ext; } diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 566c3bf78f5..46c7e3e773a 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -229,11 +229,10 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends, void cmDepends::SetIncludePathFromLanguage(const std::string& lang) { // Look for the new per "TARGET_" variant first: - cmProp includePath = nullptr; std::string includePathVar = cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH"); cmMakefile* mf = this->LocalGenerator->GetMakefile(); - includePath = mf->GetDefinition(includePathVar); + cmProp includePath = mf->GetDefinition(includePathVar); if (includePath) { cmExpandList(*includePath, this->IncludePath); } else { diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 55fba7978f8..13579746d19 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2260,7 +2260,7 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, // Check whether the genex expansion of the property agrees in all // configurations. - if (trueCount && falseCount) { + if (trueCount > 0 && falseCount > 0) { std::ostringstream e; e << "The EXCLUDE_FROM_ALL property of target \"" << target->GetName() << "\" varies by configuration. This is not supported by the \"" diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 313f39b5e8c..f08b1da36aa 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -43,9 +43,7 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) return false; } if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { - std::vector command; - command.emplace_back(*nmakeCommand); - command.emplace_back("-?"); + std::vector command{ *nmakeCommand, "-?" }; std::string out; std::string err; if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index db7357a3aae..fbbdfcaa5e1 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2786,7 +2786,7 @@ void cmLocalGenerator::IncludeFileInUnitySources( cmGeneratedFileStream& unity_file, std::string const& sf_full_path, cmProp beforeInclude, cmProp afterInclude, cmProp uniqueIdName) const { - if (uniqueIdName && !uniqueIdName->empty()) { + if (cmNonempty(uniqueIdName)) { std::string pathToHash; auto PathEqOrSubDir = [](std::string const& a, std::string const& b) { return (cmSystemTools::ComparePath(a, b) || diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5a37bb9be32..29f9e36b01e 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2479,7 +2479,7 @@ const std::string& cmMakefile::GetRequiredDefinition( const std::string& name) const { static std::string const empty; - const std::string* def = this->GetDefinition(name); + cmProp def = this->GetDefinition(name); if (!def) { cmSystemTools::Error("Error required internal CMake variable not " "set, cmake may not be built correctly.\n" @@ -2553,7 +2553,7 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const { static std::string const empty; - const std::string* def = this->GetDefinition(name); + cmProp def = this->GetDefinition(name); if (!def) { return empty; } @@ -3067,7 +3067,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( if (filename && variable == lineVar) { varresult = std::to_string(line); } else { - const std::string* def = this->GetDefinition(variable); + cmProp def = this->GetDefinition(variable); if (def) { varresult = *def; } else if (!this->SuppressSideEffects) { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ba0cf9ca4de..12a3679858f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -498,7 +498,7 @@ void cmVisualStudio10TargetGenerator::Generate() cmProp targetFramework = this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK"); if (targetFramework) { - if (std::strchr(targetFramework->c_str(), ';') != nullptr) { + if (targetFramework->find(';') != std::string::npos) { e1.Element("TargetFrameworks", *targetFramework); } else { e1.Element("TargetFramework", *targetFramework); From b1729200c318dab23daac8643da5f9fdc673a5ef Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sun, 2 May 2021 14:20:56 +0200 Subject: [PATCH 0409/1519] find_*: refactor cache variable handling --- Source/cmFindBase.cxx | 62 ++++++++++++++++++++++++++++----- Source/cmFindBase.h | 10 +++++- Source/cmFindFileCommand.cxx | 5 ++- Source/cmFindLibraryCommand.cxx | 47 +++++++------------------ Source/cmFindPathCommand.cxx | 49 +++++++++----------------- Source/cmFindPathCommand.h | 1 + Source/cmFindProgramCommand.cxx | 45 +++++++----------------- 7 files changed, 109 insertions(+), 110 deletions(-) diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index bf52d7513af..409e2e0cc1f 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -10,6 +10,7 @@ #include #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmProperty.h" #include "cmRange.h" #include "cmSearchPath.h" @@ -20,8 +21,9 @@ class cmExecutionStatus; -cmFindBase::cmFindBase(cmExecutionStatus& status) +cmFindBase::cmFindBase(std::string findCommandName, cmExecutionStatus& status) : cmFindCommon(status) + , FindCommandName(std::move(findCommandName)) { } @@ -299,27 +301,69 @@ bool cmFindBase::CheckForVariableInCache() cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName); bool found = !cmIsNOTFOUND(*cacheValue); bool cached = cacheEntry != nullptr; + auto cacheType = cached ? state->GetCacheEntryType(this->VariableName) + : cmStateEnums::UNINITIALIZED; + + if (cached && cacheType != cmStateEnums::UNINITIALIZED) { + this->VariableType = cacheType; + if (const auto* hs = + state->GetCacheEntryProperty(this->VariableName, "HELPSTRING")) { + this->VariableDocumentation = *hs; + } + } + if (found) { // If the user specifies the entry on the command line without a // type we should add the type and docstring but keep the // original value. Tell the subclass implementations to do // this. - if (cached && - state->GetCacheEntryType(this->VariableName) == - cmStateEnums::UNINITIALIZED) { + if (cached && cacheType == cmStateEnums::UNINITIALIZED) { this->AlreadyInCacheWithoutMetaInfo = true; } return true; } - if (cached) { - cmProp hs = - state->GetCacheEntryProperty(this->VariableName, "HELPSTRING"); - this->VariableDocumentation = hs ? *hs : "(none)"; - } } return false; } +void cmFindBase::NormalizeFindResult() +{ + // If the user specifies the entry on the command line without a + // type we should add the type and docstring but keep the original + // value. + if (this->AlreadyInCacheWithoutMetaInfo) { + this->Makefile->AddCacheDefinition(this->VariableName, "", + this->VariableDocumentation.c_str(), + this->VariableType); + } +} + +void cmFindBase::StoreFindResult(const std::string& value) +{ + if (!value.empty()) { + this->Makefile->AddCacheDefinition(this->VariableName, value, + this->VariableDocumentation.c_str(), + this->VariableType); + return; + } + + this->Makefile->AddCacheDefinition( + this->VariableName, cmStrCat(this->VariableName, "-NOTFOUND"), + this->VariableDocumentation.c_str(), this->VariableType); + + if (this->Required) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Could not find ", this->VariableName, " using the following ", + (this->FindCommandName == "find_file" || + this->FindCommandName == "find_path" + ? "files" + : "names"), + ": ", cmJoin(this->Names, ", "))); + cmSystemTools::SetFatalErrorOccured(); + } +} + cmFindBaseDebugState::cmFindBaseDebugState(std::string commandName, cmFindBase const* findBase) : FindCommand(findBase) diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index 57a40be9b65..c2a9288aad6 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -9,6 +9,7 @@ #include #include "cmFindCommon.h" +#include "cmStateTypes.h" class cmExecutionStatus; @@ -21,7 +22,7 @@ class cmExecutionStatus; class cmFindBase : public cmFindCommon { public: - cmFindBase(cmExecutionStatus& status); + cmFindBase(std::string findCommandName, cmExecutionStatus& status); virtual ~cmFindBase() = default; /** @@ -39,8 +40,15 @@ class cmFindBase : public cmFindCommon // if it has documentation in the cache bool CheckForVariableInCache(); + void NormalizeFindResult(); + void StoreFindResult(const std::string& value); + + // actual find command name + std::string FindCommandName; + // use by command during find std::string VariableDocumentation; + cmStateEnums::CacheEntryType VariableType = cmStateEnums::UNINITIALIZED; std::string VariableName; std::vector Names; bool NamesPerDir = false; diff --git a/Source/cmFindFileCommand.cxx b/Source/cmFindFileCommand.cxx index 29a2bc49e97..a88c1b10c19 100644 --- a/Source/cmFindFileCommand.cxx +++ b/Source/cmFindFileCommand.cxx @@ -2,12 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindFileCommand.h" +#include "cmStateTypes.h" + class cmExecutionStatus; cmFindFileCommand::cmFindFileCommand(cmExecutionStatus& status) - : cmFindPathCommand(status) + : cmFindPathCommand("find_file", status) { this->IncludeFileInPath = true; + this->VariableType = cmStateEnums::FILEPATH; } bool cmFindFile(std::vector const& args, diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index d85ba8fd9f6..b1f4275951a 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -12,7 +12,6 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmMessageType.h" #include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" @@ -22,30 +21,26 @@ class cmExecutionStatus; cmFindLibraryCommand::cmFindLibraryCommand(cmExecutionStatus& status) - : cmFindBase(status) + : cmFindBase("find_library", status) { this->EnvironmentPath = "LIB"; this->NamesPerDirAllowed = true; + this->VariableDocumentation = "Path to a library."; + this->VariableType = cmStateEnums::FILEPATH; } // cmFindLibraryCommand bool cmFindLibraryCommand::InitialPass(std::vector const& argsIn) { this->DebugMode = this->ComputeIfDebugModeWanted(); - this->VariableDocumentation = "Path to a library."; this->CMakePathName = "LIBRARY"; + if (!this->ParseArguments(argsIn)) { return false; } + if (this->AlreadyInCache) { - // If the user specifies the entry on the command line without a - // type we should add the type and docstring but keep the original - // value. - if (this->AlreadyInCacheWithoutMetaInfo) { - this->Makefile->AddCacheDefinition(this->VariableName, "", - this->VariableDocumentation.c_str(), - cmStateEnums::FILEPATH); - } + this->NormalizeFindResult(); return true; } @@ -75,24 +70,7 @@ bool cmFindLibraryCommand::InitialPass(std::vector const& argsIn) } std::string const library = this->FindLibrary(); - if (!library.empty()) { - // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, library, - this->VariableDocumentation.c_str(), - cmStateEnums::FILEPATH); - return true; - } - std::string notfound = this->VariableName + "-NOTFOUND"; - this->Makefile->AddCacheDefinition(this->VariableName, notfound, - this->VariableDocumentation.c_str(), - cmStateEnums::FILEPATH); - if (this->Required) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "Could not find " + this->VariableName + - " using the following names: " + cmJoin(this->Names, ", ")); - cmSystemTools::SetFatalErrorOccured(); - } + this->StoreFindResult(library); return true; } @@ -208,7 +186,8 @@ std::string cmFindLibraryCommand::FindLibrary() struct cmFindLibraryHelper { - cmFindLibraryHelper(cmMakefile* mf, cmFindBase const* findBase); + cmFindLibraryHelper(std::string debugName, cmMakefile* mf, + cmFindBase const* findBase); // Context information. cmMakefile* Makefile; @@ -280,11 +259,11 @@ struct cmFindLibraryHelper }; }; -cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf, +cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, cmFindBase const* base) : Makefile(mf) , DebugMode(base->DebugModeEnabled()) - , DebugSearches("find_library", base) + , DebugSearches(std::move(debugName), base) { this->GG = this->Makefile->GetGlobalGenerator(); @@ -485,7 +464,7 @@ std::string cmFindLibraryCommand::FindNormalLibrary() std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir() { // Search for all names in each directory. - cmFindLibraryHelper helper(this->Makefile, this); + cmFindLibraryHelper helper(this->FindCommandName, this->Makefile, this); for (std::string const& n : this->Names) { helper.AddName(n); } @@ -502,7 +481,7 @@ std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir() std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName() { // Search the entire path for each name. - cmFindLibraryHelper helper(this->Makefile, this); + cmFindLibraryHelper helper(this->FindCommandName, this->Makefile, this); for (std::string const& n : this->Names) { // Switch to searching for this name. helper.SetName(n); diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 3fb082603ea..126cc2f2138 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -2,70 +2,53 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindPathCommand.h" +#include + #include "cmsys/Glob.hxx" -#include "cmMakefile.h" -#include "cmMessageType.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; -cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status) - : cmFindBase(status) +cmFindPathCommand::cmFindPathCommand(std::string findCommandName, + cmExecutionStatus& status) + : cmFindBase(std::move(findCommandName), status) { this->EnvironmentPath = "INCLUDE"; this->IncludeFileInPath = false; + this->VariableDocumentation = "Path to a file."; + this->VariableType = cmStateEnums::PATH; +} +cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status) + : cmFindPathCommand("find_path", status) +{ } // cmFindPathCommand bool cmFindPathCommand::InitialPass(std::vector const& argsIn) { this->DebugMode = this->ComputeIfDebugModeWanted(); - this->VariableDocumentation = "Path to a file."; this->CMakePathName = "INCLUDE"; + if (!this->ParseArguments(argsIn)) { return false; } + if (this->AlreadyInCache) { - // If the user specifies the entry on the command line without a - // type we should add the type and docstring but keep the original - // value. - if (this->AlreadyInCacheWithoutMetaInfo) { - this->Makefile->AddCacheDefinition( - this->VariableName, "", this->VariableDocumentation.c_str(), - (this->IncludeFileInPath ? cmStateEnums::FILEPATH - : cmStateEnums::PATH)); - } + this->NormalizeFindResult(); return true; } std::string result = this->FindHeader(); - if (!result.empty()) { - this->Makefile->AddCacheDefinition( - this->VariableName, result, this->VariableDocumentation.c_str(), - (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); - return true; - } - this->Makefile->AddCacheDefinition( - this->VariableName, this->VariableName + "-NOTFOUND", - this->VariableDocumentation.c_str(), - (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); - if (this->Required) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "Could not find " + this->VariableName + - " using the following files: " + cmJoin(this->Names, ", ")); - cmSystemTools::SetFatalErrorOccured(); - } + this->StoreFindResult(result); return true; } std::string cmFindPathCommand::FindHeader() { - std::string debug_name = this->IncludeFileInPath ? "find_file" : "find_path"; - cmFindBaseDebugState debug(debug_name, this); + cmFindBaseDebugState debug(this->FindCommandName, this); std::string header; if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) { header = this->FindFrameworkHeader(debug); diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h index 6101ea1c003..c7281f1f83a 100644 --- a/Source/cmFindPathCommand.h +++ b/Source/cmFindPathCommand.h @@ -22,6 +22,7 @@ class cmFindPathCommand : public cmFindBase { public: cmFindPathCommand(cmExecutionStatus& status); + cmFindPathCommand(std::string findCommandName, cmExecutionStatus& status); bool InitialPass(std::vector const& args); diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index c22462e84a3..76fc4a42a38 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -4,6 +4,7 @@ #include #include +#include #include "cmMakefile.h" #include "cmMessageType.h" @@ -20,8 +21,9 @@ class cmExecutionStatus; struct cmFindProgramHelper { - cmFindProgramHelper(cmMakefile* makefile, cmFindBase const* base) - : DebugSearches("find_program", base) + cmFindProgramHelper(std::string debugName, cmMakefile* makefile, + cmFindBase const* base) + : DebugSearches(std::move(debugName), base) , Makefile(makefile) , PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109)) { @@ -145,52 +147,31 @@ struct cmFindProgramHelper }; cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status) - : cmFindBase(status) + : cmFindBase("find_program", status) { this->NamesPerDirAllowed = true; + this->VariableDocumentation = "Path to a program."; + this->VariableType = cmStateEnums::FILEPATH; } // cmFindProgramCommand bool cmFindProgramCommand::InitialPass(std::vector const& argsIn) { this->DebugMode = this->ComputeIfDebugModeWanted(); - this->VariableDocumentation = "Path to a program."; this->CMakePathName = "PROGRAM"; + // call cmFindBase::ParseArguments if (!this->ParseArguments(argsIn)) { return false; } + if (this->AlreadyInCache) { - // If the user specifies the entry on the command line without a - // type we should add the type and docstring but keep the original - // value. - if (this->AlreadyInCacheWithoutMetaInfo) { - this->Makefile->AddCacheDefinition(this->VariableName, "", - this->VariableDocumentation.c_str(), - cmStateEnums::FILEPATH); - } + this->NormalizeFindResult(); return true; } std::string const result = this->FindProgram(); - if (!result.empty()) { - // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, result, - this->VariableDocumentation.c_str(), - cmStateEnums::FILEPATH); - - return true; - } - this->Makefile->AddCacheDefinition( - this->VariableName, this->VariableName + "-NOTFOUND", - this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); - if (this->Required) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "Could not find " + this->VariableName + - " using the following names: " + cmJoin(this->Names, ", ")); - cmSystemTools::SetFatalErrorOccured(); - } + this->StoreFindResult(result); return true; } @@ -222,7 +203,7 @@ std::string cmFindProgramCommand::FindNormalProgram() std::string cmFindProgramCommand::FindNormalProgramNamesPerDir() { // Search for all names in each directory. - cmFindProgramHelper helper(this->Makefile, this); + cmFindProgramHelper helper(this->FindCommandName, this->Makefile, this); for (std::string const& n : this->Names) { helper.AddName(n); } @@ -245,7 +226,7 @@ std::string cmFindProgramCommand::FindNormalProgramNamesPerDir() std::string cmFindProgramCommand::FindNormalProgramDirsPerName() { // Search the entire path for each name. - cmFindProgramHelper helper(this->Makefile, this); + cmFindProgramHelper helper(this->FindCommandName, this->Makefile, this); for (std::string const& n : this->Names) { // Switch to searching for this name. helper.SetName(n); From f5fa6d53b07d5c6224de2a491856a36fe3516218 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Tue, 4 May 2021 13:57:47 +0200 Subject: [PATCH 0410/1519] class cmake: Store working directory at cmake launch --- Source/cmake.cxx | 3 ++- Source/cmake.h | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 61234971ba2..54409843159 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -157,7 +157,8 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, #endif cmake::cmake(Role role, cmState::Mode mode) - : FileTimeCache(cm::make_unique()) + : CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory()) + , FileTimeCache(cm::make_unique()) #ifndef CMAKE_BOOTSTRAP , VariableWatch(cm::make_unique()) #endif diff --git a/Source/cmake.h b/Source/cmake.h index 9b29098ff6d..e845662911d 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -193,6 +193,14 @@ class cmake std::string const& GetHomeOutputDirectory() const; //@} + /** + * Working directory at CMake launch + */ + std::string const& GetCMakeWorkingDirectory() const + { + return this->CMakeWorkingDirectory; + } + /** * Handle a command line invocation of cmake. */ @@ -628,6 +636,7 @@ class cmake void GenerateGraphViz(const std::string& fileName) const; private: + std::string CMakeWorkingDirectory; ProgressCallbackType ProgressCallback; WorkingMode CurrentWorkingMode = NORMAL_MODE; bool DebugOutput = false; From 4281cd15dba47a802889dfc891470239db91dd96 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 15:49:20 -0400 Subject: [PATCH 0411/1519] clang-tidy: fix `bugprone-redundant-branch-condition` --- Source/CPack/cpack.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 85c13ada76e..a7789390339 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -341,7 +341,7 @@ int main(int argc, char const* const* argv) cmMakefile* mf = &globalMF; cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Specified generator: " << gen << std::endl); - if (parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME")) { + if (!mf->GetDefinition("CPACK_PACKAGE_NAME")) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack project name not specified" << std::endl); parsed = 0; From 40c672aaeb0b794b882bf562372f2be78725c9f5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 13:23:59 -0400 Subject: [PATCH 0412/1519] clang-tidy: ignore `readability-function-cognitive-complexity` --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-tidy b/.clang-tidy index 5e513fbd1b1..dda86b079c5 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -19,6 +19,7 @@ modernize-*,\ performance-*,\ readability-*,\ -readability-convert-member-functions-to-static,\ +-readability-function-cognitive-complexity,\ -readability-function-size,\ -readability-identifier-naming,\ -readability-implicit-bool-conversion,\ From 1c7c155366f28a56a679379b903a6f035636f0cf Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 12 May 2021 00:01:11 -0400 Subject: [PATCH 0413/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4af9474c4a6..7ebc881a5d0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210511) +set(CMake_VERSION_PATCH 20210512) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 08db1341a60035b303a20eb3f23126a661323c27 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 3 May 2021 14:16:07 +0200 Subject: [PATCH 0414/1519] find_*: ensure consistent behavior for cache variables Fixes: #22121 --- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0125.rst | 25 ++++++++ .../dev/find_item-consistent-behavior.rst | 6 ++ Source/cmFindBase.cxx | 58 ++++++++++++++++--- Source/cmMakefile.cxx | 2 + Source/cmPolicies.h | 6 +- .../CMP0125/CMP0125-find_file-Common.cmake | 51 ++++++++++++++++ .../CMP0125/CMP0125-find_file-NEW-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_file-NEW.cmake | 4 ++ .../CMP0125/CMP0125-find_file-OLD-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_file-OLD.cmake | 4 ++ .../CMP0125/CMP0125-find_library-Common.cmake | 52 +++++++++++++++++ .../CMP0125-find_library-NEW-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_library-NEW.cmake | 6 ++ .../CMP0125-find_library-OLD-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_library-OLD.cmake | 6 ++ .../CMP0125/CMP0125-find_path-Common.cmake | 51 ++++++++++++++++ .../CMP0125/CMP0125-find_path-NEW-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_path-NEW.cmake | 4 ++ .../CMP0125/CMP0125-find_path-OLD-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_path-OLD.cmake | 4 ++ .../CMP0125/CMP0125-find_program-Common.cmake | 52 +++++++++++++++++ .../CMP0125-find_program-NEW-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_program-NEW.cmake | 4 ++ .../CMP0125-find_program-OLD-stderr.txt | 14 +++++ .../CMP0125/CMP0125-find_program-OLD.cmake | 4 ++ Tests/RunCMake/CMP0125/CMakeLists.txt | 3 + Tests/RunCMake/CMP0125/RunCMakeTest.cmake | 36 ++++++++++++ Tests/RunCMake/CMakeLists.txt | 4 ++ 29 files changed, 485 insertions(+), 10 deletions(-) create mode 100644 Help/policy/CMP0125.rst create mode 100644 Help/release/dev/find_item-consistent-behavior.rst create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake create mode 100644 Tests/RunCMake/CMP0125/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0125/RunCMakeTest.cmake diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index a4804733269..62ccb015003 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.21 .. toctree:: :maxdepth: 1 + CMP0125: find_(path|file|library|program) have consistent behavior for cache variables. CMP0124: foreach() loop variables are only available in the loop scope. CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. CMP0122: UseSWIG use standard library name conventions for csharp language. diff --git a/Help/policy/CMP0125.rst b/Help/policy/CMP0125.rst new file mode 100644 index 00000000000..19571dc2517 --- /dev/null +++ b/Help/policy/CMP0125.rst @@ -0,0 +1,25 @@ +CMP0125 +------- + +.. versionadded:: 3.21 + +The :command:`find_file`, :command:`find_path`, :command:`find_library` and +:command:`find_program` commands handle cache variables in the same way +regardless of whether they are defined on the command line, with or without a +type, or using the :command:`set` command. + +Starting with CMake 3.21, the :command:`find_file`, :command:`find_path`, +:command:`find_library`, and :command:`find_program` commands ensure that the +cache variables will be used in the same way regardless how they were defined +and the result will be always successful if the searched artifact exists. + +The ``OLD`` behavior for this policy is to have the find commands' behaviors +differ depending on how the cache variable is defined. The ``NEW`` behavior for +this policy is to have consistent behavior. + +This policy was introduced in CMake version 3.21. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn when the policy +is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/find_item-consistent-behavior.rst b/Help/release/dev/find_item-consistent-behavior.rst new file mode 100644 index 00000000000..43905e72978 --- /dev/null +++ b/Help/release/dev/find_item-consistent-behavior.rst @@ -0,0 +1,6 @@ +find_item-consistent-behavior +----------------------------- + +* The :command:`find_file`, :command:`find_path`, :command:`find_program`, + and :command:`find_library` commands handle cache variables in the same way + regardless how they are defined. See policy :policy:`CMP0125` for details. diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 409e2e0cc1f..6296d06e243 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -9,8 +9,10 @@ #include +#include "cmCMakePath.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmProperty.h" #include "cmRange.h" #include "cmSearchPath.h" @@ -18,6 +20,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmake.h" class cmExecutionStatus; @@ -328,28 +331,65 @@ bool cmFindBase::CheckForVariableInCache() void cmFindBase::NormalizeFindResult() { - // If the user specifies the entry on the command line without a - // type we should add the type and docstring but keep the original - // value. - if (this->AlreadyInCacheWithoutMetaInfo) { - this->Makefile->AddCacheDefinition(this->VariableName, "", - this->VariableDocumentation.c_str(), - this->VariableType); + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) == + cmPolicies::NEW) { + // ensure the path returned by find_* command is absolute + const auto* existingValue = + this->Makefile->GetDefinition(this->VariableName); + std::string value; + if (!existingValue->empty()) { + value = + cmCMakePath(*existingValue, cmCMakePath::auto_format) + .Absolute(cmCMakePath( + this->Makefile->GetCMakeInstance()->GetCMakeWorkingDirectory())) + .Normal() + .GenericString(); + // value = cmSystemTools::CollapseFullPath(*existingValue); + if (!cmSystemTools::FileExists(value, false)) { + value = *existingValue; + } + } + + // If the user specifies the entry on the command line without a + // type we should add the type and docstring but keep the original + // value. + if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) { + this->Makefile->GetCMakeInstance()->AddCacheEntry( + this->VariableName, value.c_str(), this->VariableDocumentation.c_str(), + this->VariableType); + // if there was a definition then remove it + // This is required to ensure same behavior as + // cmMakefile::AddCacheDefinition. + // See #22038 for problems raised by this behavior. + this->Makefile->RemoveDefinition(this->VariableName); + } + } else { + // If the user specifies the entry on the command line without a + // type we should add the type and docstring but keep the original + // value. + if (this->AlreadyInCacheWithoutMetaInfo) { + this->Makefile->AddCacheDefinition(this->VariableName, "", + this->VariableDocumentation.c_str(), + this->VariableType); + } } } void cmFindBase::StoreFindResult(const std::string& value) { + bool force = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) == cmPolicies::NEW; + if (!value.empty()) { this->Makefile->AddCacheDefinition(this->VariableName, value, this->VariableDocumentation.c_str(), - this->VariableType); + this->VariableType, force); return; } this->Makefile->AddCacheDefinition( this->VariableName, cmStrCat(this->VariableName, "-NOTFOUND"), - this->VariableDocumentation.c_str(), this->VariableType); + this->VariableDocumentation.c_str(), this->VariableType, force); if (this->Required) { this->Makefile->IssueMessage( diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5a37bb9be32..f7e81bc5f25 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1963,6 +1963,8 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, } this->GetCMakeInstance()->AddCacheEntry(name, value, doc, type); // if there was a definition then remove it + // The method cmFindBase::NormalizeFindResult also apply same workflow. + // See #22038 for problems raised by this behavior. this->StateSnapshot.RemoveDefinition(name); } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 0ff12d57b17..3ebb17d6262 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -372,7 +372,11 @@ class cmMakefile; 3, 21, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0124, \ "foreach() loop variables are only available in the loop scope.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0125, \ + "find_(path|file|library|program) have consistent behavior for " \ + "cache variables.", \ + 3, 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake new file mode 100644 index 00000000000..a85978bf653 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-Common.cmake @@ -0,0 +1,51 @@ + +find_file(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_file(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_file(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "") +find_file(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH=${RELATIVE_PATH}") +message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}") + +message("ABSOLUTE_PATH=${ABSOLUTE_PATH}") +message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}") + +message("NOTFOUND_PATH=${NOTFOUND_PATH}") +message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}") + +message("FILE_NAME=${FILE_NAME}") +message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}") + + +set(RELATIVE_PATH_AND_LOCAL relative_local) +set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local) +set(ABSOLUTE_PATH_AND_LOCAL /absolute_local) +set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local) +set(NOTFOUND_AND_LOCAL "${FILE_NAME}") +set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}") + +find_file(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_file(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_file(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_file(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}") +message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}") + +message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}") +message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}") + +message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}") +message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}") diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt new file mode 100644 index 00000000000..10f95bcbddd --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=/.+/CMP0125/file\.txt +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt +FILE_NAME=/.+/CMP0125/CMP0125-find_file-NEW-build/file2\.txt +FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_file-NEW-build/file2\.txt +RELATIVE_PATH_AND_LOCAL=relative_local +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute_local +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/file.txt +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file.txt diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake new file mode 100644 index 00000000000..4f048349934 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-NEW.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0125 NEW) + +include(CMP0125-find_file-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt new file mode 100644 index 00000000000..5b25f9227d6 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=/.+/CMP0125/CMP0125-find_file-OLD-build/relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=NOTFOUND +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt +FILE_NAME=/.+/CMP0125/CMP0125-find_file-OLD-build/file2\.txt +FILE_NAME_WITH_TYPE=file2\.txt +RELATIVE_PATH_AND_LOCAL=/.+/CMP0125/CMP0125-find_file-OLD-build/relative +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=NOTFOUND +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file\.txt diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake new file mode 100644 index 00000000000..21884b5a8b2 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_file-OLD.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0125 OLD) + +include(CMP0125-find_file-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake new file mode 100644 index 00000000000..d2bc0062a05 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-Common.cmake @@ -0,0 +1,52 @@ + +find_library(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_library(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_library(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "") +file(CHMOD "${CMAKE_BINARY_DIR}/${FILE_NAME}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) +find_library(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH=${RELATIVE_PATH}") +message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}") + +message("ABSOLUTE_PATH=${ABSOLUTE_PATH}") +message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}") + +message("NOTFOUND_PATH=${NOTFOUND_PATH}") +message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}") + +message("FILE_NAME=${FILE_NAME}") +message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}") + + +set(RELATIVE_PATH_AND_LOCAL relative_local) +set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local) +set(ABSOLUTE_PATH_AND_LOCAL /absolute_local) +set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local) +set(NOTFOUND_AND_LOCAL "${FILE_NAME}") +set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}") + +find_library(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_library(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_library(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_library(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}") +message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}") + +message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}") +message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}") + +message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}") +message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}") diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt new file mode 100644 index 00000000000..d180833e7f7 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=/.+/CMP0125/libfile\.(so|dylib) +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/libfile\.(so|dylib) +FILE_NAME=/.+/CMP0125/CMP0125-find_library-NEW-build/libfile2\.(so|dylib) +FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_library-NEW-build/libfile2\.(so|dylib) +RELATIVE_PATH_AND_LOCAL=relative_local +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute_local +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/libfile.(so|dylib) +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/libfile.(so|dylib) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake new file mode 100644 index 00000000000..31f5441cd44 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-NEW.cmake @@ -0,0 +1,6 @@ + +cmake_policy(SET CMP0125 NEW) + +enable_language(C) + +include(CMP0125-find_library-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt new file mode 100644 index 00000000000..cd3af5669f8 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=/.+/CMP0125/CMP0125-find_library-OLD-build/relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=NOTFOUND +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/libfile\.(so|dylib) +FILE_NAME=/.+/CMP0125/CMP0125-find_library-OLD-build/libfile2\.(so|dylib) +FILE_NAME_WITH_TYPE=libfile2\.(so|dylib) +RELATIVE_PATH_AND_LOCAL=relative_local +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute_local +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/libfile\.(so|dylib) +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/libfile\.(so|dylib) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake new file mode 100644 index 00000000000..1dc4a95f5e8 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_library-OLD.cmake @@ -0,0 +1,6 @@ + +cmake_policy(SET CMP0125 OLD) + +enable_language(C) + +include(CMP0125-find_library-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake new file mode 100644 index 00000000000..37680c2a3e9 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-Common.cmake @@ -0,0 +1,51 @@ + +find_path(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_path(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_path(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "") +find_path(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH=${RELATIVE_PATH}") +message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}") + +message("ABSOLUTE_PATH=${ABSOLUTE_PATH}") +message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}") + +message("NOTFOUND_PATH=${NOTFOUND_PATH}") +message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}") + +message("FILE_NAME=${FILE_NAME}") +message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}") + + +set(RELATIVE_PATH_AND_LOCAL relative_local) +set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local) +set(ABSOLUTE_PATH_AND_LOCAL /absolute_local) +set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local) +set(NOTFOUND_AND_LOCAL "${FILE_NAME}") +set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}") + +find_path(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_path(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_path(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_path(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}") +message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}") + +message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}") +message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}") + +message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}") +message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}") diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt new file mode 100644 index 00000000000..c3f02083d5e --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=/.+/CMP0125 +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125 +FILE_NAME=/.+/CMP0125/CMP0125-find_path-NEW-build/file2\.txt +FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_path-NEW-build/file2\.txt +RELATIVE_PATH_AND_LOCAL=relative_local +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute_local +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125 +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125 diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake new file mode 100644 index 00000000000..d6a854404b0 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-NEW.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0125 NEW) + +include(CMP0125-find_path-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt new file mode 100644 index 00000000000..b84c8695ab2 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=/.+/CMP0125/CMP0125-find_path-OLD-build/relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=NOTFOUND +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125 +FILE_NAME=/.+/CMP0125/CMP0125-find_path-OLD-build/file2\.txt +FILE_NAME_WITH_TYPE=file2\.txt +RELATIVE_PATH_AND_LOCAL=/.+/CMP0125/CMP0125-find_path-OLD-build/relative +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=NOTFOUND +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125 diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake new file mode 100644 index 00000000000..2e98ded0132 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_path-OLD.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0125 OLD) + +include(CMP0125-find_path-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake new file mode 100644 index 00000000000..fee4c348b78 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-Common.cmake @@ -0,0 +1,52 @@ + +find_program(RELATIVE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(RELATIVE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_program(ABSOLUTE_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(ABSOLUTE_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_program(NOTFOUND_PATH NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(NOTFOUND_PATH_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +file(WRITE "${CMAKE_BINARY_DIR}/${FILE_NAME}" "") +file(CHMOD "${CMAKE_BINARY_DIR}/${FILE_NAME}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) +find_program(FILE_NAME NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(FILE_NAME_WITH_TYPE NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH=${RELATIVE_PATH}") +message("RELATIVE_PATH_WITH_TYPE=${RELATIVE_PATH_WITH_TYPE}") + +message("ABSOLUTE_PATH=${ABSOLUTE_PATH}") +message("ABSOLUTE_PATH_WITH_TYPE=${ABSOLUTE_PATH_WITH_TYPE}") + +message("NOTFOUND_PATH=${NOTFOUND_PATH}") +message("NOTFOUND_PATH_WITH_TYPE=${NOTFOUND_PATH_WITH_TYPE}") + +message("FILE_NAME=${FILE_NAME}") +message("FILE_NAME_WITH_TYPE=${FILE_NAME_WITH_TYPE}") + + +set(RELATIVE_PATH_AND_LOCAL relative_local) +set(RELATIVE_PATH_WITH_TYPE_AND_LOCAL relative_local) +set(ABSOLUTE_PATH_AND_LOCAL /absolute_local) +set(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL /absolute_local) +set(NOTFOUND_AND_LOCAL "${FILE_NAME}") +set(NOTFOUND_WITH_TYPE_AND_LOCAL "${FILE_NAME}") + +find_program(RELATIVE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(RELATIVE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_program(ABSOLUTE_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +find_program(NOTFOUND_PATH_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) +find_program(NOTFOUND_PATH_WITH_TYPE_AND_LOCAL NAMES ${SEARCH_NAME} PATHS ${SEARCH_PATH}) + +message("RELATIVE_PATH_AND_LOCAL=${RELATIVE_PATH_AND_LOCAL}") +message("RELATIVE_PATH_WITH_TYPE_AND_LOCAL=${RELATIVE_PATH_WITH_TYPE_AND_LOCAL}") + +message("ABSOLUTE_PATH_AND_LOCAL=${ABSOLUTE_PATH_AND_LOCAL}") +message("ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=${ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL}") + +message("NOTFOUND_PATH_AND_LOCAL=${NOTFOUND_PATH_AND_LOCAL}") +message("NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=${NOTFOUND_PATH_WITH_TYPE_AND_LOCAL}") diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt new file mode 100644 index 00000000000..62da5bf0b25 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=/.+/CMP0125/file\.txt +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt +FILE_NAME=/.+/CMP0125/CMP0125-find_program-NEW-build/file2\.txt +FILE_NAME_WITH_TYPE=/.+/CMP0125/CMP0125-find_program-NEW-build/file2\.txt +RELATIVE_PATH_AND_LOCAL=relative_local +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute_local +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=/.+/CMP0125/file.txt +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file.txt diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake new file mode 100644 index 00000000000..c02f23b33c3 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-NEW.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0125 NEW) + +include(CMP0125-find_program-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt new file mode 100644 index 00000000000..a97fc07908c --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD-stderr.txt @@ -0,0 +1,14 @@ +RELATIVE_PATH=/.+/CMP0125/CMP0125-find_program-OLD-build/relative +RELATIVE_PATH_WITH_TYPE=relative +ABSOLUTE_PATH=/absolute +ABSOLUTE_PATH_WITH_TYPE=/absolute +NOTFOUND_PATH=NOTFOUND +NOTFOUND_PATH_WITH_TYPE=/.+/CMP0125/file\.txt +FILE_NAME=/.+/CMP0125/CMP0125-find_program-OLD-build/file2\.txt +FILE_NAME_WITH_TYPE=file2\.txt +RELATIVE_PATH_AND_LOCAL=/.+/CMP0125/CMP0125-find_program-OLD-build/relative +RELATIVE_PATH_WITH_TYPE_AND_LOCAL=relative_local +ABSOLUTE_PATH_AND_LOCAL=/absolute +ABSOLUTE_PATH_WITH_TYPE_AND_LOCAL=/absolute_local +NOTFOUND_PATH_AND_LOCAL=NOTFOUND +NOTFOUND_PATH_WITH_TYPE_AND_LOCAL=/.+/CMP0125/file.txt diff --git a/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake new file mode 100644 index 00000000000..6be85349690 --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMP0125-find_program-OLD.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0125 OLD) + +include(CMP0125-find_program-Common.cmake) diff --git a/Tests/RunCMake/CMP0125/CMakeLists.txt b/Tests/RunCMake/CMP0125/CMakeLists.txt new file mode 100644 index 00000000000..7cabeb68b2f --- /dev/null +++ b/Tests/RunCMake/CMP0125/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.20) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0125/RunCMakeTest.cmake b/Tests/RunCMake/CMP0125/RunCMakeTest.cmake new file mode 100644 index 00000000000..56d4c863532 --- /dev/null +++ b/Tests/RunCMake/CMP0125/RunCMakeTest.cmake @@ -0,0 +1,36 @@ +include(RunCMake) + +file(WRITE "${RunCMake_BINARY_DIR}/file.txt" "") +file(CHMOD "${RunCMake_BINARY_DIR}/file.txt" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) + +set(options -DRELATIVE_PATH=relative -DABSOLUTE_PATH=/absolute + -DRELATIVE_PATH_WITH_TYPE:PATH=relative -DABSOLUTE_PATH_WITH_TYPE:PATH=/absolute + -DNOTFOUND_PATH=NOTFOUND -DNOTFOUND_PATH_WITH_TYPE:PATH=NOTFOUND + -DFILE_NAME=file2.txt -DFILE_NAME_WITH_TYPE:PATH=file2.txt + -DSEARCH_NAME=file.txt "-DSEARCH_PATH=${RunCMake_BINARY_DIR}" + -DRELATIVE_PATH_AND_LOCAL=relative -DABSOLUTE_PATH_AND_LOCAL=/absolute + -DRELATIVE_PATH_WITH_TYPE_AND_LOCAL:PATH=relative -DABSOLUTE_PATH_WITH_TYPE_AND_LOCAL:PATH=/absolute + -DNOTFOUND_PATH_AND_LOCAL=NOTFOUND -DNOTFOUND_PATH_WITH_TYPE_AND_LOCAL:PATH=NOTFOUND + -DFILE_NAME=file2.txt -DFILE_NAME_WITH_TYPE:PATH=file2.txt + -DSEARCH_NAME=file.txt "-DSEARCH_PATH=${RunCMake_BINARY_DIR}") + +run_cmake_with_options(CMP0125-find_file-OLD ${options}) +run_cmake_with_options(CMP0125-find_file-NEW ${options}) +run_cmake_with_options(CMP0125-find_path-OLD ${options}) +run_cmake_with_options(CMP0125-find_path-NEW ${options}) +run_cmake_with_options(CMP0125-find_program-OLD ${options}) +run_cmake_with_options(CMP0125-find_program-NEW ${options}) + + +file(WRITE "${RunCMake_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}file${CMAKE_SHARED_LIBRARY_SUFFIX}" "") +file(CHMOD "${RunCMake_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}file${CMAKE_SHARED_LIBRARY_SUFFIX}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) + +set(options -DRELATIVE_PATH=relative -DABSOLUTE_PATH=/absolute + -DRELATIVE_PATH_WITH_TYPE:PATH=relative -DABSOLUTE_PATH_WITH_TYPE:PATH=/absolute + -DNOTFOUND_PATH=NOTFOUND -DNOTFOUND_PATH_WITH_TYPE:PATH=NOTFOUND + -DFILE_NAME=${CMAKE_SHARED_LIBRARY_PREFIX}file2${CMAKE_SHARED_LIBRARY_SUFFIX} + -DFILE_NAME_WITH_TYPE:PATH=${CMAKE_SHARED_LIBRARY_PREFIX}file2${CMAKE_SHARED_LIBRARY_SUFFIX} + -DSEARCH_NAME=file "-DSEARCH_PATH=${RunCMake_BINARY_DIR}") + +run_cmake_with_options(CMP0125-find_library-OLD ${options}) +run_cmake_with_options(CMP0125-find_library-NEW ${options}) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 9bc41316cec..afaeaef6410 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -136,6 +136,10 @@ endif() add_RunCMake_test(CMP0118) add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) add_RunCMake_test(CMP0121) +if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)") + add_RunCMake_test(CMP0125 -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} + -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}) +endif() # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode From a69e6dba924262f6e291406b0e9b3d5c1ff1ae86 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 10:43:59 -0400 Subject: [PATCH 0415/1519] gitlab-ci: update to Fedora 34 for upload jobs Also add 'cmake' tag to match the rest of our jobs. --- .gitlab/upload.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab/upload.yml b/.gitlab/upload.yml index 3253fd3de19..693388d9bf9 100644 --- a/.gitlab/upload.yml +++ b/.gitlab/upload.yml @@ -1,9 +1,10 @@ # Steps for uploading artifacts .rsync_upload_binary: - image: "fedora:32" + image: "fedora:34" stage: upload tags: + - cmake - docker - linux - build @@ -19,8 +20,9 @@ .rsync_upload_help: stage: upload - image: "fedora:33" + image: "fedora:34" tags: + - cmake - docker - linux - build From 82fc490f93034373ec822fc974be9e1dc4c080db Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 10:43:12 -0400 Subject: [PATCH 0416/1519] ci: update to Fedora 34 for Linux base images --- .gitlab/ci/docker/{fedora33 => fedora34}/Dockerfile | 4 ++-- .gitlab/ci/docker/{fedora33 => fedora34}/install_deps.sh | 8 +++++++- .gitlab/ci/docker/{fedora33 => fedora34}/install_ispc.sh | 0 .gitlab/ci/docker/{fedora33 => fedora34}/install_rvm.sh | 0 4 files changed, 9 insertions(+), 3 deletions(-) rename .gitlab/ci/docker/{fedora33 => fedora34}/Dockerfile (90%) rename .gitlab/ci/docker/{fedora33 => fedora34}/install_deps.sh (89%) rename .gitlab/ci/docker/{fedora33 => fedora34}/install_ispc.sh (100%) rename .gitlab/ci/docker/{fedora33 => fedora34}/install_rvm.sh (100%) diff --git a/.gitlab/ci/docker/fedora33/Dockerfile b/.gitlab/ci/docker/fedora34/Dockerfile similarity index 90% rename from .gitlab/ci/docker/fedora33/Dockerfile rename to .gitlab/ci/docker/fedora34/Dockerfile index 8ebcb9ee3f4..af2322d88d0 100644 --- a/.gitlab/ci/docker/fedora33/Dockerfile +++ b/.gitlab/ci/docker/fedora34/Dockerfile @@ -1,10 +1,10 @@ -FROM fedora:33 as rvm-build +FROM fedora:34 as rvm-build MAINTAINER Ben Boeckel COPY install_rvm.sh /root/install_rvm.sh RUN sh /root/install_rvm.sh -FROM fedora:33 +FROM fedora:34 MAINTAINER Ben Boeckel COPY install_deps.sh /root/install_deps.sh diff --git a/.gitlab/ci/docker/fedora33/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh similarity index 89% rename from .gitlab/ci/docker/fedora33/install_deps.sh rename to .gitlab/ci/docker/fedora34/install_deps.sh index cdfe35e55e8..6edb2aac555 100755 --- a/.gitlab/ci/docker/fedora33/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -67,7 +67,7 @@ dnf install --setopt=install_weak_deps=False -y \ protobuf-devel protobuf-c-devel protobuf-lite-devel \ pypy2 pypy2-devel \ pypy3 pypy3-devel \ - python2 python2-devel python2-numpy \ + python2 python2-devel \ python3 python3-devel python3-numpy \ python3-jsmin python3-jsonschema \ ruby rubygems ruby-devel \ @@ -80,3 +80,9 @@ dnf install --setopt=install_weak_deps=False -y \ xz-devel dnf clean all + +# Fedora no longer packages python2 numpy. +curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py +python2 get-pip.py +rm get-pip.py +pip2.7 install numpy diff --git a/.gitlab/ci/docker/fedora33/install_ispc.sh b/.gitlab/ci/docker/fedora34/install_ispc.sh similarity index 100% rename from .gitlab/ci/docker/fedora33/install_ispc.sh rename to .gitlab/ci/docker/fedora34/install_ispc.sh diff --git a/.gitlab/ci/docker/fedora33/install_rvm.sh b/.gitlab/ci/docker/fedora34/install_rvm.sh similarity index 100% rename from .gitlab/ci/docker/fedora33/install_rvm.sh rename to .gitlab/ci/docker/fedora34/install_rvm.sh From fa261d1b7de5bf1b5b805955654ca01d17826835 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 11:53:30 -0400 Subject: [PATCH 0417/1519] ci: add Qt 6 to Fedora base image --- .gitlab/ci/docker/fedora34/install_deps.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 6edb2aac555..4123d873ece 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -6,7 +6,8 @@ set -e dnf install --setopt=install_weak_deps=False -y \ ncurses-devel \ openssl-devel \ - qt5-qtbase-devel + qt5-qtbase-devel \ + qt6-qtbase-devel # Install development tools. dnf install --setopt=install_weak_deps=False -y \ @@ -19,7 +20,8 @@ dnf install --setopt=install_weak_deps=False -y \ dnf install --setopt=install_weak_deps=False -y \ python3-sphinx \ texinfo \ - qt5-qttools-devel + qt5-qttools-devel \ + qt6-qttools-devel # Tools needed for the test suite. dnf install --setopt=install_weak_deps=False -y \ From 4ad8bfcd9ba1bf34deb87b5ae67bc24dc3095435 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 7 May 2021 11:20:15 -0400 Subject: [PATCH 0418/1519] ci: add codespell to Fedora base image --- .gitlab/ci/docker/fedora34/install_deps.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 4123d873ece..091bd6483a4 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -23,6 +23,10 @@ dnf install --setopt=install_weak_deps=False -y \ qt5-qttools-devel \ qt6-qttools-devel +# Install lint tools. +dnf install --setopt=install_weak_deps=False -y \ + codespell + # Tools needed for the test suite. dnf install --setopt=install_weak_deps=False -y \ findutils \ From 6ff48b862c0f24f9ad9f89c8c3511f22a8a54e9d Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 7 May 2021 11:25:26 -0400 Subject: [PATCH 0419/1519] ci: add gRPC to Debian and Fedora base images --- .gitlab/ci/docker/debian10-aarch64/install_deps.sh | 3 ++- .gitlab/ci/docker/debian10/install_deps.sh | 3 ++- .gitlab/ci/docker/fedora34/install_deps.sh | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh index d84b3c87d05..fea502ec575 100755 --- a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh +++ b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh @@ -45,6 +45,7 @@ apt-get install -y \ libgif-dev \ libgl1-mesa-dev \ libglew-dev \ + libgrpc++-dev libgrpc-dev \ libgsl-dev \ libgtest-dev \ libgtk2.0-dev \ @@ -56,7 +57,7 @@ apt-get install -y \ libopenmpi-dev openmpi-bin \ libpng-dev \ libpq-dev postgresql-server-dev-11 \ - libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler \ + libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler protobuf-compiler-grpc \ libsdl-dev \ libsqlite3-dev \ libtiff-dev \ diff --git a/.gitlab/ci/docker/debian10/install_deps.sh b/.gitlab/ci/docker/debian10/install_deps.sh index e6c9ba09994..4bb03bc6bc7 100755 --- a/.gitlab/ci/docker/debian10/install_deps.sh +++ b/.gitlab/ci/docker/debian10/install_deps.sh @@ -45,6 +45,7 @@ apt-get install -y \ libgif-dev \ libgl1-mesa-dev \ libglew-dev \ + libgrpc++-dev libgrpc-dev \ libgsl-dev \ libgtest-dev \ libgtk2.0-dev \ @@ -56,7 +57,7 @@ apt-get install -y \ libopenmpi-dev openmpi-bin \ libpng-dev \ libpq-dev postgresql-server-dev-11 \ - libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler \ + libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler protobuf-compiler-grpc \ libsdl-dev \ libsqlite3-dev \ libtiff-dev \ diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 091bd6483a4..ece0666d51f 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -52,6 +52,7 @@ dnf install --setopt=install_weak_deps=False -y \ glew-devel \ gmock \ gnutls-devel \ + grpc-devel grpc-plugins \ gsl-devel \ gtest-devel \ gtk2-devel \ From 89478e643f42bfdf0ace9f83416536bea9f23fab Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 10:44:24 -0400 Subject: [PATCH 0420/1519] gitlab-ci: update to Fedora 34 base images --- .gitlab-ci.yml | 34 +++++++------- .gitlab/ci/configure_fedora33_tidy.cmake | 3 -- ....cmake => configure_fedora34_common.cmake} | 1 + ...ake => configure_fedora34_makefiles.cmake} | 0 ...a.cmake => configure_fedora34_ninja.cmake} | 2 +- ...e => configure_fedora34_ninja_multi.cmake} | 0 ....cmake => configure_fedora34_sphinx.cmake} | 0 ...> configure_fedora34_sphinx_package.cmake} | 0 .gitlab/ci/configure_fedora34_tidy.cmake | 3 ++ ...les.cmake => env_fedora34_makefiles.cmake} | 0 .gitlab/os-linux.yml | 44 +++++++++---------- 11 files changed, 44 insertions(+), 43 deletions(-) delete mode 100644 .gitlab/ci/configure_fedora33_tidy.cmake rename .gitlab/ci/{configure_fedora33_common.cmake => configure_fedora34_common.cmake} (82%) rename .gitlab/ci/{configure_fedora33_makefiles.cmake => configure_fedora34_makefiles.cmake} (100%) rename .gitlab/ci/{configure_fedora33_ninja.cmake => configure_fedora34_ninja.cmake} (75%) rename .gitlab/ci/{configure_fedora33_ninja_multi.cmake => configure_fedora34_ninja_multi.cmake} (100%) rename .gitlab/ci/{configure_fedora33_sphinx.cmake => configure_fedora34_sphinx.cmake} (100%) rename .gitlab/ci/{configure_fedora33_sphinx_package.cmake => configure_fedora34_sphinx_package.cmake} (100%) create mode 100644 .gitlab/ci/configure_fedora34_tidy.cmake rename .gitlab/ci/{env_fedora33_makefiles.cmake => env_fedora34_makefiles.cmake} (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f8a22a5b359..1fc907dfb00 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,7 @@ prep:source-package: prep:doc-package: extends: - - .fedora33_sphinx_package + - .fedora34_sphinx_package - .cmake_prep_doc_linux - .linux_builder_tags_qt - .cmake_doc_artifacts @@ -106,16 +106,16 @@ build:debian10-iwyu: - .linux_builder_tags - .run_automatically -build:fedora33-tidy: +build:fedora34-tidy: extends: - - .fedora33_tidy + - .fedora34_tidy - .cmake_build_linux - .linux_builder_tags_qt - .run_automatically -build:fedora33-sphinx: +build:fedora34-sphinx: extends: - - .fedora33_sphinx + - .fedora34_sphinx - .cmake_build_linux - .linux_builder_tags_qt - .run_automatically @@ -161,9 +161,9 @@ test:debian10-aarch64-ninja: variables: CMAKE_CI_NO_MR: "true" -test:fedora33-makefiles: +test:fedora34-makefiles: extends: - - .fedora33_makefiles + - .fedora34_makefiles - .cmake_test_linux_release - .linux_builder_tags_qt - .run_dependent @@ -177,36 +177,36 @@ test:cuda10.2-nvidia: - .run_dependent - .needs_centos6_x86_64 -build:fedora33-ninja: +build:fedora34-ninja: extends: - - .fedora33_ninja + - .fedora34_ninja - .cmake_build_linux - .cmake_build_artifacts - .linux_builder_tags_qt - .run_manually -test:fedora33-ninja: +test:fedora34-ninja: extends: - - .fedora33_ninja + - .fedora34_ninja - .cmake_test_linux - .linux_builder_tags_x11 - .cmake_test_artifacts - .run_dependent dependencies: - - build:fedora33-ninja + - build:fedora34-ninja needs: - - build:fedora33-ninja + - build:fedora34-ninja -test:fedora33-ninja-multi: +test:fedora34-ninja-multi: extends: - - .fedora33_ninja_multi + - .fedora34_ninja_multi - .cmake_test_linux_external - .linux_builder_tags_qt - .run_dependent dependencies: - - test:fedora33-ninja + - test:fedora34-ninja needs: - - test:fedora33-ninja + - test:fedora34-ninja test:intel2016-makefiles: extends: diff --git a/.gitlab/ci/configure_fedora33_tidy.cmake b/.gitlab/ci/configure_fedora33_tidy.cmake deleted file mode 100644 index 9052fdc5623..00000000000 --- a/.gitlab/ci/configure_fedora33_tidy.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(CMake_RUN_CLANG_TIDY ON CACHE BOOL "") - -include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora33_common.cmake") diff --git a/.gitlab/ci/configure_fedora33_common.cmake b/.gitlab/ci/configure_fedora34_common.cmake similarity index 82% rename from .gitlab/ci/configure_fedora33_common.cmake rename to .gitlab/ci/configure_fedora34_common.cmake index dee78abfe73..4484e264ff0 100644 --- a/.gitlab/ci/configure_fedora33_common.cmake +++ b/.gitlab/ci/configure_fedora34_common.cmake @@ -1,5 +1,6 @@ set(BUILD_CursesDialog ON CACHE BOOL "") set(BUILD_QtDialog ON CACHE BOOL "") +set(CMake_QT_MAJOR_VERSION "5" CACHE STRING "") set(CMake_TEST_JQ "/usr/bin/jq" CACHE PATH "") set(CMake_TEST_JSON_SCHEMA ON CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora33_makefiles.cmake b/.gitlab/ci/configure_fedora34_makefiles.cmake similarity index 100% rename from .gitlab/ci/configure_fedora33_makefiles.cmake rename to .gitlab/ci/configure_fedora34_makefiles.cmake diff --git a/.gitlab/ci/configure_fedora33_ninja.cmake b/.gitlab/ci/configure_fedora34_ninja.cmake similarity index 75% rename from .gitlab/ci/configure_fedora33_ninja.cmake rename to .gitlab/ci/configure_fedora34_ninja.cmake index 883f425e7bc..37bc189dbc6 100644 --- a/.gitlab/ci/configure_fedora33_ninja.cmake +++ b/.gitlab/ci/configure_fedora34_ninja.cmake @@ -4,4 +4,4 @@ set(CMake_TEST_GUI "ON" CACHE BOOL "") # Cover compilation with C++11 only and not higher standards. set(CMAKE_CXX_STANDARD "11" CACHE STRING "") -include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora33_common.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora34_common.cmake") diff --git a/.gitlab/ci/configure_fedora33_ninja_multi.cmake b/.gitlab/ci/configure_fedora34_ninja_multi.cmake similarity index 100% rename from .gitlab/ci/configure_fedora33_ninja_multi.cmake rename to .gitlab/ci/configure_fedora34_ninja_multi.cmake diff --git a/.gitlab/ci/configure_fedora33_sphinx.cmake b/.gitlab/ci/configure_fedora34_sphinx.cmake similarity index 100% rename from .gitlab/ci/configure_fedora33_sphinx.cmake rename to .gitlab/ci/configure_fedora34_sphinx.cmake diff --git a/.gitlab/ci/configure_fedora33_sphinx_package.cmake b/.gitlab/ci/configure_fedora34_sphinx_package.cmake similarity index 100% rename from .gitlab/ci/configure_fedora33_sphinx_package.cmake rename to .gitlab/ci/configure_fedora34_sphinx_package.cmake diff --git a/.gitlab/ci/configure_fedora34_tidy.cmake b/.gitlab/ci/configure_fedora34_tidy.cmake new file mode 100644 index 00000000000..9c79303dfe1 --- /dev/null +++ b/.gitlab/ci/configure_fedora34_tidy.cmake @@ -0,0 +1,3 @@ +set(CMake_RUN_CLANG_TIDY ON CACHE BOOL "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora34_common.cmake") diff --git a/.gitlab/ci/env_fedora33_makefiles.cmake b/.gitlab/ci/env_fedora34_makefiles.cmake similarity index 100% rename from .gitlab/ci/env_fedora33_makefiles.cmake rename to .gitlab/ci/env_fedora34_makefiles.cmake diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index d0ac85e5bb3..e914b00b017 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -5,7 +5,7 @@ ### Release .linux_prep_source: - image: "fedora:33" + image: "fedora:34" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -68,8 +68,8 @@ ### Fedora -.fedora33: - image: "kitware/cmake:ci-fedora33-x86_64-2021-04-06" +.fedora34: + image: "kitware/cmake:ci-fedora34-x86_64-2021-05-10" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" @@ -77,28 +77,28 @@ #### Lint builds -.fedora33_tidy: - extends: .fedora33 +.fedora34_tidy: + extends: .fedora34 variables: - CMAKE_CONFIGURATION: fedora33_tidy + CMAKE_CONFIGURATION: fedora34_tidy CTEST_NO_WARNINGS_ALLOWED: 1 CMake_SKIP_INSTALL: 1 -.fedora33_sphinx: - extends: .fedora33 +.fedora34_sphinx: + extends: .fedora34 variables: - CMAKE_CONFIGURATION: fedora33_sphinx + CMAKE_CONFIGURATION: fedora34_sphinx CTEST_NO_WARNINGS_ALLOWED: 1 CTEST_SOURCE_SUBDIRECTORY: "Utilities/Sphinx" CMake_SKIP_INSTALL: 1 -.fedora33_sphinx_package: - extends: .fedora33 +.fedora34_sphinx_package: + extends: .fedora34 variables: - CMAKE_CONFIGURATION: fedora33_sphinx_package + CMAKE_CONFIGURATION: fedora34_sphinx_package CTEST_SOURCE_SUBDIRECTORY: "Utilities/Sphinx" #### Build and test @@ -117,26 +117,26 @@ CMAKE_CONFIGURATION: debian10_aarch64_ninja CTEST_NO_WARNINGS_ALLOWED: 1 -.fedora33_ninja: - extends: .fedora33 +.fedora34_ninja: + extends: .fedora34 variables: - CMAKE_CONFIGURATION: fedora33_ninja + CMAKE_CONFIGURATION: fedora34_ninja CTEST_NO_WARNINGS_ALLOWED: 1 -.fedora33_ninja_multi: - extends: .fedora33 +.fedora34_ninja_multi: + extends: .fedora34 variables: - CMAKE_CONFIGURATION: fedora33_ninja_multi + CMAKE_CONFIGURATION: fedora34_ninja_multi CTEST_NO_WARNINGS_ALLOWED: 1 CMAKE_GENERATOR: "Ninja Multi-Config" -.fedora33_makefiles: - extends: .fedora33 +.fedora34_makefiles: + extends: .fedora34 variables: - CMAKE_CONFIGURATION: fedora33_makefiles + CMAKE_CONFIGURATION: fedora34_makefiles CTEST_NO_WARNINGS_ALLOWED: 1 CMAKE_GENERATOR: "Unix Makefiles" @@ -374,7 +374,7 @@ .cmake_org_help: stage: build extends: - - .fedora33 + - .fedora34 - .linux_builder_tags - .cmake_org_help_artifacts script: From 27adb6c78e77af022e6854e9eb35bd78e623a4c7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 May 2021 15:29:02 -0400 Subject: [PATCH 0421/1519] gitlab-ci: update Debian base images --- .gitlab/os-linux.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index e914b00b017..f608474db97 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -45,7 +45,7 @@ ### Debian .debian10: - image: "kitware/cmake:ci-debian10-x86_64-2021-04-06" + image: "kitware/cmake:ci-debian10-x86_64-2021-05-11" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -60,7 +60,7 @@ CMake_SKIP_INSTALL: 1 .debian10_aarch64: - image: "kitware/cmake:ci-debian10-aarch64-2021-04-06" + image: "kitware/cmake:ci-debian10-aarch64-2021-05-11" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" From 18bd63af416560361b26762f730da5955e67256e Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 7 May 2021 11:40:38 -0400 Subject: [PATCH 0422/1519] ci: enable FindProtobuf gRPC test on Linux builds --- .gitlab/ci/configure_debian10_aarch64_ninja.cmake | 1 + .gitlab/ci/configure_debian10_ninja.cmake | 1 + .gitlab/ci/configure_fedora34_makefiles.cmake | 1 + 3 files changed, 3 insertions(+) diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index 8fc850c03b5..4d8dde6d9e6 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -48,6 +48,7 @@ set(CMake_TEST_FindPatch "ON" CACHE BOOL "") set(CMake_TEST_FindPNG "ON" CACHE BOOL "") set(CMake_TEST_FindPostgreSQL "ON" CACHE BOOL "") set(CMake_TEST_FindProtobuf "ON" CACHE BOOL "") +set(CMake_TEST_FindProtobuf_gRPC "ON" CACHE BOOL "") set(CMake_TEST_FindPython "ON" CACHE BOOL "") set(CMake_TEST_FindPython_NumPy "ON" CACHE BOOL "") set(CMake_TEST_FindPython_PyPy "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index 94cf6c102a2..732624ad525 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -48,6 +48,7 @@ set(CMake_TEST_FindPatch "ON" CACHE BOOL "") set(CMake_TEST_FindPNG "ON" CACHE BOOL "") set(CMake_TEST_FindPostgreSQL "ON" CACHE BOOL "") set(CMake_TEST_FindProtobuf "ON" CACHE BOOL "") +set(CMake_TEST_FindProtobuf_gRPC "ON" CACHE BOOL "") set(CMake_TEST_FindPython "ON" CACHE BOOL "") set(CMake_TEST_FindPython_IronPython "ON" CACHE BOOL "") set(CMake_TEST_FindPython_NumPy "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora34_makefiles.cmake b/.gitlab/ci/configure_fedora34_makefiles.cmake index 7519d95c1d9..48786e45731 100644 --- a/.gitlab/ci/configure_fedora34_makefiles.cmake +++ b/.gitlab/ci/configure_fedora34_makefiles.cmake @@ -48,6 +48,7 @@ set(CMake_TEST_FindPatch "ON" CACHE BOOL "") set(CMake_TEST_FindPNG "ON" CACHE BOOL "") set(CMake_TEST_FindPostgreSQL "ON" CACHE BOOL "") set(CMake_TEST_FindProtobuf "ON" CACHE BOOL "") +set(CMake_TEST_FindProtobuf_gRPC "ON" CACHE BOOL "") set(CMake_TEST_FindPython "ON" CACHE BOOL "") set(CMake_TEST_FindPython_NumPy "ON" CACHE BOOL "") set(CMake_TEST_FindPython_PyPy "ON" CACHE BOOL "") From f89c1a559d2cd53bf5b3b4218e6b657517eabe58 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 May 2021 14:53:53 -0400 Subject: [PATCH 0423/1519] UseJava: Avoid non-word "compilability" in documentation Also fix spelling in the release note from commit 3e03f359a7 (UseJava: Add RESOURCES with NAMESPACE to add_jar(), 2021-04-27). --- Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst | 2 +- Modules/UseJava.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst b/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst index a7bb685937e..caa07e7d8cb 100644 --- a/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst +++ b/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst @@ -2,4 +2,4 @@ UseJava-RESOURCES-NAMESPACE --------------------------- * The :module:`UseJava` module command ``add_jar`` gained option RESOURCES - allow explicit naming of resouces with non-optional namespace. + allow explicit naming of resources with non-optional namespace. diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 67478cca3e1..baed7ef2535 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -51,7 +51,7 @@ almost certainly result in confusion. .. note:: SOURCES Adding resources via the ``SOURCES`` parameter relies upon a hard-coded - list of file extensions which are tested to determine compilability + list of file extensions which are tested to determine whether they compile (e.g. File.java). ``SOURCES`` files which match the extensions are compiled. Files which do not match are treated as resources. To include uncompiled resources matching those file extensions use the ``RESOURCES`` parameter. From bf35f3848a95c1dbebe09f2f1fca6ba4635b5aec Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 11:07:36 -0400 Subject: [PATCH 0424/1519] gitlab-ci: rename lint builds to start in lint: --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1fc907dfb00..1d4e7f5a4ab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -99,21 +99,21 @@ upload:help:stage: # Lint builds -build:debian10-iwyu: +lint:debian10-iwyu: extends: - .debian10_iwyu - .cmake_build_linux - .linux_builder_tags - .run_automatically -build:fedora34-tidy: +lint:fedora34-tidy: extends: - .fedora34_tidy - .cmake_build_linux - .linux_builder_tags_qt - .run_automatically -build:fedora34-sphinx: +lint:fedora34-sphinx: extends: - .fedora34_sphinx - .cmake_build_linux From bca69d4272b975e7cad7b8dd780cf45dc30f6b68 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 10 May 2021 11:08:11 -0400 Subject: [PATCH 0425/1519] gitlab-ci: add codespell lint job --- .codespellrc | 2 +- .gitlab-ci.yml | 6 ++++++ .gitlab/os-linux.yml | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index c450ea22463..ba0fba66926 100644 --- a/.codespellrc +++ b/.codespellrc @@ -5,5 +5,5 @@ count = # Disable warnings about binary files quiet-level = 2 builtin = clear,rare,en-GB_to_en-US -skip = */.git,*/Copyright.txt,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Utilities/cm* +skip = */.git,*/build,*/Copyright.txt,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Utilities/cm* ignore-words-list = aci,ake,ans,ba,cconfiguration,conly,dependees,dne,dum,earch,ect,filetest,fo,helpfull,hiden,isnt,keypair,nd,ned,nin,nknown,ot,pard,seh,ser,te,upto,varn,vas,wee diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d4e7f5a4ab..aac1d9c91ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -99,6 +99,12 @@ upload:help:stage: # Lint builds +lint:codespell: + extends: + - .cmake_codespell_linux + - .linux_builder_tags + - .run_automatically + lint:debian10-iwyu: extends: - .debian10_iwyu diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index f608474db97..1bf4098956c 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -258,6 +258,13 @@ interruptible: true +.cmake_codespell_linux: + stage: build + extends: .fedora34 + script: + - codespell + interruptible: true + .cmake_build_linux: stage: build From 928cdb17c53f2fc5e57d658f297ec735ab8cb81d Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 12 May 2021 09:43:33 -0400 Subject: [PATCH 0426/1519] cmCommandLineArgument: Correctly record parsing failures --- Source/cmCommandLineArgument.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index 495dc697915..f4153fcbff6 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -98,17 +98,11 @@ struct cmCommandLineArgument // parse the string to get the value auto possible_value = cm::string_view(input).substr(this->Name.size()); if (possible_value.empty()) { - parseState = ParseMode::SyntaxError; parseState = ParseMode::ValueError; } else if (possible_value[0] == '=') { possible_value.remove_prefix(1); if (possible_value.empty()) { parseState = ParseMode::ValueError; - } else { - parseState = this->StoreCall(std::string(possible_value), - std::forward(state)...) - ? ParseMode::Valid - : ParseMode::Invalid; } } if (parseState == ParseMode::Valid) { @@ -150,6 +144,8 @@ struct cmCommandLineArgument : ParseMode::Invalid; index = (nextValueIndex - 1); } + } else { + parseState = ParseMode::SyntaxError; } } From 3a7153440282148233c7dff33538fd3b46a3175d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 10:05:50 -0400 Subject: [PATCH 0427/1519] Ninja: Restore support for Fortran in a symlinked build tree Since commit f3eed2c49d (cmGlobalNinjaGenerator: use P1689 dependency file format for Fortran, 2019-03-12, v3.20.0-rc1~454^2), Fortran stopped working in a build tree whose path contains a symlink. The reason is that the P1689r3 format's `work-directory` field gets populated with the realpath (via `getcwd`) of the build tree instead of the logical path to the build tree used for generating relative paths in `build.ninja`. This causes the `Fortran.dd` file to get absolute (real)paths to `.o` files, and Ninja does not match them with the relative `.o` file paths in `build.ninja`. Fix this by dropping use of the `work-directory` field. This restores our prior approach of generating paths in the dyndep file using the same forms of paths received from the buildsystem generator. The P1689r3 paper's format may need to be revised to account for this. Fixes: #21683 --- Source/cmScanDepFormat.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index e0460694e06..f988fe45f9a 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -69,7 +69,7 @@ static Json::Value EncodeFilename(std::string const& path) return false; \ } \ \ - if (!cmSystemTools::FileIsFullPath(res)) { \ + if (!work_directory.empty() && !cmSystemTools::FileIsFullPath(res)) { \ res = cmStrCat(work_directory, '/', res); \ } \ } while (0) @@ -105,15 +105,16 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info) } for (auto const& rule : rules) { + std::string work_directory; Json::Value const& workdir = rule["work-directory"]; - if (!workdir.isString()) { + if (workdir.isString()) { + PARSE_BLOB(workdir, work_directory); + } else if (!workdir.isNull()) { cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, ": work-directory is not a string")); return false; } - std::string work_directory; - PARSE_BLOB(workdir, work_directory); Json::Value const& depends = rule["depends"]; if (depends.isArray()) { @@ -203,8 +204,6 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, Json::Value& rules = ddi["rules"] = Json::arrayValue; Json::Value rule(Json::objectValue); - rule["work-directory"] = - EncodeFilename(cmSystemTools::GetCurrentWorkingDirectory()); Json::Value& inputs = rule["inputs"] = Json::arrayValue; inputs.append(EncodeFilename(input)); From f69079577a50ab203b6355a22a2e2243f5480628 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 15:42:14 -0400 Subject: [PATCH 0428/1519] cmGlobalXCodeGenerator: Simplify relative path conversion under project root --- Source/cmGlobalXCodeGenerator.cxx | 14 ++++---------- Source/cmGlobalXCodeGenerator.h | 3 +-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index f753f775e96..dd0ddf5e78c 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -586,13 +586,7 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root) { this->CurrentProject = root->GetProjectName(); this->SetCurrentLocalGenerator(root); - cmSystemTools::SplitPath( - this->CurrentLocalGenerator->GetCurrentSourceDirectory(), - this->ProjectSourceDirectoryComponents); - cmSystemTools::SplitPath( - this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), - this->ProjectOutputDirectoryComponents); - + this->CurrentRootGenerator = root; this->CurrentXCodeHackMakefile = cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts"); cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile); @@ -4704,13 +4698,13 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p) // We force conversion because Xcode breakpoints do not work unless // they are in a file named relative to the source tree. return cmSystemTools::ForceToRelativePath( - cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p); + this->CurrentRootGenerator->GetCurrentSourceDirectory(), p); } std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p) { - return this->CurrentLocalGenerator->MaybeConvertToRelativePath( - cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p); + return this->CurrentRootGenerator->MaybeConvertToRelativePath( + this->CurrentRootGenerator->GetCurrentBinaryDirectory(), p); } std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p) diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index a7b1814c5fe..1e1b344c9b5 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -348,13 +348,12 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator cmXCodeObject* FrameworkGroup; cmMakefile* CurrentMakefile; cmLocalGenerator* CurrentLocalGenerator; + cmLocalGenerator* CurrentRootGenerator = nullptr; std::vector CurrentConfigurationTypes; std::string CurrentReRunCMakeMakefile; std::string CurrentXCodeHackMakefile; std::string CurrentProject; std::set TargetDoneSet; - std::vector ProjectSourceDirectoryComponents; - std::vector ProjectOutputDirectoryComponents; std::map GroupMap; std::map GroupNameMap; std::map TargetGroup; From 09bee3bee137af72f57ee10327e4e5f689ce7e90 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 15:50:22 -0400 Subject: [PATCH 0429/1519] cmGlobalGhsMultiGenerator: Simplify relative path conversion logic Our call to `MaybeConvertToRelativePath` uses paths that always pass the "maybe" checks. Use `ForceToRelativePath` directly. --- Source/cmGlobalGhsMultiGenerator.cxx | 8 ++++---- Source/cmGlobalGhsMultiGenerator.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 172cf3fc0c7..7cf3e9363a7 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -375,7 +375,7 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, } void cmGlobalGhsMultiGenerator::WriteProjectLine( - std::ostream& fout, cmGeneratorTarget const* target, cmLocalGenerator* root, + std::ostream& fout, cmGeneratorTarget const* target, std::string& rootBinaryDir) { cmProp projName = target->GetProperty("GENERATOR_FILE_NAME"); @@ -383,7 +383,7 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine( if (projName && projType) { cmLocalGenerator* lg = target->GetLocalGenerator(); std::string dir = lg->GetCurrentBinaryDirectory(); - dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir); + dir = cmSystemTools::ForceToRelativePath(rootBinaryDir, dir); if (dir == ".") { dir.clear(); } else { @@ -433,7 +433,7 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) target->GetName(), "] had a cycle.\n")); } else { for (auto& tgt : build) { - this->WriteProjectLine(fbld, tgt, root, rootBinaryDir); + this->WriteProjectLine(fbld, tgt, rootBinaryDir); } } fbld.Close(); @@ -490,7 +490,7 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget( target->GetType() == cmStateEnums::SHARED_LIBRARY) { continue; } - this->WriteProjectLine(fbld, target, root, rootBinaryDir); + this->WriteProjectLine(fbld, target, rootBinaryDir); } } fbld.Close(); diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 7753b311b77..bd08301fdf1 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -103,7 +103,7 @@ class cmGlobalGhsMultiGenerator : public cmGlobalGenerator void WriteSubProjects(std::ostream& fout, std::string& all_target); void WriteTargets(cmLocalGenerator* root); void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target, - cmLocalGenerator* root, std::string& rootBinaryDir); + std::string& rootBinaryDir); void WriteCustomRuleBOD(std::ostream& fout); void WriteCustomTargetBOD(std::ostream& fout); void WriteAllTarget(cmLocalGenerator* root, From ba7b939831428e51042ba98ea54df8b98a20ab27 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 15:26:12 -0400 Subject: [PATCH 0430/1519] cmStateDirectory: Rename ConvertToRelPathIf{Not => }Contained The "Not" in the method name is backward from its logic. --- Source/cmGlobalGenerator.cxx | 2 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 2 +- Source/cmListFileCache.cxx | 4 ++-- Source/cmLocalGenerator.cxx | 2 +- Source/cmStateDirectory.cxx | 2 +- Source/cmStateDirectory.h | 2 +- Source/cmTarget.cxx | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 13579746d19..cca3bdc0df0 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -3029,7 +3029,7 @@ void cmGlobalGenerator::AddRuleHash(const std::vector& outputs, // Shorten the output name (in expected use case). cmStateDirectory cmDir = this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory(); - std::string fname = cmDir.ConvertToRelPathIfNotContained( + std::string fname = cmDir.ConvertToRelPathIfContained( this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]); // Associate the hash with this output. diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 248abffa646..e28baf3dd8d 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -610,7 +610,7 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( tname += "/fast"; } tname = - mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained( + mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfContained( mf->GetState()->GetBinaryDirectory(), tname); cmSystemTools::ConvertToOutputSlashes(tname); makeCommand.Add(std::move(tname)); diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 5c3a0344dc3..2b98f204c84 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -550,7 +550,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const cmListFileContext lfc = this->TopEntry->Context; cmStateSnapshot bottom = this->GetBottom(); if (!bottom.GetState()->GetIsInTryCompile()) { - lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained( + lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfContained( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << (lfc.Line ? " at " : " in ") << lfc; @@ -581,7 +581,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const } cmListFileContext lfc = cur->Context; if (!bottom.GetState()->GetIsInTryCompile()) { - lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained( + lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfContained( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << " " << lfc << "\n"; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index fbbdfcaa5e1..304b607c51c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3676,7 +3676,7 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const std::string cmLocalGenerator::MaybeConvertToRelativePath( std::string const& local_path, std::string const& remote_path) const { - return this->StateSnapshot.GetDirectory().ConvertToRelPathIfNotContained( + return this->StateSnapshot.GetDirectory().ConvertToRelPathIfContained( local_path, remote_path); } diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 7ce362a584a..7f25b4be7a5 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -159,7 +159,7 @@ bool cmStateDirectory::ContainsBoth(std::string const& local_path, return bothInBinary || bothInSource; } -std::string cmStateDirectory::ConvertToRelPathIfNotContained( +std::string cmStateDirectory::ConvertToRelPathIfContained( std::string const& local_path, std::string const& remote_path) const { if (!this->ContainsBoth(local_path, remote_path)) { diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 70c19bc1c2b..4dab9ff946d 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -36,7 +36,7 @@ class cmStateDirectory bool ContainsBoth(std::string const& local_path, std::string const& remote_path) const; - std::string ConvertToRelPathIfNotContained( + std::string ConvertToRelPathIfContained( std::string const& local_path, std::string const& remote_path) const; cmStringRange GetIncludeDirectoriesEntries() const; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 91dcd0efc9a..f84d2464042 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -934,7 +934,7 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const for (auto const& cmd : this->impl->TLLCommands) { if (cmd.first == sig) { cmListFileContext lfc = cmd.second; - lfc.FilePath = cmDir.ConvertToRelPathIfNotContained( + lfc.FilePath = cmDir.ConvertToRelPathIfContained( this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath); s << " * " << lfc << '\n'; } From 049d388cfa73bf034655dcb976fa059d29ab7abc Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 13 May 2021 00:01:10 -0400 Subject: [PATCH 0431/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7ebc881a5d0..b7eae3f18fe 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210512) +set(CMake_VERSION_PATCH 20210513) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 65b58b0316598d03c6865a11203c3ac5b8ba36a4 Mon Sep 17 00:00:00 2001 From: Dario Passet Date: Thu, 13 May 2021 07:26:06 +0000 Subject: [PATCH 0432/1519] VS Generator: Properly reference included external C# projects --- Source/cmVisualStudio10TargetGenerator.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 12a3679858f..ad98ba58524 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -4253,11 +4253,10 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) if (dt->IsCSharpOnly() || cmHasLiteralSuffix(path, "csproj")) { e2.Element("SkipGetTargetFrameworkProperties", "true"); } - // Don't reference targets that don't produce any output. - if (this->Configurations.empty() || - dt->GetManagedType(this->Configurations[0]) == - cmGeneratorTarget::ManagedType::Undefined) { + else if (this->Configurations.empty() || + dt->GetManagedType(this->Configurations[0]) == + cmGeneratorTarget::ManagedType::Undefined) { e2.Element("ReferenceOutputAssembly", "false"); e2.Element("CopyToOutputDirectory", "Never"); } From bd12b97d05314500892426e827dc0ad57c4f4fdc Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 May 2021 08:24:29 -0400 Subject: [PATCH 0433/1519] cmScanDepFormat: Drop unused "outputs", "inputs", and "depends" fields These fields are specified by our `P1689r3` paper, but are not actually needed. The dependencies of the scanning results themselves can be captured via normal depfile logic. Avoid saving this possibly-large information in the scanning results. It is not needed by later steps. --- Help/dev/experimental.rst | 5 ++++- Source/cmGlobalNinjaGenerator.cxx | 36 ++++++++++++++++++------------- Source/cmNinjaTargetGenerator.cxx | 2 +- Source/cmScanDepFormat.cxx | 25 +++------------------ Source/cmScanDepFormat.h | 10 +++------ 5 files changed, 32 insertions(+), 46 deletions(-) diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index d0191615a36..3db81779be4 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -39,7 +39,10 @@ to the file specified by the ```` placeholder, and write module dependencies to the file specified by the ```` placeholder. The module dependencies should be written in the format described -by the `P1689r3`_ paper. +by the `P1689r3`_ paper, with the following updates: + +* Omit the ``outputs``, ``inputs``, and ``depends`` fields from + each entry in the ``rules`` array. They are unused. Compiler writers may try out their scanning functionality using the `cxx-modules-sandbox`_ test project, modified to set variables diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 6937639e833..0a5b16926ef 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2247,14 +2247,22 @@ Compilation of source files within a target is split into the following steps: (because the latter consumes the module). */ -static std::unique_ptr cmcmd_cmake_ninja_depends_fortran( +namespace { + +struct cmSourceInfo +{ + cmScanDepInfo ScanDep; + std::vector Includes; +}; + +std::unique_ptr cmcmd_cmake_ninja_depends_fortran( std::string const& arg_tdi, std::string const& arg_pp); +} int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, std::vector::const_iterator argEnd) { std::string arg_tdi; - std::string arg_src; std::string arg_pp; std::string arg_dep; std::string arg_obj; @@ -2263,8 +2271,6 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, for (std::string const& arg : cmMakeRange(argBeg, argEnd)) { if (cmHasLiteralPrefix(arg, "--tdi=")) { arg_tdi = arg.substr(6); - } else if (cmHasLiteralPrefix(arg, "--src=")) { - arg_src = arg.substr(6); } else if (cmHasLiteralPrefix(arg, "--pp=")) { arg_pp = arg.substr(5); } else if (cmHasLiteralPrefix(arg, "--dep=")) { @@ -2305,9 +2311,6 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, cmSystemTools::Error("-E cmake_ninja_depends requires value for --lang="); return 1; } - if (arg_src.empty()) { - arg_src = cmStrCat("<", arg_obj, " input file>"); - } std::unique_ptr info; if (arg_lang == "Fortran") { @@ -2324,7 +2327,7 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, return 1; } - info->PrimaryOutput = arg_obj; + info->ScanDep.PrimaryOutput = arg_obj; { cmGeneratedFileStream depfile(arg_dep); @@ -2335,7 +2338,7 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, depfile << "\n"; } - if (!cmScanDepFormat_P1689_Write(arg_ddi, arg_src, *info)) { + if (!cmScanDepFormat_P1689_Write(arg_ddi, info->ScanDep)) { cmSystemTools::Error( cmStrCat("-E cmake_ninja_depends failed to write ", arg_ddi)); return 1; @@ -2343,6 +2346,8 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, return 0; } +namespace { + std::unique_ptr cmcmd_cmake_ninja_depends_fortran( std::string const& arg_tdi, std::string const& arg_pp) { @@ -2397,7 +2402,7 @@ std::unique_ptr cmcmd_cmake_ninja_depends_fortran( cmSourceReqInfo src_info; src_info.LogicalName = provide; src_info.CompiledModulePath = provide; - info->Provides.emplace_back(src_info); + info->ScanDep.Provides.emplace_back(src_info); } for (std::string const& require : finfo.Requires) { // Require modules not provided in the same source. @@ -2407,13 +2412,14 @@ std::unique_ptr cmcmd_cmake_ninja_depends_fortran( cmSourceReqInfo src_info; src_info.LogicalName = require; src_info.CompiledModulePath = require; - info->Requires.emplace_back(src_info); + info->ScanDep.Requires.emplace_back(src_info); } for (std::string const& include : finfo.Includes) { info->Includes.push_back(include); } return info; } +} bool cmGlobalNinjaGenerator::WriteDyndepFile( std::string const& dir_top_src, std::string const& dir_top_bld, @@ -2436,9 +2442,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( this->LocalGenerators.push_back(std::move(lgd)); } - std::vector objects; + std::vector objects; for (std::string const& arg_ddi : arg_ddis) { - cmSourceInfo info; + cmScanDepInfo info; if (!cmScanDepFormat_P1689_Parse(arg_ddi, &info)) { cmSystemTools::Error( cmStrCat("-E cmake_ninja_dyndep failed to parse ddi file ", arg_ddi)); @@ -2474,7 +2480,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( // We do this after loading the modules provided by linked targets // in case we have one of the same name that must be preferred. Json::Value tm = Json::objectValue; - for (cmSourceInfo const& object : objects) { + for (cmScanDepInfo const& object : objects) { for (auto const& p : object.Provides) { std::string const mod = cmStrCat( module_dir, cmSystemTools::GetFilenameName(p.CompiledModulePath)); @@ -2489,7 +2495,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( { cmNinjaBuild build("dyndep"); build.Outputs.emplace_back(""); - for (cmSourceInfo const& object : objects) { + for (cmScanDepInfo const& object : objects) { build.Outputs[0] = this->ConvertToNinjaPath(object.PrimaryOutput); build.ImplicitOuts.clear(); for (auto const& p : object.Provides) { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index ce0d8693aad..3ebf3645df0 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -528,7 +528,7 @@ std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi, const std::string& ddiFile) { return cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, - " --lang=", lang, " --src=$in", " --pp=", ppFile, + " --lang=", lang, " --pp=", ppFile, " --dep=$DEP_FILE --obj=$OBJ_FILE --ddi=", ddiFile); } diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index f988fe45f9a..e66f96dfc61 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -74,7 +74,8 @@ static Json::Value EncodeFilename(std::string const& path) } \ } while (0) -bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info) +bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, + cmScanDepInfo* info) { Json::Value ppio; Json::Value const& ppi = ppio; @@ -116,15 +117,6 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info) return false; } - Json::Value const& depends = rule["depends"]; - if (depends.isArray()) { - std::string depend_filename; - for (auto const& depend : depends) { - PARSE_FILENAME(depend, depend_filename); - info->Includes.push_back(depend_filename); - } - } - if (rule.isMember("future-compile")) { Json::Value const& future_compile = rule["future-compile"]; @@ -194,8 +186,7 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info) } bool cmScanDepFormat_P1689_Write(std::string const& path, - std::string const& input, - cmSourceInfo const& info) + cmScanDepInfo const& info) { Json::Value ddi(Json::objectValue); ddi["version"] = 0; @@ -204,16 +195,6 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, Json::Value& rules = ddi["rules"] = Json::arrayValue; Json::Value rule(Json::objectValue); - Json::Value& inputs = rule["inputs"] = Json::arrayValue; - inputs.append(EncodeFilename(input)); - - Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue; - rule_outputs.append(EncodeFilename(path)); - - Json::Value& depends = rule["depends"] = Json::arrayValue; - for (auto const& include : info.Includes) { - depends.append(EncodeFilename(include)); - } Json::Value& future_compile = rule["future-compile"] = Json::objectValue; diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h index 1ad0ecf73ec..51ceec1f61b 100644 --- a/Source/cmScanDepFormat.h +++ b/Source/cmScanDepFormat.h @@ -11,20 +11,16 @@ struct cmSourceReqInfo std::string CompiledModulePath; }; -struct cmSourceInfo +struct cmScanDepInfo { std::string PrimaryOutput; // Set of provided and required modules. std::vector Provides; std::vector Requires; - - // Set of files included in the translation unit. - std::vector Includes; }; bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, - cmSourceInfo* info); + cmScanDepInfo* info); bool cmScanDepFormat_P1689_Write(std::string const& path, - std::string const& input, - cmSourceInfo const& info); + cmScanDepInfo const& info); From db8e0beeaca0f0330431d5874bfb22e0a3f1fb70 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 11 May 2021 08:47:58 -0400 Subject: [PATCH 0434/1519] cmGlobalNinjaGenerator: Clarify semantics of Fortran scanning info Use `optional<>` instead of `unique_ptr<>` to hold optional value. --- Source/cmGlobalNinjaGenerator.cxx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 0a5b16926ef..d6675759f6b 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -2255,7 +2256,7 @@ struct cmSourceInfo std::vector Includes; }; -std::unique_ptr cmcmd_cmake_ninja_depends_fortran( +cm::optional cmcmd_cmake_ninja_depends_fortran( std::string const& arg_tdi, std::string const& arg_pp); } @@ -2312,7 +2313,7 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, return 1; } - std::unique_ptr info; + cm::optional info; if (arg_lang == "Fortran") { info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_pp); } else { @@ -2348,9 +2349,10 @@ int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, namespace { -std::unique_ptr cmcmd_cmake_ninja_depends_fortran( +cm::optional cmcmd_cmake_ninja_depends_fortran( std::string const& arg_tdi, std::string const& arg_pp) { + cm::optional info; cmFortranCompiler fc; std::vector includes; { @@ -2363,7 +2365,7 @@ std::unique_ptr cmcmd_cmake_ninja_depends_fortran( cmSystemTools::Error( cmStrCat("-E cmake_ninja_depends failed to parse ", arg_tdi, reader.getFormattedErrorMessages())); - return nullptr; + return info; } } @@ -2390,14 +2392,14 @@ std::unique_ptr cmcmd_cmake_ninja_depends_fortran( if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) { cmSystemTools::Error( cmStrCat("-E cmake_ninja_depends failed to open ", arg_pp)); - return nullptr; + return info; } if (cmFortran_yyparse(parser.Scanner) != 0) { // Failed to parse the file. - return nullptr; + return info; } - auto info = cm::make_unique(); + info = cmSourceInfo(); for (std::string const& provide : finfo.Provides) { cmSourceReqInfo src_info; src_info.LogicalName = provide; From 5d32ce320be5081d53a431126143360e364803be Mon Sep 17 00:00:00 2001 From: Arcturus Arcturus Date: Tue, 11 May 2021 11:27:40 +0100 Subject: [PATCH 0435/1519] FetchContent: Use private local variables in FetchContent_MakeAvailable --- Modules/FetchContent.cmake | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index f5de93043e4..bd82a90e1d9 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -1182,11 +1182,11 @@ endfunction() # calls will be available to the caller. macro(FetchContent_MakeAvailable) - foreach(contentName IN ITEMS ${ARGV}) - string(TOLOWER ${contentName} contentNameLower) - FetchContent_GetProperties(${contentName}) - if(NOT ${contentNameLower}_POPULATED) - FetchContent_Populate(${contentName}) + foreach(__cmake_contentName IN ITEMS ${ARGV}) + string(TOLOWER ${__cmake_contentName} __cmake_contentNameLower) + FetchContent_GetProperties(${__cmake_contentName}) + if(NOT ${__cmake_contentNameLower}_POPULATED) + FetchContent_Populate(${__cmake_contentName}) # Only try to call add_subdirectory() if the populated content # can be treated that way. Protecting the call with the check @@ -1197,22 +1197,28 @@ macro(FetchContent_MakeAvailable) # for ExternalProject. It won't matter if it was passed through # to the ExternalProject sub-build, since it would have been # ignored there. - set(__fc_srcdir "${${contentNameLower}_SOURCE_DIR}") - __FetchContent_getSavedDetails(${contentName} contentDetails) - if("${contentDetails}" STREQUAL "") - message(FATAL_ERROR "No details have been set for content: ${contentName}") + set(__cmake_srcdir "${${__cmake_contentNameLower}_SOURCE_DIR}") + __FetchContent_getSavedDetails(${__cmake_contentName} __cmake_contentDetails) + if("${__cmake_contentDetails}" STREQUAL "") + message(FATAL_ERROR "No details have been set for content: ${__cmake_contentName}") endif() - cmake_parse_arguments(__fc_arg "" "SOURCE_SUBDIR" "" ${contentDetails}) - if(NOT "${__fc_arg_SOURCE_SUBDIR}" STREQUAL "") - string(APPEND __fc_srcdir "/${__fc_arg_SOURCE_SUBDIR}") + cmake_parse_arguments(__cmake_arg "" "SOURCE_SUBDIR" "" ${__cmake_contentDetails}) + if(NOT "${__cmake_arg_SOURCE_SUBDIR}" STREQUAL "") + string(APPEND __cmake_srcdir "/${__cmake_arg_SOURCE_SUBDIR}") endif() - if(EXISTS ${__fc_srcdir}/CMakeLists.txt) - add_subdirectory(${__fc_srcdir} ${${contentNameLower}_BINARY_DIR}) + if(EXISTS ${__cmake_srcdir}/CMakeLists.txt) + add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR}) endif() - unset(__fc_srcdir) + unset(__cmake_srcdir) endif() endforeach() + # clear local variables to prevent leaking into the caller's scope + unset(__cmake_contentName) + unset(__cmake_contentNameLower) + unset(__cmake_contentDetails) + unset(__cmake_arg_SOURCE_SUBDIR) + endmacro() From 5aa0dec6b011c74225f4af895922edd10db09607 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 12 May 2021 09:44:39 -0400 Subject: [PATCH 0436/1519] cmake: `--build` and `--install` error out when encountering bad flags Fixes #22186 --- Source/cmakemain.cxx | 26 +++++++++++++++++-- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 12 +++++++++ .../build-invalid-target-syntax-result.txt | 1 + .../build-invalid-target-syntax-stderr.txt | 2 ++ .../build-unknown-command-long-result.txt | 1 + .../build-unknown-command-long-stderr.txt | 2 ++ ...d-unknown-command-partial-match-result.txt | 1 + ...d-unknown-command-partial-match-stderr.txt | 2 ++ .../build-unknown-command-short-result.txt | 1 + .../build-unknown-command-short-stderr.txt | 2 ++ .../install-unknown-command-long-result.txt | 1 + .../install-unknown-command-long-stderr.txt | 2 ++ .../install-unknown-command-short-result.txt | 1 + .../install-unknown-command-short-stderr.txt | 2 ++ 14 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/CommandLine/build-invalid-target-syntax-result.txt create mode 100644 Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/build-unknown-command-long-result.txt create mode 100644 Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/build-unknown-command-partial-match-result.txt create mode 100644 Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/build-unknown-command-short-result.txt create mode 100644 Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/install-unknown-command-long-result.txt create mode 100644 Tests/RunCMake/CommandLine/install-unknown-command-long-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/install-unknown-command-short-result.txt create mode 100644 Tests/RunCMake/CommandLine/install-unknown-command-short-stderr.txt diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 88ba0116ca6..ad648186bd5 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -532,11 +532,22 @@ int do_build(int ac, char const* const* av) for (; i < inputArgs.size() && !nativeOptionsPassed; ++i) { std::string const& arg = inputArgs[i]; + bool matched = false; + bool parsed = false; for (auto const& m : arguments) { - if (m.matches(arg) && m.parse(arg, i, inputArgs)) { + matched = m.matches(arg); + if (matched) { + parsed = m.parse(arg, i, inputArgs); break; } } + if (!(matched && parsed)) { + dir.clear(); + if (!matched) { + std::cerr << "Unknown argument " << arg << std::endl; + } + break; + } } if (nativeOptionsPassed) { @@ -806,11 +817,22 @@ int do_install(int ac, char const* const* av) for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) { std::string const& arg = inputArgs[i]; + bool matched = false; + bool parsed = false; for (auto const& m : arguments) { - if (m.matches(arg) && m.parse(arg, i, inputArgs)) { + matched = m.matches(arg); + if (matched) { + parsed = m.parse(arg, i, inputArgs); break; } } + if (!(matched && parsed)) { + dir.clear(); + if (!matched) { + std::cerr << "Unknown argument " << arg << std::endl; + } + break; + } } } diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 8072a2cad45..caf3c889661 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -54,6 +54,14 @@ run_cmake_command(build-no-dir ${CMAKE_COMMAND} --build) run_cmake_command(build-no-cache ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}) +run_cmake_command(build-unknown-command-short + ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR} -invalid-command) +run_cmake_command(build-unknown-command-long + ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR} --invalid-command) +run_cmake_command(build-unknown-command-partial-match + ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR} --targetinvalid) +run_cmake_command(build-invalid-target-syntax + ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR} --target=invalid) run_cmake_command(build-no-generator ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-no-generator) run_cmake_command(build-bad-dir @@ -65,6 +73,10 @@ run_cmake_command(install-no-dir ${CMAKE_COMMAND} --install) run_cmake_command(install-bad-dir ${CMAKE_COMMAND} --install dir-does-not-exist) +run_cmake_command(install-unknown-command-short + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR} -invalid-command) +run_cmake_command(install-unknown-command-long + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR} --invalid-command) 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) diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-result.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt new file mode 100644 index 00000000000..ce1c92d5171 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Invalid syntax used with --target +Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-long-result.txt b/Tests/RunCMake/CommandLine/build-unknown-command-long-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-unknown-command-long-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt new file mode 100644 index 00000000000..c8f1a03cb82 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt @@ -0,0 +1,2 @@ +^Unknown argument --invalid-command +Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-result.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt new file mode 100644 index 00000000000..ce1c92d5171 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Invalid syntax used with --target +Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-short-result.txt b/Tests/RunCMake/CommandLine/build-unknown-command-short-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-unknown-command-short-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt new file mode 100644 index 00000000000..a6cfeceaced --- /dev/null +++ b/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt @@ -0,0 +1,2 @@ +^Unknown argument -invalid-command +Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/install-unknown-command-long-result.txt b/Tests/RunCMake/CommandLine/install-unknown-command-long-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-unknown-command-long-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-unknown-command-long-stderr.txt b/Tests/RunCMake/CommandLine/install-unknown-command-long-stderr.txt new file mode 100644 index 00000000000..e6cee6b45ad --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-unknown-command-long-stderr.txt @@ -0,0 +1,2 @@ +^Unknown argument --invalid-command +Usage: cmake --install \[options\] diff --git a/Tests/RunCMake/CommandLine/install-unknown-command-short-result.txt b/Tests/RunCMake/CommandLine/install-unknown-command-short-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-unknown-command-short-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-unknown-command-short-stderr.txt b/Tests/RunCMake/CommandLine/install-unknown-command-short-stderr.txt new file mode 100644 index 00000000000..f690ec43041 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-unknown-command-short-stderr.txt @@ -0,0 +1,2 @@ +^Unknown argument -invalid-command +Usage: cmake --install \[options\] From f78b167a2364d81fe8effab5face0ff888f6d9c2 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 13 May 2021 09:33:30 -0400 Subject: [PATCH 0437/1519] cmCommandLineArgument: Provide more information syntax error messages --- Source/cmCommandLineArgument.h | 7 ++++--- .../CommandLine/build-invalid-target-syntax-stderr.txt | 2 +- .../build-unknown-command-partial-match-stderr.txt | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index f4153fcbff6..ddfff32f6f5 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -25,7 +25,7 @@ struct cmCommandLineArgument template cmCommandLineArgument(std::string n, Values t, FunctionType&& func) - : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) + : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n)) , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) , Name(std::move(n)) , Type(t) @@ -36,7 +36,7 @@ struct cmCommandLineArgument template cmCommandLineArgument(std::string n, std::string failedMsg, Values t, FunctionType&& func) - : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) + : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n)) , InvalidValueMessage(std::move(failedMsg)) , Name(std::move(n)) , Type(t) @@ -150,7 +150,8 @@ struct cmCommandLineArgument } if (parseState == ParseMode::SyntaxError) { - cmSystemTools::Error(this->InvalidSyntaxMessage); + cmSystemTools::Error( + cmStrCat("'", input, "'", this->InvalidSyntaxMessage)); } else if (parseState == ParseMode::ValueError) { cmSystemTools::Error(this->InvalidValueMessage); } diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt index ce1c92d5171..5fe25390a25 100644 --- a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt @@ -1,2 +1,2 @@ -^CMake Error: Invalid syntax used with --target +^CMake Error: '--target=invalid' is invalid syntax for --target Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt index ce1c92d5171..d69338a411e 100644 --- a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt @@ -1,2 +1,2 @@ -^CMake Error: Invalid syntax used with --target +^CMake Error: '--targetinvalid' is invalid syntax for --target Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] From caea48eec966db7b5093bf85559b41da52eafd0e Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Thu, 13 May 2021 15:32:25 +0200 Subject: [PATCH 0438/1519] CMakeParseImplicitIncludeInfo: remove needless variable expansions They seem to actually cause trouble, like an error reported on IRC where some but not all CMake invocations may end up with an error like this: CMake Warning (dev) at /usr/share/cmake/Modules/CMakeParseImplicitIncludeInfo.cmake:74 (if): Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted. Run "cmake --help-policy CMP0054" for policy details. Use the cmake_policy command to set the policy and suppress this warning. Quoted keywords like ")" will no longer be interpreted as keywords when the policy is set to NEW. Since the policy is not set the OLD behavior will be used. Call Stack (most recent call first): /usr/share/cmake/Modules/CMakeParseImplicitIncludeInfo.cmake:179 (cmake_parse_implicit_include_line) /usr/share/cmake/Modules/CMakeDetermineCompilerABI.cmake:119 (cmake_parse_implicit_include_info) /usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI) CMakeLists.txt:24 (project) This warning is for project developers. Use -Wno-dev to suppress it. CMake Error at /usr/share/cmake/Modules/CMakeParseImplicitIncludeInfo.cmake:74 (if): if given arguments: "GNU" "STREQUAL" "SunPro" "AND" "(" ")" "MATCHES" "-D__SUNPRO_C" "OR" ")" "MATCHES" "-D__SUNPRO_F" ")" I suspect that the line ends up being just ")", which then causes this error. --- Modules/CMakeParseImplicitIncludeInfo.cmake | 50 ++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Modules/CMakeParseImplicitIncludeInfo.cmake b/Modules/CMakeParseImplicitIncludeInfo.cmake index a8e6ac0b6ee..5c0eda27031 100644 --- a/Modules/CMakeParseImplicitIncludeInfo.cmake +++ b/Modules/CMakeParseImplicitIncludeInfo.cmake @@ -12,9 +12,9 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) set(log "") # Cray compiler (from cray wrapper, via PrgEnv-cray) - if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "Cray" AND - "${line}" MATCHES "^/" AND "${line}" MATCHES "/ccfe |/ftnfe " AND - "${line}" MATCHES " -isystem| -I") + if(CMAKE_${lang}_COMPILER_ID STREQUAL "Cray" AND + line MATCHES "^/" AND line MATCHES "/ccfe |/ftnfe " AND + line MATCHES " -isystem| -I") string(REGEX MATCHALL " (-I ?|-isystem )(\"[^\"]+\"|[^ \"]+)" incs "${line}") foreach(inc IN LISTS incs) string(REGEX REPLACE " (-I ?|-isystem )(\"[^\"]+\"|[^ \"]+)" "\\2" idir "${inc}") @@ -28,12 +28,12 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) endif() # PGI compiler - if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "PGI") + if(CMAKE_${lang}_COMPILER_ID STREQUAL "PGI") # pgc++ verbose output differs - if(("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "Fortran") AND - "${line}" MATCHES "^/" AND - "${line}" MATCHES "/pgc |/pgf901 |/pgftnc " AND - "${line}" MATCHES " -cmdline ") + if((lang STREQUAL "C" OR lang STREQUAL "Fortran") AND + line MATCHES "^/" AND + line MATCHES "/pgc |/pgf901 |/pgftnc " AND + line MATCHES " -cmdline ") # cmdline has unparsed cmdline, remove it string(REGEX REPLACE "-cmdline .*" "" line "${line}") if("${line}" MATCHES " -nostdinc ") @@ -51,14 +51,14 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) else() string(APPEND log " warning: PGI C/F parse failed!\n") endif() - elseif("${lang}" STREQUAL "CXX" AND "${line}" MATCHES "^/" AND - "${line}" MATCHES "/pggpp1 " AND "${line}" MATCHES " -I") + elseif(lang STREQUAL "CXX" AND line MATCHES "^/" AND + line MATCHES "/pggpp1 " AND line MATCHES " -I") # oddly, -Mnostdinc does not get rid of system -I's, at least in # PGI 18.10.1 ... string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}") foreach(inc IN LISTS incs) string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}") - if(NOT "${idir}" STREQUAL "-") # filter out "-I-" + if(NOT idir STREQUAL "-") # filter out "-I-" list(APPEND rv "${idir}") endif() endforeach() @@ -71,8 +71,8 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) endif() # SunPro compiler - if("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "SunPro" AND - ("${line}" MATCHES "-D__SUNPRO_C" OR "${line}" MATCHES "-D__SUNPRO_F") ) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "SunPro" AND + (line MATCHES "-D__SUNPRO_C" OR line MATCHES "-D__SUNPRO_F")) string(REGEX MATCHALL " (-I ?)([^ ]*)" incs "${line}") foreach(inc IN LISTS incs) string(REGEX REPLACE " (-I ?)([^ ]*)" "\\2" idir "${inc}") @@ -81,7 +81,7 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) endif() endforeach() if(rv) - if ("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "CXX") + if (lang STREQUAL "C" OR lang STREQUAL "CXX") # /usr/include appears to be hardwired in list(APPEND rv "/usr/include") endif() @@ -92,24 +92,24 @@ function(cmake_parse_implicit_include_line line lang id_var log_var state_var) endif() # XL compiler - if(("${CMAKE_${lang}_COMPILER_ID}" STREQUAL "XL" - OR "${CMAKE_${lang}_COMPILER_ID}" STREQUAL "XLClang") - AND "${line}" MATCHES "^/" - AND ( ("${lang}" STREQUAL "Fortran" AND - "${line}" MATCHES "/xl[fF]entry " AND - "${line}" MATCHES "OSVAR\\([^ ]+\\)") + if((CMAKE_${lang}_COMPILER_ID STREQUAL "XL" + OR CMAKE_${lang}_COMPILER_ID STREQUAL "XLClang") + AND line MATCHES "^/" + AND ( (lang STREQUAL "Fortran" AND + line MATCHES "/xl[fF]entry " AND + line MATCHES "OSVAR\\([^ ]+\\)") OR - ( ("${lang}" STREQUAL "C" OR "${lang}" STREQUAL "CXX") AND - "${line}" MATCHES "/xl[cC]2?entry " AND - "${line}" MATCHES " -qosvar=") + ( (lang STREQUAL "C" OR lang STREQUAL "CXX") AND + line MATCHES "/xl[cC]2?entry " AND + line MATCHES " -qosvar=") ) ) # -qnostdinc cancels other stdinc flags, even if present string(FIND "${line}" " -qnostdinc" nostd) - if(NOT ${nostd} EQUAL -1) + if(NOT nostd EQUAL -1) set(rv "") # defined but empty string(APPEND log " got implicit includes via XL parser (nostdinc)\n") else() - if("${lang}" STREQUAL "CXX") + if(lang STREQUAL "CXX") string(REGEX MATCHALL " -qcpp_stdinc=([^ ]*)" std "${line}") string(REGEX MATCHALL " -qgcc_cpp_stdinc=([^ ]*)" gcc_std "${line}") else() From c7aa3bdefc05848666578802da2423efa4f24e26 Mon Sep 17 00:00:00 2001 From: Dario Passet Date: Thu, 13 May 2021 18:38:01 +0200 Subject: [PATCH 0439/1519] Tests/include_external_msproject: Check C# project reference --- .../RunCMakeTest.cmake | 1 + .../VSCSharpReference-check.cmake | 36 +++++++++++++++++++ .../VSCSharpReference.cmake | 10 ++++++ 3 files changed, 47 insertions(+) create mode 100644 Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake create mode 100644 Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake diff --git a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake index 7ed0773f9f1..cb0eb187999 100644 --- a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake @@ -8,4 +8,5 @@ run_cmake(CustomConfig) if(RunCMake_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])") run_cmake(SkipGetTargetFrameworkProperties) + run_cmake(VSCSharpReference) endif() diff --git a/Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake b/Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake new file mode 100644 index 00000000000..71b8c1f9c6b --- /dev/null +++ b/Tests/RunCMake/include_external_msproject/VSCSharpReference-check.cmake @@ -0,0 +1,36 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/internal.vcxproj" all_build) + +string(REGEX MATCH + ".*" + ProjectReference + ${all_build} +) + +if(ProjectReference STREQUAL "") + set(RunCMake_TEST_FAILED "${test} is being set unexpectedly.") +else() + string(REGEX MATCH + ".*" + ReferenceOutputAssembly + ${ProjectReference} + ) + + if(NOT ReferenceOutputAssembly STREQUAL "") + string(REPLACE + "" + "" + ReferenceOutputAssemblyValue + ${ReferenceOutputAssembly} + ) + string(REPLACE + "" + "" + ReferenceOutputAssemblyValue + ${ReferenceOutputAssemblyValue} + ) + + if(ReferenceOutputAssemblyValue MATCHES "[Fa][Ll][Ss][Ee]") + set(RunCMake_TEST_FAILED "Referenced C# project with ReferenceOutputAssembly set to false.") + endif() + endif() +endif() diff --git a/Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake b/Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake new file mode 100644 index 00000000000..6229e612aff --- /dev/null +++ b/Tests/RunCMake/include_external_msproject/VSCSharpReference.cmake @@ -0,0 +1,10 @@ +project(VSCSharpReference) + +include_external_msproject(external external.csproj) + +add_executable(internal + main.cpp +) +add_dependencies(internal + external +) From ec1ea13066e1b65bfd56ae62bda036f13c950c2d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 May 2021 11:54:15 -0400 Subject: [PATCH 0440/1519] cmDependsFortran: Simplify relative path conversion helper Revert commit 8377d9e00b (Fortran: Inline conversion to relative path, 2016-10-04, v3.8.0-rc1~494^2~4). The inline implementation is still identical to what was previously called. Restore the call again. --- Source/cmDependsFortran.cxx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 1a06f317062..636b5e41112 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -17,8 +17,6 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmProperty.h" -#include "cmStateDirectory.h" -#include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -685,9 +683,5 @@ bool cmDependsFortran::ModulesDiffer(const std::string& modFile, std::string cmDependsFortran::MaybeConvertToRelativePath( std::string const& base, std::string const& path) { - if (!this->LocalGenerator->GetStateSnapshot().GetDirectory().ContainsBoth( - base, path)) { - return path; - } - return cmSystemTools::ForceToRelativePath(base, path); + return this->LocalGenerator->MaybeConvertToRelativePath(base, path); } From 1d1d88d3c8b6745b31c220599f536fd50bf5cbe9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 14:38:21 -0400 Subject: [PATCH 0441/1519] cmMakefileTargetGenerator: Clarify name of relative path conversion helper --- Source/cmMakefileTargetGenerator.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index e07e722fe8a..bec7805c4bf 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1775,7 +1775,7 @@ class cmMakefileTargetGeneratorObjectStrings { // Construct the name of the next object. this->NextObject = this->OutputConverter->ConvertToOutputFormat( - this->MaybeConvertToRelativePath(obj), cmOutputConverter::RESPONSE); + this->MaybeRelativeToCurBinDir(obj), cmOutputConverter::RESPONSE); // Roll over to next string if the limit will be exceeded. if (this->LengthLimit != std::string::npos && @@ -1796,13 +1796,13 @@ class cmMakefileTargetGeneratorObjectStrings void Done() { this->Strings.push_back(this->CurrentString); } private: - std::string MaybeConvertToRelativePath(std::string const& obj) + std::string MaybeRelativeToCurBinDir(std::string const& path) { - if (!this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), obj)) { - return obj; + std::string const& base = this->StateDir.GetCurrentBinary(); + if (!this->StateDir.ContainsBoth(base, path)) { + return path; } - return cmSystemTools::ForceToRelativePath( - this->StateDir.GetCurrentBinary(), obj); + return cmSystemTools::ForceToRelativePath(base, path); } std::vector& Strings; From 1879f1bcbc4e2fbd9eaca4eff351ab928c4a3268 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 15:34:38 -0400 Subject: [PATCH 0442/1519] cmLocalCommonGenerator: Factor out relative path conversion helper --- Source/cmCommonTargetGenerator.cxx | 3 +-- Source/cmLocalCommonGenerator.cxx | 9 +++++++-- Source/cmLocalCommonGenerator.h | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 228cff7ae15..0c5a7dfae2a 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -241,8 +241,7 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config) manifests.reserve(manifest_srcs.size()); for (cmSourceFile const* manifest_src : manifest_srcs) { manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat( - this->LocalCommonGenerator->MaybeConvertToRelativePath( - this->LocalCommonGenerator->GetWorkingDirectory(), + this->LocalCommonGenerator->MaybeRelativeToWorkDir( manifest_src->GetFullPath()), cmOutputConverter::SHELL)); } diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 5daaeff4904..4ec0c9d9691 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -24,6 +24,12 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, cmLocalCommonGenerator::~cmLocalCommonGenerator() = default; +std::string cmLocalCommonGenerator::MaybeRelativeToWorkDir( + std::string const& path) const +{ + return this->MaybeConvertToRelativePath(this->WorkingDirectory, path); +} + std::string cmLocalCommonGenerator::GetTargetFortranFlags( cmGeneratorTarget const* target, std::string const& config) { @@ -38,8 +44,7 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( target->GetFortranModuleDirectory(this->WorkingDirectory); if (!mod_dir.empty()) { mod_dir = this->ConvertToOutputFormat( - this->MaybeConvertToRelativePath(this->WorkingDirectory, mod_dir), - cmOutputConverter::SHELL); + this->MaybeRelativeToWorkDir(mod_dir), cmOutputConverter::SHELL); } else { mod_dir = this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT"); diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index f1eaf61fa75..72c8e833701 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -32,6 +32,8 @@ class cmLocalCommonGenerator : public cmLocalGenerator std::string GetWorkingDirectory() const { return this->WorkingDirectory; } + std::string MaybeRelativeToWorkDir(std::string const& path) const; + std::string GetTargetFortranFlags(cmGeneratorTarget const* target, std::string const& config) override; From 15fa3200715869d5acb94a282feb301d2e10a0eb Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 12 May 2021 15:51:47 -0400 Subject: [PATCH 0443/1519] cmLocalGenerator: Factor out relative path conversion helpers Most calls to `MaybeConvertToRelativePath` use one of our common work directories (e.g. top of the build tree) as the local path. Add helpers for each of the common cases to simplify and clarify call sites. --- Source/cmDependsC.cxx | 7 +- Source/cmDependsCompiler.cxx | 14 +-- Source/cmDependsFortran.cxx | 29 ++--- Source/cmDependsFortran.h | 4 - Source/cmExtraEclipseCDT4Generator.cxx | 4 +- Source/cmGhsMultiTargetGenerator.cxx | 8 +- Source/cmGlobalNinjaGenerator.cxx | 6 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 26 ++-- Source/cmGlobalVisualStudio7Generator.cxx | 3 +- Source/cmGlobalXCodeGenerator.cxx | 3 +- Source/cmLocalCommonGenerator.cxx | 2 +- Source/cmLocalGenerator.cxx | 32 +++-- Source/cmLocalGenerator.h | 12 +- Source/cmLocalNinjaGenerator.cxx | 12 +- Source/cmLocalUnixMakefileGenerator3.cxx | 63 ++++------ Source/cmLocalVisualStudio7Generator.cxx | 13 +- Source/cmLocalVisualStudioGenerator.cxx | 6 +- .../cmMakefileExecutableTargetGenerator.cxx | 66 ++++------ Source/cmMakefileLibraryTargetGenerator.cxx | 76 +++++------- Source/cmMakefileTargetGenerator.cxx | 113 +++++++----------- Source/cmMakefileUtilityTargetGenerator.cxx | 6 +- Source/cmTransformDepfile.cxx | 13 +- Source/cmVisualStudio10TargetGenerator.cxx | 18 +-- 23 files changed, 210 insertions(+), 326 deletions(-) diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 60e8cbf2c38..da37d4531ce 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -90,13 +90,10 @@ bool cmDependsC::WriteDependencies(const std::set& sources, std::set dependencies; bool haveDeps = false; - std::string binDir = this->LocalGenerator->GetBinaryDirectory(); - // Compute a path to the object file to write to the internal depend file. // Any existing content of the internal depend file has already been // loaded in ValidDeps with this path as a key. - std::string obj_i = - this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj); + std::string obj_i = this->LocalGenerator->MaybeRelativeToTopBinDir(obj); if (this->ValidDeps != nullptr) { auto const tmpIt = this->ValidDeps->find(obj_i); @@ -228,7 +225,7 @@ bool cmDependsC::WriteDependencies(const std::set& sources, } for (std::string const& dep : dependencies) { std::string dependee = this->LocalGenerator->ConvertToMakefilePath( - this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep)); + this->LocalGenerator->MaybeRelativeToTopBinDir(dep)); if (supportLongLineDepend) { makeDepends << ' ' << lineContinue << ' ' << dependee; } else { diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx index 2b48df96934..800725fd537 100644 --- a/Source/cmDependsCompiler.cxx +++ b/Source/cmDependsCompiler.cxx @@ -190,21 +190,19 @@ void cmDependsCompiler::WriteDependencies( bool supportLongLineDepend = static_cast( this->LocalGenerator->GetGlobalGenerator()) ->SupportsLongLineDependencies(); - const auto& binDir = this->LocalGenerator->GetBinaryDirectory(); cmDepends::DependencyMap makeDependencies(dependencies); std::unordered_set phonyTargets; // external dependencies file for (auto& node : makeDependencies) { auto target = this->LocalGenerator->ConvertToMakefilePath( - this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first)); + this->LocalGenerator->MaybeRelativeToTopBinDir(node.first)); auto& deps = node.second; - std::transform( - deps.cbegin(), deps.cend(), deps.begin(), - [this, &binDir](const std::string& dep) { - return this->LocalGenerator->ConvertToMakefilePath( - this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep)); - }); + std::transform(deps.cbegin(), deps.cend(), deps.begin(), + [this](const std::string& dep) { + return this->LocalGenerator->ConvertToMakefilePath( + this->LocalGenerator->MaybeRelativeToTopBinDir(dep)); + }); bool first_dep = true; if (supportLongLineDepend) { diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 636b5e41112..bca26b9caaf 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -190,8 +190,6 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, cmGeneratedFileStream fcStream(fcName); fcStream << "# Remove fortran modules provided by this target.\n"; fcStream << "FILE(REMOVE"; - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); for (std::string const& i : provides) { std::string mod_upper = cmStrCat(mod_dir, '/'); std::string mod_lower = cmStrCat(mod_dir, '/'); @@ -199,13 +197,13 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp"); fcStream << "\n" " \"" - << this->MaybeConvertToRelativePath(currentBinDir, mod_lower) + << this->LocalGenerator->MaybeRelativeToCurBinDir(mod_lower) << "\"\n" " \"" - << this->MaybeConvertToRelativePath(currentBinDir, mod_upper) + << this->LocalGenerator->MaybeRelativeToCurBinDir(mod_upper) << "\"\n" " \"" - << this->MaybeConvertToRelativePath(currentBinDir, stamp) + << this->LocalGenerator->MaybeRelativeToCurBinDir(stamp) << "\"\n"; } fcStream << " )\n"; @@ -315,8 +313,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, std::string const& src = info.Source; // Write the include dependencies to the output stream. - std::string binDir = this->LocalGenerator->GetBinaryDirectory(); - std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj); + std::string obj_i = this->LocalGenerator->MaybeRelativeToTopBinDir(obj); std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i); internalDepends << obj_i << "\n " << src << '\n'; if (!info.Includes.empty()) { @@ -331,7 +328,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, } for (std::string const& i : info.Includes) { std::string dependee = cmSystemTools::ConvertToOutputPath( - this->MaybeConvertToRelativePath(binDir, i)); + this->LocalGenerator->MaybeRelativeToTopBinDir(i)); if (supportLongLineDepend) { makeDepends << ' ' << lineContinue << ' ' << dependee; } else { @@ -358,7 +355,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, if (!required->second.empty()) { // This module is known. Depend on its timestamp file. std::string stampFile = cmSystemTools::ConvertToOutputPath( - this->MaybeConvertToRelativePath(binDir, required->second)); + this->LocalGenerator->MaybeRelativeToTopBinDir(required->second)); makeDepends << obj_m << ": " << stampFile << '\n'; } else { // This module is not known to CMake. Try to locate it where @@ -366,7 +363,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, std::string module; if (this->FindModule(i, module)) { module = cmSystemTools::ConvertToOutputPath( - this->MaybeConvertToRelativePath(binDir, module)); + this->LocalGenerator->MaybeRelativeToTopBinDir(module)); makeDepends << obj_m << ": " << module << '\n'; } } @@ -385,10 +382,10 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, // try various cases for the real mod file name. std::string modFile = cmStrCat(mod_dir, '/', i); modFile = this->LocalGenerator->ConvertToOutputFormat( - this->MaybeConvertToRelativePath(binDir, modFile), + this->LocalGenerator->MaybeRelativeToTopBinDir(modFile), cmOutputConverter::SHELL); std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp"); - stampFile = this->MaybeConvertToRelativePath(binDir, stampFile); + stampFile = this->LocalGenerator->MaybeRelativeToTopBinDir(stampFile); std::string const stampFileForShell = this->LocalGenerator->ConvertToOutputFormat(stampFile, cmOutputConverter::SHELL); @@ -423,7 +420,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, // the target finishes building. std::string driver = cmStrCat(this->TargetDirectory, "/build"); driver = cmSystemTools::ConvertToOutputPath( - this->MaybeConvertToRelativePath(binDir, driver)); + this->LocalGenerator->MaybeRelativeToTopBinDir(driver)); makeDepends << driver << ": " << obj_m << ".provides.build\n"; } @@ -679,9 +676,3 @@ bool cmDependsFortran::ModulesDiffer(const std::string& modFile, // content. return cmFortranStreamsDiffer(finModFile, finStampFile); } - -std::string cmDependsFortran::MaybeConvertToRelativePath( - std::string const& base, std::string const& path) -{ - return this->LocalGenerator->MaybeConvertToRelativePath(base, path); -} diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index e377a2c3384..0d407bc3bc0 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -85,8 +85,4 @@ class cmDependsFortran : public cmDepends // Internal implementation details. std::unique_ptr Internal; - -private: - std::string MaybeConvertToRelativePath(std::string const& base, - std::string const& path); }; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 70d373c41bc..672089c7362 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -916,8 +916,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // and UTILITY targets for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { const auto& targets = lgen->GetGeneratorTargets(); - std::string subdir = lgen->MaybeConvertToRelativePath( - this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory()); + std::string subdir = + lgen->MaybeRelativeToTopBinDir(lgen->GetCurrentBinaryDirectory()); if (subdir == ".") { subdir.clear(); } diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 9a17d07d7da..32238e4bd32 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -159,13 +159,11 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, const std::string& config) { std::string outpath; - std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory(); if (this->TagType != GhsMultiGpj::SUBPROJECT) { // set target binary file destination outpath = this->GeneratorTarget->GetDirectory(config); - outpath = - this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath); + outpath = this->LocalGenerator->MaybeRelativeToCurBinDir(outpath); /* clang-format off */ fout << " :binDirRelative=\"" << outpath << "\"\n" " -o \"" << this->TargetNameReal << "\"\n"; @@ -369,7 +367,6 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( // if the command specified a working directory use it. std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory(); - std::string currentBinDir = dir; std::string workingDir = ccg.GetWorkingDirectory(); if (!workingDir.empty()) { dir = workingDir; @@ -427,8 +424,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( // working directory will be the start-output directory. bool had_slash = cmd.find('/') != std::string::npos; if (workingDir.empty()) { - cmd = - this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, cmd); + cmd = this->LocalGenerator->MaybeRelativeToCurBinDir(cmd); } bool has_slash = cmd.find('/') != std::string::npos; if (had_slash && !has_slash) { diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 6937639e833..8cbc8e18d13 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1122,10 +1122,8 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( return f->second; } - const auto& ng = - cm::static_reference_cast(this->LocalGenerators[0]); - std::string const& bin_dir = ng.GetState()->GetBinaryDirectory(); - std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path); + std::string convPath = + this->LocalGenerators[0]->MaybeRelativeToTopBinDir(path); convPath = this->NinjaOutputPath(convPath); #ifdef _WIN32 std::replace(convPath.begin(), convPath.end(), '/', '\\'); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index e28baf3dd8d..837c59fed5e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -318,16 +318,13 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() const auto& lg = cm::static_reference_cast( this->LocalGenerators[0]); - const std::string& currentBinDir = lg.GetCurrentBinaryDirectory(); // Save the list to the cmake file. cmakefileStream << "# The top level Makefile was generated from the following files:\n" << "set(CMAKE_MAKEFILE_DEPENDS\n" << " \"CMakeCache.txt\"\n"; for (std::string const& f : lfiles) { - cmakefileStream << " \"" - << lg.MaybeConvertToRelativePath(currentBinDir, f) - << "\"\n"; + cmakefileStream << " \"" << lg.MaybeRelativeToCurBinDir(f) << "\"\n"; } cmakefileStream << " )\n\n"; @@ -339,17 +336,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() // Set the corresponding makefile in the cmake file. cmakefileStream << "# The corresponding makefile is:\n" << "set(CMAKE_MAKEFILE_OUTPUTS\n" - << " \"" - << lg.MaybeConvertToRelativePath(currentBinDir, - makefileName) + << " \"" << lg.MaybeRelativeToCurBinDir(makefileName) << "\"\n" - << " \"" - << lg.MaybeConvertToRelativePath(currentBinDir, check) - << "\"\n"; + << " \"" << lg.MaybeRelativeToCurBinDir(check) << "\"\n"; cmakefileStream << " )\n\n"; - const std::string& binDir = lg.GetBinaryDirectory(); - // CMake must rerun if a byproduct is missing. cmakefileStream << "# Byproducts of CMake generate step:\n" << "set(CMAKE_MAKEFILE_PRODUCTS\n"; @@ -359,14 +350,12 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() for (const auto& localGen : this->LocalGenerators) { for (std::string const& outfile : localGen->GetMakefile()->GetOutputFiles()) { - cmakefileStream << " \"" - << lg.MaybeConvertToRelativePath(binDir, outfile) + cmakefileStream << " \"" << lg.MaybeRelativeToTopBinDir(outfile) << "\"\n"; } tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(), "/CMakeFiles/CMakeDirectoryInformation.cmake"); - cmakefileStream << " \"" - << localGen->MaybeConvertToRelativePath(binDir, tmpStr) + cmakefileStream << " \"" << localGen->MaybeRelativeToTopBinDir(tmpStr) << "\"\n"; } cmakefileStream << " )\n\n"; @@ -458,9 +447,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2( auto* lg = static_cast(dt.LG); // Begin the directory-level rules section. { - std::string dir = - cmSystemTools::ConvertToOutputPath(lg->MaybeConvertToRelativePath( - lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory())); + std::string dir = cmSystemTools::ConvertToOutputPath( + lg->MaybeRelativeToTopBinDir(lg->GetCurrentBinaryDirectory())); lg->WriteDivider(ruleFileStream); if (lg->IsRootMakefile()) { ruleFileStream << "# Directory level rules for the build root directory"; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 75cd7144375..0c85a044e1e 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -367,7 +367,6 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( { VisualStudioFolders.clear(); - std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); for (cmGeneratorTarget const* target : projectTargets) { if (!target->IsInBuildSystem()) { continue; @@ -390,7 +389,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( if (vcprojName) { cmLocalGenerator* lg = target->GetLocalGenerator(); std::string dir = lg->GetCurrentBinaryDirectory(); - dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir); + dir = root->MaybeRelativeToCurBinDir(dir); if (dir == ".") { dir.clear(); // msbuild cannot handle ".\" prefix } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index dd0ddf5e78c..009d133805a 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -4703,8 +4703,7 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p) std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p) { - return this->CurrentRootGenerator->MaybeConvertToRelativePath( - this->CurrentRootGenerator->GetCurrentBinaryDirectory(), p); + return this->CurrentRootGenerator->MaybeRelativeToCurBinDir(p); } std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p) diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 4ec0c9d9691..50657f6c939 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -27,7 +27,7 @@ cmLocalCommonGenerator::~cmLocalCommonGenerator() = default; std::string cmLocalCommonGenerator::MaybeRelativeToWorkDir( std::string const& path) const { - return this->MaybeConvertToRelativePath(this->WorkingDirectory, path); + return this->MaybeRelativeTo(this->WorkingDirectory, path); } std::string cmLocalCommonGenerator::GetTargetFortranFlags( diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 304b607c51c..ced535dbced 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -351,11 +351,10 @@ void cmLocalGenerator::GenerateTestFiles() } using vec_t = std::vector; vec_t const& children = this->Makefile->GetStateSnapshot().GetChildren(); - std::string parentBinDir = this->GetCurrentBinaryDirectory(); for (cmStateSnapshot const& i : children) { // TODO: Use add_subdirectory instead? std::string outP = i.GetDirectory().GetCurrentBinary(); - outP = this->MaybeConvertToRelativePath(parentBinDir, outP); + outP = this->MaybeRelativeToCurBinDir(outP); outP = cmOutputConverter::EscapeForCMake(outP); fout << "subdirs(" << outP << ")\n"; } @@ -3286,10 +3285,9 @@ std::string cmLocalGenerator::ConstructComment( std::string comment; comment = "Generating "; const char* sep = ""; - std::string currentBinaryDir = this->GetCurrentBinaryDirectory(); for (std::string const& o : ccg.GetOutputs()) { comment += sep; - comment += this->MaybeConvertToRelativePath(currentBinaryDir, o); + comment += this->MaybeRelativeToCurBinDir(o); sep = ", "; } return comment; @@ -3550,15 +3548,13 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( std::string const& fullPath = source.GetFullPath(); // Try referencing the source relative to the source tree. - std::string relFromSource = this->MaybeConvertToRelativePath( - this->GetCurrentSourceDirectory(), fullPath); + std::string relFromSource = this->MaybeRelativeToCurSrcDir(fullPath); assert(!relFromSource.empty()); bool relSource = !cmSystemTools::FileIsFullPath(relFromSource); bool subSource = relSource && relFromSource[0] != '.'; // Try referencing the source relative to the binary tree. - std::string relFromBinary = this->MaybeConvertToRelativePath( - this->GetCurrentBinaryDirectory(), fullPath); + std::string relFromBinary = this->MaybeRelativeToCurBinDir(fullPath); assert(!relFromBinary.empty()); bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary); bool subBinary = relBinary && relFromBinary[0] != '.'; @@ -3673,13 +3669,31 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const return this->StateSnapshot.GetDirectory().GetCurrentSource(); } -std::string cmLocalGenerator::MaybeConvertToRelativePath( +std::string cmLocalGenerator::MaybeRelativeTo( std::string const& local_path, std::string const& remote_path) const { return this->StateSnapshot.GetDirectory().ConvertToRelPathIfContained( local_path, remote_path); } +std::string cmLocalGenerator::MaybeRelativeToTopBinDir( + std::string const& path) const +{ + return this->MaybeRelativeTo(this->GetBinaryDirectory(), path); +} + +std::string cmLocalGenerator::MaybeRelativeToCurBinDir( + std::string const& path) const +{ + return this->MaybeRelativeTo(this->GetCurrentBinaryDirectory(), path); +} + +std::string cmLocalGenerator::MaybeRelativeToCurSrcDir( + std::string const& path) const +{ + return this->MaybeRelativeTo(this->GetCurrentSourceDirectory(), path); +} + std::string cmLocalGenerator::GetTargetDirectory( const cmGeneratorTarget* /*unused*/) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index f59712055bf..5ebf70c85fe 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -464,13 +464,14 @@ class cmLocalGenerator : public cmOutputConverter /** * Convert the given remote path to a relative path with respect to - * the given local path. Both paths must use forward slashes and not - * already be escaped or quoted. + * one of our common work directories. The path must use forward + * slashes and not already be escaped or quoted. * The conversion is skipped if the paths are not both in the source * or both in the binary tree. */ - std::string MaybeConvertToRelativePath(std::string const& local_path, - std::string const& remote_path) const; + std::string MaybeRelativeToTopBinDir(std::string const& path) const; + std::string MaybeRelativeToCurBinDir(std::string const& path) const; + std::string MaybeRelativeToCurSrcDir(std::string const& path) const; /** * Generate a macOS application bundle Info.plist file. @@ -558,6 +559,9 @@ class cmLocalGenerator : public cmOutputConverter cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop); protected: + std::string MaybeRelativeTo(std::string const& local_path, + std::string const& remote_path) const; + // The default implementation ignores the IncludePathStyle and always // uses absolute paths. A generator may override this to use relative // paths in some cases. diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 588f70b4132..475045a16ae 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -60,8 +60,8 @@ void cmLocalNinjaGenerator::Generate() { // Compute the path to use when referencing the current output // directory from the top output directory. - this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); + this->HomeRelativeOutputPath = + this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory()); if (this->HomeRelativeOutputPath == ".") { this->HomeRelativeOutputPath.clear(); } @@ -213,9 +213,8 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()), format); } - return this->ConvertToOutputFormat( - this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path), - format); + return this->ConvertToOutputFormat(this->MaybeRelativeToTopBinDir(path), + format); } // Private methods. @@ -881,8 +880,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( if (!outputs.empty()) { output = outputs[0]; if (ccg.GetWorkingDirectory().empty()) { - output = this->MaybeConvertToRelativePath( - this->GetCurrentBinaryDirectory(), output); + output = this->MaybeRelativeToCurBinDir(output); } output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL); } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 464df685427..4e7562d023b 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -177,8 +177,8 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath() { // Compute the path to use when referencing the current output // directory from the top output directory. - this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); + this->HomeRelativeOutputPath = + this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory()); if (this->HomeRelativeOutputPath == ".") { this->HomeRelativeOutputPath.clear(); } @@ -561,8 +561,8 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule( } // Construct the left hand side of the rule. - std::string tgt = this->ConvertToMakefilePath( - this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target)); + std::string tgt = + this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(target)); const char* space = ""; if (tgt.size() == 1) { @@ -586,11 +586,9 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule( } else { // Split dependencies into multiple rule lines. This allows for // very long dependency lists even on older make implementations. - std::string binDir = this->GetBinaryDirectory(); for (std::string const& depend : depends) { os << tgt << space << ": " - << this->ConvertToMakefilePath( - this->MaybeConvertToRelativePath(binDir, depend)) + << this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(depend)) << '\n'; } } @@ -968,7 +966,6 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // Add each command line to the set of commands. std::vector commands1; - std::string currentBinDir = this->GetCurrentBinaryDirectory(); for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) { // Build the command line in a single string. std::string cmd = ccg.GetCommand(c); @@ -993,7 +990,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // working directory will be the start-output directory. bool had_slash = cmd.find('/') != std::string::npos; if (workingDir.empty()) { - cmd = this->MaybeConvertToRelativePath(currentBinDir, cmd); + cmd = this->MaybeRelativeToCurBinDir(cmd); } bool has_slash = cmd.find('/') != std::string::npos; if (had_slash && !has_slash) { @@ -1017,8 +1014,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( if (!outputs.empty()) { output = outputs[0]; if (workingDir.empty()) { - output = this->MaybeConvertToRelativePath( - this->GetCurrentBinaryDirectory(), output); + output = this->MaybeRelativeToCurBinDir(output); } output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL); @@ -1097,18 +1093,16 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand( if (!files.empty()) { fout << "file(REMOVE_RECURSE\n"; for (std::string const& file : files) { - std::string fc = this->MaybeConvertToRelativePath(currentBinDir, file); + std::string fc = this->MaybeRelativeToCurBinDir(file); fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n"; } fout << ")\n"; } { - std::string remove = - cmStrCat("$(CMAKE_COMMAND) -P ", - this->ConvertToOutputFormat( - this->MaybeConvertToRelativePath( - this->GetCurrentBinaryDirectory(), cleanfile), - cmOutputConverter::SHELL)); + std::string remove = cmStrCat( + "$(CMAKE_COMMAND) -P ", + this->ConvertToOutputFormat(this->MaybeRelativeToCurBinDir(cleanfile), + cmOutputConverter::SHELL)); commands.push_back(std::move(remove)); } @@ -1146,7 +1140,6 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( } const auto& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0); - std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory(); std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory(); std::string cleanfile = cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake"); @@ -1159,19 +1152,18 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( } fout << "file(REMOVE_RECURSE\n"; for (std::string const& cfl : cleanFiles) { - std::string fc = rootLG->MaybeConvertToRelativePath( - binaryDir, cmSystemTools::CollapseFullPath(cfl, currentBinaryDir)); + std::string fc = rootLG->MaybeRelativeToCurBinDir( + cmSystemTools::CollapseFullPath(cfl, currentBinaryDir)); fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n"; } fout << ")\n"; } // Create command { - std::string remove = - cmStrCat("$(CMAKE_COMMAND) -P ", - this->ConvertToOutputFormat( - rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile), - cmOutputConverter::SHELL)); + std::string remove = cmStrCat( + "$(CMAKE_COMMAND) -P ", + this->ConvertToOutputFormat(rootLG->MaybeRelativeToCurBinDir(cleanfile), + cmOutputConverter::SHELL)); commands.push_back(std::move(remove)); } } @@ -1964,8 +1956,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir)); } for (std::string const& include : includes) { - cmakefileStream << " \"" - << this->MaybeConvertToRelativePath(binaryDir, include) + cmakefileStream << " \"" << this->MaybeRelativeToTopBinDir(include) << "\"\n"; } cmakefileStream << " )\n"; @@ -2004,12 +1995,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( for (auto const& compilerPair : compilerPairs) { for (auto const& src : compilerPair.second) { cmakefileStream << R"( "" ")" - << this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), compilerPair.first) + << this->MaybeRelativeToTopBinDir(compilerPair.first) << R"(" "custom" ")" - << this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), src) - << "\"\n"; + << this->MaybeRelativeToTopBinDir(src) << "\"\n"; } } } else { @@ -2018,11 +2006,9 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( for (auto const& compilerPair : compilerPairs) { for (auto const& src : compilerPair.second) { cmakefileStream << " \"" << src << "\" \"" - << this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), compilerPair.first) + << this->MaybeRelativeToTopBinDir(compilerPair.first) << "\" \"" << depFormat << "\" \"" - << this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), compilerPair.first) + << this->MaybeRelativeToTopBinDir(compilerPair.first) << ".d\"\n"; } } @@ -2066,8 +2052,7 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall( // Add the target. if (!tgt.empty()) { // The make target is always relative to the top of the build tree. - std::string tgt2 = - this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), tgt); + std::string tgt2 = this->MaybeRelativeToTopBinDir(tgt); // The target may have been written with windows paths. cmSystemTools::ConvertToOutputSlashes(tgt2); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index cead87b064c..c50cc5dbff1 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -784,8 +784,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( cmProp target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY"); std::string modDir; if (target_mod_dir) { - modDir = this->MaybeConvertToRelativePath( - this->GetCurrentBinaryDirectory(), *target_mod_dir); + modDir = this->MaybeRelativeToCurBinDir(*target_mod_dir); } else { modDir = "."; } @@ -1254,11 +1253,9 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( std::ostream& fout, ItemVector const& libs) { cmLocalVisualStudio7Generator* lg = this->LocalGenerator; - std::string currentBinDir = lg->GetCurrentBinaryDirectory(); for (auto const& lib : libs) { if (lib.IsPath) { - std::string rel = - lg->MaybeConvertToRelativePath(currentBinDir, lib.Value.Value); + std::string rel = lg->MaybeRelativeToCurBinDir(lib.Value.Value); fout << lg->ConvertToXMLOutputPath(rel) << " "; } else if (!lib.Target || lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { @@ -1274,7 +1271,6 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects( // VS < 8 does not support per-config source locations so we // list object library content on the link line instead. cmLocalVisualStudio7Generator* lg = this->LocalGenerator; - std::string currentBinDir = lg->GetCurrentBinaryDirectory(); std::vector objs; gt->GetExternalObjects(objs, configName); @@ -1283,7 +1279,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects( for (cmSourceFile const* obj : objs) { if (!obj->GetObjectLibrary().empty()) { std::string const& objFile = obj->GetFullPath(); - std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile); + std::string rel = lg->MaybeRelativeToCurBinDir(objFile); fout << sep << lg->ConvertToXMLOutputPath(rel); sep = " "; } @@ -1294,7 +1290,6 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories( std::ostream& fout, std::vector const& dirs) { const char* comma = ""; - std::string currentBinDir = this->GetCurrentBinaryDirectory(); for (std::string dir : dirs) { // Remove any trailing slash and skip empty paths. if (dir.back() == '/') { @@ -1306,7 +1301,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories( // Switch to a relative path specification if it is shorter. if (cmSystemTools::FileIsFullPath(dir)) { - std::string rel = this->MaybeConvertToRelativePath(currentBinDir, dir); + std::string rel = this->MaybeRelativeToCurBinDir(dir); if (rel.size() < dir.size()) { dir = rel; } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 6d6ed9f400a..002f484bcbb 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -207,10 +207,8 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( } if (workingDirectory.empty()) { - script += - this->ConvertToOutputFormat(this->MaybeConvertToRelativePath( - this->GetCurrentBinaryDirectory(), cmd), - cmOutputConverter::SHELL); + script += this->ConvertToOutputFormat( + this->MaybeRelativeToCurBinDir(cmd), cmOutputConverter::SHELL); } else { script += this->ConvertToOutputFormat(cmd.c_str(), SHELL); } diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 6783341095d..2940b8b8e9c 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -104,13 +104,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = - cmStrCat("Linking CUDA device code ", - this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - this->DeviceLinkObject), - cmOutputConverter::SHELL)); + std::string buildEcho = cmStrCat( + "Linking CUDA device code ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject), + cmOutputConverter::SHELL)); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -152,8 +150,8 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( // Construct a list of files associated with this executable that // may need to be cleaned. std::vector exeCleanFiles; - exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput)); + exeCleanFiles.push_back( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput)); // Determine whether a link script will be used. bool useLinkScript = this->GlobalGenerator->GetUseLinkScript(); @@ -203,17 +201,14 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), + this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir), cmOutputConverter::SHELL); cmOutputConverter::OutputFormat output = (useWatcomQuote) ? cmOutputConverter::WATCOMQUOTE : cmOutputConverter::SHELL; std::string target = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput), - output); + this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output); std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(this->GetConfigName()); @@ -330,18 +325,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) targetFullPathPDB, cmOutputConverter::SHELL); // Convert to the output path to use in constructing commands. std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath), cmOutputConverter::SHELL); std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal), cmOutputConverter::SHELL); std::string targetOutPathImport = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - targetFullPathImport), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport), cmOutputConverter::SHELL); // Get the language to use for linking this executable. @@ -436,36 +427,34 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct a list of files associated with this executable that // may need to be cleaned. std::vector exeCleanFiles; - exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath)); + exeCleanFiles.push_back( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath)); #ifdef _WIN32 // There may be a manifest file for this target. Add it to the // clean set just in case. - exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), + exeCleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir( targetFullPath + ".manifest")); #endif if (this->TargetNames.Real != this->TargetNames.Output) { - exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal)); + exeCleanFiles.push_back( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal)); } if (!this->TargetNames.ImportLibrary.empty()) { - exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - targetFullPathImport)); + exeCleanFiles.push_back( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( this->GetConfigName(), targetFullPathImport, implib)) { - exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); + exeCleanFiles.push_back( + this->LocalGenerator->MaybeRelativeToCurBinDir(implib)); } } // List the PDB for cleaning only when the whole target is // cleaned. We do not want to delete the .pdb file just before // linking the target. - this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB)); + this->CleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB)); // Add the pre-build and pre-link rules building but not when relinking. if (!relink) { @@ -529,8 +518,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) if (!this->DeviceLinkObject.empty()) { buildObjs += " " + this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), + this->LocalGenerator->MaybeRelativeToCurBinDir( this->DeviceLinkObject), cmOutputConverter::SHELL); } @@ -549,16 +537,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), + this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir), cmOutputConverter::SHELL); vars.ObjectDir = objectDir.c_str(); cmOutputConverter::OutputFormat output = (useWatcomQuote) ? cmOutputConverter::WATCOMQUOTE : cmOutputConverter::SHELL; std::string target = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal), output); vars.Target = target.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 5e4f03d0c71..f96bcdee40e 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -250,13 +250,11 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = - cmStrCat("Linking CUDA device code ", - this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - this->DeviceLinkObject), - cmOutputConverter::SHELL)); + std::string buildEcho = cmStrCat( + "Linking CUDA device code ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeRelativeToCurBinDir(this->DeviceLinkObject), + cmOutputConverter::SHELL)); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -293,8 +291,8 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( // Clean files associated with this library. std::set libCleanFiles; - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput)); + libCleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput)); // Determine whether a link script will be used. bool useLinkScript = this->GlobalGenerator->GetUseLinkScript(); @@ -342,14 +340,11 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), + this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir), cmOutputConverter::SHELL); std::string target = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput), - output); + this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output); std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(this->GetConfigName()); @@ -519,22 +514,17 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( targetFullPathPDB, cmOutputConverter::SHELL); std::string targetOutPath = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath), cmOutputConverter::SHELL); std::string targetOutPathSO = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathSO), cmOutputConverter::SHELL); std::string targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal), cmOutputConverter::SHELL); std::string targetOutPathImport = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - targetFullPathImport), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport), cmOutputConverter::SHELL); this->NumberOfProgressActions++; @@ -567,8 +557,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Clean files associated with this library. std::set libCleanFiles; - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal)); + libCleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal)); std::vector commands1; // Add a command to remove any existing files for this library. @@ -584,38 +574,36 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } if (this->TargetNames.Output != this->TargetNames.Real) { - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath)); + libCleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPath)); } if (this->TargetNames.SharedObject != this->TargetNames.Real && this->TargetNames.SharedObject != this->TargetNames.Output) { - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO)); + libCleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathSO)); } if (!this->TargetNames.ImportLibrary.empty()) { - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - targetFullPathImport)); + libCleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( this->GetConfigName(), targetFullPathImport, implib)) { - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); + libCleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(implib)); } } // List the PDB for cleaning only when the whole target is // cleaned. We do not want to delete the .pdb file just before // linking the target. - this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB)); + this->CleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathPDB)); #ifdef _WIN32 // There may be a manifest file for this target. Add it to the // clean set just in case. if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) { - libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), + libCleanFiles.insert(this->LocalGenerator->MaybeRelativeToCurBinDir( targetFullPath + ".manifest")); } #endif @@ -723,8 +711,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( if (!this->DeviceLinkObject.empty()) { buildObjs += " " + this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), + this->LocalGenerator->MaybeRelativeToCurBinDir( this->DeviceLinkObject), cmOutputConverter::SHELL); } @@ -765,8 +752,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), + this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir), cmOutputConverter::SHELL); vars.ObjectDir = objectDir.c_str(); @@ -774,8 +760,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( ? cmOutputConverter::WATCOMQUOTE : cmOutputConverter::SHELL; std::string target = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal), output); vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); @@ -839,8 +824,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // only occur on archives which have CUDA_RESOLVE_DEVICE_SYMBOLS enabled if (!this->DeviceLinkObject.empty()) { object_strings.push_back(this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), + this->LocalGenerator->MaybeRelativeToCurBinDir( this->DeviceLinkObject), cmOutputConverter::SHELL)); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index bec7805c4bf..1cc843467d9 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -218,15 +218,12 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); - // Look for ISPC extra object files generated by this target auto ispcAdditionalObjs = this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName()); for (std::string const& ispcObj : ispcAdditionalObjs) { - this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( - currentBinDir, ispcObj)); + this->CleanFiles.insert( + this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj)); } // add custom commands to the clean rules? @@ -251,14 +248,12 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() const std::vector& outputs = ccg.GetOutputs(); for (std::string const& output : outputs) { this->CleanFiles.insert( - this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, - output)); + this->LocalGenerator->MaybeRelativeToCurBinDir(output)); } const std::vector& byproducts = ccg.GetByproducts(); for (std::string const& byproduct : byproducts) { this->CleanFiles.insert( - this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, - byproduct)); + this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct)); } } } @@ -279,8 +274,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() const std::vector& byproducts = beg.GetByproducts(); for (std::string const& byproduct : byproducts) { this->CleanFiles.insert( - this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, - byproduct)); + this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct)); } } } @@ -327,8 +321,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << "# Include any dependencies generated for this target.\n" << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull)) + this->LocalGenerator->MaybeRelativeToTopBinDir(dependFileNameFull)) << "\n"; std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER"; @@ -336,14 +329,14 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->Makefile->IsOn(depsUseCompiler)) { std::string compilerDependFile = cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make"); - *this->BuildFileStream - << "# Include any dependencies generated by the " - "compiler for this target.\n" - << this->GlobalGenerator->IncludeDirective << " " << root - << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), compilerDependFile)) - << "\n\n"; + *this->BuildFileStream << "# Include any dependencies generated by the " + "compiler for this target.\n" + << this->GlobalGenerator->IncludeDirective << " " + << root + << cmSystemTools::ConvertToOutputPath( + this->LocalGenerator->MaybeRelativeToTopBinDir( + compilerDependFile)) + << "\n\n"; // Write an empty dependency file. cmGeneratedFileStream depFileStream( @@ -399,8 +392,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << "# Include the progress variables for this target.\n" << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), + this->LocalGenerator->MaybeRelativeToTopBinDir( this->ProgressFileNameFull)) << "\n\n"; } @@ -423,8 +415,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << "# Include the compile flags for this target's objects.\n" << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), this->FlagFileNameFull)) + this->LocalGenerator->MaybeRelativeToTopBinDir( + this->FlagFileNameFull)) << "\n\n"; } @@ -491,10 +483,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( std::string output = cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input)); this->Generator->CleanFiles.insert( - this->Generator->LocalGenerator->MaybeConvertToRelativePath( - this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output)); - output = this->Generator->LocalGenerator->MaybeConvertToRelativePath( - this->Generator->LocalGenerator->GetBinaryDirectory(), output); + this->Generator->LocalGenerator->MaybeRelativeToCurBinDir(output)); + output = this->Generator->LocalGenerator->MaybeRelativeToTopBinDir(output); // Create a rule to copy the content into the bundle. std::vector depends; @@ -797,15 +787,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal), cmOutputConverter::SHELL); targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat( targetFullPathPDB, cmOutputConverter::SHELL); targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - targetFullPathCompilePDB), + this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathCompilePDB), cmOutputConverter::SHELL); if (this->LocalGenerator->IsMinGWMake() && @@ -834,14 +821,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.Object = shellObj.c_str(); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), + this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir), cmOutputConverter::SHELL); vars.ObjectDir = objectDir.c_str(); std::string objectFileDir = cmSystemTools::GetFilenamePath(obj); objectFileDir = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectFileDir), + this->LocalGenerator->MaybeRelativeToCurBinDir(objectFileDir), cmOutputConverter::SHELL); vars.ObjectFileDir = objectFileDir.c_str(); vars.Flags = flags.c_str(); @@ -865,8 +850,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( if (compilerGenerateDeps) { dependencyTarget = this->LocalGenerator->EscapeForShell( this->LocalGenerator->ConvertToMakefilePath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), relativeObj))); + this->LocalGenerator->MaybeRelativeToTopBinDir(relativeObj))); vars.DependencyTarget = dependencyTarget.c_str(); auto depFile = cmStrCat(obj, ".d"); @@ -875,8 +859,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.DependencyFile = shellDependencyFile.c_str(); this->CleanFiles.insert(depFile); - dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), + dependencyTimestamp = this->LocalGenerator->MaybeRelativeToTopBinDir( cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")); } @@ -1302,12 +1285,11 @@ bool cmMakefileTargetGenerator::WriteMakeRule( // For multiple outputs, make the extra ones depend on the first one. std::vector const output_depends(1, outputs[0]); - std::string binDir = this->LocalGenerator->GetBinaryDirectory(); for (std::string const& output : cmMakeRange(outputs).advance(1)) { // Touch the extra output so "make" knows that it was updated, // but only if the output was actually created. std::string const out = this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath(binDir, output), + this->LocalGenerator->MaybeRelativeToTopBinDir(output), cmOutputConverter::SHELL); std::vector output_commands; @@ -1515,14 +1497,12 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( const std::string objectDir = this->GeneratorTarget->ObjectDirectory; const std::string relObjectDir = - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir); + this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir); // Construct a list of files associated with this executable that // may need to be cleaned. std::vector cleanFiles; - cleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), output)); + cleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(output)); std::string profiles; std::vector fatbinaryDepends; @@ -1547,8 +1527,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( // generate it only on the first invocation to reduce overhead. if (fatbinaryDepends.size() == 1) { std::string registerFileRel = - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), registerFile); + this->LocalGenerator->MaybeRelativeToCurBinDir(registerFile); registerFileCmd = cmStrCat(" --register-link-binaries=", registerFileRel); cleanFiles.push_back(registerFileRel); @@ -1572,8 +1551,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( const std::string fatbinaryOutput = cmStrCat(objectDir, "cmake_cuda_fatbin.h"); const std::string fatbinaryOutputRel = - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), fatbinaryOutput); + this->LocalGenerator->MaybeRelativeToCurBinDir(fatbinaryOutput); this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, fatbinaryOutputRel, fatbinaryDepends, @@ -1640,8 +1618,7 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( if (!ccg.GetCC().GetDepfile().empty()) { // Add dependency over timestamp file for dependencies management auto dependTimestamp = cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), + this->LocalGenerator->MaybeRelativeToTopBinDir( cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"))); depends.push_back(dependTimestamp); @@ -1743,11 +1720,8 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( << this->GeneratorTarget->GetName() << "\n" << variableNameExternal << " ="; /* clang-format on */ - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); for (std::string const& obj : this->ExternalObjects) { - object = - this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, obj); + object = this->LocalGenerator->MaybeRelativeToCurBinDir(obj); *this->BuildFileStream << " " << lineContinue; *this->BuildFileStream << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( @@ -1847,8 +1821,8 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule( this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget); std::string buildTargetRuleName = cmStrCat(dir, relink ? "/preinstall" : "/build"); - buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName); + buildTargetRuleName = + this->LocalGenerator->MaybeRelativeToTopBinDir(buildTargetRuleName); // Build the list of target outputs to drive. std::vector depends; @@ -1985,13 +1959,12 @@ void cmMakefileTargetGenerator::CreateLinkScript( } // Create the makefile command to invoke the link script. - std::string link_command = cmStrCat( - "$(CMAKE_COMMAND) -E cmake_link_script ", - this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName), - cmOutputConverter::SHELL), - " --verbose=$(VERBOSE)"); + std::string link_command = + cmStrCat("$(CMAKE_COMMAND) -E cmake_link_script ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeRelativeToCurBinDir(linkScriptName), + cmOutputConverter::SHELL), + " --verbose=$(VERBOSE)"); makefile_commands.push_back(std::move(link_command)); makefile_depends.push_back(std::move(linkScriptName)); } @@ -2233,14 +2206,12 @@ void cmMakefileTargetGenerator::GenDefFile( this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL), " -E __create_def ", this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile), + this->LocalGenerator->MaybeRelativeToCurBinDir(mdi->DefFile), cmOutputConverter::SHELL), ' '); std::string objlist_file = mdi->DefFile + ".objs"; cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), + this->LocalGenerator->MaybeRelativeToCurBinDir(objlist_file), cmOutputConverter::SHELL); cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); if (cmNonempty(nm_executable)) { diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index a885b171684..7f854ee6e64 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -48,8 +48,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() << "# Include any custom commands dependencies for this target.\n" << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), dependFile)) + this->LocalGenerator->MaybeRelativeToTopBinDir(dependFile)) << "\n\n"; if (!cmSystemTools::FileExists(dependFile)) { // Write an empty dependency file. @@ -78,8 +77,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() << "# Include the progress variables for this target.\n" << this->GlobalGenerator->IncludeDirective << " " << root << cmSystemTools::ConvertToOutputPath( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetBinaryDirectory(), + this->LocalGenerator->MaybeRelativeToTopBinDir( this->ProgressFileNameFull)) << "\n\n"; } diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 6e0366c2ba2..6927300ce3f 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -40,10 +40,9 @@ void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout, const cmLocalGenerator& lg, const cmGccDepfileContent& content) { - const auto& binDir = lg.GetBinaryDirectory(); std::function formatPath = - [&lg, &binDir](const std::string& path) -> std::string { - return lg.MaybeConvertToRelativePath(binDir, path); + [&lg](const std::string& path) -> std::string { + return lg.MaybeRelativeToTopBinDir(path); }; if (lg.GetGlobalGenerator()->GetName() == "Xcode") { // full paths must be preserved for Xcode compliance @@ -93,8 +92,6 @@ std::string ConvertToTLogOutputPath(const std::string& path) void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg, const cmGccDepfileContent& content) { - const auto& binDir = lg.GetBinaryDirectory(); - for (auto const& dep : content) { fout << '^'; bool first = true; @@ -103,13 +100,11 @@ void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg, fout << '|'; } first = false; - fout << ConvertToTLogOutputPath( - lg.MaybeConvertToRelativePath(binDir, rule)); + fout << ConvertToTLogOutputPath(lg.MaybeRelativeToTopBinDir(rule)); } fout << "\r\n"; for (auto const& path : dep.paths) { - fout << ConvertToTLogOutputPath( - lg.MaybeConvertToRelativePath(binDir, path)) + fout << ConvertToTLogOutputPath(lg.MaybeRelativeToTopBinDir(path)) << "\r\n"; } } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 12a3679858f..a7a908e610f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3356,8 +3356,6 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( // cmLinkLineDeviceComputer cmComputeLinkInformation& cli = *pcli; std::vector libVec; - const std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); const auto& libs = cli.GetItems(); for (cmComputeLinkInformation::Item const& l : libs) { @@ -3394,8 +3392,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( } if (l.IsPath) { - std::string path = this->LocalGenerator->MaybeConvertToRelativePath( - currentBinDir, l.Value.Value); + std::string path = + this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); if (!cmVS10IsTargetsFile(l.Value.Value)) { libVec.push_back(path); @@ -3946,12 +3944,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions( cmComputeLinkInformation& cli = *pcli; using ItemVector = cmComputeLinkInformation::ItemVector; const ItemVector& libs = cli.GetItems(); - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmComputeLinkInformation::Item const& l : libs) { if (l.IsPath && cmVS10IsTargetsFile(l.Value.Value)) { - std::string path = this->LocalGenerator->MaybeConvertToRelativePath( - currentBinDir, l.Value.Value); + std::string path = + this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); this->AddTargetsFileAndConfigPair(path, config); } @@ -3991,8 +3987,6 @@ void cmVisualStudio10TargetGenerator::AddLibraries( { using ItemVector = cmComputeLinkInformation::ItemVector; ItemVector const& libs = cli.GetItems(); - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmComputeLinkInformation::Item const& l : libs) { if (l.Target) { auto managedType = l.Target->GetManagedType(config); @@ -4035,8 +4029,8 @@ void cmVisualStudio10TargetGenerator::AddLibraries( } if (l.IsPath) { - std::string path = this->LocalGenerator->MaybeConvertToRelativePath( - currentBinDir, l.Value.Value); + std::string path = + this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); if (cmVS10IsTargetsFile(l.Value.Value)) { vsTargetVec.push_back(path); From d346805e419b213230e4ff24d8be0100bee7168d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 May 2021 10:08:35 -0400 Subject: [PATCH 0444/1519] cmLocalCommonGenerator: Select work directory semantically --- Source/cmLocalCommonGenerator.cxx | 22 ++++++++++++++++++---- Source/cmLocalCommonGenerator.h | 14 ++++++++++---- Source/cmLocalNinjaGenerator.cxx | 2 +- Source/cmLocalUnixMakefileGenerator3.cxx | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 50657f6c939..211525a2659 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -9,14 +9,17 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmProperty.h" +#include "cmState.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" class cmGlobalGenerator; cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, - cmMakefile* mf, std::string wd) + cmMakefile* mf, WorkDir wd) : cmLocalGenerator(gg, mf) - , WorkingDirectory(std::move(wd)) + , WorkingDirectory(wd) { this->ConfigNames = this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); @@ -24,10 +27,21 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, cmLocalCommonGenerator::~cmLocalCommonGenerator() = default; +std::string const& cmLocalCommonGenerator::GetWorkingDirectory() const +{ + if (this->WorkingDirectory == WorkDir::TopBin) { + return this->GetState()->GetBinaryDirectory(); + } + return this->StateSnapshot.GetDirectory().GetCurrentBinary(); +} + std::string cmLocalCommonGenerator::MaybeRelativeToWorkDir( std::string const& path) const { - return this->MaybeRelativeTo(this->WorkingDirectory, path); + if (this->WorkingDirectory == WorkDir::TopBin) { + return this->MaybeRelativeToTopBinDir(path); + } + return this->MaybeRelativeToCurBinDir(path); } std::string cmLocalCommonGenerator::GetTargetFortranFlags( @@ -41,7 +55,7 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( // Add a module output directory flag if necessary. std::string mod_dir = - target->GetFortranModuleDirectory(this->WorkingDirectory); + target->GetFortranModuleDirectory(this->GetWorkingDirectory()); if (!mod_dir.empty()) { mod_dir = this->ConvertToOutputFormat( this->MaybeRelativeToWorkDir(mod_dir), cmOutputConverter::SHELL); diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index 72c8e833701..0505c138d14 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -20,9 +20,15 @@ class cmSourceFile; */ class cmLocalCommonGenerator : public cmLocalGenerator { +protected: + enum class WorkDir + { + TopBin, + CurBin, + }; + public: - cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf, - std::string wd); + cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf, WorkDir wd); ~cmLocalCommonGenerator() override; std::vector const& GetConfigNames() const @@ -30,7 +36,7 @@ class cmLocalCommonGenerator : public cmLocalGenerator return this->ConfigNames; } - std::string GetWorkingDirectory() const { return this->WorkingDirectory; } + std::string const& GetWorkingDirectory() const; std::string MaybeRelativeToWorkDir(std::string const& path) const; @@ -42,7 +48,7 @@ class cmLocalCommonGenerator : public cmLocalGenerator cmGeneratorTarget const* gt = nullptr) override; protected: - std::string WorkingDirectory; + WorkDir WorkingDirectory; std::vector ConfigNames; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 475045a16ae..a8570e24997 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -39,7 +39,7 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmMakefile* mf) - : cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory()) + : cmLocalCommonGenerator(gg, mf, WorkDir::TopBin) { } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 4e7562d023b..a652c7b398a 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -110,7 +110,7 @@ class NotInProjectDir cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3( cmGlobalGenerator* gg, cmMakefile* mf) - : cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory()) + : cmLocalCommonGenerator(gg, mf, WorkDir::CurBin) { this->MakefileVariableSize = 0; this->ColorMakefile = false; From f0ffb1e2d4431c705a37410890f38de5f3cf5526 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 May 2021 09:19:44 -0400 Subject: [PATCH 0445/1519] cmGlobalGenerator: Simplify relative path conversion in AddRuleHash Revert commit 204aecdf82 (cmGlobalGenerator: Port configure-time code to cmMakefile., 2015-08-02, v3.4.0-rc1~234^2~8). `AddRuleHash` is generate-time code. --- Source/cmGlobalGenerator.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index cca3bdc0df0..d7da0d33180 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -3027,10 +3027,8 @@ void cmGlobalGenerator::AddRuleHash(const std::vector& outputs, } // Shorten the output name (in expected use case). - cmStateDirectory cmDir = - this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory(); - std::string fname = cmDir.ConvertToRelPathIfContained( - this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]); + std::string fname = + this->LocalGenerators[0]->MaybeRelativeToTopBinDir(outputs[0]); // Associate the hash with this output. this->RuleHashes[fname] = hash; From f6d4fa63f84a88dbc59020b10fbdb7fb02fa1f9d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 13 May 2021 09:47:33 -0400 Subject: [PATCH 0446/1519] cmStateDirectory: Comment relative path top directory selection approach --- Source/cmStateDirectory.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 7f25b4be7a5..a0bfd2820f7 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -44,6 +44,9 @@ void cmStateDirectory::ComputeRelativePathTopSource() std::string result = snapshots.front().GetDirectory().GetCurrentSource(); + // Walk up the buildsystem directory tree to find the highest source + // directory that contains the current source directory and the + // intermediate ancestors. for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) { std::string currentSource = snp.GetDirectory().GetCurrentSource(); if (cmSystemTools::IsSubDirectory(result, currentSource)) { @@ -69,6 +72,9 @@ void cmStateDirectory::ComputeRelativePathTopBinary() std::string result = snapshots.front().GetDirectory().GetCurrentBinary(); + // Walk up the buildsystem directory tree to find the highest binary + // directory that contains the current binary directory and the + // intermediate ancestors. for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) { std::string currentBinary = snp.GetDirectory().GetCurrentBinary(); if (cmSystemTools::IsSubDirectory(result, currentBinary)) { From 1acc937719d92a6319899ea6aaf05924ec7a6774 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 14 May 2021 00:01:09 -0400 Subject: [PATCH 0447/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b7eae3f18fe..8da493f01c2 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210513) +set(CMake_VERSION_PATCH 20210514) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From bb9c69ed7052614546d34d98a9cf1218e4a45bdc Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 10:26:11 -0400 Subject: [PATCH 0448/1519] Utilities/Sphinx: Update man page config for Sphinx 4 Sphinx 4 by default generates `man/#/foo.#`, but older versions generate `man/foo.#` as our install rules expect. Update our Sphinx config file to tell Sphinx 4 to use the old layout. Fixes: #22192 --- Utilities/Sphinx/conf.py.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in index 5def681dc48..c383828bd71 100644 --- a/Utilities/Sphinx/conf.py.in +++ b/Utilities/Sphinx/conf.py.in @@ -53,6 +53,7 @@ for fpath in cmake_manuals: except Exception as e: sys.stderr.write("ERROR: %s\n" % str(e)) man_show_urls = False +man_make_section_directory = False html_show_sourcelink = True html_static_path = ['@conf_path@/static'] From 929c8a7860344b0b2edeefaf09be1ef0b09f4b23 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 14 May 2021 11:42:34 +0200 Subject: [PATCH 0449/1519] INTERFACE_POSITION_INDEPENDENT_CODE must be transitive for OBJECT library Fixes: #22174 --- Source/cmLocalGenerator.cxx | 7 ------- Tests/PositionIndependentTargets/interface/CMakeLists.txt | 3 +++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ced535dbced..c101ff3f15b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2306,13 +2306,6 @@ void cmLocalGenerator::AddCMP0018Flags(std::string& flags, if (this->GetShouldUseOldFlags(shared, lang)) { this->AddSharedFlags(flags, lang, shared); } else { - if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) { - this->AddPositionIndependentFlags(flags, lang, targetType); - } - return; - } - if (target->GetLinkInterfaceDependentBoolProperty( "POSITION_INDEPENDENT_CODE", config)) { this->AddPositionIndependentFlags(flags, lang, targetType); diff --git a/Tests/PositionIndependentTargets/interface/CMakeLists.txt b/Tests/PositionIndependentTargets/interface/CMakeLists.txt index 65f3b767ed8..90186a38180 100644 --- a/Tests/PositionIndependentTargets/interface/CMakeLists.txt +++ b/Tests/PositionIndependentTargets/interface/CMakeLists.txt @@ -12,6 +12,9 @@ set_property(TARGET sharedlib PROPERTY DEFINE_SYMBOL PIC_TEST_BUILD_DLL) add_executable(test_iface_via_shared "${CMAKE_CURRENT_SOURCE_DIR}/../pic_main.cpp") target_link_libraries(test_iface_via_shared sharedlib) +add_library(objectlib OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/../pic_lib.cpp") +target_link_libraries(objectlib piciface) + add_library(sharedlibpic SHARED "${CMAKE_CURRENT_SOURCE_DIR}/../pic_lib.cpp") set_property(TARGET sharedlibpic PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON) set_property(TARGET sharedlibpic PROPERTY DEFINE_SYMBOL PIC_TEST_BUILD_DLL) From 639a6bd4c75740d339c8d28f5aba758a0fe11664 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 15 May 2021 00:01:09 -0400 Subject: [PATCH 0450/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8da493f01c2..26ce362eb25 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210514) +set(CMake_VERSION_PATCH 20210515) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b00a171b2b07d1644eba5c34a8679c6bb368cda7 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sat, 15 May 2021 15:26:01 +1000 Subject: [PATCH 0451/1519] Help: Clarify calling cmake_minimum_required() inside a function Fixes: #21519 --- Help/command/cmake_minimum_required.rst | 9 +++++++-- Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst index 2cc3cfe5ba3..d159770492f 100644 --- a/Help/command/cmake_minimum_required.rst +++ b/Help/command/cmake_minimum_required.rst @@ -40,8 +40,13 @@ with an error instead of just a warning. they may affect. See also policy :policy:`CMP0000`. Calling ``cmake_minimum_required()`` inside a :command:`function` - limits some effects to the function scope when invoked. Such calls - should not be made with the intention of having global effects. + limits some effects to the function scope when invoked. For example, + the :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable won't be set + in the calling scope. Functions do not introduce their own policy + scope though, so policy settings of the caller *will* be affected + (see below). Due to this mix of things that do and do not affect the + calling scope, calling ``cmake_minimum_required()`` inside a function + is generally discouraged. .. _`Policy Settings`: diff --git a/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst b/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst index f466468d812..8d6b533692d 100644 --- a/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst +++ b/Help/variable/CMAKE_MINIMUM_REQUIRED_VERSION.rst @@ -2,4 +2,5 @@ CMAKE_MINIMUM_REQUIRED_VERSION ------------------------------ The ```` version of CMake given to the most recent call to the -:command:`cmake_minimum_required(VERSION)` command. +:command:`cmake_minimum_required(VERSION)` command in the current +variable scope or any parent variable scope. From b20c1f4880aa7fb764f4e2a47b92fca846e84941 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sat, 15 May 2021 16:23:54 +1000 Subject: [PATCH 0452/1519] Help: Make SHELL option examples more generic Comments at the bottom of the docs for add_compile_options() and target_compile_options() recommend using other commands if setting compiler definitions. Change the examples we use for the SHELL: functionality to use -option instead of -D so that we don't violate our own recommendations. This also makes the examples more appropriate for use with link options as well. Tweak the wording to not specify the type of option being discussed. This will already be clear from the page the text is included into and it avoids naming unrelated option types for the given page. --- Help/command/OPTIONS_SHELL.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Help/command/OPTIONS_SHELL.txt b/Help/command/OPTIONS_SHELL.txt index 4051ffe16ee..7f03f4e081e 100644 --- a/Help/command/OPTIONS_SHELL.txt +++ b/Help/command/OPTIONS_SHELL.txt @@ -1,11 +1,12 @@ -The final set of compile or link options used for a target is constructed by +The final set of options used for a target is constructed by accumulating options from the current target and the usage requirements of its dependencies. The set of options is de-duplicated to avoid repetition. .. versionadded:: 3.12 While beneficial for individual options, the de-duplication step can break - up option groups. For example, ``-D A -D B`` becomes ``-D A B``. One may - specify a group of options using shell-like quoting along with a ``SHELL:`` - prefix. The ``SHELL:`` prefix is dropped, and the rest of the option string - is parsed using the :command:`separate_arguments` ``UNIX_COMMAND`` mode. - For example, ``"SHELL:-D A" "SHELL:-D B"`` becomes ``-D A -D B``. + up option groups. For example, ``-option A -option B`` becomes + ``-option A B``. One may specify a group of options using shell-like + quoting along with a ``SHELL:`` prefix. The ``SHELL:`` prefix is dropped, + and the rest of the option string is parsed using the + :command:`separate_arguments` ``UNIX_COMMAND`` mode. For example, + ``"SHELL:-option A" "SHELL:-option B"`` becomes ``-option A -option B``. From 2eba7d75248142483107ca0194c718f4a9f1796d Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sat, 15 May 2021 16:12:22 +1000 Subject: [PATCH 0453/1519] Help: Add SHELL, LINKER and host/device discussions to property docs Section headings are also added for each common block to help guide the reader and improve navigation. Fixes: #21640 --- Help/command/DEVICE_LINK_OPTIONS.txt | 2 ++ Help/command/LINK_OPTIONS_LINKER.txt | 3 +++ Help/command/OPTIONS_SHELL.txt | 3 +++ Help/prop_tgt/COMPILE_OPTIONS.rst | 2 ++ Help/prop_tgt/LINK_OPTIONS.rst | 6 ++++++ Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst | 2 ++ 6 files changed, 18 insertions(+) diff --git a/Help/command/DEVICE_LINK_OPTIONS.txt b/Help/command/DEVICE_LINK_OPTIONS.txt index 1297cd0547a..3d50208163e 100644 --- a/Help/command/DEVICE_LINK_OPTIONS.txt +++ b/Help/command/DEVICE_LINK_OPTIONS.txt @@ -1,3 +1,5 @@ +Host And Device Specific Link Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.18 When a device link step is involved, which is controlled by diff --git a/Help/command/LINK_OPTIONS_LINKER.txt b/Help/command/LINK_OPTIONS_LINKER.txt index 3f66181befa..e71e5ea25dc 100644 --- a/Help/command/LINK_OPTIONS_LINKER.txt +++ b/Help/command/LINK_OPTIONS_LINKER.txt @@ -1,3 +1,6 @@ +Handling Compiler Driver Differences +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + To pass options to the linker tool, each compiler driver has its own syntax. The ``LINKER:`` prefix and ``,`` separator can be used to specify, in a portable way, options to pass to the linker tool. ``LINKER:`` is replaced by the diff --git a/Help/command/OPTIONS_SHELL.txt b/Help/command/OPTIONS_SHELL.txt index 7f03f4e081e..4171f016272 100644 --- a/Help/command/OPTIONS_SHELL.txt +++ b/Help/command/OPTIONS_SHELL.txt @@ -1,3 +1,6 @@ +Option De-duplication +^^^^^^^^^^^^^^^^^^^^^ + The final set of options used for a target is constructed by accumulating options from the current target and the usage requirements of its dependencies. The set of options is de-duplicated to avoid repetition. diff --git a/Help/prop_tgt/COMPILE_OPTIONS.rst b/Help/prop_tgt/COMPILE_OPTIONS.rst index 0cd68361041..4bc190abc03 100644 --- a/Help/prop_tgt/COMPILE_OPTIONS.rst +++ b/Help/prop_tgt/COMPILE_OPTIONS.rst @@ -15,3 +15,5 @@ Contents of ``COMPILE_OPTIONS`` 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. + +.. include:: ../command/OPTIONS_SHELL.txt diff --git a/Help/prop_tgt/LINK_OPTIONS.rst b/Help/prop_tgt/LINK_OPTIONS.rst index 8c0dfc42667..27eadf92dbb 100644 --- a/Help/prop_tgt/LINK_OPTIONS.rst +++ b/Help/prop_tgt/LINK_OPTIONS.rst @@ -28,3 +28,9 @@ for more on defining buildsystem properties. .. note:: This property must be used in preference to :prop_tgt:`LINK_FLAGS` property. + +.. include:: ../command/DEVICE_LINK_OPTIONS.txt + +.. include:: ../command/OPTIONS_SHELL.txt + +.. include:: ../command/LINK_OPTIONS_LINKER.txt diff --git a/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst b/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst index 2f4a3baab3b..f5d943723ba 100644 --- a/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst +++ b/Help/prop_tgt/STATIC_LIBRARY_OPTIONS.rst @@ -20,3 +20,5 @@ for more on defining buildsystem properties. This property must be used in preference to :prop_tgt:`STATIC_LIBRARY_FLAGS` property. + +.. include:: ../command/OPTIONS_SHELL.txt From 49975358fc87b2374f446562c939891ae18cb1a0 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 16 May 2021 00:01:06 -0400 Subject: [PATCH 0454/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 26ce362eb25..a35202e73ec 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210515) +set(CMake_VERSION_PATCH 20210516) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From cf3bc271d1637d71209e4b5aa4126b5a6ccf57e0 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 16 May 2021 20:28:00 +1000 Subject: [PATCH 0455/1519] Help: Clarify details passed to ExternalProject configure and build Fixes: #22116 --- Modules/ExternalProject.cmake | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 45b6124de06..026d1fc4647 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -456,9 +456,16 @@ External Project Definition overridden if required. ``CONFIGURE_COMMAND ...`` - The default configure command runs CMake with options based on the main - project. For non-CMake external projects, the ``CONFIGURE_COMMAND`` - option must be used to override this behavior + The default configure command runs CMake with a few options based on + the main project. The options added are typically only those needed to + use the same generator as the main project, but the ``CMAKE_GENERATOR`` + option can be given to override this. The project is responsible for + adding any toolchain details, flags or other settings it wants to + re-use from the main project or otherwise specify (see ``CMAKE_ARGS``, + ``CMAKE_CACHE_ARGS`` and ``CMAKE_CACHE_DEFAULT_ARGS`` below). + + For non-CMake external projects, the ``CONFIGURE_COMMAND`` option must + be used to override the default configure command (:manual:`generator expressions ` are supported). For projects that require no configure step, specify this option with an empty string as the command to execute. @@ -564,6 +571,16 @@ External Project Definition default build step. This can be overridden with custom build commands if required. + If both the main project and the external project use make as their build + tool, the build step of the external project is invoked as a recursive + make using ``$(MAKE)``. This will communicate some build tool settings + from the main project to the external project. If either the main project + or external project is not using make, no build tool settings will be + passed to the external project other than those established by the + configure step (i.e. running ``ninja -v`` in the main project will not + pass ``-v`` to the external project's build step, even if it also uses + ``ninja`` as its build tool). + ``BUILD_COMMAND ...`` Overrides the default build command (:manual:`generator expressions ` are From 33185217b064efafb8f185e57c96e615ab0ae2fe Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 17 May 2021 00:01:11 -0400 Subject: [PATCH 0456/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a35202e73ec..ee9a5f9d210 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210516) +set(CMake_VERSION_PATCH 20210517) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d8d0f3ec377380af07b3185e82a4d853f556e4f9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 11:46:48 -0400 Subject: [PATCH 0457/1519] Makefiles: Remove non-functioning relative path conversion In CMake 3.6 and below, running cmake --build . --target "$(pwd)/SomeTarget" with a Makefiles generator automatically converted the target name and invoked `make SomeTarget`. This made the build command work even though make "$(pwd)/SomeTarget" would fail. This behavior was not implemented for any other generators, and does not make sense because `cmake --build` is supposed to be a thin wrapper around the native build tool. It has also been broken since commit 8d47a20f13 (cmOutputConverter: use new ConvertToRelativePath signature internally, 2016-06-16, v3.7.0-rc1~90^2~1) because cmState's relative path conversion logic is not initialized in `cmake --build`. Remove the non-functioning code. --- Source/cmGlobalUnixMakefileGenerator3.cxx | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 837c59fed5e..9c3de1eed6f 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -22,7 +22,6 @@ #include "cmOutputConverter.h" #include "cmProperty.h" #include "cmState.h" -#include "cmStateDirectory.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -552,21 +551,6 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( bool fast, int jobs, bool verbose, std::vector const& makeOptions) { - std::unique_ptr mfu; - cmMakefile* mf; - if (!this->Makefiles.empty()) { - mf = this->Makefiles[0].get(); - } else { - cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot(); - snapshot.GetDirectory().SetCurrentSource( - this->CMakeInstance->GetHomeDirectory()); - snapshot.GetDirectory().SetCurrentBinary( - this->CMakeInstance->GetHomeOutputDirectory()); - snapshot.SetDefaultDefinitions(); - mfu = cm::make_unique(this, snapshot); - mf = mfu.get(); - } - GeneratedMakeCommand makeCommand; // Make it possible to set verbosity also from command line @@ -597,9 +581,6 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( if (fast) { tname += "/fast"; } - tname = - mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfContained( - mf->GetState()->GetBinaryDirectory(), tname); cmSystemTools::ConvertToOutputSlashes(tname); makeCommand.Add(std::move(tname)); } From b4f07bfe5ad822b6e07372ceb06485aafc68a774 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 15:27:56 -0400 Subject: [PATCH 0458/1519] cmStateDirectory: Fix comment on relative path top directory selection Fix the comment added by commit f6d4fa63f8 (cmStateDirectory: Comment relative path top directory selection approach, 2021-05-13) to describe the actual behavior. --- Source/cmStateDirectory.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index a0bfd2820f7..804b7760387 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -45,8 +45,7 @@ void cmStateDirectory::ComputeRelativePathTopSource() std::string result = snapshots.front().GetDirectory().GetCurrentSource(); // Walk up the buildsystem directory tree to find the highest source - // directory that contains the current source directory and the - // intermediate ancestors. + // directory that contains the current source directory. for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) { std::string currentSource = snp.GetDirectory().GetCurrentSource(); if (cmSystemTools::IsSubDirectory(result, currentSource)) { @@ -73,8 +72,7 @@ void cmStateDirectory::ComputeRelativePathTopBinary() std::string result = snapshots.front().GetDirectory().GetCurrentBinary(); // Walk up the buildsystem directory tree to find the highest binary - // directory that contains the current binary directory and the - // intermediate ancestors. + // directory that contains the current binary directory. for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) { std::string currentBinary = snp.GetDirectory().GetCurrentBinary(); if (cmSystemTools::IsSubDirectory(result, currentBinary)) { From 2d9109df7cae62138d7d0347f4e90330d053424b Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 15:29:36 -0400 Subject: [PATCH 0459/1519] cmStateDirectory: Remove network path logic from relative path top selection The logic skipping relative paths for build trees on network paths came from commit b5035770bc (BUG: On Windows network paths do not really work..., 2003-12-24, v2.4.0~3517). However, since commit ad4055f3e2 (ENH: Set RelativePathTopSource and RelativePathTopBinary independently ..., 2007-03-07, v2.6.0~2061) we effectively ignore this logic if the build tree is inside the source tree on a network path. Also, it is not clear that logic using `RelativePathTopBinary` is prepared for it to be empty. Remove the logic for now. If a problem comes up, we can choose a new approach. --- Source/cmStateDirectory.cxx | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 804b7760387..31ee4589d70 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -26,10 +26,6 @@ static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES"; void cmStateDirectory::ComputeRelativePathTopSource() { - // Relative path conversion inside the source tree is not used to - // construct relative paths passed to build tools so it is safe to use - // even when the source is a network path. - cmStateSnapshot snapshot = this->Snapshot_; std::vector snapshots; snapshots.push_back(snapshot); @@ -80,14 +76,7 @@ void cmStateDirectory::ComputeRelativePathTopBinary() } } - // The current working directory on Windows cannot be a network - // path. Therefore relative paths cannot work when the binary tree - // is a network path. - if (result.size() < 2 || result.substr(0, 2) != "//") { - this->DirectoryState->RelativePathTopBinary = result; - } else { - this->DirectoryState->RelativePathTopBinary.clear(); - } + this->DirectoryState->RelativePathTopBinary = result; } std::string const& cmStateDirectory::GetCurrentSource() const From ea9b1d36b8cdf384903021d41ca665848895480f Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 14:58:45 -0400 Subject: [PATCH 0460/1519] cmStateDirectory: Clarify relative path top selection logic Re-implement the same algorithm using direct iteration without collecting a vector first. --- Source/cmStateDirectory.cxx | 56 ++++++++++++------------------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 31ee4589d70..140ff0d3087 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -26,57 +26,37 @@ static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES"; void cmStateDirectory::ComputeRelativePathTopSource() { - cmStateSnapshot snapshot = this->Snapshot_; - std::vector snapshots; - snapshots.push_back(snapshot); - while (true) { - snapshot = snapshot.GetBuildsystemDirectoryParent(); - if (snapshot.IsValid()) { - snapshots.push_back(snapshot); - } else { - break; - } - } - - std::string result = snapshots.front().GetDirectory().GetCurrentSource(); - // Walk up the buildsystem directory tree to find the highest source // directory that contains the current source directory. - for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) { - std::string currentSource = snp.GetDirectory().GetCurrentSource(); - if (cmSystemTools::IsSubDirectory(result, currentSource)) { - result = currentSource; + cmStateSnapshot snapshot = this->Snapshot_; + for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent(); + parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) { + if (cmSystemTools::IsSubDirectory( + snapshot.GetDirectory().GetCurrentSource(), + parent.GetDirectory().GetCurrentSource())) { + snapshot = parent; } } - this->DirectoryState->RelativePathTopSource = result; + this->DirectoryState->RelativePathTopSource = + snapshot.GetDirectory().GetCurrentSource(); } void cmStateDirectory::ComputeRelativePathTopBinary() { - cmStateSnapshot snapshot = this->Snapshot_; - std::vector snapshots; - snapshots.push_back(snapshot); - while (true) { - snapshot = snapshot.GetBuildsystemDirectoryParent(); - if (snapshot.IsValid()) { - snapshots.push_back(snapshot); - } else { - break; - } - } - - std::string result = snapshots.front().GetDirectory().GetCurrentBinary(); - // Walk up the buildsystem directory tree to find the highest binary // directory that contains the current binary directory. - for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) { - std::string currentBinary = snp.GetDirectory().GetCurrentBinary(); - if (cmSystemTools::IsSubDirectory(result, currentBinary)) { - result = currentBinary; + cmStateSnapshot snapshot = this->Snapshot_; + for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent(); + parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) { + if (cmSystemTools::IsSubDirectory( + snapshot.GetDirectory().GetCurrentBinary(), + parent.GetDirectory().GetCurrentBinary())) { + snapshot = parent; } } - this->DirectoryState->RelativePathTopBinary = result; + this->DirectoryState->RelativePathTopBinary = + snapshot.GetDirectory().GetCurrentBinary(); } std::string const& cmStateDirectory::GetCurrentSource() const From 5b3a71a83faf913aa4a9644779ae35c9d5eda733 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 12:57:06 -0400 Subject: [PATCH 0461/1519] cmSystemTools: Adopt RelativeIfUnder helper This returns a relative path if it does not start in `../`. --- Source/cmFileAPICodemodel.cxx | 10 +--------- Source/cmSystemTools.cxx | 14 ++++++++++++++ Source/cmSystemTools.h | 6 ++++++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 6b8757c4164..6b358423f14 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -57,15 +57,7 @@ using TargetIndexMapType = std::string RelativeIfUnder(std::string const& top, std::string const& in) { - std::string out; - if (in == top) { - out = "."; - } else if (cmSystemTools::IsSubDirectory(in, top)) { - out = in.substr(top.size() + 1); - } else { - out = in; - } - return out; + return cmSystemTools::RelativeIfUnder(top, in); } class JBTIndex diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ab42810feb2..2fba13f436b 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1491,6 +1491,20 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path, return relative; } +std::string cmSystemTools::RelativeIfUnder(std::string const& top, + std::string const& in) +{ + std::string out; + if (in == top) { + out = "."; + } else if (cmSystemTools::IsSubDirectory(in, top)) { + out = in.substr(top.size() + 1); + } else { + out = in; + } + return out; +} + #ifndef CMAKE_BOOTSTRAP bool cmSystemTools::UnsetEnv(const char* value) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 9f9c493a433..474f591ef55 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -346,6 +346,12 @@ class cmSystemTools : public cmsys::SystemTools static std::string ForceToRelativePath(std::string const& local_path, std::string const& remote_path); + /** + * Express the 'in' path relative to 'top' if it does not start in '../'. + */ + static std::string RelativeIfUnder(std::string const& top, + std::string const& in); + #ifndef CMAKE_BOOTSTRAP /** Remove an environment variable */ static bool UnsetEnv(const char* value); From 4cb6a53bf524258c34440fc573ab6a9a4de0f0b2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 13:09:56 -0400 Subject: [PATCH 0462/1519] cmListFileCache: Simplify relative path conversion in backtraces Printing paths to CMake input files does not need to use the generator-wide relative path conversion rules because we are not actually generating a relative path for the build system that needs to be consistent with anything else. Instead, simply print a relative path if it does not need to start in `../`, and otherwise an absolute path. --- Source/cmListFileCache.cxx | 5 ++--- Source/cmTarget.cxx | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 2b98f204c84..4f7c9594441 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -15,7 +15,6 @@ #include "cmMessageType.h" #include "cmMessenger.h" #include "cmState.h" -#include "cmStateDirectory.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -550,7 +549,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const cmListFileContext lfc = this->TopEntry->Context; cmStateSnapshot bottom = this->GetBottom(); if (!bottom.GetState()->GetIsInTryCompile()) { - lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfContained( + lfc.FilePath = cmSystemTools::RelativeIfUnder( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << (lfc.Line ? " at " : " in ") << lfc; @@ -581,7 +580,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const } cmListFileContext lfc = cur->Context; if (!bottom.GetState()->GetIsInTryCompile()) { - lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfContained( + lfc.FilePath = cmSystemTools::RelativeIfUnder( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } out << " " << lfc << "\n"; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f84d2464042..29e361c3673 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -929,12 +929,10 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const const char* sigString = (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain"); s << "The uses of the " << sigString << " signature are here:\n"; - cmStateDirectory cmDir = - this->impl->Makefile->GetStateSnapshot().GetDirectory(); for (auto const& cmd : this->impl->TLLCommands) { if (cmd.first == sig) { cmListFileContext lfc = cmd.second; - lfc.FilePath = cmDir.ConvertToRelPathIfContained( + lfc.FilePath = cmSystemTools::RelativeIfUnder( this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath); s << " * " << lfc << '\n'; } From d6fe1bdb6d79516a68a88d5f5a11d2531dae7074 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 12:33:34 -0400 Subject: [PATCH 0463/1519] cmLocalGenerator: Localize logic mapping source path to object file name We select an object file name based on the path to its source file. Localize the logic for shortening this via relative paths. It does not need to use the generator-wide relative path conversion rules because we are not actually generating a relative path that needs to be consistent with anything else. --- Source/cmLocalGenerator.cxx | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index c101ff3f15b..79ad46f5dd7 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3532,6 +3532,21 @@ bool cmLocalGenerator::IsNinjaMulti() const return this->GetState()->UseNinjaMulti(); } +namespace { +std::string relativeIfUnder(std::string const& top, std::string const& cur, + std::string const& path) +{ + // Use a path relative to 'cur' if it can be expressed without + // a `../` sequence that leaves 'top'. + if (cmSystemTools::IsSubDirectory(path, cur) || + (cmSystemTools::IsSubDirectory(cur, top) && + cmSystemTools::IsSubDirectory(path, top))) { + return cmSystemTools::ForceToRelativePath(cur, path); + } + return path; +} +} + std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( const cmSourceFile& source, std::string const& dir_max, bool* hasSourceExtension, char const* customOutputExtension) @@ -3541,13 +3556,15 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( std::string const& fullPath = source.GetFullPath(); // Try referencing the source relative to the source tree. - std::string relFromSource = this->MaybeRelativeToCurSrcDir(fullPath); + std::string relFromSource = relativeIfUnder( + this->GetSourceDirectory(), this->GetCurrentSourceDirectory(), fullPath); assert(!relFromSource.empty()); bool relSource = !cmSystemTools::FileIsFullPath(relFromSource); bool subSource = relSource && relFromSource[0] != '.'; // Try referencing the source relative to the binary tree. - std::string relFromBinary = this->MaybeRelativeToCurBinDir(fullPath); + std::string relFromBinary = relativeIfUnder( + this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory(), fullPath); assert(!relFromBinary.empty()); bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary); bool subBinary = relBinary && relFromBinary[0] != '.'; From 24bfdbcffba42fc0aac6ef3b575bd50a180d26ea Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 12:43:35 -0400 Subject: [PATCH 0464/1519] cmLocalGenerator: Remove unused MaybeRelativeToCurSrcDir method With the recent update to `GetObjectFileNameWithoutTarget`, we no longer have any call sites for `MaybeRelativeToCurSrcDir`. It does not make sense for the generator to produce paths relative to the source tree in general, so remove the method. --- Source/cmLocalGenerator.cxx | 6 ------ Source/cmLocalGenerator.h | 1 - 2 files changed, 7 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 79ad46f5dd7..4a35909d7da 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3698,12 +3698,6 @@ std::string cmLocalGenerator::MaybeRelativeToCurBinDir( return this->MaybeRelativeTo(this->GetCurrentBinaryDirectory(), path); } -std::string cmLocalGenerator::MaybeRelativeToCurSrcDir( - std::string const& path) const -{ - return this->MaybeRelativeTo(this->GetCurrentSourceDirectory(), path); -} - std::string cmLocalGenerator::GetTargetDirectory( const cmGeneratorTarget* /*unused*/) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 5ebf70c85fe..1f8970f7c33 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -471,7 +471,6 @@ class cmLocalGenerator : public cmOutputConverter */ std::string MaybeRelativeToTopBinDir(std::string const& path) const; std::string MaybeRelativeToCurBinDir(std::string const& path) const; - std::string MaybeRelativeToCurSrcDir(std::string const& path) const; /** * Generate a macOS application bundle Info.plist file. From 013ec595c8d6971c568cff4f8e457d90a6e8be88 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 14:16:53 -0400 Subject: [PATCH 0465/1519] cmLocalGenerator: De-duplicate StateSnapshot member We have the member from the cmOutputConverter parent. --- Source/cmLocalGenerator.cxx | 1 - Source/cmLocalGenerator.h | 1 - Source/cmOutputConverter.h | 5 +++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4a35909d7da..3b01b1fa57e 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -88,7 +88,6 @@ static auto ruleReplaceVars = { "CMAKE_${LANG}_COMPILER", cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) : cmOutputConverter(makefile->GetStateSnapshot()) - , StateSnapshot(makefile->GetStateSnapshot()) , DirectoryBacktrace(makefile->GetBacktrace()) { this->GlobalGenerator = gg; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1f8970f7c33..0d652675667 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -594,7 +594,6 @@ class cmLocalGenerator : public cmOutputConverter virtual bool CheckDefinition(std::string const& define) const; cmMakefile* Makefile; - cmStateSnapshot StateSnapshot; cmListFileBacktrace DirectoryBacktrace; cmGlobalGenerator* GlobalGenerator; std::map UniqueObjectNamesMap; diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index f1a8041ba72..c67e74b9bef 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -102,6 +102,9 @@ class cmOutputConverter }; static FortranPreprocess GetFortranPreprocess(cm::string_view value); +protected: + cmStateSnapshot StateSnapshot; + private: cmState* GetState() const; @@ -111,7 +114,5 @@ class cmOutputConverter static bool Shell_ArgumentNeedsQuotes(cm::string_view in, int flags); static std::string Shell_GetArgument(cm::string_view in, int flags); - cmStateSnapshot StateSnapshot; - bool LinkScriptShell; }; From 8526756b61014f780348346ba5fdf0604a02d158 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 May 2021 15:38:27 -0400 Subject: [PATCH 0466/1519] cmOutputConverter: Adopt relative path conversion helpers Move them up from cmLocalGenerator and out of cmStateDirectory. --- Source/cmGlobalNinjaGenerator.cxx | 4 +- Source/cmLinkLineComputer.cxx | 10 +-- Source/cmLocalGenerator.cxx | 19 ----- Source/cmLocalGenerator.h | 13 ---- Source/cmLocalUnixMakefileGenerator3.cxx | 13 +--- Source/cmMakefileTargetGenerator.cxx | 12 +-- Source/cmOutputConverter.cxx | 94 ++++++++++++++++++++++++ Source/cmOutputConverter.h | 27 +++++++ Source/cmStateDirectory.cxx | 89 ---------------------- Source/cmStateDirectory.h | 14 ---- Source/cmStatePrivate.h | 8 -- Source/cmcmd.cxx | 16 +++- 12 files changed, 142 insertions(+), 177 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 5cf37daee38..565b9514dac 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2434,10 +2434,10 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( cmStateSnapshot snapshot = this->GetCMakeInstance()->GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentSource(dir_cur_src); snapshot.GetDirectory().SetCurrentBinary(dir_cur_bld); - snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str()); - snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str()); auto mfd = cm::make_unique(this, snapshot); auto lgd = this->CreateLocalGenerator(mfd.get()); + lgd->SetRelativePathTopSource(dir_top_src); + lgd->SetRelativePathTopBinary(dir_top_bld); this->Makefiles.push_back(std::move(mfd)); this->LocalGenerators.push_back(std::move(lgd)); } diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 480c005cd30..a3f2968b1c9 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -11,10 +11,8 @@ #include "cmGeneratorTarget.h" #include "cmListFileCache.h" #include "cmOutputConverter.h" -#include "cmStateDirectory.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" -#include "cmSystemTools.h" cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) @@ -52,13 +50,7 @@ void cmLinkLineComputer::SetRelink(bool relink) std::string cmLinkLineComputer::ConvertToLinkReference( std::string const& lib) const { - std::string relLib = lib; - - if (this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), lib)) { - relLib = cmSystemTools::ForceToRelativePath( - this->StateDir.GetCurrentBinary(), lib); - } - return relLib; + return this->OutputConverter->MaybeRelativeToCurBinDir(lib); } std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3b01b1fa57e..4db9216056c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3678,25 +3678,6 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const return this->StateSnapshot.GetDirectory().GetCurrentSource(); } -std::string cmLocalGenerator::MaybeRelativeTo( - std::string const& local_path, std::string const& remote_path) const -{ - return this->StateSnapshot.GetDirectory().ConvertToRelPathIfContained( - local_path, remote_path); -} - -std::string cmLocalGenerator::MaybeRelativeToTopBinDir( - std::string const& path) const -{ - return this->MaybeRelativeTo(this->GetBinaryDirectory(), path); -} - -std::string cmLocalGenerator::MaybeRelativeToCurBinDir( - std::string const& path) const -{ - return this->MaybeRelativeTo(this->GetCurrentBinaryDirectory(), path); -} - std::string cmLocalGenerator::GetTargetDirectory( const cmGeneratorTarget* /*unused*/) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 0d652675667..993280ac2da 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -462,16 +462,6 @@ class cmLocalGenerator : public cmOutputConverter std::string const& GetCurrentBinaryDirectory() const; std::string const& GetCurrentSourceDirectory() const; - /** - * Convert the given remote path to a relative path with respect to - * one of our common work directories. The path must use forward - * slashes and not already be escaped or quoted. - * The conversion is skipped if the paths are not both in the source - * or both in the binary tree. - */ - std::string MaybeRelativeToTopBinDir(std::string const& path) const; - std::string MaybeRelativeToCurBinDir(std::string const& path) const; - /** * Generate a macOS application bundle Info.plist file. */ @@ -558,9 +548,6 @@ class cmLocalGenerator : public cmOutputConverter cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop); protected: - std::string MaybeRelativeTo(std::string const& local_path, - std::string const& remote_path) const; - // The default implementation ignores the IncludePathStyle and always // uses absolute paths. A generator may override this to use relative // paths in some cases. diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index a652c7b398a..3a65a80c9e6 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -38,7 +38,6 @@ #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmState.h" -#include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -474,11 +473,9 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() infoFileStream << "# Relative path conversion top directories.\n" << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" - << this->StateSnapshot.GetDirectory().GetRelativePathTopSource() - << "\")\n" + << this->GetRelativePathTopSource() << "\")\n" << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \"" - << this->StateSnapshot.GetDirectory().GetRelativePathTopBinary() - << "\")\n" + << this->GetRelativePathTopBinary() << "\")\n" << "\n"; /* clang-format on */ @@ -1513,13 +1510,11 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // Setup relative path top directories. if (cmProp relativePathTopSource = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) { - this->StateSnapshot.GetDirectory().SetRelativePathTopSource( - relativePathTopSource->c_str()); + this->SetRelativePathTopSource(*relativePathTopSource); } if (cmProp relativePathTopBinary = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) { - this->StateSnapshot.GetDirectory().SetRelativePathTopBinary( - relativePathTopBinary->c_str()); + this->SetRelativePathTopBinary(*relativePathTopBinary); } } else { cmSystemTools::Error("Directory Information file not found"); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1cc843467d9..4542672bd8c 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1749,7 +1749,8 @@ class cmMakefileTargetGeneratorObjectStrings { // Construct the name of the next object. this->NextObject = this->OutputConverter->ConvertToOutputFormat( - this->MaybeRelativeToCurBinDir(obj), cmOutputConverter::RESPONSE); + this->OutputConverter->MaybeRelativeToCurBinDir(obj), + cmOutputConverter::RESPONSE); // Roll over to next string if the limit will be exceeded. if (this->LengthLimit != std::string::npos && @@ -1770,15 +1771,6 @@ class cmMakefileTargetGeneratorObjectStrings void Done() { this->Strings.push_back(this->CurrentString); } private: - std::string MaybeRelativeToCurBinDir(std::string const& path) - { - std::string const& base = this->StateDir.GetCurrentBinary(); - if (!this->StateDir.ContainsBoth(base, path)) { - return path; - } - return cmSystemTools::ForceToRelativePath(base, path); - } - std::vector& Strings; cmOutputConverter* OutputConverter; cmStateDirectory StateDir; diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index ec5453716ac..840fdb9ecfc 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -9,14 +9,108 @@ #include #include "cmState.h" +#include "cmStateDirectory.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +namespace { +bool PathEqOrSubDir(std::string const& a, std::string const& b) +{ + return (cmSystemTools::ComparePath(a, b) || + cmSystemTools::IsSubDirectory(a, b)); +}; +} + cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot) : StateSnapshot(snapshot) , LinkScriptShell(false) { assert(this->StateSnapshot.IsValid()); + this->ComputeRelativePathTopSource(); + this->ComputeRelativePathTopBinary(); +} + +void cmOutputConverter::ComputeRelativePathTopSource() +{ + // Walk up the buildsystem directory tree to find the highest source + // directory that contains the current source directory. + cmStateSnapshot snapshot = this->StateSnapshot; + for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent(); + parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) { + if (cmSystemTools::IsSubDirectory( + snapshot.GetDirectory().GetCurrentSource(), + parent.GetDirectory().GetCurrentSource())) { + snapshot = parent; + } + } + this->RelativePathTopSource = snapshot.GetDirectory().GetCurrentSource(); +} + +void cmOutputConverter::ComputeRelativePathTopBinary() +{ + // Walk up the buildsystem directory tree to find the highest binary + // directory that contains the current binary directory. + cmStateSnapshot snapshot = this->StateSnapshot; + for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent(); + parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) { + if (cmSystemTools::IsSubDirectory( + snapshot.GetDirectory().GetCurrentBinary(), + parent.GetDirectory().GetCurrentBinary())) { + snapshot = parent; + } + } + + this->RelativePathTopBinary = snapshot.GetDirectory().GetCurrentBinary(); +} + +std::string const& cmOutputConverter::GetRelativePathTopSource() const +{ + return this->RelativePathTopSource; +} + +std::string const& cmOutputConverter::GetRelativePathTopBinary() const +{ + return this->RelativePathTopBinary; +} + +void cmOutputConverter::SetRelativePathTopSource(std::string const& top) +{ + this->RelativePathTopSource = top; +} + +void cmOutputConverter::SetRelativePathTopBinary(std::string const& top) +{ + this->RelativePathTopBinary = top; +} + +std::string cmOutputConverter::MaybeRelativeTo( + std::string const& local_path, std::string const& remote_path) const +{ + bool bothInBinary = + PathEqOrSubDir(local_path, this->RelativePathTopBinary) && + PathEqOrSubDir(remote_path, this->RelativePathTopBinary); + + bool bothInSource = + PathEqOrSubDir(local_path, this->RelativePathTopSource) && + PathEqOrSubDir(remote_path, this->RelativePathTopSource); + + if (bothInBinary || bothInSource) { + return cmSystemTools::ForceToRelativePath(local_path, remote_path); + } + return remote_path; +} + +std::string cmOutputConverter::MaybeRelativeToTopBinDir( + std::string const& path) const +{ + return this->MaybeRelativeTo(this->GetState()->GetBinaryDirectory(), path); +} + +std::string cmOutputConverter::MaybeRelativeToCurBinDir( + std::string const& path) const +{ + return this->MaybeRelativeTo( + this->StateSnapshot.GetDirectory().GetCurrentBinary(), path); } std::string cmOutputConverter::ConvertToOutputForExisting( diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index c67e74b9bef..865df718b11 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -17,6 +17,21 @@ class cmOutputConverter public: cmOutputConverter(cmStateSnapshot const& snapshot); + /** + * Convert the given remote path to a relative path with respect to + * one of our common work directories. The path must use forward + * slashes and not already be escaped or quoted. + * The conversion is skipped if the paths are not both in the source + * or both in the binary tree. + */ + std::string MaybeRelativeToTopBinDir(std::string const& path) const; + std::string MaybeRelativeToCurBinDir(std::string const& path) const; + + std::string const& GetRelativePathTopSource() const; + std::string const& GetRelativePathTopBinary() const; + void SetRelativePathTopSource(std::string const& top); + void SetRelativePathTopBinary(std::string const& top); + enum OutputFormat { SHELL, @@ -115,4 +130,16 @@ class cmOutputConverter static std::string Shell_GetArgument(cm::string_view in, int flags); bool LinkScriptShell; + + // The top-most directories for relative path conversion. Both the + // source and destination location of a relative path conversion + // must be underneath one of these directories (both under source or + // both under binary) in order for the relative path to be evaluated + // safely by the build tools. + std::string RelativePathTopSource; + std::string RelativePathTopBinary; + void ComputeRelativePathTopSource(); + void ComputeRelativePathTopBinary(); + std::string MaybeRelativeTo(std::string const& local_path, + std::string const& remote_path) const; }; diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 140ff0d3087..9ae2861574f 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -24,41 +24,6 @@ static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS"; static std::string const kSOURCE_DIR = "SOURCE_DIR"; static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES"; -void cmStateDirectory::ComputeRelativePathTopSource() -{ - // Walk up the buildsystem directory tree to find the highest source - // directory that contains the current source directory. - cmStateSnapshot snapshot = this->Snapshot_; - for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent(); - parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) { - if (cmSystemTools::IsSubDirectory( - snapshot.GetDirectory().GetCurrentSource(), - parent.GetDirectory().GetCurrentSource())) { - snapshot = parent; - } - } - this->DirectoryState->RelativePathTopSource = - snapshot.GetDirectory().GetCurrentSource(); -} - -void cmStateDirectory::ComputeRelativePathTopBinary() -{ - // Walk up the buildsystem directory tree to find the highest binary - // directory that contains the current binary directory. - cmStateSnapshot snapshot = this->Snapshot_; - for (cmStateSnapshot parent = snapshot.GetBuildsystemDirectoryParent(); - parent.IsValid(); parent = parent.GetBuildsystemDirectoryParent()) { - if (cmSystemTools::IsSubDirectory( - snapshot.GetDirectory().GetCurrentBinary(), - parent.GetDirectory().GetCurrentBinary())) { - snapshot = parent; - } - } - - this->DirectoryState->RelativePathTopBinary = - snapshot.GetDirectory().GetCurrentBinary(); -} - std::string const& cmStateDirectory::GetCurrentSource() const { return this->DirectoryState->Location; @@ -70,9 +35,6 @@ void cmStateDirectory::SetCurrentSource(std::string const& dir) loc = dir; cmSystemTools::ConvertToUnixSlashes(loc); loc = cmSystemTools::CollapseFullPath(loc); - - this->ComputeRelativePathTopSource(); - this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc); } @@ -87,60 +49,9 @@ void cmStateDirectory::SetCurrentBinary(std::string const& dir) loc = dir; cmSystemTools::ConvertToUnixSlashes(loc); loc = cmSystemTools::CollapseFullPath(loc); - - this->ComputeRelativePathTopBinary(); - this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc); } -std::string const& cmStateDirectory::GetRelativePathTopSource() const -{ - return this->DirectoryState->RelativePathTopSource; -} - -std::string const& cmStateDirectory::GetRelativePathTopBinary() const -{ - return this->DirectoryState->RelativePathTopBinary; -} - -void cmStateDirectory::SetRelativePathTopSource(const char* dir) -{ - this->DirectoryState->RelativePathTopSource = dir; -} - -void cmStateDirectory::SetRelativePathTopBinary(const char* dir) -{ - this->DirectoryState->RelativePathTopBinary = dir; -} - -bool cmStateDirectory::ContainsBoth(std::string const& local_path, - std::string const& remote_path) const -{ - auto PathEqOrSubDir = [](std::string const& a, std::string const& b) { - return (cmSystemTools::ComparePath(a, b) || - cmSystemTools::IsSubDirectory(a, b)); - }; - - bool bothInBinary = - PathEqOrSubDir(local_path, this->GetRelativePathTopBinary()) && - PathEqOrSubDir(remote_path, this->GetRelativePathTopBinary()); - - bool bothInSource = - PathEqOrSubDir(local_path, this->GetRelativePathTopSource()) && - PathEqOrSubDir(remote_path, this->GetRelativePathTopSource()); - - return bothInBinary || bothInSource; -} - -std::string cmStateDirectory::ConvertToRelPathIfContained( - std::string const& local_path, std::string const& remote_path) const -{ - if (!this->ContainsBoth(local_path, remote_path)) { - return remote_path; - } - return cmSystemTools::ForceToRelativePath(local_path, remote_path); -} - cmStateDirectory::cmStateDirectory( cmLinkedTree::iterator iter, const cmStateSnapshot& snapshot) diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 4dab9ff946d..ce00dbb3c39 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -28,17 +28,6 @@ class cmStateDirectory std::string const& GetCurrentBinary() const; void SetCurrentBinary(std::string const& dir); - std::string const& GetRelativePathTopSource() const; - std::string const& GetRelativePathTopBinary() const; - void SetRelativePathTopSource(const char* dir); - void SetRelativePathTopBinary(const char* dir); - - bool ContainsBoth(std::string const& local_path, - std::string const& remote_path) const; - - std::string ConvertToRelPathIfContained( - std::string const& local_path, std::string const& remote_path) const; - cmStringRange GetIncludeDirectoriesEntries() const; cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const; void AppendIncludeDirectoriesEntry(std::string const& vec, @@ -94,9 +83,6 @@ class cmStateDirectory void AddNormalTargetName(std::string const& name); private: - void ComputeRelativePathTopSource(); - void ComputeRelativePathTopBinary(); - cmLinkedTree::iterator DirectoryState; cmStateSnapshot Snapshot_; diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index 489264468d9..a437ce2efc1 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -67,14 +67,6 @@ struct cmStateDetail::BuildsystemDirectoryStateType std::string Location; std::string OutputLocation; - // The top-most directories for relative path conversion. Both the - // source and destination location of a relative path conversion - // must be underneath one of these directories (both under source or - // both under binary) in order for the relative path to be evaluated - // safely by the build tools. - std::string RelativePathTopSource; - std::string RelativePathTopBinary; - std::vector IncludeDirectories; std::vector IncludeDirectoryBacktraces; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 98946b64fba..727e41263cd 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1270,11 +1270,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary(startOutDir); snapshot.GetDirectory().SetCurrentSource(startDir); - snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str()); - snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str()); cmMakefile mf(cm.GetGlobalGenerator(), snapshot); auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf); + // FIXME: With advanced add_subdirectory usage, these are + // not necessarily the same as the generator originally used. + // We should pass all these directories through an info file. + lgd->SetRelativePathTopSource(homeDir); + lgd->SetRelativePathTopBinary(homeOutDir); + // Actually scan dependencies. return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2; } @@ -1551,11 +1555,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary(startOutDir); snapshot.GetDirectory().SetCurrentSource(startDir); - snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str()); - snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str()); cmMakefile mf(cm.GetGlobalGenerator(), snapshot); auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf); + // FIXME: With advanced add_subdirectory usage, these are + // not necessarily the same as the generator originally used. + // We should pass all these directories through an info file. + lgd->SetRelativePathTopSource(homeDir); + lgd->SetRelativePathTopBinary(homeOutDir); + return cmTransformDepfile(format, *lgd, args[8], args[9]) ? 0 : 2; } return 1; From 3f9acb9a60595322ebe901f188e557f622e5853c Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 18 May 2021 00:01:10 -0400 Subject: [PATCH 0467/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ee9a5f9d210..bdba53535ca 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210517) +set(CMake_VERSION_PATCH 20210518) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From cbeff3082dff634876c834afa3cdf5091a087a5c Mon Sep 17 00:00:00 2001 From: Viktor Wallner Date: Tue, 18 May 2021 16:09:12 +0200 Subject: [PATCH 0468/1519] .gitignore: Add CLion directories and VS build directory --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 2f356157d34..d39684d6b48 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,13 @@ CMakeUserPresets.json # Visual Studio work directory .vs/ +# Visual Studio build directory +out/ # Visual Studio Code .vscode/ + +# CLion work directory +.idea/ +# CLion build directories +cmake-build-*/ From 521cfc38a3faa9239015ceb8281800aa14a215cb Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 18 May 2021 11:30:01 -0400 Subject: [PATCH 0469/1519] NVHPC: Support explicit language flags --- Modules/Compiler/NVHPC-C.cmake | 4 ++++ Modules/Compiler/NVHPC-CXX.cmake | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake index d16c72b76e8..72c26563f47 100644 --- a/Modules/Compiler/NVHPC-C.cmake +++ b/Modules/Compiler/NVHPC-C.cmake @@ -1,3 +1,7 @@ include(Compiler/PGI-C) include(Compiler/NVHPC) + +# Needed so that we support `LANGUAGE` property correctly +set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c) + __compiler_nvhpc(C) diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake index 18ace8bfe68..ac75b53a409 100644 --- a/Modules/Compiler/NVHPC-CXX.cmake +++ b/Modules/Compiler/NVHPC-CXX.cmake @@ -1,3 +1,7 @@ include(Compiler/PGI-CXX) include(Compiler/NVHPC) + +# Needed so that we support `LANGUAGE` property correctly +set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++) + __compiler_nvhpc(CXX) From 364f6af1d753bacf7a007033b30ebf2d6e15fe24 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 18 May 2021 11:30:36 -0400 Subject: [PATCH 0470/1519] NVHPC: Support Ninja dependency scanning Fixes: #22168 --- Modules/Compiler/NVHPC-C.cmake | 5 +++++ Modules/Compiler/NVHPC-CXX.cmake | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake index 72c26563f47..a734edf1988 100644 --- a/Modules/Compiler/NVHPC-C.cmake +++ b/Modules/Compiler/NVHPC-C.cmake @@ -4,4 +4,9 @@ include(Compiler/NVHPC) # Needed so that we support `LANGUAGE` property correctly set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c) +# Required since as of NVHPC 21.03 the `-MD` flag implicitly +# implies `-E` and therefore compilation and dependency generation +# can't occur in the same invocation +set(CMAKE_C_DEPENDS_EXTRA_COMMANDS " -x c -M -MT -MD") + __compiler_nvhpc(C) diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake index ac75b53a409..98d00225764 100644 --- a/Modules/Compiler/NVHPC-CXX.cmake +++ b/Modules/Compiler/NVHPC-CXX.cmake @@ -4,4 +4,9 @@ include(Compiler/NVHPC) # Needed so that we support `LANGUAGE` property correctly set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++) +# Required since as of NVHPC 21.03 the `-MD` flag implicitly +# implies `-E` and therefore compilation and dependency generation +# can't occur in the same invocation +set(CMAKE_CXX_DEPENDS_EXTRA_COMMANDS " -x c++ -M -MT -MD") + __compiler_nvhpc(CXX) From 4b12aa6e6c193139feb55e865fa7c6783ffdccea Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 19 May 2021 00:01:42 -0400 Subject: [PATCH 0471/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bdba53535ca..83a41c16b14 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210518) +set(CMake_VERSION_PATCH 20210519) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From bceb8e2ed23340a90d2093e05d50f0cc797f6432 Mon Sep 17 00:00:00 2001 From: Marius Messerschmidt Date: Sat, 8 May 2021 22:30:35 +0200 Subject: [PATCH 0472/1519] cmMessenger: Pass title inside a metadata structure --- Source/CMakeLists.txt | 1 + Source/CTest/cmCTestBuildAndTestHandler.cxx | 4 +++- Source/CursesDialog/ccmake.cxx | 5 +++-- Source/QtDialog/QCMake.cxx | 5 +++-- Source/cmMessageMetadata.h | 8 ++++++++ Source/cmMessenger.cxx | 8 ++++++-- Source/cmSystemTools.cxx | 10 +++++++++- Source/cmSystemTools.h | 6 +++++- Source/cmakemain.cxx | 22 +++++++++++---------- 9 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 Source/cmMessageMetadata.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c19c1546228..bd9e4c2d824 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -638,6 +638,7 @@ set(SRCS cmMathCommand.h cmMessageCommand.cxx cmMessageCommand.h + cmMessageMetadata.h cmOptionCommand.cxx cmOptionCommand.h cmOutputRequiredFilesCommand.cxx diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index a18cbb49bca..adfc8ef774f 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -19,6 +19,8 @@ #include "cmWorkingDirectory.h" #include "cmake.h" +struct cmMessageMetadata; + cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler() { this->BuildTwoConfig = false; @@ -125,7 +127,7 @@ class cmCTestBuildAndTestCaptureRAII : CM(cm) { cmSystemTools::SetMessageCallback( - [&s](const std::string& msg, const char* /*unused*/) { + [&s](const std::string& msg, const cmMessageMetadata& /* unused */) { s += msg; s += "\n"; }); diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 85e256b8bc3..1ba45e5f7a1 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -19,6 +19,7 @@ #include "cmCursesStandardIncludes.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" // IWYU pragma: keep +#include "cmMessageMetadata.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -181,8 +182,8 @@ int main(int argc, char const* const* argv) return msg; }; cmSystemTools::SetMessageCallback( - [&](const std::string& message, const char* title) { - myform->AddError(cleanMessage(message), title); + [&](const std::string& message, const cmMessageMetadata& md) { + myform->AddError(cleanMessage(message), md.title); }); cmSystemTools::SetStderrCallback([&](const std::string& message) { myform->AddError(cleanMessage(message), ""); diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index a83622afe87..e6faef47033 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -13,6 +13,7 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmGlobalGenerator.h" +#include "cmMessageMetadata.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -37,8 +38,8 @@ QCMake::QCMake(QObject* p) cmSystemTools::SetRunCommandHideConsole(true); cmSystemTools::SetMessageCallback( - [this](std::string const& msg, const char* title) { - this->messageCallback(msg, title); + [this](std::string const& msg, const cmMessageMetadata& md) { + this->messageCallback(msg, md.title); }); cmSystemTools::SetStdoutCallback( [this](std::string const& msg) { this->stdoutCallback(msg); }); diff --git a/Source/cmMessageMetadata.h b/Source/cmMessageMetadata.h new file mode 100644 index 00000000000..5688dc57a2d --- /dev/null +++ b/Source/cmMessageMetadata.h @@ -0,0 +1,8 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +struct cmMessageMetadata +{ + const char* title = nullptr; +}; diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index af83478a65b..4c0faa9236b 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -3,6 +3,7 @@ #include "cmMessenger.h" #include "cmDocumentationFormatter.h" +#include "cmMessageMetadata.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -120,12 +121,15 @@ void displayMessage(MessageType t, std::ostringstream& msg) #endif // Output the message. + cmMessageMetadata md; if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR || t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) { cmSystemTools::SetErrorOccured(); - cmSystemTools::Message(msg.str(), "Error"); + md.title = "Error"; + cmSystemTools::Message(msg.str(), md); } else { - cmSystemTools::Message(msg.str(), "Warning"); + md.title = "Warning"; + cmSystemTools::Message(msg.str(), md); } } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 2fba13f436b..9b81bf2675b 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -19,6 +19,7 @@ #include #include "cmDuration.h" +#include "cmMessageMetadata.h" #include "cmProcessOutput.h" #include "cmRange.h" #include "cmStringAlgorithms.h" @@ -262,9 +263,16 @@ void cmSystemTools::Stdout(const std::string& s) } void cmSystemTools::Message(const std::string& m, const char* title) +{ + cmMessageMetadata md; + md.title = title; + Message(m, md); +} + +void cmSystemTools::Message(const std::string& m, const cmMessageMetadata& md) { if (s_MessageCallback) { - s_MessageCallback(m, title); + s_MessageCallback(m, md); } else { std::cerr << m << std::endl; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 474f591ef55..5c3b5a9a0a9 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -19,6 +19,8 @@ #include "cmDuration.h" #include "cmProcessOutput.h" +struct cmMessageMetadata; + /** \class cmSystemTools * \brief A collection of useful functions for CMake. * @@ -40,7 +42,8 @@ class cmSystemTools : public cmsys::SystemTools /** Map help document name to file name. */ static std::string HelpFileName(cm::string_view); - using MessageCallback = std::function; + using MessageCallback = + std::function; /** * Set the function used by GUIs to display error messages * Function gets passed: message as a const char*, @@ -57,6 +60,7 @@ class cmSystemTools : public cmsys::SystemTools * Display a message. */ static void Message(const std::string& m, const char* title = nullptr); + static void Message(const std::string& m, const cmMessageMetadata& md); using OutputCallback = std::function; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index ad648186bd5..60ac0caa726 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -38,6 +38,8 @@ #include "cmsys/Encoding.hxx" +struct cmMessageMetadata; + namespace { #ifndef CMAKE_BOOTSTRAP const char* cmDocumentationName[][2] = { @@ -147,8 +149,8 @@ std::string cmakemainGetStack(cmake* cm) return msg; } -void cmakemainMessageCallback(const std::string& m, const char* /*unused*/, - cmake* cm) +void cmakemainMessageCallback(const std::string& m, + const cmMessageMetadata& /* unused */, cmake* cm) { std::cerr << m << cmakemainGetStack(cm) << std::endl; } @@ -342,8 +344,8 @@ int do_cmake(int ac, char const* const* av) cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmSystemTools::SetMessageCallback( - [&cm](const std::string& msg, const char* title) { - cmakemainMessageCallback(msg, title, &cm); + [&cm](const std::string& msg, const cmMessageMetadata& md) { + cmakemainMessageCallback(msg, md, &cm); }); cm.SetProgressCallback([&cm](const std::string& msg, float prog) { cmakemainProgressCallback(msg, prog, &cm); @@ -624,8 +626,8 @@ int do_build(int ac, char const* const* av) cmake cm(cmake::RoleInternal, cmState::Project); cmSystemTools::SetMessageCallback( - [&cm](const std::string& msg, const char* title) { - cmakemainMessageCallback(msg, title, &cm); + [&cm](const std::string& msg, const cmMessageMetadata& md) { + cmakemainMessageCallback(msg, md, &cm); }); cm.SetProgressCallback([&cm](const std::string& msg, float prog) { cmakemainProgressCallback(msg, prog, &cm); @@ -857,8 +859,8 @@ int do_install(int ac, char const* const* av) cmake cm(cmake::RoleScript, cmState::Script); cmSystemTools::SetMessageCallback( - [&cm](const std::string& msg, const char* title) { - cmakemainMessageCallback(msg, title, &cm); + [&cm](const std::string& msg, const cmMessageMetadata& md) { + cmakemainMessageCallback(msg, md, &cm); }); cm.SetProgressCallback([&cm](const std::string& msg, float prog) { cmakemainProgressCallback(msg, prog, &cm); @@ -938,8 +940,8 @@ int do_open(int ac, char const* const* av) cmake cm(cmake::RoleInternal, cmState::Unknown); cmSystemTools::SetMessageCallback( - [&cm](const std::string& msg, const char* title) { - cmakemainMessageCallback(msg, title, &cm); + [&cm](const std::string& msg, const cmMessageMetadata& md) { + cmakemainMessageCallback(msg, md, &cm); }); cm.SetProgressCallback([&cm](const std::string& msg, float prog) { cmakemainProgressCallback(msg, prog, &cm); From 372bf1bcc410f3e36397bae9834ec141a5fca7ec Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 19 May 2021 11:05:17 -0400 Subject: [PATCH 0473/1519] cmCommandLineArgument: Understands which commands require partial matching Allows us to provide better error messages when commands such as `--target` are passed invalid input. --- Source/cmCommandLineArgument.h | 48 +++++++++++++- Source/cmake.cxx | 66 ++++++++++++------- Source/cmakemain.cxx | 6 +- ...d-unknown-command-partial-match-stderr.txt | 2 +- 4 files changed, 93 insertions(+), 29 deletions(-) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index 5031c6551ca..e2697718f9e 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -17,10 +17,17 @@ struct cmCommandLineArgument OneOrMore }; + enum class RequiresSeparator + { + Yes, + No + }; + std::string InvalidSyntaxMessage; std::string InvalidValueMessage; std::string Name; Values Type; + RequiresSeparator SeparatorNeeded; std::function StoreCall; template @@ -29,6 +36,19 @@ struct cmCommandLineArgument , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) , Name(std::move(n)) , Type(t) + , SeparatorNeeded(RequiresSeparator::Yes) + , StoreCall(std::forward(func)) + { + } + + template + cmCommandLineArgument(std::string n, Values t, RequiresSeparator s, + FunctionType&& func) + : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n)) + , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) + , Name(std::move(n)) + , Type(t) + , SeparatorNeeded(s) , StoreCall(std::forward(func)) { } @@ -40,14 +60,38 @@ struct cmCommandLineArgument , InvalidValueMessage(std::move(failedMsg)) , Name(std::move(n)) , Type(t) + , SeparatorNeeded(RequiresSeparator::Yes) + , StoreCall(std::forward(func)) + { + } + + template + cmCommandLineArgument(std::string n, std::string failedMsg, Values t, + RequiresSeparator s, FunctionType&& func) + : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n)) + , InvalidValueMessage(std::move(failedMsg)) + , Name(std::move(n)) + , Type(t) + , SeparatorNeeded(s) , StoreCall(std::forward(func)) { } bool matches(std::string const& input) const { - return (this->Type == Values::Zero) ? (input == this->Name) - : cmHasPrefix(input, this->Name); + if (this->Type == Values::Zero) { + return input == this->Name; + } else if (this->SeparatorNeeded == RequiresSeparator::No) { + return cmHasPrefix(input, this->Name); + } else if (cmHasPrefix(input, this->Name)) { + if (input.size() == this->Name.size()) { + return true; + } else { + return (input[this->Name.size()] == '=' || + input[this->Name.size()] == ' '); + } + } + return false; } template diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 54409843159..315bd20efa2 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -529,25 +529,29 @@ bool cmake::SetCacheArgs(const std::vector& args) std::vector arguments = { CommandArgument{ "-D", "-D must be followed with VAR=VALUE.", - CommandArgument::Values::One, DefineLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, DefineLambda }, CommandArgument{ "-W", "-W must be followed with [no-].", - CommandArgument::Values::One, WarningLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, WarningLambda }, CommandArgument{ "-U", "-U must be followed with VAR.", - CommandArgument::Values::One, UnSetLambda }, - CommandArgument{ "-C", "-C must be followed by a file name.", CommandArgument::Values::One, - [&](std::string const& value, cmake* state) -> bool { - cmSystemTools::Stdout("loading initial cache file " + - value + "\n"); - // Resolve script path specified on command line - // relative to $PWD. - auto path = cmSystemTools::CollapseFullPath(value); - state->ReadListFile(args, path); - return true; - } }, + CommandArgument::RequiresSeparator::No, UnSetLambda }, + CommandArgument{ + "-C", "-C must be followed by a file name.", + CommandArgument::Values::One, CommandArgument::RequiresSeparator::No, + [&](std::string const& value, cmake* state) -> bool { + cmSystemTools::Stdout("loading initial cache file " + value + "\n"); + // Resolve script path specified on command line + // relative to $PWD. + auto path = cmSystemTools::CollapseFullPath(value); + state->ReadListFile(args, path); + return true; + } }, CommandArgument{ "-P", "-P must be followed by a file name.", - CommandArgument::Values::One, ScriptLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, ScriptLambda }, CommandArgument{ "--toolchain", "No file specified for --toolchain", CommandArgument::Values::One, ToolchainLambda }, CommandArgument{ "--install-prefix", @@ -830,31 +834,44 @@ void cmake::SetArgs(const std::vector& args) std::vector arguments = { CommandArgument{ "-S", "No source directory specified for -S", - CommandArgument::Values::One, SourceArgLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, SourceArgLambda }, CommandArgument{ "-H", "No source directory specified for -H", - CommandArgument::Values::One, SourceArgLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, SourceArgLambda }, CommandArgument{ "-O", CommandArgument::Values::Zero, IgnoreAndTrueLambda }, CommandArgument{ "-B", "No build directory specified for -B", - CommandArgument::Values::One, BuildArgLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, BuildArgLambda }, CommandArgument{ "-P", "-P must be followed by a file name.", CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, [&](std::string const&, cmake*) -> bool { scriptMode = true; return true; } }, CommandArgument{ "-D", "-D must be followed with VAR=VALUE.", - CommandArgument::Values::One, IgnoreAndTrueLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, + IgnoreAndTrueLambda }, CommandArgument{ "-C", "-C must be followed by a file name.", - CommandArgument::Values::One, IgnoreAndTrueLambda }, - CommandArgument{ "-U", "-U must be followed with VAR.", - CommandArgument::Values::One, IgnoreAndTrueLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, + IgnoreAndTrueLambda }, + CommandArgument{ + "-U", "-U must be followed with VAR.", CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, IgnoreAndTrueLambda }, CommandArgument{ "-W", "-W must be followed with [no-].", - CommandArgument::Values::One, IgnoreAndTrueLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, + IgnoreAndTrueLambda }, CommandArgument{ "-A", "No platform specified for -A", - CommandArgument::Values::One, PlatformLambda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, PlatformLambda }, CommandArgument{ "-T", "No toolset specified for -T", - CommandArgument::Values::One, ToolsetLamda }, + CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, ToolsetLamda }, CommandArgument{ "--toolchain", "No file specified for --toolchain", CommandArgument::Values::One, IgnoreAndTrueLambda }, CommandArgument{ "--install-prefix", @@ -1079,6 +1096,7 @@ void cmake::SetArgs(const std::vector& args) bool badGeneratorName = false; CommandArgument generatorCommand( "-G", "No generator specified for -G", CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, [&](std::string const& value, cmake* state) -> bool { bool valid = state->CreateAndSetGlobalGenerator(value, true); badGeneratorName = !valid; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index ad648186bd5..997d8555e4f 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -271,6 +271,7 @@ int do_cmake(int ac, char const* const* av) } }, CommandArgument{ "-P", "No script specified for argument -P", CommandArgument::Values::One, + CommandArgument::RequiresSeparator::No, [&](std::string const& value) -> bool { workingMode = cmake::SCRIPT_MODE; parsedArgs.emplace_back("-P"); @@ -476,9 +477,10 @@ int do_build(int ac, char const* const* av) listPresets = true; return true; } }, - CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda }, + CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, + CommandArgument::RequiresSeparator::No, jLambda }, CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne, - parallelLambda }, + CommandArgument::RequiresSeparator::No, parallelLambda }, CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda }, CommandArgument{ "--target", CommandArgument::Values::OneOrMore, targetLambda }, diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt index d69338a411e..e4ad6b2da41 100644 --- a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt @@ -1,2 +1,2 @@ -^CMake Error: '--targetinvalid' is invalid syntax for --target +^Unknown argument --targetinvalid Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] From 396e0a840e75afb3f5ed7b50892b93ce946fac2e Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 19 May 2021 11:07:34 -0400 Subject: [PATCH 0474/1519] cmCommandLineArgument: OneOrMore mode supports `=` separator Fixes #22187 --- Source/cmCommandLineArgument.h | 75 +++++++++++-------- .../build-invalid-target-syntax-stderr.txt | 3 +- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h index e2697718f9e..72ab0450fd2 100644 --- a/Source/cmCommandLineArgument.h +++ b/Source/cmCommandLineArgument.h @@ -23,6 +23,14 @@ struct cmCommandLineArgument No }; + enum class ParseMode + { + Valid, + Invalid, + SyntaxError, + ValueError + }; + std::string InvalidSyntaxMessage; std::string InvalidValueMessage; std::string Name; @@ -79,19 +87,20 @@ struct cmCommandLineArgument bool matches(std::string const& input) const { + bool matched = false; if (this->Type == Values::Zero) { - return input == this->Name; + matched = (input == this->Name); } else if (this->SeparatorNeeded == RequiresSeparator::No) { - return cmHasPrefix(input, this->Name); + matched = cmHasPrefix(input, this->Name); } else if (cmHasPrefix(input, this->Name)) { if (input.size() == this->Name.size()) { - return true; + matched = true; } else { - return (input[this->Name.size()] == '=' || - input[this->Name.size()] == ' '); + matched = + (input[this->Name.size()] == '=' || input[this->Name.size()] == ' '); } } - return false; + return matched; } template @@ -99,13 +108,6 @@ struct cmCommandLineArgument std::vector const& allArgs, CallState&&... state) const { - enum class ParseMode - { - Valid, - Invalid, - SyntaxError, - ValueError - }; ParseMode parseState = ParseMode::Valid; if (this->Type == Values::Zero) { @@ -139,23 +141,10 @@ struct cmCommandLineArgument index = nextValueIndex; } } else { - // parse the string to get the value - auto possible_value = cm::string_view(input).substr(this->Name.size()); - if (possible_value.empty()) { - parseState = ParseMode::ValueError; - } else if (possible_value[0] == '=') { - possible_value.remove_prefix(1); - if (possible_value.empty()) { - parseState = ParseMode::ValueError; - } - } + auto value = this->extract_single_value(input, parseState); if (parseState == ParseMode::Valid) { - if (possible_value[0] == ' ') { - possible_value.remove_prefix(1); - } - - parseState = this->StoreCall(std::string(possible_value), - std::forward(state)...) + parseState = + this->StoreCall(value, std::forward(state)...) ? ParseMode::Valid : ParseMode::Invalid; } @@ -193,7 +182,13 @@ struct cmCommandLineArgument index = (nextValueIndex - 1); } } else { - parseState = ParseMode::SyntaxError; + auto value = this->extract_single_value(input, parseState); + if (parseState == ParseMode::Valid) { + parseState = + this->StoreCall(value, std::forward(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } } } @@ -205,4 +200,24 @@ struct cmCommandLineArgument } return (parseState == ParseMode::Valid); } + +private: + std::string extract_single_value(std::string const& input, + ParseMode& parseState) const + { + // parse the string to get the value + auto possible_value = cm::string_view(input).substr(this->Name.size()); + if (possible_value.empty()) { + parseState = ParseMode::ValueError; + } else if (possible_value[0] == '=') { + possible_value.remove_prefix(1); + if (possible_value.empty()) { + parseState = ParseMode::ValueError; + } + } + if (parseState == ParseMode::Valid && possible_value[0] == ' ') { + possible_value.remove_prefix(1); + } + return std::string(possible_value); + } }; diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt index 5fe25390a25..fa3adc87435 100644 --- a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt @@ -1,2 +1 @@ -^CMake Error: '--target=invalid' is invalid syntax for --target -Usage: cmake --build \[ \| --preset \] \[options\] \[-- \[native-options\]\] +^Error: could not load cache From ceb82752efbd7a25d1b54e0b038712eecb70163b Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 18 May 2021 13:10:51 -0400 Subject: [PATCH 0475/1519] cmLocalNinjaGenerator: Use variable for main custom command output path --- Source/cmLocalNinjaGenerator.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index a8570e24997..82aa3c4c7ce 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -649,6 +649,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( gg->SeenCustomCommandOutput(ninjaOutput); } + std::string mainOutput = ninjaOutputs[0]; + cmNinjaDeps ninjaDeps; this->AppendCustomCommandDeps(ccg, ninjaDeps, fileConfig); @@ -657,13 +659,13 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( if (cmdLines.empty()) { cmNinjaBuild build("phony"); - build.Comment = "Phony custom command for " + ninjaOutputs[0]; + build.Comment = cmStrCat("Phony custom command for ", mainOutput); build.Outputs = std::move(ninjaOutputs); build.ExplicitDeps = std::move(ninjaDeps); build.OrderOnlyDeps = orderOnlyDeps; gg->WriteBuild(this->GetImplFileStream(fileConfig), build); } else { - std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]); + std::string customStep = cmSystemTools::GetFilenameName(mainOutput); if (this->GlobalGenerator->IsMultiConfig()) { customStep += '-'; customStep += fileConfig; @@ -673,7 +675,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( // Hash full path to make unique. customStep += '-'; cmCryptoHash hash(cmCryptoHash::AlgoSHA256); - customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7); + customStep += hash.HashString(mainOutput).substr(0, 7); std::string depfile = ccg.GetDepfile(); if (!depfile.empty()) { @@ -701,11 +703,12 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } } + std::string comment = cmStrCat("Custom command for ", mainOutput); gg->WriteCustomCommandBuild( this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig, customStep), - this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], - depfile, cc->GetJobPool(), cc->GetUsesTerminal(), + this->ConstructComment(ccg), comment, depfile, cc->GetJobPool(), + cc->GetUsesTerminal(), /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig, ninjaDeps, orderOnlyDeps); } From ddc030f5ca20d4519559e052b7c5538cf40f34f6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 18 May 2021 11:08:55 -0400 Subject: [PATCH 0476/1519] cmGlobalNinjaGenerator: Record implicit outputs as known too --- Source/cmGlobalNinjaGenerator.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 565b9514dac..a1a17c35d63 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -226,6 +226,9 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, buildStr += " |"; for (std::string const& implicitOut : build.ImplicitOuts) { buildStr += cmStrCat(' ', this->EncodePath(implicitOut)); + if (this->ComputingUnknownDependencies) { + this->CombinedBuildOutputs.insert(implicitOut); + } } } buildStr += ':'; From 8bac527b0c8ada5c40171cf01f673f9597ffdb90 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 18 May 2021 14:34:48 -0400 Subject: [PATCH 0477/1519] cmGlobalNinjaGenerator: Re-order logic in WriteCustomCommandBuild Save explicit dependencies earlier. --- Source/cmGlobalNinjaGenerator.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index a1a17c35d63..f7b338fb018 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -319,6 +319,14 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( { this->AddCustomCommandRule(); + if (this->ComputingUnknownDependencies) { + // we need to track every dependency that comes in, since we are trying + // to find dependencies that are side effects of build commands + for (std::string const& dep : explicitDeps) { + this->CombinedCustomCommandExplicitDependencies.insert(dep); + } + } + { cmNinjaBuild build("CUSTOM_COMMAND"); build.Comment = comment; @@ -354,14 +362,6 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( this->WriteBuild(*this->GetImplFileStream(config), build); } } - - if (this->ComputingUnknownDependencies) { - // we need to track every dependency that comes in, since we are trying - // to find dependencies that are side effects of build commands - for (std::string const& dep : explicitDeps) { - this->CombinedCustomCommandExplicitDependencies.insert(dep); - } - } } void cmGlobalNinjaGenerator::AddMacOSXContentRule() From c5195193d3525dc2b661757e0039486e39b94f27 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 18 May 2021 11:09:22 -0400 Subject: [PATCH 0478/1519] cmGlobalNinjaGenerator: Reduce string copies in WriteCustomCommandBuild Re-order arguments to group those with similar roles. Use move semantics to avoid copying vectors of strings. --- Source/cmGlobalNinjaGenerator.cxx | 20 ++++++++++---------- Source/cmGlobalNinjaGenerator.h | 16 +++++++++------- Source/cmLocalNinjaGenerator.cxx | 5 +++-- Source/cmNinjaUtilityTargetGenerator.cxx | 2 +- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f7b338fb018..06f7e45e714 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -311,11 +311,11 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule() } void cmGlobalNinjaGenerator::WriteCustomCommandBuild( - const std::string& command, const std::string& description, - const std::string& comment, const std::string& depfile, - const std::string& job_pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, const std::string& config, - const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps) + std::string const& command, std::string const& description, + std::string const& comment, std::string const& depfile, + std::string const& job_pool, bool uses_terminal, bool restat, + std::string const& config, cmNinjaDeps outputs, cmNinjaDeps explicitDeps, + cmNinjaDeps orderOnlyDeps) { this->AddCustomCommandRule(); @@ -330,9 +330,9 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( { cmNinjaBuild build("CUSTOM_COMMAND"); build.Comment = comment; - build.Outputs = outputs; - build.ExplicitDeps = explicitDeps; - build.OrderOnlyDeps = orderOnlyDeps; + build.Outputs = std::move(outputs); + build.ExplicitDeps = std::move(explicitDeps); + build.OrderOnlyDeps = std::move(orderOnlyDeps); cmNinjaVars& vars = build.Variables; { @@ -1209,8 +1209,8 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() "Assume dependencies for generated source file.", /*depfile*/ "", /*job_pool*/ "", /*uses_terminal*/ false, - /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(), - orderOnlyDeps); + /*restat*/ true, std::string(), cmNinjaDeps(1, asd.first), cmNinjaDeps(), + std::move(orderOnlyDeps)); } } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 9f317087474..6fbdb8293a1 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -110,13 +110,15 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator void WriteBuild(std::ostream& os, cmNinjaBuild const& build, int cmdLineLimit = 0, bool* usedResponseFile = nullptr); - void WriteCustomCommandBuild( - const std::string& command, const std::string& description, - const std::string& comment, const std::string& depfile, - const std::string& pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, const std::string& config, - const cmNinjaDeps& explicitDeps = cmNinjaDeps(), - const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps()); + void WriteCustomCommandBuild(std::string const& command, + std::string const& description, + std::string const& comment, + std::string const& depfile, + std::string const& pool, bool uses_terminal, + bool restat, std::string const& config, + cmNinjaDeps outputs, + cmNinjaDeps explicitDeps = cmNinjaDeps(), + cmNinjaDeps orderOnlyDeps = cmNinjaDeps()); void WriteMacOSXContentBuild(std::string input, std::string output, const std::string& config); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 82aa3c4c7ce..a2090cfc206 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -709,8 +709,9 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( customStep), this->ConstructComment(ccg), comment, depfile, cc->GetJobPool(), cc->GetUsesTerminal(), - /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig, - ninjaDeps, orderOnlyDeps); + /*restat*/ !symbolic || !byproducts.empty(), fileConfig, + std::move(ninjaOutputs), std::move(ninjaDeps), + std::move(orderOnlyDeps)); } } } diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 7a04c470bcd..6297252f3ab 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -180,7 +180,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( gg->WriteCustomCommandBuild( command, desc, "Utility command for " + this->GetTargetName(), /*depfile*/ "", /*job_pool*/ "", uses_terminal, - /*restat*/ true, util_outputs, ccConfig, deps); + /*restat*/ true, ccConfig, std::move(util_outputs), std::move(deps)); } phonyBuild.ExplicitDeps.push_back(utilCommandName); From 68e5f92cada35068f71a8c46388aeb4eb1383bca Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 18 May 2021 11:43:11 -0400 Subject: [PATCH 0479/1519] cmGlobalNinjaGenerator: Factor out custom command output collection De-duplicate code paths calling ConvertToNinjaPath and SeenCustomCommandOutput on custom command outputs and custom target byproducts. --- Source/cmGlobalNinjaGenerator.cxx | 18 +++++++++++++++--- Source/cmGlobalNinjaGenerator.h | 15 ++++++++++++++- Source/cmLocalNinjaGenerator.cxx | 20 ++++++-------------- Source/cmNinjaUtilityTargetGenerator.cxx | 15 +++++---------- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 06f7e45e714..64aaf4863e2 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -310,11 +310,21 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule() this->AddRule(rule); } +void cmGlobalNinjaGenerator::CCOutputs::Add( + std::vector const& paths) +{ + for (std::string const& path : paths) { + std::string out = this->GG->ConvertToNinjaPath(path); + this->GG->SeenCustomCommandOutput(out); + this->ExplicitOuts.emplace_back(std::move(out)); + } +} + void cmGlobalNinjaGenerator::WriteCustomCommandBuild( std::string const& command, std::string const& description, std::string const& comment, std::string const& depfile, std::string const& job_pool, bool uses_terminal, bool restat, - std::string const& config, cmNinjaDeps outputs, cmNinjaDeps explicitDeps, + std::string const& config, CCOutputs outputs, cmNinjaDeps explicitDeps, cmNinjaDeps orderOnlyDeps) { this->AddCustomCommandRule(); @@ -330,7 +340,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( { cmNinjaBuild build("CUSTOM_COMMAND"); build.Comment = comment; - build.Outputs = std::move(outputs); + build.Outputs = std::move(outputs.ExplicitOuts); build.ExplicitDeps = std::move(explicitDeps); build.OrderOnlyDeps = std::move(orderOnlyDeps); @@ -1201,6 +1211,8 @@ void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os) const void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() { for (auto const& asd : this->AssumedSourceDependencies) { + CCOutputs outputs(this); + outputs.ExplicitOuts.emplace_back(asd.first); cmNinjaDeps orderOnlyDeps; std::copy(asd.second.begin(), asd.second.end(), std::back_inserter(orderOnlyDeps)); @@ -1209,7 +1221,7 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() "Assume dependencies for generated source file.", /*depfile*/ "", /*job_pool*/ "", /*uses_terminal*/ false, - /*restat*/ true, std::string(), cmNinjaDeps(1, asd.first), cmNinjaDeps(), + /*restat*/ true, std::string(), outputs, cmNinjaDeps(), std::move(orderOnlyDeps)); } } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 6fbdb8293a1..2833367e577 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -110,13 +110,26 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator void WriteBuild(std::ostream& os, cmNinjaBuild const& build, int cmdLineLimit = 0, bool* usedResponseFile = nullptr); + class CCOutputs + { + cmGlobalNinjaGenerator* GG; + + public: + CCOutputs(cmGlobalNinjaGenerator* gg) + : GG(gg) + { + } + void Add(std::vector const& outputs); + cmNinjaDeps ExplicitOuts; + }; + void WriteCustomCommandBuild(std::string const& command, std::string const& description, std::string const& comment, std::string const& depfile, std::string const& pool, bool uses_terminal, bool restat, std::string const& config, - cmNinjaDeps outputs, + CCOutputs outputs, cmNinjaDeps explicitDeps = cmNinjaDeps(), cmNinjaDeps orderOnlyDeps = cmNinjaDeps()); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index a2090cfc206..9eb3e46136f 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -638,18 +638,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } } - cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size()); - std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(), - gg->MapToNinjaPath()); - std::transform(byproducts.begin(), byproducts.end(), - ninjaOutputs.begin() + outputs.size(), - gg->MapToNinjaPath()); - - for (std::string const& ninjaOutput : ninjaOutputs) { - gg->SeenCustomCommandOutput(ninjaOutput); - } + cmGlobalNinjaGenerator::CCOutputs ccOutputs(gg); + ccOutputs.Add(outputs); + ccOutputs.Add(byproducts); - std::string mainOutput = ninjaOutputs[0]; + std::string mainOutput = ccOutputs.ExplicitOuts[0]; cmNinjaDeps ninjaDeps; this->AppendCustomCommandDeps(ccg, ninjaDeps, fileConfig); @@ -660,7 +653,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( if (cmdLines.empty()) { cmNinjaBuild build("phony"); build.Comment = cmStrCat("Phony custom command for ", mainOutput); - build.Outputs = std::move(ninjaOutputs); + build.Outputs = std::move(ccOutputs.ExplicitOuts); build.ExplicitDeps = std::move(ninjaDeps); build.OrderOnlyDeps = orderOnlyDeps; gg->WriteBuild(this->GetImplFileStream(fileConfig), build); @@ -710,8 +703,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( this->ConstructComment(ccg), comment, depfile, cc->GetJobPool(), cc->GetUsesTerminal(), /*restat*/ !symbolic || !byproducts.empty(), fileConfig, - std::move(ninjaOutputs), std::move(ninjaDeps), - std::move(orderOnlyDeps)); + std::move(ccOutputs), std::move(ninjaDeps), std::move(orderOnlyDeps)); } } } diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 6297252f3ab..1f5a7ff4c5b 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -73,7 +73,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( cmNinjaBuild phonyBuild("phony"); std::vector commands; cmNinjaDeps deps; - cmNinjaDeps util_outputs(1, utilCommandName); + cmGlobalNinjaGenerator::CCOutputs util_outputs(gg); + util_outputs.ExplicitOuts.emplace_back(utilCommandName); bool uses_terminal = false; { @@ -86,10 +87,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( cmCustomCommandGenerator ccg(ci, fileConfig, lg); lg->AppendCustomCommandDeps(ccg, deps, fileConfig); lg->AppendCustomCommandLines(ccg, commands); - std::vector const& ccByproducts = ccg.GetByproducts(); - std::transform(ccByproducts.begin(), ccByproducts.end(), - std::back_inserter(util_outputs), - this->MapToNinjaPath()); + util_outputs.Add(ccg.GetByproducts()); if (ci.GetUsesTerminal()) { uses_terminal = true; } @@ -124,7 +122,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) { lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(), config); - std::copy(util_outputs.begin(), util_outputs.end(), + std::copy(util_outputs.ExplicitOuts.begin(), + util_outputs.ExplicitOuts.end(), std::back_inserter(gg->GetByproductsForCleanTarget())); } lg->AppendTargetDepends(genTarget, deps, config, fileConfig, @@ -166,10 +165,6 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( return; } - for (std::string const& util_output : util_outputs) { - gg->SeenCustomCommandOutput(util_output); - } - std::string ccConfig; if (genTarget->Target->IsPerConfig() && genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { From ae927f936d6bfc6c5004fc6c47994f481b9d6796 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 May 2021 11:32:02 -0400 Subject: [PATCH 0480/1519] cmGlobalNinjaGenerator: Improve allocation pattern in WriteBuild --- Source/cmGlobalNinjaGenerator.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 64aaf4863e2..a0baf3ffc56 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -216,25 +216,24 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, { // Write explicit outputs for (std::string const& output : build.Outputs) { - buildStr += cmStrCat(' ', this->EncodePath(output)); + buildStr = cmStrCat(buildStr, ' ', this->EncodePath(output)); if (this->ComputingUnknownDependencies) { this->CombinedBuildOutputs.insert(output); } } // Write implicit outputs if (!build.ImplicitOuts.empty()) { - buildStr += " |"; + buildStr = cmStrCat(buildStr, " |"); for (std::string const& implicitOut : build.ImplicitOuts) { - buildStr += cmStrCat(' ', this->EncodePath(implicitOut)); + buildStr = cmStrCat(buildStr, ' ', this->EncodePath(implicitOut)); if (this->ComputingUnknownDependencies) { this->CombinedBuildOutputs.insert(implicitOut); } } } - buildStr += ':'; // Write the rule. - buildStr += cmStrCat(' ', build.Rule); + buildStr = cmStrCat(buildStr, ": ", build.Rule); } std::string arguments; From bc40cd7a4e107be68debb01760700850d4c1106c Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 18 May 2021 13:24:43 -0400 Subject: [PATCH 0481/1519] Tests: Add case covering a unity build with a generated source Exclude the case on generators where it does not yet work. Issue: #21865 --- .../CustomCommandUnityBuild.cmake | 19 ++++++++++++++ .../CustomCommandUnityBuild.step1.cmake | 3 +++ .../CustomCommandUnityBuild.step2.cmake | 3 +++ .../RunCMake/BuildDepends/RunCMakeTest.cmake | 25 +++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake create mode 100644 Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake create mode 100644 Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake new file mode 100644 index 00000000000..22e7f273317 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.cmake @@ -0,0 +1,19 @@ +enable_language(C) + +add_custom_command( + OUTPUT main.c + COMMAND ${CMAKE_COMMAND} -E copy main.c.in main.c + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/main.c.in + ) +add_executable(main main.c) +set_property(TARGET main PROPERTY UNITY_BUILD ON) + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$>.cmake CONTENT " +set(check_pairs + \"$|${CMAKE_CURRENT_BINARY_DIR}/main.c.in\" + \"$|${CMAKE_CURRENT_BINARY_DIR}/main.c\" + ) +set(check_exes + \"$\" + ) +") diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake new file mode 100644 index 00000000000..87576ebf002 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step1.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[ +int main(void) { return 1; } +]]) diff --git a/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake new file mode 100644 index 00000000000..69b21b8319d --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandUnityBuild.step2.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[ +int main(void) { return 2; } +]]) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 72faddb0c89..947a2fe2fba 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -1,5 +1,22 @@ include(RunCMake) +if(RunCMake_GENERATOR MATCHES "Ninja") + # Detect ninja version so we know what tests can be supported. + execute_process( + COMMAND "${RunCMake_MAKE_PROGRAM}" --version + OUTPUT_VARIABLE ninja_out + ERROR_VARIABLE ninja_out + RESULT_VARIABLE ninja_res + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+") + set(ninja_version "${ninja_out}") + message(STATUS "ninja version: ${ninja_version}") + else() + message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}") + endif() +endif() + if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR RunCMake_GENERATOR STREQUAL "Watcom WMake") set(fs_delay 3) @@ -164,3 +181,11 @@ endif() if(RunCMake_GENERATOR MATCHES "Make") run_BuildDepends(MakeDependencies) endif() + +if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 " OR + RunCMake_GENERATOR MATCHES "Ninja") + # This build tool misses the dependency. + set(run_BuildDepends_skip_step_2 1) +endif() +run_BuildDepends(CustomCommandUnityBuild) +unset(run_BuildDepends_skip_step_2) From 99ff75455ece5ec4add771a2de93b237ab858d08 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Wed, 19 May 2021 10:15:16 +0200 Subject: [PATCH 0482/1519] install: Implement new install(CODE|SCRIPT) option ALL_COMPONENTS In a per-component installation the generated installation scripts are invoked once for each component. Per default custom installation script code added by install(CODE|SCRIPT) only runs for one specific component in this context. The new ALL_COMPONENTS option allows custom script code to be run once for each component being installed. --- Help/command/install.rst | 8 ++- Help/manual/cmake-file-api.7.rst | 5 ++ .../dev/install-script-all-components.rst | 7 +++ Source/cmFileAPICodemodel.cxx | 5 ++ Source/cmInstallCommand.cxx | 12 ++++- Source/cmInstallDirectoryGenerator.cxx | 2 +- Source/cmInstallExportGenerator.cxx | 2 +- Source/cmInstallFilesGenerator.cxx | 2 +- Source/cmInstallGenerator.cxx | 18 ++++--- Source/cmInstallGenerator.h | 5 +- Source/cmInstallScriptGenerator.cxx | 5 +- Source/cmInstallScriptGenerator.h | 2 +- Source/cmInstallSubdirectoryGenerator.cxx | 2 +- Source/cmInstallTargetGenerator.cxx | 2 +- Source/cmLocalGenerator.cxx | 4 +- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 4 ++ .../directories/external.json | 2 + .../codemodel-v2-data/directories/object.json | 2 + .../codemodel-v2-data/directories/top.json | 54 +++++++++++++++++++ Tests/RunCMake/FileAPI/codemodel-v2.cmake | 1 + Tests/RunCMake/install/RunCMakeTest.cmake | 1 + .../SCRIPT-ALL_COMPONENTS-all-check.cmake | 1 + .../SCRIPT-ALL_COMPONENTS-dev-check.cmake | 1 + .../SCRIPT-ALL_COMPONENTS-uns-check.cmake | 1 + .../install/SCRIPT-ALL_COMPONENTS.cmake | 5 ++ 25 files changed, 133 insertions(+), 20 deletions(-) create mode 100644 Help/release/dev/install-script-all-components.rst create mode 100644 Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake create mode 100644 Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake create mode 100644 Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake create mode 100644 Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake diff --git a/Help/command/install.rst b/Help/command/install.rst index 993cf7f3f3c..2259176d746 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -619,7 +619,7 @@ Custom Installation Logic .. code-block:: cmake install([[SCRIPT ] [CODE ]] - [COMPONENT ] [EXCLUDE_FROM_ALL] [...]) + [COMPONENT ] [EXCLUDE_FROM_ALL] [ALL_COMPONENTS] [...]) The ``SCRIPT`` form will invoke the given CMake script files during installation. If the script file name is a relative path it will be @@ -634,6 +634,12 @@ example, the code will print a message during installation. +The option ``ALL_COMPONENTS`` + .. versionadded:: 3.21 + + Run the custom installation script code for every component of a + component-specific installation. + .. versionadded:: 3.14 ```` or ```` may use "generator expressions" with the syntax ``$<...>`` (in the case of ````, this refers to their use in the file diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 445ebeb4da6..0e530bc0bd2 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -751,6 +751,11 @@ with members: Optional member that is present with boolean value ``true`` when :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option. + ``isForAllComponents`` + Optional member that is present with boolean value ``true`` when + :command:`install(SCRIPT|CODE)` is called with the + ``ALL_COMPONENTS`` option. + ``isOptional`` Optional member that is present with boolean value ``true`` when :command:`install` is called with the ``OPTIONAL`` option. diff --git a/Help/release/dev/install-script-all-components.rst b/Help/release/dev/install-script-all-components.rst new file mode 100644 index 00000000000..e421d3df781 --- /dev/null +++ b/Help/release/dev/install-script-all-components.rst @@ -0,0 +1,7 @@ +install-script-all-components +----------------------------- + +* The :command:`install(SCRIPT|CODE)` command + supports a new option ``ALL_COMPONENTS`` which allows + the corresponding code to run for every component of + a per component installation. diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 6b358423f14..945b5475ca4 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -1016,6 +1016,11 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) if (gen->GetExcludeFromAll()) { installer["isExcludeFromAll"] = true; } + + if (gen->GetAllComponentsFlag()) { + installer["isForAllComponents"] = true; + } + this->AddBacktrace(installer, gen->GetBacktrace()); return installer; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index d5d6d93350b..e973764814f 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -161,6 +161,7 @@ bool HandleScriptMode(std::vector const& args, bool doing_script = false; bool doing_code = false; bool exclude_from_all = false; + bool all_components = false; // Scan the args once for COMPONENT. Only allow one. // @@ -172,6 +173,8 @@ bool HandleScriptMode(std::vector const& args, } if (args[i] == "EXCLUDE_FROM_ALL") { exclude_from_all = true; + } else if (args[i] == "ALL_COMPONENTS") { + all_components = true; } } @@ -182,6 +185,11 @@ bool HandleScriptMode(std::vector const& args, return false; } + if (all_components && componentCount == 1) { + status.SetError("ALL_COMPONENTS and COMPONENT are mutually exclusive"); + return false; + } + // Scan the args again, this time adding install generators each time we // encounter a SCRIPT or CODE arg: // @@ -208,14 +216,14 @@ bool HandleScriptMode(std::vector const& args, } helper.Makefile->AddInstallGenerator( cm::make_unique( - script, false, component, exclude_from_all, + script, false, component, exclude_from_all, all_components, helper.Makefile->GetBacktrace())); } else if (doing_code) { doing_code = false; std::string const& code = arg; helper.Makefile->AddInstallGenerator( cm::make_unique( - code, true, component, exclude_from_all, + code, true, component, exclude_from_all, all_components, helper.Makefile->GetBacktrace())); } } diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index 4eb5f69e480..86362e48bba 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -18,7 +18,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator( MessageLevel message, bool exclude_from_all, std::string literal_args, bool optional, cmListFileBacktrace backtrace) : cmInstallGenerator(dest, configurations, component, message, - exclude_from_all, std::move(backtrace)) + exclude_from_all, false, std::move(backtrace)) , LocalGenerator(nullptr) , Directories(dirs) , FilePermissions(std::move(file_permissions)) diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index fdc3f8c1a3b..ccefd92c220 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -26,7 +26,7 @@ cmInstallExportGenerator::cmInstallExportGenerator( std::string filename, std::string name_space, bool exportOld, bool android, cmListFileBacktrace backtrace) : cmInstallGenerator(destination, configurations, component, message, - exclude_from_all, std::move(backtrace)) + exclude_from_all, false, std::move(backtrace)) , ExportSet(exportSet) , FilePermissions(std::move(file_permissions)) , FileName(std::move(filename)) diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 556c938274a..04aaa29a31d 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -17,7 +17,7 @@ cmInstallFilesGenerator::cmInstallFilesGenerator( MessageLevel message, bool exclude_from_all, std::string rename, bool optional, cmListFileBacktrace backtrace) : cmInstallGenerator(dest, configurations, component, message, - exclude_from_all, std::move(backtrace)) + exclude_from_all, false, std::move(backtrace)) , LocalGenerator(nullptr) , Files(files) , FilePermissions(std::move(file_permissions)) diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 98e37666d20..cf5f45e3db4 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -11,12 +11,13 @@ cmInstallGenerator::cmInstallGenerator( std::string destination, std::vector const& configurations, std::string component, MessageLevel message, bool exclude_from_all, - cmListFileBacktrace backtrace) + bool all_components, cmListFileBacktrace backtrace) : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations) , Destination(std::move(destination)) , Component(std::move(component)) , Message(message) , ExcludeFromAll(exclude_from_all) + , AllComponents(all_components) , Backtrace(std::move(backtrace)) { } @@ -160,15 +161,20 @@ void cmInstallGenerator::GenerateScript(std::ostream& os) Indent indent; // Begin this block of installation. - std::string component_test = - this->CreateComponentTest(this->Component, this->ExcludeFromAll); - os << indent << "if(" << component_test << ")\n"; + if (!this->AllComponents) { + std::string component_test = + this->CreateComponentTest(this->Component, this->ExcludeFromAll); + os << indent << "if(" << component_test << ")\n"; + } // Generate the script possibly with per-configuration code. - this->GenerateScriptConfigs(os, indent.Next()); + this->GenerateScriptConfigs(os, + this->AllComponents ? indent : indent.Next()); // End this block of installation. - os << indent << "endif()\n\n"; + if (!this->AllComponents) { + os << indent << "endif()\n\n"; + } } bool cmInstallGenerator::InstallsForConfig(const std::string& config) diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 6cd9ff9bb9c..0117617cdbf 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -33,7 +33,8 @@ class cmInstallGenerator : public cmScriptGenerator cmInstallGenerator(std::string destination, std::vector const& configurations, std::string component, MessageLevel message, - bool exclude_from_all, cmListFileBacktrace backtrace); + bool exclude_from_all, bool all_components, + cmListFileBacktrace backtrace); ~cmInstallGenerator() override; cmInstallGenerator(cmInstallGenerator const&) = delete; @@ -65,6 +66,7 @@ class cmInstallGenerator : public cmScriptGenerator std::string const& GetComponent() const { return this->Component; } bool GetExcludeFromAll() const { return this->ExcludeFromAll; } + bool GetAllComponentsFlag() const { return this->AllComponents; } cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } @@ -79,5 +81,6 @@ class cmInstallGenerator : public cmScriptGenerator std::string const Component; MessageLevel const Message; bool const ExcludeFromAll; + bool const AllComponents; cmListFileBacktrace const Backtrace; }; diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index bb389906ad3..bec98b6e91c 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -14,9 +14,10 @@ cmInstallScriptGenerator::cmInstallScriptGenerator( std::string script, bool code, std::string const& component, - bool exclude_from_all, cmListFileBacktrace backtrace) + bool exclude_from_all, bool all_components, cmListFileBacktrace backtrace) : cmInstallGenerator("", std::vector(), component, - MessageDefault, exclude_from_all, std::move(backtrace)) + MessageDefault, exclude_from_all, all_components, + std::move(backtrace)) , Script(std::move(script)) , Code(code) , AllowGenex(false) diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index 6274f1cd2e0..2cf6a4b6f4b 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -21,7 +21,7 @@ class cmInstallScriptGenerator : public cmInstallGenerator public: cmInstallScriptGenerator( std::string script, bool code, std::string const& component, - bool exclude_from_all, + bool exclude_from_all, bool all_components, cmListFileBacktrace backtrace = cmListFileBacktrace()); ~cmInstallScriptGenerator() override; diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx index 76806e535a5..0fcfa546fec 100644 --- a/Source/cmInstallSubdirectoryGenerator.cxx +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -17,7 +17,7 @@ cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator( cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll, cmListFileBacktrace backtrace) : cmInstallGenerator("", std::vector(), "", MessageDefault, - excludeFromAll, std::move(backtrace)) + excludeFromAll, false, std::move(backtrace)) , Makefile(makefile) , BinaryDirectory(std::move(binaryDirectory)) { diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index eb214fa1c74..3e79ad8b096 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -46,7 +46,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator( std::string const& component, MessageLevel message, bool exclude_from_all, bool optional, cmListFileBacktrace backtrace) : cmInstallGenerator(dest, configurations, component, message, - exclude_from_all, std::move(backtrace)) + exclude_from_all, false, std::move(backtrace)) , TargetName(std::move(targetName)) , Target(nullptr) , FilePermissions(std::move(file_permissions)) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4db9216056c..0c686aa2963 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3317,7 +3317,7 @@ void cmLocalGenerator::GenerateTargetInstallRules( // Include the user-specified pre-install script for this target. if (cmProp preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) { - cmInstallScriptGenerator g(*preinstall, false, "", false); + cmInstallScriptGenerator g(*preinstall, false, "", false, false); g.Generate(os, config, configurationTypes); } @@ -3370,7 +3370,7 @@ void cmLocalGenerator::GenerateTargetInstallRules( // Include the user-specified post-install script for this target. if (cmProp postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) { - cmInstallScriptGenerator g(*postinstall, false, "", false); + cmInstallScriptGenerator g(*postinstall, false, "", false, false); g.Generate(os, config, configurationTypes); } } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 0d718a4e7c0..b9a1fbfc6a2 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -136,6 +136,10 @@ def _check(actual, expected): expected_keys.append("isExcludeFromAll") assert is_bool(a["isExcludeFromAll"], e["isExcludeFromAll"]) + if e["isForAllComponents"] is not None: + expected_keys.append("isForAllComponents") + assert is_bool(a["isForAllComponents"], e["isForAllComponents"]) + if e["isOptional"] is not None: expected_keys.append("isOptional") assert is_bool(a["isOptional"], e["isOptional"]) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json index 55dd57327e5..6d2952d143a 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json @@ -20,6 +20,7 @@ "^.*/Tests/RunCMake/FileAPIExternalSource/\\.$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": null, "targetIndex": null, @@ -51,6 +52,7 @@ "^.*/Tests/RunCMake/FileAPIExternalSource$" ], "isExcludeFromAll": true, + "isForAllComponents": null, "isOptional": null, "targetId": null, "targetIndex": null, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json index ef2dd0b61bb..44bc72545d6 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json @@ -23,6 +23,7 @@ "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?c_object_exe(\\.exe)?$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^c_object_exe::@5ed5358f70faf8d8af7a$", "targetIndex": "c_object_exe", @@ -54,6 +55,7 @@ "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_object_exe(\\.exe)?$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^cxx_object_exe::@5ed5358f70faf8d8af7a$", "targetIndex": "cxx_object_exe", diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json index 472760703df..99287fb6f03 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json @@ -35,6 +35,7 @@ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^cxx_exe::@a56b12a3f5c0529fb296$", "targetIndex": "cxx_exe", @@ -78,6 +79,7 @@ "^((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(lib|dll\\.a)$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$", "targetIndex": "c_shared_lib", @@ -126,6 +128,7 @@ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1|1\\.dylib)$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$", "targetIndex": "c_shared_lib", @@ -169,6 +172,7 @@ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?cxx_shared_lib\\.(lib|dll\\.a)$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$", "targetIndex": "cxx_shared_lib", @@ -213,6 +217,7 @@ "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(dll|so|dylib)$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$", "targetIndex": "cxx_shared_lib", @@ -256,6 +261,7 @@ "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(dll|so|dylib)$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$", "targetIndex": "c_shared_lib", @@ -302,6 +308,7 @@ } ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": true, "targetId": null, "targetIndex": null, @@ -346,6 +353,7 @@ "^empty\\.h$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": null, "targetIndex": null, @@ -394,6 +402,7 @@ } ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": true, "targetId": null, "targetIndex": null, @@ -445,6 +454,7 @@ } ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": null, "targetIndex": null, @@ -488,6 +498,7 @@ "^CMakeFiles/Export/lib/cmake/foo/FooTargets\\.cmake$" ], "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": null, "targetIndex": null, @@ -534,6 +545,7 @@ "destination": null, "paths": null, "isExcludeFromAll": null, + "isForAllComponents": null, "isOptional": null, "targetId": null, "targetIndex": null, @@ -568,6 +580,48 @@ "hasParent": false } ] + }, + { + "component": "Unspecified", + "type": "code", + "destination": null, + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": true, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 54, + "command": "install", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] } ] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake index 528f07546d1..da928ebfc89 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake @@ -51,3 +51,4 @@ install(DIRECTORY . dir cxx/ OPTIONAL DESTINATION dir1) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}/cxx/" DESTINATION dir2) install(EXPORT FooTargets DESTINATION lib/cmake/foo) install(SCRIPT InstallScript.cmake) +install(CODE "message(foo)" ALL_COMPONENTS) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 3e567466c06..94887a0dbed 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -179,3 +179,4 @@ run_install_test(FILES-EXCLUDE_FROM_ALL) run_install_test(TARGETS-EXCLUDE_FROM_ALL) run_install_test(TARGETS-NAMELINK_COMPONENT) run_install_test(SCRIPT-COMPONENT) +run_install_test(SCRIPT-ALL_COMPONENTS) diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake new file mode 100644 index 00000000000..48d8e1aec60 --- /dev/null +++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake @@ -0,0 +1 @@ +check_installed([[^empty1.txt;empty2.txt$]]) diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake new file mode 100644 index 00000000000..48d8e1aec60 --- /dev/null +++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake @@ -0,0 +1 @@ +check_installed([[^empty1.txt;empty2.txt$]]) diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake new file mode 100644 index 00000000000..48d8e1aec60 --- /dev/null +++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake @@ -0,0 +1 @@ +check_installed([[^empty1.txt;empty2.txt$]]) diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake new file mode 100644 index 00000000000..aa3f9d1b7a4 --- /dev/null +++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake @@ -0,0 +1,5 @@ +install( + SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake" + CODE "write_empty_file(empty2.txt)" + ALL_COMPONENTS + ) From 2725ecff38ccd25905a9bc968bfb1b2f0d09b34a Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 May 2021 10:21:11 -0400 Subject: [PATCH 0483/1519] Ninja: Handle depfiles with absolute paths to generated files Ninja treats every (normalized) path as its own node. It does not recognize `/abs/path/to/file` in a depfile as matching `path/to/file` even when `build.ninja` and the working directory are in `/abs/`. See Ninja Issue 1251. In cases where we pass absolute paths to the compiler, it will write a depfile containing absolute paths. If those files are generated in the build tree by custom commands, `build.ninja` references them by relative path in build statement outputs, so Ninja does not hook up the dependency and rebuild the project correctly. Add infrastructure to work around this problem by adding implicit outputs to custom command build statements that reference the main outputs by absolute path. Use a `${cmake_ninja_workdir}` placeholder to avoid repeating the base path. For example: build out.txt | ${cmake_ninja_workdir}out.txt: CUSTOM_COMMAND ... Ninja will create two nodes for the output file, one with a relative path and one with an absolute path. A depfile may then mention either form of the path and Ninja will hook up the dependency. Unfortunately Ninja will also stat the file twice. Issue: #13894 Fixes: #21865 --- Source/cmGlobalNinjaGenerator.cxx | 17 ++++++++++++++++- Source/cmGlobalNinjaGenerator.h | 1 + Source/cmLocalNinjaGenerator.cxx | 13 +++++++++++++ Source/cmLocalNinjaGenerator.h | 1 + Source/cmNinjaTypes.h | 1 + Tests/RunCMake/BuildDepends/RunCMakeTest.cmake | 2 +- 6 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index a0baf3ffc56..6034434e2cf 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -222,7 +222,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, } } // Write implicit outputs - if (!build.ImplicitOuts.empty()) { + if (!build.ImplicitOuts.empty() || !build.WorkDirOuts.empty()) { buildStr = cmStrCat(buildStr, " |"); for (std::string const& implicitOut : build.ImplicitOuts) { buildStr = cmStrCat(buildStr, ' ', this->EncodePath(implicitOut)); @@ -230,6 +230,14 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, this->CombinedBuildOutputs.insert(implicitOut); } } + for (std::string const& workdirOut : build.WorkDirOuts) { + // Repeat some outputs, but expressed as absolute paths. + // This helps Ninja handle absolute paths found in a depfile. + // FIXME: Unfortunately this causes Ninja to stat the file twice. + // We could avoid this if Ninja Issue 1251 were fixed. + buildStr = cmStrCat(buildStr, " ${cmake_ninja_workdir}", + this->EncodePath(workdirOut)); + } } // Write the rule. @@ -314,6 +322,12 @@ void cmGlobalNinjaGenerator::CCOutputs::Add( { for (std::string const& path : paths) { std::string out = this->GG->ConvertToNinjaPath(path); + if (this->GG->SupportsImplicitOuts() && + !cmSystemTools::FileIsFullPath(out)) { + // This output is expressed as a relative path. Repeat it, + // but expressed as an absolute path for Ninja Issue 1251. + this->WorkDirOuts.emplace_back(out); + } this->GG->SeenCustomCommandOutput(out); this->ExplicitOuts.emplace_back(std::move(out)); } @@ -340,6 +354,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( cmNinjaBuild build("CUSTOM_COMMAND"); build.Comment = comment; build.Outputs = std::move(outputs.ExplicitOuts); + build.WorkDirOuts = std::move(outputs.WorkDirOuts); build.ExplicitDeps = std::move(explicitDeps); build.OrderOnlyDeps = std::move(orderOnlyDeps); diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 2833367e577..7a3674e76f3 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -121,6 +121,7 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator } void Add(std::vector const& outputs); cmNinjaDeps ExplicitOuts; + cmNinjaDeps WorkDirOuts; }; void WriteCustomCommandBuild(std::string const& command, diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 9eb3e46136f..fb6c730e6a9 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -263,6 +263,7 @@ void cmLocalNinjaGenerator::WriteBuildFileTop() this->GetConfigNames().front()); } this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream()); + this->WriteNinjaWorkDir(this->GetCommonFileStream()); // For the rule file. this->WriteProjectHeader(this->GetRulesFileStream()); @@ -364,6 +365,17 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os) os << "\n"; } +void cmLocalNinjaGenerator::WriteNinjaWorkDir(std::ostream& os) +{ + cmGlobalNinjaGenerator::WriteDivider(os); + cmGlobalNinjaGenerator::WriteComment( + os, "Logical path to working directory; prefix for absolute paths."); + cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator(); + std::string ninja_workdir = this->GetBinaryDirectory(); + ng->StripNinjaOutputPathPrefixAsSuffix(ninja_workdir); // Also appends '/'. + os << "cmake_ninja_workdir = " << ng->EncodePath(ninja_workdir) << "\n"; +} + void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); @@ -654,6 +666,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( cmNinjaBuild build("phony"); build.Comment = cmStrCat("Phony custom command for ", mainOutput); build.Outputs = std::move(ccOutputs.ExplicitOuts); + build.WorkDirOuts = std::move(ccOutputs.WorkDirOuts); build.ExplicitDeps = std::move(ninjaDeps); build.OrderOnlyDeps = orderOnlyDeps; gg->WriteBuild(this->GetImplFileStream(fileConfig), build); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index a73fa275f18..64040374e40 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -108,6 +108,7 @@ class cmLocalNinjaGenerator : public cmLocalCommonGenerator const std::string& config); void WriteNinjaFilesInclusionConfig(std::ostream& os); void WriteNinjaFilesInclusionCommon(std::ostream& os); + void WriteNinjaWorkDir(std::ostream& os); void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h index 320f41bb323..c8a411e1dfa 100644 --- a/Source/cmNinjaTypes.h +++ b/Source/cmNinjaTypes.h @@ -53,6 +53,7 @@ class cmNinjaBuild std::string Rule; cmNinjaDeps Outputs; cmNinjaDeps ImplicitOuts; + cmNinjaDeps WorkDirOuts; // For cmake_ninja_workdir. cmNinjaDeps ExplicitDeps; cmNinjaDeps ImplicitDeps; cmNinjaDeps OrderOnlyDeps; diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 947a2fe2fba..0a8058049bd 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -183,7 +183,7 @@ if(RunCMake_GENERATOR MATCHES "Make") endif() if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 " OR - RunCMake_GENERATOR MATCHES "Ninja") + (RunCMake_GENERATOR MATCHES "Ninja" AND ninja_version VERSION_LESS 1.7)) # This build tool misses the dependency. set(run_BuildDepends_skip_step_2 1) endif() From 34f9a551ce5631baef159076c697dd8f86daa8b8 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 20 May 2021 00:01:08 -0400 Subject: [PATCH 0484/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 83a41c16b14..f559e04c5bc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210519) +set(CMake_VERSION_PATCH 20210520) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0a0a0f8a744e2bfa35cdbc90db6e4e23adadd59b Mon Sep 17 00:00:00 2001 From: Marius Messerschmidt Date: Tue, 18 May 2021 23:32:44 +0200 Subject: [PATCH 0485/1519] cmMessenger: Color messages to terminal by type Fixes: #16183 --- Help/release/dev/message-color.rst | 4 ++++ Source/cmMessageMetadata.h | 3 +++ Source/cmMessenger.cxx | 18 ++++++++++++++++++ Source/cmakemain.cxx | 11 +++++++---- 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/message-color.rst diff --git a/Help/release/dev/message-color.rst b/Help/release/dev/message-color.rst new file mode 100644 index 00000000000..4acf15e9ff7 --- /dev/null +++ b/Help/release/dev/message-color.rst @@ -0,0 +1,4 @@ +message-color +------------- + +* Messages printed to a terminal now may be colored by message type. diff --git a/Source/cmMessageMetadata.h b/Source/cmMessageMetadata.h index 5688dc57a2d..7b56faed7bd 100644 --- a/Source/cmMessageMetadata.h +++ b/Source/cmMessageMetadata.h @@ -2,7 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include "cmsys/Terminal.h" + struct cmMessageMetadata { const char* title = nullptr; + int desiredColor = cmsysTerminal_Color_Normal; }; diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index 4c0faa9236b..1cb638ac25e 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -13,6 +13,8 @@ #include +#include "cmsys/Terminal.h" + MessageType cmMessenger::ConvertMessageType(MessageType t) const { bool warningsAsErrors; @@ -85,6 +87,21 @@ static bool printMessagePreamble(MessageType t, std::ostream& msg) return true; } +static int getMessageColor(MessageType t) +{ + switch (t) { + case MessageType::INTERNAL_ERROR: + case MessageType::FATAL_ERROR: + case MessageType::AUTHOR_ERROR: + return cmsysTerminal_Color_ForegroundRed; + case MessageType::AUTHOR_WARNING: + case MessageType::WARNING: + return cmsysTerminal_Color_ForegroundYellow; + default: + return cmsysTerminal_Color_Normal; + } +} + void printMessageText(std::ostream& msg, std::string const& text) { msg << ":\n"; @@ -122,6 +139,7 @@ void displayMessage(MessageType t, std::ostringstream& msg) // Output the message. cmMessageMetadata md; + md.desiredColor = getMessageColor(t); if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR || t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) { cmSystemTools::SetErrorOccured(); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 60ac0caa726..93eb4156975 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmMessageMetadata.h" #include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" @@ -37,8 +39,7 @@ #endif #include "cmsys/Encoding.hxx" - -struct cmMessageMetadata; +#include "cmsys/Terminal.h" namespace { #ifndef CMAKE_BOOTSTRAP @@ -150,9 +151,11 @@ std::string cmakemainGetStack(cmake* cm) } void cmakemainMessageCallback(const std::string& m, - const cmMessageMetadata& /* unused */, cmake* cm) + const cmMessageMetadata& md, cmake* cm) { - std::cerr << m << cmakemainGetStack(cm) << std::endl; + cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str()); + fflush(stderr); // stderr is buffered in some cases. + std::cerr << cmakemainGetStack(cm) << "\n"; } void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm) From 8a9753e4279788ff30bd59c0a9f88392fa3cfd68 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Thu, 20 May 2021 22:37:40 +1000 Subject: [PATCH 0486/1519] ExternalProject: Only add git config setting with git 1.7.7 or later 1cb65e680d (ExternalProject: Prevent the noisy detached head messages on checkout, 2021-01-17) unconditionally added the advice.detachedHead git config setting, but it requires git 1.7.7 or later. Since it isn't fatal to not have it, just noisier, only add it when it is supported. Fixes: #22206 --- Modules/ExternalProject.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 56525080cc2..90ed1ee63b0 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -2663,9 +2663,11 @@ function(_ep_add_download_command name) get_property(git_progress TARGET ${name} PROPERTY _EP_GIT_PROGRESS) get_property(git_config TARGET ${name} PROPERTY _EP_GIT_CONFIG) - # Make checkouts quiet when checking out a git hash (this avoids the - # very noisy detached head message) - list(PREPEND git_config advice.detachedHead=false) + # If git supports it, make checkouts quiet when checking out a git hash. + # This avoids the very noisy detached head message. + if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7) + list(PREPEND git_config advice.detachedHead=false) + endif() # For the download step, and the git clone operation, only the repository # should be recorded in a configured RepositoryInfo file. If the repo From d96eb5528276a19d79116d842389f3ea165ef21b Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 20 May 2021 15:14:30 +0200 Subject: [PATCH 0487/1519] set(CACHE): do not remove normal variable Fixes: #22038 --- Help/command/set.rst | 10 ++++-- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0126.rst | 20 ++++++++++++ Help/release/dev/set-cache-variable.rst | 5 +++ Source/cmFindBase.cxx | 35 ++++++++++++++++++--- Source/cmFindPackageCommand.cxx | 5 +++ Source/cmMakefile.cxx | 8 ++--- Source/cmOptionCommand.cxx | 7 +++++ Source/cmPolicies.h | 5 ++- Tests/RunCMake/CMP0126/CMP0126-NEW.cmake | 28 +++++++++++++++++ Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake | 9 ++++++ Tests/RunCMake/CMP0126/CMP0126-OLD.cmake | 25 +++++++++++++++ Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake | 9 ++++++ Tests/RunCMake/CMP0126/CMakeLists.txt | 3 ++ Tests/RunCMake/CMP0126/RunCMakeTest.cmake | 6 ++++ Tests/RunCMake/CMakeLists.txt | 1 + 16 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 Help/policy/CMP0126.rst create mode 100644 Help/release/dev/set-cache-variable.rst create mode 100644 Tests/RunCMake/CMP0126/CMP0126-NEW.cmake create mode 100644 Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake create mode 100644 Tests/RunCMake/CMP0126/CMP0126-OLD.cmake create mode 100644 Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake create mode 100644 Tests/RunCMake/CMP0126/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0126/RunCMakeTest.cmake diff --git a/Help/command/set.rst b/Help/command/set.rst index c0e02e2465a..af862e4da3e 100644 --- a/Help/command/set.rst +++ b/Help/command/set.rst @@ -68,9 +68,13 @@ users. If the cache entry does not exist prior to the call or the ``FORCE`` option is given then the cache entry will be set to the given value. -Furthermore, any normal variable binding in the current scope will -be removed to expose the newly cached value to any immediately -following evaluation. + +.. note:: + + The content of the cache variable will not be directly accessible if a normal + variable of the same name already exists (see :ref:`rules of variable + evaluation `). If policy :policy:`CMP0126` is set + to ``OLD``, any normal variable binding in the current scope will be removed. It is possible for the cache entry to exist prior to the call but have no type set if it was created on the :manual:`cmake(1)` command diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 62ccb015003..b9e3d452fdd 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.21 .. toctree:: :maxdepth: 1 + CMP0126: set(CACHE) does not remove a normal variable of the same name. CMP0125: find_(path|file|library|program) have consistent behavior for cache variables. CMP0124: foreach() loop variables are only available in the loop scope. CMP0123: ARMClang cpu/arch compile and link flags must be set explicitly. diff --git a/Help/policy/CMP0126.rst b/Help/policy/CMP0126.rst new file mode 100644 index 00000000000..4c8e9281424 --- /dev/null +++ b/Help/policy/CMP0126.rst @@ -0,0 +1,20 @@ +CMP0126 +------- + +.. versionadded:: 3.21 + +The :command:`set(CACHE)` does not remove a normal variable of the same name. + +Starting with CMake 3.21, the :command:`set(CACHE)` does not remove, in the +current scope, any normal variable with the same name. + +The ``OLD`` behavior for this policy is to have the :command:`set(CACHE)` +command removing the normal variable of the same name, if any. The ``NEW`` +behavior for this policy is to keep the normal variable of the same name. + +This policy was introduced in CMake version 3.21. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn when the policy +is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/set-cache-variable.rst b/Help/release/dev/set-cache-variable.rst new file mode 100644 index 00000000000..a96242c7cff --- /dev/null +++ b/Help/release/dev/set-cache-variable.rst @@ -0,0 +1,5 @@ +set-cache-variable +------------------ + +* The :command:`set(CACHE)` command no longer removes a normal variable of the + same name, if any. See policy :policy:`CMP0126`. diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 6296d06e243..c1281e3278b 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -357,11 +357,17 @@ void cmFindBase::NormalizeFindResult() this->Makefile->GetCMakeInstance()->AddCacheEntry( this->VariableName, value.c_str(), this->VariableDocumentation.c_str(), this->VariableType); - // if there was a definition then remove it - // This is required to ensure same behavior as - // cmMakefile::AddCacheDefinition. - // See #22038 for problems raised by this behavior. - this->Makefile->RemoveDefinition(this->VariableName); + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == + cmPolicies::NEW) { + if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition(this->VariableName, value); + } + } else { + // if there was a definition then remove it + // This is required to ensure same behavior as + // cmMakefile::AddCacheDefinition. + this->Makefile->RemoveDefinition(this->VariableName); + } } } else { // If the user specifies the entry on the command line without a @@ -371,6 +377,14 @@ void cmFindBase::NormalizeFindResult() this->Makefile->AddCacheDefinition(this->VariableName, "", this->VariableDocumentation.c_str(), this->VariableType); + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == + cmPolicies::NEW && + this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition( + this->VariableName, + *this->Makefile->GetCMakeInstance()->GetCacheDefinition( + this->VariableName)); + } } } } @@ -379,17 +393,28 @@ void cmFindBase::StoreFindResult(const std::string& value) { bool force = this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) == cmPolicies::NEW; + bool updateNormalVariable = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW; if (!value.empty()) { this->Makefile->AddCacheDefinition(this->VariableName, value, this->VariableDocumentation.c_str(), this->VariableType, force); + if (updateNormalVariable && + this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition(this->VariableName, value); + } return; } this->Makefile->AddCacheDefinition( this->VariableName, cmStrCat(this->VariableName, "-NOTFOUND"), this->VariableDocumentation.c_str(), this->VariableType, force); + if (updateNormalVariable && + this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition(this->VariableName, + cmStrCat(this->VariableName, "-NOTFOUND")); + } if (this->Required) { this->Makefile->IssueMessage( diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 3719fe194b6..fba736eed64 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1138,6 +1138,11 @@ bool cmFindPackageCommand::FindConfig() // We force the value since we do not get here if it was already set. this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), cmStateEnums::PATH, true); + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == + cmPolicies::NEW && + this->Makefile->IsNormalDefinitionSet(this->Variable)) { + this->Makefile->AddDefinition(this->Variable, init); + } return found; } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 4ffd47bec6f..d7987c26624 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1962,10 +1962,10 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, } } this->GetCMakeInstance()->AddCacheEntry(name, value, doc, type); - // if there was a definition then remove it - // The method cmFindBase::NormalizeFindResult also apply same workflow. - // See #22038 for problems raised by this behavior. - this->StateSnapshot.RemoveDefinition(name); + if (this->GetPolicyStatus(cmPolicies::CMP0126) != cmPolicies::NEW) { + // if there was a definition then remove it + this->StateSnapshot.RemoveDefinition(name); + } } void cmMakefile::MarkVariableAsUsed(const std::string& var) diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index a58e2f8cc82..bae67e04d18 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -68,6 +68,13 @@ bool cmOptionCommand(std::vector const& args, bool init = cmIsOn(initialValue); status.GetMakefile().AddCacheDefinition(args[0], init ? "ON" : "OFF", args[1].c_str(), cmStateEnums::BOOL); + if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077) != + cmPolicies::NEW && + status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0126) == + cmPolicies::NEW) { + // if there was a definition then remove it + status.GetMakefile().GetStateSnapshot().RemoveDefinition(args[0]); + } if (checkAndWarn) { const auto* existsAfterSet = diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 3ebb17d6262..f7c0d2592e7 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -376,7 +376,10 @@ class cmMakefile; SELECT(POLICY, CMP0125, \ "find_(path|file|library|program) have consistent behavior for " \ "cache variables.", \ - 3, 21, 0, cmPolicies::WARN) + 3, 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0126, \ + "set(CACHE) does not remove a normal variable of the same name.", 3, \ + 21, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/CMP0126/CMP0126-NEW.cmake b/Tests/RunCMake/CMP0126/CMP0126-NEW.cmake new file mode 100644 index 00000000000..2f8562bb9a9 --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-NEW.cmake @@ -0,0 +1,28 @@ + +# enforce policy CMP0125 to ensure predictable result of find_* commands +cmake_policy(SET CMP0125 NEW) + +cmake_policy(SET CMP0126 NEW) + +set(VAR 1) +set(VAR 2 CACHE STRING "") + +if (NOT VAR EQUAL 1) + message(FATAL_ERROR "normal variable does not exist anymore.") +endif() + + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/file.txt" "") +set(VAR file.txt) +set(VAR "" CACHE STRING "" FORCE) +set_property(CACHE VAR PROPERTY TYPE UNINITIALIZED) + +find_file(VAR NAMES file.txt PATHS "${CMAKE_CURRENT_BINARY_DIR}") + +unset(VAR CACHE) +if (NOT DEFINED VAR) + message(FATAL_ERROR "find_file: normal variable does not exist anymore.") +endif() +if (NOT VAR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/file.txt") + message(FATAL_ERROR "find_file: failed to set normal variable.") +endif() diff --git a/Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake b/Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake new file mode 100644 index 00000000000..cfaa1e303e4 --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-NEW_CL.cmake @@ -0,0 +1,9 @@ + +cmake_policy(SET CMP0126 NEW) + +set(VAR 1) +set(VAR 2 CACHE STRING "") + +if (NOT VAR EQUAL 1) + message(FATAL_ERROR "normal variable does not exist anymore.") +endif() diff --git a/Tests/RunCMake/CMP0126/CMP0126-OLD.cmake b/Tests/RunCMake/CMP0126/CMP0126-OLD.cmake new file mode 100644 index 00000000000..22a50377777 --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-OLD.cmake @@ -0,0 +1,25 @@ + +# enforce policy CMP0125 to ensure predictable result of find_* commands +cmake_policy(SET CMP0125 NEW) + +cmake_policy(SET CMP0126 OLD) + +set(VAR 1) +set(VAR 2 CACHE STRING "") + +if (VAR EQUAL 1) + message(FATAL_ERROR "normal variable still exist.") +endif() + + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/file.txt" "") +set(VAR file.txt) +set(VAR "" CACHE STRING "" FORCE) +set_property(CACHE VAR PROPERTY TYPE UNINITIALIZED) + +find_file(VAR NAMES file.txt PATHS "${CMAKE_CURRENT_BINARY_DIR}") + +unset(VAR CACHE) +if (DEFINED VAR) + message(FATAL_ERROR "find_file: normal variable still exist.") +endif() diff --git a/Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake b/Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake new file mode 100644 index 00000000000..5d72a876544 --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-OLD_CL.cmake @@ -0,0 +1,9 @@ + +cmake_policy(SET CMP0126 OLD) + +set(VAR 1) +set(VAR 2 CACHE STRING "") + +if (NOT VAR EQUAL 3) + message(FATAL_ERROR "normal variable still exist.") +endif() diff --git a/Tests/RunCMake/CMP0126/CMakeLists.txt b/Tests/RunCMake/CMP0126/CMakeLists.txt new file mode 100644 index 00000000000..7cabeb68b2f --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.20) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0126/RunCMakeTest.cmake b/Tests/RunCMake/CMP0126/RunCMakeTest.cmake new file mode 100644 index 00000000000..ae988f4c68d --- /dev/null +++ b/Tests/RunCMake/CMP0126/RunCMakeTest.cmake @@ -0,0 +1,6 @@ +include(RunCMake) + +run_cmake(CMP0126-OLD) +run_cmake_with_options(CMP0126-OLD_CL -DVAR=3) +run_cmake(CMP0126-NEW) +run_cmake_with_options(CMP0126-NEW_CL -DVAR=3) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index afaeaef6410..14a7fa3cbcf 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -140,6 +140,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)") add_RunCMake_test(CMP0125 -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}) endif() +add_RunCMake_test(CMP0126) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode From 820d3afb2881265a811cffd42b66f9288932bf1d Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 20 May 2021 13:24:31 -0400 Subject: [PATCH 0488/1519] Framework: Fix $ for imported frameworks --- Source/cmGeneratorTarget.cxx | 29 +++++++++++++++++-- .../ImportedFrameworkTest-build-stdout.txt | 1 + .../Framework/ImportedFrameworkTest.cmake | 10 +++++++ Tests/RunCMake/Framework/RunCMakeTest.cmake | 12 ++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt create mode 100644 Tests/RunCMake/Framework/ImportedFrameworkTest.cmake diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index bbc0050d3dc..e2ec82a5e24 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -52,6 +52,11 @@ class cmMessenger; +namespace { +const cmsys::RegularExpression FrameworkRegularExpression( + "^(.*/)?([^/]*)\\.framework/(.*)$"); +} + template <> cmProp cmTargetPropertyComputer::GetSources( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, @@ -2257,8 +2262,16 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const return cmSystemTools::GetFilenameName(info->Location); } // Use the soname given if any. + if (this->IsFrameworkOnApple()) { + cmsys::RegularExpressionMatch match; + if (FrameworkRegularExpression.find(info->SOName.c_str(), match)) { + auto frameworkName = match.match(2); + auto fileName = match.match(3); + return cmStrCat(frameworkName, ".framework/", fileName); + } + } if (cmHasLiteralPrefix(info->SOName, "@rpath/")) { - return info->SOName.substr(6); + return info->SOName.substr(cmStrLen("@rpath/")); } return info->SOName; } @@ -6459,9 +6472,19 @@ std::string cmGeneratorTarget::GetDirectory( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { + auto fullPath = this->Target->ImportedGetFullPath(config, artifact); + if (this->IsFrameworkOnApple()) { + cmsys::RegularExpressionMatch match; + if (FrameworkRegularExpression.find(fullPath.c_str(), match)) { + auto path = match.match(1); + if (!path.empty()) { + path.erase(path.length() - 1); + } + return path; + } + } // Return the directory from which the target is imported. - return cmSystemTools::GetFilenamePath( - this->Target->ImportedGetFullPath(config, artifact)); + return cmSystemTools::GetFilenamePath(fullPath); } if (OutputInfo const* info = this->GetOutputInfo(config)) { // Return the directory in which the target will be built. diff --git a/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt b/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt new file mode 100644 index 00000000000..bd75ccdf4d4 --- /dev/null +++ b/Tests/RunCMake/Framework/ImportedFrameworkTest-build-stdout.txt @@ -0,0 +1 @@ +xxx/no/exist/fw\.framework/Versions/A/fwxxx diff --git a/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake b/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake new file mode 100644 index 00000000000..42edaea4fed --- /dev/null +++ b/Tests/RunCMake/Framework/ImportedFrameworkTest.cmake @@ -0,0 +1,10 @@ +add_library(fw SHARED IMPORTED) +set_target_properties(fw PROPERTIES + FRAMEWORK TRUE + IMPORTED_LOCATION "/no/exist/fw.framework/Versions/A/fw" + IMPORTED_SONAME "@rpath/fw.framework/Versions/A/fw" + ) + +add_custom_target(print_fw ALL COMMAND + ${CMAKE_COMMAND} -E echo "xxx$xxx" + ) diff --git a/Tests/RunCMake/Framework/RunCMakeTest.cmake b/Tests/RunCMake/Framework/RunCMakeTest.cmake index 6ee61a30b73..36eaf5c9486 100644 --- a/Tests/RunCMake/Framework/RunCMakeTest.cmake +++ b/Tests/RunCMake/Framework/RunCMakeTest.cmake @@ -81,3 +81,15 @@ function(framework_multi_config_postfix_test) endfunction() framework_multi_config_postfix_test() + +function(imported_framework_test) + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ImportedFrameworkTest-build") + set(RunCMake_TEST_NO_CLEAN 1) + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(ImportedFrameworkTest) + run_cmake_command(ImportedFrameworkTest-build ${CMAKE_COMMAND} --build .) +endfunction() + +imported_framework_test() From f9067e806f7a7863cdb439e267750a2047814181 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 21 May 2021 00:01:09 -0400 Subject: [PATCH 0489/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f559e04c5bc..fc19c77b4d6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210520) +set(CMake_VERSION_PATCH 20210521) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ef25359edac842614029f0cceb040f9b65cc817c Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 21 May 2021 12:31:28 -0400 Subject: [PATCH 0490/1519] ci: add MPICH to Fedora base image --- .gitlab/ci/docker/fedora34/install_deps.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index ece0666d51f..dfd7db80936 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -68,6 +68,7 @@ dnf install --setopt=install_weak_deps=False -y \ libuv-devel \ libxml2-devel \ libxslt-devel \ + mpich-devel \ openmpi-devel \ patch \ perl \ From 2bc0708c39470d6ce612047d9864c1bbf2e67304 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 21 May 2021 12:32:39 -0400 Subject: [PATCH 0491/1519] ci: Switch to MPICH in Fedora jobs The OpenMPI package in Fedora 34 requires a CPU with AVX instructions. Some of our CI machines do not have them, and so fail the FindMPI.Test test with `SIGILL`. Switch to MPICH. Since we test with OpenMPI on the Debian jobs, this covers more MPI vendors anyway. --- .gitlab/ci/env_fedora34_makefiles.cmake | 2 +- .gitlab/os-linux.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/env_fedora34_makefiles.cmake b/.gitlab/ci/env_fedora34_makefiles.cmake index 1d0efa7d5ac..aa84e2396ad 100644 --- a/.gitlab/ci/env_fedora34_makefiles.cmake +++ b/.gitlab/ci/env_fedora34_makefiles.cmake @@ -1,2 +1,2 @@ set(ENV{MY_RUBY_HOME} "/usr/local/rvm/rubies/ruby-2.7.0") -set(ENV{PATH} "/usr/lib64/openmpi/bin:$ENV{PATH}") +set(ENV{PATH} "/usr/lib64/mpich/bin:$ENV{PATH}") diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 1bf4098956c..dcaa6438470 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -69,7 +69,7 @@ ### Fedora .fedora34: - image: "kitware/cmake:ci-fedora34-x86_64-2021-05-10" + image: "kitware/cmake:ci-fedora34-x86_64-2021-05-21" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" From 7ee3ccbbeabfcd27ebfbab48b05539134e63cb8f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 22 May 2021 00:01:12 -0400 Subject: [PATCH 0492/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fc19c77b4d6..a0283887bd3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210521) +set(CMake_VERSION_PATCH 20210522) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e16b06f4b913c222aeb09c7465e372ca5e46bf83 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 22 May 2021 11:14:03 +0300 Subject: [PATCH 0493/1519] FindCUDA: Make the deprecation notice more prominent FindCUDA is still widely used, but has been superseded by the much more robust native language support. However the deprecation hasn't been noticed well enough and real-world experience shows there's still new code written to use it. Change this particular notice to a warning to get a hard to miss red box. We lose the semantic meaning, but we don't want to make all notices like this. If there are similar cases in the future requiring it would be worth adding a custom variant of the deprecated directive. Fixes #22203. --- Modules/FindCUDA.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 16d75711b2b..57482f11ab8 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -2,7 +2,7 @@ FindCUDA -------- -.. deprecated:: 3.10 +.. warning:: *Deprecated since version 3.10.* It is no longer necessary to use this module or call ``find_package(CUDA)`` for compiling CUDA code. Instead, list ``CUDA`` among the languages named From 15fda9384a99035b2e77cce608a6b6e296a952c9 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 22 May 2021 11:30:31 +0300 Subject: [PATCH 0494/1519] FindCUDA: Improve deprecation guidance wording Simplified the text regarding adding sources to be more general as there's also target_sources(). Improved the wording for FindCUDAToolkit to be more explicit of its usecase and avoid using "superseded" since the common usecase of FindCUDA was superseded by the language support. Wording suggestions incopropated from discussion on #22203. --- Modules/FindCUDA.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 57482f11ab8..dd795f449f6 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -8,13 +8,13 @@ It is no longer necessary to use this module or call ``find_package(CUDA)`` for compiling CUDA code. Instead, list ``CUDA`` among the languages named in the top-level call to the :command:`project` command, or call the :command:`enable_language` command with ``CUDA``. -Then one can add CUDA (``.cu``) sources to programs directly -in calls to :command:`add_library` and :command:`add_executable`. +Then one can add CUDA (``.cu``) sources directly to targets similar to other +languages. .. versionadded:: 3.17 - To find and use the CUDA toolkit libraries the :module:`FindCUDAToolkit` - module has superseded this module. It works whether or not the ``CUDA`` - language is enabled. + To find and use the CUDA toolkit libraries manually, use the + :module:`FindCUDAToolkit` module instead. It works regardless of the + ``CUDA`` language being enabled. Documentation of Deprecated Usage ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 95df258b7fe10f132de10cc9d53a0e710605392f Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 23 May 2021 00:01:05 -0400 Subject: [PATCH 0495/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a0283887bd3..dafa9945d8b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210522) +set(CMake_VERSION_PATCH 20210523) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 26e36111d326bbf69f437ef1335423ea3b2835e2 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Wed, 19 May 2021 12:10:58 +0200 Subject: [PATCH 0496/1519] CPack: Implement new variable CPACK_CUSTOM_INSTALL_VARIABLES The new variable allows projects to define custom key=value pairs of variables to be set in CPack cmake_install.cmake script invocations. This allows install(SCRIPT|CODE) to be parameterized at runtime. --- Help/manual/cmake-variables.7.rst | 1 + Help/release/dev/cpack-install-opts.rst | 6 +++ .../CPACK_CUSTOM_INSTALL_VARIABLES.rst | 42 +++++++++++++++++++ Source/CPack/cmCPackGenerator.cxx | 17 ++++++++ Tests/RunCMake/CPack/RunCMakeTest.cmake | 1 + .../ExpectedFiles.cmake | 7 ++++ .../CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake | 7 ++++ 7 files changed, 81 insertions(+) create mode 100644 Help/release/dev/cpack-install-opts.rst create mode 100644 Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst create mode 100644 Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 33beba989bc..0720d49dc56 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -671,6 +671,7 @@ Variables for CPack /variable/CPACK_ABSOLUTE_DESTINATION_FILES /variable/CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY + /variable/CPACK_CUSTOM_INSTALL_VARIABLES /variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION /variable/CPACK_INCLUDE_TOPLEVEL_DIRECTORY /variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS diff --git a/Help/release/dev/cpack-install-opts.rst b/Help/release/dev/cpack-install-opts.rst new file mode 100644 index 00000000000..970f9a9bf04 --- /dev/null +++ b/Help/release/dev/cpack-install-opts.rst @@ -0,0 +1,6 @@ +cpack-install-opts +------------------ + +* The new :variable:`CPACK_CUSTOM_INSTALL_VARIABLES` + can be used to set variables in CPack ``cmake_install.cmake`` + invocations. diff --git a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst new file mode 100644 index 00000000000..534e2ada3a9 --- /dev/null +++ b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst @@ -0,0 +1,42 @@ +CPACK_CUSTOM_INSTALL_VARIABLES +------------------------------ + +CPack variables (set via e.g. ``cpack -D``, ``CPackConfig.cmake`` or +:variable:`CPACK_PROJECT_CONFIG_FILE` scripts) are not directly visible in +installation scripts. Instead, one can pass a list of ``varName=value`` +pairs in the ``CPACK_CUSTOM_INSTALL_VARIABLES`` variable. At install time, +each list item will result in a variable of the specified name (``varName``) +being set to the given ``value``. The ``=`` can be omitted for an empty +``value``. + +``CPACK_CUSTOM_INSTALL_VARIABLES`` allows the packaging installation to be +influenced by the user or driving script at CPack runtime without having to +regenerate the install scripts. + +Example +""""""" + +.. code-block:: cmake + + install(FILES large.txt DESTINATION data) + + install(CODE [[ + if(ENABLE_COMPRESSION) + # "run-compressor" is a fictional tool that produces + # large.txt.xz from large.txt and then removes the input file + execute_process(COMMAND run-compressor $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/large.txt) + endif() + ]]) + +With the above example snippet, :manual:`cpack ` will by default +run the installation script with ``ENABLE_COMPRESSION`` unset, resulting in +a package containing the uncompressed ``large.txt``. This can be overridden +when invoking :manual:`cpack ` like so: + +.. code-block:: shell + + cpack -D "CPACK_CUSTOM_INSTALL_VARIABLES=ENABLE_COMPRESSION=TRUE" + +The installation script will then run with ``ENABLE_COMPRESSION`` set to +``TRUE``, resulting in a package containing the compressed ``large.txt.xz`` +instead. diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index cd2adaa304b..00e274d6d0b 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -902,6 +902,23 @@ int cmCPackGenerator::InstallCMakeProject( this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) { mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1"); } + + std::vector custom_variables; + this->MakefileMap->GetDefExpandList("CPACK_CUSTOM_INSTALL_VARIABLES", + custom_variables); + + for (auto const& custom_variable : custom_variables) { + std::string value; + + auto i = custom_variable.find('='); + + if (i != std::string::npos) { + value = custom_variable.substr(i + 1); + } + + mf.AddDefinition(custom_variable.substr(0, i), value); + } + // do installation bool res = mf.ReadListFile(installFile); // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index a3c72a1cf29..746ff8b1c07 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -37,6 +37,7 @@ unset(ENVIRONMENT) run_cpack_test(USER_FILELIST "RPM.USER_FILELIST" false "MONOLITHIC") run_cpack_test(MD5SUMS "DEB.MD5SUMS" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests(CPACK_INSTALL_SCRIPTS "singular;plural;both" "ZIP" false "MONOLITHIC") +run_cpack_test(CPACK_CUSTOM_INSTALL_VARIABLES "ZIP" false "MONOLITHIC") run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad;stage_and_package" "External" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests( diff --git a/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake new file mode 100644 index 00000000000..a05513b2fcf --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/ExpectedFiles.cmake @@ -0,0 +1,7 @@ +set(EXPECTED_FILES_COUNT "1") +set(EXPECTED_FILE_CONTENT_1_LIST + "/foo" + "/foo/bar.txt" + "/foo/baz.txt" + "/foo/foo.txt" +) diff --git a/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake new file mode 100644 index 00000000000..4a12f198781 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CPACK_CUSTOM_INSTALL_VARIABLES/test.cmake @@ -0,0 +1,7 @@ +set(CPACK_CUSTOM_INSTALL_VARIABLES "FOO=foo.txt" "BAR=bar.txt") + +install(CODE [[ + file(WRITE ${CMAKE_INSTALL_PREFIX}/foo/${FOO}) + file(WRITE ${CMAKE_INSTALL_PREFIX}/foo/${BAR}) + file(WRITE ${CMAKE_INSTALL_PREFIX}/foo/baz.txt) +]]) From c3b9d9b756c84961208ad3086f5f123828fc5400 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 24 May 2021 00:01:10 -0400 Subject: [PATCH 0497/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index dafa9945d8b..b80af475ed3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210523) +set(CMake_VERSION_PATCH 20210524) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From c3bd5a6a2cb0f08d125655967a2f52bdd551ae6b Mon Sep 17 00:00:00 2001 From: Jake Cobb Date: Fri, 21 May 2021 07:43:10 -0400 Subject: [PATCH 0498/1519] cmake-gui: Unset empty CC,CXX on global generator change On subsequent runs of configure from cmake-gui the global generator is swapped. So on runs other than the first it was setting CC and CXX to empty when they were otherwise undefined. Instead, restore them if non-empty and unset them if empty when changing the global generator and a previous generator exists. Fixes: #21449 --- Source/cmake.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 315bd20efa2..840a9d959cf 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1751,17 +1751,20 @@ void cmake::SetGlobalGenerator(std::unique_ptr gg) } if (this->GlobalGenerator) { // restore the original environment variables CXX and CC - // Restore CC std::string env = "CC="; if (!this->CCEnvironment.empty()) { env += this->CCEnvironment; + cmSystemTools::PutEnv(env); + } else { + cmSystemTools::UnPutEnv(env); } - cmSystemTools::PutEnv(env); env = "CXX="; if (!this->CXXEnvironment.empty()) { env += this->CXXEnvironment; + cmSystemTools::PutEnv(env); + } else { + cmSystemTools::UnPutEnv(env); } - cmSystemTools::PutEnv(env); } // set the new From 0ac6af4457daa8b247f645d13f6bb8adf9ec0259 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 24 May 2021 11:37:56 -0400 Subject: [PATCH 0499/1519] expat: Update script to get Expat 2.4.1 --- Utilities/Scripts/update-expat.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-expat.bash b/Utilities/Scripts/update-expat.bash index 75e492a1c09..a052c0edd3c 100755 --- a/Utilities/Scripts/update-expat.bash +++ b/Utilities/Scripts/update-expat.bash @@ -8,7 +8,7 @@ readonly name="expat" readonly ownership="Expat Upstream " readonly subtree="Utilities/cmexpat" readonly repo="https://github.com/libexpat/libexpat.git" -readonly tag="R_2_2_10" +readonly tag="R_2_4_1" readonly shortlog=false readonly paths=" expat/lib/asciitab.h From 2da34f062a9fa2aac32a4b1da247a7828da5b6b4 Mon Sep 17 00:00:00 2001 From: Expat Upstream Date: Sun, 23 May 2021 17:56:03 +0200 Subject: [PATCH 0500/1519] expat 2021-05-23 (a28238bd) Code extracted from: https://github.com/libexpat/libexpat.git at commit a28238bdeebc087071777001245df1876a11f5ee (R_2_4_1). --- README.md | 89 ++- lib/ascii.h | 7 +- lib/asciitab.h | 4 +- lib/expat.h | 38 +- lib/expat_external.h | 9 +- lib/iasciitab.h | 4 +- lib/internal.h | 58 +- lib/latin1tab.h | 4 +- lib/nametab.h | 4 +- lib/siphash.h | 13 +- lib/utf8tab.h | 4 +- lib/winconfig.h | 19 +- lib/xmlparse.c | 1222 +++++++++++++++++++++++++++++++++++++++--- lib/xmlrole.c | 17 +- lib/xmlrole.h | 5 +- lib/xmltok.c | 42 +- lib/xmltok.h | 6 +- lib/xmltok_impl.c | 14 +- lib/xmltok_impl.h | 3 +- lib/xmltok_ns.c | 6 +- 20 files changed, 1405 insertions(+), 163 deletions(-) diff --git a/README.md b/README.md index 428a11ab245..251dc8a19b3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ -[![Travis CI Build Status](https://travis-ci.org/libexpat/libexpat.svg?branch=master)](https://travis-ci.org/libexpat/libexpat) +[![Run Linux Travis CI tasks](https://github.com/libexpat/libexpat/actions/workflows/linux.yml/badge.svg)](https://github.com/libexpat/libexpat/actions/workflows/linux.yml) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/libexpat/libexpat?svg=true)](https://ci.appveyor.com/project/libexpat/libexpat) [![Packaging status](https://repology.org/badge/tiny-repos/expat.svg)](https://repology.org/metapackage/expat/versions) +[![Downloads SourceForge](https://img.shields.io/sourceforge/dt/expat?label=Downloads%20SourceForge)](https://sourceforge.net/projects/expat/files/) +[![Downloads GitHub](https://img.shields.io/github/downloads/libexpat/libexpat/total?label=Downloads%20GitHub)](https://github.com/libexpat/libexpat/releases) -# Expat, Release 2.2.10 +# Expat, Release 2.4.1 This is Expat, a C library for parsing XML, started by -[James Clark](https://en.wikipedia.org/wiki/James_Clark_(programmer)) in 1997. +[James Clark](https://en.wikipedia.org/wiki/James_Clark_%28programmer%29) in 1997. Expat is a stream-oriented XML parser. This means that you register handlers with the parser before starting the parse. These handlers are called when the parser discovers the associated structures in the @@ -14,13 +16,14 @@ document being parsed. A start tag is an example of the kind of structures for which you may register handlers. Expat supports the following compilers: + - GNU GCC >=4.5 - LLVM Clang >=3.5 -- Microsoft Visual Studio >=9.0/2008 +- Microsoft Visual Studio >=15.0/2017 (rolling `${today} minus 5 years`) Windows users can use the -[`expat_win32` package](https://sourceforge.net/projects/expat/files/expat_win32/), -which includes both precompiled libraries and executables, and source code for +[`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases), +which includes both pre-compiled libraries and executables, and source code for developers. Expat is [free software](https://www.gnu.org/philosophy/free-sw.en.html). @@ -30,6 +33,67 @@ contained in the file distributed with this package. This license is the same as the MIT/X Consortium license. + +## Using libexpat in your CMake-Based Project + +There are two ways of using libexpat with CMake: + +### a) Module Mode + +This approach leverages CMake's own [module `FindEXPAT`](https://cmake.org/cmake/help/latest/module/FindEXPAT.html). + +Notice the *uppercase* `EXPAT` in the following example: + +```cmake +cmake_minimum_required(VERSION 3.0) # or 3.10, see below + +project(hello VERSION 1.0.0) + +find_package(EXPAT 2.2.8 MODULE REQUIRED) + +add_executable(hello + hello.c +) + +# a) for CMake >=3.10 (see CMake's FindEXPAT docs) +target_link_libraries(hello PUBLIC EXPAT::EXPAT) + +# b) for CMake >=3.0 +target_include_directories(hello PRIVATE ${EXPAT_INCLUDE_DIRS}) +target_link_libraries(hello PUBLIC ${EXPAT_LIBRARIES}) +``` + +### b) Config Mode + +This approach requires files from… + +- libexpat >=2.2.8 where packaging uses the CMake build system +or +- libexpat >=2.3.0 where packaging uses the GNU Autotools build system + on Linux +or +- libexpat >=2.4.0 where packaging uses the GNU Autotools build system + on macOS or MinGW. + +Notice the *lowercase* `expat` in the following example: + +```cmake +cmake_minimum_required(VERSION 3.0) + +project(hello VERSION 1.0.0) + +find_package(expat 2.2.8 CONFIG REQUIRED char dtd ns) + +add_executable(hello + hello.c +) + +target_link_libraries(hello PUBLIC expat::expat) +``` + + +## Building from a Git Clone + If you are building Expat from a check-out from the [Git repository](https://github.com/libexpat/libexpat/), you need to run a script that generates the configure script using the @@ -43,6 +107,11 @@ autoconf 2.58 or newer. Run the script like this: Once this has been done, follow the same instructions as for building from a source distribution. + +## Building from a Source Distribution + +### a) Building with the configure script (i.e. GNU Autotools) + To build Expat from a source distribution, you first run the configuration shell script in the top level distribution directory: @@ -132,8 +201,14 @@ A reference manual is available in the file `doc/reference.html` in this distribution. -The CMake build system is still *experimental* and will replace the primary +### b) Building with CMake + +The CMake build system is still *experimental* and may replace the primary build system based on GNU Autotools at some point when it is ready. + + +#### Available Options + For an idea of the available (non-advanced) options for building with CMake: ```console diff --git a/lib/ascii.h b/lib/ascii.h index c3587e57332..1f594d2e54b 100644 --- a/lib/ascii.h +++ b/lib/ascii.h @@ -6,8 +6,11 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 1999-2000 Thai Open Source Software Center Ltd + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2007 Karl Waclawek + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/asciitab.h b/lib/asciitab.h index 63b1d1b4482..af766fb2478 100644 --- a/lib/asciitab.h +++ b/lib/asciitab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/expat.h b/lib/expat.h index cb828db155f..b7d6d354801 100644 --- a/lib/expat.h +++ b/lib/expat.h @@ -7,7 +7,14 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2000-2005 Fred L. Drake, Jr. + Copyright (c) 2001-2002 Greg Stein + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016 Cristian Rodríguez + Copyright (c) 2016 Thomas Beutlich + Copyright (c) 2017 Rhodri James Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -115,7 +122,11 @@ enum XML_Error { XML_ERROR_RESERVED_PREFIX_XMLNS, XML_ERROR_RESERVED_NAMESPACE_URI, /* Added in 2.2.1. */ - XML_ERROR_INVALID_ARGUMENT + XML_ERROR_INVALID_ARGUMENT, + /* Added in 2.3.0. */ + XML_ERROR_NO_BUFFER, + /* Added in 2.4.0. */ + XML_ERROR_AMPLIFICATION_LIMIT_BREACH }; enum XML_Content_Type { @@ -513,7 +524,7 @@ typedef struct { Otherwise it must return XML_STATUS_ERROR. If info does not describe a suitable encoding, then the parser will - return an XML_UNKNOWN_ENCODING error. + return an XML_ERROR_UNKNOWN_ENCODING error. */ typedef int(XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, @@ -997,7 +1008,10 @@ enum XML_FeatureEnum { XML_FEATURE_SIZEOF_XML_LCHAR, XML_FEATURE_NS, XML_FEATURE_LARGE_SIZE, - XML_FEATURE_ATTR_INFO + XML_FEATURE_ATTR_INFO, + /* Added in Expat 2.4.0. */ + XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT /* Additional features must be added to the end of this enum. */ }; @@ -1010,12 +1024,24 @@ typedef struct { XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); +#ifdef XML_DTD +/* Added in Expat 2.4.0. */ +XMLPARSEAPI(XML_Bool) +XML_SetBillionLaughsAttackProtectionMaximumAmplification( + XML_Parser parser, float maximumAmplificationFactor); + +/* Added in Expat 2.4.0. */ +XMLPARSEAPI(XML_Bool) +XML_SetBillionLaughsAttackProtectionActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes); +#endif + /* Expat follows the semantic versioning convention. See http://semver.org. */ #define XML_MAJOR_VERSION 2 -#define XML_MINOR_VERSION 2 -#define XML_MICRO_VERSION 10 +#define XML_MINOR_VERSION 4 +#define XML_MICRO_VERSION 1 #ifdef __cplusplus } diff --git a/lib/expat_external.h b/lib/expat_external.h index b3b6e74d9d2..8829f770910 100644 --- a/lib/expat_external.h +++ b/lib/expat_external.h @@ -7,7 +7,14 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2000-2004 Fred L. Drake, Jr. + Copyright (c) 2001-2002 Greg Stein + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2016 Cristian Rodríguez + Copyright (c) 2016-2019 Sebastian Pipping + Copyright (c) 2017 Rhodri James + Copyright (c) 2018 Yury Gribov Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/iasciitab.h b/lib/iasciitab.h index ea97cfcf678..5d8646f2a31 100644 --- a/lib/iasciitab.h +++ b/lib/iasciitab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/internal.h b/lib/internal.h index 60913dab762..444eba0fb03 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -25,8 +25,12 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2002-2003 Fred L. Drake, Jr. + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2003 Greg Stein + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2018 Yury Gribov + Copyright (c) 2019 David Loffredo Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -101,22 +105,58 @@ # endif #endif +#include // ULONG_MAX + +#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO) +# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u" +# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u" +# else +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" +# endif +#else +# define EXPAT_FMT_ULL(midpart) "%" midpart "llu" +# if ! defined(ULONG_MAX) +# error Compiler did not define ULONG_MAX for us +# elif ULONG_MAX == 18446744073709551615u // 2^64-1 +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu" +# else +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" +# endif +#endif + #ifndef UNUSED_P # define UNUSED_P(p) (void)p #endif +/* NOTE BEGIN If you ever patch these defaults to greater values + for non-attack XML payload in your environment, + please file a bug report with libexpat. Thank you! +*/ +#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \ + 100.0f +#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \ + 8388608 // 8 MiB, 2^23 +/* NOTE END */ + +#include "expat.h" // so we can use type XML_Parser below + #ifdef __cplusplus extern "C" { #endif -#ifdef XML_ENABLE_VISIBILITY -# if XML_ENABLE_VISIBILITY -__attribute__((visibility("default"))) -# endif +void _INTERNAL_trim_to_complete_utf8_characters(const char *from, + const char **fromLimRef); + +#if defined(XML_DTD) +unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser); +unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser); +const char *unsignedCharToPrintable(unsigned char c); #endif -void -_INTERNAL_trim_to_complete_utf8_characters(const char *from, - const char **fromLimRef); #ifdef __cplusplus } diff --git a/lib/latin1tab.h b/lib/latin1tab.h index 6f916041355..b681d278af6 100644 --- a/lib/latin1tab.h +++ b/lib/latin1tab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/nametab.h b/lib/nametab.h index 3681df348ee..63485446b96 100644 --- a/lib/nametab.h +++ b/lib/nametab.h @@ -6,8 +6,8 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/siphash.h b/lib/siphash.h index bfee65a332f..e5406d7ee9e 100644 --- a/lib/siphash.h +++ b/lib/siphash.h @@ -11,6 +11,9 @@ * -------------------------------------------------------------------------- * HISTORY: * + * 2020-10-03 (Sebastian Pipping) + * - Drop support for Visual Studio 9.0/2008 and earlier + * * 2019-08-03 (Sebastian Pipping) * - Mark part of sip24_valid as to be excluded from clang-format * - Re-format code using clang-format 9 @@ -96,15 +99,7 @@ #define SIPHASH_H #include /* size_t */ - -#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600) -/* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */ -typedef unsigned __int8 uint8_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#else -# include /* uint64_t uint32_t uint8_t */ -#endif +#include /* uint64_t uint32_t uint8_t */ /* * Workaround to not require a C++11 compiler for using ULL suffix diff --git a/lib/utf8tab.h b/lib/utf8tab.h index a22986acbb9..88efcf91cc1 100644 --- a/lib/utf8tab.h +++ b/lib/utf8tab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/winconfig.h b/lib/winconfig.h index 562a4a82dc1..2ecd61b5b94 100644 --- a/lib/winconfig.h +++ b/lib/winconfig.h @@ -6,8 +6,10 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Greg Stein + Copyright (c) 2005 Karl Waclawek + Copyright (c) 2017-2021 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -40,17 +42,4 @@ #include #include -#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */ -# include -#else /* !defined(HAVE_EXPAT_CONFIG_H) */ - -# define XML_NS 1 -# define XML_DTD 1 -# define XML_CONTEXT_BYTES 1024 - -/* we will assume all Windows platforms are little endian */ -# define BYTEORDER 1234 - -#endif /* !defined(HAVE_EXPAT_CONFIG_H) */ - #endif /* ndef WINCONFIG_H */ diff --git a/lib/xmlparse.c b/lib/xmlparse.c index dfc316ca36c..5ba56eaea63 100644 --- a/lib/xmlparse.c +++ b/lib/xmlparse.c @@ -1,4 +1,4 @@ -/* 5cd169f2942b85c05e0b1b96f9990f91ac3d07e470ad7ce906ac8590c8ed4f35 (2.2.10+) +/* 8539b9040d9d901366a62560a064af7cb99811335784b363abc039c5b0ebc416 (2.4.1+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -7,7 +7,31 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2000-2006 Fred L. Drake, Jr. + Copyright (c) 2001-2002 Greg Stein + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2005-2009 Steven Solie + Copyright (c) 2016 Eric Rahm + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016 Gaurav + Copyright (c) 2016 Thomas Beutlich + Copyright (c) 2016 Gustavo Grieco + Copyright (c) 2016 Pascal Cuoq + Copyright (c) 2016 Ed Schouten + Copyright (c) 2017-2018 Rhodri James + Copyright (c) 2017 Václav Slavík + Copyright (c) 2017 Viktor Szakats + Copyright (c) 2017 Chanho Park + Copyright (c) 2017 Rolf Eike Beer + Copyright (c) 2017 Hans Wennborg + Copyright (c) 2018 Anton Maklakov + Copyright (c) 2018 Benjamin Peterson + Copyright (c) 2018 Marco Maggi + Copyright (c) 2018 Mariusz Zaborski + Copyright (c) 2019 David Loffredo + Copyright (c) 2019-2020 Ben Wagner + Copyright (c) 2019 Vadim Zeitlin Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -47,17 +71,8 @@ #include /* UINT_MAX */ #include /* fprintf */ #include /* getenv, rand_s */ - -#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600) -/* vs2008/9.0 and earlier lack stdint.h; _MSC_VER 1600 is vs2010/10.0 */ -# if defined(_WIN64) -typedef unsigned __int64 uintptr_t; -# else -typedef unsigned __int32 uintptr_t; -# endif -#else -# include /* uintptr_t */ -#endif +#include /* uintptr_t */ +#include /* isnan */ #ifdef _WIN32 # define getpid GetCurrentProcessId @@ -73,9 +88,9 @@ typedef unsigned __int32 uintptr_t; #ifdef _WIN32 # include "winconfig.h" -#elif defined(HAVE_EXPAT_CONFIG_H) -# include -#endif /* ndef _WIN32 */ +#endif + +#include #include "ascii.h" #include "expat.h" @@ -382,6 +397,31 @@ typedef struct open_internal_entity { XML_Bool betweenDecl; /* WFC: PE Between Declarations */ } OPEN_INTERNAL_ENTITY; +enum XML_Account { + XML_ACCOUNT_DIRECT, /* bytes directly passed to the Expat parser */ + XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity + expansion */ + XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */ +}; + +#ifdef XML_DTD +typedef unsigned long long XmlBigCount; +typedef struct accounting { + XmlBigCount countBytesDirect; + XmlBigCount countBytesIndirect; + int debugLevel; + float maximumAmplificationFactor; // >=1.0 + unsigned long long activationThresholdBytes; +} ACCOUNTING; + +typedef struct entity_stats { + unsigned int countEverOpened; + unsigned int currentDepth; + unsigned int maximumDepthSeen; + int debugLevel; +} ENTITY_STATS; +#endif /* XML_DTD */ + typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start, const char *end, const char **endPtr); @@ -412,16 +452,18 @@ static enum XML_Error initializeEncoding(XML_Parser parser); static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr, - XML_Bool haveMore, XML_Bool allowClosingDoctype); + XML_Bool haveMore, XML_Bool allowClosingDoctype, + enum XML_Account account); static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl); static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *start, const char *end, const char **endPtr, - XML_Bool haveMore); + XML_Bool haveMore, enum XML_Account account); static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, - const char **nextPtr, XML_Bool haveMore); + const char **nextPtr, XML_Bool haveMore, + enum XML_Account account); #ifdef XML_DTD static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, @@ -431,7 +473,8 @@ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, static void freeBindings(XML_Parser parser, BINDING *bindings); static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, TAG_NAME *tagNamePtr, - BINDING **bindingsPtr); + BINDING **bindingsPtr, + enum XML_Account account); static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); @@ -440,15 +483,18 @@ static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, XML_Parser parser); static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, - const char *, STRING_POOL *); + const char *, STRING_POOL *, + enum XML_Account account); static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, - const char *, STRING_POOL *); + const char *, STRING_POOL *, + enum XML_Account account); static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, - const char *start, const char *end); + const char *start, const char *end, + enum XML_Account account); static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportComment(XML_Parser parser, const ENCODING *enc, @@ -512,6 +558,34 @@ static XML_Parser parserCreate(const XML_Char *encodingName, static void parserInit(XML_Parser parser, const XML_Char *encodingName); +#ifdef XML_DTD +static float accountingGetCurrentAmplification(XML_Parser rootParser); +static void accountingReportStats(XML_Parser originParser, const char *epilog); +static void accountingOnAbort(XML_Parser originParser); +static void accountingReportDiff(XML_Parser rootParser, + unsigned int levelsAwayFromRootParser, + const char *before, const char *after, + ptrdiff_t bytesMore, int source_line, + enum XML_Account account); +static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok, + const char *before, const char *after, + int source_line, + enum XML_Account account); + +static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity, + const char *action, int sourceLine); +static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity, + int sourceLine); +static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity, + int sourceLine); + +static XML_Parser getRootParserOf(XML_Parser parser, + unsigned int *outLevelDiff); +#endif /* XML_DTD */ + +static unsigned long getDebugLevel(const char *variableName, + unsigned long defaultDebugLevel); + #define poolStart(pool) ((pool)->start) #define poolEnd(pool) ((pool)->ptr) #define poolLength(pool) ((pool)->ptr - (pool)->start) @@ -625,6 +699,10 @@ struct XML_ParserStruct { enum XML_ParamEntityParsing m_paramEntityParsing; #endif unsigned long m_hash_secret_salt; +#ifdef XML_DTD + ACCOUNTING m_accounting; + ENTITY_STATS m_entity_stats; +#endif }; #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) @@ -809,9 +887,8 @@ gather_time_entropy(void) { static unsigned long ENTROPY_DEBUG(const char *label, unsigned long entropy) { - const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG"); - if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) { - fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label, + if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) { + fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label, (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy)); } return entropy; @@ -1073,6 +1150,18 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) { parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif parser->m_hash_secret_salt = 0; + +#ifdef XML_DTD + memset(&parser->m_accounting, 0, sizeof(ACCOUNTING)); + parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u); + parser->m_accounting.maximumAmplificationFactor + = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT; + parser->m_accounting.activationThresholdBytes + = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT; + + memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS)); + parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u); +#endif } /* moves list of bindings to m_freeBindingList */ @@ -1893,6 +1982,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { parser->m_errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR; case XML_INITIALIZED: + /* Has someone called XML_GetBuffer successfully before? */ + if (! parser->m_bufferPtr) { + parser->m_errorCode = XML_ERROR_NO_BUFFER; + return XML_STATUS_ERROR; + } + if (parser->m_parentParser == NULL && ! startParsing(parser)) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; @@ -2337,6 +2432,14 @@ XML_ErrorString(enum XML_Error code) { /* Added in 2.2.5. */ case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */ return XML_L("invalid argument"); + /* Added in 2.3.0. */ + case XML_ERROR_NO_BUFFER: + return XML_L( + "a successful prior call to function XML_GetBuffer is required"); + /* Added in 2.4.0. */ + case XML_ERROR_AMPLIFICATION_LIMIT_BREACH: + return XML_L( + "limit on input amplification factor (from DTD and entities) breached"); } return NULL; } @@ -2373,41 +2476,75 @@ XML_ExpatVersionInfo(void) { const XML_Feature *XMLCALL XML_GetFeatureList(void) { - static const XML_Feature features[] - = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), - sizeof(XML_Char)}, - {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), - sizeof(XML_LChar)}, + static const XML_Feature features[] = { + {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), + sizeof(XML_Char)}, + {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), + sizeof(XML_LChar)}, #ifdef XML_UNICODE - {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, + {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, #endif #ifdef XML_UNICODE_WCHAR_T - {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, + {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, #endif #ifdef XML_DTD - {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, + {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, #endif #ifdef XML_CONTEXT_BYTES - {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), - XML_CONTEXT_BYTES}, + {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), + XML_CONTEXT_BYTES}, #endif #ifdef XML_MIN_SIZE - {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, + {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, #endif #ifdef XML_NS - {XML_FEATURE_NS, XML_L("XML_NS"), 0}, + {XML_FEATURE_NS, XML_L("XML_NS"), 0}, #endif #ifdef XML_LARGE_SIZE - {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, + {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, #endif #ifdef XML_ATTR_INFO - {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, + {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, #endif - {XML_FEATURE_END, NULL, 0}}; +#ifdef XML_DTD + /* Added in Expat 2.4.0. */ + {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_L("XML_BLAP_MAX_AMP"), + (long int) + EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT}, + {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT, + XML_L("XML_BLAP_ACT_THRES"), + EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT}, +#endif + {XML_FEATURE_END, NULL, 0}}; return features; } +#ifdef XML_DTD +XML_Bool XMLCALL +XML_SetBillionLaughsAttackProtectionMaximumAmplification( + XML_Parser parser, float maximumAmplificationFactor) { + if ((parser == NULL) || (parser->m_parentParser != NULL) + || isnan(maximumAmplificationFactor) + || (maximumAmplificationFactor < 1.0f)) { + return XML_FALSE; + } + parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor; + return XML_TRUE; +} + +XML_Bool XMLCALL +XML_SetBillionLaughsAttackProtectionActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes) { + if ((parser == NULL) || (parser->m_parentParser != NULL)) { + return XML_FALSE; + } + parser->m_accounting.activationThresholdBytes = activationThresholdBytes; + return XML_TRUE; +} +#endif /* XML_DTD */ + /* Initially tag->rawName always points into the parse buffer; for those TAG instances opened while the current parse buffer was processed, and not yet closed, we need to store tag->rawName in a more @@ -2460,9 +2597,9 @@ storeRawNames(XML_Parser parser) { static enum XML_Error PTRCALL contentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { - enum XML_Error result - = doContent(parser, 0, parser->m_encoding, start, end, endPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + enum XML_Error result = doContent( + parser, 0, parser->m_encoding, start, end, endPtr, + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; @@ -2487,6 +2624,14 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start, int tok = XmlContentTok(parser->m_encoding, start, end, &next); switch (tok) { case XML_TOK_BOM: +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, start, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif /* XML_DTD */ + /* If we are at the end of the buffer, this would cause the next stage, i.e. externalEntityInitProcessor3, to pass control directly to doContent (by detecting XML_TOK_NONE) without processing any xml text @@ -2524,6 +2669,10 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start, const char *next = start; /* XmlContentTok doesn't always set the last arg */ parser->m_eventPtr = start; tok = XmlContentTok(parser->m_encoding, start, end, &next); + /* Note: These bytes are accounted later in: + - processXmlDecl + - externalEntityContentProcessor + */ parser->m_eventEndPtr = next; switch (tok) { @@ -2565,7 +2714,8 @@ externalEntityContentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end, endPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, + XML_ACCOUNT_ENTITY_EXPANSION); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; @@ -2576,7 +2726,7 @@ externalEntityContentProcessor(XML_Parser parser, const char *start, static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *s, const char *end, const char **nextPtr, - XML_Bool haveMore) { + XML_Bool haveMore, enum XML_Account account) { /* save one level of indirection */ DTD *const dtd = parser->m_dtd; @@ -2594,6 +2744,17 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, for (;;) { const char *next = s; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(enc, s, end, &next); +#ifdef XML_DTD + const char *accountAfter + = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR)) + ? (haveMore ? s /* i.e. 0 bytes */ : end) + : next; + if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__, + account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif *eventEndPP = next; switch (tok) { case XML_TOK_TRAILING_CR: @@ -2649,6 +2810,14 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { +#ifdef XML_DTD + /* NOTE: We are replacing 4-6 characters original input for 1 character + * so there is no amplification and hence recording without + * protection. */ + accountingDiffTolerated(parser, tok, (char *)&ch, + ((char *)&ch) + sizeof(XML_Char), __LINE__, + XML_ACCOUNT_ENTITY_EXPANSION); +#endif /* XML_DTD */ if (parser->m_characterDataHandler) parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1); else if (parser->m_defaultHandler) @@ -2767,7 +2936,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, } tag->name.str = (XML_Char *)tag->buf; *toPtr = XML_T('\0'); - result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); + result + = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account); if (result) return result; if (parser->m_startElementHandler) @@ -2791,7 +2961,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, if (! name.str) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); - result = storeAtts(parser, enc, s, &name, &bindings); + result = storeAtts(parser, enc, s, &name, &bindings, + XML_ACCOUNT_NONE /* token spans whole start tag */); if (result != XML_ERROR_NONE) { freeBindings(parser, bindings); return result; @@ -2926,7 +3097,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, /* END disabled code */ else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); + result + = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account); if (result != XML_ERROR_NONE) return result; else if (! next) { @@ -3055,7 +3227,8 @@ freeBindings(XML_Parser parser, BINDING *bindings) { */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, - TAG_NAME *tagNamePtr, BINDING **bindingsPtr) { + TAG_NAME *tagNamePtr, BINDING **bindingsPtr, + enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ ELEMENT_TYPE *elementType; int nDefaultAtts; @@ -3165,7 +3338,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, /* normalize the attribute value */ result = storeAttributeValue( parser, enc, isCdata, parser->m_atts[i].valuePtr, - parser->m_atts[i].valueEnd, &parser->m_tempPool); + parser->m_atts[i].valueEnd, &parser->m_tempPool, account); if (result) return result; appAtts[attIndex] = poolStart(&parser->m_tempPool); @@ -3554,9 +3727,9 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, static enum XML_Error PTRCALL cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { - enum XML_Error result - = doCdataSection(parser, parser->m_encoding, &start, end, endPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + enum XML_Error result = doCdataSection( + parser, parser->m_encoding, &start, end, endPtr, + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result != XML_ERROR_NONE) return result; if (start) { @@ -3576,7 +3749,8 @@ cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, */ static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, - const char *end, const char **nextPtr, XML_Bool haveMore) { + const char *end, const char **nextPtr, XML_Bool haveMore, + enum XML_Account account) { const char *s = *startPtr; const char **eventPP; const char **eventEndPP; @@ -3594,6 +3768,14 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, for (;;) { const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */ int tok = XmlCdataSectionTok(enc, s, end, &next); +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#else + UNUSED_P(account); +#endif *eventEndPP = next; switch (tok) { case XML_TOK_CDATA_SECT_CLOSE: @@ -3738,6 +3920,13 @@ doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, *eventPP = s; *startPtr = NULL; tok = XmlIgnoreSectionTok(enc, s, end, &next); +# ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +# endif *eventEndPP = next; switch (tok) { case XML_TOK_IGNORE_SECT: @@ -3822,6 +4011,15 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *versionend; const XML_Char *storedversion = NULL; int standalone = -1; + +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif + if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)( isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr, &version, &versionend, &encodingName, &newEncoding, &standalone)) { @@ -3971,6 +4169,10 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, for (;;) { tok = XmlPrologTok(parser->m_encoding, start, end, &next); + /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in: + - storeEntityValue + - processXmlDecl + */ parser->m_eventEndPtr = next; if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { @@ -3989,7 +4191,8 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, break; } /* found end of entity value - can store it now */ - return storeEntityValue(parser, parser->m_encoding, s, end); + return storeEntityValue(parser, parser->m_encoding, s, end, + XML_ACCOUNT_DIRECT); } else if (tok == XML_TOK_XML_DECL) { enum XML_Error result; result = processXmlDecl(parser, 0, start, next); @@ -4016,6 +4219,14 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, */ else if (tok == XML_TOK_BOM && next == end && ! parser->m_parsingStatus.finalBuffer) { +# ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +# endif + *nextPtr = next; return XML_ERROR_NONE; } @@ -4058,16 +4269,24 @@ externalParEntProcessor(XML_Parser parser, const char *s, const char *end, } /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. However, when parsing an external subset, doProlog will not accept a BOM - as valid, and report a syntax error, so we have to skip the BOM + as valid, and report a syntax error, so we have to skip the BOM, and + account for the BOM bytes. */ else if (tok == XML_TOK_BOM) { + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } + s = next; tok = XmlPrologTok(parser->m_encoding, s, end, &next); } parser->m_processor = prologProcessor; return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, + XML_ACCOUNT_DIRECT); } static enum XML_Error PTRCALL @@ -4080,6 +4299,9 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end, for (;;) { tok = XmlPrologTok(enc, start, end, &next); + /* Note: These bytes are accounted later in: + - storeEntityValue + */ if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; @@ -4097,7 +4319,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end, break; } /* found end of entity value - can store it now */ - return storeEntityValue(parser, enc, s, end); + return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT); } start = next; } @@ -4111,13 +4333,14 @@ prologProcessor(XML_Parser parser, const char *s, const char *end, const char *next = s; int tok = XmlPrologTok(parser->m_encoding, s, end, &next); return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, + XML_ACCOUNT_DIRECT); } static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr, XML_Bool haveMore, - XML_Bool allowClosingDoctype) { + XML_Bool allowClosingDoctype, enum XML_Account account) { #ifdef XML_DTD static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'}; #endif /* XML_DTD */ @@ -4144,6 +4367,10 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'}; static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'}; +#ifndef XML_DTD + UNUSED_P(account); +#endif + /* save one level of indirection */ DTD *const dtd = parser->m_dtd; @@ -4208,6 +4435,19 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, } } role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc); +#ifdef XML_DTD + switch (role) { + case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor + case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl + case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl + break; + default: + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } + } +#endif switch (role) { case XML_ROLE_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 0, s, next); @@ -4483,7 +4723,8 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, const XML_Char *attVal; enum XML_Error result = storeAttributeValue( parser, enc, parser->m_declAttributeIsCdata, - s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool); + s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool, + XML_ACCOUNT_NONE); if (result) return result; attVal = poolStart(&dtd->pool); @@ -4516,8 +4757,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, break; case XML_ROLE_ENTITY_VALUE: if (dtd->keepProcessing) { - enum XML_Error result = storeEntityValue( - parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); + enum XML_Error result + = storeEntityValue(parser, enc, s + enc->minBytesPerChar, + next - enc->minBytesPerChar, XML_ACCOUNT_NONE); if (parser->m_declEntity) { parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool); parser->m_declEntity->textLen @@ -4907,12 +5149,15 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, if (parser->m_externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; + entityTrackingOnOpen(parser, entity, __LINE__); if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; return XML_ERROR_EXTERNAL_ENTITY_HANDLING; } + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; handleDefault = XML_FALSE; if (! dtd->paramEntityRead) { @@ -5110,6 +5355,13 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end, for (;;) { const char *next = NULL; int tok = XmlPrologTok(parser->m_encoding, s, end, &next); +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif parser->m_eventEndPtr = next; switch (tok) { /* report partial linebreak - it might be the last token */ @@ -5183,6 +5435,9 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { return XML_ERROR_NO_MEMORY; } entity->open = XML_TRUE; +#ifdef XML_DTD + entityTrackingOnOpen(parser, entity, __LINE__); +#endif entity->processed = 0; openEntity->next = parser->m_openInternalEntities; parser->m_openInternalEntities = openEntity; @@ -5201,17 +5456,22 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, - tok, next, &next, XML_FALSE, XML_FALSE); + tok, next, &next, XML_FALSE, XML_FALSE, + XML_ACCOUNT_ENTITY_EXPANSION); } else #endif /* XML_DTD */ result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, - textStart, textEnd, &next, XML_FALSE); + textStart, textEnd, &next, XML_FALSE, + XML_ACCOUNT_ENTITY_EXPANSION); if (result == XML_ERROR_NONE) { if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { entity->processed = (int)(next - textStart); parser->m_processor = internalEntityProcessor; } else { +#ifdef XML_DTD + entityTrackingOnClose(parser, entity, __LINE__); +#endif /* XML_DTD */ entity->open = XML_FALSE; parser->m_openInternalEntities = openEntity->next; /* put openEntity back in list of free instances */ @@ -5244,12 +5504,13 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, - tok, next, &next, XML_FALSE, XML_TRUE); + tok, next, &next, XML_FALSE, XML_TRUE, + XML_ACCOUNT_ENTITY_EXPANSION); } else #endif /* XML_DTD */ result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding, textStart, textEnd, &next, - XML_FALSE); + XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); if (result != XML_ERROR_NONE) return result; @@ -5258,6 +5519,9 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, entity->processed = (int)(next - (const char *)entity->textPtr); return result; } else { +#ifdef XML_DTD + entityTrackingOnClose(parser, entity, __LINE__); +#endif entity->open = XML_FALSE; parser->m_openInternalEntities = openEntity->next; /* put openEntity back in list of free instances */ @@ -5271,7 +5535,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, parser->m_processor = prologProcessor; tok = XmlPrologTok(parser->m_encoding, s, end, &next); return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, + XML_ACCOUNT_DIRECT); } else #endif /* XML_DTD */ { @@ -5279,7 +5544,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, /* see externalEntityContentProcessor vs contentProcessor */ return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, + XML_ACCOUNT_DIRECT); } } @@ -5294,9 +5560,10 @@ errorProcessor(XML_Parser parser, const char *s, const char *end, static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, - const char *ptr, const char *end, STRING_POOL *pool) { + const char *ptr, const char *end, STRING_POOL *pool, + enum XML_Account account) { enum XML_Error result - = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); + = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account); if (result) return result; if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) @@ -5308,11 +5575,23 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, - const char *ptr, const char *end, STRING_POOL *pool) { + const char *ptr, const char *end, STRING_POOL *pool, + enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ +#ifndef XML_DTD + UNUSED_P(account); +#endif + for (;;) { - const char *next; + const char *next + = ptr; /* XmlAttributeValueTok doesn't always set the last arg */ int tok = XmlAttributeValueTok(enc, ptr, end, &next); +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif switch (tok) { case XML_TOK_NONE: return XML_ERROR_NONE; @@ -5372,6 +5651,14 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { +#ifdef XML_DTD + /* NOTE: We are replacing 4-6 characters original input for 1 character + * so there is no amplification and hence recording without + * protection. */ + accountingDiffTolerated(parser, tok, (char *)&ch, + ((char *)&ch) + sizeof(XML_Char), __LINE__, + XML_ACCOUNT_ENTITY_EXPANSION); +#endif /* XML_DTD */ if (! poolAppendChar(pool, ch)) return XML_ERROR_NO_MEMORY; break; @@ -5449,9 +5736,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, enum XML_Error result; const XML_Char *textEnd = entity->textPtr + entity->textLen; entity->open = XML_TRUE; +#ifdef XML_DTD + entityTrackingOnOpen(parser, entity, __LINE__); +#endif result = appendAttributeValue(parser, parser->m_internalEncoding, isCdata, (const char *)entity->textPtr, - (const char *)textEnd, pool); + (const char *)textEnd, pool, + XML_ACCOUNT_ENTITY_EXPANSION); +#ifdef XML_DTD + entityTrackingOnClose(parser, entity, __LINE__); +#endif entity->open = XML_FALSE; if (result) return result; @@ -5481,13 +5775,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, - const char *entityTextPtr, const char *entityTextEnd) { + const char *entityTextPtr, const char *entityTextEnd, + enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ STRING_POOL *pool = &(dtd->entityValuePool); enum XML_Error result = XML_ERROR_NONE; #ifdef XML_DTD int oldInEntityValue = parser->m_prologState.inEntityValue; parser->m_prologState.inEntityValue = 1; +#else + UNUSED_P(account); #endif /* XML_DTD */ /* never return Null for the value argument in EntityDeclHandler, since this would indicate an external entity; therefore we @@ -5498,8 +5795,19 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, } for (;;) { - const char *next; + const char *next + = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__, + account)) { + accountingOnAbort(parser); + result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + goto endEntityValue; + } +#endif + switch (tok) { case XML_TOK_PARAM_ENTITY_REF: #ifdef XML_DTD @@ -5535,13 +5843,16 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, if (parser->m_externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; + entityTrackingOnOpen(parser, entity, __LINE__); if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; goto endEntityValue; } + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; if (! dtd->paramEntityRead) dtd->keepProcessing = dtd->standalone; @@ -5549,9 +5860,12 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, dtd->keepProcessing = dtd->standalone; } else { entity->open = XML_TRUE; + entityTrackingOnOpen(parser, entity, __LINE__); result = storeEntityValue( parser, parser->m_internalEncoding, (const char *)entity->textPtr, - (const char *)(entity->textPtr + entity->textLen)); + (const char *)(entity->textPtr + entity->textLen), + XML_ACCOUNT_ENTITY_EXPANSION); + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; if (result) goto endEntityValue; @@ -6912,3 +7226,755 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { memcpy(result, s, charsRequired * sizeof(XML_Char)); return result; } + +#ifdef XML_DTD + +static float +accountingGetCurrentAmplification(XML_Parser rootParser) { + const XmlBigCount countBytesOutput + = rootParser->m_accounting.countBytesDirect + + rootParser->m_accounting.countBytesIndirect; + const float amplificationFactor + = rootParser->m_accounting.countBytesDirect + ? (countBytesOutput + / (float)(rootParser->m_accounting.countBytesDirect)) + : 1.0f; + assert(! rootParser->m_parentParser); + return amplificationFactor; +} + +static void +accountingReportStats(XML_Parser originParser, const char *epilog) { + const XML_Parser rootParser = getRootParserOf(originParser, NULL); + assert(! rootParser->m_parentParser); + + if (rootParser->m_accounting.debugLevel < 1) { + return; + } + + const float amplificationFactor + = accountingGetCurrentAmplification(rootParser); + fprintf(stderr, + "expat: Accounting(%p): Direct " EXPAT_FMT_ULL( + "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s", + (void *)rootParser, rootParser->m_accounting.countBytesDirect, + rootParser->m_accounting.countBytesIndirect, + (double)amplificationFactor, epilog); +} + +static void +accountingOnAbort(XML_Parser originParser) { + accountingReportStats(originParser, " ABORTING\n"); +} + +static void +accountingReportDiff(XML_Parser rootParser, + unsigned int levelsAwayFromRootParser, const char *before, + const char *after, ptrdiff_t bytesMore, int source_line, + enum XML_Account account) { + assert(! rootParser->m_parentParser); + + fprintf(stderr, + " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"", + bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP", + levelsAwayFromRootParser, source_line, 10, ""); + + const char ellipis[] = "[..]"; + const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1; + const unsigned int contextLength = 10; + + /* Note: Performance is of no concern here */ + const char *walker = before; + if ((rootParser->m_accounting.debugLevel >= 3) + || (after - before) + <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) { + for (; walker < after; walker++) { + fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); + } + } else { + for (; walker < before + contextLength; walker++) { + fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); + } + fprintf(stderr, ellipis); + walker = after - contextLength; + for (; walker < after; walker++) { + fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); + } + } + fprintf(stderr, "\"\n"); +} + +static XML_Bool +accountingDiffTolerated(XML_Parser originParser, int tok, const char *before, + const char *after, int source_line, + enum XML_Account account) { + /* Note: We need to check the token type *first* to be sure that + * we can even access variable , safely. + * E.g. for XML_TOK_NONE may hold an invalid pointer. */ + switch (tok) { + case XML_TOK_INVALID: + case XML_TOK_PARTIAL: + case XML_TOK_PARTIAL_CHAR: + case XML_TOK_NONE: + return XML_TRUE; + } + + if (account == XML_ACCOUNT_NONE) + return XML_TRUE; /* because these bytes have been accounted for, already */ + + unsigned int levelsAwayFromRootParser; + const XML_Parser rootParser + = getRootParserOf(originParser, &levelsAwayFromRootParser); + assert(! rootParser->m_parentParser); + + const int isDirect + = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser); + const ptrdiff_t bytesMore = after - before; + + XmlBigCount *const additionTarget + = isDirect ? &rootParser->m_accounting.countBytesDirect + : &rootParser->m_accounting.countBytesIndirect; + + /* Detect and avoid integer overflow */ + if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore) + return XML_FALSE; + *additionTarget += bytesMore; + + const XmlBigCount countBytesOutput + = rootParser->m_accounting.countBytesDirect + + rootParser->m_accounting.countBytesIndirect; + const float amplificationFactor + = accountingGetCurrentAmplification(rootParser); + const XML_Bool tolerated + = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes) + || (amplificationFactor + <= rootParser->m_accounting.maximumAmplificationFactor); + + if (rootParser->m_accounting.debugLevel >= 2) { + accountingReportStats(rootParser, ""); + accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after, + bytesMore, source_line, account); + } + + return tolerated; +} + +unsigned long long +testingAccountingGetCountBytesDirect(XML_Parser parser) { + if (! parser) + return 0; + return parser->m_accounting.countBytesDirect; +} + +unsigned long long +testingAccountingGetCountBytesIndirect(XML_Parser parser) { + if (! parser) + return 0; + return parser->m_accounting.countBytesIndirect; +} + +static void +entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity, + const char *action, int sourceLine) { + assert(! rootParser->m_parentParser); + if (rootParser->m_entity_stats.debugLevel < 1) + return; + +# if defined(XML_UNICODE) + const char *const entityName = "[..]"; +# else + const char *const entityName = entity->name; +# endif + + fprintf( + stderr, + "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n", + (void *)rootParser, rootParser->m_entity_stats.countEverOpened, + rootParser->m_entity_stats.currentDepth, + rootParser->m_entity_stats.maximumDepthSeen, + (rootParser->m_entity_stats.currentDepth - 1) * 2, "", + entity->is_param ? "%" : "&", entityName, action, entity->textLen, + sourceLine); +} + +static void +entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) { + const XML_Parser rootParser = getRootParserOf(originParser, NULL); + assert(! rootParser->m_parentParser); + + rootParser->m_entity_stats.countEverOpened++; + rootParser->m_entity_stats.currentDepth++; + if (rootParser->m_entity_stats.currentDepth + > rootParser->m_entity_stats.maximumDepthSeen) { + rootParser->m_entity_stats.maximumDepthSeen++; + } + + entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine); +} + +static void +entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) { + const XML_Parser rootParser = getRootParserOf(originParser, NULL); + assert(! rootParser->m_parentParser); + + entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine); + rootParser->m_entity_stats.currentDepth--; +} + +static XML_Parser +getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) { + XML_Parser rootParser = parser; + unsigned int stepsTakenUpwards = 0; + while (rootParser->m_parentParser) { + rootParser = rootParser->m_parentParser; + stepsTakenUpwards++; + } + assert(! rootParser->m_parentParser); + if (outLevelDiff != NULL) { + *outLevelDiff = stepsTakenUpwards; + } + return rootParser; +} + +const char * +unsignedCharToPrintable(unsigned char c) { + switch (c) { + case 0: + return "\\0"; + case 1: + return "\\x1"; + case 2: + return "\\x2"; + case 3: + return "\\x3"; + case 4: + return "\\x4"; + case 5: + return "\\x5"; + case 6: + return "\\x6"; + case 7: + return "\\x7"; + case 8: + return "\\x8"; + case 9: + return "\\t"; + case 10: + return "\\n"; + case 11: + return "\\xB"; + case 12: + return "\\xC"; + case 13: + return "\\r"; + case 14: + return "\\xE"; + case 15: + return "\\xF"; + case 16: + return "\\x10"; + case 17: + return "\\x11"; + case 18: + return "\\x12"; + case 19: + return "\\x13"; + case 20: + return "\\x14"; + case 21: + return "\\x15"; + case 22: + return "\\x16"; + case 23: + return "\\x17"; + case 24: + return "\\x18"; + case 25: + return "\\x19"; + case 26: + return "\\x1A"; + case 27: + return "\\x1B"; + case 28: + return "\\x1C"; + case 29: + return "\\x1D"; + case 30: + return "\\x1E"; + case 31: + return "\\x1F"; + case 32: + return " "; + case 33: + return "!"; + case 34: + return "\\\""; + case 35: + return "#"; + case 36: + return "$"; + case 37: + return "%"; + case 38: + return "&"; + case 39: + return "'"; + case 40: + return "("; + case 41: + return ")"; + case 42: + return "*"; + case 43: + return "+"; + case 44: + return ","; + case 45: + return "-"; + case 46: + return "."; + case 47: + return "/"; + case 48: + return "0"; + case 49: + return "1"; + case 50: + return "2"; + case 51: + return "3"; + case 52: + return "4"; + case 53: + return "5"; + case 54: + return "6"; + case 55: + return "7"; + case 56: + return "8"; + case 57: + return "9"; + case 58: + return ":"; + case 59: + return ";"; + case 60: + return "<"; + case 61: + return "="; + case 62: + return ">"; + case 63: + return "?"; + case 64: + return "@"; + case 65: + return "A"; + case 66: + return "B"; + case 67: + return "C"; + case 68: + return "D"; + case 69: + return "E"; + case 70: + return "F"; + case 71: + return "G"; + case 72: + return "H"; + case 73: + return "I"; + case 74: + return "J"; + case 75: + return "K"; + case 76: + return "L"; + case 77: + return "M"; + case 78: + return "N"; + case 79: + return "O"; + case 80: + return "P"; + case 81: + return "Q"; + case 82: + return "R"; + case 83: + return "S"; + case 84: + return "T"; + case 85: + return "U"; + case 86: + return "V"; + case 87: + return "W"; + case 88: + return "X"; + case 89: + return "Y"; + case 90: + return "Z"; + case 91: + return "["; + case 92: + return "\\\\"; + case 93: + return "]"; + case 94: + return "^"; + case 95: + return "_"; + case 96: + return "`"; + case 97: + return "a"; + case 98: + return "b"; + case 99: + return "c"; + case 100: + return "d"; + case 101: + return "e"; + case 102: + return "f"; + case 103: + return "g"; + case 104: + return "h"; + case 105: + return "i"; + case 106: + return "j"; + case 107: + return "k"; + case 108: + return "l"; + case 109: + return "m"; + case 110: + return "n"; + case 111: + return "o"; + case 112: + return "p"; + case 113: + return "q"; + case 114: + return "r"; + case 115: + return "s"; + case 116: + return "t"; + case 117: + return "u"; + case 118: + return "v"; + case 119: + return "w"; + case 120: + return "x"; + case 121: + return "y"; + case 122: + return "z"; + case 123: + return "{"; + case 124: + return "|"; + case 125: + return "}"; + case 126: + return "~"; + case 127: + return "\\x7F"; + case 128: + return "\\x80"; + case 129: + return "\\x81"; + case 130: + return "\\x82"; + case 131: + return "\\x83"; + case 132: + return "\\x84"; + case 133: + return "\\x85"; + case 134: + return "\\x86"; + case 135: + return "\\x87"; + case 136: + return "\\x88"; + case 137: + return "\\x89"; + case 138: + return "\\x8A"; + case 139: + return "\\x8B"; + case 140: + return "\\x8C"; + case 141: + return "\\x8D"; + case 142: + return "\\x8E"; + case 143: + return "\\x8F"; + case 144: + return "\\x90"; + case 145: + return "\\x91"; + case 146: + return "\\x92"; + case 147: + return "\\x93"; + case 148: + return "\\x94"; + case 149: + return "\\x95"; + case 150: + return "\\x96"; + case 151: + return "\\x97"; + case 152: + return "\\x98"; + case 153: + return "\\x99"; + case 154: + return "\\x9A"; + case 155: + return "\\x9B"; + case 156: + return "\\x9C"; + case 157: + return "\\x9D"; + case 158: + return "\\x9E"; + case 159: + return "\\x9F"; + case 160: + return "\\xA0"; + case 161: + return "\\xA1"; + case 162: + return "\\xA2"; + case 163: + return "\\xA3"; + case 164: + return "\\xA4"; + case 165: + return "\\xA5"; + case 166: + return "\\xA6"; + case 167: + return "\\xA7"; + case 168: + return "\\xA8"; + case 169: + return "\\xA9"; + case 170: + return "\\xAA"; + case 171: + return "\\xAB"; + case 172: + return "\\xAC"; + case 173: + return "\\xAD"; + case 174: + return "\\xAE"; + case 175: + return "\\xAF"; + case 176: + return "\\xB0"; + case 177: + return "\\xB1"; + case 178: + return "\\xB2"; + case 179: + return "\\xB3"; + case 180: + return "\\xB4"; + case 181: + return "\\xB5"; + case 182: + return "\\xB6"; + case 183: + return "\\xB7"; + case 184: + return "\\xB8"; + case 185: + return "\\xB9"; + case 186: + return "\\xBA"; + case 187: + return "\\xBB"; + case 188: + return "\\xBC"; + case 189: + return "\\xBD"; + case 190: + return "\\xBE"; + case 191: + return "\\xBF"; + case 192: + return "\\xC0"; + case 193: + return "\\xC1"; + case 194: + return "\\xC2"; + case 195: + return "\\xC3"; + case 196: + return "\\xC4"; + case 197: + return "\\xC5"; + case 198: + return "\\xC6"; + case 199: + return "\\xC7"; + case 200: + return "\\xC8"; + case 201: + return "\\xC9"; + case 202: + return "\\xCA"; + case 203: + return "\\xCB"; + case 204: + return "\\xCC"; + case 205: + return "\\xCD"; + case 206: + return "\\xCE"; + case 207: + return "\\xCF"; + case 208: + return "\\xD0"; + case 209: + return "\\xD1"; + case 210: + return "\\xD2"; + case 211: + return "\\xD3"; + case 212: + return "\\xD4"; + case 213: + return "\\xD5"; + case 214: + return "\\xD6"; + case 215: + return "\\xD7"; + case 216: + return "\\xD8"; + case 217: + return "\\xD9"; + case 218: + return "\\xDA"; + case 219: + return "\\xDB"; + case 220: + return "\\xDC"; + case 221: + return "\\xDD"; + case 222: + return "\\xDE"; + case 223: + return "\\xDF"; + case 224: + return "\\xE0"; + case 225: + return "\\xE1"; + case 226: + return "\\xE2"; + case 227: + return "\\xE3"; + case 228: + return "\\xE4"; + case 229: + return "\\xE5"; + case 230: + return "\\xE6"; + case 231: + return "\\xE7"; + case 232: + return "\\xE8"; + case 233: + return "\\xE9"; + case 234: + return "\\xEA"; + case 235: + return "\\xEB"; + case 236: + return "\\xEC"; + case 237: + return "\\xED"; + case 238: + return "\\xEE"; + case 239: + return "\\xEF"; + case 240: + return "\\xF0"; + case 241: + return "\\xF1"; + case 242: + return "\\xF2"; + case 243: + return "\\xF3"; + case 244: + return "\\xF4"; + case 245: + return "\\xF5"; + case 246: + return "\\xF6"; + case 247: + return "\\xF7"; + case 248: + return "\\xF8"; + case 249: + return "\\xF9"; + case 250: + return "\\xFA"; + case 251: + return "\\xFB"; + case 252: + return "\\xFC"; + case 253: + return "\\xFD"; + case 254: + return "\\xFE"; + case 255: + return "\\xFF"; + default: + assert(0); /* never gets here */ + return "dead code"; + } + assert(0); /* never gets here */ +} + +#endif /* XML_DTD */ + +static unsigned long +getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) { + const char *const valueOrNull = getenv(variableName); + if (valueOrNull == NULL) { + return defaultDebugLevel; + } + const char *const value = valueOrNull; + + errno = 0; + char *afterValue = (char *)value; + unsigned long debugLevel = strtoul(value, &afterValue, 10); + if ((errno != 0) || (afterValue[0] != '\0')) { + errno = 0; + return defaultDebugLevel; + } + + return debugLevel; +} diff --git a/lib/xmlrole.c b/lib/xmlrole.c index 3b676a415d8..08173b0fd54 100644 --- a/lib/xmlrole.c +++ b/lib/xmlrole.c @@ -7,7 +7,14 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Greg Stein + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2002-2003 Fred L. Drake, Jr. + Copyright (c) 2005-2009 Steven Solie + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2017 Rhodri James + Copyright (c) 2019 David Loffredo Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -34,11 +41,9 @@ #ifdef _WIN32 # include "winconfig.h" -#else -# ifdef HAVE_EXPAT_CONFIG_H -# include -# endif -#endif /* ndef _WIN32 */ +#endif + +#include #include "expat_external.h" #include "internal.h" diff --git a/lib/xmlrole.h b/lib/xmlrole.h index 036aba64fd2..d6e1fa150a1 100644 --- a/lib/xmlrole.h +++ b/lib/xmlrole.h @@ -7,7 +7,10 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Karl Waclawek + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/xmltok.c b/lib/xmltok.c index c4f9897f7dc..f2b6b406067 100644 --- a/lib/xmltok.c +++ b/lib/xmltok.c @@ -7,7 +7,19 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2001-2003 Fred L. Drake, Jr. + Copyright (c) 2002 Greg Stein + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2005-2009 Steven Solie + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016 Pascal Cuoq + Copyright (c) 2016 Don Lewis + Copyright (c) 2017 Rhodri James + Copyright (c) 2017 Alexander Bluhm + Copyright (c) 2017 Benbuck Nason + Copyright (c) 2017 José Gutiérrez de la Concha + Copyright (c) 2019 David Loffredo Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -32,23 +44,13 @@ #include #include /* memcpy */ - -#if defined(_MSC_VER) && (_MSC_VER <= 1700) -/* for vs2012/11.0/1700 and earlier Visual Studio compilers */ -# define bool int -# define false 0 -# define true 1 -#else -# include -#endif +#include #ifdef _WIN32 # include "winconfig.h" -#else -# ifdef HAVE_EXPAT_CONFIG_H -# include -# endif -#endif /* ndef _WIN32 */ +#endif + +#include #include "expat_external.h" #include "internal.h" @@ -269,8 +271,14 @@ sb_byteToAscii(const ENCODING *enc, const char *p) { #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p)) #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p)) -#define IS_INVALID_CHAR(enc, p, n) \ - (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) +#ifdef XML_MIN_SIZE +# define IS_INVALID_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isInvalid##n \ + && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) +#else +# define IS_INVALID_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) +#endif #ifdef XML_MIN_SIZE # define IS_NAME_CHAR_MINBPC(enc, p) \ diff --git a/lib/xmltok.h b/lib/xmltok.h index 2adbf5307be..6f630c2f9ba 100644 --- a/lib/xmltok.h +++ b/lib/xmltok.h @@ -7,7 +7,11 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2002-2005 Karl Waclawek + Copyright (c) 2016-2017 Sebastian Pipping + Copyright (c) 2017 Rhodri James Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c index 06d5c90851f..0430591b426 100644 --- a/lib/xmltok_impl.c +++ b/lib/xmltok_impl.c @@ -1,4 +1,4 @@ -/* This file is included! +/* This file is included (from xmltok.c, 1-3 times depending on XML_MIN_SIZE)! __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -7,7 +7,15 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2017 Rhodri James + Copyright (c) 2018 Benjamin Peterson + Copyright (c) 2018 Anton Maklakov + Copyright (c) 2019 David Loffredo + Copyright (c) 2020 Boris Kolpackov Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -32,7 +40,7 @@ #ifdef XML_TOK_IMPL_C -# ifndef IS_INVALID_CHAR +# ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined # define IS_INVALID_CHAR(enc, ptr, n) (0) # endif diff --git a/lib/xmltok_impl.h b/lib/xmltok_impl.h index e925dbc7e2c..c518aada013 100644 --- a/lib/xmltok_impl.h +++ b/lib/xmltok_impl.h @@ -7,7 +7,8 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2017-2019 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/lib/xmltok_ns.c b/lib/xmltok_ns.c index 919c74e9f97..5fd83922359 100644 --- a/lib/xmltok_ns.c +++ b/lib/xmltok_ns.c @@ -7,7 +7,11 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Greg Stein + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining From a50db66bbd131b1d5f5cc44a388e4478633bfbde Mon Sep 17 00:00:00 2001 From: Jason Erb Date: Sat, 22 May 2021 19:12:01 -0400 Subject: [PATCH 0501/1519] CPack/WIX: Use language en-US, font Consolas, size 14 Improve rendering of text from `CPACK_RESOURCE_FILE_LICENSE`. Fixes: #22228 --- Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx index 751f7dc3a36..d7e534a705c 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -79,7 +79,7 @@ void cmWIXRichTextFormatWriter::WriteHeader() ControlWord("ansi"); ControlWord("ansicpg1252"); ControlWord("deff0"); - ControlWord("deflang1031"); + ControlWord("deflang1033"); WriteFontTable(); WriteColorTable(); @@ -94,7 +94,7 @@ void cmWIXRichTextFormatWriter::WriteFontTable() StartGroup(); ControlWord("f0"); ControlWord("fswiss"); - ControlWord("fcharset0 Arial;"); + ControlWord("fcharset0 Consolas;"); EndGroup(); EndGroup(); @@ -130,7 +130,7 @@ void cmWIXRichTextFormatWriter::WriteDocumentPrefix() ControlWord("uc1"); ControlWord("pard"); ControlWord("f0"); - ControlWord("fs20"); + ControlWord("fs14"); } void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword) From 668ba68a7af9e7511e0e6c988ccfe297956a42b6 Mon Sep 17 00:00:00 2001 From: PCJohn Date: Sat, 22 May 2021 15:34:17 +0200 Subject: [PATCH 0502/1519] FindVulkan: add Vulkan::Headers and Vulkan::glslangValidator targets The `Vulkan::Headers` target complements existing Vulkan::Vulkan target. It is the same except it omits the Vulkan library which supports applications that loads the Vulkan library in at runtime. The `Vulkan::glslangValidator` target provides the glslangValidator executable which is the tool for converting between shader languages (GLSL, SPIR-V, etc.). --- ...n-add-Headers-glslangValidator-targets.rst | 5 ++ Modules/FindVulkan.cmake | 54 ++++++++++++++++-- Tests/FindVulkan/Test/CMakeLists.txt | 20 ++++++- .../Test/Run-glslangValidator.cmake | 20 +++++++ .../Test/main-dynamicVulkanLoading.cpp | 55 +++++++++++++++++++ 5 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst create mode 100644 Tests/FindVulkan/Test/Run-glslangValidator.cmake create mode 100644 Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp diff --git a/Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst b/Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst new file mode 100644 index 00000000000..4f224cc58f0 --- /dev/null +++ b/Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst @@ -0,0 +1,5 @@ +FindVulkan-add-Headers-glslangValidator-targets +----------------------------------------------- + +* The :module:`FindVulkan` module gained imported targets + ``Vulkan::Headers`` and ``Vulkan::glslangValidator``. diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake index ceb1921e9ef..4f48e135aa2 100644 --- a/Modules/FindVulkan.cmake +++ b/Modules/FindVulkan.cmake @@ -13,12 +13,28 @@ and computing API. IMPORTED Targets ^^^^^^^^^^^^^^^^ -This module defines :prop_tgt:`IMPORTED` target ``Vulkan::Vulkan``, if -Vulkan has been found. +This module defines :prop_tgt:`IMPORTED` targets if Vulkan has been found: -.. versionadded:: 3.19 - This module defines :prop_tgt:`IMPORTED` target ``Vulkan::glslc``, if - Vulkan and the GLSLC SPIR-V compiler has been found. +``Vulkan::Vulkan`` + The main Vulkan library. + +``Vulkan::glslc`` + .. versionadded:: 3.19 + + The GLSLC SPIR-V compiler, if it has been found. + +``Vulkan::Headers`` + .. versionadded:: 3.21 + + Provides just Vulkan headers include paths, if found. No library is + included in this target. This can be useful for applications that + load Vulkan library dynamically. + +``Vulkan::glslangValidator`` + .. versionadded:: 3.21 + + The glslangValidator tool, if found. It is used to compile GLSL and + HLSL shaders into SPIR-V. Result Variables ^^^^^^^^^^^^^^^^ @@ -34,6 +50,7 @@ The module will also define three cache variables:: Vulkan_INCLUDE_DIR - the Vulkan include directory Vulkan_LIBRARY - the path to the Vulkan library Vulkan_GLSLC_EXECUTABLE - the path to the GLSL SPIR-V compiler + Vulkan_GLSLANG_VALIDATOR_EXECUTABLE - the path to the glslangValidator tool Hints ^^^^^ @@ -67,6 +84,11 @@ if(WIN32) HINTS "$ENV{VULKAN_SDK}/Bin" ) + find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE + NAMES glslangValidator + HINTS + "$ENV{VULKAN_SDK}/Bin" + ) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) find_library(Vulkan_LIBRARY NAMES vulkan-1 @@ -79,6 +101,11 @@ if(WIN32) HINTS "$ENV{VULKAN_SDK}/Bin32" ) + find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE + NAMES glslangValidator + HINTS + "$ENV{VULKAN_SDK}/Bin32" + ) endif() else() find_path(Vulkan_INCLUDE_DIR @@ -90,6 +117,9 @@ else() find_program(Vulkan_GLSLC_EXECUTABLE NAMES glslc HINTS "$ENV{VULKAN_SDK}/bin") + find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE + NAMES glslangValidator + HINTS "$ENV{VULKAN_SDK}/bin") endif() set(Vulkan_LIBRARIES ${Vulkan_LIBRARY}) @@ -100,7 +130,8 @@ find_package_handle_standard_args(Vulkan DEFAULT_MSG Vulkan_LIBRARY Vulkan_INCLUDE_DIR) -mark_as_advanced(Vulkan_INCLUDE_DIR Vulkan_LIBRARY Vulkan_GLSLC_EXECUTABLE) +mark_as_advanced(Vulkan_INCLUDE_DIR Vulkan_LIBRARY Vulkan_GLSLC_EXECUTABLE + Vulkan_GLSLANG_VALIDATOR_EXECUTABLE) if(Vulkan_FOUND AND NOT TARGET Vulkan::Vulkan) add_library(Vulkan::Vulkan UNKNOWN IMPORTED) @@ -109,7 +140,18 @@ if(Vulkan_FOUND AND NOT TARGET Vulkan::Vulkan) INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") endif() +if(Vulkan_FOUND AND NOT TARGET Vulkan::Headers) + add_library(Vulkan::Headers INTERFACE IMPORTED) + set_target_properties(Vulkan::Headers PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") +endif() + if(Vulkan_FOUND AND Vulkan_GLSLC_EXECUTABLE AND NOT TARGET Vulkan::glslc) add_executable(Vulkan::glslc IMPORTED) set_property(TARGET Vulkan::glslc PROPERTY IMPORTED_LOCATION "${Vulkan_GLSLC_EXECUTABLE}") endif() + +if(Vulkan_FOUND AND Vulkan_GLSLANG_VALIDATOR_EXECUTABLE AND NOT TARGET Vulkan::glslangValidator) + add_executable(Vulkan::glslangValidator IMPORTED) + set_property(TARGET Vulkan::glslangValidator PROPERTY IMPORTED_LOCATION "${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE}") +endif() diff --git a/Tests/FindVulkan/Test/CMakeLists.txt b/Tests/FindVulkan/Test/CMakeLists.txt index 9d36a0da30c..7ae8a1104a5 100644 --- a/Tests/FindVulkan/Test/CMakeLists.txt +++ b/Tests/FindVulkan/Test/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.4) -project(TestFindVulkan C) +project(TestFindVulkan C CXX) include(CTest) SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../) @@ -14,6 +14,15 @@ target_include_directories(test_var PRIVATE ${Vulkan_INCLUDE_DIRS}) target_link_libraries(test_var PRIVATE ${Vulkan_LIBRARIES}) add_test(NAME test_var COMMAND test_var) +add_executable(test_tgt_dl main-dynamicVulkanLoading.cpp) +target_link_libraries(test_tgt_dl Vulkan::Headers ${CMAKE_DL_LIBS}) +add_test(NAME test_tgt_dl COMMAND test_tgt_dl) + +add_executable(test_var_dl main-dynamicVulkanLoading.cpp) +target_include_directories(test_var_dl PRIVATE ${Vulkan_INCLUDE_DIRS}) +target_link_libraries(test_var_dl ${CMAKE_DL_LIBS}) +add_test(NAME test_var_dl COMMAND test_var_dl) + if(Vulkan_GLSLC_EXECUTABLE) add_test(NAME test_glslc COMMAND ${CMAKE_COMMAND} @@ -22,3 +31,12 @@ if(Vulkan_GLSLC_EXECUTABLE) -P "${CMAKE_CURRENT_LIST_DIR}/Run-glslc.cmake" ) endif() + +if(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE) + add_test(NAME test_glslangValidator + COMMAND ${CMAKE_COMMAND} + "-DVULKAN_GLSLANG_VALIDATOR_EXECUTABLE=${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE}" + "-DVULKAN_GLSLANG_VALIDATOR_EXECUTABLE_TARGET=$" + -P "${CMAKE_CURRENT_LIST_DIR}/Run-glslangValidator.cmake" + ) +endif() diff --git a/Tests/FindVulkan/Test/Run-glslangValidator.cmake b/Tests/FindVulkan/Test/Run-glslangValidator.cmake new file mode 100644 index 00000000000..27fd9503da5 --- /dev/null +++ b/Tests/FindVulkan/Test/Run-glslangValidator.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.12) + +function(run_glslangValidator exe exe_display) + execute_process(COMMAND ${exe} --help + OUTPUT_VARIABLE output + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE result + ) + + if(NOT result EQUAL 1) + message(SEND_ERROR "Result of ${exe_display} --help is ${result}, should be 1") + endif() + + if(NOT output MATCHES "^Usage: glslangValidator") + message(SEND_ERROR "Output of ${exe_display} --help is \"${output}\", should begin with \"Usage: glslangValidator\"") + endif() +endfunction() + +run_glslangValidator("${VULKAN_GLSLANG_VALIDATOR_EXECUTABLE}" "\${VULKAN_GLSLANG_VALIDATOR_EXECUTABLE}") +run_glslangValidator("${VULKAN_GLSLANG_VALIDATOR_EXECUTABLE_TARGET}" "Vulkan::glslangValidator") diff --git a/Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp b/Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp new file mode 100644 index 00000000000..f6f909fe1e1 --- /dev/null +++ b/Tests/FindVulkan/Test/main-dynamicVulkanLoading.cpp @@ -0,0 +1,55 @@ +#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 + +#include + +#include + +using namespace std; + +VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE + +int main() +{ + // catch exceptions + // (vulkan.hpp functions throws if they fail) + try { + + // initialize dynamic dispatcher + vk::DynamicLoader dl; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + dl.getProcAddress("vkGetInstanceProcAddr"); + VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); + + // Vulkan instance + vk::UniqueInstance instance = + vk::createInstanceUnique(vk::InstanceCreateInfo{ + vk::InstanceCreateFlags(), // flags + &(const vk::ApplicationInfo&)vk::ApplicationInfo{ + "CMake Test application", // application name + VK_MAKE_VERSION(0, 0, 0), // application version + "CMake Test Engine", // engine name + VK_MAKE_VERSION(0, 0, 0), // engine version + VK_API_VERSION_1_0, // api version + }, + 0, // enabled layer count + nullptr, // enabled layer names + 0, // enabled extension count + nullptr, // enabled extension names + }); + VULKAN_HPP_DEFAULT_DISPATCHER.init(instance.get()); + + // catch exceptions + } catch (vk::Error& e) { + cout << "Failed because of Vulkan exception: " << e.what() << endl; + } catch (exception& e) { + cout << "Failed because of exception: " << e.what() << endl; + } catch (...) { + cout << "Failed because of unspecified exception." << endl; + } + + // We can't assert in this code because in general vk::createInstanceUnique + // might throw if no driver is found - but if we get here, FindVulkan is + // working + + return 0; +} From 49693fab0d8380123a9c5442dbed480f0a35a244 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 24 May 2021 12:59:55 -0400 Subject: [PATCH 0503/1519] cmexpat: Create expat_config.h in build within CMake itself Expat 2.4.1 no longer supports compiling without this header. --- Utilities/cmexpat/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt index 904809683a6..ce7292728b1 100644 --- a/Utilities/cmexpat/CMakeLists.txt +++ b/Utilities/cmexpat/CMakeLists.txt @@ -7,6 +7,8 @@ ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") ENDIF() include(ConfigureChecks.cmake) +configure_file(expat_config.h.cmake expat_config.h @ONLY) + if(NOT WIN32) add_definitions(-DXML_DEV_URANDOM) endif() From 38f2562d5b159cdf7ce4340911c1adb30b3a003e Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Mon, 24 May 2021 13:40:25 -0400 Subject: [PATCH 0504/1519] CMP0082: Check EXCLUDE_FROM_ALL property at generate time Fixes: #22234 --- Source/cmInstallSubdirectoryGenerator.cxx | 6 +++--- Source/cmInstallSubdirectoryGenerator.h | 1 - Source/cmMakefile.cxx | 2 +- .../add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt | 1 + Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake | 2 +- Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake | 2 +- Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx index 76806e535a5..c333bcab208 100644 --- a/Source/cmInstallSubdirectoryGenerator.cxx +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -14,10 +14,10 @@ #include "cmSystemTools.h" cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator( - cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll, + cmMakefile* makefile, std::string binaryDirectory, cmListFileBacktrace backtrace) : cmInstallGenerator("", std::vector(), "", MessageDefault, - excludeFromAll, std::move(backtrace)) + false, std::move(backtrace)) , Makefile(makefile) , BinaryDirectory(std::move(binaryDirectory)) { @@ -52,7 +52,7 @@ bool cmInstallSubdirectoryGenerator::Compute(cmLocalGenerator* lg) void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os) { - if (!this->ExcludeFromAll) { + if (!this->Makefile->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { cmPolicies::PolicyStatus status = this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082); switch (status) { diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h index 614cef9214f..f174d07c4a5 100644 --- a/Source/cmInstallSubdirectoryGenerator.h +++ b/Source/cmInstallSubdirectoryGenerator.h @@ -21,7 +21,6 @@ class cmInstallSubdirectoryGenerator : public cmInstallGenerator public: cmInstallSubdirectoryGenerator(cmMakefile* makefile, std::string binaryDirectory, - bool excludeFromAll, cmListFileBacktrace backtrace); ~cmInstallSubdirectoryGenerator() override; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 78cae0e9864..dd254063c8f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1844,7 +1844,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, } this->AddInstallGenerator(cm::make_unique( - subMf, binPath, excludeFromAll, this->GetBacktrace())); + subMf, binPath, this->GetBacktrace())); } const std::string& cmMakefile::GetCurrentSourceDirectory() const diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt index 1bd7f495bf6..32bb1a96b65 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-ExcludeFromAll/CMakeLists.txt @@ -1 +1,2 @@ install(CODE "message(STATUS \"exclude\")") +set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake b/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake index 56c1b81f79d..8ebf21b3d69 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake +++ b/Tests/RunCMake/add_subdirectory/CMP0082-NEW.cmake @@ -1,3 +1,3 @@ add_subdirectory(CMP0082) -add_subdirectory(CMP0082-ExcludeFromAll EXCLUDE_FROM_ALL) +add_subdirectory(CMP0082-ExcludeFromAll) install(CODE "message(STATUS \"top\")") diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake b/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake index 56c1b81f79d..8ebf21b3d69 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake +++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD.cmake @@ -1,3 +1,3 @@ add_subdirectory(CMP0082) -add_subdirectory(CMP0082-ExcludeFromAll EXCLUDE_FROM_ALL) +add_subdirectory(CMP0082-ExcludeFromAll) install(CODE "message(STATUS \"top\")") diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake b/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake index 56c1b81f79d..8ebf21b3d69 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN.cmake @@ -1,3 +1,3 @@ add_subdirectory(CMP0082) -add_subdirectory(CMP0082-ExcludeFromAll EXCLUDE_FROM_ALL) +add_subdirectory(CMP0082-ExcludeFromAll) install(CODE "message(STATUS \"top\")") From 0f553b14b415b96ccea8a9dc9bd6537e5475d150 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 25 May 2021 00:01:05 -0400 Subject: [PATCH 0505/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b80af475ed3..e92c2a00d8a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210524) +set(CMake_VERSION_PATCH 20210525) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 74a2a7a4779636e814e28da41a6e164bfbc3d266 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Mon, 24 May 2021 22:56:16 +0200 Subject: [PATCH 0506/1519] Compiler/TI: Restore response file usage for linker The commit 98fea8205e (Compiler/TI: Avoid response file usage for linker, 2020-07-11, v3.19.0-rc1~495^2) disabled linker file usage by default. The previous settings were working, even if not for all cases. Restore them and add an explanation in a comment. Issue: #22233 --- Modules/Compiler/TI.cmake | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Modules/Compiler/TI.cmake b/Modules/Compiler/TI.cmake index c8c16351343..0f9ded3ca4e 100644 --- a/Modules/Compiler/TI.cmake +++ b/Modules/Compiler/TI.cmake @@ -16,6 +16,10 @@ set(__COMPILER_TI_SOURCE_FLAG_ASM "--asm_file") macro(__compiler_ti lang) set(CMAKE_${lang}_RESPONSE_FILE_FLAG "--cmd_file=") + # Using --cmd_file flag is not possible after the --run_linker flag. + # By using a whitespace only the filename is used without flag. + # That file is interpreted as linker command file which may contain files to link. + set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG " ") set(CMAKE_INCLUDE_FLAG_${lang} "--include_path=") set(CMAKE_DEPFILE_FLAGS_${lang} "--preproc_with_compile --preproc_dependency=") @@ -29,11 +33,6 @@ macro(__compiler_ti lang) set(CMAKE_${lang}_ARCHIVE_APPEND " qa ") set(CMAKE_${lang}_ARCHIVE_FINISH "") - # After the --run_linker flag a response file is not possible - set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "") - set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 0) - set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 0) - set(CMAKE_${lang}_LINK_EXECUTABLE " --run_linker --output_file= --map_file=.map ") endmacro() From ef553410e24959dac8413a7f2277d42530fbc0f7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 20 May 2021 14:21:56 -0400 Subject: [PATCH 0507/1519] Ninja/Swift: Remove redundant calls to ConvertToNinjaPath `GetSourceFilePath` already handles converting to a Ninja path. --- Source/cmNinjaNormalTargetGenerator.cxx | 8 +++----- Source/cmNinjaTargetGenerator.cxx | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 1b514b8a8db..e4439814182 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -1072,9 +1072,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmLocalGenerator const* LocalGen = this->GetLocalGenerator(); for (const auto& source : sources) { oss << " " - << LocalGen->ConvertToOutputFormat( - this->ConvertToNinjaPath(this->GetSourceFilePath(source)), - cmOutputConverter::SHELL); + << LocalGen->ConvertToOutputFormat(this->GetSourceFilePath(source), + cmOutputConverter::SHELL); } return oss.str(); }(); @@ -1094,8 +1093,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( for (const auto& source : sources) { linkBuild.Outputs.push_back( this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); - linkBuild.ExplicitDeps.push_back( - this->ConvertToNinjaPath(this->GetSourceFilePath(source))); + linkBuild.ExplicitDeps.emplace_back(this->GetSourceFilePath(source)); } linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3ebf3645df0..669953f8fd3 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1575,8 +1575,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( cmSourceFile const* source, const std::string& config) { - std::string const sourceFilePath = - this->ConvertToNinjaPath(this->GetSourceFilePath(source)); + std::string const sourceFilePath = this->GetSourceFilePath(source); std::string const objectFilePath = this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const swiftDepsPath = [source, objectFilePath]() -> std::string { From 51116c3ea9d9d69c9c71cf736225f1ef0e927593 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 May 2021 13:58:46 -0400 Subject: [PATCH 0508/1519] cmLocalNinjaGenerator: Remove unnecessary CollapseFullPath call `ConvertToIncludeReference` is only called with absolute paths. One branch already assumed this. --- Source/cmLocalNinjaGenerator.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index fb6c730e6a9..22a1a1a66a0 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -209,9 +209,7 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( cmOutputConverter::OutputFormat format) { if (pathStyle == IncludePathStyle::Absolute) { - return this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(path, this->GetCurrentBinaryDirectory()), - format); + return this->ConvertToOutputFormat(path, format); } return this->ConvertToOutputFormat(this->MaybeRelativeToTopBinDir(path), format); From dfc98774a2bca87bf6c2b986389763100fd59037 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 May 2021 14:29:52 -0400 Subject: [PATCH 0509/1519] cmNinjaTargetGenerator: Rename local variable for clarity --- Source/cmNinjaTargetGenerator.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 669953f8fd3..b22f8f7a530 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1199,7 +1199,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( const std::string& fileConfig, bool firstForConfig) { std::string const language = source->GetLanguage(); - std::string const sourceFileName = + std::string const sourceFilePath = language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source); std::string const objectDir = this->ConvertToNinjaPath( cmStrCat(this->GeneratorTarget->GetSupportDirectory(), @@ -1251,7 +1251,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } this->ExportObjectCompileCommand( - language, sourceFileName, objectDir, objectFileName, objectFileDir, + language, sourceFilePath, objectDir, objectFileName, objectFileDir, vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config); objBuild.Outputs.push_back(objectFileName); @@ -1265,7 +1265,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } } - objBuild.ExplicitDeps.push_back(sourceFileName); + objBuild.ExplicitDeps.push_back(sourceFilePath); // Add precompile headers dependencies std::vector depList; @@ -1323,9 +1323,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( if (source->GetIsGenerated() && !source->GetPropertyAsBool("__CMAKE_GENERATED_BY_CMAKE") && !source->GetCustomCommand() && - !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) { + !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFilePath)) { this->GetGlobalGenerator()->AddAssumedSourceDependencies( - sourceFileName, objBuild.OrderOnlyDeps); + sourceFilePath, objBuild.OrderOnlyDeps); } // For some cases we scan to dynamically discover dependencies. From 0f2b1c9d1bc4f802a4ecb647f2ca7258fc378df5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 20 May 2021 14:16:09 -0400 Subject: [PATCH 0510/1519] cmNinjaTargetGenerator: Remove GetSourceFilePath call with different semantics Reference external object files using `ConvertToNinjaPath` directly. `GetSourceFilePath` is meant to reference source files to be compiled. --- Source/cmNinjaTargetGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index b22f8f7a530..5c365c4e907 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -987,7 +987,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir( - this->GetSourceFilePath(sf), config); + this->ConvertToNinjaPath(sf->GetFullPath()), config); if (!cmSystemTools::StringEndsWith(objectFileName, cmToCStr(pchExtension))) { this->Configs[config].Objects.push_back(objectFileName); From fb3a57575aa91c636963a12b7d0b6ec64bfce241 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 May 2021 14:14:53 -0400 Subject: [PATCH 0511/1519] cmNinjaTargetGenerator: Rename source file path lookup method for clarity The `GetSourceFilePath` method is meant only for compiled sources, and automatically handles converting it to a path for the Ninja build manifest. Rename the method to clarify both. --- Source/cmNinjaNormalTargetGenerator.cxx | 8 +++++--- Source/cmNinjaTargetGenerator.cxx | 9 +++++---- Source/cmNinjaTargetGenerator.h | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index e4439814182..e5e57d28a0f 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -1072,8 +1072,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmLocalGenerator const* LocalGen = this->GetLocalGenerator(); for (const auto& source : sources) { oss << " " - << LocalGen->ConvertToOutputFormat(this->GetSourceFilePath(source), - cmOutputConverter::SHELL); + << LocalGen->ConvertToOutputFormat( + this->GetCompiledSourceNinjaPath(source), + cmOutputConverter::SHELL); } return oss.str(); }(); @@ -1093,7 +1094,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( for (const auto& source : sources) { linkBuild.Outputs.push_back( this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); - linkBuild.ExplicitDeps.emplace_back(this->GetSourceFilePath(source)); + linkBuild.ExplicitDeps.emplace_back( + this->GetCompiledSourceNinjaPath(source)); } linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 5c365c4e907..5499ff7c5b6 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -379,7 +379,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( return result; } -std::string cmNinjaTargetGenerator::GetSourceFilePath( +std::string cmNinjaTargetGenerator::GetCompiledSourceNinjaPath( cmSourceFile const* source) const { return this->ConvertToNinjaPath(source->GetFullPath()); @@ -1199,8 +1199,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( const std::string& fileConfig, bool firstForConfig) { std::string const language = source->GetLanguage(); - std::string const sourceFilePath = - language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source); + std::string const sourceFilePath = language == "RC" + ? source->GetFullPath() + : this->GetCompiledSourceNinjaPath(source); std::string const objectDir = this->ConvertToNinjaPath( cmStrCat(this->GeneratorTarget->GetSupportDirectory(), this->GetGlobalGenerator()->ConfigDirectory(config))); @@ -1575,7 +1576,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( cmSourceFile const* source, const std::string& config) { - std::string const sourceFilePath = this->GetSourceFilePath(source); + std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source); std::string const objectFilePath = this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const swiftDepsPath = [source, objectFilePath]() -> std::string { diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 3a28cef94c9..72f6b5f2247 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -116,7 +116,7 @@ class cmNinjaTargetGenerator : public cmCommonTargetGenerator bool ignoreType = false) const; /// @return the source file path for the given @a source. - std::string GetSourceFilePath(cmSourceFile const* source) const; + std::string GetCompiledSourceNinjaPath(cmSourceFile const* source) const; /// @return the object file path for the given @a source. std::string GetObjectFilePath(cmSourceFile const* source, From efb8d7b4a1d82f2ce4bb01f200367679a6dc46c4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 20 May 2021 14:39:43 -0400 Subject: [PATCH 0512/1519] cmNinjaTargetGenerator: Reduce string copies in ConvertToNinjaPath wrapper The global generator's method returns a reference to a cached value. Return that from the wrapper too. --- Source/cmNinjaTargetGenerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 72f6b5f2247..daf78176202 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -101,7 +101,7 @@ class cmNinjaTargetGenerator : public cmCommonTargetGenerator const std::string& language, const std::string& config); - std::string ConvertToNinjaPath(const std::string& path) const + std::string const& ConvertToNinjaPath(const std::string& path) const { return this->GetGlobalGenerator()->ConvertToNinjaPath(path); } From 18408c0b88423a40d239705eb28b65b481cf0973 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 20 May 2021 14:36:58 -0400 Subject: [PATCH 0513/1519] cmGlobalNinjaGenerator: Add helper to compute absolute paths for build.ninja --- Source/cmGlobalNinjaGenerator.cxx | 9 +++++++++ Source/cmGlobalNinjaGenerator.h | 1 + Source/cmNinjaTargetGenerator.h | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 6034434e2cf..09cbaec999a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1160,6 +1160,15 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( .first->second; } +std::string cmGlobalNinjaGenerator::ConvertToNinjaAbsPath( + std::string path) const +{ +#ifdef _WIN32 + std::replace(path.begin(), path.end(), '/', '\\'); +#endif + return path; +} + void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName, const std::string& config) { diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 7a3674e76f3..bb4ce2bf202 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -261,6 +261,7 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator } std::string const& ConvertToNinjaPath(const std::string& path) const; + std::string ConvertToNinjaAbsPath(std::string path) const; struct MapToNinjaPathImpl { diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index daf78176202..4b4cf8d3619 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -110,6 +110,11 @@ class cmNinjaTargetGenerator : public cmCommonTargetGenerator return this->GetGlobalGenerator()->MapToNinjaPath(); } + std::string ConvertToNinjaAbsPath(std::string path) const + { + return this->GetGlobalGenerator()->ConvertToNinjaAbsPath(std::move(path)); + } + /// @return the list of link dependency for the given target @a target. cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage, const std::string& config, From 48471cfd18d5b2b6b4fd7270d21732335156d086 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 20 May 2021 16:52:54 -0400 Subject: [PATCH 0514/1519] cmNinjaNormalTargetGenerator: Factor out build event byproduct collection This was left out of commit 68e5f92cad (cmGlobalNinjaGenerator: Factor out custom command output collection, 2021-05-18). --- Source/cmNinjaNormalTargetGenerator.cxx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index e5e57d28a0f..4c33334aeb1 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -1195,7 +1195,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( } } - cmNinjaDeps byproducts; + cmGlobalNinjaGenerator::CCOutputs byproducts(this->GetGlobalGenerator()); if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( @@ -1203,7 +1203,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( vars["TARGET_IMPLIB"] = impLibPath; this->EnsureParentDirectoryExists(impLibPath); if (gt->HasImportLibrary(config)) { - byproducts.push_back(targetOutputImplib); + // Some linkers may update a binary without touching its import lib. + byproducts.ExplicitOuts.emplace_back(targetOutputImplib); if (firstForConfig) { globalGen->GetByproductsForCleanTarget(config).push_back( targetOutputImplib); @@ -1261,8 +1262,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( true, config); localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); std::vector const& ccByproducts = ccg.GetByproducts(); - std::transform(ccByproducts.begin(), ccByproducts.end(), - std::back_inserter(byproducts), this->MapToNinjaPath()); + byproducts.Add(ccByproducts); std::transform( ccByproducts.begin(), ccByproducts.end(), std::back_inserter(globalGen->GetByproductsForCleanTarget()), @@ -1382,12 +1382,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( } // Ninja should restat after linking if and only if there are byproducts. - vars["RESTAT"] = byproducts.empty() ? "" : "1"; + vars["RESTAT"] = byproducts.ExplicitOuts.empty() ? "" : "1"; - for (std::string const& o : byproducts) { - globalGen->SeenCustomCommandOutput(o); - linkBuild.Outputs.push_back(o); - } + linkBuild.Outputs.reserve(linkBuild.Outputs.size() + + byproducts.ExplicitOuts.size()); + std::move(byproducts.ExplicitOuts.begin(), byproducts.ExplicitOuts.end(), + std::back_inserter(linkBuild.Outputs)); + linkBuild.WorkDirOuts = std::move(byproducts.WorkDirOuts); // Write the build statement for this target. bool usedResponseFile = false; From eb98d4511146db844029c809fde81982d3928e54 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 25 May 2021 10:40:15 -0400 Subject: [PATCH 0515/1519] Ninja: Handle depfiles with absolute paths to generated files in Ninja < 1.7 Extend the change from commit 2725ecff38 (Ninja: Handle depfiles with absolute paths to generated files, 2021-05-19) to work on versions of Ninja that do not support implicit outputs. Specify the absolute paths as normal outputs on such versions. Issue: #13894, #21865 --- Source/cmGlobalNinjaGenerator.cxx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 09cbaec999a..a8a49a03725 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -222,7 +222,9 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, } } // Write implicit outputs - if (!build.ImplicitOuts.empty() || !build.WorkDirOuts.empty()) { + if (!build.ImplicitOuts.empty()) { + // Assume Ninja is new enough to support implicit outputs. + // Callers should not populate this field otherwise. buildStr = cmStrCat(buildStr, " |"); for (std::string const& implicitOut : build.ImplicitOuts) { buildStr = cmStrCat(buildStr, ' ', this->EncodePath(implicitOut)); @@ -230,11 +232,18 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, this->CombinedBuildOutputs.insert(implicitOut); } } + } + + // Repeat some outputs, but expressed as absolute paths. + // This helps Ninja handle absolute paths found in a depfile. + // FIXME: Unfortunately this causes Ninja to stat the file twice. + // We could avoid this if Ninja Issue 1251 were fixed. + if (!build.WorkDirOuts.empty()) { + if (this->SupportsImplicitOuts() && build.ImplicitOuts.empty()) { + // Make them implicit outputs if supported by this version of Ninja. + buildStr = cmStrCat(buildStr, " |"); + } for (std::string const& workdirOut : build.WorkDirOuts) { - // Repeat some outputs, but expressed as absolute paths. - // This helps Ninja handle absolute paths found in a depfile. - // FIXME: Unfortunately this causes Ninja to stat the file twice. - // We could avoid this if Ninja Issue 1251 were fixed. buildStr = cmStrCat(buildStr, " ${cmake_ninja_workdir}", this->EncodePath(workdirOut)); } @@ -322,8 +331,7 @@ void cmGlobalNinjaGenerator::CCOutputs::Add( { for (std::string const& path : paths) { std::string out = this->GG->ConvertToNinjaPath(path); - if (this->GG->SupportsImplicitOuts() && - !cmSystemTools::FileIsFullPath(out)) { + if (!cmSystemTools::FileIsFullPath(out)) { // This output is expressed as a relative path. Repeat it, // but expressed as an absolute path for Ninja Issue 1251. this->WorkDirOuts.emplace_back(out); From c564a3e3fff52ef811291c5ba8fb07a5a1b47f97 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 19 May 2021 14:27:04 -0400 Subject: [PATCH 0516/1519] Ninja: Always compile sources using absolute paths The Ninja generator traditionally referenced source files and include directories using paths relative to the build directory if they could be expressed without a `../` sequence that leaves the build and source directories. For example, when using a `build/` directory inside the source tree, sources would be compiled as `-c ../src.c` and include directories would be referenced as `-I ../include`. This approach matches the traditional Ninja convention of using relative paths whenever possible, but has undesirable side effects such as: * Compiler diagnostic messages may not use absolute paths, making it harder for IDEs/editors to find the referenced sources or headers. * Debug symbols may not use absolute paths, making it harder for debuggers to find the referenced sources or headers. * Different results depending on the path to the build tree relative to the source tree. * Inconsistent with the Makefile generators, which use absolute paths. Switch to always using absolute paths to reference source files and include directories on compiler command lines. While alternative solutions for diagnostic messages and debug symbols may exist with specific tooling, this is the simplest and most consistent approach. Note that a previous attempt to do this in commit 955c2a630a (Ninja: Use full path for all source files, 2016-08-05, v3.7.0-rc1~275^2) was reverted by commit 666ad1df2d (Revert "Ninja: Use full path for all source files", 2017-02-24, v3.8.0-rc2~9^2) due to problems hooking up depfile dependencies on generated files. This time, the changes in commit 2725ecff38 (Ninja: Handle depfiles with absolute paths to generated files, 2021-05-19) should avoid those problems. Fixes: #13894, #17450 --- Help/release/dev/ninja-absolute-paths.rst | 6 ++++++ Source/cmGlobalNinjaGenerator.cxx | 1 + Source/cmLocalNinjaGenerator.cxx | 8 +++----- Source/cmNinjaTargetGenerator.cxx | 7 +++---- Tests/RunCMake/Ninja/RunCMakeTest.cmake | 4 ++-- 5 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 Help/release/dev/ninja-absolute-paths.rst diff --git a/Help/release/dev/ninja-absolute-paths.rst b/Help/release/dev/ninja-absolute-paths.rst new file mode 100644 index 00000000000..2dfc1b76fe1 --- /dev/null +++ b/Help/release/dev/ninja-absolute-paths.rst @@ -0,0 +1,6 @@ +ninja-absolute-paths +-------------------- + +* The :ref:`Ninja Generators` now pass source files and include directories + to the compiler using absolute paths. This makes diagnostic messages and + debug symbols more consistent, and matches the :ref:`Makefile Generators`. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index a8a49a03725..cbe1bc85014 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -335,6 +335,7 @@ void cmGlobalNinjaGenerator::CCOutputs::Add( // This output is expressed as a relative path. Repeat it, // but expressed as an absolute path for Ninja Issue 1251. this->WorkDirOuts.emplace_back(out); + this->GG->SeenCustomCommandOutput(this->GG->ConvertToNinjaAbsPath(path)); } this->GG->SeenCustomCommandOutput(out); this->ExplicitOuts.emplace_back(std::move(out)); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 22a1a1a66a0..81425991c43 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -208,11 +208,9 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( std::string const& path, IncludePathStyle pathStyle, cmOutputConverter::OutputFormat format) { - if (pathStyle == IncludePathStyle::Absolute) { - return this->ConvertToOutputFormat(path, format); - } - return this->ConvertToOutputFormat(this->MaybeRelativeToTopBinDir(path), - format); + // FIXME: Remove IncludePathStyle infrastructure. It is no longer used. + static_cast(pathStyle); + return this->ConvertToOutputFormat(path, format); } // Private methods. diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 5499ff7c5b6..4feb0bb2288 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -382,7 +382,8 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( std::string cmNinjaTargetGenerator::GetCompiledSourceNinjaPath( cmSourceFile const* source) const { - return this->ConvertToNinjaPath(source->GetFullPath()); + // Pass source files to the compiler by absolute path. + return this->ConvertToNinjaAbsPath(source->GetFullPath()); } std::string cmNinjaTargetGenerator::GetObjectFilePath( @@ -1199,9 +1200,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( const std::string& fileConfig, bool firstForConfig) { std::string const language = source->GetLanguage(); - std::string const sourceFilePath = language == "RC" - ? source->GetFullPath() - : this->GetCompiledSourceNinjaPath(source); + std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source); std::string const objectDir = this->ConvertToNinjaPath( cmStrCat(this->GeneratorTarget->GetSupportDirectory(), this->GetGlobalGenerator()->ConfigDirectory(config))); diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 1350326164b..8c91b34d9d8 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -163,12 +163,12 @@ run_LooseObjectDepends() function (run_AssumedSources) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build) run_cmake(AssumedSources) - run_ninja("${RunCMake_TEST_BINARY_DIR}" "target.c") + run_ninja("${RunCMake_TEST_BINARY_DIR}" "${RunCMake_TEST_BINARY_DIR}/target.c") if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/target.c") message(FATAL_ERROR "Dependencies for an assumed source did not hook up properly for 'target.c'.") endif () - run_ninja("${RunCMake_TEST_BINARY_DIR}" "target-no-depends.c") + run_ninja("${RunCMake_TEST_BINARY_DIR}" "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c") if (EXISTS "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c") message(FATAL_ERROR "Dependencies for an assumed source were magically hooked up for 'target-no-depends.c'.") From c6e36f6059d279ad72bbbd4e56e96c57e0dd0c8e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 26 May 2021 00:01:43 -0400 Subject: [PATCH 0517/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e92c2a00d8a..8abb44c4cae 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210525) +set(CMake_VERSION_PATCH 20210526) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2ae72ef74b1a8b3034c4685de68f39d1e198a84c Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 14:22:32 -0400 Subject: [PATCH 0518/1519] Xcode: Enable multi-arch TARGET_OBJECTS genex in [INTERFACE_]LINK_LIBRARIES This was an oversight in the original implementation. --- Source/cmGeneratorTarget.cxx | 2 ++ Tests/RunCMake/add_executable/RunCMakeTest.cmake | 4 +--- Tests/RunCMake/add_library/RunCMakeTest.cmake | 14 ++++++-------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e2ec82a5e24..a7d825deb96 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6291,6 +6291,7 @@ void cmGeneratorTarget::ExpandLinkItems( } std::vector libs; std::unique_ptr cge = ge.Parse(value); + cge->SetEvaluateForBuildsystem(true); cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this, headTarget->LinkerLanguage), libs); @@ -7428,6 +7429,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( nullptr); cmGeneratorExpression ge(*btIt); std::unique_ptr const cge = ge.Parse(*le); + cge->SetEvaluateForBuildsystem(true); std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr, this->LinkerLanguage); diff --git a/Tests/RunCMake/add_executable/RunCMakeTest.cmake b/Tests/RunCMake/add_executable/RunCMakeTest.cmake index 88916b71f35..70a68f265b4 100644 --- a/Tests/RunCMake/add_executable/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_executable/RunCMakeTest.cmake @@ -2,6 +2,4 @@ include(RunCMake) run_cmake(NoSources) run_cmake(OnlyObjectSources) -if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") - run_cmake(NoSourcesButLinkObjects) -endif() +run_cmake(NoSourcesButLinkObjects) diff --git a/Tests/RunCMake/add_library/RunCMakeTest.cmake b/Tests/RunCMake/add_library/RunCMakeTest.cmake index dfadb8fc18b..3283625e494 100644 --- a/Tests/RunCMake/add_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_library/RunCMakeTest.cmake @@ -16,11 +16,9 @@ run_cmake(SHAREDwithOnlyObjectSources) run_cmake(MODULEwithOnlyObjectSources) run_cmake(UNKNOWNwithOnlyObjectSources) -if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") - run_cmake(INTERFACEwithNoSourcesButLinkObjects) - run_cmake(OBJECTwithNoSourcesButLinkObjects) - run_cmake(STATICwithNoSourcesButLinkObjects) - run_cmake(SHAREDwithNoSourcesButLinkObjects) - run_cmake(MODULEwithNoSourcesButLinkObjects) - run_cmake(UNKNOWNwithNoSourcesButLinkObjects) -endif() +run_cmake(INTERFACEwithNoSourcesButLinkObjects) +run_cmake(OBJECTwithNoSourcesButLinkObjects) +run_cmake(STATICwithNoSourcesButLinkObjects) +run_cmake(SHAREDwithNoSourcesButLinkObjects) +run_cmake(MODULEwithNoSourcesButLinkObjects) +run_cmake(UNKNOWNwithNoSourcesButLinkObjects) From e55c86873e87ef464b49bec944948273ce38e4ca Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 27 May 2021 00:01:13 -0400 Subject: [PATCH 0519/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8abb44c4cae..84523ca9a54 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210526) +set(CMake_VERSION_PATCH 20210527) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e71c4f7729930a6e5ff803edc5c9e2b5db54695e Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 27 May 2021 10:26:11 -0400 Subject: [PATCH 0520/1519] CMAKE_CFG_INTDIR: Formally deprecate in favor of $ --- Help/variable/CMAKE_CFG_INTDIR.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Help/variable/CMAKE_CFG_INTDIR.rst b/Help/variable/CMAKE_CFG_INTDIR.rst index 842654ec5c3..43668eaac87 100644 --- a/Help/variable/CMAKE_CFG_INTDIR.rst +++ b/Help/variable/CMAKE_CFG_INTDIR.rst @@ -1,6 +1,12 @@ CMAKE_CFG_INTDIR ---------------- +.. deprecated:: 3.21 + + This variable has poor support on :generator:`Ninja Multi-Config`, and + predates the existence of the :genex:`$` generator expression. Use + ``$`` instead. + Build-time reference to per-configuration output subdirectory. For native build systems supporting multiple configurations in the @@ -19,11 +25,6 @@ Example values: . = Ninja ${CONFIGURATION} = Ninja Multi-Config -Note that this variable only has limited support on -:generator:`Ninja Multi-Config`. It is recommended that you use the -``$`` :manual:`generator expression ` -instead. - Since these values are evaluated by the native build system, this variable is suitable only for use in command lines that will be evaluated at build time. Example of intended usage: From cf82300a63d476f897c2cf6176378dc870be4282 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 09:43:57 -0400 Subject: [PATCH 0521/1519] BinUtils: Clarify search logic and make it more consistent Consistently consider more-specific names before less-specific names. --- Modules/CMakeFindBinUtils.cmake | 75 ++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 4ce45af6d12..bfa949171a5 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -70,14 +70,17 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND OR (CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")) + # Start with the canonical names. set(_CMAKE_LINKER_NAMES "link") set(_CMAKE_AR_NAMES "lib") set(_CMAKE_MT_NAMES "mt") + + # Prepend toolchain-specific names. if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xClang") set(_CMAKE_NM_NAMES "llvm-nm" "nm") - list(APPEND _CMAKE_AR_NAMES "lib" "llvm-lib") - list(APPEND _CMAKE_MT_NAMES "mt" "llvm-mt") - list(APPEND _CMAKE_LINKER_NAMES "lld-link") + list(PREPEND _CMAKE_AR_NAMES "llvm-lib") + list(PREPEND _CMAKE_MT_NAMES "llvm-mt") + list(PREPEND _CMAKE_LINKER_NAMES "lld-link") list(APPEND _CMAKE_TOOL_VARS NM) endif() @@ -92,50 +95,54 @@ else() set(_CMAKE_TOOLCHAIN_LOCATION ${_CMAKE_TOOLCHAIN_LOCATION} ${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}/bin) endif() + # Start with the canonical names. + set(_CMAKE_AR_NAMES "ar") + set(_CMAKE_RANLIB_NAMES "ranlib") + set(_CMAKE_STRIP_NAMES "strip") + set(_CMAKE_LINKER_NAMES "ld") + set(_CMAKE_NM_NAMES "nm") + set(_CMAKE_OBJDUMP_NAMES "objdump") + set(_CMAKE_OBJCOPY_NAMES "objcopy") + set(_CMAKE_READELF_NAMES "readelf") + set(_CMAKE_DLLTOOL_NAMES "dlltool") + set(_CMAKE_ADDR2LINE_NAMES "addr2line") + + # Prepend toolchain-specific names. if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang) if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC") set(_CMAKE_LINKER_NAMES "lld-link") else() set(_CMAKE_LINKER_NAMES "ld.lld") endif() - list(APPEND _CMAKE_AR_NAMES "llvm-ar") - list(APPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") - list(APPEND _CMAKE_STRIP_NAMES "llvm-strip") - list(APPEND _CMAKE_NM_NAMES "llvm-nm") - list(APPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump") - list(APPEND _CMAKE_OBJCOPY_NAMES "llvm-objcopy") - list(APPEND _CMAKE_READELF_NAMES "llvm-readelf") - list(APPEND _CMAKE_DLLTOOL_NAMES "llvm-dlltool") - list(APPEND _CMAKE_ADDR2LINE_NAMES "llvm-addr2line") + list(PREPEND _CMAKE_AR_NAMES "llvm-ar") + list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") + list(PREPEND _CMAKE_STRIP_NAMES "llvm-strip") + list(PREPEND _CMAKE_NM_NAMES "llvm-nm") + list(PREPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump") + list(PREPEND _CMAKE_OBJCOPY_NAMES "llvm-objcopy") + list(PREPEND _CMAKE_READELF_NAMES "llvm-readelf") + list(PREPEND _CMAKE_DLLTOOL_NAMES "llvm-dlltool") + list(PREPEND _CMAKE_ADDR2LINE_NAMES "llvm-addr2line") endif() - list(APPEND _CMAKE_AR_NAMES "ar") - list(APPEND _CMAKE_RANLIB_NAMES "ranlib") - list(APPEND _CMAKE_STRIP_NAMES "strip") - list(APPEND _CMAKE_LINKER_NAMES "ld") - list(APPEND _CMAKE_NM_NAMES "nm") - list(APPEND _CMAKE_OBJDUMP_NAMES "objdump") - list(APPEND _CMAKE_OBJCOPY_NAMES "objcopy") - list(APPEND _CMAKE_READELF_NAMES "readelf") - list(APPEND _CMAKE_DLLTOOL_NAMES "dlltool") - list(APPEND _CMAKE_ADDR2LINE_NAMES "addr2line") - - list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE) + list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE) endif() foreach(_CMAKE_TOOL IN LISTS _CMAKE_TOOL_VARS) + # Build the final list of prefixed/suffixed names. + set(_CMAKE_${_CMAKE_TOOL}_FIND_NAMES "") foreach(_CMAKE_TOOL_NAME IN LISTS _CMAKE_${_CMAKE_TOOL}_NAMES) - if(NOT _CMAKE_TOOLCHAIN_PREFIX STREQUAL "") - if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "") - list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX}) - endif() - list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}) - endif() - if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "") - list(PREPEND _CMAKE_${_CMAKE_TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX}) - endif() + list(APPEND _CMAKE_${_CMAKE_TOOL}_FIND_NAMES + ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX} + ${_CMAKE_TOOLCHAIN_PREFIX}${_CMAKE_TOOL_NAME} + ${_CMAKE_TOOL_NAME}${_CMAKE_TOOLCHAIN_SUFFIX} + ${_CMAKE_TOOL_NAME} + ) endforeach() - find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + list(REMOVE_DUPLICATES _CMAKE_${_CMAKE_TOOL}_FIND_NAMES) + + find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_FIND_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + unset(_CMAKE_${_CMAKE_TOOL}_FIND_NAMES) endforeach() if(NOT CMAKE_RANLIB) From 995f5b4e7b81e6672eaafba2c6d9a145e3aefe5d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 09:29:35 -0400 Subject: [PATCH 0522/1519] BinUtils: Find linker and librarian for OpenWatcom Update our OpenWatcom linker and archiver rules to use the `` and `` placeholders instead of hard-coding the tool names. --- Modules/CMakeFindBinUtils.cmake | 5 +++++ Modules/Compiler/OpenWatcom.cmake | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index bfa949171a5..de516fce146 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -86,6 +86,11 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND list(APPEND _CMAKE_TOOL_VARS LINKER MT AR) +elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^x(Open)?Watcom$") + set(_CMAKE_LINKER_NAMES "wlink") + set(_CMAKE_AR_NAMES "wlib") + list(APPEND _CMAKE_TOOL_VARS LINKER AR) + # in all other cases search for ar, ranlib, etc. else() if(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN) diff --git a/Modules/Compiler/OpenWatcom.cmake b/Modules/Compiler/OpenWatcom.cmake index a9625137aaa..ec369081af6 100644 --- a/Modules/Compiler/OpenWatcom.cmake +++ b/Modules/Compiler/OpenWatcom.cmake @@ -43,13 +43,13 @@ endforeach() # C create import library set(CMAKE_C_CREATE_IMPORT_LIBRARY - "wlib -c -q -n -b +") + " -c -q -n -b +") # C++ create import library set(CMAKE_CXX_CREATE_IMPORT_LIBRARY ${CMAKE_C_CREATE_IMPORT_LIBRARY}) # C link a object files into an executable file set(CMAKE_C_LINK_EXECUTABLE - "wlink ${CMAKE_WLINK_QUIET} name file {} ") + " ${CMAKE_WLINK_QUIET} name file {} ") # C++ link a object files into an executable file set(CMAKE_CXX_LINK_EXECUTABLE ${CMAKE_C_LINK_EXECUTABLE}) @@ -69,19 +69,19 @@ set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE # C create a shared library set(CMAKE_C_CREATE_SHARED_LIBRARY - "wlink ${CMAKE_WLINK_QUIET} name option implib= file {} ") + " ${CMAKE_WLINK_QUIET} name option implib= file {} ") # C++ create a shared library set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) # C create a shared module set(CMAKE_C_CREATE_SHARED_MODULE - "wlink ${CMAKE_WLINK_QUIET} name file {} ") + " ${CMAKE_WLINK_QUIET} name file {} ") # C++ create a shared module set(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_C_CREATE_SHARED_MODULE}) # C create a static library set(CMAKE_C_CREATE_STATIC_LIBRARY - "wlib ${CMAKE_LIB_QUIET} -c -n -b ") + " ${CMAKE_LIB_QUIET} -c -n -b ") # C++ create a static library set(CMAKE_CXX_CREATE_STATIC_LIBRARY ${CMAKE_C_CREATE_STATIC_LIBRARY}) From 047585edc62fc4223a77a2c587a2ac795c91718f Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 10:37:17 -0400 Subject: [PATCH 0523/1519] BinUtils: Find linker and librarian for Intel compilers on Windows Update our Intel linker and archiver rules to use the `` and `` placeholders instead of hard-coding the tool names. --- Modules/CMakeFindBinUtils.cmake | 3 +++ Modules/Platform/Windows-Intel.cmake | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index de516fce146..9dac4a9b4ef 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -82,6 +82,9 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND list(PREPEND _CMAKE_MT_NAMES "llvm-mt") list(PREPEND _CMAKE_LINKER_NAMES "lld-link") list(APPEND _CMAKE_TOOL_VARS NM) + elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIntel") + list(PREPEND _CMAKE_AR_NAMES "xilib") + list(PREPEND _CMAKE_LINKER_NAMES "xilink") endif() list(APPEND _CMAKE_TOOL_VARS LINKER MT AR) diff --git a/Modules/Platform/Windows-Intel.cmake b/Modules/Platform/Windows-Intel.cmake index 01f8dd0b158..26e0cdef4f3 100644 --- a/Modules/Platform/Windows-Intel.cmake +++ b/Modules/Platform/Windows-Intel.cmake @@ -25,8 +25,4 @@ endif() include(Platform/Windows-MSVC) macro(__windows_compiler_intel lang) __windows_compiler_msvc(${lang}) - string(REPLACE "" "xilib" CMAKE_${lang}_CREATE_STATIC_LIBRARY "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}") - foreach(rule CREATE_SHARED_LIBRARY CREATE_SHARED_MODULE LINK_EXECUTABLE) - string(REPLACE "" "xilink" CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}") - endforeach() endmacro() From 91b8676f8c6dd2611a234bb0ef1697627e901772 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 12:06:36 -0400 Subject: [PATCH 0524/1519] Help: Clarify {PASS,FAIL}_REGULAR_EXPRESSION semantics w.r.t. exit code Also cross-reference them with each other and `SKIP_REGULAR_EXPRESSION`. --- Help/prop_test/FAIL_REGULAR_EXPRESSION.rst | 6 +++++- Help/prop_test/PASS_REGULAR_EXPRESSION.rst | 4 ++++ Help/prop_test/SKIP_REGULAR_EXPRESSION.rst | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst b/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst index facf90255d4..1ec451760a0 100644 --- a/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst +++ b/Help/prop_test/FAIL_REGULAR_EXPRESSION.rst @@ -1,7 +1,8 @@ FAIL_REGULAR_EXPRESSION ----------------------- -If the output matches this regular expression the test will fail. +If the output matches this regular expression the test will fail, +regardless of the process exit code. If set, if the output matches one of specified regular expressions, the test will fail. Example: @@ -13,3 +14,6 @@ the test will fail. Example: ) ``FAIL_REGULAR_EXPRESSION`` expects a list of regular expressions. + +See also the :prop_test:`PASS_REGULAR_EXPRESSION` and +:prop_test:`SKIP_REGULAR_EXPRESSION` test properties. diff --git a/Help/prop_test/PASS_REGULAR_EXPRESSION.rst b/Help/prop_test/PASS_REGULAR_EXPRESSION.rst index 0cd621526a5..96468c02a5b 100644 --- a/Help/prop_test/PASS_REGULAR_EXPRESSION.rst +++ b/Help/prop_test/PASS_REGULAR_EXPRESSION.rst @@ -2,6 +2,7 @@ PASS_REGULAR_EXPRESSION ----------------------- The output must match this regular expression for the test to pass. +The process exit code is ignored. If set, the test output will be checked against the specified regular expressions and at least one of the regular expressions has to match, @@ -14,3 +15,6 @@ otherwise the test will fail. Example: ) ``PASS_REGULAR_EXPRESSION`` expects a list of regular expressions. + +See also the :prop_test:`FAIL_REGULAR_EXPRESSION` and +:prop_test:`SKIP_REGULAR_EXPRESSION` test properties. diff --git a/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst index 46c4363c49c..60038e44075 100644 --- a/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst +++ b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst @@ -16,4 +16,6 @@ the test will be marked as skipped. Example: ``SKIP_REGULAR_EXPRESSION`` expects a list of regular expressions. -See also the :prop_test:`SKIP_RETURN_CODE` property. +See also the :prop_test:`SKIP_RETURN_CODE`, +:prop_test:`PASS_REGULAR_EXPRESSION`, and :prop_test:`FAIL_REGULAR_EXPRESSION` +test properties. From 13d112ea03f2b068da1f7ac3239a42a6cff94eda Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 14:05:04 -0400 Subject: [PATCH 0525/1519] CMake 3.20.3 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9057828b065..e0d72f22888 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 3) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2f38e5d21472f880ad9ad77a1cd6eb66d0363060 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 15:11:10 -0400 Subject: [PATCH 0526/1519] curl: Update script to get curl 7.77.0 --- Utilities/Scripts/update-curl.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash index 16cdd6575ba..34ff4de5705 100755 --- a/Utilities/Scripts/update-curl.bash +++ b/Utilities/Scripts/update-curl.bash @@ -8,7 +8,7 @@ readonly name="curl" readonly ownership="Curl Upstream " readonly subtree="Utilities/cmcurl" readonly repo="https://github.com/curl/curl.git" -readonly tag="curl-7_75_0" +readonly tag="curl-7_77_0" readonly shortlog=false readonly paths=" CMake/* From 18b2a8d7604f3aced9c93220806851f96e231f36 Mon Sep 17 00:00:00 2001 From: Curl Upstream Date: Wed, 26 May 2021 08:18:11 +0200 Subject: [PATCH 0527/1519] curl 2021-05-26 (6b951a69) Code extracted from: https://github.com/curl/curl.git at commit 6b951a6928811507d493303b2878e848c077b471 (curl-7_77_0). --- CMake/CurlTests.c | 20 +- CMake/Platforms/WindowsCache.cmake | 5 +- CMakeLists.txt | 127 +- include/curl/curl.h | 45 +- include/curl/curlver.h | 10 +- include/curl/typecheck-gcc.h | 12 +- lib/CMakeLists.txt | 17 +- lib/Makefile.inc | 5 + lib/amigaos.c | 29 +- lib/asyn-ares.c | 62 +- lib/asyn-thread.c | 76 +- lib/bufref.c | 127 ++ lib/bufref.h | 46 + lib/c-hyper.c | 47 +- lib/conncache.c | 2 - lib/connect.c | 129 +- lib/connect.h | 6 +- lib/content_encoding.c | 9 +- lib/cookie.c | 435 ++++--- lib/cookie.h | 13 +- lib/curl_addrinfo.c | 8 +- lib/curl_config.h.cmake | 65 +- lib/curl_endian.c | 6 +- lib/curl_endian.h | 4 +- lib/curl_get_line.c | 4 +- lib/curl_gssapi.c | 2 +- lib/curl_krb5.h | 1 - lib/curl_multibyte.c | 84 +- lib/curl_multibyte.h | 43 +- lib/curl_ntlm_core.c | 145 ++- lib/curl_ntlm_core.h | 18 +- lib/curl_path.c | 10 +- lib/curl_rtmp.c | 8 +- lib/curl_sasl.c | 302 +++-- lib/curl_sasl.h | 17 +- lib/curl_setup.h | 71 +- lib/curl_setup_once.h | 19 +- lib/dict.c | 11 +- lib/doh.c | 125 +- lib/dynbuf.h | 4 +- lib/easy.c | 58 +- lib/easyoptions.c | 7 +- lib/file.c | 40 +- lib/ftp.c | 121 +- lib/ftplistparser.c | 3 +- lib/getinfo.c | 10 +- lib/gopher.c | 2 + lib/hash.c | 4 +- lib/hostcheck.c | 8 +- lib/hostip.c | 84 +- lib/hostip.h | 10 +- lib/hostip6.c | 19 +- lib/hsts.c | 21 +- lib/hsts.h | 8 +- lib/http.c | 221 ++-- lib/http.h | 16 +- lib/http2.c | 219 ++-- lib/http2.h | 6 +- lib/http_aws_sigv4.c | 4 +- lib/http_digest.c | 11 +- lib/http_digest.h | 1 - lib/http_negotiate.c | 2 +- lib/http_ntlm.c | 102 +- lib/http_proxy.c | 114 +- lib/http_proxy.h | 24 + lib/imap.c | 10 +- lib/inet_ntop.c | 4 +- lib/krb5.c | 22 +- lib/ldap.c | 40 +- lib/llist.c | 6 +- lib/md4.c | 33 +- lib/md5.c | 31 +- lib/memdebug.c | 35 +- lib/mime.c | 4 +- lib/mprintf.c | 4 +- lib/mqtt.c | 1 + lib/multi.c | 480 +++++--- lib/multihandle.h | 50 +- lib/non-ascii.c | 8 +- lib/nonblock.c | 10 +- lib/openldap.c | 138 ++- lib/pingpong.h | 7 +- lib/pop3.c | 27 +- lib/progress.c | 92 +- lib/rtsp.c | 9 +- lib/select.c | 2 +- lib/sendf.c | 23 +- lib/setopt.c | 170 ++- lib/setup-vms.h | 8 +- lib/sha256.c | 42 +- lib/share.c | 4 +- lib/sigpipe.h | 4 +- lib/smb.c | 11 +- lib/smb.h | 6 +- lib/smtp.c | 12 +- lib/socketpair.h | 5 +- lib/socks.c | 6 +- lib/socks_gssapi.c | 2 +- lib/socks_sspi.c | 2 +- lib/splay.c | 18 +- lib/strerror.c | 5 +- lib/system_win32.c | 4 +- lib/telnet.c | 3 +- lib/tftp.c | 82 +- lib/timeval.c | 8 +- lib/transfer.c | 112 +- lib/url.c | 387 +++--- lib/urlapi.c | 96 +- lib/urldata.h | 167 ++- lib/vauth/cleartext.c | 70 +- lib/vauth/cram.c | 65 +- lib/vauth/digest.c | 62 +- lib/vauth/digest_sspi.c | 54 +- lib/vauth/gsasl.c | 124 ++ lib/vauth/krb5_gssapi.c | 100 +- lib/vauth/krb5_sspi.c | 115 +- lib/vauth/ntlm.c | 190 ++- lib/vauth/ntlm_sspi.c | 58 +- lib/vauth/oauth2.c | 53 +- lib/vauth/vauth.c | 25 +- lib/vauth/vauth.h | 89 +- lib/version.c | 59 +- lib/vquic/ngtcp2.c | 66 +- lib/vquic/quiche.c | 33 +- lib/vssh/libssh.c | 157 +-- lib/vssh/libssh2.c | 88 +- lib/vssh/ssh.h | 3 + lib/vssh/wolfssh.c | 10 +- lib/vtls/bearssl.c | 28 +- lib/vtls/gskit.c | 40 +- lib/vtls/gtls.c | 139 +-- lib/vtls/mbedtls.c | 53 +- lib/vtls/mesalink.c | 22 +- lib/vtls/nss.c | 65 +- lib/vtls/openssl.c | 583 +++++---- lib/vtls/rustls.c | 583 +++++++++ lib/vtls/rustls.h | 33 + lib/vtls/schannel.c | 137 ++- lib/vtls/schannel.h | 3 + lib/vtls/schannel_verify.c | 285 +++-- lib/vtls/sectransp.c | 1759 +++++++++++++++------------- lib/vtls/vtls.c | 73 +- lib/vtls/vtls.h | 39 +- lib/vtls/wolfssl.c | 117 +- lib/x509asn1.c | 6 +- 145 files changed, 6381 insertions(+), 4479 deletions(-) create mode 100644 lib/bufref.c create mode 100644 lib/bufref.h create mode 100644 lib/vauth/gsasl.c create mode 100644 lib/vtls/rustls.c create mode 100644 lib/vtls/rustls.h diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c index 949910d5e41..2fcce1bb383 100644 --- a/CMake/CurlTests.c +++ b/CMake/CurlTests.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -214,24 +214,6 @@ if (sizeof (bool *) ) #include int main() { return 0; } #endif -#ifdef RETSIGTYPE_TEST -#include -#include -#ifdef signal -# undef signal -#endif -#ifdef __cplusplus -extern "C" void (*signal (int, void (*)(int)))(int); -#else -void (*signal ()) (); -#endif - -int -main () -{ - return 0; -} -#endif #ifdef HAVE_INET_NTOA_R_DECL #include diff --git a/CMake/Platforms/WindowsCache.cmake b/CMake/Platforms/WindowsCache.cmake index 12cec52dc29..33c735a225f 100644 --- a/CMake/Platforms/WindowsCache.cmake +++ b/CMake/Platforms/WindowsCache.cmake @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -89,8 +89,6 @@ if(NOT UNIX) set(HAVE_INET_ADDR 1) set(HAVE_INET_NTOA 1) set(HAVE_INET_NTOA_R 0) - set(HAVE_TCGETATTR 0) - set(HAVE_TCSETATTR 0) set(HAVE_PERROR 1) set(HAVE_CLOSESOCKET 1) set(HAVE_SETVBUF 0) @@ -134,7 +132,6 @@ if(NOT UNIX) set(HAVE_GETADDRINFO 0) endif() set(STDC_HEADERS 1) - set(RETSIGTYPE_TEST 1) set(HAVE_SIGACTION 0) set(HAVE_MACRO_SIGSETJMP 0) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b92c2b6180..f5f560292f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,9 @@ mark_as_advanced(CURL_DISABLE_GOPHER) option(CURL_DISABLE_MQTT "to disable MQTT" OFF) mark_as_advanced(CURL_DISABLE_MQTT) +option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON) +mark_as_advanced(CURL_ENABLE_EXPORT_TARGET) + if(HTTP_ONLY) set(CURL_DISABLE_DICT ON) set(CURL_DISABLE_FILE ON) @@ -210,6 +213,8 @@ endif() option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF) mark_as_advanced(CURL_DISABLE_ALTSVC) +option(CURL_DISABLE_HSTS "to disable HSTS support" OFF) +mark_as_advanced(CURL_DISABLE_HSTS) option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) mark_as_advanced(CURL_DISABLE_COOKIES) option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) @@ -310,7 +315,6 @@ check_function_exists(gethostname HAVE_GETHOSTNAME) if(WIN32) check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32) check_library_exists_concat("winmm" getch HAVE_LIBWINMM) - list(APPEND CURL_LIBS "advapi32") endif() # check SSL libraries @@ -356,7 +360,6 @@ if(CMAKE_USE_SCHANNEL) set(SSL_ENABLED ON) set(USE_SCHANNEL ON) # Windows native SSL/TLS support set(USE_WINDOWS_SSPI ON) # CMAKE_USE_SCHANNEL implies CURL_WINDOWS_SSPI - list(APPEND CURL_LIBS "crypt32") endif() if(CURL_WINDOWS_SSPI) set(USE_WINDOWS_SSPI ON) @@ -383,6 +386,14 @@ if(CMAKE_USE_SECTRANSP) list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}") endif() +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration") + if(NOT SYSTEMCONFIGURATION_FRAMEWORK) + message(FATAL_ERROR "SystemConfiguration framework not found") + endif() + list(APPEND CURL_LIBS "${SYSTEMCONFIGURATION_FRAMEWORK}") +endif() + if(CMAKE_USE_OPENSSL) find_package(OpenSSL REQUIRED) set(SSL_ENABLED ON) @@ -505,10 +516,6 @@ if(USE_QUICHE) cmake_pop_check_state() endif() -if(WIN32) - set(USE_WIN32_CRYPTO ON) -endif() - if(NOT CURL_DISABLE_LDAP) if(WIN32) option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON) @@ -625,6 +632,14 @@ if(USE_LIBIDN2) check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2) endif() +if(WIN32) + option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF) + if(USE_WIN32_IDN) + list(APPEND CURL_LIBS "Normaliz") + set(WANT_IDN_PROTOTYPES ON) + endif() +endif() + # Check for symbol dlopen (same as HAVE_LIBDL) check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) @@ -847,7 +862,8 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT) foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS}) if(EXISTS "${SEARCH_CA_BUNDLE_PATH}") message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}") - set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}") + set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}" CACHE STRING + "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") break() endif() @@ -856,7 +872,8 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT) if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET)) if(EXISTS "/etc/ssl/certs") - set(CURL_CA_PATH "/etc/ssl/certs") + set(CURL_CA_PATH "/etc/ssl/certs" CACHE STRING + "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") endif() endif() @@ -874,9 +891,7 @@ if(NOT UNIX) check_include_file_concat("winsock.h" HAVE_WINSOCK_H) check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) - if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL) - set(CURL_LIBS ${CURL_LIBS} "crypt32") - endif() + check_include_file_concat("wincrypt.h" HAVE_WINCRYPT_H) endif() check_include_file_concat("stdio.h" HAVE_STDIO_H) @@ -999,20 +1014,18 @@ check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM) if(NOT HAVE_STRNCMPI) set(HAVE_STRCMPI) endif() +check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID) +check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES) + check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR) check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R) check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY) check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR) check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA) check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R) -check_symbol_exists(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR) -check_symbol_exists(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR) -check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET) -check_symbol_exists(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF) check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP) check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R) -check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT) check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID) check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R) check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID) @@ -1062,6 +1075,16 @@ if(HAVE_FSETXATTR) endforeach() endif() +set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h") +check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T) +set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T}) +set(CMAKE_EXTRA_INCLUDE_FILES "") + +set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h") +check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY) +set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY}) +set(CMAKE_EXTRA_INCLUDE_FILES "") + # sigaction and sigsetjmp are special. Use special mechanism for # detecting those, but only if previous attempt failed. if(HAVE_SIGNAL_H) @@ -1110,7 +1133,6 @@ foreach(CURL_TEST HAVE_IN_ADDR_T HAVE_BOOL_T STDC_HEADERS - RETSIGTYPE_TEST HAVE_INET_NTOA_R_DECL HAVE_INET_NTOA_R_DECL_REENTRANT HAVE_GETADDRINFO @@ -1211,12 +1233,6 @@ if(HAVE_FIONBIO OR set(HAVE_DISABLED_NONBLOCKING) endif() -if(RETSIGTYPE_TEST) - set(RETSIGTYPE void) -else() - set(RETSIGTYPE int) -endif() - if(CMAKE_COMPILER_IS_GNUCC AND APPLE) include(CheckCCompilerFlag) check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double) @@ -1254,6 +1270,19 @@ if(WIN32) # Use the manifest embedded in the Windows Resource set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST") + + # Check if crypto functions in wincrypt.h are actually available + if(HAVE_WINCRYPT_H) + check_symbol_exists(CryptAcquireContext "${CURL_INCLUDES}" USE_WINCRYPT) + endif() + if(USE_WINCRYPT) + set(USE_WIN32_CRYPTO ON) + endif() + + # Link required libraries for USE_WIN32_CRYPTO or USE_SCHANNEL + if(USE_WIN32_CRYPTO OR USE_SCHANNEL) + list(APPEND CURL_LIBS "advapi32" "crypt32") + endif() endif() if(MSVC) @@ -1266,6 +1295,11 @@ if(MSVC) else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") endif() + + # Use multithreaded compilation on VS 2008+ + if(MSVC_VERSION GREATER_EQUAL 1500) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") + endif() endif() if(CURL_WERROR) @@ -1335,14 +1369,6 @@ if(BUILD_TESTING) add_subdirectory(tests) endif() -# NTLM support requires crypto function adaptions from various SSL libs -# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS -if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO)) - set(use_ntlm ON) -else() - set(use_ntlm OFF) -endif() - # Helper to populate a list (_items) with a label when conditions (the remaining # args) are satisfied macro(_add_if label) @@ -1352,6 +1378,13 @@ macro(_add_if label) endif() endmacro() +# NTLM support requires crypto function adaptions from various SSL libs +# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS +if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_MBEDTLS OR + USE_DARWINSSL OR USE_WIN32_CRYPTO)) + set(use_curl_ntlm_core ON) +endif() + # Clear list and try to detect available features set(_items) _add_if("SSL" SSL_ENABLED) @@ -1361,13 +1394,14 @@ _add_if("libz" HAVE_LIBZ) _add_if("brotli" HAVE_BROTLI) _add_if("zstd" HAVE_ZSTD) _add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) -_add_if("IDN" HAVE_LIBIDN2) -_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND +_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN) +_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) # TODO SSP1 (Schannel) check is missing _add_if("SSPI" USE_WINDOWS_SSPI) _add_if("GSS-API" HAVE_GSSAPI) _add_if("alt-svc" NOT CURL_DISABLE_ALTSVC) +_add_if("HSTS" NOT CURL_DISABLE_HSTS) # TODO SSP1 missing for SPNEGO _add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) @@ -1375,9 +1409,12 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) # NTLM support requires crypto function adaptions from various SSL libs # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS -_add_if("NTLM" use_ntlm OR USE_WINDOWS_SSPI) +_add_if("NTLM" NOT CURL_DISABLE_CRYPTO_AUTH AND + (use_curl_ntlm_core OR USE_WINDOWS_SSPI)) # TODO missing option (autoconf: --enable-ntlm-wb) -_add_if("NTLM_WB" use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) +_add_if("NTLM_WB" NOT CURL_DISABLE_CRYPTO_AUTH AND + (use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND + NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) # TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP _add_if("TLS-SRP" USE_TLS_SRP) # TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header @@ -1411,8 +1448,10 @@ _add_if("POP3" NOT CURL_DISABLE_POP3) _add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED) _add_if("IMAP" NOT CURL_DISABLE_IMAP) _add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED) -_add_if("SMB" NOT CURL_DISABLE_SMB AND use_ntlm) -_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm) +_add_if("SMB" NOT CURL_DISABLE_SMB AND + use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) +_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND + use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) _add_if("SMTP" NOT CURL_DISABLE_SMTP) _add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED) _add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH) @@ -1428,7 +1467,7 @@ message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") # Clear list and collect SSL backends set(_items) -_add_if("Schannel" SSL_ENABLED AND USE_WINDOWS_SSPI) +_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL) _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) _add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP) _add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) @@ -1533,11 +1572,13 @@ configure_package_config_file(CMake/curl-config.cmake.in INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR} ) -install( - EXPORT "${TARGETS_EXPORT_NAME}" - NAMESPACE "${PROJECT_NAME}::" - DESTINATION ${CURL_INSTALL_CMAKE_DIR} -) +if(CURL_ENABLE_EXPORT_TARGET) + install( + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION ${CURL_INSTALL_CMAKE_DIR} + ) +endif() install( FILES ${version_config} ${project_config} diff --git a/include/curl/curl.h b/include/curl/curl.h index 71204ee327a..97de8c88ae0 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -155,7 +155,8 @@ typedef enum { CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ CURLSSLBACKEND_MBEDTLS = 11, CURLSSLBACKEND_MESALINK = 12, - CURLSSLBACKEND_BEARSSL = 13 + CURLSSLBACKEND_BEARSSL = 13, + CURLSSLBACKEND_RUSTLS = 14 } curl_sslbackend; /* aliases for library clones and renames */ @@ -611,6 +612,7 @@ typedef enum { CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ CURL_LAST /* never use! */ } CURLcode; @@ -887,6 +889,10 @@ typedef enum { operating system. Currently implemented under MS-Windows. */ #define CURLSSLOPT_NATIVE_CA (1<<4) +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5) + /* The default connection attempt delay in milliseconds for happy eyeballs. CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document this value, keep them in sync. */ @@ -1460,8 +1466,8 @@ typedef enum { #define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to - tell libcurl to resolve names to those IP versions only. This only has - affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), /* Set this option to limit the size of a file that will be downloaded from @@ -2078,6 +2084,23 @@ typedef enum { /* Parameters for V4 signature */ CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + /* Same as CURLOPT_SSL_VERIFYPEER but for DOH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), + + /* Same as CURLOPT_SSL_VERIFYHOST but for DOH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -2112,10 +2135,10 @@ typedef enum { /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host name resolves addresses using more than one IP protocol version, this option might be handy to force libcurl to use a specific IP version. */ -#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP +#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP versions that your system allows */ -#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ -#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ +#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */ /* three convenient "aliases" that follow the name scheme better */ #define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER @@ -2751,8 +2774,9 @@ typedef enum { CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59, + CURLINFO_REFERER = CURLINFO_STRING + 60, - CURLINFO_LASTONE = 59 + CURLINFO_LASTONE = 60 } CURLINFO; /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as @@ -2855,6 +2879,7 @@ typedef enum { CURLVERSION_SEVENTH, CURLVERSION_EIGHTH, CURLVERSION_NINTH, + CURLVERSION_TENTH, CURLVERSION_LAST /* never actually use this */ } CURLversion; @@ -2863,7 +2888,7 @@ typedef enum { 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_NINTH +#define CURLVERSION_NOW CURLVERSION_TENTH struct curl_version_info_data { CURLversion age; /* age of the returned struct */ @@ -2916,6 +2941,9 @@ struct curl_version_info_data { /* These fields were added in CURLVERSION_NINTH */ const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_version; /* human readable string. */ }; typedef struct curl_version_info_data curl_version_info_data; @@ -2953,6 +2981,7 @@ typedef struct curl_version_info_data curl_version_info_data; #define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ #define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ #define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */ +#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */ /* * NAME curl_version_info() diff --git a/include/curl/curlver.h b/include/curl/curlver.h index d61bb1c2d92..75fa93ca752 100644 --- a/include/curl/curlver.h +++ b/include/curl/curlver.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,16 +26,16 @@ a script at release-time. This was made its own header file in 7.11.2 */ /* This is the global package copyright */ -#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, ." +#define LIBCURL_COPYRIGHT "1996 - 2021 Daniel Stenberg, ." /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.75.0-DEV" +#define LIBCURL_VERSION "7.77.0-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 75 +#define LIBCURL_VERSION_MINOR 77 #define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier @@ -57,7 +57,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 0x074b00 +#define LIBCURL_VERSION_NUM 0x074d00 /* * This is the date and time when the full source package was created. The diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index 230f4c1067e..34d0267ed95 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -667,11 +667,11 @@ typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX * this will of course break if we're included before OpenSSL headers... */ -typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); -typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); -typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); -typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, - const void *); +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *, + const void *); #else typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9736e39e527..2575288f709 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms @@ -20,6 +20,7 @@ # ########################################################################### set(LIB_NAME libcurl) +set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library") if(BUILD_SHARED_LIBS) set(CURL_STATICLIB NO) @@ -98,7 +99,10 @@ if(WIN32) add_definitions(-D_USRDLL) endif() -set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL) +set_target_properties(${LIB_NAME} PROPERTIES + COMPILE_DEFINITIONS BUILDING_LIBCURL + OUTPUT_NAME ${LIBCURL_OUTPUT_NAME} + ) if(HIDES_CURL_PRIVATE_SYMBOLS) set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") @@ -117,13 +121,16 @@ endif() if(WIN32) if(BUILD_SHARED_LIBS) - # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" - set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") + if(MSVC) + # Add "_imp" as a suffix before the extension to avoid conflicting with + # the statically linked "libcurl.lib" + set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") + endif() endif() endif() target_include_directories(${LIB_NAME} INTERFACE - $ + $ $) install(TARGETS ${LIB_NAME} diff --git a/lib/Makefile.inc b/lib/Makefile.inc index e8d2259f2fd..3e9ddec12c2 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -25,6 +25,7 @@ LIB_VAUTH_CFILES = \ vauth/cram.c \ vauth/digest.c \ vauth/digest_sspi.c \ + vauth/gsasl.c \ vauth/krb5_gssapi.c \ vauth/krb5_sspi.c \ vauth/ntlm.c \ @@ -49,6 +50,7 @@ LIB_VTLS_CFILES = \ vtls/mesalink.c \ vtls/nss.c \ vtls/openssl.c \ + vtls/rustls.c \ vtls/schannel.c \ vtls/schannel_verify.c \ vtls/sectransp.c \ @@ -65,6 +67,7 @@ LIB_VTLS_HFILES = \ vtls/mesalink.h \ vtls/nssg.h \ vtls/openssl.h \ + vtls/rustls.h \ vtls/schannel.h \ vtls/sectransp.h \ vtls/vtls.h \ @@ -94,6 +97,7 @@ LIB_CFILES = \ asyn-ares.c \ asyn-thread.c \ base64.c \ + bufref.c \ c-hyper.c \ conncache.c \ connect.c \ @@ -214,6 +218,7 @@ LIB_HFILES = \ amigaos.h \ arpa_telnet.h \ asyn.h \ + bufref.h \ c-hyper.h \ conncache.h \ connect.h \ diff --git a/lib/amigaos.c b/lib/amigaos.c index d3b00d9083e..78bb22c7e2f 100644 --- a/lib/amigaos.c +++ b/lib/amigaos.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -90,6 +90,33 @@ void Curl_amiga_X509_free(X509 *a) { X509_free(a); } + +/* AmiSSL replaces many functions with macros. Curl requires pointer + * to some of these functions. Thus, we have to encapsulate these macros. + */ + +#include "warnless.h" + +int (SHA256_Init)(SHA256_CTX *c) +{ + return SHA256_Init(c); +}; + +int (SHA256_Update)(SHA256_CTX *c, const void *data, size_t len) +{ + return SHA256_Update(c, data, curlx_uztoui(len)); +}; + +int (SHA256_Final)(unsigned char *md, SHA256_CTX *c) +{ + return SHA256_Final(md, c); +}; + +void (X509_INFO_free)(X509_INFO *a) +{ + X509_INFO_free(a); +}; + #endif /* USE_AMISSL */ #endif /* __AMIGA__ */ diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 2484a7b498e..7827847350c 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -309,7 +309,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) pfd[i].fd = socks[i]; pfd[i].events |= POLLWRNORM|POLLOUT; } - if(pfd[i].events != 0) + if(pfd[i].events) num++; else break; @@ -384,13 +384,8 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, them */ res->temp_ai = NULL; - if(!data->state.async.dns) { - failf(data, "Could not resolve: %s (%s)", - data->state.async.hostname, - ares_strerror(data->state.async.status)); - result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: - CURLE_COULDNT_RESOLVE_HOST; - } + if(!data->state.async.dns) + result = Curl_resolver_error(data); else *dns = data->state.async.dns; @@ -625,28 +620,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, int *waitp) { char *bufp; - int family = PF_INET; *waitp = 0; /* default to synchronous response */ -#ifdef ENABLE_IPV6 - switch(data->set.ipver) { - default: -#if ARES_VERSION >= 0x010601 - family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older - c-ares versions this just falls through and defaults - to PF_INET */ - break; -#endif - case CURL_IPRESOLVE_V4: - family = PF_INET; - break; - case CURL_IPRESOLVE_V6: - family = PF_INET6; - break; - } -#endif /* ENABLE_IPV6 */ - bufp = strdup(hostname); if(bufp) { struct thread_data *res = NULL; @@ -666,33 +642,27 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, /* initial status - failed */ res->last_status = ARES_ENOTFOUND; -#ifdef ENABLE_IPV6 - if(family == PF_UNSPEC) { - if(Curl_ipv6works(data)) { - res->num_pending = 2; - - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET, query_completed_cb, data); - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET6, query_completed_cb, data); - } - else { - res->num_pending = 1; - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET, query_completed_cb, data); - } +#if ARES_VERSION >= 0x010601 + /* IPv6 supported by c-ares since 1.6.1 */ + if(Curl_ipv6works(data)) { + /* The stack seems to be IPv6-enabled */ + res->num_pending = 2; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET6, query_completed_cb, data); } else -#endif /* ENABLE_IPV6 */ +#endif /* ARES_VERSION >= 0x010601 */ { res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname((ares_channel)data->state.async.resolver, - hostname, family, + hostname, PF_INET, query_completed_cb, data); } diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 9fcbc3c1fdd..36f68cb493f 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -163,7 +163,7 @@ struct thread_sync_data { int port; char *hostname; /* hostname to resolve, Curl_async.hostname duplicate */ -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR struct Curl_easy *data; curl_socket_t sock_pair[2]; /* socket pair */ #endif @@ -201,7 +201,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd) if(tsd->res) Curl_freeaddrinfo(tsd->res); -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR /* * close one end of the socket pair (may be done in resolver thread); * the other end (for reading) is always closed in the parent thread. @@ -238,12 +238,12 @@ int init_thread_sync_data(struct thread_data *td, #endif tsd->mtx = malloc(sizeof(curl_mutex_t)); - if(tsd->mtx == NULL) + if(!tsd->mtx) goto err_exit; Curl_mutex_init(tsd->mtx); -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */ if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) { tsd->sock_pair[0] = CURL_SOCKET_BAD; @@ -297,7 +297,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) struct thread_data *td = tsd->td; char service[12]; int rc; -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR char buf[1]; #endif @@ -305,7 +305,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); - if(rc != 0) { + if(rc) { tsd->sock_error = SOCKERRNO?SOCKERRNO:rc; if(tsd->sock_error == 0) tsd->sock_error = RESOLVER_ENOMEM; @@ -322,7 +322,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) free(td); } else { -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR if(tsd->sock_pair[1] != CURL_SOCKET_BAD) { /* DNS has been resolved, signal client task */ buf[0] = 1; @@ -382,7 +382,7 @@ static void destroy_async_data(struct Curl_async *async) if(async->tdata) { struct thread_data *td = async->tdata; int done; -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR curl_socket_t sock_rd = td->tsd.sock_pair[0]; struct Curl_easy *data = td->tsd.data; #endif @@ -407,7 +407,7 @@ static void destroy_async_data(struct Curl_async *async) free(async->tdata); } -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR /* * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL @@ -483,35 +483,6 @@ static bool init_resolve_thread(struct Curl_easy *data, return FALSE; } -/* - * resolver_error() calls failf() with the appropriate message after a resolve - * error - */ - -static CURLcode resolver_error(struct Curl_easy *data) -{ - const char *host_or_proxy; - CURLcode result; - -#ifndef CURL_DISABLE_PROXY - struct connectdata *conn = data->conn; - if(conn->bits.httpproxy) { - host_or_proxy = "proxy"; - result = CURLE_COULDNT_RESOLVE_PROXY; - } - else -#endif - { - host_or_proxy = "host"; - result = CURLE_COULDNT_RESOLVE_HOST; - } - - failf(data, "Could not resolve %s: %s", host_or_proxy, - data->state.async.hostname); - - return result; -} - /* * 'entry' may be NULL and then no data is returned */ @@ -542,7 +513,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, if(!data->state.async.dns && report) /* a name was not resolved, report error */ - result = resolver_error(data); + result = Curl_resolver_error(data); destroy_async_data(&data->state.async); @@ -616,7 +587,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, getaddrinfo_complete(data); if(!data->state.async.dns) { - CURLcode result = resolver_error(data); + CURLcode result = Curl_resolver_error(data); destroy_async_data(&data->state.async); return result; } @@ -654,13 +625,13 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) timediff_t milli; timediff_t ms; struct resdata *reslv = (struct resdata *)data->state.async.resolver; -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR struct thread_data *td = data->state.async.tdata; #else (void)socks; #endif -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR if(td) { /* return read fd to client for polling the DNS resolution status */ socks[0] = td->tsd.sock_pair[0]; @@ -679,7 +650,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) else milli = 200; Curl_expire(data, milli, EXPIRE_ASYNC_NAME); -#ifdef USE_SOCKETPAIR +#ifndef CURL_DISABLE_SOCKETPAIR } #endif @@ -730,24 +701,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, *waitp = 0; /* default to synchronous response */ #ifdef CURLRES_IPV6 - /* - * Check if a limited name resolve has been requested. - */ - switch(data->set.ipver) { - case CURL_IPRESOLVE_V4: - pf = PF_INET; - break; - case CURL_IPRESOLVE_V6: - pf = PF_INET6; - break; - default: + if(Curl_ipv6works(data)) + /* The stack seems to be IPv6-enabled */ pf = PF_UNSPEC; - break; - } - - if((pf != PF_INET) && !Curl_ipv6works(data)) - /* The stack seems to be a non-IPv6 one */ - pf = PF_INET; #endif /* CURLRES_IPV6 */ memset(&hints, 0, sizeof(hints)); diff --git a/lib/bufref.c b/lib/bufref.c new file mode 100644 index 00000000000..b84511e1859 --- /dev/null +++ b/lib/bufref.c @@ -0,0 +1,127 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2021, Daniel Stenberg, , 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. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" +#include "bufref.h" + +#include "curl_memory.h" +#include "memdebug.h" + +#define SIGNATURE 0x5c48e9b2 /* Random pattern. */ + +/* + * Init a bufref struct. + */ +void Curl_bufref_init(struct bufref *br) +{ + DEBUGASSERT(br); + br->dtor = NULL; + br->ptr = NULL; + br->len = 0; + +#ifdef DEBUGBUILD + br->signature = SIGNATURE; +#endif +} + +/* + * Free the buffer and re-init the necessary fields. It doesn't touch the + * 'signature' field and thus this buffer reference can be reused. + */ + +void Curl_bufref_free(struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + if(br->ptr && br->dtor) + br->dtor((void *) br->ptr); + + br->dtor = NULL; + br->ptr = NULL; + br->len = 0; +} + +/* + * Set the buffer reference to new values. The previously referenced buffer + * is released before assignment. + */ +void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, + void (*dtor)(void *)) +{ + DEBUGASSERT(ptr || !len); + DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH); + + Curl_bufref_free(br); + br->ptr = (const unsigned char *) ptr; + br->len = len; + br->dtor = dtor; +} + +/* + * Get a pointer to the referenced buffer. + */ +const unsigned char *Curl_bufref_ptr(const struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + return br->ptr; +} + +/* + * Get the length of the referenced buffer data. + */ +size_t Curl_bufref_len(const struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + return br->len; +} + +CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len) +{ + unsigned char *cpy = NULL; + + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + DEBUGASSERT(ptr || !len); + DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH); + + if(ptr) { + cpy = malloc(len + 1); + if(!cpy) + return CURLE_OUT_OF_MEMORY; + if(len) + memcpy(cpy, ptr, len); + cpy[len] = '\0'; + } + + Curl_bufref_set(br, cpy, len, curl_free); + return CURLE_OK; +} diff --git a/lib/bufref.h b/lib/bufref.h new file mode 100644 index 00000000000..25f65d894dd --- /dev/null +++ b/lib/bufref.h @@ -0,0 +1,46 @@ +#ifndef HEADER_CURL_BUFREF_H +#define HEADER_CURL_BUFREF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2021, Daniel Stenberg, , 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. + * + ***************************************************************************/ + +/* + * Generic buffer reference. + */ +struct bufref { + void (*dtor)(void *); /* Associated destructor. */ + const unsigned char *ptr; /* Referenced data buffer. */ + size_t len; /* The data size in bytes. */ +#ifdef DEBUGBUILD + int signature; /* Detect API use mistakes. */ +#endif +}; + + +void Curl_bufref_init(struct bufref *br); +void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, + void (*dtor)(void *)); +const unsigned char *Curl_bufref_ptr(const struct bufref *br); +size_t Curl_bufref_len(const struct bufref *br); +CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len); +void Curl_bufref_free(struct bufref *br); + +#endif diff --git a/lib/c-hyper.c b/lib/c-hyper.c index 10bd7ef9bf1..81f589eb9e6 100644 --- a/lib/c-hyper.c +++ b/lib/c-hyper.c @@ -51,6 +51,7 @@ #include "transfer.h" #include "multiif.h" #include "progress.h" +#include "content_encoding.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -174,8 +175,14 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) } if(k->ignorebody) return HYPER_ITER_CONTINUE; + if(0 == len) + return HYPER_ITER_CONTINUE; Curl_debug(data, CURLINFO_DATA_IN, buf, len); - result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len); + if(!data->set.http_ce_skip && k->writer_stack) + /* content-encoded data */ + result = Curl_unencode_write(data, k->writer_stack, buf, len); + else + result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len); if(result) { data->state.hresult = result; @@ -198,11 +205,8 @@ static CURLcode status_line(struct Curl_easy *data, const uint8_t *reason, size_t rlen) { CURLcode result; - size_t wrote; size_t len; const char *vstr; - curl_write_callback writeheader = - data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" : (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0"); conn->httpversion = @@ -225,12 +229,12 @@ static CURLcode status_line(struct Curl_easy *data, len = Curl_dyn_len(&data->state.headerb); Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - Curl_set_in_callback(data, true); - wrote = writeheader(Curl_dyn_ptr(&data->state.headerb), 1, len, - data->set.writeheader); - Curl_set_in_callback(data, false); - if(wrote != len) - return CURLE_WRITE_ERROR; + result = Curl_client_write(data, CLIENTWRITE_HEADER, + Curl_dyn_ptr(&data->state.headerb), len); + if(result) { + data->state.hresult = CURLE_ABORTED_BY_CALLBACK; + return HYPER_ITER_BREAK; + } data->info.header_size += (long)len; data->req.headerbytecount += (long)len; @@ -327,7 +331,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, infof(data, "hyperstream is done!\n"); break; } - else if(t != HYPER_TASK_RESPONSE) { + else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) { *didwhat = KEEP_RECV; break; } @@ -464,8 +468,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, else linelen = 2; /* CRLF ending */ linelen += (p - n); - if(!n) - return CURLE_BAD_FUNCTION_ARGUMENT; vlen = p - v; if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen, @@ -741,7 +743,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } - if(data->set.httpversion == CURL_HTTP_VERSION_1_0) { + if(data->state.httpwant == CURL_HTTP_VERSION_1_0) { if(HYPERE_OK != hyper_request_set_version(req, HYPER_HTTP_VERSION_1_0)) { failf(data, "error setting HTTP version"); @@ -807,14 +809,27 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) #endif Curl_safefree(data->state.aptr.ref); - if(data->change.referer && !Curl_checkheaders(data, "Referer")) { - data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(data->state.referer && !Curl_checkheaders(data, "Referer")) { + data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer); if(!data->state.aptr.ref) return CURLE_OUT_OF_MEMORY; if(Curl_hyper_header(data, headers, data->state.aptr.ref)) goto error; } + if(!Curl_checkheaders(data, "Accept-Encoding") && + data->set.str[STRING_ENCODING]) { + Curl_safefree(data->state.aptr.accept_encoding); + data->state.aptr.accept_encoding = + aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); + if(!data->state.aptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; + if(Curl_hyper_header(data, headers, data->state.aptr.accept_encoding)) + goto error; + } + else + Curl_safefree(data->state.aptr.accept_encoding); + result = cookies(data, conn, headers); if(result) return result; diff --git a/lib/conncache.c b/lib/conncache.c index 8dfdc0ac81e..5453c00f33e 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -466,7 +466,6 @@ Curl_conncache_extract_bundle(struct Curl_easy *data, data->state.conn_cache->num_conn--; DEBUGF(infof(data, "The cache now contains %zu members\n", data->state.conn_cache->num_conn)); - conn_candidate->data = data; /* associate! */ } return conn_candidate; @@ -529,7 +528,6 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) connc->num_conn--; DEBUGF(infof(data, "The cache now contains %zu members\n", connc->num_conn)); - conn_candidate->data = data; /* associate! */ } CONNCACHE_UNLOCK(data); diff --git a/lib/connect.c b/lib/connect.c index baab1840e1d..d9317f3783c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -171,65 +171,63 @@ singleipconnect(struct Curl_easy *data, * infinite time left). If the value is negative, the timeout time has already * elapsed. * - * The start time is stored in progress.t_startsingle - as set with - * Curl_pgrsTime(..., TIMER_STARTSINGLE); - * * If 'nowp' is non-NULL, it points to the current time. * 'duringconnect' is FALSE if not during a connect, as then of course the * connect timeout is not taken into account! * * @unittest: 1303 */ + +#define TIMEOUT_CONNECT 1 +#define TIMEOUT_MAXTIME 2 + timediff_t Curl_timeleft(struct Curl_easy *data, struct curltime *nowp, bool duringconnect) { - int timeout_set = 0; - timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + unsigned int timeout_set = 0; + timediff_t connect_timeout_ms = 0; + timediff_t maxtime_timeout_ms = 0; + timediff_t timeout_ms = 0; struct curltime now; - /* if a timeout is set, use the most restrictive one */ - - if(data->set.timeout > 0) - timeout_set |= 1; - if(duringconnect && (data->set.connecttimeout > 0)) - timeout_set |= 2; - - switch(timeout_set) { - case 1: - timeout_ms = data->set.timeout; - break; - case 2: - timeout_ms = data->set.connecttimeout; - break; - case 3: - if(data->set.timeout < data->set.connecttimeout) - timeout_ms = data->set.timeout; - else - timeout_ms = data->set.connecttimeout; - break; - default: - /* use the default */ - if(!duringconnect) - /* if we're not during connect, there's no default timeout so if we're - at zero we better just return zero and not make it a negative number - by the math below */ - return 0; - break; + /* 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 > 0) { + timeout_set = TIMEOUT_MAXTIME; + maxtime_timeout_ms = data->set.timeout; + } + if(duringconnect) { + timeout_set |= TIMEOUT_CONNECT; + connect_timeout_ms = (data->set.connecttimeout > 0) ? + data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT; } + if(!timeout_set) + /* no timeout */ + return 0; if(!nowp) { now = Curl_now(); nowp = &now; } - /* subtract elapsed time */ - if(duringconnect) - /* since this most recent connect started */ - timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle); - else - /* since the entire operation started */ - timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop); + if(timeout_set & TIMEOUT_MAXTIME) { + maxtime_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop); + timeout_ms = maxtime_timeout_ms; + } + + if(timeout_set & TIMEOUT_CONNECT) { + connect_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle); + + if(!(timeout_set & TIMEOUT_MAXTIME) || + (connect_timeout_ms < maxtime_timeout_ms)) + timeout_ms = connect_timeout_ms; + } + if(!timeout_ms) /* avoid returning 0 as that means no timeout! */ return -1; @@ -611,7 +609,7 @@ static CURLcode trynextip(struct Curl_easy *data, /* Copies connection info into the transfer handle to make it available when the transfer handle is no longer associated with the connection. */ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, - char *local_ip, long local_port) + char *local_ip, int local_port) { memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); if(local_ip && local_ip[0]) @@ -627,7 +625,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, /* retrieves ip address and port from a sockaddr structure. note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, long *port) + char *addr, int *port) { struct sockaddr_in *si = NULL; #ifdef ENABLE_IPV6 @@ -662,7 +660,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, #endif #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) case AF_UNIX: - if(salen > (curl_socklen_t)sizeof(sa_family_t)) { + if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) { su = (struct sockaddr_un*)sa; msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); } @@ -690,7 +688,7 @@ void Curl_conninfo_remote(struct Curl_easy *data, char buffer[STRERROR_LEN]; struct Curl_sockaddr_storage ssrem; curl_socklen_t plen; - long port; + int port; plen = sizeof(struct Curl_sockaddr_storage); memset(&ssrem, 0, sizeof(ssrem)); if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) { @@ -715,7 +713,7 @@ void Curl_conninfo_remote(struct Curl_easy *data, /* retrieves the start/end point information of a socket of an established connection */ void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd, - char *local_ip, long *local_port) + char *local_ip, int *local_port) { #ifdef HAVE_GETSOCKNAME char buffer[STRERROR_LEN]; @@ -752,7 +750,7 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn, ip address and port number whenever an outgoing connection is **established** from the primary socket to a remote address. */ char local_ip[MAX_IPADR_LEN] = ""; - long local_port = -1; + int local_port = -1; if(conn->transport == TRNSPRT_TCP) { if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { @@ -908,8 +906,10 @@ CURLcode Curl_is_connected(struct Curl_easy *data, connkeep(conn, "HTTP/3 default"); return CURLE_OK; } - if(result) + if(result) { + conn->tempsock[i] = CURL_SOCKET_BAD; error = SOCKERRNO; + } } else #endif @@ -1158,7 +1158,7 @@ static CURLcode singleipconnect(struct Curl_easy *data, curl_socket_t sockfd; CURLcode result; char ipaddress[MAX_IPADR_LEN]; - long port; + int port; bool is_tcp; #ifdef TCP_FASTOPEN_CONNECT int optval = 1; @@ -1180,7 +1180,7 @@ static CURLcode singleipconnect(struct Curl_easy *data, Curl_closesocket(data, conn, sockfd); return CURLE_OK; } - infof(data, " Trying %s:%ld...\n", ipaddress, port); + infof(data, " Trying %s:%d...\n", ipaddress, port); #ifdef ENABLE_IPV6 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && @@ -1367,14 +1367,31 @@ CURLcode Curl_connecthost(struct Curl_easy *data, conn->timeoutms_per_addr[1] = conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2; - conn->tempfamily[0] = conn->tempaddr[0]? - conn->tempaddr[0]->ai_family:0; + if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) { + /* any IP version is allowed */ + conn->tempfamily[0] = conn->tempaddr[0]? + conn->tempaddr[0]->ai_family:0; +#ifdef ENABLE_IPV6 + conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ? + AF_INET : AF_INET6; +#else + conn->tempfamily[1] = AF_UNSPEC; +#endif + } + else { + /* only one IP version is allowed */ + conn->tempfamily[0] = (conn->ip_version == CURL_IPRESOLVE_V4) ? + AF_INET : #ifdef ENABLE_IPV6 - conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ? - AF_INET : AF_INET6; + AF_INET6; #else - conn->tempfamily[1] = AF_UNSPEC; + AF_UNSPEC; #endif + conn->tempfamily[1] = AF_UNSPEC; + + ainext(conn, 0, FALSE); /* find first address of the right type */ + } + ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */ DEBUGF(infof(data, "family0 == %s, family1 == %s\n", @@ -1448,11 +1465,9 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, } c = find.found; - if(connp) { + if(connp) /* only store this if the caller cares for it */ *connp = c; - c->data = data; - } return c->sock[FIRSTSOCKET]; } return CURL_SOCKET_BAD; diff --git a/lib/connect.h b/lib/connect.h index 566b3531d76..1a055f58de2 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -54,7 +54,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, struct connectdata **connp); bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, long *port); + char *addr, int *port); /* * Check if a connection seems to be alive. @@ -81,9 +81,9 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn, void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn, curl_socket_t sockfd); void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd, - char *local_ip, long *local_port); + char *local_ip, int *local_port); void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, - char *local_ip, long local_port); + char *local_ip, int local_port); int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn, curl_socket_t sock); diff --git a/lib/content_encoding.c b/lib/content_encoding.c index f179b81796f..a84ff543b92 100644 --- a/lib/content_encoding.c +++ b/lib/content_encoding.c @@ -178,7 +178,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, /* Dynamically allocate a buffer for decompression because it's uncommonly large to hold on the stack */ decomp = malloc(DSIZ); - if(decomp == NULL) + if(!decomp) return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); /* because the buffer size is fixed, iteratively decompress and transfer to @@ -487,7 +487,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, */ z->avail_in = (uInt) nbytes; z->next_in = malloc(z->avail_in); - if(z->next_in == NULL) { + if(!z->next_in) { return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } memcpy(z->next_in, buf, z->avail_in); @@ -509,7 +509,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data, ssize_t hlen; z->avail_in += (uInt) nbytes; z->next_in = Curl_saferealloc(z->next_in, z->avail_in); - if(z->next_in == NULL) { + if(!z->next_in) { return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ @@ -985,7 +985,8 @@ new_unencoding_writer(struct Curl_easy *data, return writer; } -/* Write data using an unencoding writer stack. */ +/* Write data using an unencoding writer stack. "nbytes" is not + allowed to be 0. */ CURLcode Curl_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes) diff --git a/lib/cookie.c b/lib/cookie.c index 09fd092ac3d..941623f9d28 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -105,6 +105,8 @@ Example set of cookies: #include "curl_memory.h" #include "memdebug.h" +static void strstore(char **str, const char *newstr); + static void freecookie(struct Cookie *co) { free(co->expirestr); @@ -129,12 +131,13 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len)) return FALSE; - /* A lead char of cookie_domain is not '.'. - RFC6265 4.1.2.3. The Domain Attribute says: - For example, if the value of the Domain attribute is - "example.com", the user agent will include the cookie in the Cookie - header when making HTTP requests to example.com, www.example.com, and - www.corp.example.com. + /* + * A lead char of cookie_domain is not '.'. + * RFC6265 4.1.2.3. The Domain Attribute says: + * For example, if the value of the Domain attribute is + * "example.com", the user agent will include the cookie in the Cookie + * header when making HTTP requests to example.com, www.example.com, and + * www.corp.example.com. */ if(hostname_len == cookie_domain_len) return TRUE; @@ -144,7 +147,10 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) } /* - * Return true if the given string is an IP(v4|v6) address. + * isip + * + * Returns true if the given string is an IPv4 or IPv6 address (if IPv6 has + * been enabled while building libcurl, and false otherwise. */ static bool isip(const char *domain) { @@ -193,19 +199,19 @@ static bool pathmatch(const char *cookie_path, const char *request_uri) /* #-fragments are already cut off! */ if(0 == strlen(uri_path) || uri_path[0] != '/') { - free(uri_path); - uri_path = strdup("/"); + strstore(&uri_path, "/"); if(!uri_path) return FALSE; } - /* here, RFC6265 5.1.4 says - 4. Output the characters of the uri-path from the first character up - to, but not including, the right-most %x2F ("/"). - but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site - without redirect. - Ignore this algorithm because /hoge is uri path for this case - (uri path is not /). + /* + * here, RFC6265 5.1.4 says + * 4. Output the characters of the uri-path from the first character up + * to, but not including, the right-most %x2F ("/"). + * but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site + * without redirect. + * Ignore this algorithm because /hoge is uri path for this case + * (uri path is not /). */ uri_path_len = strlen(uri_path); @@ -328,8 +334,7 @@ static char *sanitize_cookie_path(const char *cookie_path) /* RFC6265 5.2.4 The Path Attribute */ if(new_path[0] != '/') { /* Let cookie-path be the default-path. */ - free(new_path); - new_path = strdup("/"); + strstore(&new_path, "/"); return new_path; } @@ -348,7 +353,7 @@ static char *sanitize_cookie_path(const char *cookie_path) */ void Curl_cookie_loadfiles(struct Curl_easy *data) { - struct curl_slist *list = data->change.cookielist; + struct curl_slist *list = data->state.cookielist; if(list) { Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); while(list) { @@ -357,7 +362,8 @@ void Curl_cookie_loadfiles(struct Curl_easy *data) data->cookies, data->set.cookiesession); if(!newcookies) - /* Failure may be due to OOM or a bad cookie; both are ignored + /* + * Failure may be due to OOM or a bad cookie; both are ignored * but only the first should be */ infof(data, "ignoring failed cookie_init for %s\n", list->data); @@ -365,17 +371,20 @@ void Curl_cookie_loadfiles(struct Curl_easy *data) data->cookies = newcookies; list = list->next; } - curl_slist_free_all(data->change.cookielist); /* clean up list */ - data->change.cookielist = NULL; /* don't do this again! */ + curl_slist_free_all(data->state.cookielist); /* clean up list */ + data->state.cookielist = NULL; /* don't do this again! */ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } } /* - * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL - * that will be freed before the allocated string is stored there. + * strstore * - * It is meant to easily replace strdup() + * A thin wrapper around strdup which ensures that any memory allocated at + * *str will be freed before the string allocated by strdup is stored there. + * The intended usecase is repeated assignments to the same variable during + * parsing in a last-wins scenario. The caller is responsible for checking + * for OOM errors. */ static void strstore(char **str, const char *newstr) { @@ -384,7 +393,11 @@ static void strstore(char **str, const char *newstr) } /* - * remove_expired() removes expired cookies. + * remove_expired + * + * Remove expired cookies from the hash by inspecting the expires timestamp on + * each cookie in the hash, freeing and deleting any where the timestamp is in + * the past. */ static void remove_expired(struct CookieInfo *cookies) { @@ -421,25 +434,23 @@ static bool bad_domain(const char *domain) return !strchr(domain, '.') && !strcasecompare(domain, "localhost"); } -/**************************************************************************** - * - * Curl_cookie_add() - * - * Add a single cookie line to the cookie keeping object. +/* + * Curl_cookie_add * - * Be aware that sometimes we get an IP-only host name, and that might also be - * a numerical IPv6 address. + * Add a single cookie line to the cookie keeping object. Be aware that + * sometimes we get an IP-only host name, and that might also be a numerical + * IPv6 address. * * Returns NULL on out of memory or invalid cookie. This is suboptimal, * as they should be treated separately. - ***************************************************************************/ - + */ struct Cookie * Curl_cookie_add(struct Curl_easy *data, - /* The 'data' pointer here may be NULL at times, and thus - must only be used very carefully for things that can deal - with data being NULL. Such as infof() and similar */ - + /* + * The 'data' pointer here may be NULL at times, and thus + * must only be used very carefully for things that can deal + * with data being NULL. Such as infof() and similar + */ struct CookieInfo *c, bool httpheader, /* TRUE if HTTP header-style line */ bool noexpire, /* if TRUE, skip remove_expired() */ @@ -493,9 +504,11 @@ Curl_cookie_add(struct Curl_easy *data, if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%" MAX_NAME_TXT "[^;\r\n]", name, what)) { - /* Use strstore() below to properly deal with received cookie - headers that have the same string property set more than once, - and then we use the last one. */ + /* + * Use strstore() below to properly deal with received cookie + * headers that have the same string property set more than once, + * and then we use the last one. + */ const char *whatptr; bool done = FALSE; bool sep; @@ -503,11 +516,13 @@ Curl_cookie_add(struct Curl_easy *data, size_t nlen = strlen(name); const char *endofn = &ptr[ nlen ]; + /* + * Check for too long individual name or contents, or too long + * combination of name + contents. Chrome and Firefox support 4095 or + * 4096 bytes combo + */ if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) || ((nlen + len) > MAX_NAME)) { - /* too long individual name or contents, or too long combination of - name + contents. Chrome and Firefox support 4095 or 4096 bytes - combo. */ freecookie(co); infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n", nlen, len); @@ -569,8 +584,10 @@ Curl_cookie_add(struct Curl_easy *data, } } else if(!len) { - /* this was a "=" with no content, and we must allow - 'secure' and 'httponly' specified this weirdly */ + /* + * this was a "=" with no content, and we must allow + * 'secure' and 'httponly' specified this weirdly + */ done = TRUE; /* * secure cookies are only allowed to be set when the connection is @@ -610,8 +627,10 @@ Curl_cookie_add(struct Curl_easy *data, else if(strcasecompare("domain", name)) { bool is_ip; - /* Now, we make sure that our host is within the given domain, - or the given domain is not valid and thus cannot be set. */ + /* + * Now, we make sure that our host is within the given domain, or + * the given domain is not valid and thus cannot be set. + */ if('.' == whatptr[0]) whatptr++; /* ignore preceding dot */ @@ -641,9 +660,10 @@ Curl_cookie_add(struct Curl_easy *data, given */ } else { - /* we did not get a tailmatch and then the attempted set domain - is not a domain to which the current host belongs. Mark as - bad. */ + /* + * We did not get a tailmatch and then the attempted set domain is + * not a domain to which the current host belongs. Mark as bad. + */ badcookie = TRUE; infof(data, "skipped cookie with bad tailmatch domain: %s\n", whatptr); @@ -657,15 +677,15 @@ Curl_cookie_add(struct Curl_easy *data, } } else if(strcasecompare("max-age", name)) { - /* Defined in RFC2109: - - Optional. The Max-Age attribute defines the lifetime of the - cookie, in seconds. The delta-seconds value is a decimal non- - negative integer. After delta-seconds seconds elapse, the - client should discard the cookie. A value of zero means the - cookie should be discarded immediately. - - */ + /* + * Defined in RFC2109: + * + * Optional. The Max-Age attribute defines the lifetime of the + * cookie, in seconds. The delta-seconds value is a decimal non- + * negative integer. After delta-seconds seconds elapse, the + * client should discard the cookie. A value of zero means the + * cookie should be discarded immediately. + */ strstore(&co->maxage, whatptr); if(!co->maxage) { badcookie = TRUE; @@ -679,9 +699,10 @@ Curl_cookie_add(struct Curl_easy *data, break; } } + /* - else this is the second (or more) name we don't know - about! */ + * Else, this is the second (or more) name we don't know about! + */ } else { /* this is an "illegal" = pair */ @@ -699,8 +720,10 @@ Curl_cookie_add(struct Curl_easy *data, semiptr = strchr(ptr, ';'); /* now, find the next semicolon */ if(!semiptr && *ptr) - /* There are no more semicolons, but there's a final name=value pair - coming up */ + /* + * There are no more semicolons, but there's a final name=value pair + * coming up + */ semiptr = strchr(ptr, '\0'); } while(semiptr); @@ -724,13 +747,16 @@ Curl_cookie_add(struct Curl_easy *data, } } else if(co->expirestr) { - /* Note that if the date couldn't get parsed for whatever reason, - the cookie will be treated as a session cookie */ + /* + * Note that if the date couldn't get parsed for whatever reason, the + * cookie will be treated as a session cookie + */ co->expires = Curl_getdate_capped(co->expirestr); - /* Session cookies have expires set to 0 so if we get that back - from the date parser let's add a second to make it a - non-session cookie */ + /* + * Session cookies have expires set to 0 so if we get that back from the + * date parser let's add a second to make it a non-session cookie + */ if(co->expires == 0) co->expires = 1; else if(co->expires < 0) @@ -747,13 +773,17 @@ Curl_cookie_add(struct Curl_easy *data, } if(!badcookie && !co->path && path) { - /* No path was given in the header line, set the default. - Note that the passed-in path to this function MAY have a '?' and - following part that MUST not be stored as part of the path. */ + /* + * No path was given in the header line, set the default. Note that the + * passed-in path to this function MAY have a '?' and following part that + * MUST NOT be stored as part of the path. + */ char *queryp = strchr(path, '?'); - /* queryp is where the interesting part of the path ends, so now we - want to the find the last */ + /* + * queryp is where the interesting part of the path ends, so now we + * want to the find the last + */ char *endslash; if(!queryp) endslash = strrchr(path, '/'); @@ -774,29 +804,34 @@ Curl_cookie_add(struct Curl_easy *data, } } + /* + * If we didn't get a cookie name, or a bad one, the this is an illegal + * line so bail out. + */ if(badcookie || !co->name) { - /* we didn't get a cookie name or a bad one, - this is an illegal line, bail out */ freecookie(co); return NULL; } } else { - /* This line is NOT a HTTP header style line, we do offer support for - reading the odd netscape cookies-file format here */ + /* + * This line is NOT a HTTP header style line, we do offer support for + * reading the odd netscape cookies-file format here + */ char *ptr; char *firstptr; char *tok_buf = NULL; int fields; - /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies - marked with httpOnly after the domain name are not accessible - from javascripts, but since curl does not operate at javascript - level, we include them anyway. In Firefox's cookie files, these - lines are preceded with #HttpOnly_ and then everything is - as usual, so we skip 10 characters of the line.. - */ + /* + * IE introduced HTTP-only cookies to prevent XSS attacks. Cookies marked + * with httpOnly after the domain name are not accessible from javascripts, + * but since curl does not operate at javascript level, we include them + * anyway. In Firefox's cookie files, these lines are preceded with + * #HttpOnly_ and then everything is as usual, so we skip 10 characters of + * the line.. + */ if(strncmp(lineptr, "#HttpOnly_", 10) == 0) { lineptr += 10; co->httponly = TRUE; @@ -817,8 +852,10 @@ Curl_cookie_add(struct Curl_easy *data, firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ - /* Now loop through the fields and init the struct we already have - allocated */ + /* + * Now loop through the fields and init the struct we already have + * allocated + */ for(ptr = firstptr, fields = 0; ptr && !badcookie; ptr = strtok_r(NULL, "\t", &tok_buf), fields++) { switch(fields) { @@ -830,10 +867,11 @@ Curl_cookie_add(struct Curl_easy *data, badcookie = TRUE; break; case 1: - /* flag: A TRUE/FALSE value indicating if all machines within a given - domain can access the variable. Set TRUE when the cookie says - .domain.com and to false when the domain is complete www.domain.com - */ + /* + * flag: A TRUE/FALSE value indicating if all machines within a given + * domain can access the variable. Set TRUE when the cookie says + * .domain.com and to false when the domain is complete www.domain.com + */ co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE; break; case 2: @@ -942,17 +980,23 @@ Curl_cookie_add(struct Curl_easy *data, co->livecookie = c->running; co->creationtime = ++c->lastct; - /* now, we have parsed the incoming line, we must now check if this - supersedes an already existing cookie, which it may if the previous have - the same domain and path as this */ + /* + * Now we have parsed the incoming line, we must now check if this supersedes + * an already existing cookie, which it may if the previous have the same + * domain and path as this. + */ /* at first, remove expired cookies */ if(!noexpire) remove_expired(c); #ifdef USE_LIBPSL - /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ - if(domain && co->domain && !isip(co->domain)) { + /* + * Check if the domain is a Public Suffix and if yes, ignore the cookie. We + * must also check that the data handle isn't NULL since the psl code will + * dereference it. + */ + if(data && (domain && co->domain && !isip(co->domain))) { const psl_ctx_t *psl = Curl_psl_use(data); int acceptable; @@ -1028,12 +1072,12 @@ Curl_cookie_add(struct Curl_easy *data, } if(replace_old && !co->livecookie && clist->livecookie) { - /* Both cookies matched fine, except that the already present - cookie is "live", which means it was set from a header, while - the new one isn't "live" and thus only read from a file. We let - live cookies stay alive */ - - /* Free the newcomer and get out of here! */ + /* + * Both cookies matched fine, except that the already present cookie is + * "live", which means it was set from a header, while the new one was + * read from a file and thus isn't "live". "live" cookies are preferred + * so the new cookie is freed. + */ freecookie(co); return NULL; } @@ -1059,8 +1103,10 @@ Curl_cookie_add(struct Curl_easy *data, free(co); /* free the newly allocated memory */ co = clist; /* point to the previous struct instead */ - /* We have replaced a cookie, now skip the rest of the list but - make sure the 'lastc' pointer is properly set */ + /* + * We have replaced a cookie, now skip the rest of the list but make + * sure the 'lastc' pointer is properly set + */ do { lastc = clist; clist = clist->next; @@ -1092,19 +1138,19 @@ Curl_cookie_add(struct Curl_easy *data, } -/***************************************************************************** - * +/* * Curl_cookie_init() * * Inits a cookie struct to read data from a local file. This is always - * called before any cookies are set. File may be NULL. + * called before any cookies are set. File may be NULL in which case only the + * struct is initialized. Is file is "-" then STDIN is read. * * If 'newsession' is TRUE, discard all "session cookies" on read from file. * * Note that 'data' might be called as NULL pointer. * * Returns NULL on out of memory. Invalid cookies are ignored. - ****************************************************************************/ + */ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, const char *file, struct CookieInfo *inc, @@ -1166,7 +1212,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE); } free(line); /* free the line buffer */ - remove_expired(c); /* run this once, not on every cookie */ + + /* + * Remove expired cookies from the hash. We must make sure to run this + * after reading the file, and not not on every cookie. + */ + remove_expired(c); if(fromfile) fclose(fp); @@ -1180,16 +1231,24 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, fail: free(line); + /* + * Only clean up if we allocated it here, as the original could still be in + * use by a share handle. + */ if(!inc) - /* Only clean up if we allocated it here, as the original could still be in - * use by a share handle */ Curl_cookie_cleanup(c); if(fromfile && fp) fclose(fp); return NULL; /* out of memory */ } -/* sort this so that the longest path gets before the shorter path */ +/* + * cookie_sort + * + * Helper function to sort cookies such that the longest path gets before the + * shorter path. Path, domain and name lengths are considered in that order, + * with tge creationtime as the tiebreaker. + */ static int cookie_sort(const void *p1, const void *p2) { struct Cookie *c1 = *(struct Cookie **)p1; @@ -1221,7 +1280,11 @@ static int cookie_sort(const void *p1, const void *p2) return (c2->creationtime > c1->creationtime) ? 1 : -1; } -/* sort cookies only according to creation time */ +/* + * cookie_sort_ct + * + * Helper function to sort cookies according to creation time. + */ static int cookie_sort_ct(const void *p1, const void *p2) { struct Cookie *c1 = *(struct Cookie **)p1; @@ -1265,18 +1328,15 @@ static struct Cookie *dup_cookie(struct Cookie *src) return NULL; } -/***************************************************************************** - * - * Curl_cookie_getlist() +/* + * Curl_cookie_getlist * - * For a given host and path, return a linked list of cookies that the - * client should send to the server if used now. The secure boolean informs - * the cookie if a secure connection is achieved or not. + * For a given host and path, return a linked list of cookies that the client + * should send to the server if used now. The secure boolean informs the cookie + * if a secure connection is achieved or not. * * It shall only return cookies that haven't expired. - * - ****************************************************************************/ - + */ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host, const char *path, bool secure) @@ -1307,15 +1367,21 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, if(!co->domain || (co->tailmatch && !is_ip && tailmatch(co->domain, host)) || ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) { - /* the right part of the host matches the domain stuff in the - cookie data */ + /* + * the right part of the host matches the domain stuff in the + * cookie data + */ - /* now check the left part of the path with the cookies path - requirement */ + /* + * now check the left part of the path with the cookies path + * requirement + */ if(!co->spath || pathmatch(co->spath, path) ) { - /* and now, we know this is a match and we should create an - entry for the return-linked-list */ + /* + * and now, we know this is a match and we should create an + * entry for the return-linked-list + */ newco = dup_cookie(co); if(newco) { @@ -1336,9 +1402,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, } 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. */ + /* + * 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. + */ struct Cookie **array; size_t i; @@ -1373,13 +1441,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, return NULL; } -/***************************************************************************** - * - * Curl_cookie_clearall() +/* + * Curl_cookie_clearall * * Clear all existing cookies and reset the counter. - * - ****************************************************************************/ + */ void Curl_cookie_clearall(struct CookieInfo *cookies) { if(cookies) { @@ -1392,14 +1458,11 @@ void Curl_cookie_clearall(struct CookieInfo *cookies) } } -/***************************************************************************** - * - * Curl_cookie_freelist() +/* + * Curl_cookie_freelist * * Free a list of cookies previously returned by Curl_cookie_getlist(); - * - ****************************************************************************/ - + */ void Curl_cookie_freelist(struct Cookie *co) { struct Cookie *next; @@ -1410,14 +1473,11 @@ void Curl_cookie_freelist(struct Cookie *co) } } - -/***************************************************************************** - * - * Curl_cookie_clearsess() +/* + * Curl_cookie_clearsess * * Free all session cookies in the cookies list. - * - ****************************************************************************/ + */ void Curl_cookie_clearsess(struct CookieInfo *cookies) { struct Cookie *first, *curr, *next, *prev = NULL; @@ -1454,14 +1514,11 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies) } } - -/***************************************************************************** - * +/* * Curl_cookie_cleanup() * * Free a "cookie object" previous created with Curl_cookie_init(). - * - ****************************************************************************/ + */ void Curl_cookie_cleanup(struct CookieInfo *c) { if(c) { @@ -1473,12 +1530,13 @@ void Curl_cookie_cleanup(struct CookieInfo *c) } } -/* get_netscape_format() +/* + * get_netscape_format() * * Formats a string for Netscape output file, w/o a newline at the end. - * - * Function returns a char * to a formatted line. Has to be free()d -*/ + * Function returns a char * to a formatted line. The caller is responsible + * for freeing the returned pointer. + */ static char *get_netscape_format(const struct Cookie *co) { return aprintf( @@ -1491,8 +1549,10 @@ static char *get_netscape_format(const struct Cookie *co) "%s\t" /* name */ "%s", /* value */ co->httponly?"#HttpOnly_":"", - /* Make sure all domains are prefixed with a dot if they allow - tailmatching. This is Mozilla-style. */ + /* + * Make sure all domains are prefixed with a dot if they allow + * tailmatching. This is Mozilla-style. + */ (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", co->domain?co->domain:"unknown", co->tailmatch?"TRUE":"FALSE", @@ -1511,18 +1571,18 @@ static char *get_netscape_format(const struct Cookie *co) * * The function returns non-zero on write failure. */ -static int cookie_output(struct Curl_easy *data, - struct CookieInfo *c, const char *filename) +static CURLcode cookie_output(struct Curl_easy *data, + struct CookieInfo *c, const char *filename) { struct Cookie *co; FILE *out = NULL; bool use_stdout = FALSE; char *tempstore = NULL; - bool error = false; + CURLcode error = CURLE_OK; if(!c) /* no cookie engine alive */ - return 0; + return CURLE_OK; /* at first, remove expired cookies */ remove_expired(c); @@ -1540,11 +1600,13 @@ static int cookie_output(struct Curl_easy *data, tempstore = aprintf("%s.%s.tmp", filename, randsuffix); if(!tempstore) - return 1; + return CURLE_OUT_OF_MEMORY; out = fopen(tempstore, FOPEN_WRITETEXT); - if(!out) + if(!out) { + error = CURLE_WRITE_ERROR; goto error; + } } fputs("# Netscape HTTP Cookie File\n" @@ -1559,6 +1621,7 @@ static int cookie_output(struct Curl_easy *data, array = calloc(1, sizeof(struct Cookie *) * c->numcookies); if(!array) { + error = CURLE_OUT_OF_MEMORY; goto error; } @@ -1575,9 +1638,9 @@ static int cookie_output(struct Curl_easy *data, for(i = 0; i < nvalid; i++) { char *format_ptr = get_netscape_format(array[i]); - if(format_ptr == NULL) { - fprintf(out, "#\n# Fatal libcurl error\n"); + if(!format_ptr) { free(array); + error = CURLE_OUT_OF_MEMORY; goto error; } fprintf(out, "%s\n", format_ptr); @@ -1592,18 +1655,24 @@ static int cookie_output(struct Curl_easy *data, out = NULL; if(Curl_rename(tempstore, filename)) { unlink(tempstore); + error = CURLE_WRITE_ERROR; goto error; } } - goto cleanup; + /* + * If we reach here we have successfully written a cookie file so theree is + * no need to inspect the error, any error case should have jumped into the + * error block below. + */ + free(tempstore); + return CURLE_OK; + error: - error = true; -cleanup: if(out && !use_stdout) fclose(out); free(tempstore); - return error ? 1 : 0; + return error; } static struct curl_slist *cookie_list(struct Curl_easy *data) @@ -1614,8 +1683,7 @@ static struct curl_slist *cookie_list(struct Curl_easy *data) char *line; unsigned int i; - if((data->cookies == NULL) || - (data->cookies->numcookies == 0)) + if(!data->cookies || (data->cookies->numcookies == 0)) return NULL; for(i = 0; i < COOKIE_HASH_SIZE; i++) { @@ -1651,8 +1719,10 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data) void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) { + CURLcode res; + if(data->set.str[STRING_COOKIEJAR]) { - if(data->change.cookielist) { + if(data->state.cookielist) { /* If there is a list of cookie files to read, do it first so that we have all the told files read before we write the new jar. Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */ @@ -1662,16 +1732,17 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); /* if we have a destination file for all the cookies to get dumped to */ - if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR])) - infof(data, "WARNING: failed to save cookies in %s\n", - data->set.str[STRING_COOKIEJAR]); + res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]); + if(res) + infof(data, "WARNING: failed to save cookies in %s: %s\n", + data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res)); } else { - if(cleanup && data->change.cookielist) { + if(cleanup && data->state.cookielist) { /* since nothing is written, we can just free the list of cookie file names */ - curl_slist_free_all(data->change.cookielist); /* clean up list */ - data->change.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); /* clean up list */ + data->state.cookielist = NULL; } Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); } diff --git a/lib/cookie.h b/lib/cookie.h index e0aa383becb..460bbb10405 100644 --- a/lib/cookie.h +++ b/lib/cookie.h @@ -91,13 +91,13 @@ struct Curl_easy; */ struct Cookie *Curl_cookie_add(struct Curl_easy *data, - struct CookieInfo *, bool header, bool noexpiry, - char *lineptr, + struct CookieInfo *c, bool header, + bool noexpiry, char *lineptr, const char *domain, const char *path, bool secure); -struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, - const char *, bool); +struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host, + const char *path, bool secure); void Curl_cookie_freelist(struct Cookie *cookies); void Curl_cookie_clearall(struct CookieInfo *cookies); void Curl_cookie_clearsess(struct CookieInfo *cookies); @@ -110,9 +110,10 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies); #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 *); +void Curl_cookie_cleanup(struct CookieInfo *c); struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, - const char *, struct CookieInfo *, bool); + const char *file, struct CookieInfo *inc, + bool newsession); struct curl_slist *Curl_cookie_list(struct Curl_easy *data); void Curl_cookie_loadfiles(struct Curl_easy *data); #endif diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index 06537b275fd..1d5067bc00c 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -50,6 +50,12 @@ # define in_addr_t unsigned long #endif +#if defined(USE_UNIX_SOCKETS) && defined(WINAPI_FAMILY) && \ + (WINAPI_FAMILY == WINAPI_FAMILY_APP) + /* Required for sockaddr_un type */ +# include +#endif + #include #include "curl_addrinfo.h" @@ -141,7 +147,7 @@ Curl_getaddrinfo_ex(const char *nodename, continue; /* ignore elements without required address info */ - if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) + if(!ai->ai_addr || !(ai->ai_addrlen > 0)) continue; /* ignore elements with bogus address size */ diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index 4c61a02c6e3..96a19afc51e 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -98,7 +98,7 @@ #endif /* Allow SMB to work on Windows */ -#cmakedefine USE_WIN32_CRYPTO +#cmakedefine USE_WIN32_CRYPTO 1 /* Use Windows LDAP implementation */ #cmakedefine USE_WIN32_LDAP 1 @@ -112,21 +112,6 @@ /* Define if you want to enable IPv6 support */ #cmakedefine ENABLE_IPV6 1 -/* Define to the type qualifier of arg 1 for getnameinfo. */ -#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1} - -/* Define to the type of arg 1 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1} - -/* Define to the type of arg 2 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2} - -/* Define to the type of args 4 and 6 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46} - -/* Define to the type of arg 7 for getnameinfo. */ -#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7} - /* Specifies the number of arguments to getservbyport_r */ #cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS} @@ -208,6 +193,9 @@ /* Define to 1 if you have the `geteuid' function. */ #cmakedefine HAVE_GETEUID 1 +/* Define to 1 if you have the `getppid' function. */ +#cmakedefine HAVE_GETPPID 1 + /* Define to 1 if you have the gethostbyaddr function. */ #cmakedefine HAVE_GETHOSTBYADDR 1 @@ -244,9 +232,6 @@ /* Define to 1 if you have a working getifaddrs function. */ #cmakedefine HAVE_GETIFADDRS 1 -/* Define to 1 if you have the getnameinfo function. */ -#cmakedefine HAVE_GETNAMEINFO 1 - /* Define to 1 if you have the `getpass_r' function. */ #cmakedefine HAVE_GETPASS_R 1 @@ -322,21 +307,18 @@ /* Define to 1 if you have the `inet_addr' function. */ #cmakedefine HAVE_INET_ADDR 1 -/* Define to 1 if you have the inet_ntoa_r function. */ -#cmakedefine HAVE_INET_NTOA_R 1 - -/* inet_ntoa_r() takes 2 args */ -#cmakedefine HAVE_INET_NTOA_R_2 1 - -/* inet_ntoa_r() takes 3 args */ -#cmakedefine HAVE_INET_NTOA_R_3 1 - /* Define to 1 if you have a IPv6 capable working inet_ntop function. */ #cmakedefine HAVE_INET_NTOP 1 /* Define to 1 if you have a IPv6 capable working inet_pton function. */ #cmakedefine HAVE_INET_PTON 1 +/* Define to 1 if symbol `sa_family_t' exists */ +#cmakedefine HAVE_SA_FAMILY_T 1 + +/* Define to 1 if symbol `ADDRESS_FAMILY' exists */ +#cmakedefine HAVE_ADDRESS_FAMILY 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H 1 @@ -509,9 +491,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PEM_H 1 -/* Define to 1 if you have the `perror' function. */ -#cmakedefine HAVE_PERROR 1 - /* Define to 1 if you have the `pipe' function. */ #cmakedefine HAVE_PIPE 1 @@ -653,15 +632,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRING_H 1 -/* Define to 1 if you have the strlcat function. */ -#cmakedefine HAVE_STRLCAT 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#cmakedefine HAVE_STRLCPY 1 - -/* Define to 1 if you have the strncasecmp function. */ -#cmakedefine HAVE_STRNCASECMP 1 - /* Define to 1 if you have the strncmpi function. */ #cmakedefine HAVE_STRNCMPI 1 @@ -752,6 +722,9 @@ /* Define to 1 if you have the `utime' function. */ #cmakedefine HAVE_UTIME 1 +/* Define to 1 if you have the `utimes' function. */ +#cmakedefine HAVE_UTIMES 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTIME_H 1 @@ -879,9 +852,6 @@ /* Define to the function return type for recv. */ #cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV} -/* Define as the return type of signal handlers (`int' or `void'). */ -#cmakedefine RETSIGTYPE ${RETSIGTYPE} - /* Define to the type qualifier of arg 5 for select. */ #cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5} @@ -963,9 +933,6 @@ ${SIZEOF_TIME_T_CODE} /* Define if you want to enable WIN32 threaded DNS lookup */ #cmakedefine USE_THREADS_WIN32 1 -/* Define to disable non-blocking sockets. */ -#cmakedefine USE_BLOCKING_SOCKETS 1 - /* if GnuTLS is enabled */ #cmakedefine USE_GNUTLS 1 @@ -1079,3 +1046,9 @@ ${SIZEOF_TIME_T_CODE} /* Define to 1 if you have the mach_absolute_time function. */ #cmakedefine HAVE_MACH_ABSOLUTE_TIME 1 + +/* to enable Windows IDN */ +#cmakedefine USE_WIN32_IDN 1 + +/* to make the compiler know the prototypes of Windows IDN APIs */ +#cmakedefine WANT_IDN_PROTOTYPES 1 diff --git a/lib/curl_endian.c b/lib/curl_endian.c index 2fc25bc1733..b6f107e10a4 100644 --- a/lib/curl_endian.c +++ b/lib/curl_endian.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,7 +81,7 @@ unsigned short Curl_read16_be(const unsigned char *buf) ((unsigned short)buf[1])); } -#if (CURL_SIZEOF_CURL_OFF_T > 4) +#if (SIZEOF_CURL_OFF_T > 4) /* * write32_le() * @@ -121,4 +121,4 @@ void Curl_write64_le(const __int64 value, unsigned char *buffer) write32_le((int)value, buffer); write32_le((int)(value >> 32), buffer + 4); } -#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ +#endif /* SIZEOF_CURL_OFF_T > 4 */ diff --git a/lib/curl_endian.h b/lib/curl_endian.h index 341dfaf3cce..4e12d7da4d9 100644 --- a/lib/curl_endian.h +++ b/lib/curl_endian.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,7 +31,7 @@ unsigned int Curl_read32_le(const unsigned char *buf); /* Converts a 16-bit integer from big endian */ unsigned short Curl_read16_be(const unsigned char *buf); -#if (CURL_SIZEOF_CURL_OFF_T > 4) +#if (SIZEOF_CURL_OFF_T > 4) /* Converts a 64-bit integer to little endian */ #if defined(HAVE_LONGLONG) void Curl_write64_le(const long long value, unsigned char *buffer); diff --git a/lib/curl_get_line.c b/lib/curl_get_line.c index 438ede7046f..8f3b0bd8c10 100644 --- a/lib/curl_get_line.c +++ b/lib/curl_get_line.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \ - defined(USE_HSTS) + !defined(CURL_DISABLE_HSTS) #include "curl_get_line.h" #include "curl_memory.h" diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c index 6445fbad090..acaaa1c6831 100644 --- a/lib/curl_gssapi.c +++ b/lib/curl_gssapi.c @@ -102,7 +102,7 @@ static size_t display_gss_error(OM_uint32 status, int type, (char *)status_string.value); } gss_release_buffer(&min_stat, &status_string); - } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); + } while(!GSS_ERROR(maj_stat) && msg_ctx); return len; } diff --git a/lib/curl_krb5.h b/lib/curl_krb5.h index 3f40f9a6cab..ca068407425 100644 --- a/lib/curl_krb5.h +++ b/lib/curl_krb5.h @@ -29,7 +29,6 @@ struct Curl_sec_client_mech { int (*auth)(void *, struct Curl_easy *data, struct connectdata *); void (*end)(void *); int (*check_prot)(void *, int); - int (*overhead)(void *, int, int); int (*encode)(void *, const void *, int, int, void **); int (*decode)(void *, void *, int, int, struct connectdata *); }; diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c index d327c8ba771..16418bee4c8 100644 --- a/lib/curl_multibyte.c +++ b/lib/curl_multibyte.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -21,7 +21,11 @@ ***************************************************************************/ /* - * This file is 'mem-include-scan' clean. See test 1132. + * This file is 'mem-include-scan' clean, which means memdebug.h and + * curl_memory.h are purposely not included in this file. See test 1132. + * + * The functions in this file are curlx functions which are not tracked by the + * curl memory tracker memdebug. */ #include "curl_setup.h" @@ -82,6 +86,32 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) #if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES) +int curlx_win32_open(const char *filename, int oflag, ...) +{ + int pmode = 0; + +#ifdef _UNICODE + int result = -1; + wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename); +#endif + + va_list param; + va_start(param, oflag); + if(oflag & O_CREAT) + pmode = va_arg(param, int); + va_end(param); + +#ifdef _UNICODE + if(filename_w) + result = _wopen(filename_w, oflag, pmode); + free(filename_w); + if(result != -1) + return result; +#endif + + return (_open)(filename, oflag, pmode); +} + FILE *curlx_win32_fopen(const char *filename, const char *mode) { #ifdef _UNICODE @@ -104,50 +134,38 @@ int curlx_win32_stat(const char *path, struct_stat *buffer) int result = -1; #ifdef _UNICODE wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); -#endif /* _UNICODE */ - + if(path_w) { #if defined(USE_WIN32_SMALL_FILES) -#if defined(_UNICODE) - if(path_w) result = _wstat(path_w, buffer); - else -#endif /* _UNICODE */ - result = _stat(path, buffer); -#else /* USE_WIN32_SMALL_FILES */ -#if defined(_UNICODE) - if(path_w) +#else result = _wstati64(path_w, buffer); - else +#endif + free(path_w); + if(result != -1) + return result; + } #endif /* _UNICODE */ - result = _stati64(path, buffer); -#endif /* USE_WIN32_SMALL_FILES */ -#ifdef _UNICODE - free(path_w); +#if defined(USE_WIN32_SMALL_FILES) + result = _stat(path, buffer); +#else + result = _stati64(path, buffer); #endif - return result; } int curlx_win32_access(const char *path, int mode) { - int result = -1; -#ifdef _UNICODE - wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); -#endif /* _UNICODE */ - #if defined(_UNICODE) - if(path_w) - result = _waccess(path_w, mode); - else -#endif /* _UNICODE */ - result = _access(path, mode); - -#ifdef _UNICODE + wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); + if(path_w) { + int result = _waccess(path_w, mode); free(path_w); -#endif - - return result; + if(result != -1) + return result; + } +#endif /* _UNICODE */ + return _access(path, mode); } #endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */ diff --git a/lib/curl_multibyte.h b/lib/curl_multibyte.h index 8adaf497847..491155e6a71 100644 --- a/lib/curl_multibyte.h +++ b/lib/curl_multibyte.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,7 +31,6 @@ wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8); char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); - #endif /* WIN32 */ /* @@ -40,29 +39,23 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); * preprocessor conditional directives needed by code using these * to differentiate UNICODE from non-UNICODE builds. * - * When building with UNICODE defined, these two macros - * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8() - * return a pointer to a newly allocated memory area holding result. - * When the result is no longer needed, allocated memory is intended - * to be free'ed with curlx_unicodefree(). + * In the case of a non-UNICODE build the tchar strings are char strings that + * are duplicated via strdup and remain in whatever the passed in encoding is, + * which is assumed to be UTF-8 but may be other encoding. Therefore the + * significance of the conversion functions is primarily for UNICODE builds. + * + * Allocated memory should be free'd with curlx_unicodefree(). * - * When building without UNICODE defined, this macros - * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8() - * return the pointer received as argument. curlx_unicodefree() does - * no actual free'ing of this pointer it is simply set to NULL. + * Note: Because these are curlx functions their memory usage is not tracked + * by the curl memory tracker memdebug. You'll notice that curlx function-like + * macros call free and strdup in parentheses, eg (strdup)(ptr), and that's to + * ensure that the curl memdebug override macros do not replace them. */ #if defined(UNICODE) && defined(WIN32) #define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr)) #define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr)) -#define curlx_unicodefree(ptr) \ - do { \ - if(ptr) { \ - (free)(ptr); \ - (ptr) = NULL; \ - } \ - } while(0) typedef union { unsigned short *tchar_ptr; @@ -73,10 +66,8 @@ typedef union { #else -#define curlx_convert_UTF8_to_tchar(ptr) (ptr) -#define curlx_convert_tchar_to_UTF8(ptr) (ptr) -#define curlx_unicodefree(ptr) \ - do {(ptr) = NULL;} while(0) +#define curlx_convert_UTF8_to_tchar(ptr) (strdup)(ptr) +#define curlx_convert_tchar_to_UTF8(ptr) (strdup)(ptr) typedef union { char *tchar_ptr; @@ -87,4 +78,12 @@ typedef union { #endif /* UNICODE && WIN32 */ +#define curlx_unicodefree(ptr) \ + do { \ + if(ptr) { \ + (free)(ptr); \ + (ptr) = NULL; \ + } \ + } while(0) + #endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 9a075ac90fa..89d4ec872eb 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,13 +34,12 @@ /* Please keep the SSL backend-specific #if branches in this order: 1. USE_OPENSSL - 2. USE_GNUTLS_NETTLE - 3. USE_GNUTLS - 4. USE_NSS - 5. USE_MBEDTLS - 6. USE_SECTRANSP - 7. USE_OS400CRYPTO - 8. USE_WIN32_CRYPTO + 2. USE_GNUTLS + 3. USE_NSS + 4. USE_MBEDTLS + 5. USE_SECTRANSP + 6. USE_OS400CRYPTO + 7. USE_WIN32_CRYPTO This ensures that: - the same SSL branch gets activated throughout this source @@ -74,13 +73,9 @@ # define DESKEY(x) &x # endif -#elif defined(USE_GNUTLS_NETTLE) - -# include - #elif defined(USE_GNUTLS) -# include +# include #elif defined(USE_NSS) @@ -159,7 +154,7 @@ static void setup_des_key(const unsigned char *key_56, DES_set_key(&key, ks); } -#elif defined(USE_GNUTLS_NETTLE) +#elif defined(USE_GNUTLS) static void setup_des_key(const unsigned char *key_56, struct des_ctx *des) @@ -176,26 +171,6 @@ static void setup_des_key(const unsigned char *key_56, des_set_key(des, (const uint8_t *) key); } -#elif defined(USE_GNUTLS) - -/* - * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. - */ -static void setup_des_key(const unsigned char *key_56, - gcry_cipher_hd_t *des) -{ - char key[8]; - - /* Expand the 56-bit key to 64-bits */ - extend_key_56_to_64(key_56, key); - - /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); - - /* Set the key */ - gcry_cipher_setkey(*des, key, sizeof(key)); -} - #elif defined(USE_NSS) /* @@ -402,7 +377,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, setup_des_key(keys + 14, DESKEY(ks)); DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16), DESKEY(ks), DES_ENCRYPT); -#elif defined(USE_GNUTLS_NETTLE) +#elif defined(USE_GNUTLS) struct des_ctx des; setup_des_key(keys, &des); des_encrypt(&des, 8, results, plaintext); @@ -410,23 +385,6 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, des_encrypt(&des, 8, results + 8, plaintext); setup_des_key(keys + 14, &des); des_encrypt(&des, 8, results + 16, plaintext); -#elif defined(USE_GNUTLS) - gcry_cipher_hd_t des; - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(keys, &des); - gcry_cipher_encrypt(des, results, 8, plaintext, 8); - gcry_cipher_close(des); - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(keys + 7, &des); - gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8); - gcry_cipher_close(des); - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(keys + 14, &des); - gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); - gcry_cipher_close(des); #elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) encrypt_des(plaintext, results, keys); @@ -473,24 +431,12 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, setup_des_key(pw + 7, DESKEY(ks)); DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8), DESKEY(ks), DES_ENCRYPT); -#elif defined(USE_GNUTLS_NETTLE) +#elif defined(USE_GNUTLS) struct des_ctx des; setup_des_key(pw, &des); des_encrypt(&des, 8, lmbuffer, magic); setup_des_key(pw + 7, &des); des_encrypt(&des, 8, lmbuffer + 8, magic); -#elif defined(USE_GNUTLS) - gcry_cipher_hd_t des; - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(pw, &des); - gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); - gcry_cipher_close(des); - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(pw + 7, &des); - gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); - gcry_cipher_close(des); #elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) encrypt_des(magic, lmbuffer, pw); @@ -567,6 +513,56 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) +/* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */ +struct ms_filetime { + unsigned int dwLowDateTime; + unsigned int dwHighDateTime; +}; + +/* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */ +static void time2filetime(struct ms_filetime *ft, time_t t) +{ +#if SIZEOF_TIME_T > 4 + t = (t + CURL_OFF_T_C(11644473600)) * 10000000; + ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF); + ft->dwHighDateTime = (unsigned int) (t >> 32); +#else + unsigned int r, s; + unsigned int i; + + ft->dwLowDateTime = t & 0xFFFFFFFF; + ft->dwHighDateTime = 0; + +# ifndef HAVE_TIME_T_UNSIGNED + /* Extend sign if needed. */ + if(ft->dwLowDateTime & 0x80000000) + ft->dwHighDateTime = ~0; +# endif + + /* Bias seconds to Jan 1, 1601. + 134774 days = 11644473600 seconds = 0x2B6109100 */ + r = ft->dwLowDateTime; + ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF; + ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02; + + /* Convert to tenths of microseconds. */ + ft->dwHighDateTime *= 10000000; + i = 32; + do { + i -= 8; + s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1); + r = (s << i) & 0xFFFFFFFF; + s >>= 1; /* Split shift to avoid width overflow. */ + s >>= 31 - i; + ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF; + if(ft->dwLowDateTime < r) + s++; + ft->dwHighDateTime += s; + } while(i); + ft->dwHighDateTime &= 0xFFFFFFFF; +#endif +} + /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode * (uppercase UserName + Domain) as the data */ @@ -640,22 +636,18 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned int len = 0; unsigned char *ptr = NULL; unsigned char hmac_output[HMAC_MD5_LENGTH]; - curl_off_t tw; + struct ms_filetime tw; CURLcode result = CURLE_OK; -#if CURL_SIZEOF_CURL_OFF_T < 8 -#error "this section needs 64bit support to work" -#endif - /* Calculate the timestamp */ #ifdef DEBUGBUILD char *force_timestamp = getenv("CURL_FORCETIME"); if(force_timestamp) - tw = CURL_OFF_T_C(11644473600) * 10000000; + time2filetime(&tw, (time_t) 0); else #endif - tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000; + time2filetime(&tw, time(NULL)); /* Calculate the response len */ len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN; @@ -667,13 +659,14 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, /* Create the BLOB structure */ msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN, - "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ - "%c%c%c%c", /* Reserved = 0 */ + "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ + "%c%c%c%c" /* Reserved = 0 */ + "%c%c%c%c%c%c%c%c", /* Timestamp */ NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], - 0, 0, 0, 0); + 0, 0, 0, 0, + LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime)); - Curl_write64_le(tw, ptr + 24); memcpy(ptr + 32, challenge_client, 8); memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h index fab628c590a..02b39d48584 100644 --- a/lib/curl_ntlm_core.h +++ b/lib/curl_ntlm_core.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,7 +30,6 @@ then it must be initialized to be used by NTLM. */ #if !defined(USE_OPENSSL) && \ !defined(USE_WOLFSSL) && \ - !defined(USE_GNUTLS_NETTLE) && \ !defined(USE_GNUTLS) && \ defined(USE_NSS) #define NTLM_NEEDS_NSS_INIT @@ -48,19 +47,22 @@ #define USE_NTRESPONSES /* Define USE_NTLM2SESSION in order to make the type-3 message include the - NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and - MD5 support */ -#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH) + NTLM2Session response message, requires USE_NTRESPONSES defined to 1 */ +#if defined(USE_NTRESPONSES) #define USE_NTLM2SESSION #endif /* Define USE_NTLM_V2 in order to allow the type-3 message to include the - LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 - and support for 64-bit integers. */ -#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4) + LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 */ +#if defined(USE_NTRESPONSES) #define USE_NTLM_V2 #endif +/* Helpers to generate function byte arguments in little endian order */ +#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)) +#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \ + ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff)) + void Curl_ntlm_core_lm_resp(const unsigned char *keys, const unsigned char *plaintext, unsigned char *results); diff --git a/lib/curl_path.c b/lib/curl_path.c index 6100d77bd97..65106188c72 100644 --- a/lib/curl_path.c +++ b/lib/curl_path.c @@ -48,7 +48,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, /* Check for /~/, indicating relative to the user's home directory */ if(data->conn->handler->protocol & CURLPROTO_SCP) { real_path = malloc(working_path_len + 1); - if(real_path == NULL) { + if(!real_path) { free(working_path); return CURLE_OUT_OF_MEMORY; } @@ -62,7 +62,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, if((working_path_len > 1) && (working_path[1] == '~')) { size_t homelen = strlen(homedir); real_path = malloc(homelen + working_path_len + 1); - if(real_path == NULL) { + if(!real_path) { free(working_path); return CURLE_OUT_OF_MEMORY; } @@ -78,7 +78,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, } else { real_path = malloc(working_path_len + 1); - if(real_path == NULL) { + if(!real_path) { free(working_path); return CURLE_OUT_OF_MEMORY; } @@ -130,7 +130,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) /* Allocate enough space for home directory and filename + separator */ fullPathLength = strlen(cp) + strlen(homedir) + 2; *path = malloc(fullPathLength); - if(*path == NULL) + if(!*path) return CURLE_OUT_OF_MEMORY; /* Check for quoted filenames */ @@ -169,7 +169,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) else { /* Read to end of filename - either to whitespace or terminator */ end = strpbrk(cp, WHITESPACE); - if(end == NULL) + if(!end) end = strchr(cp, '\0'); /* return pointer to second parameter if it exists */ *cpp = end + strspn(end, WHITESPACE); diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index fabdc884842..2fa026796e6 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_rtmp = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMP, /* defport */ CURLPROTO_RTMP, /* protocol */ CURLPROTO_RTMP, /* family */ @@ -101,6 +102,7 @@ const struct Curl_handler Curl_handler_rtmpt = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPT, /* defport */ CURLPROTO_RTMPT, /* protocol */ CURLPROTO_RTMPT, /* family */ @@ -123,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMP, /* defport */ CURLPROTO_RTMPE, /* protocol */ CURLPROTO_RTMPE, /* family */ @@ -145,6 +148,7 @@ const struct Curl_handler Curl_handler_rtmpte = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPT, /* defport */ CURLPROTO_RTMPTE, /* protocol */ CURLPROTO_RTMPTE, /* family */ @@ -167,6 +171,7 @@ const struct Curl_handler Curl_handler_rtmps = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPS, /* defport */ CURLPROTO_RTMPS, /* protocol */ CURLPROTO_RTMP, /* family */ @@ -189,6 +194,7 @@ const struct Curl_handler Curl_handler_rtmpts = { rtmp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTMPS, /* defport */ CURLPROTO_RTMPTS, /* protocol */ CURLPROTO_RTMPT, /* family */ @@ -204,7 +210,7 @@ static CURLcode rtmp_setup_connection(struct Curl_easy *data, RTMP_Init(r); RTMP_SetBufferMS(r, DEF_BUFTIME); - if(!RTMP_SetupURL(r, data->change.url)) { + if(!RTMP_SetupURL(r, data->state.url)) { RTMP_Free(r); return CURLE_URL_MALFORMAT; } diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index ffeb75164dc..a4d1059cb94 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -23,6 +23,8 @@ * RFC2831 DIGEST-MD5 authentication * RFC4422 Simple Authentication and Security Layer (SASL) * RFC4616 PLAIN authentication + * RFC5802 SCRAM-SHA-1 authentication + * RFC7677 SCRAM-SHA-256 authentication * RFC6749 OAuth 2.0 Authorization Framework * RFC7628 A Set of SASL Mechanisms for OAuth * Draft LOGIN SASL Mechanism @@ -56,7 +58,7 @@ static const struct { const char *name; /* Name */ size_t len; /* Name length */ - unsigned int bit; /* Flag bit */ + unsigned short bit; /* Flag bit */ } mechtable[] = { { "LOGIN", 5, SASL_MECH_LOGIN }, { "PLAIN", 5, SASL_MECH_PLAIN }, @@ -67,6 +69,8 @@ static const struct { { "NTLM", 4, SASL_MECH_NTLM }, { "XOAUTH2", 7, SASL_MECH_XOAUTH2 }, { "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER }, + { "SCRAM-SHA-1", 11, SASL_MECH_SCRAM_SHA_1 }, + { "SCRAM-SHA-256",13, SASL_MECH_SCRAM_SHA_256 }, { ZERO_NULL, 0, 0 } }; @@ -90,6 +94,13 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) } #endif +#if defined(USE_GSASL) + /* Cleanup the GSASL structure */ + if(authused & (SASL_MECH_SCRAM_SHA_1 | SASL_MECH_SCRAM_SHA_256)) { + Curl_auth_gsasl_cleanup(&conn->gsasl); + } +#endif + #if defined(USE_NTLM) /* Cleanup the NTLM structure */ if(authused == SASL_MECH_NTLM) { @@ -117,7 +128,8 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused) * * Returns the SASL mechanism token or 0 if no match. */ -unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len) +unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen, + size_t *len) { unsigned int i; char c; @@ -162,7 +174,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, if(!strncmp(value, "*", len)) sasl->prefmech = SASL_AUTH_DEFAULT; else { - unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen); + unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen); if(mechbit && mechlen == len) sasl->prefmech |= mechbit; else @@ -215,6 +227,7 @@ static void state(struct SASL *sasl, struct Curl_easy *data, "GSSAPI_NO_DATA", "OAUTH2", "OAUTH2_RESP", + "GSASL", "CANCEL", "FINAL", /* LAST */ @@ -230,6 +243,49 @@ static void state(struct SASL *sasl, struct Curl_easy *data, sasl->state = newstate; } +/* Get the SASL server message and convert it to binary. */ +static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, + struct bufref *out) +{ + unsigned char *msg; + size_t msglen; + char *serverdata = NULL; + CURLcode result = CURLE_OK; + + sasl->params->getmessage(data->state.buffer, &serverdata); + if(!serverdata) + result = CURLE_BAD_CONTENT_ENCODING; + else if(!*serverdata || *serverdata == '=') + Curl_bufref_set(out, NULL, 0, NULL); + else { + result = Curl_base64_decode(serverdata, &msg, &msglen); + if(!result) + Curl_bufref_set(out, msg, msglen, curl_free); + } + return result; +} + +/* Encode the outgoing SASL message. */ +static CURLcode build_message(struct Curl_easy *data, struct bufref *msg) +{ + CURLcode result = CURLE_OK; + char *base64; + size_t base64len; + + if(!Curl_bufref_ptr(msg)) /* Empty mesage. */ + Curl_bufref_set(msg, "", 0, NULL); + else if(!Curl_bufref_len(msg)) /* Explicit empty response. */ + Curl_bufref_set(msg, "=", 1, NULL); + else { + result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg), + Curl_bufref_len(msg), &base64, &base64len); + if(!result) + Curl_bufref_set(msg, base64, base64len, curl_free); + } + + return result; +} + /* * Curl_sasl_can_authenticate() * @@ -260,25 +316,21 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, CURLcode result = CURLE_OK; unsigned int enabledmechs; const char *mech = NULL; - char *resp = NULL; - size_t len = 0; + struct bufref resp; saslstate state1 = SASL_STOP; saslstate state2 = SASL_FINAL; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); #if defined(USE_KERBEROS5) || defined(USE_NTLM) const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : sasl->params->service; #endif const char *oauth_bearer = data->set.str[STRING_BEARER]; + struct bufref nullmsg; + Curl_bufref_init(&nullmsg); + Curl_bufref_init(&resp); sasl->force_ir = force_ir; /* Latch for future use */ sasl->authused = 0; /* No mechanism used yet */ enabledmechs = sasl->authmechs & sasl->prefmech; @@ -292,8 +344,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_EXTERNAL; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_external_message(data, conn->user, &resp, - &len); + result = Curl_auth_create_external_message(conn->user, &resp); } else if(conn->bits.user_passwd) { #if defined(USE_KERBEROS5) @@ -309,10 +360,39 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_gssapi_user_message(data, conn->user, conn->passwd, service, - data->conn->host.name, + conn->host.name, sasl->mutual_auth, NULL, &conn->krb5, - &resp, &len); + &resp); + } + else +#endif +#ifdef USE_GSASL + if((enabledmechs & SASL_MECH_SCRAM_SHA_256) && + Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256, + &conn->gsasl)) { + mech = SASL_MECH_STRING_SCRAM_SHA_256; + sasl->authused = SASL_MECH_SCRAM_SHA_256; + state1 = SASL_GSASL; + state2 = SASL_GSASL; + + result = Curl_auth_gsasl_start(data, conn->user, + conn->passwd, &conn->gsasl); + if(result == CURLE_OK && (force_ir || data->set.sasl_ir)) + result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp); + } + else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) && + Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1, + &conn->gsasl)) { + mech = SASL_MECH_STRING_SCRAM_SHA_1; + sasl->authused = SASL_MECH_SCRAM_SHA_1; + state1 = SASL_GSASL; + state2 = SASL_GSASL; + + result = Curl_auth_gsasl_start(data, conn->user, + conn->passwd, &conn->gsasl); + if(result == CURLE_OK && (force_ir || data->set.sasl_ir)) + result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp); } else #endif @@ -342,8 +422,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, conn->user, conn->passwd, service, hostname, - &conn->ntlm, &resp, - &len); + &conn->ntlm, &resp); } else #endif @@ -354,11 +433,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_OAUTHBEARER; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_oauth_bearer_message(data, conn->user, + result = Curl_auth_create_oauth_bearer_message(conn->user, hostname, port, oauth_bearer, - &resp, &len); + &resp); } else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) { mech = SASL_MECH_STRING_XOAUTH2; @@ -366,9 +445,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_XOAUTH2; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + result = Curl_auth_create_xoauth_bearer_message(conn->user, oauth_bearer, - &resp, &len); + &resp); } else if(enabledmechs & SASL_MECH_PLAIN) { mech = SASL_MECH_STRING_PLAIN; @@ -376,9 +455,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_PLAIN; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_plain_message(data, conn->sasl_authzid, + result = Curl_auth_create_plain_message(conn->sasl_authzid, conn->user, conn->passwd, - &resp, &len); + &resp); } else if(enabledmechs & SASL_MECH_LOGIN) { mech = SASL_MECH_STRING_LOGIN; @@ -387,26 +466,29 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, sasl->authused = SASL_MECH_LOGIN; if(force_ir || data->set.sasl_ir) - result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + result = Curl_auth_create_login_message(conn->user, &resp); } } if(!result && mech) { - if(resp && sasl->params->maxirlen && - strlen(mech) + len > sasl->params->maxirlen) { - free(resp); - resp = NULL; - } + if(Curl_bufref_ptr(&resp)) + result = build_message(data, &resp); + + if(sasl->params->maxirlen && + strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen) + Curl_bufref_free(&resp); + + if(!result) + result = sasl->params->sendauth(data, conn, mech, + (const char *) Curl_bufref_ptr(&resp)); - result = sasl->params->sendauth(data, conn, mech, resp); if(!result) { *progress = SASL_INPROGRESS; - state(sasl, data, resp ? state2 : state1); + state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1); } } - free(resp); - + Curl_bufref_free(&resp); return result; } @@ -421,29 +503,20 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, { CURLcode result = CURLE_OK; saslstate newstate = SASL_FINAL; - char *resp = NULL; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif -#if !defined(CURL_DISABLE_CRYPTO_AUTH) - char *chlg = NULL; - size_t chlglen = 0; -#endif + struct bufref resp; + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \ defined(USE_NTLM) const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : sasl->params->service; - char *serverdata; #endif - size_t len = 0; const char *oauth_bearer = data->set.str[STRING_BEARER]; + struct bufref serverdata; + Curl_bufref_init(&serverdata); + Curl_bufref_init(&resp); *progress = SASL_INPROGRESS; if(sasl->state == SASL_FINAL) { @@ -466,42 +539,45 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, *progress = SASL_DONE; return result; case SASL_PLAIN: - result = Curl_auth_create_plain_message(data, conn->sasl_authzid, - conn->user, conn->passwd, - &resp, &len); + result = Curl_auth_create_plain_message(conn->sasl_authzid, + conn->user, conn->passwd, &resp); break; case SASL_LOGIN: - result = Curl_auth_create_login_message(data, conn->user, &resp, &len); + result = Curl_auth_create_login_message(conn->user, &resp); newstate = SASL_LOGIN_PASSWD; break; case SASL_LOGIN_PASSWD: - result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len); + result = Curl_auth_create_login_message(conn->passwd, &resp); break; case SASL_EXTERNAL: - result = Curl_auth_create_external_message(data, conn->user, &resp, &len); + result = Curl_auth_create_external_message(conn->user, &resp); break; - #ifndef CURL_DISABLE_CRYPTO_AUTH +#ifdef USE_GSASL + case SASL_GSASL: + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp); + if(!result && Curl_bufref_len(&resp) > 0) + newstate = SASL_GSASL; + break; +#endif case SASL_CRAMMD5: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen); + result = get_server_message(sasl, data, &serverdata); if(!result) - result = Curl_auth_create_cram_md5_message(data, chlg, conn->user, - conn->passwd, &resp, &len); - free(chlg); + result = Curl_auth_create_cram_md5_message(&serverdata, conn->user, + conn->passwd, &resp); break; case SASL_DIGESTMD5: - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_create_digest_md5_message(data, serverdata, - conn->user, conn->passwd, - service, - &resp, &len); + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_create_digest_md5_message(data, &serverdata, + conn->user, conn->passwd, + service, &resp); newstate = SASL_DIGESTMD5_RESP; break; case SASL_DIGESTMD5_RESP: - resp = strdup(""); - if(!resp) - result = CURLE_OUT_OF_MEMORY; + /* Keep response NULL to output an empty line. */ break; #endif @@ -511,18 +587,19 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_ntlm_type1_message(data, conn->user, conn->passwd, service, hostname, - &conn->ntlm, &resp, &len); + &conn->ntlm, &resp); newstate = SASL_NTLM_TYPE2MSG; break; case SASL_NTLM_TYPE2MSG: /* Decode the type-2 message */ - sasl->params->getmessage(data->state.buffer, &serverdata); - result = Curl_auth_decode_ntlm_type2_message(data, serverdata, - &conn->ntlm); + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_decode_ntlm_type2_message(data, &serverdata, + &conn->ntlm); if(!result) result = Curl_auth_create_ntlm_type3_message(data, conn->user, conn->passwd, &conn->ntlm, - &resp, &len); + &resp); break; #endif @@ -531,55 +608,59 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, result = Curl_auth_create_gssapi_user_message(data, conn->user, conn->passwd, service, - data->conn->host.name, + conn->host.name, sasl->mutual_auth, NULL, &conn->krb5, - &resp, &len); + &resp); newstate = SASL_GSSAPI_TOKEN; break; case SASL_GSSAPI_TOKEN: - sasl->params->getmessage(data->state.buffer, &serverdata); - if(sasl->mutual_auth) { - /* Decode the user token challenge and create the optional response - message */ - result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, - NULL, NULL, - sasl->mutual_auth, - serverdata, &conn->krb5, - &resp, &len); - newstate = SASL_GSSAPI_NO_DATA; + result = get_server_message(sasl, data, &serverdata); + if(!result) { + if(sasl->mutual_auth) { + /* Decode the user token challenge and create the optional response + message */ + result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, + NULL, NULL, + sasl->mutual_auth, + &serverdata, + &conn->krb5, + &resp); + newstate = SASL_GSSAPI_NO_DATA; + } + else + /* Decode the security challenge and create the response message */ + result = Curl_auth_create_gssapi_security_message(data, &serverdata, + &conn->krb5, + &resp); } - else - /* Decode the security challenge and create the response message */ - result = Curl_auth_create_gssapi_security_message(data, serverdata, - &conn->krb5, - &resp, &len); break; case SASL_GSSAPI_NO_DATA: - sasl->params->getmessage(data->state.buffer, &serverdata); /* Decode the security challenge and create the response message */ - result = Curl_auth_create_gssapi_security_message(data, serverdata, - &conn->krb5, - &resp, &len); + result = get_server_message(sasl, data, &serverdata); + if(!result) + result = Curl_auth_create_gssapi_security_message(data, &serverdata, + &conn->krb5, + &resp); break; #endif case SASL_OAUTH2: /* Create the authorisation message */ if(sasl->authused == SASL_MECH_OAUTHBEARER) { - result = Curl_auth_create_oauth_bearer_message(data, conn->user, + result = Curl_auth_create_oauth_bearer_message(conn->user, hostname, port, oauth_bearer, - &resp, &len); + &resp); /* Failures maybe sent by the server as continuations for OAUTHBEARER */ newstate = SASL_OAUTH2_RESP; } else - result = Curl_auth_create_xoauth_bearer_message(data, conn->user, + result = Curl_auth_create_xoauth_bearer_message(conn->user, oauth_bearer, - &resp, &len); + &resp); break; case SASL_OAUTH2_RESP: @@ -591,11 +672,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, return result; } else if(code == sasl->params->contcode) { - /* Acknowledge the continuation by sending a 0x01 response base64 - encoded */ - resp = strdup("AQ=="); - if(!resp) - result = CURLE_OUT_OF_MEMORY; + /* Acknowledge the continuation by sending a 0x01 response. */ + Curl_bufref_set(&resp, "\x01", 1, NULL); break; } else { @@ -609,15 +687,15 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, sasl->authmechs ^= sasl->authused; /* Start an alternative SASL authentication */ - result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress); - newstate = sasl->state; /* Use state from Curl_sasl_start() */ - break; + return Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress); default: failf(data, "Unsupported SASL authentication mechanism"); result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ break; } + Curl_bufref_free(&serverdata); + switch(result) { case CURLE_BAD_CONTENT_ENCODING: /* Cancel dialog */ @@ -625,8 +703,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, newstate = SASL_CANCEL; break; case CURLE_OK: - if(resp) - result = sasl->params->sendcont(data, conn, resp); + result = build_message(data, &resp); + if(!result) + result = sasl->params->sendcont(data, conn, + (const char *) Curl_bufref_ptr(&resp)); break; default: newstate = SASL_STOP; /* Stop on error */ @@ -634,7 +714,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, break; } - free(resp); + Curl_bufref_free(&resp); state(sasl, data, newstate); diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h index 75a957583aa..e17d323eba7 100644 --- a/lib/curl_sasl.h +++ b/lib/curl_sasl.h @@ -37,10 +37,12 @@ struct connectdata; #define SASL_MECH_NTLM (1 << 6) #define SASL_MECH_XOAUTH2 (1 << 7) #define SASL_MECH_OAUTHBEARER (1 << 8) +#define SASL_MECH_SCRAM_SHA_1 (1 << 9) +#define SASL_MECH_SCRAM_SHA_256 (1 << 10) /* Authentication mechanism values */ #define SASL_AUTH_NONE 0 -#define SASL_AUTH_ANY ~0U +#define SASL_AUTH_ANY 0xffff #define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL) /* Authentication mechanism strings */ @@ -53,6 +55,8 @@ struct connectdata; #define SASL_MECH_STRING_NTLM "NTLM" #define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" #define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER" +#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1" +#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256" /* SASL machine states */ typedef enum { @@ -71,6 +75,7 @@ typedef enum { SASL_GSSAPI_NO_DATA, SASL_OAUTH2, SASL_OAUTH2_RESP, + SASL_GSASL, SASL_CANCEL, SASL_FINAL } saslstate; @@ -103,9 +108,9 @@ struct SASLproto { struct SASL { const struct SASLproto *params; /* Protocol dependent parameters */ saslstate state; /* Current machine state */ - unsigned int authmechs; /* Accepted authentication mechanisms */ - unsigned int prefmech; /* Preferred authentication mechanism */ - unsigned int authused; /* Auth mechanism used for the connection */ + unsigned short authmechs; /* Accepted authentication mechanisms */ + unsigned short prefmech; /* Preferred authentication mechanism */ + unsigned short authused; /* Auth mechanism used for the connection */ bool resetprefs; /* For URL auth option parsing. */ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ bool force_ir; /* Protocol always supports initial response */ @@ -121,8 +126,8 @@ struct SASL { void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); /* Convert a mechanism name to a token */ -unsigned int Curl_sasl_decode_mech(const char *ptr, - size_t maxlen, size_t *len); +unsigned short Curl_sasl_decode_mech(const char *ptr, + size_t maxlen, size_t *len); /* Parse the URL login options */ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 22def2defac..be4a58d4b62 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -54,6 +54,16 @@ # 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)) || \ + defined(WINAPI_FAMILY) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define CURL_WINDOWS_APP +# endif +# endif #endif /* @@ -151,8 +161,6 @@ #include -#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T - /* * Disable other protocols when http is the only one desired. */ @@ -239,7 +247,11 @@ * performing this task will result in a synthesized IPv6 address. */ #if defined(__APPLE__) && !defined(USE_ARES) +#include #define USE_RESOLVE_ON_IPS 1 +# if defined(TARGET_OS_OSX) && TARGET_OS_OSX +# define CURL_OSX_CALL_COPYPROXIES 1 +# endif #endif #ifdef USE_LWIPSOCK @@ -335,8 +347,10 @@ # define stat(fname,stp) curlx_win32_stat(fname, stp) # define struct_stat struct _stati64 # define LSEEK_ERROR (__int64)-1 +# define open curlx_win32_open # define fopen(fname,mode) curlx_win32_fopen(fname, mode) # define access(fname,mode) curlx_win32_access(fname, mode) + int curlx_win32_open(const char *filename, int oflag, ...); int curlx_win32_stat(const char *path, struct_stat *buffer); FILE *curlx_win32_fopen(const char *filename, const char *mode); int curlx_win32_access(const char *path, int mode); @@ -356,9 +370,11 @@ # define fstat(fdes,stp) _fstat(fdes, stp) # define stat(fname,stp) curlx_win32_stat(fname, stp) # define struct_stat struct _stat +# define open curlx_win32_open # define fopen(fname,mode) curlx_win32_fopen(fname, mode) # define access(fname,mode) curlx_win32_access(fname, mode) int curlx_win32_stat(const char *path, struct_stat *buffer); + int curlx_win32_open(const char *filename, int oflag, ...); FILE *curlx_win32_fopen(const char *filename, const char *mode); int curlx_win32_access(const char *path, int mode); # endif @@ -408,7 +424,7 @@ #if (SIZEOF_CURL_OFF_T == 4) # define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF) #else - /* assume CURL_SIZEOF_CURL_OFF_T == 8 */ + /* assume SIZEOF_CURL_OFF_T == 8 */ # define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) #endif #define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1)) @@ -505,7 +521,6 @@ # undef HAVE_GETADDRINFO_THREADSAFE # undef HAVE_FREEADDRINFO # undef HAVE_GETADDRINFO -# undef HAVE_GETNAMEINFO # undef ENABLE_IPV6 # endif #endif @@ -612,7 +627,7 @@ int netware_init(void); defined(USE_MBEDTLS) || \ defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \ defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) || \ - defined(USE_BEARSSL) + defined(USE_BEARSSL) || defined(USE_RUSTLS) #define USE_SSL /* SSL support has been enabled */ #endif @@ -629,7 +644,7 @@ int netware_init(void); #endif /* Single point where USE_NTLM definition might be defined */ -#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) +#ifndef CURL_DISABLE_CRYPTO_AUTH #if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ @@ -703,13 +718,19 @@ int netware_init(void); #endif /* - * Portable symbolic names for Winsock shutdown() mode flags. + * shutdown() flags for systems that don't define them */ -#ifdef USE_WINSOCK -# define SHUT_RD 0x00 -# define SHUT_WR 0x01 -# define SHUT_RDWR 0x02 +#ifndef SHUT_RD +#define SHUT_RD 0x00 +#endif + +#ifndef SHUT_WR +#define SHUT_WR 0x01 +#endif + +#ifndef SHUT_RDWR +#define SHUT_RDWR 0x02 #endif /* Define S_ISREG if not defined by system headers, f.e. MSVC */ @@ -760,20 +781,16 @@ endings either CRLF or LF so 't' is appropriate. # endif #endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ -/* Detect Windows App environment which has a restricted access - * to the Win32 APIs. */ -# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ - defined(WINAPI_FAMILY) -# include -# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ - !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -# define CURL_WINDOWS_APP -# endif -# endif - -/* for systems that don't detect this in configure, use a sensible default */ +/* for systems that don't detect this in configure */ #ifndef CURL_SA_FAMILY_T -#define CURL_SA_FAMILY_T unsigned short +# if defined(HAVE_SA_FAMILY_T) +# define CURL_SA_FAMILY_T sa_family_t +# elif defined(HAVE_ADDRESS_FAMILY) +# define CURL_SA_FAMILY_T ADDRESS_FAMILY +# else +/* use a sensible default */ +# define CURL_SA_FAMILY_T unsigned short +# endif #endif /* Some convenience macros to get the larger/smaller value out of two given. @@ -794,6 +811,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #define UNITTEST static #endif +#if defined(USE_NGHTTP2) || defined(USE_HYPER) +#define USE_HTTP2 +#endif + #if defined(USE_NGTCP2) || defined(USE_QUICHE) #define ENABLE_QUIC #endif diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h index ef60bc7ae78..22d0a063eff 100644 --- a/lib/curl_setup_once.h +++ b/lib/curl_setup_once.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef HAVE_ERRNO_H #include @@ -55,13 +56,6 @@ #ifdef HAVE_SYS_TIME_H #include -#ifdef TIME_WITH_SYS_TIME -#include -#endif -#else -#ifdef HAVE_TIME_H -#include -#endif #endif #ifdef WIN32 @@ -350,15 +344,6 @@ typedef int sig_atomic_t; #endif -/* - * Default return type for signal handlers. - */ - -#ifndef RETSIGTYPE -#define RETSIGTYPE void -#endif - - /* * Macro used to include code only in debug builds. */ diff --git a/lib/dict.c b/lib/dict.c index 4319dadba56..625b057774e 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -89,6 +89,7 @@ const struct Curl_handler Curl_handler_dict = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_DICT, /* defport */ CURLPROTO_DICT, /* protocol */ CURLPROTO_DICT, /* family */ @@ -214,14 +215,14 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } } - if((word == NULL) || (*word == (char)0)) { + if(!word || (*word == (char)0)) { infof(data, "lookup word is missing\n"); word = (char *)"default"; } - if((database == NULL) || (*database == (char)0)) { + if(!database || (*database == (char)0)) { database = (char *)"!"; } - if((strategy == NULL) || (*strategy == (char)0)) { + if(!strategy || (*strategy == (char)0)) { strategy = (char *)"."; } @@ -265,11 +266,11 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } } - if((word == NULL) || (*word == (char)0)) { + if(!word || (*word == (char)0)) { infof(data, "lookup word is missing\n"); word = (char *)"default"; } - if((database == NULL) || (*database == (char)0)) { + if(!database || (*database == (char)0)) { database = (char *)"!"; } diff --git a/lib/doh.c b/lib/doh.c index 004244c8d22..36f8cd58dc5 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -207,10 +207,12 @@ static int doh_done(struct Curl_easy *doh, CURLcode result) } #define ERROR_CHECK_SETOPT(x,y) \ -do { \ - result = curl_easy_setopt(doh, x, y); \ - if(result) \ - goto error; \ +do { \ + result = curl_easy_setopt(doh, x, y); \ + if(result && \ + result != CURLE_NOT_BUILT_IN && \ + result != CURLE_UNKNOWN_OPTION) \ + goto error; \ } while(0) static CURLcode dohprobe(struct Curl_easy *data, @@ -282,84 +284,93 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); #endif ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms); + ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share); + if(data->set.err && data->set.err != stderr) + ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err); if(data->set.verbose) ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); if(data->set.no_signal) ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L); + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, + data->set.doh_verifyhost ? 2L : 0L); + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, + data->set.doh_verifypeer ? 1L : 0L); + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, + data->set.doh_verifystatus ? 1L : 0L); + /* Inherit *some* SSL options from the user's transfer. This is a - best-guess as to which options are needed for compatibility. #3661 */ + best-guess as to which options are needed for compatibility. #3661 + + Note DOH does not inherit the user's proxy server so proxy SSL settings + have no effect and are not inherited. If that changes then two new + options should be added to check doh proxy insecure separately, + CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER. + */ if(data->set.ssl.falsestart) ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L); - if(data->set.ssl.primary.verifyhost) - ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L); -#ifndef CURL_DISABLE_PROXY - if(data->set.proxy_ssl.primary.verifyhost) - ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L); - if(data->set.proxy_ssl.primary.verifypeer) - ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L); - if(data->set.str[STRING_SSL_CAFILE_PROXY]) { - ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO, - data->set.str[STRING_SSL_CAFILE_PROXY]); - } - if(data->set.str[STRING_SSL_CRLFILE_PROXY]) { - ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE, - data->set.str[STRING_SSL_CRLFILE_PROXY]); - } - if(data->set.proxy_ssl.no_revoke) - ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); - else if(data->set.proxy_ssl.revoke_best_effort) - ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, - CURLSSLOPT_REVOKE_BEST_EFFORT); - if(data->set.str[STRING_SSL_CAPATH_PROXY]) { - ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH, - data->set.str[STRING_SSL_CAPATH_PROXY]); - } -#endif - if(data->set.ssl.primary.verifypeer) - ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L); - if(data->set.ssl.primary.verifystatus) - ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L); - if(data->set.str[STRING_SSL_CAFILE_ORIG]) { + if(data->set.str[STRING_SSL_CAFILE]) { ERROR_CHECK_SETOPT(CURLOPT_CAINFO, - data->set.str[STRING_SSL_CAFILE_ORIG]); + data->set.str[STRING_SSL_CAFILE]); + } + if(data->set.blobs[BLOB_CAINFO]) { + ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, + data->set.blobs[BLOB_CAINFO]); } - if(data->set.str[STRING_SSL_CAPATH_ORIG]) { + if(data->set.str[STRING_SSL_CAPATH]) { ERROR_CHECK_SETOPT(CURLOPT_CAPATH, - data->set.str[STRING_SSL_CAPATH_ORIG]); + data->set.str[STRING_SSL_CAPATH]); } - if(data->set.str[STRING_SSL_CRLFILE_ORIG]) { + if(data->set.str[STRING_SSL_CRLFILE]) { ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, - data->set.str[STRING_SSL_CRLFILE_ORIG]); + data->set.str[STRING_SSL_CRLFILE]); } if(data->set.ssl.certinfo) ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); if(data->set.str[STRING_SSL_RANDOM_FILE]) { ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE, - data->set.str[STRING_SSL_RANDOM_FILE]); + data->set.str[STRING_SSL_RANDOM_FILE]); } if(data->set.str[STRING_SSL_EGDSOCKET]) { ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET, - data->set.str[STRING_SSL_EGDSOCKET]); + data->set.str[STRING_SSL_EGDSOCKET]); } - if(data->set.ssl.no_revoke) - ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); - else if(data->set.ssl.revoke_best_effort) - ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT); if(data->set.ssl.fsslctx) ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx); if(data->set.ssl.fsslctxp) ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp); if(data->set.str[STRING_SSL_EC_CURVES]) { ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES, - data->set.str[STRING_SSL_EC_CURVES]); + data->set.str[STRING_SSL_EC_CURVES]); + } + + { + long mask = + (data->set.ssl.enable_beast ? + CURLSSLOPT_ALLOW_BEAST : 0) | + (data->set.ssl.no_revoke ? + CURLSSLOPT_NO_REVOKE : 0) | + (data->set.ssl.no_partialchain ? + CURLSSLOPT_NO_PARTIALCHAIN : 0) | + (data->set.ssl.revoke_best_effort ? + CURLSSLOPT_REVOKE_BEST_EFFORT : 0) | + (data->set.ssl.native_ca_store ? + CURLSSLOPT_NATIVE_CA : 0) | + (data->set.ssl.auto_client_cert ? + CURLSSLOPT_AUTO_CLIENT_CERT : 0); + + curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask); } doh->set.fmultidone = doh_done; doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; - /* add this transfer to the multi handle */ + /* DOH private_data must be null because the user must have a way to + distinguish their transfer's handle from DOH handles in user + callbacks (ie SSL CTX callback). */ + DEBUGASSERT(!data->set.private_data); + if(curl_multi_add_handle(multi, doh)) goto error; } @@ -409,17 +420,15 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, if(!dohp->headers) goto error; - if(conn->ip_version != CURL_IPRESOLVE_V6) { - /* create IPv4 DOH request */ - result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], - DNS_TYPE_A, hostname, data->set.str[STRING_DOH], - data->multi, dohp->headers); - if(result) - goto error; - dohp->pending++; - } + /* create IPv4 DOH request */ + result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], + DNS_TYPE_A, hostname, data->set.str[STRING_DOH], + data->multi, dohp->headers); + if(result) + goto error; + dohp->pending++; - if(conn->ip_version != CURL_IPRESOLVE_V4) { + if(Curl_ipv6works(data)) { /* create IPv6 DOH request */ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH], diff --git a/lib/dynbuf.h b/lib/dynbuf.h index 484e40c645b..252411f8421 100644 --- a/lib/dynbuf.h +++ b/lib/dynbuf.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2020, Daniel Stenberg, , et al. + * Copyright (C) 2020, 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -74,7 +74,7 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save); #define DYN_DOH_CNAME 256 #define DYN_PAUSE_BUFFER (64 * 1024 * 1024) #define DYN_HAXPROXY 2048 -#define DYN_HTTP_REQUEST (128*1024) +#define DYN_HTTP_REQUEST (1024*1024) #define DYN_H2_HEADERS (128*1024) #define DYN_H2_TRAILERS (128*1024) #define DYN_APRINTF 8000000 diff --git a/lib/easy.c b/lib/easy.c index 0fb255af499..530b7c73f22 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -789,7 +789,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) /* duplicate all blobs */ for(j = (enum dupblob)0; j < BLOB_LAST; j++) { result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]); - /* Curl_setstropt return CURLE_BAD_FUNCTION_ARGUMENT with blob */ if(result) return result; } @@ -810,7 +809,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost); if(src->set.resolve) - dst->change.resolve = dst->set.resolve; + dst->state.resolve = dst->set.resolve; return result; } @@ -858,25 +857,25 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) } /* duplicate all values in 'change' */ - if(data->change.cookielist) { - outcurl->change.cookielist = - Curl_slist_duplicate(data->change.cookielist); - if(!outcurl->change.cookielist) + if(data->state.cookielist) { + outcurl->state.cookielist = + Curl_slist_duplicate(data->state.cookielist); + if(!outcurl->state.cookielist) goto fail; } - if(data->change.url) { - outcurl->change.url = strdup(data->change.url); - if(!outcurl->change.url) + if(data->state.url) { + outcurl->state.url = strdup(data->state.url); + if(!outcurl->state.url) goto fail; - outcurl->change.url_alloc = TRUE; + outcurl->state.url_alloc = TRUE; } - if(data->change.referer) { - outcurl->change.referer = strdup(data->change.referer); - if(!outcurl->change.referer) + if(data->state.referer) { + outcurl->state.referer = strdup(data->state.referer); + if(!outcurl->state.referer) goto fail; - outcurl->change.referer_alloc = TRUE; + outcurl->state.referer_alloc = TRUE; } /* Reinitialize an SSL engine for the new handle @@ -895,7 +894,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) (void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]); } #endif -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS if(data->hsts) { outcurl->hsts = Curl_hsts_init(); if(!outcurl->hsts) @@ -947,12 +946,12 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) fail: if(outcurl) { - curl_slist_free_all(outcurl->change.cookielist); - outcurl->change.cookielist = NULL; + curl_slist_free_all(outcurl->state.cookielist); + outcurl->state.cookielist = NULL; Curl_safefree(outcurl->state.buffer); Curl_dyn_free(&outcurl->state.headerb); - Curl_safefree(outcurl->change.url); - Curl_safefree(outcurl->change.referer); + Curl_safefree(outcurl->state.url); + Curl_safefree(outcurl->state.referer); Curl_altsvc_cleanup(&outcurl->asi); Curl_hsts_cleanup(&outcurl->hsts); Curl_freeset(outcurl); @@ -1034,8 +1033,8 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) /* Unpause parts in active mime tree. */ if((k->keepon & ~newstate & KEEP_SEND_PAUSE) && - (data->mstate == CURLM_STATE_PERFORM || - data->mstate == CURLM_STATE_TOOFAST) && + (data->mstate == MSTATE_PERFORMING || + data->mstate == MSTATE_RATELIMITING) && data->state.fread_func == (curl_read_callback) Curl_mime_read) { Curl_mime_unpause(data->state.in); } @@ -1052,8 +1051,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) unsigned int i; unsigned int count = data->state.tempcount; struct tempbuf writebuf[3]; /* there can only be three */ - struct connectdata *conn = data->conn; - struct Curl_easy *saved_data = NULL; /* copy the structs to allow for immediate re-pausing */ for(i = 0; i < data->state.tempcount; i++) { @@ -1062,12 +1059,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) } data->state.tempcount = 0; - /* set the connection's current owner */ - if(conn->data != data) { - saved_data = conn->data; - conn->data = data; - } - for(i = 0; i < count; i++) { /* even if one function returns error, this loops through and frees all buffers */ @@ -1078,10 +1069,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) Curl_dyn_free(&writebuf[i].b); } - /* recover previous owner of the connection */ - if(saved_data) - conn->data = saved_data; - if(result) return result; } @@ -1117,7 +1104,7 @@ static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd, struct connectdata **connp) { - if(data == NULL) + if(!data) return CURLE_BAD_FUNCTION_ARGUMENT; /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ @@ -1183,6 +1170,7 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, CURLcode result; ssize_t n1; struct connectdata *c = NULL; + SIGPIPE_VARIABLE(pipe_st); if(Curl_is_in_callback(data)) return CURLE_RECURSIVE_API_CALL; @@ -1197,7 +1185,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, Curl_attach_connnection(data, c); *n = 0; + sigpipe_ignore(data, &pipe_st); result = Curl_write(data, sfd, buffer, buflen, &n1); + sigpipe_restore(&pipe_st); if(n1 == -1) return CURLE_SEND_ERROR; diff --git a/lib/easyoptions.c b/lib/easyoptions.c index b54829ba385..4e65e3525bf 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -38,6 +38,7 @@ struct curl_easyoption Curl_easyopts[] = { {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0}, {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0}, {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0}, + {"CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0}, {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0}, {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0}, {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0}, @@ -78,6 +79,9 @@ struct curl_easyoption Curl_easyopts[] = { {"DNS_SERVERS", CURLOPT_DNS_SERVERS, CURLOT_STRING, 0}, {"DNS_SHUFFLE_ADDRESSES", CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOT_LONG, 0}, {"DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOT_LONG, 0}, + {"DOH_SSL_VERIFYHOST", CURLOPT_DOH_SSL_VERIFYHOST, CURLOT_LONG, 0}, + {"DOH_SSL_VERIFYPEER", CURLOPT_DOH_SSL_VERIFYPEER, CURLOT_LONG, 0}, + {"DOH_SSL_VERIFYSTATUS", CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOT_LONG, 0}, {"DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0}, {"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0}, {"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS}, @@ -202,6 +206,7 @@ struct curl_easyoption Curl_easyopts[] = { {"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0}, {"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0}, {"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0}, + {"PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0}, {"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0}, {"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0}, {"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0}, @@ -349,6 +354,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (305 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (310 + 1)); } #endif diff --git a/lib/file.c b/lib/file.c index dd8a1fd12ac..0420db34549 100644 --- a/lib/file.c +++ b/lib/file.c @@ -111,6 +111,7 @@ const struct Curl_handler Curl_handler_file = { file_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ 0, /* defport */ CURLPROTO_FILE, /* protocol */ CURLPROTO_FILE, /* family */ @@ -410,19 +411,21 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) struct tm buffer; const struct tm *tm = &buffer; char header[80]; + int headerlen; + char accept_ranges[24]= { "Accept-ranges: bytes\r\n" }; if(expected_size >= 0) { - msnprintf(header, sizeof(header), + headerlen = msnprintf(header, sizeof(header), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size); - result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0); + result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen); if(result) return result; - } - result = Curl_client_write(data, CLIENTWRITE_HEADER, - (char *)"Accept-ranges: bytes\r\n", 0); - if(result) - return result; + result = Curl_client_write(data, CLIENTWRITE_HEADER, + accept_ranges, strlen(accept_ranges)); + if(result != CURLE_OK) + return result; + } filetime = (time_t)statbuf.st_mtime; result = Curl_gmtime(filetime, &buffer); @@ -430,7 +433,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) return result; /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - msnprintf(header, sizeof(header), + headerlen = msnprintf(header, sizeof(header), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s", Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -440,7 +443,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) tm->tm_min, tm->tm_sec, data->set.opt_no_body ? "": "\r\n"); - result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0); + result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen); if(result) return result; /* set the file size to make it available post transfer */ @@ -464,18 +467,23 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) data->state.resume_from += (curl_off_t)statbuf.st_size; } - if(data->state.resume_from <= expected_size) - expected_size -= data->state.resume_from; - else { - failf(data, "failed to resume file:// transfer"); - return CURLE_BAD_DOWNLOAD_RESUME; + if(data->state.resume_from > 0) { + /* We check explicitly if we have a start offset, because + * expected_size may be -1 if we don't know how large the file is, + * in which case we should not adjust it. */ + if(data->state.resume_from <= expected_size) + expected_size -= data->state.resume_from; + else { + failf(data, "failed to resume file:// transfer"); + return CURLE_BAD_DOWNLOAD_RESUME; + } } /* A high water mark has been specified so we obey... */ if(data->req.maxdownload > 0) expected_size = data->req.maxdownload; - if(!fstated || (expected_size == 0)) + if(!fstated || (expected_size <= 0)) size_known = FALSE; else size_known = TRUE; @@ -484,7 +492,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) this is both more efficient than the former call to download() and it avoids problems with select() and recv() on file descriptors in Winsock */ - if(fstated) + if(size_known) Curl_pgrsSetDownloadSize(data, expected_size); if(data->state.resume_from) { diff --git a/lib/ftp.c b/lib/ftp.c index 3818a9ea46b..444cf35f55b 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -175,6 +175,7 @@ const struct Curl_handler Curl_handler_ftp = { ftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_FTP, /* defport */ CURLPROTO_FTP, /* protocol */ CURLPROTO_FTP, /* family */ @@ -205,6 +206,7 @@ const struct Curl_handler Curl_handler_ftps = { ftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_FTPS, /* defport */ CURLPROTO_FTPS, /* protocol */ CURLPROTO_FTP, /* family */ @@ -1090,7 +1092,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, else res = NULL; /* failure! */ - if(res == NULL) { + if(!res) { failf(data, "failed to resolve the address provided to PORT: %s", host); free(addr); return CURLE_FTP_PORT_FAILED; @@ -1357,7 +1359,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data) struct FTP *ftp = data->req.p.ftp; struct connectdata *conn = data->conn; - if(ftp->transfer != FTPTRANSFER_BODY) { + if(ftp->transfer != PPTRANSFER_BODY) { /* doesn't transfer any data */ /* still possibly do PRE QUOTE jobs */ @@ -1378,7 +1380,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data) result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s", data->set.str[STRING_CUSTOMREQUEST]? data->set.str[STRING_CUSTOMREQUEST]: - (data->set.ftp_list_only?"NLST":"LIST")); + (data->state.list_only?"NLST":"LIST")); else if(data->set.upload) result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", conn->proto.ftpc.file); @@ -1401,7 +1403,7 @@ static CURLcode ftp_state_rest(struct Curl_easy *data, struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; - if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { + if((ftp->transfer != PPTRANSFER_BODY) && ftpc->file) { /* if a "head"-like request is being made (on a file) */ /* Determine if server can respond to REST command and therefore @@ -1423,7 +1425,7 @@ static CURLcode ftp_state_size(struct Curl_easy *data, struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; - if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { + if((ftp->transfer == PPTRANSFER_INFO) && ftpc->file) { /* if a "head"-like request is being made (on a file) */ /* we know ftpc->file is a valid pointer to a file name */ @@ -1485,7 +1487,7 @@ static CURLcode ftp_state_list(struct Curl_easy *data) cmd = aprintf("%s%s%s", data->set.str[STRING_CUSTOMREQUEST]? data->set.str[STRING_CUSTOMREQUEST]: - (data->set.ftp_list_only?"NLST":"LIST"), + (data->state.list_only?"NLST":"LIST"), lstArg? " ": "", lstArg? lstArg: ""); free(lstArg); @@ -1525,17 +1527,17 @@ static CURLcode ftp_state_type(struct Curl_easy *data) information. Which in FTP can't be much more than the file size and date. */ if(data->set.opt_no_body && ftpc->file && - ftp_need_type(conn, data->set.prefer_ascii)) { + ftp_need_type(conn, data->state.prefer_ascii)) { /* The SIZE command is _not_ RFC 959 specified, and therefore many servers may not support it! It is however the only way we have to get a file's size! */ - ftp->transfer = FTPTRANSFER_INFO; + ftp->transfer = PPTRANSFER_INFO; /* this means no actual transfer will be made */ /* Some servers return different sizes for different modes, and thus we must set the proper type before we check the size */ - result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE); + result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE); if(result) return result; } @@ -1578,6 +1580,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, struct connectdata *conn = data->conn; struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; + bool append = data->set.remote_append; if((data->state.resume_from && !sizechecked) || ((data->state.resume_from > 0) && sizechecked)) { @@ -1604,7 +1607,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, } /* enable append */ - data->set.ftp_append = TRUE; + append = TRUE; /* Let's read off the proper amount of bytes from the input. */ if(conn->seek_func) { @@ -1652,7 +1655,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, /* Set ->transfer so that we won't get any error in * ftp_done() because we didn't transfer anything! */ - ftp->transfer = FTPTRANSFER_NONE; + ftp->transfer = PPTRANSFER_NONE; state(data, FTP_STOP); return CURLE_OK; @@ -1661,8 +1664,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, /* we've passed, proceed as normal */ } /* resume_from */ - result = Curl_pp_sendf(data, &ftpc->pp, - data->set.ftp_append?"APPE %s":"STOR %s", + result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s", ftpc->file); if(!result) state(data, FTP_STOR); @@ -1739,7 +1741,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data, result = ftp_state_cwd(data, conn); break; case FTP_RETR_PREQUOTE: - if(ftp->transfer != FTPTRANSFER_BODY) + if(ftp->transfer != PPTRANSFER_BODY) state(data, FTP_STOP); else { if(ftpc->known_filesize != -1) { @@ -1747,13 +1749,19 @@ static CURLcode ftp_state_quote(struct Curl_easy *data, result = ftp_state_retr(data, ftpc->known_filesize); } else { - if(data->set.ignorecl) { - /* This code is to support download of growing files. It prevents - the state machine from requesting the file size from the - server. With an unknown file size the download continues until - the server terminates it, otherwise the client stops if the - received byte count exceeds the reported file size. Set option - CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/ + if(data->set.ignorecl || data->state.prefer_ascii) { + /* 'ignorecl' is used to support download of growing files. It + prevents the state machine from requesting the file size from + the server. With an unknown file size the download continues + until the server terminates it, otherwise the client stops if + the received byte count exceeds the reported file size. Set + option CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this + behavior. + + In addition: asking for the size for 'TYPE A' transfers is not + constructive since servers don't report the converted size. So + skip it. + */ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file); if(!result) state(data, FTP_RETR); @@ -2092,6 +2100,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, data->set.get_filetime && (data->info.filetime >= 0) ) { char headerbuf[128]; + int headerbuflen; time_t filetime = data->info.filetime; struct tm buffer; const struct tm *tm = &buffer; @@ -2101,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, return result; /* format: "Tue, 15 Nov 1994 12:45:26" */ - msnprintf(headerbuf, sizeof(headerbuf), + headerbuflen = msnprintf(headerbuf, sizeof(headerbuf), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -2110,7 +2119,8 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, tm->tm_hour, tm->tm_min, tm->tm_sec); - result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, + headerbuflen); if(result) return result; } /* end of a ridiculous amount of conditionals */ @@ -2133,7 +2143,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, default: if(data->info.filetime <= data->set.timevalue) { infof(data, "The requested document is not new enough\n"); - ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */ data->info.timecond = TRUE; state(data, FTP_STOP); return CURLE_OK; @@ -2142,7 +2152,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, case CURL_TIMECOND_IFUNMODSINCE: if(data->info.filetime > data->set.timevalue) { infof(data, "The requested document is not old enough\n"); - ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */ data->info.timecond = TRUE; state(data, FTP_STOP); return CURLE_OK; @@ -2250,7 +2260,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data, /* Set ->transfer so that we won't get any error in ftp_done() * because we didn't transfer the any file */ - ftp->transfer = FTPTRANSFER_NONE; + ftp->transfer = PPTRANSFER_NONE; state(data, FTP_STOP); return CURLE_OK; } @@ -2303,17 +2313,21 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data, } else if(ftpcode == 550) { /* "No such file or directory" */ - failf(data, "The file does not exist"); - return CURLE_REMOTE_FILE_NOT_FOUND; + /* allow a SIZE failure for (resumed) uploads, when probing what command + to use */ + if(instate != FTP_STOR_SIZE) { + failf(data, "The file does not exist"); + return CURLE_REMOTE_FILE_NOT_FOUND; + } } if(instate == FTP_SIZE) { #ifdef CURL_FTP_HTTPSTYLE_HEAD if(-1 != filesize) { char clbuf[128]; - msnprintf(clbuf, sizeof(clbuf), + int clbuflen = msnprintf(clbuf, sizeof(clbuf), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); - result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen); if(result) return result; } @@ -2347,7 +2361,8 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data, #ifdef CURL_FTP_HTTPSTYLE_HEAD if(ftpcode == 350) { char buffer[24]= { "Accept-ranges: bytes\r\n" }; - result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0); + result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, + strlen(buffer)); if(result) return result; } @@ -2448,7 +2463,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, */ if((instate != FTP_LIST) && - !data->set.prefer_ascii && + !data->state.prefer_ascii && (ftp->downloadsize < 1)) { /* * It seems directory listings either don't show the size or very @@ -2476,7 +2491,8 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, bytes--; } /* if we have nothing but digits: */ - if(bytes++) { + if(bytes) { + ++bytes; /* get the number! */ (void)curlx_strtoofft(bytes, NULL, 0, &size); } @@ -2487,7 +2503,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, if(size > data->req.maxdownload && data->req.maxdownload > 0) size = data->req.size = data->req.maxdownload; - else if((instate != FTP_LIST) && (data->set.prefer_ascii)) + else if((instate != FTP_LIST) && (data->state.prefer_ascii)) size = -1; /* kludge for servers that understate ASCII mode file size */ infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", @@ -2521,7 +2537,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, else { if((instate == FTP_LIST) && (ftpcode == 450)) { /* simply no matching files in the dir listing */ - ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ + ftp->transfer = PPTRANSFER_NONE; /* don't download anything */ state(data, FTP_STOP); /* this phase is over */ } else { @@ -3291,7 +3307,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, close_secondarysocket(data, conn); } - if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && + if(!result && (ftp->transfer == PPTRANSFER_BODY) && ftpc->ctl_valid && pp->pending_resp && !premature) { /* * Let's see what the server says about the transfer we just performed, @@ -3314,8 +3330,10 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */ } - if(result) + if(result) { + Curl_safefree(ftp->pathalloc); return result; + } if(ftpc->dont_check && data->req.maxdownload > 0) { /* we have just sent ABOR and there is no reliable way to check if it was @@ -3351,7 +3369,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, if((-1 != data->state.infilesize) && (data->state.infilesize != data->req.writebytecount) && !data->set.crlf && - (ftp->transfer == FTPTRANSFER_BODY)) { + (ftp->transfer == PPTRANSFER_BODY)) { failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", data->req.bytecount, data->state.infilesize); @@ -3383,7 +3401,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, } /* clear these for next connection */ - ftp->transfer = FTPTRANSFER_BODY; + ftp->transfer = PPTRANSFER_BODY; ftpc->dont_check = FALSE; /* Send any post-transfer QUOTE strings? */ @@ -3594,7 +3612,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) *completep = 0; } - if(ftp->transfer <= FTPTRANSFER_INFO) { + if(ftp->transfer <= PPTRANSFER_INFO) { /* a transfer is about to take place, or if not a file name was given so we'll do a SIZE on it later and then we need the right TYPE first */ @@ -3620,7 +3638,8 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) } } else if(data->set.upload) { - result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE); + result = ftp_nb_type(data, conn, data->state.prefer_ascii, + FTP_STOR_TYPE); if(result) return result; @@ -3641,13 +3660,13 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) if(result) ; - else if(data->set.ftp_list_only || !ftpc->file) { + else if(data->state.list_only || !ftpc->file) { /* The specified path ends with a slash, and therefore we think this is a directory that is requested, use LIST. But before that we need to set ASCII transfer mode. */ /* But only if a body transfer was requested. */ - if(ftp->transfer == FTPTRANSFER_BODY) { + if(ftp->transfer == PPTRANSFER_BODY) { result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE); if(result) return result; @@ -3655,7 +3674,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) /* otherwise just fall through */ } else { - result = ftp_nb_type(data, conn, data->set.prefer_ascii, + result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_RETR_TYPE); if(result) return result; @@ -3703,7 +3722,7 @@ CURLcode ftp_perform(struct Curl_easy *data, if(data->set.opt_no_body) { /* requested no body means no transfer... */ struct FTP *ftp = data->req.p.ftp; - ftp->transfer = FTPTRANSFER_INFO; + ftp->transfer = PPTRANSFER_INFO; } *dophase_done = FALSE; /* not done yet */ @@ -4193,7 +4212,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data) ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL pointer */ - if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { + if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) { /* We need a file name when uploading. Return error! */ failf(data, "Uploading to a URL without a file name!"); free(rawPath); @@ -4241,7 +4260,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected) } } - if(ftp->transfer != FTPTRANSFER_BODY) + if(ftp->transfer != PPTRANSFER_BODY) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); else if(!connected) @@ -4345,23 +4364,23 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, switch(command) { case 'A': /* ASCII mode */ - data->set.prefer_ascii = TRUE; + data->state.prefer_ascii = TRUE; break; case 'D': /* directory mode */ - data->set.ftp_list_only = TRUE; + data->state.list_only = TRUE; break; case 'I': /* binary mode */ default: /* switch off ASCII */ - data->set.prefer_ascii = FALSE; + data->state.prefer_ascii = FALSE; break; } } /* get some initial data into the ftp struct */ - ftp->transfer = FTPTRANSFER_BODY; + ftp->transfer = PPTRANSFER_BODY; ftp->downloadsize = 0; conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index d3720b1f10a..716ff381727 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -424,7 +424,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, endptr++; while(ISDIGIT(*endptr)) endptr++; - if(*endptr != 0) { + if(*endptr) { parser->error = CURLE_FTP_BAD_FILE_LIST; goto fail; } @@ -966,7 +966,6 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, else if(c == '\n') { parser->offsets.filename = parser->item_offset; finfo->b_data[finfo->b_used - 1] = 0; - parser->offsets.filename = parser->item_offset; result = ftp_pl_insert_finfo(data, infop); if(result) { parser->error = result; diff --git a/lib/getinfo.c b/lib/getinfo.c index 67ea07d2eee..9091e6139dc 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -94,7 +94,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, { switch(info) { case CURLINFO_EFFECTIVE_URL: - *param_charp = data->change.url?data->change.url:(char *)""; + *param_charp = data->state.url?data->state.url:(char *)""; break; case CURLINFO_EFFECTIVE_METHOD: { const char *m = data->set.str[STRING_CUSTOMREQUEST]; @@ -145,6 +145,10 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, option had been enabled! */ *param_charp = data->info.wouldredirect; break; + case CURLINFO_REFERER: + /* Return the referrer header for this request, or NULL if unset */ + *param_charp = data->state.referer; + break; case CURLINFO_PRIMARY_IP: /* Return the ip address of the most recent (primary) connection */ *param_charp = data->info.conn_primary_ip; @@ -235,7 +239,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, break; #endif case CURLINFO_REDIRECT_COUNT: - *param_longp = data->set.followlocation; + *param_longp = data->state.followlocation; break; case CURLINFO_HTTPAUTH_AVAIL: lptr.to_long = param_longp; diff --git a/lib/gopher.c b/lib/gopher.c index a39cc7e6b40..f61232ff561 100644 --- a/lib/gopher.c +++ b/lib/gopher.c @@ -74,6 +74,7 @@ const struct Curl_handler Curl_handler_gopher = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_GOPHER, /* defport */ CURLPROTO_GOPHER, /* protocol */ CURLPROTO_GOPHER, /* family */ @@ -97,6 +98,7 @@ const struct Curl_handler Curl_handler_gophers = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_GOPHER, /* defport */ CURLPROTO_GOPHERS, /* protocol */ CURLPROTO_GOPHER, /* family */ diff --git a/lib/hash.c b/lib/hash.c index 5d433ad1fbb..12e7aa5f278 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -245,7 +245,7 @@ Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user, struct Curl_hash_element *he = le->ptr; lnext = le->next; /* ask the callback function if we shall remove this entry or not */ - if(comp == NULL || comp(user, he->ptr)) { + if(!comp || comp(user, he->ptr)) { Curl_llist_remove(list, le, (void *) h); --h->size; /* one less entry in the hash now */ } diff --git a/lib/hostcheck.c b/lib/hostcheck.c index 0fef98b2ad7..49dbab34721 100644 --- a/lib/hostcheck.c +++ b/lib/hostcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,7 +81,7 @@ static int hostmatch(char *hostname, char *pattern) pattern[len-1] = 0; pattern_wildcard = strchr(pattern, '*'); - if(pattern_wildcard == NULL) + if(!pattern_wildcard) return strcasecompare(pattern, hostname) ? CURL_HOST_MATCH : CURL_HOST_NOMATCH; @@ -97,7 +97,7 @@ static int hostmatch(char *hostname, char *pattern) match. */ wildcard_enabled = 1; pattern_label_end = strchr(pattern, '.'); - if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL || + if(!pattern_label_end || strchr(pattern_label_end + 1, '.') == NULL || pattern_wildcard > pattern_label_end || strncasecompare(pattern, "xn--", 4)) { wildcard_enabled = 0; @@ -107,7 +107,7 @@ static int hostmatch(char *hostname, char *pattern) CURL_HOST_MATCH : CURL_HOST_NOMATCH; hostname_label_end = strchr(hostname, '.'); - if(hostname_label_end == NULL || + if(!hostname_label_end || !strcasecompare(pattern_label_end, hostname_label_end)) return CURL_HOST_NOMATCH; diff --git a/lib/hostip.c b/lib/hostip.c index 8ba3fe81cee..e0e3cfc2cbd 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -68,6 +68,10 @@ #include "curl_memory.h" #include "memdebug.h" +#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES) +#include +#endif + #if defined(CURLRES_SYNCH) && \ defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) /* alarm-based timeouts can only be used with all the dependencies satisfied */ @@ -269,7 +273,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data, dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); /* No entry found in cache, check if we might have a wildcard entry */ - if(!dns && data->change.wildcard_resolve) { + if(!dns && data->state.wildcard_resolve) { create_hostcache_id("*", port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); @@ -466,10 +470,6 @@ Curl_cache_addr(struct Curl_easy *data, * function is used. You MUST call Curl_resolv_unlock() later (when you're * done using this struct) to decrease the counter again. * - * In debug mode, we specifically test for an interface name "LocalHost" - * and resolve "localhost" instead as a means to permit test cases - * to connect to a local test server with any host name. - * * Return codes: * * CURLRESOLV_ERROR (-1) = error, no pointer @@ -520,13 +520,32 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, if(data->set.resolver_start) { int st; Curl_set_in_callback(data, true); - st = data->set.resolver_start(data->state.async.resolver, NULL, - data->set.resolver_start_client); + st = data->set.resolver_start( +#ifdef USE_CURL_ASYNC + data->state.async.resolver, +#else + NULL, +#endif + NULL, + data->set.resolver_start_client); Curl_set_in_callback(data, false); if(st) return CURLRESOLV_ERROR; } +#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES) + /* + * The automagic conversion from IPv4 literals to IPv6 literals only works + * if the SCDynamicStoreCopyProxies system function gets called first. As + * Curl currently doesn't support system-wide HTTP proxies, we therefore + * don't use any value this function might return. + * + * This function is only available on a macOS and is not needed for + * IPv4-only builds, hence the conditions above. + */ + SCDynamicStoreCopyProxies(NULL); +#endif + #ifndef USE_RESOLVE_ON_IPS /* First check if this is an IPv4 address string */ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) @@ -572,13 +591,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ - addr = Curl_getaddrinfo(data, -#ifdef DEBUGBUILD - (data->set.str[STRING_DEVICE] - && !strcmp(data->set.str[STRING_DEVICE], - "LocalHost"))?"localhost": -#endif - hostname, port, &respwait); + addr = Curl_getaddrinfo(data, hostname, port, &respwait); } } if(!addr) { @@ -625,7 +638,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, * within a signal handler which is nonportable and could lead to problems. */ static -RETSIGTYPE alarmfunc(int sig) +void alarmfunc(int sig) { /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ (void)sig; @@ -872,9 +885,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) int port = 0; /* Default is no wildcard found */ - data->change.wildcard_resolve = false; + data->state.wildcard_resolve = false; - for(hostp = data->change.resolve; hostp; hostp = hostp->next) { + for(hostp = data->state.resolve; hostp; hostp = hostp->next) { char entry_id[MAX_HOSTCACHE_LEN]; if(!hostp->data) continue; @@ -1055,11 +1068,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) if(hostname[0] == '*' && hostname[1] == '\0') { infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n", hostname, port); - data->change.wildcard_resolve = true; + data->state.wildcard_resolve = true; } } } - data->change.resolve = NULL; /* dealt with now */ + data->state.resolve = NULL; /* dealt with now */ return CURLE_OK; } @@ -1102,10 +1115,12 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) CURLcode result; struct connectdata *conn = data->conn; +#ifdef USE_CURL_ASYNC if(data->state.async.dns) { conn->dns_entry = data->state.async.dns; data->state.async.dns = NULL; } +#endif result = Curl_setup_conn(data, protocol_done); @@ -1116,3 +1131,34 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) } return result; } + +/* + * Curl_resolver_error() calls failf() with the appropriate message after a + * resolve error + */ + +#ifdef USE_CURL_ASYNC +CURLcode Curl_resolver_error(struct Curl_easy *data) +{ + const char *host_or_proxy; + CURLcode result; + +#ifndef CURL_DISABLE_PROXY + struct connectdata *conn = data->conn; + if(conn->bits.httpproxy) { + host_or_proxy = "proxy"; + result = CURLE_COULDNT_RESOLVE_PROXY; + } + else +#endif + { + host_or_proxy = "host"; + result = CURLE_COULDNT_RESOLVE_HOST; + } + + failf(data, "Could not resolve %s: %s", host_or_proxy, + data->state.async.hostname); + + return result; +} +#endif /* USE_CURL_ASYNC */ diff --git a/lib/hostip.h b/lib/hostip.h index c495c21e025..d178976aa17 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -136,15 +136,6 @@ void Curl_hostcache_prune(struct Curl_easy *data); /* Return # of addresses in a Curl_addrinfo struct */ int Curl_num_addresses(const struct Curl_addrinfo *addr); -#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) -int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, - GETNAMEINFO_TYPE_ARG2 salen, - char *host, GETNAMEINFO_TYPE_ARG46 hostlen, - char *serv, GETNAMEINFO_TYPE_ARG46 servlen, - GETNAMEINFO_TYPE_ARG7 flags, - int line, const char *source); -#endif - /* IPv4 threadsafe resolve function used for synch and asynch builds */ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); @@ -245,4 +236,5 @@ CURLcode Curl_resolv_check(struct Curl_easy *data, int Curl_resolv_getsock(struct Curl_easy *data, curl_socket_t *socks); +CURLcode Curl_resolver_error(struct Curl_easy *data); #endif /* HEADER_CURL_HOSTIP_H */ diff --git a/lib/hostip6.c b/lib/hostip6.c index 53b3c672239..9791d86468d 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -140,26 +140,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, #ifndef USE_RESOLVE_ON_IPS char addrbuf[128]; #endif - int pf; + int pf = PF_INET; *waitp = 0; /* synchronous response only */ - /* Check if a limited name resolve has been requested */ - switch(data->set.ipver) { - case CURL_IPRESOLVE_V4: - pf = PF_INET; - break; - case CURL_IPRESOLVE_V6: - pf = PF_INET6; - break; - default: + if(Curl_ipv6works(data)) + /* The stack seems to be IPv6-enabled */ pf = PF_UNSPEC; - break; - } - - if((pf != PF_INET) && !Curl_ipv6works(data)) - /* The stack seems to be a non-IPv6 one */ - pf = PF_INET; memset(&hints, 0, sizeof(hints)); hints.ai_family = pf; diff --git a/lib/hsts.c b/lib/hsts.c index 0e7c19cfbd9..ef166f196cd 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -25,7 +25,7 @@ */ #include "curl_setup.h" -#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS) +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include #include "urldata.h" #include "llist.h" @@ -37,6 +37,7 @@ #include "parsedate.h" #include "rand.h" #include "rename.h" +#include "strtoofft.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -46,8 +47,6 @@ #define MAX_HSTS_LINE 4095 #define MAX_HSTS_HOSTLEN 256 #define MAX_HSTS_HOSTLENSTR "256" -#define MAX_HSTS_SUBLEN 4 -#define MAX_HSTS_SUBLENSTR "4" #define MAX_HSTS_DATELEN 64 #define MAX_HSTS_DATELENSTR "64" @@ -60,7 +59,10 @@ static time_t debugtime(void *unused) char *timestr = getenv("CURL_TIME"); (void)unused; if(timestr) { - unsigned long val = strtol(timestr, NULL, 10) + deltatime; + curl_off_t val; + (void)curlx_strtoofft(timestr, NULL, 10, &val); + + val += (curl_off_t)deltatime; return (time_t)val; } return time(NULL); @@ -276,7 +278,7 @@ static CURLcode hsts_push(struct Curl_easy *data, e.namelen = strlen(sts->host); e.includeSubDomains = sts->includeSubDomains; - result = Curl_gmtime(sts->expires, &stamp); + result = Curl_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -296,7 +298,7 @@ static CURLcode hsts_push(struct Curl_easy *data, static CURLcode hsts_out(struct stsentry *sts, FILE *fp) { struct tm stamp; - CURLcode result = Curl_gmtime(sts->expires, &stamp); + CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -441,7 +443,10 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) expires = Curl_getdate_capped(e.expire); else expires = TIME_T_MAX; /* the end of time */ - result = hsts_create(h, e.name, e.includeSubDomains, expires); + result = hsts_create(h, e.name, + /* bitfield to bool conversion: */ + e.includeSubDomains ? TRUE : FALSE, + expires); if(result) return result; } @@ -519,4 +524,4 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) return hsts_pull(data, h); } -#endif /* CURL_DISABLE_HTTP || USE_HSTS */ +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ diff --git a/lib/hsts.h b/lib/hsts.h index ae5db74a245..baa582864a2 100644 --- a/lib/hsts.h +++ b/lib/hsts.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2020, Daniel Stenberg, , et al. + * Copyright (C) 2020 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS) +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include #include "llist.h" @@ -35,7 +35,7 @@ struct stsentry { struct Curl_llist_element node; const char *host; bool includeSubDomains; - time_t expires; /* the timestamp of this entry's expiry */ + curl_off_t expires; /* the timestamp of this entry's expiry */ }; /* The HSTS cache. Needs to be able to tailmatch host names. */ @@ -61,5 +61,5 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, #define Curl_hsts_cleanup(x) #define Curl_hsts_loadcb(x,y) #define Curl_hsts_save(x,y,z) -#endif /* CURL_DISABLE_HTTP || USE_HSTS */ +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ #endif /* HEADER_CURL_HSTS_H */ diff --git a/lib/http.c b/lib/http.c index 6f7f55d078f..628dd73703f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -133,6 +133,7 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -160,6 +161,7 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTPS, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -183,7 +185,7 @@ static CURLcode http_setup_conn(struct Curl_easy *data, Curl_mime_initpart(&http->form, data); data->req.p.http = http; - if(data->set.httpversion == CURL_HTTP_VERSION_3) { + if(data->state.httpwant == CURL_HTTP_VERSION_3) { if(conn->handler->flags & PROTOPT_SSL) /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does the QUIC dance. */ @@ -298,26 +300,27 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy) { size_t size = 0; char *authorization = NULL; - struct connectdata *conn = data->conn; char **userp; const char *user; const char *pwd; CURLcode result; char *out; + /* credentials are unique per transfer for HTTP, do not use the ones for the + connection */ if(proxy) { #ifndef CURL_DISABLE_PROXY userp = &data->state.aptr.proxyuserpwd; - user = conn->http_proxy.user; - pwd = conn->http_proxy.passwd; + user = data->state.aptr.proxyuser; + pwd = data->state.aptr.proxypasswd; #else return CURLE_NOT_BUILT_IN; #endif } else { userp = &data->state.aptr.userpwd; - user = conn->user; - pwd = conn->passwd; + user = data->state.aptr.user; + pwd = data->state.aptr.passwd; } out = aprintf("%s:%s", user, pwd ? pwd : ""); @@ -595,7 +598,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) conn->httpversion > 11) { infof(data, "Forcing HTTP/1.1 for NTLM"); connclose(conn, "Force HTTP/1.1 connection"); - data->set.httpversion = CURL_HTTP_VERSION_1_1; + data->state.httpwant = CURL_HTTP_VERSION_1_1; } } #ifndef CURL_DISABLE_PROXY @@ -621,7 +624,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) we must make sure to free it before allocating a new one. As figured out in bug #2284386 */ Curl_safefree(data->req.newurl); - data->req.newurl = strdup(data->change.url); /* clone URL */ + data->req.newurl = strdup(data->state.url); /* clone URL */ if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; } @@ -634,7 +637,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) we didn't try HEAD or GET */ if((data->state.httpreq != HTTPREQ_GET) && (data->state.httpreq != HTTPREQ_HEAD)) { - data->req.newurl = strdup(data->change.url); /* clone URL */ + data->req.newurl = strdup(data->state.url); /* clone URL */ if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; data->state.authhost.done = TRUE; @@ -709,7 +712,6 @@ output_auth_headers(struct Curl_easy *data, if(authstatus->picked == CURLAUTH_DIGEST) { auth = "Digest"; result = Curl_output_digest(data, - conn, proxy, (const unsigned char *)request, (const unsigned char *)path); @@ -740,7 +742,7 @@ output_auth_headers(struct Curl_easy *data, if(authstatus->picked == CURLAUTH_BEARER) { /* Bearer */ if((!proxy && data->set.str[STRING_BEARER] && - !Curl_checkheaders(data, "Authorization:"))) { + !Curl_checkheaders(data, "Authorization"))) { auth = "Bearer"; result = http_output_bearer(data); if(result) @@ -756,11 +758,14 @@ output_auth_headers(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY infof(data, "%s auth using %s with user '%s'\n", proxy ? "Proxy" : "Server", auth, - proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") : - (conn->user ? conn->user : "")); + proxy ? (data->state.aptr.proxyuser ? + data->state.aptr.proxyuser : "") : + (data->state.aptr.user ? + data->state.aptr.user : "")); #else infof(data, "Server auth using %s with user '%s'\n", - auth, conn->user ? conn->user : ""); + auth, data->state.aptr.user ? + data->state.aptr.user : ""); #endif authstatus->multipass = (!authstatus->done) ? TRUE : FALSE; } @@ -871,13 +876,17 @@ Curl_http_output_auth(struct Curl_easy *data, #else /* when disabled */ CURLcode -Curl_http_output_auth(struct connectdata *conn, +Curl_http_output_auth(struct Curl_easy *data, + struct connectdata *conn, const char *request, + Curl_HttpReq httpreq, const char *path, bool proxytunnel) { + (void)data; (void)conn; (void)request; + (void)httpreq; (void)path; (void)proxytunnel; return CURLE_OK; @@ -890,6 +899,11 @@ Curl_http_output_auth(struct connectdata *conn, * proxy CONNECT loop. */ +static int is_valid_auth_separator(char ch) +{ + return ch == '\0' || ch == ',' || ISSPACE(ch); +} + CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, const char *auth) /* the first non-space */ { @@ -933,7 +947,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, while(*auth) { #ifdef USE_SPNEGO - if(checkprefix("Negotiate", auth)) { + if(checkprefix("Negotiate", auth) && is_valid_auth_separator(auth[9])) { if((authp->avail & CURLAUTH_NEGOTIATE) || Curl_auth_is_spnego_supported()) { *availp |= CURLAUTH_NEGOTIATE; @@ -943,7 +957,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, CURLcode result = Curl_input_negotiate(data, conn, proxy, auth); if(!result) { DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); + data->req.newurl = strdup(data->state.url); if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; data->state.authproblem = FALSE; @@ -959,7 +973,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, #endif #ifdef USE_NTLM /* NTLM support requires the SSL crypto libs */ - if(checkprefix("NTLM", auth)) { + if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) { if((authp->avail & CURLAUTH_NTLM) || (authp->avail & CURLAUTH_NTLM_WB) || Curl_auth_is_ntlm_supported()) { @@ -997,7 +1011,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, else #endif #ifndef CURL_DISABLE_CRYPTO_AUTH - if(checkprefix("Digest", auth)) { + if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) { if((authp->avail & CURLAUTH_DIGEST) != 0) infof(data, "Ignoring duplicate digest auth header.\n"); else if(Curl_auth_is_digest_supported()) { @@ -1019,7 +1033,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, } else #endif - if(checkprefix("Basic", auth)) { + if(checkprefix("Basic", auth) && + is_valid_auth_separator(auth[5])) { *availp |= CURLAUTH_BASIC; authp->avail |= CURLAUTH_BASIC; if(authp->picked == CURLAUTH_BASIC) { @@ -1032,7 +1047,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, } } else - if(checkprefix("Bearer", auth)) { + if(checkprefix("Bearer", auth) && + is_valid_auth_separator(auth[6])) { *availp |= CURLAUTH_BEARER; authp->avail |= CURLAUTH_BEARER; if(authp->picked == CURLAUTH_BEARER) { @@ -1087,6 +1103,14 @@ static bool http_should_fail(struct Curl_easy *data) if(httpcode < 400) return FALSE; + /* + ** A 416 response to a resume request is presumably because the file is + ** already completely downloaded and thus not actually a fail. + */ + if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET && + httpcode == 416) + return FALSE; + /* ** Any code >= 400 that's not 401 or 407 is always ** a terminal error @@ -1152,7 +1176,12 @@ static size_t readmoredata(char *buffer, /* make sure that a HTTP request is never sent away chunked! */ data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; - if(http->postsize <= (curl_off_t)fullsize) { + if(data->set.max_send_speed && + (data->set.max_send_speed < http->postsize)) + /* speed limit */ + fullsize = (size_t)data->set.max_send_speed; + + else if(http->postsize <= (curl_off_t)fullsize) { memcpy(buffer, http->postdata, (size_t)http->postsize); fullsize = (size_t)http->postsize; @@ -1192,7 +1221,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in, counter */ curl_off_t *bytes_written, /* how much of the buffer contains body data */ - size_t included_body_bytes, + curl_off_t included_body_bytes, int socketindex) { ssize_t amount; @@ -1215,10 +1244,10 @@ CURLcode Curl_buffer_send(struct dynbuf *in, ptr = Curl_dyn_ptr(in); size = Curl_dyn_len(in); - headersize = size - included_body_bytes; /* the initial part that isn't body - is header */ + headersize = size - (size_t)included_body_bytes; /* the initial part that + isn't body is header */ - DEBUGASSERT(size > included_body_bytes); + DEBUGASSERT(size > (size_t)included_body_bytes); result = Curl_convert_to_network(data, ptr, headersize); /* Curl_convert_to_network calls failf if unsuccessful */ @@ -1234,13 +1263,17 @@ CURLcode Curl_buffer_send(struct dynbuf *in, #endif ) && conn->httpversion != 20) { - /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk - when we speak HTTPS, as if only a fraction of it is sent now, this data - needs to fit into the normal read-callback buffer later on and that - buffer is using this size. + /* Make sure this doesn't send more body bytes than what the max send + speed says. The request bytes do not count to the max speed. */ - - sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE); + if(data->set.max_send_speed && + (included_body_bytes > data->set.max_send_speed)) { + curl_off_t overflow = included_body_bytes - data->set.max_send_speed; + DEBUGASSERT((size_t)overflow < size); + sendsize = size - (size_t)overflow; + } + else + sendsize = size; /* OpenSSL is very picky and we must send the SAME buffer pointer to the library when we attempt to re-send this buffer. Sending the same data @@ -1254,6 +1287,14 @@ CURLcode Curl_buffer_send(struct dynbuf *in, Curl_dyn_free(in); return result; } + /* We never send more than upload_buffer_size bytes in one single chunk + when we speak HTTPS, as if only a fraction of it is sent now, this data + needs to fit into the normal read-callback buffer later on and that + buffer is using this size. + */ + if(sendsize > (size_t)data->set.upload_buffer_size) + sendsize = (size_t)data->set.upload_buffer_size; + memcpy(data->state.ulbuf, ptr, sendsize); ptr = data->state.ulbuf; } @@ -1272,7 +1313,19 @@ CURLcode Curl_buffer_send(struct dynbuf *in, } else #endif - sendsize = size; + { + /* Make sure this doesn't send more body bytes than what the max send + speed says. The request bytes do not count to the max speed. + */ + if(data->set.max_send_speed && + (included_body_bytes > data->set.max_send_speed)) { + curl_off_t overflow = included_body_bytes - data->set.max_send_speed; + DEBUGASSERT((size_t)overflow < size); + sendsize = size - (size_t)overflow; + } + else + sendsize = size; + } } result = Curl_write(data, sockfd, ptr, sendsize, &amount); @@ -1500,7 +1553,7 @@ static CURLcode add_haproxy_protocol_header(struct Curl_easy *data) msnprintf(proxy_header, sizeof(proxy_header), - "PROXY %s %s %s %li %li\r\n", + "PROXY %s %s %s %i %i\r\n", tcp_version, data->info.conn_local_ip, data->info.conn_primary_ip, @@ -1548,7 +1601,7 @@ static int https_getsock(struct Curl_easy *data, { (void)data; if(conn->handler->flags & PROTOPT_SSL) - return Curl_ssl_getsock(conn, socks); + return Curl_ssl->getsock(conn, socks); return GETSOCK_BLANK; } #endif /* USE_SSL */ @@ -1621,11 +1674,11 @@ static bool use_http_1_1plus(const struct Curl_easy *data, { if((data->state.httpversion == 10) || (conn->httpversion == 10)) return FALSE; - if((data->set.httpversion == CURL_HTTP_VERSION_1_0) && + if((data->state.httpwant == CURL_HTTP_VERSION_1_0) && (conn->httpversion <= 10)) return FALSE; - return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) || - (data->set.httpversion >= CURL_HTTP_VERSION_1_1)); + return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) || + (data->state.httpwant >= CURL_HTTP_VERSION_1_1)); } #ifndef USE_HYPER @@ -1633,7 +1686,7 @@ static const char *get_http_string(const struct Curl_easy *data, const struct connectdata *conn) { #ifdef ENABLE_QUIC - if((data->set.httpversion == CURL_HTTP_VERSION_3) || + if((data->state.httpwant == CURL_HTTP_VERSION_3) || (conn->httpversion == 30)) return "3"; #endif @@ -1698,7 +1751,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, if( #ifdef CURL_DO_LINEEND_CONV - (handle->set.prefer_ascii) || + (handle->state.prefer_ascii) || #endif (handle->set.crlf)) { /* \n will become \r\n later on */ @@ -1960,10 +2013,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, } #else /* disabled */ -CURLcode Curl_add_timecondition(const struct connectdata *conn, +CURLcode Curl_add_timecondition(struct Curl_easy *data, struct dynbuf *req) { - (void)conn; + (void)data; (void)req; return CURLE_OK; } @@ -2174,7 +2227,7 @@ CURLcode Curl_http_target(struct Curl_easy *data, /* Extract the URL to use in the request. Store in STRING_TEMP_URL for clean-up reasons if the function returns before the free() further down. */ - uc = curl_url_get(h, CURLUPART_URL, &url, 0); + uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT); if(uc) { curl_url_cleanup(h); return CURLE_OUT_OF_MEMORY; @@ -2205,7 +2258,7 @@ CURLcode Curl_http_target(struct Curl_easy *data, } if(!type) { result = Curl_dyn_addf(r, ";type=%c", - data->set.prefer_ascii ? 'a' : 'i'); + data->state.prefer_ascii ? 'a' : 'i'); if(result) return result; } @@ -2614,8 +2667,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, } } /* issue the request */ - result = Curl_buffer_send(r, data, &data->info.request_size, - (size_t)included_body, FIRSTSOCKET); + result = Curl_buffer_send(r, data, &data->info.request_size, included_body, + FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP POST request"); @@ -2946,7 +2999,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) default: /* Check if user wants to use HTTP/2 with clear TCP*/ #ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { + if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { #ifndef CURL_DISABLE_PROXY if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { /* We don't support HTTP/2 proxies yet. Also it's debatable @@ -3002,8 +3055,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) } Curl_safefree(data->state.aptr.ref); - if(data->change.referer && !Curl_checkheaders(data, "Referer")) { - data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(data->state.referer && !Curl_checkheaders(data, "Referer")) { + data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer); if(!data->state.aptr.ref) return CURLE_OUT_OF_MEMORY; } @@ -3016,10 +3069,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(!data->state.aptr.accept_encoding) return CURLE_OUT_OF_MEMORY; } - else { + else Curl_safefree(data->state.aptr.accept_encoding); - data->state.aptr.accept_encoding = NULL; - } #ifdef HAVE_LIBZ /* we only consider transfer-encoding magic if libz support is built-in */ @@ -3071,6 +3122,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) /* initialize a dynamic send-buffer */ Curl_dyn_init(&req, DYN_HTTP_REQUEST); + /* make sure the header buffer is reset - if there are leftovers from a + previous transfer */ + Curl_dyn_reset(&data->state.headerb); + /* add the main request stuff */ /* GET/HEAD/POST/PUT */ result = Curl_dyn_addf(&req, "%s ", request); @@ -3124,7 +3179,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) *data->set.str[STRING_ENCODING] && data->state.aptr.accept_encoding)? data->state.aptr.accept_encoding:"", - (data->change.referer && data->state.aptr.ref)? + (data->state.referer && data->state.aptr.ref)? data->state.aptr.ref:"" /* Referer: */, #ifndef CURL_DISABLE_PROXY (conn->bits.httpproxy && @@ -3152,10 +3207,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(!(conn->handler->flags&PROTOPT_SSL) && conn->httpversion != 20 && - (data->set.httpversion == CURL_HTTP_VERSION_2)) { + (data->state.httpwant == CURL_HTTP_VERSION_2)) { /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done over SSL */ - result = Curl_http2_request_upgrade(&req, conn); + result = Curl_http2_request_upgrade(&req, data); if(result) { Curl_dyn_free(&req); return result; @@ -3333,7 +3388,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, if(!k->http_bodyless && !data->set.ignorecl && checkprefix("Content-Length:", headp)) { curl_off_t contentlength; - CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength); + CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"), + NULL, 10, &contentlength); if(offt == CURL_OFFT_OK) { if(data->set.max_filesize && @@ -3432,7 +3488,9 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * of chunks, and a chunk-data set to zero signals the * end-of-chunks. */ - result = Curl_build_unencoding_stack(data, headp + 18, TRUE); + result = Curl_build_unencoding_stack(data, + headp + strlen("Transfer-Encoding:"), + TRUE); if(result) return result; } @@ -3445,17 +3503,20 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * 2616). zlib cannot handle compress. However, errors are * handled further down when the response body is processed */ - result = Curl_build_unencoding_stack(data, headp + 17, FALSE); + result = Curl_build_unencoding_stack(data, + headp + strlen("Content-Encoding:"), + FALSE); if(result) return result; } else if(checkprefix("Retry-After:", headp)) { /* Retry-After = HTTP-date / delay-seconds */ curl_off_t retry_after = 0; /* zero for unknown or "now" */ - time_t date = Curl_getdate_capped(&headp[12]); + time_t date = Curl_getdate_capped(headp + strlen("Retry-After:")); if(-1 == date) { /* not a date, try it as a decimal number */ - (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after); + (void)curlx_strtoofft(headp + strlen("Retry-After:"), + NULL, 10, &retry_after); } else /* convert date to number of seconds into the future */ @@ -3474,7 +3535,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, The forth means the requested range was unsatisfied. */ - char *ptr = headp + 14; + char *ptr = headp + strlen("Content-Range:"); /* Move forward until first digit or asterisk */ while(*ptr && !ISDIGIT(*ptr) && *ptr != '*') @@ -3497,7 +3558,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); Curl_cookie_add(data, - data->cookies, TRUE, FALSE, headp + 11, + data->cookies, TRUE, FALSE, + headp + strlen("Set-Cookie:"), /* If there is a custom-set Host: name, use it here, or else use real peer host name. */ data->state.aptr.cookiehost? @@ -3532,7 +3594,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, return result; } #ifdef USE_SPNEGO - else if(checkprefix("Persistent-Auth", headp)) { + else if(checkprefix("Persistent-Auth:", headp)) { struct negotiatedata *negdata = &conn->negotiate; struct auth *authp = &data->state.authhost; if(authp->picked == CURLAUTH_NEGOTIATE) { @@ -3576,13 +3638,13 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, } } -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS /* If enabled, the header is incoming and this is over HTTPS */ else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) && (conn->handler->flags & PROTOPT_SSL)) { CURLcode check = Curl_hsts_parse(data->hsts, data->state.up.hostname, - &headp[ sizeof("Strict-Transport-Security:") -1 ]); + headp + strlen("Strict-Transport-Security:")); if(check) infof(data, "Illegal STS header skipped\n"); #ifdef DEBUGBUILD @@ -3606,7 +3668,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, /* the ALPN of the current request */ enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; result = Curl_altsvc_parse(data, data->asi, - &headp[ strlen("Alt-Svc:") ], + headp + strlen("Alt-Svc:"), id, conn->host.name, curlx_uitous(conn->remote_port)); if(result) @@ -3995,7 +4057,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, infof(data, "Got 417 while waiting for a 100\n"); data->state.disableexpect = TRUE; DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); + data->req.newurl = strdup(data->state.url); Curl_done_sending(data, k); } else if(data->set.http_keep_sending_on_error) { @@ -4144,10 +4206,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, */ char separator; char twoorthree[2]; + int httpversion = 0; nc = sscanf(HEADER1, " HTTP/%1d.%1d%c%3d", &httpversion_major, - &conn->httpversion, + &httpversion, &separator, &k->httpcode); @@ -4159,7 +4222,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, } if((nc == 4) && (' ' == separator)) { - conn->httpversion += 10 * httpversion_major; + httpversion += 10 * httpversion_major; + switch(httpversion) { + case 10: + case 11: +#if defined(USE_NGHTTP2) || defined(USE_HYPER) + case 20: +#endif +#if defined(ENABLE_QUIC) + case 30: +#endif + conn->httpversion = (unsigned char)httpversion; + break; + default: + failf(data, "Unsupported HTTP version (%u.%d) in response", + httpversion/10, httpversion%10); + return CURLE_UNSUPPORTED_PROTOCOL; + } if(k->upgr101 == UPGR101_RECEIVED) { /* supposedly upgraded to http2 now */ @@ -4200,14 +4279,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, } else if(conn->handler->protocol & CURLPROTO_RTSP) { char separator; + int rtspversion; nc = sscanf(HEADER1, " RTSP/%1d.%1d%c%3d", &rtspversion_major, - &conn->rtspversion, + &rtspversion, &separator, &k->httpcode); if((nc == 4) && (' ' == separator)) { - conn->rtspversion += 10 * rtspversion_major; conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ } else { diff --git a/lib/http.h b/lib/http.h index 28f9341f678..2a3834ae11c 100644 --- a/lib/http.h +++ b/lib/http.h @@ -58,7 +58,7 @@ char *Curl_checkProxyheaders(struct Curl_easy *data, CURLcode Curl_buffer_send(struct dynbuf *in, struct Curl_easy *data, curl_off_t *bytes_written, - size_t included_body_bytes, + curl_off_t included_body_bytes, int socketindex); #else #define Curl_buffer_send(a,b,c,d,e) CURLE_OK @@ -184,8 +184,7 @@ struct HTTP { enum { HTTPSEND_NADA, /* init */ HTTPSEND_REQUEST, /* sending a request */ - HTTPSEND_BODY, /* sending body */ - HTTPSEND_LAST /* never use this */ + HTTPSEND_BODY /* sending body */ } sending; #ifndef CURL_DISABLE_HTTP @@ -211,6 +210,7 @@ struct HTTP { char **push_headers; /* allocated array */ size_t push_headers_used; /* number of entries filled in */ size_t push_headers_alloc; /* number of entries allocated */ + uint32_t error; /* HTTP/2 stream error code */ #endif #if defined(USE_NGHTTP2) || defined(USE_NGHTTP3) bool closed; /* TRUE on HTTP2 stream close */ @@ -251,9 +251,16 @@ struct h2settings { struct http_conn { #ifdef USE_NGHTTP2 #define H2_BINSETTINGS_LEN 80 - nghttp2_session *h2; uint8_t binsettings[H2_BINSETTINGS_LEN]; size_t binlen; /* length of the binsettings data */ + + /* We associate the connnectdata struct with the connection, but we need to + make sure we can identify the current "driving" transfer. This is a + work-around for the lack of nghttp2_session_set_user_data() in older + nghttp2 versions that we want to support. (Added in 1.31.0) */ + struct Curl_easy *trnsfr; + + nghttp2_session *h2; Curl_send *send_underlying; /* underlying send Curl_send callback */ Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */ char *inbuf; /* buffer to receive data from underlying socket */ @@ -274,7 +281,6 @@ struct http_conn { /* list of settings that will be sent */ nghttp2_settings_entry local_settings[3]; size_t local_settings_num; - uint32_t error_code; /* HTTP/2 error code */ #else int unused; /* prevent a compiler warning */ #endif diff --git a/lib/http2.c b/lib/http2.c index be4c712420e..f194c18b230 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -211,6 +211,24 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn) return dead; } +/* + * Set the transfer that is currently using this HTTP/2 connection. + */ +static void set_transfer(struct http_conn *c, + struct Curl_easy *data) +{ + c->trnsfr = data; +} + +/* + * Get the transfer that is currently using this HTTP/2 connection. + */ +static struct Curl_easy *get_transfer(struct http_conn *c) +{ + DEBUGASSERT(c && c->trnsfr); + return c->trnsfr; +} + static unsigned int http2_conncheck(struct Curl_easy *data, struct connectdata *conn, unsigned int checks_to_perform) @@ -247,6 +265,7 @@ static unsigned int http2_conncheck(struct Curl_easy *data, } if(send_frames) { + set_transfer(c, data); /* set the transfer */ rc = nghttp2_session_send(c->h2); if(rc) failf(data, "nghttp2_session_send() failed: %s(%d)", @@ -269,6 +288,7 @@ void Curl_http2_setup_req(struct Curl_easy *data) http->mem = NULL; http->len = 0; http->memlen = 0; + http->error = NGHTTP2_NO_ERROR; } /* called from http_setup_conn */ @@ -276,7 +296,6 @@ void Curl_http2_setup_conn(struct connectdata *conn) { conn->proto.httpc.settings.max_concurrent_streams = DEFAULT_MAX_CONCURRENT_STREAMS; - conn->proto.httpc.error_code = NGHTTP2_NO_ERROR; } /* @@ -300,6 +319,7 @@ static const struct Curl_handler Curl_handler_http2 = { http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ http2_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -322,6 +342,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = { http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ http2_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -349,6 +370,7 @@ static ssize_t send_callback(nghttp2_session *h2, { struct connectdata *conn = (struct connectdata *)userp; struct http_conn *c = &conn->proto.httpc; + struct Curl_easy *data = get_transfer(c); ssize_t written; CURLcode result = CURLE_OK; @@ -359,7 +381,7 @@ static ssize_t send_callback(nghttp2_session *h2, /* called before setup properly! */ return NGHTTP2_ERR_CALLBACK_FAILURE; - written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET, + written = ((Curl_send*)c->send_underlying)(data, FIRSTSOCKET, mem, length, &result); if(result == CURLE_AGAIN) { @@ -367,7 +389,7 @@ static ssize_t send_callback(nghttp2_session *h2, } if(written == -1) { - failf(conn->data, "Failed sending HTTP2 data"); + failf(data, "Failed sending HTTP2 data"); return NGHTTP2_ERR_CALLBACK_FAILURE; } @@ -479,38 +501,48 @@ static int set_transfer_url(struct Curl_easy *data, const char *v; CURLU *u = curl_url(); CURLUcode uc; - char *url; + char *url = NULL; + int rc = 0; v = curl_pushheader_byname(hp, ":scheme"); if(v) { uc = curl_url_set(u, CURLUPART_SCHEME, v, 0); - if(uc) - return 1; + if(uc) { + rc = 1; + goto fail; + } } v = curl_pushheader_byname(hp, ":authority"); if(v) { uc = curl_url_set(u, CURLUPART_HOST, v, 0); - if(uc) - return 2; + if(uc) { + rc = 2; + goto fail; + } } v = curl_pushheader_byname(hp, ":path"); if(v) { uc = curl_url_set(u, CURLUPART_PATH, v, 0); - if(uc) - return 3; + if(uc) { + rc = 3; + goto fail; + } } uc = curl_url_get(u, CURLUPART_URL, &url, 0); if(uc) - return 4; + rc = 4; + fail: curl_url_cleanup(u); + if(rc) + return rc; - if(data->change.url_alloc) - free(data->change.url); - data->change.url_alloc = TRUE; - data->change.url = url; + if(data->state.url_alloc) + free(data->state.url); + data->state.url_alloc = TRUE; + data->state.url = url; return 0; } @@ -551,6 +583,7 @@ static int push_promise(struct Curl_easy *data, rv = set_transfer_url(newhandle, &heads); if(rv) { + (void)Curl_close(&newhandle); rv = CURL_PUSH_DENY; goto fail; } @@ -633,6 +666,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, struct http_conn *httpc = &conn->proto.httpc; struct Curl_easy *data_s = NULL; struct HTTP *stream = NULL; + struct Curl_easy *data = get_transfer(httpc); int rv; size_t left, ncopy; int32_t stream_id = frame->hd.stream_id; @@ -642,30 +676,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, /* stream ID zero is for connection-oriented stuff */ if(frame->hd.type == NGHTTP2_SETTINGS) { uint32_t max_conn = httpc->settings.max_concurrent_streams; - H2BUGF(infof(conn->data, "Got SETTINGS\n")); + H2BUGF(infof(data, "Got SETTINGS\n")); httpc->settings.max_concurrent_streams = nghttp2_session_get_remote_settings( session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); httpc->settings.enable_push = nghttp2_session_get_remote_settings( session, NGHTTP2_SETTINGS_ENABLE_PUSH); - H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n", + H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d\n", httpc->settings.max_concurrent_streams)); - H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n", + H2BUGF(infof(data, "ENABLE_PUSH == %s\n", httpc->settings.enable_push?"TRUE":"false")); if(max_conn != httpc->settings.max_concurrent_streams) { /* only signal change if the value actually changed */ - infof(conn->data, + infof(data, "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", httpc->settings.max_concurrent_streams); - multi_connchanged(conn->data->multi); + multi_connchanged(data->multi); } } return 0; } data_s = nghttp2_session_get_stream_user_data(session, stream_id); if(!data_s) { - H2BUGF(infof(conn->data, + H2BUGF(infof(data, "No Curl_easy associated with stream: %x\n", stream_id)); return 0; @@ -733,14 +767,9 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, stream->memlen += ncopy; drain_this(data_s, httpc); - { - /* get the pointer from userp again since it was re-assigned above */ - struct connectdata *conn_s = (struct connectdata *)userp; - - /* if we receive data for another handle, wake that up */ - if(conn_s->data != data_s) - Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - } + /* if we receive data for another handle, wake that up */ + if(get_transfer(httpc) != data_s) + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); break; case NGHTTP2_PUSH_PROMISE: rv = push_promise(data_s, conn, &frame->push_promise); @@ -768,15 +797,15 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, int32_t stream_id, - const uint8_t *data, size_t len, void *userp) + const uint8_t *mem, size_t len, void *userp) { struct HTTP *stream; struct Curl_easy *data_s; size_t nread; struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *httpc = &conn->proto.httpc; (void)session; (void)flags; - (void)data; DEBUGASSERT(stream_id); /* should never be a zero stream ID here */ @@ -792,7 +821,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, return NGHTTP2_ERR_CALLBACK_FAILURE; nread = CURLMIN(stream->len, len); - memcpy(&stream->mem[stream->memlen], data, nread); + memcpy(&stream->mem[stream->memlen], mem, nread); stream->len -= nread; stream->memlen += nread; @@ -800,7 +829,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, drain_this(data_s, &conn->proto.httpc); /* if we receive data for another handle, wake that up */ - if(conn->data != data_s) + if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); H2BUGF(infof(data_s, "%zu data received for stream %u " @@ -810,7 +839,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, stream->memlen)); if(nread < len) { - stream->pausedata = data + nread; + stream->pausedata = mem + nread; stream->pauselen = len - nread; H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" ", stream %u\n", @@ -822,7 +851,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, /* pause execution of nghttp2 if we received data for another handle in order to process them first. */ - if(conn->data != data_s) { + if(get_transfer(httpc) != data_s) { data_s->conn->proto.httpc.pause_stream_id = stream_id; return NGHTTP2_ERR_PAUSE; @@ -861,7 +890,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, httpc = &conn->proto.httpc; drain_this(data_s, httpc); Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - httpc->error_code = error_code; + stream->error = error_code; /* remove the entry from the hash as the stream is now gone */ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0); @@ -944,6 +973,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, struct Curl_easy *data_s; int32_t stream_id = frame->hd.stream_id; struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *httpc = &conn->proto.httpc; CURLcode result; (void)flags; @@ -1049,7 +1079,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(result) return NGHTTP2_ERR_CALLBACK_FAILURE; /* if we receive data for another handle, wake that up */ - if(conn->data != data_s) + if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n", @@ -1073,7 +1103,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(result) return NGHTTP2_ERR_CALLBACK_FAILURE; /* if we receive data for another handle, wake that up */ - if(conn->data != data_s) + if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, @@ -1138,27 +1168,27 @@ static int error_callback(nghttp2_session *session, size_t len, void *userp) { - struct connectdata *conn = (struct connectdata *)userp; (void)session; - infof(conn->data, "http2 error: %.*s\n", len, msg); + (void)msg; + (void)len; + (void)userp; return 0; } #endif -static void populate_settings(struct connectdata *conn, +static void populate_settings(struct Curl_easy *data, struct http_conn *httpc) { nghttp2_settings_entry *iv = httpc->local_settings; - DEBUGASSERT(conn->data); iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi); + iv[0].value = Curl_multi_max_concurrent_streams(data->multi); iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; iv[1].value = HTTP2_HUGE_WINDOW_SIZE; iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; - iv[2].value = conn->data->multi->push_cb != NULL; + iv[2].value = data->multi->push_cb != NULL; httpc->local_settings_num = 3; } @@ -1187,6 +1217,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) if(premature) { /* RST_STREAM */ + set_transfer(httpc, data); /* set the transfer */ if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id, NGHTTP2_STREAM_CLOSED)) (void)nghttp2_session_send(httpc->h2); @@ -1209,6 +1240,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) http->stream_id); DEBUGASSERT(0); } + set_transfer(httpc, NULL); http->stream_id = 0; } } @@ -1223,7 +1255,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn) nghttp2_session_callbacks *callbacks; conn->proto.httpc.inbuf = malloc(H2_BUFSIZE); - if(conn->proto.httpc.inbuf == NULL) + if(!conn->proto.httpc.inbuf) return CURLE_OUT_OF_MEMORY; rc = nghttp2_session_callbacks_new(&callbacks); @@ -1269,18 +1301,18 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn) * Append headers to ask for a HTTP1.1 to HTTP2 upgrade. */ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, - struct connectdata *conn) + struct Curl_easy *data) { CURLcode result; ssize_t binlen; char *base64; size_t blen; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SingleRequest *k = &data->req; uint8_t *binsettings = conn->proto.httpc.binsettings; struct http_conn *httpc = &conn->proto.httpc; - populate_settings(conn, httpc); + populate_settings(data, httpc); /* this returns number of bytes it wrote */ binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, @@ -1338,6 +1370,7 @@ static int h2_process_pending_input(struct Curl_easy *data, nread = httpc->inbuflen - httpc->nread_inbuf; inbuf = httpc->inbuf + httpc->nread_inbuf; + set_transfer(httpc, data); /* set the transfer */ rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); if(rv < 0) { failf(data, @@ -1363,7 +1396,7 @@ static int h2_process_pending_input(struct Curl_easy *data, } rv = h2_session_send(data, httpc->h2); - if(rv != 0) { + if(rv) { *err = CURLE_SEND_ERROR; return -1; } @@ -1377,9 +1410,10 @@ static int h2_process_pending_input(struct Curl_easy *data, } if(should_close_session(httpc)) { + struct HTTP *stream = data->req.p.http; H2BUGF(infof(data, "h2_process_pending_input: nothing to do in this session\n")); - if(httpc->error_code) + if(stream->error) *err = CURLE_HTTP2; else { /* not an error per se, but should still close the connection */ @@ -1402,9 +1436,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data, if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) { /* make sure this is only attempted for HTTP/2 transfers */ - struct HTTP *stream = data->req.p.http; - struct http_conn *httpc = &conn->proto.httpc; nghttp2_session *h2 = httpc->h2; @@ -1426,13 +1458,15 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data, H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data)); - /* re-set KEEP_SEND to make sure we are called again */ - k->keepon |= KEEP_SEND; - /* and attempt to send the pending frames */ rv = h2_session_send(data, h2); - if(rv != 0) + if(rv) result = CURLE_SEND_ERROR; + + if(nghttp2_session_want_write(h2)) { + /* re-set KEEP_SEND to make sure we are called again */ + k->keepon |= KEEP_SEND; + } } } return result; @@ -1460,7 +1494,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ stream->closed = FALSE; - if(httpc->error_code == NGHTTP2_REFUSED_STREAM) { + if(stream->error == NGHTTP2_REFUSED_STREAM) { H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", stream->stream_id)); connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ @@ -1468,10 +1502,10 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ return -1; } - else if(httpc->error_code != NGHTTP2_NO_ERROR) { + else if(stream->error != NGHTTP2_NO_ERROR) { failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", - stream->stream_id, nghttp2_http2_strerror(httpc->error_code), - httpc->error_code); + stream->stream_id, nghttp2_http2_strerror(stream->error), + stream->error); *err = CURLE_HTTP2_STREAM; return -1; } @@ -1542,6 +1576,8 @@ static int h2_session_send(struct Curl_easy *data, nghttp2_session *h2) { struct HTTP *stream = data->req.p.http; + struct http_conn *httpc = &data->conn->proto.httpc; + set_transfer(httpc, data); if((data->set.stream_weight != data->state.stream_weight) || (data->set.stream_depends_e != data->state.stream_depends_e) || (data->set.stream_depends_on != data->state.stream_depends_on) ) { @@ -1585,6 +1621,10 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } + if(stream->closed) + /* closed overrides paused */ + return http2_handle_stream_close(conn, data, stream, err); + /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ stream->upload_mem = NULL; @@ -1707,6 +1747,17 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, } if(nread == 0) { + if(!stream->closed) { + /* This will happen when the server or proxy server is SIGKILLed + during data transfer. We should emit an error since our data + received may be incomplete. */ + failf(data, "HTTP/2 stream %d was not closed cleanly before" + " end of the underlying stream", + stream->stream_id); + *err = CURLE_HTTP2_STREAM; + return -1; + } + H2BUGF(infof(data, "end of stream\n")); *err = CURLE_OK; return 0; @@ -1725,7 +1776,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, nread)); } - if(h2_process_pending_input(data, httpc, err) != 0) + if(h2_process_pending_input(data, httpc, err)) return -1; } if(stream->memlen) { @@ -1750,7 +1801,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return retlen; } if(stream->closed) - return 0; + return http2_handle_stream_close(conn, data, stream, err); *err = CURLE_AGAIN; H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", stream->stream_id)); @@ -1925,7 +1976,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, more space. */ nheader += 1; nva = malloc(sizeof(nghttp2_nv) * nheader); - if(nva == NULL) { + if(!nva) { *err = CURLE_OUT_OF_MEMORY; return -1; } @@ -2048,7 +2099,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, } /* :authority must come before non-pseudo header fields */ - if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + if(authority_idx && authority_idx != AUTHORITY_DST_IDX) { nghttp2_nv authority = nva[authority_idx]; for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { nva[i] = nva[i - 1]; @@ -2117,10 +2168,8 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, stream_id, (void *)data); stream->stream_id = stream_id; - /* this does not call h2_session_send() since there can not have been any - * priority update since the nghttp2_submit_request() call above */ - rv = nghttp2_session_send(h2); - if(rv != 0) { + rv = h2_session_send(data, h2); + if(rv) { H2BUGF(infof(data, "http2_send() nghttp2_session_send error (%s)%d\n", nghttp2_strerror(rv), rv)); @@ -2226,10 +2275,10 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, /* stream 1 is opened implicitly on upgrade */ stream->stream_id = 1; /* queue SETTINGS frame (again) */ - rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, - httpc->binlen, NULL); - if(rv != 0) { - failf(data, "nghttp2_session_upgrade() failed: %s(%d)", + rv = nghttp2_session_upgrade2(httpc->h2, httpc->binsettings, httpc->binlen, + data->state.httpreq == HTTPREQ_HEAD, NULL); + if(rv) { + failf(data, "nghttp2_session_upgrade2() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; } @@ -2244,14 +2293,14 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, } } else { - populate_settings(conn, httpc); + populate_settings(data, httpc); /* stream ID is unknown at this point */ stream->stream_id = -1; rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, httpc->local_settings, httpc->local_settings_num); - if(rv != 0) { + if(rv) { failf(data, "nghttp2_submit_settings() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; @@ -2260,7 +2309,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, HTTP2_HUGE_WINDOW_SIZE); - if(rv != 0) { + if(rv) { failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", nghttp2_strerror(rv), rv); return CURLE_HTTP2; @@ -2288,8 +2337,15 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, DEBUGASSERT(httpc->nread_inbuf == 0); - if(-1 == h2_process_pending_input(data, httpc, &result)) - return CURLE_HTTP2; + /* Good enough to call it an end once the remaining payload is copied to the + * connection buffer. + * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately + * following the protocol switch other than waiting for the client-side + * connection preface. If h2_process_pending_input is invoked here to parse + * the remaining payload, stream 1 would be marked as closed too early and + * thus ignored in http2_recv (following 252790c53). + * The logic in lib/http.c and lib/transfer.c guarantees a following + * http2_recv would be invoked very soon. */ return CURLE_OK; } @@ -2299,7 +2355,8 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) DEBUGASSERT(data); DEBUGASSERT(data->conn); /* if it isn't HTTP/2, we're done */ - if(!data->conn->proto.httpc.h2) + if(!(data->conn->handler->protocol & PROTO_FAMILY_HTTP) || + !data->conn->proto.httpc.h2) return CURLE_OK; #ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE else { @@ -2423,10 +2480,10 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data) /* Only call this function for a transfer that already got a HTTP/2 CURLE_HTTP2_STREAM error! */ -bool Curl_h2_http_1_1_error(struct connectdata *conn) +bool Curl_h2_http_1_1_error(struct Curl_easy *data) { - struct http_conn *httpc = &conn->proto.httpc; - return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED); + struct HTTP *stream = data->req.p.http; + return (stream->error == NGHTTP2_HTTP_1_1_REQUIRED); } #else /* !USE_NGHTTP2 */ diff --git a/lib/http2.h b/lib/http2.h index 119e584a8bd..21e2c086a38 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -29,7 +29,7 @@ /* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting from the peer */ -#define DEFAULT_MAX_CONCURRENT_STREAMS 13 +#define DEFAULT_MAX_CONCURRENT_STREAMS 100 /* * Store nghttp2 version info in this buffer, Prefix with a space. Return @@ -43,7 +43,7 @@ CURLcode Curl_http2_init(struct connectdata *conn); void Curl_http2_init_state(struct UrlState *state); void Curl_http2_init_userset(struct UserDefined *set); CURLcode Curl_http2_request_upgrade(struct dynbuf *req, - struct connectdata *conn); + struct Curl_easy *data); CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn); CURLcode Curl_http2_switched(struct Curl_easy *data, const char *ptr, size_t nread); @@ -62,7 +62,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data); CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause); /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ -bool Curl_h2_http_1_1_error(struct connectdata *conn); +bool Curl_h2_http_1_1_error(struct Curl_easy *data); #else /* USE_NGHTTP2 */ #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL diff --git a/lib/http_aws_sigv4.c b/lib/http_aws_sigv4.c index 8fd1c77e606..a04b46a3514 100644 --- a/lib/http_aws_sigv4.c +++ b/lib/http_aws_sigv4.c @@ -99,8 +99,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) char *request_type = NULL; char *credential_scope = NULL; char *str_to_sign = NULL; - const char *user = conn->user ? conn->user : ""; - const char *passwd = conn->passwd ? conn->passwd : ""; + const char *user = data->state.aptr.user ? data->state.aptr.user : ""; + const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : ""; char *secret = NULL; unsigned char tmp_sign0[32] = {0}; unsigned char tmp_sign1[32] = {0}; diff --git a/lib/http_digest.c b/lib/http_digest.c index 596b215db64..049b232e014 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -56,7 +56,7 @@ CURLcode Curl_input_digest(struct Curl_easy *data, digest = &data->state.digest; } - if(!checkprefix("Digest", header)) + if(!checkprefix("Digest", header) || !ISSPACE(header[6])) return CURLE_BAD_CONTENT_ENCODING; header += strlen("Digest"); @@ -67,7 +67,6 @@ CURLcode Curl_input_digest(struct Curl_easy *data, } CURLcode Curl_output_digest(struct Curl_easy *data, - struct connectdata *conn, bool proxy, const unsigned char *request, const unsigned char *uripath) @@ -97,16 +96,16 @@ CURLcode Curl_output_digest(struct Curl_easy *data, #else digest = &data->state.proxydigest; allocuserpwd = &data->state.aptr.proxyuserpwd; - userp = conn->http_proxy.user; - passwdp = conn->http_proxy.passwd; + userp = data->state.aptr.proxyuser; + passwdp = data->state.aptr.proxypasswd; authp = &data->state.authproxy; #endif } else { digest = &data->state.digest; allocuserpwd = &data->state.aptr.userpwd; - userp = conn->user; - passwdp = conn->passwd; + userp = data->state.aptr.user; + passwdp = data->state.aptr.passwd; authp = &data->state.authhost; } diff --git a/lib/http_digest.h b/lib/http_digest.h index 106caa7c4f4..89438d1a1ff 100644 --- a/lib/http_digest.h +++ b/lib/http_digest.h @@ -31,7 +31,6 @@ CURLcode Curl_input_digest(struct Curl_easy *data, /* this is for creating digest header output */ CURLcode Curl_output_digest(struct Curl_easy *data, - struct connectdata *conn, bool proxy, const unsigned char *request, const unsigned char *uripath); diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index d759748f2e2..68cce1bbb2b 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -179,7 +179,7 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data, free(base64); - if(userp == NULL) { + if(!userp) { return CURLE_OUT_OF_MEMORY; } diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index 6cb829edfa1..e200fdb1dae 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -39,6 +39,7 @@ #include "http_ntlm.h" #include "curl_ntlm_core.h" #include "curl_ntlm_wb.h" +#include "curl_base64.h" #include "vauth/vauth.h" #include "url.h" @@ -80,7 +81,18 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data, header++; if(*header) { - result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm); + unsigned char *hdr; + size_t hdrlen; + + result = Curl_base64_decode(header, &hdr, &hdrlen); + if(!result) { + struct bufref hdrbuf; + + Curl_bufref_init(&hdrbuf); + Curl_bufref_set(&hdrbuf, hdr, hdrlen, curl_free); + result = Curl_auth_decode_ntlm_type2_message(data, &hdrbuf, ntlm); + Curl_bufref_free(&hdrbuf); + } if(result) return result; @@ -116,7 +128,8 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) { char *base64 = NULL; size_t len = 0; - CURLcode result; + CURLcode result = CURLE_OK; + struct bufref ntlmmsg; /* point to the address of the pointer that holds the string to send to the server, which is for a plain host or for a HTTP proxy */ @@ -140,10 +153,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) if(proxy) { #ifndef CURL_DISABLE_PROXY allocuserpwd = &data->state.aptr.proxyuserpwd; - userp = conn->http_proxy.user; - passwdp = conn->http_proxy.passwd; + userp = data->state.aptr.proxyuser; + passwdp = data->state.aptr.proxypasswd; service = data->set.str[STRING_PROXY_SERVICE_NAME] ? - data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; hostname = conn->http_proxy.host.name; ntlm = &conn->proxyntlm; state = &conn->proxy_ntlm_state; @@ -154,10 +167,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) } else { allocuserpwd = &data->state.aptr.userpwd; - userp = conn->user; - passwdp = conn->passwd; + userp = data->state.aptr.user; + passwdp = data->state.aptr.passwd; service = data->set.str[STRING_SERVICE_NAME] ? - data->set.str[STRING_SERVICE_NAME] : "HTTP"; + data->set.str[STRING_SERVICE_NAME] : "HTTP"; hostname = conn->host.name; ntlm = &conn->ntlm; state = &conn->http_ntlm_state; @@ -173,10 +186,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) passwdp = ""; #ifdef USE_WINDOWS_SSPI - if(s_hSecDll == NULL) { + if(!s_hSecDll) { /* not thread safe and leaks - use curl_global_init() to avoid */ CURLcode err = Curl_sspi_global_init(); - if(s_hSecDll == NULL) + if(!s_hSecDll) return err; } #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS @@ -184,50 +197,52 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) #endif #endif + Curl_bufref_init(&ntlmmsg); switch(*state) { case NTLMSTATE_TYPE1: default: /* for the weird cases we (re)start here */ /* Create a type-1 message */ result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp, service, hostname, - ntlm, &base64, - &len); - if(result) - return result; - - if(base64) { - free(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", - proxy ? "Proxy-" : "", - base64); - free(base64); - if(!*allocuserpwd) - return CURLE_OUT_OF_MEMORY; - - DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); + ntlm, &ntlmmsg); + if(!result) { + DEBUGASSERT(Curl_bufref_len(&ntlmmsg) != 0); + result = Curl_base64_encode(data, + (const char *) Curl_bufref_ptr(&ntlmmsg), + Curl_bufref_len(&ntlmmsg), &base64, &len); + if(!result) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + result = CURLE_OUT_OF_MEMORY; + } } break; case NTLMSTATE_TYPE2: /* We already received the type-2 message, create a type-3 message */ result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp, - ntlm, &base64, &len); - if(result) - return result; - - if(base64) { - free(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", - proxy ? "Proxy-" : "", - base64); - free(base64); - if(!*allocuserpwd) - return CURLE_OUT_OF_MEMORY; - - DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); - - *state = NTLMSTATE_TYPE3; /* we send a type-3 */ - authp->done = TRUE; + ntlm, &ntlmmsg); + if(!result && Curl_bufref_len(&ntlmmsg)) { + result = Curl_base64_encode(data, + (const char *) Curl_bufref_ptr(&ntlmmsg), + Curl_bufref_len(&ntlmmsg), &base64, &len); + if(!result) { + free(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", + proxy ? "Proxy-" : "", + base64); + free(base64); + if(!*allocuserpwd) + result = CURLE_OUT_OF_MEMORY; + else { + *state = NTLMSTATE_TYPE3; /* we send a type-3 */ + authp->done = TRUE; + } + } } break; @@ -241,8 +256,9 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) authp->done = TRUE; break; } + Curl_bufref_free(&ntlmmsg); - return CURLE_OK; + return result; } void Curl_http_auth_cleanup_ntlm(struct connectdata *conn) diff --git a/lib/http_proxy.c b/lib/http_proxy.c index a03a27fdc4e..a3a62c1cad4 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -39,6 +39,8 @@ #include "connect.h" #include "curlx.h" #include "vtls/vtls.h" +#include "transfer.h" +#include "multiif.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -88,29 +90,12 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex) if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { #ifndef CURL_DISABLE_PROXY /* for [protocol] tunneled through HTTP proxy */ - struct HTTP http_proxy; - void *prot_save; const char *hostname; int remote_port; CURLcode result; - /* BLOCKING */ /* We want "seamless" operations through HTTP proxy tunnel */ - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want [protocol] through HTTP and we have - * to change the member temporarily for connecting to the HTTP - * proxy. After Curl_proxyCONNECT we have to set back the member to the - * original pointer - * - * This function might be called several times in the multi interface case - * if the proxy's CONNECT response is not instant. - */ - prot_save = data->req.p.http; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->req.p.http = &http_proxy; - connkeep(conn, "HTTP proxy CONNECT"); - /* for the secondary socket (FTP), use the "connect to host" * but ignore the "connect to port" (use the secondary port) */ @@ -128,8 +113,8 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex) remote_port = conn->conn_to_port; else remote_port = conn->remote_port; + result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port); - data->req.p.http = prot_save; if(CURLE_OK != result) return result; Curl_safefree(data->state.aptr.proxyuserpwd); @@ -153,18 +138,53 @@ bool Curl_connect_ongoing(struct connectdata *conn) (conn->connect_state->tunnel_state != TUNNEL_COMPLETE); } +/* when we've sent a CONNECT to a proxy, we should rather either wait for the + socket to become readable to be able to get the response headers or if + we're still sending the request, wait for write. */ +int Curl_connect_getsock(struct connectdata *conn) +{ + struct HTTP *http; + DEBUGASSERT(conn); + DEBUGASSERT(conn->connect_state); + http = &conn->connect_state->http_proxy; + + if(http->sending) + return GETSOCK_WRITESOCK(0); + + return GETSOCK_READSOCK(0); +} + static CURLcode connect_init(struct Curl_easy *data, bool reinit) { struct http_connect_state *s; struct connectdata *conn = data->conn; if(!reinit) { + CURLcode result; DEBUGASSERT(!conn->connect_state); + /* we might need the upload buffer for streaming a partial request */ + result = Curl_get_upload_buffer(data); + if(result) + return result; + s = calloc(1, sizeof(struct http_connect_state)); if(!s) return CURLE_OUT_OF_MEMORY; infof(data, "allocate connect buffer!\n"); conn->connect_state = s; Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS); + + /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the + * member conn->proto.http; we want [protocol] through HTTP and we have + * to change the member temporarily for connecting to the HTTP + * proxy. After Curl_proxyCONNECT we have to set back the member to the + * original pointer + * + * This function might be called several times in the multi interface case + * if the proxy's CONNECT response is not instant. + */ + s->prot_save = data->req.p.http; + data->req.p.http = &s->http_proxy; + connkeep(conn, "HTTP proxy CONNECT"); } else { DEBUGASSERT(conn->connect_state); @@ -184,6 +204,10 @@ static void connect_done(struct Curl_easy *data) struct http_connect_state *s = conn->connect_state; s->tunnel_state = TUNNEL_COMPLETE; Curl_dyn_free(&s->rcvbuf); + Curl_dyn_free(&s->req); + + /* retore the protocol pointer */ + data->req.p.http = s->prot_save; infof(data, "CONNECT phase completed!\n"); } @@ -231,6 +255,7 @@ static CURLcode CONNECT(struct Curl_easy *data, struct connectdata *conn = data->conn; curl_socket_t tunnelsocket = conn->sock[sockindex]; struct http_connect_state *s = conn->connect_state; + struct HTTP *http = data->req.p.http; char *linep; size_t perline; @@ -246,7 +271,7 @@ static CURLcode CONNECT(struct Curl_easy *data, timediff_t check; if(TUNNEL_INIT == s->tunnel_state) { /* BEGIN CONNECT PHASE */ - struct dynbuf req; + struct dynbuf *req = &s->req; char *hostheader = NULL; char *host = NULL; @@ -259,8 +284,8 @@ static CURLcode CONNECT(struct Curl_easy *data, free(data->req.newurl); data->req.newurl = NULL; - /* initialize a dynamic send-buffer */ - Curl_dyn_init(&req, DYN_HTTP_REQUEST); + /* initialize send-buffer */ + Curl_dyn_init(req, DYN_HTTP_REQUEST); result = CONNECT_host(data, conn, hostname, remote_port, &hostheader, &host); @@ -285,7 +310,7 @@ static CURLcode CONNECT(struct Curl_easy *data, useragent = data->state.aptr.uagent; result = - Curl_dyn_addf(&req, + Curl_dyn_addf(req, "CONNECT %s HTTP/%s\r\n" "%s" /* Host: */ "%s" /* Proxy-Authorization */ @@ -300,16 +325,15 @@ static CURLcode CONNECT(struct Curl_easy *data, proxyconn); if(!result) - result = Curl_add_custom_headers(data, TRUE, &req); + result = Curl_add_custom_headers(data, TRUE, req); if(!result) /* CRLF terminate the request */ - result = Curl_dyn_add(&req, "\r\n"); + result = Curl_dyn_add(req, "\r\n"); if(!result) { /* Send the connect request to the proxy */ - /* BLOCKING */ - result = Curl_buffer_send(&req, data, &data->info.request_size, 0, + result = Curl_buffer_send(req, data, &data->info.request_size, 0, sockindex); } if(result) @@ -317,7 +341,6 @@ static CURLcode CONNECT(struct Curl_easy *data, } free(host); free(hostheader); - Curl_dyn_free(&req); if(result) return result; @@ -330,12 +353,42 @@ static CURLcode CONNECT(struct Curl_easy *data, return CURLE_OPERATION_TIMEDOUT; } - if(!Curl_conn_data_pending(conn, sockindex)) + if(!Curl_conn_data_pending(conn, sockindex) && !http->sending) /* return so we'll be called again polling-style */ return CURLE_OK; /* at this point, the tunnel_connecting phase is over. */ + if(http->sending == HTTPSEND_REQUEST) { + if(!s->nsend) { + size_t fillcount; + k->upload_fromhere = data->state.ulbuf; + result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, + &fillcount); + if(result) + return result; + s->nsend = fillcount; + } + if(s->nsend) { + ssize_t bytes_written; + /* write to socket (send away data) */ + result = Curl_write(data, + conn->writesockfd, /* socket to send to */ + k->upload_fromhere, /* buffer pointer */ + s->nsend, /* buffer size */ + &bytes_written); /* actually sent */ + + if(!result) + /* send to debug callback! */ + result = Curl_debug(data, CURLINFO_HEADER_OUT, + k->upload_fromhere, bytes_written); + + s->nsend -= bytes_written; + k->upload_fromhere += bytes_written; + return result; + } + /* if nothing left to send, continue */ + } { /* READING RESPONSE PHASE */ int error = SELECT_OK; @@ -358,7 +411,8 @@ static CURLcode CONNECT(struct Curl_easy *data, break; } else if(gotbytes <= 0) { - if(data->set.proxyauth && data->state.authproxy.avail) { + if(data->set.proxyauth && data->state.authproxy.avail && + data->state.aptr.proxyuserpwd) { /* proxy auth was requested and there was proxy auth available, then deem this as "mere" proxy disconnect */ conn->bits.proxy_connect_closed = TRUE; @@ -759,7 +813,7 @@ static CURLcode CONNECT(struct Curl_easy *data, if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) && (HYPERE_OK != hyper_request_set_version(req, HYPER_HTTP_VERSION_1_0))) { - failf(data, "error settting HTTP version"); + failf(data, "error setting HTTP version"); goto error; } diff --git a/lib/http_proxy.h b/lib/http_proxy.h index a78db0d046a..f5a4cb07cf1 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -38,15 +38,39 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex); bool Curl_connect_complete(struct connectdata *conn); bool Curl_connect_ongoing(struct connectdata *conn); +int Curl_connect_getsock(struct connectdata *conn); #else #define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN #define Curl_proxy_connect(x,y) CURLE_OK #define Curl_connect_complete(x) CURLE_OK #define Curl_connect_ongoing(x) FALSE +#define Curl_connect_getsock(x) 0 #endif void Curl_connect_free(struct Curl_easy *data); void Curl_connect_done(struct Curl_easy *data); +/* struct for HTTP CONNECT state data */ +struct http_connect_state { + struct HTTP http_proxy; + struct HTTP *prot_save; + struct dynbuf rcvbuf; + struct dynbuf req; + size_t nsend; + enum keeponval { + KEEPON_DONE, + KEEPON_CONNECT, + KEEPON_IGNORE + } keepon; + curl_off_t cl; /* size of content to read and ignore */ + enum { + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE /* CONNECT response received completely */ + } tunnel_state; + BIT(chunked_encoding); + BIT(close_connection); +}; + #endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/lib/imap.c b/lib/imap.c index 2d8069921c9..d85bcc391da 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_imap = { imap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_IMAP, /* defport */ CURLPROTO_IMAP, /* protocol */ CURLPROTO_IMAP, /* family */ @@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_imaps = { imap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_IMAPS, /* defport */ CURLPROTO_IMAPS, /* protocol */ CURLPROTO_IMAP, /* family */ @@ -919,7 +921,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, /* Do we have a SASL based authentication mechanism? */ else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { size_t llen; - unsigned int mechbit; + unsigned short mechbit; line += 5; wordlen -= 5; @@ -1519,7 +1521,7 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status, Curl_safefree(imap->custom_params); /* Clear the transfer mode for the next request */ - imap->transfer = FTPTRANSFER_BODY; + imap->transfer = PPTRANSFER_BODY; return result; } @@ -1545,7 +1547,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, if(data->set.opt_no_body) { /* Requested no body means no transfer */ - imap->transfer = FTPTRANSFER_INFO; + imap->transfer = PPTRANSFER_INFO; } *dophase_done = FALSE; /* not done yet */ @@ -1667,7 +1669,7 @@ static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected) (void)connected; - if(imap->transfer != FTPTRANSFER_BODY) + if(imap->transfer != PPTRANSFER_BODY) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c index 9a5af7f4218..4c3e9e4dadd 100644 --- a/lib/inet_ntop.c +++ b/lib/inet_ntop.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1996-2019 Internet Software Consortium. + * Copyright (C) 1996-2021 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -134,7 +134,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) /* Are we following an initial run of 0x00s or any real hex? */ - if(i != 0) + if(i) *tp++ = ':'; /* Is this address an encapsulated IPv4? diff --git a/lib/krb5.c b/lib/krb5.c index 46116ce59fe..c8c4b6601bc 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -159,16 +159,6 @@ krb5_decode(void *app_data, void *buf, int len, return len; } -static int -krb5_overhead(void *app_data, int level, int len) -{ - /* no arguments are used */ - (void)app_data; - (void)level; - (void)len; - return 0; -} - static int krb5_encode(void *app_data, const void *from, int length, int level, void **to) { @@ -305,7 +295,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) break; } - if(output_buffer.length != 0) { + if(output_buffer.length) { char *cmd; result = Curl_base64_encode(data, (char *)output_buffer.value, @@ -392,7 +382,7 @@ static struct Curl_sec_client_mech Curl_krb5_client_mech = { krb5_auth, krb5_end, krb5_check_prot, - krb5_overhead, + krb5_encode, krb5_decode }; @@ -412,7 +402,7 @@ name_to_level(const char *name) { int i; for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) - if(checkprefix(name, level_names[i].name)) + if(curl_strequal(name, level_names[i].name)) return level_names[i].level; return PROT_NONE; } @@ -657,8 +647,6 @@ static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn, { ssize_t tx = 0, len = conn->buffer_size; - len -= conn->mech->overhead(conn->app_data, conn->data_prot, - curlx_sztosi(len)); if(len <= 0) len = length; while(length) { @@ -760,7 +748,7 @@ static int sec_set_protection_level(struct Curl_easy *data) if(level) { char *pbsz; - static unsigned int buffer_size = 1 << 20; /* 1048576 */ + unsigned int buffer_size = 1 << 20; /* 1048576 */ code = ftp_send_command(data, "PBSZ %u", buffer_size); if(code < 0) @@ -817,7 +805,7 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn) const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; tmp_allocation = realloc(conn->app_data, mech->size); - if(tmp_allocation == NULL) { + if(!tmp_allocation) { failf(data, "Failed realloc of size %zu", mech->size); mech = NULL; return CURLE_OUT_OF_MEMORY; diff --git a/lib/ldap.c b/lib/ldap.c index 307ebebafd8..ed16423026c 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -149,6 +149,7 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAP, /* defport */ CURLPROTO_LDAP, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -176,6 +177,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAPS, /* defport */ CURLPROTO_LDAPS, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -296,14 +298,14 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) *done = TRUE; /* unconditionally */ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); - infof(data, "LDAP local: %s\n", data->change.url); + infof(data, "LDAP local: %s\n", data->state.url); #ifdef HAVE_LDAP_URL_PARSE - rc = ldap_url_parse(data->change.url, &ludp); + rc = ldap_url_parse(data->state.url, &ludp); #else rc = _ldap_url_parse(data, conn, &ludp); #endif - if(rc != 0) { + if(rc) { failf(data, "LDAP local: %s", ldap_err2string(rc)); result = CURLE_LDAP_INVALID_URL; goto quit; @@ -387,7 +389,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } server = ldapssl_init(host, (int)conn->port, 1); - if(server == NULL) { + if(!server) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.dispname, conn->port); result = CURLE_COULDNT_CONNECT; @@ -428,7 +430,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } server = ldap_init(host, (int)conn->port); - if(server == NULL) { + if(!server) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.dispname, conn->port); result = CURLE_COULDNT_CONNECT; @@ -464,7 +466,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) } else { server = ldap_init(host, (int)conn->port); - if(server == NULL) { + if(!server) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.dispname, conn->port); result = CURLE_COULDNT_CONNECT; @@ -477,7 +479,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) #else rc = ldap_simple_bind_s(server, user, passwd); #endif - if(!ldap_ssl && rc != 0) { + if(!ldap_ssl && rc) { ldap_proto = LDAP_VERSION2; ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); #ifdef USE_WIN32_LDAP @@ -486,7 +488,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) rc = ldap_simple_bind_s(server, user, passwd); #endif } - if(rc != 0) { + if(rc) { #ifdef USE_WIN32_LDAP failf(data, "LDAP local: bind via ldap_win_bind %s", ldap_err2string(rc)); @@ -501,7 +503,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); - if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { + if(rc && rc != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: %s", ldap_err2string(rc)); result = CURLE_LDAP_SEARCH_FAILED; goto quit; @@ -581,7 +583,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = CURLE_OUT_OF_MEMORY; goto quit; - } + } #else char *attr = attribute; #endif @@ -875,7 +877,7 @@ static int _ldap_url_parse2(struct Curl_easy *data, ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped); /* Free the unescaped string as we are done with it */ - curlx_unicodefree(unescaped); + free(unescaped); if(!ludp->lud_dn) { rc = LDAP_NO_MEMORY; @@ -943,7 +945,7 @@ static int _ldap_url_parse2(struct Curl_easy *data, ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped); /* Free the unescaped string as we are done with it */ - curlx_unicodefree(unescaped); + free(unescaped); if(!ludp->lud_attrs[i]) { free(attributes); @@ -1010,7 +1012,7 @@ static int _ldap_url_parse2(struct Curl_easy *data, ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped); /* Free the unescaped string as we are done with it */ - curlx_unicodefree(unescaped); + free(unescaped); if(!ludp->lud_filter) { rc = LDAP_NO_MEMORY; @@ -1061,13 +1063,23 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp) if(!ludp) return; +#if defined(USE_WIN32_LDAP) + curlx_unicodefree(ludp->lud_dn); + curlx_unicodefree(ludp->lud_filter); +#else free(ludp->lud_dn); free(ludp->lud_filter); +#endif if(ludp->lud_attrs) { size_t i; - for(i = 0; i < ludp->lud_attrs_dups; i++) + for(i = 0; i < ludp->lud_attrs_dups; i++) { +#if defined(USE_WIN32_LDAP) + curlx_unicodefree(ludp->lud_attrs[i]); +#else free(ludp->lud_attrs[i]); +#endif + } free(ludp->lud_attrs); } diff --git a/lib/llist.c b/lib/llist.c index 17a7be16671..e0ec7393d28 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -94,13 +94,13 @@ Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e, void *user) { void *ptr; - if(e == NULL || list->size == 0) + if(!e || list->size == 0) return; if(e == list->head) { list->head = e->next; - if(list->head == NULL) + if(!list->head) list->tail = NULL; else e->next->prev = NULL; diff --git a/lib/md4.c b/lib/md4.c index 8ae6ac3fab7..c651ddf6696 100644 --- a/lib/md4.c +++ b/lib/md4.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,7 +44,7 @@ #endif #endif /* USE_MBEDTLS */ -#if defined(USE_GNUTLS_NETTLE) +#if defined(USE_GNUTLS) #include @@ -70,33 +70,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) md4_digest(ctx, MD4_DIGEST_SIZE, result); } -#elif defined(USE_GNUTLS) - -#include - -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -typedef gcry_md_hd_t MD4_CTX; - -static void MD4_Init(MD4_CTX *ctx) -{ - gcry_md_open(ctx, GCRY_MD_MD4, 0); -} - -static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) -{ - gcry_md_write(*ctx, data, size); -} - -static void MD4_Final(unsigned char *result, MD4_CTX *ctx) -{ - memcpy(result, gcry_md_read(*ctx, 0), MD4_DIGEST_LENGTH); - gcry_md_close(*ctx); -} - #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4) /* When OpenSSL is available we use the MD4-functions from OpenSSL */ #include @@ -201,7 +174,7 @@ static void MD4_Init(MD4_CTX *ctx) static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) { - if(ctx->data == NULL) { + if(!ctx->data) { ctx->data = malloc(size); if(ctx->data != NULL) { memcpy(ctx->data, data, size); diff --git a/lib/md5.c b/lib/md5.c index 513ffb2fb77..7a24fd8cf48 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -38,7 +38,7 @@ #endif #endif /* USE_MBEDTLS */ -#if defined(USE_GNUTLS_NETTLE) +#if defined(USE_GNUTLS) #include #include "curl_memory.h" @@ -64,33 +64,6 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) md5_digest(ctx, 16, digest); } -#elif defined(USE_GNUTLS) - -#include -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -typedef gcry_md_hd_t MD5_CTX; - -static void MD5_Init(MD5_CTX *ctx) -{ - gcry_md_open(ctx, GCRY_MD_MD5, 0); -} - -static void MD5_Update(MD5_CTX *ctx, - const unsigned char *input, - unsigned int inputLen) -{ - gcry_md_write(*ctx, input, inputLen); -} - -static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) -{ - memcpy(digest, gcry_md_read(*ctx, 0), 16); - gcry_md_close(*ctx); -} - #elif defined(USE_OPENSSL) && !defined(USE_AMISSL) /* When OpenSSL is available we use the MD5-function from OpenSSL */ #include diff --git a/lib/memdebug.c b/lib/memdebug.c index 881ee85c32e..050c5d4b2f1 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -55,9 +55,24 @@ struct memdebug { */ FILE *curl_dbg_logfile = NULL; +static bool registered_cleanup = FALSE; /* atexit registered cleanup */ static bool memlimit = FALSE; /* enable memory limit */ static long memsize = 0; /* set number of mallocs allowed */ +/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected + on exit so the logfile must be closed explicitly or data could be lost. + Though _exit() does not call atexit handlers such as this, LSAN's call to + _exit() comes after the atexit handlers are called. curl/curl#6620 */ +static void curl_dbg_cleanup(void) +{ + if(curl_dbg_logfile && + curl_dbg_logfile != stderr && + curl_dbg_logfile != stdout) { + fclose(curl_dbg_logfile); + } + curl_dbg_logfile = NULL; +} + /* this sets the log file name */ void curl_dbg_memdebug(const char *logname) { @@ -72,6 +87,8 @@ void curl_dbg_memdebug(const char *logname) setbuf(curl_dbg_logfile, (char *)NULL); #endif } + if(!registered_cleanup) + registered_cleanup = !atexit(curl_dbg_cleanup); } /* This function sets the number of malloc() calls that should return @@ -91,15 +108,13 @@ static bool countcheck(const char *func, int line, const char *source) should not be made */ if(memlimit && source) { if(!memsize) { - if(source) { - /* log to file */ - curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", - source, line, func); - /* log to stderr also */ - fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", - source, line, func); - fflush(curl_dbg_logfile); /* because it might crash now */ - } + /* log to file */ + curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", + source, line, func); + /* log to stderr also */ + fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", + source, line, func); + fflush(curl_dbg_logfile); /* because it might crash now */ errno = ENOMEM; return TRUE; /* RETURN ERROR! */ } diff --git a/lib/mime.c b/lib/mime.c index abadcb02cba..0bf1b46a4cf 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -152,14 +152,14 @@ curl_off_t VmsRealFileSize(const char *name, FILE * file; file = fopen(name, FOPEN_READTEXT); /* VMS */ - if(file == NULL) + if(!file) return 0; count = 0; ret_stat = 1; while(ret_stat > 0) { ret_stat = fread(buffer, 1, sizeof(buffer), file); - if(ret_stat != 0) + if(ret_stat) count += ret_stat; } fclose(file); diff --git a/lib/mprintf.c b/lib/mprintf.c index c681248deed..52920268615 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1999 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1999 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -815,7 +815,7 @@ static int dprintf_formatf( size_t len; str = (char *) p->data.str; - if(str == NULL) { + if(!str) { /* Write null[] if there's space. */ if(prec == -1 || prec >= (long) sizeof(null) - 1) { str = null; diff --git a/lib/mqtt.c b/lib/mqtt.c index 2134409cda8..d88fa737df6 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -86,6 +86,7 @@ const struct Curl_handler Curl_handler_mqtt = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_MQTT, /* defport */ CURLPROTO_MQTT, /* protocol */ CURLPROTO_MQTT, /* family */ diff --git a/lib/multi.c b/lib/multi.c index 85707a1af97..1b3e261c682 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -83,19 +83,19 @@ static void process_pending_handles(struct Curl_multi *multi); #ifdef DEBUGBUILD static const char * const statename[]={ "INIT", - "CONNECT_PEND", + "PENDING", "CONNECT", - "WAITRESOLVE", - "WAITCONNECT", - "WAITPROXYCONNECT", - "SENDPROTOCONNECT", + "RESOLVING", + "CONNECTING", + "TUNNELING", "PROTOCONNECT", + "PROTOCONNECTING", "DO", "DOING", - "DO_MORE", - "DO_DONE", - "PERFORM", - "TOOFAST", + "DOING_MORE", + "DID", + "PERFORMING", + "RATELIMITING", "DONE", "COMPLETED", "MSGSENT", @@ -105,8 +105,8 @@ static const char * const statename[]={ /* function pointer called once when switching TO a state */ typedef void (*init_multistate_func)(struct Curl_easy *data); -/* called when the PERFORM state starts */ -static void init_perform(struct Curl_easy *data) +/* called in DID state, before PERFORMING state */ +static void before_perform(struct Curl_easy *data) { data->req.chunk = FALSE; Curl_pgrsTime(data, TIMER_PRETRANSFER); @@ -130,21 +130,21 @@ static void mstate(struct Curl_easy *data, CURLMstate state ) { CURLMstate oldstate = data->mstate; - static const init_multistate_func finit[CURLM_STATE_LAST] = { + static const init_multistate_func finit[MSTATE_LAST] = { NULL, /* INIT */ - NULL, /* CONNECT_PEND */ + NULL, /* PENDING */ Curl_init_CONNECT, /* CONNECT */ - NULL, /* WAITRESOLVE */ - NULL, /* WAITCONNECT */ - NULL, /* WAITPROXYCONNECT */ - NULL, /* SENDPROTOCONNECT */ + NULL, /* RESOLVING */ + NULL, /* CONNECTING */ + NULL, /* TUNNELING */ NULL, /* PROTOCONNECT */ + NULL, /* PROTOCONNECTING */ Curl_connect_free, /* DO */ NULL, /* DOING */ - NULL, /* DO_MORE */ - NULL, /* DO_DONE */ - init_perform, /* PERFORM */ - NULL, /* TOOFAST */ + NULL, /* DOING_MORE */ + before_perform, /* DID */ + NULL, /* PERFORMING */ + NULL, /* RATELIMITING */ NULL, /* DONE */ init_completed, /* COMPLETED */ NULL /* MSGSENT */ @@ -161,8 +161,8 @@ static void mstate(struct Curl_easy *data, CURLMstate state data->mstate = state; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(data->mstate >= CURLM_STATE_CONNECT_PEND && - data->mstate < CURLM_STATE_COMPLETED) { + if(data->mstate >= MSTATE_PENDING && + data->mstate < MSTATE_COMPLETED) { long connection_id = -5000; if(data->conn) @@ -175,7 +175,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state } #endif - if(state == CURLM_STATE_COMPLETED) { + if(state == MSTATE_COMPLETED) { /* changing to COMPLETED means there's one less easy handle 'alive' */ DEBUGASSERT(data->multi->num_alive > 0); data->multi->num_alive--; @@ -381,6 +381,11 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ multi->max_concurrent_streams = 100; multi->ipv6_works = Curl_ipv6works(NULL); +#ifdef USE_WINSOCK + multi->wsa_event = WSACreateEvent(); + if(multi->wsa_event == WSA_INVALID_EVENT) + goto error; +#else #ifdef ENABLE_WAKEUP if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) { multi->wakeup_pair[0] = CURL_SOCKET_BAD; @@ -393,6 +398,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ multi->wakeup_pair[0] = CURL_SOCKET_BAD; multi->wakeup_pair[1] = CURL_SOCKET_BAD; } +#endif #endif return multi; @@ -447,7 +453,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->set.errorbuffer[0] = 0; /* set the easy handle */ - multistate(data, CURLM_STATE_INIT); + multistate(data, MSTATE_INIT); /* for multi interface connections, we share DNS cache automatically if the easy handle's one is currently not set. */ @@ -562,8 +568,6 @@ static CURLcode multi_done(struct Curl_easy *data, /* Stop if multi_done() has already been called */ return CURLE_OK; - conn->data = data; /* ensure the connection uses this transfer now */ - /* Stop the resolver and free its own resources (but not dns_entry yet). */ Curl_resolver_kill(data); @@ -604,16 +608,13 @@ static CURLcode multi_done(struct Curl_easy *data, Curl_detach_connnection(data); if(CONN_INUSE(conn)) { /* Stop if still used. */ - /* conn->data must not remain pointing to this transfer since it is going - away! Find another to own it! */ - conn->data = conn->easyq.head->ptr; CONNCACHE_UNLOCK(data); DEBUGF(infof(data, "Connection still in use %zu, " "no more multi_done now!\n", conn->easyq.size)); return CURLE_OK; } - conn->data = NULL; /* the connection now has no owner */ + data->state.done = TRUE; /* called just now! */ if(conn->dns_entry) { @@ -718,7 +719,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, { struct Curl_easy *easy = data; bool premature; - bool easy_owns_conn; struct Curl_llist_element *e; /* First, make some basic checks that the CURLM handle is a good handle */ @@ -740,9 +740,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; - premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE; - easy_owns_conn = (data->conn && (data->conn->data == easy)) ? - TRUE : FALSE; + premature = (data->mstate < MSTATE_COMPLETED) ? TRUE : FALSE; /* If the 'state' is not INIT or COMPLETED, we might need to do something nice to put the easy_handle in a good known state when this returns. */ @@ -753,28 +751,20 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, } if(data->conn && - data->mstate > CURLM_STATE_DO && - data->mstate < CURLM_STATE_COMPLETED) { + data->mstate > MSTATE_DO && + data->mstate < MSTATE_COMPLETED) { /* Set connection owner so that the DONE function closes it. We can safely do this here since connection is killed. */ - data->conn->data = easy; streamclose(data->conn, "Removed with partial response"); - easy_owns_conn = TRUE; } if(data->conn) { + /* multi_done() clears the association between the easy handle and the + connection. - /* we must call multi_done() here (if we still own the connection) so that - we don't leave a half-baked one around */ - if(easy_owns_conn) { - - /* multi_done() clears the association between the easy handle and the - connection. - - Note that this ignores the return code simply because there's - nothing really useful to do with it anyway! */ - (void)multi_done(data, data->result, premature); - } + Note that this ignores the return code simply because there's + nothing really useful to do with it anyway! */ + (void)multi_done(data, data->result, premature); } /* The timer must be shut down before data->multi is set to NULL, else the @@ -802,7 +792,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, /* change state without using multistate(), only to make singlesocket() do what we want */ - data->mstate = CURLM_STATE_COMPLETED; + data->mstate = MSTATE_COMPLETED; singlesocket(multi, easy); /* to let the application know what sockets that vanish with this handle */ @@ -840,6 +830,17 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, } } + /* Remove from the pending list if it is there. Otherwise this will + remain on the pending list forever due to the state change. */ + for(e = multi->pending.head; e; e = e->next) { + struct Curl_easy *curr_data = e->ptr; + + if(curr_data == data) { + Curl_llist_remove(&multi->pending, e, NULL); + break; + } + } + /* make the previous node point to our next */ if(data->prev) data->prev->next = data->next; @@ -856,6 +857,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, We do not touch the easy handle here! */ multi->num_easy--; /* one less to care about now */ + process_pending_handles(multi); + Curl_update_timer(multi); return CURLM_OK; } @@ -875,8 +878,10 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi) void Curl_detach_connnection(struct Curl_easy *data) { struct connectdata *conn = data->conn; - if(conn) + if(conn) { Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); + Curl_ssl_detach_conn(data, conn); + } data->conn = NULL; } @@ -893,6 +898,9 @@ void Curl_attach_connnection(struct Curl_easy *data, data->conn = conn; Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, &data->conn_queue); + if(conn->handler->attach) + conn->handler->attach(data, conn); + Curl_ssl_associate_conn(data, conn); } static int waitconnect_getsock(struct connectdata *conn, @@ -905,7 +913,7 @@ static int waitconnect_getsock(struct connectdata *conn, #ifdef USE_SSL #ifndef CURL_DISABLE_PROXY if(CONNECT_FIRSTSOCKET_PROXY_SSL()) - return Curl_ssl_getsock(conn, sock); + return Curl_ssl->getsock(conn, sock); #endif #endif @@ -933,10 +941,8 @@ static int waitproxyconnect_getsock(struct connectdata *conn, { sock[0] = conn->sock[FIRSTSOCKET]; - /* when we've sent a CONNECT to a proxy, we should rather wait for the - socket to become readable to be able to get the response headers */ if(conn->connect_state) - return GETSOCK_READSOCK(0); + return Curl_connect_getsock(conn); return GETSOCK_WRITESOCK(0); } @@ -984,40 +990,33 @@ static int multi_getsock(struct Curl_easy *data, if(!conn) return 0; - if(data->mstate > CURLM_STATE_CONNECT && - data->mstate < CURLM_STATE_COMPLETED) { - /* Set up ownership correctly */ - data->conn->data = data; - } - switch(data->mstate) { default: return 0; - case CURLM_STATE_WAITRESOLVE: + case MSTATE_RESOLVING: return Curl_resolv_getsock(data, socks); - case CURLM_STATE_PROTOCONNECT: - case CURLM_STATE_SENDPROTOCONNECT: + case MSTATE_PROTOCONNECTING: + case MSTATE_PROTOCONNECT: return protocol_getsock(data, conn, socks); - case CURLM_STATE_DO: - case CURLM_STATE_DOING: + case MSTATE_DO: + case MSTATE_DOING: return doing_getsock(data, conn, socks); - case CURLM_STATE_WAITPROXYCONNECT: + case MSTATE_TUNNELING: return waitproxyconnect_getsock(conn, socks); - case CURLM_STATE_WAITCONNECT: + case MSTATE_CONNECTING: return waitconnect_getsock(conn, socks); - case CURLM_STATE_DO_MORE: + case MSTATE_DOING_MORE: return domore_getsock(data, conn, socks); - case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch - to waiting for the same as the *PERFORM - states */ - case CURLM_STATE_PERFORM: + case MSTATE_DID: /* since is set after DO is completed, we switch to + waiting for the same as the PERFORMING state */ + case MSTATE_PERFORMING: return Curl_single_getsock(data, conn, socks); } @@ -1093,6 +1092,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi, struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; struct pollfd *ufds = &a_few_on_stack[0]; bool ufds_malloc = FALSE; +#ifdef USE_WINSOCK + WSANETWORKEVENTS wsa_events; + DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT); +#endif if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -1111,11 +1114,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi, for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; - if(bitmap & GETSOCK_READSOCK(i)) { + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { ++nfds; s = sockbunch[i]; } - if(bitmap & GETSOCK_WRITESOCK(i)) { + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { ++nfds; s = sockbunch[i]; } @@ -1138,7 +1141,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi, nfds += extra_nfds; /* add the externally provided ones */ #ifdef ENABLE_WAKEUP +#ifdef USE_WINSOCK + if(use_wakeup) { +#else if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { +#endif ++nfds; } #endif @@ -1166,22 +1173,40 @@ static CURLMcode multi_wait(struct Curl_multi *multi, for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; - +#ifdef USE_WINSOCK + long mask = 0; +#endif if(bitmap & GETSOCK_READSOCK(i)) { - ufds[nfds].fd = sockbunch[i]; + s = sockbunch[i]; +#ifdef USE_WINSOCK + mask |= FD_READ|FD_ACCEPT|FD_CLOSE; +#endif + ufds[nfds].fd = s; ufds[nfds].events = POLLIN; ++nfds; - s = sockbunch[i]; } if(bitmap & GETSOCK_WRITESOCK(i)) { - ufds[nfds].fd = sockbunch[i]; + s = sockbunch[i]; +#ifdef USE_WINSOCK + mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + send(s, NULL, 0, 0); /* reset FD_WRITE */ +#endif + ufds[nfds].fd = s; ufds[nfds].events = POLLOUT; ++nfds; - s = sockbunch[i]; } + /* s is only set if either being readable or writable is checked */ if(s == CURL_SOCKET_BAD) { + /* break on entry not checked for being readable or writable */ break; } +#ifdef USE_WINSOCK + if(WSAEventSelect(s, multi->wsa_event, mask) != 0) { + if(ufds_malloc) + free(ufds); + return CURLM_INTERNAL_ERROR; + } +#endif } data = data->next; /* check next handle */ @@ -1190,6 +1215,22 @@ static CURLMcode multi_wait(struct Curl_multi *multi, /* Add external file descriptions from poll-like struct curl_waitfd */ for(i = 0; i < extra_nfds; i++) { +#ifdef USE_WINSOCK + long mask = 0; + if(extra_fds[i].events & CURL_WAIT_POLLIN) + mask |= FD_READ|FD_ACCEPT|FD_CLOSE; + if(extra_fds[i].events & CURL_WAIT_POLLPRI) + mask |= FD_OOB; + if(extra_fds[i].events & CURL_WAIT_POLLOUT) { + mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */ + } + if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) { + if(ufds_malloc) + free(ufds); + return CURLM_INTERNAL_ERROR; + } +#endif ufds[nfds].fd = extra_fds[i].fd; ufds[nfds].events = 0; if(extra_fds[i].events & CURL_WAIT_POLLIN) @@ -1202,25 +1243,62 @@ static CURLMcode multi_wait(struct Curl_multi *multi, } #ifdef ENABLE_WAKEUP +#ifndef USE_WINSOCK if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { ufds[nfds].fd = multi->wakeup_pair[0]; ufds[nfds].events = POLLIN; ++nfds; } #endif +#endif +#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK) + if(nfds || use_wakeup) { +#else if(nfds) { - /* wait... */ - int pollrc = Curl_poll(ufds, nfds, timeout_ms); +#endif + int pollrc; +#ifdef USE_WINSOCK + if(nfds) + pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */ + else + pollrc = 0; + if(pollrc <= 0) /* now wait... if not ready during the pre-check above */ + WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE); +#else + pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */ +#endif + if(pollrc > 0) { retcode = pollrc; +#ifdef USE_WINSOCK + } + /* With WinSock, we have to run the following section unconditionally + to call WSAEventSelect(fd, event, 0) on all the sockets */ + { +#endif /* copy revents results from the poll to the curl_multi_wait poll struct, the bit values of the actual underlying poll() implementation may not be the same as the ones in the public libcurl API! */ for(i = 0; i < extra_nfds; i++) { - unsigned short mask = 0; unsigned r = ufds[curlfds + i].revents; - + unsigned short mask = 0; +#ifdef USE_WINSOCK + wsa_events.lNetworkEvents = 0; + if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) { + if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)) + mask |= CURL_WAIT_POLLIN; + if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE)) + mask |= CURL_WAIT_POLLOUT; + if(wsa_events.lNetworkEvents & FD_OOB) + mask |= CURL_WAIT_POLLPRI; + if(ret && pollrc <= 0 && wsa_events.lNetworkEvents) + retcode++; + } + WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0); + if(pollrc <= 0) + continue; +#endif if(r & POLLIN) mask |= CURL_WAIT_POLLIN; if(r & POLLOUT) @@ -1230,6 +1308,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi, extra_fds[i].revents = mask; } +#ifdef USE_WINSOCK + /* Count up all our own sockets that had activity, + and remove them from the event. */ + if(curlfds) { + data = multi->easyp; + while(data) { + bitmap = multi_getsock(data, sockbunch); + + for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) { + if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) { + wsa_events.lNetworkEvents = 0; + if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) { + if(ret && pollrc <= 0 && wsa_events.lNetworkEvents) + retcode++; + } + WSAEventSelect(sockbunch[i], multi->wsa_event, 0); + } + else { + /* break on entry not checked for being readable or writable */ + break; + } + } + + data = data->next; + } + } + + WSAResetEvent(multi->wsa_event); +#else #ifdef ENABLE_WAKEUP if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { if(ufds[curlfds + extra_nfds].revents & POLLIN) { @@ -1242,10 +1349,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi, when there is no more data, breaking the loop. */ nread = sread(multi->wakeup_pair[0], buf, sizeof(buf)); if(nread <= 0) { -#ifndef USE_WINSOCK if(nread < 0 && EINTR == SOCKERRNO) continue; -#endif break; } } @@ -1253,6 +1358,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, retcode--; } } +#endif #endif } } @@ -1261,10 +1367,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi, free(ufds); if(ret) *ret = retcode; - if(!extrawait || nfds) - /* if any socket was checked */ - ; - else { +#if defined(ENABLE_WAKEUP) && defined(USE_WINSOCK) + if(extrawait && !nfds && !use_wakeup) { +#else + if(extrawait && !nfds) { +#endif long sleep_ms = 0; /* Avoid busy-looping when there's nothing particular to wait for */ @@ -1313,6 +1420,10 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi) return CURLM_BAD_HANDLE; #ifdef ENABLE_WAKEUP +#ifdef USE_WINSOCK + if(WSASetEvent(multi->wsa_event)) + return CURLM_OK; +#else /* the wakeup_pair variable is only written during init and cleanup, making it safe to access from another thread after the init part and before cleanup */ @@ -1345,6 +1456,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi) return CURLM_OK; } } +#endif #endif return CURLM_WAKEUP_FAILURE; } @@ -1383,7 +1495,7 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, Curl_init_do(data, NULL); /* take this handle to the perform state right away */ - multistate(data, CURLM_STATE_PERFORM); + multistate(data, MSTATE_PERFORMING); Curl_attach_connnection(data, conn); k->keepon |= KEEP_RECV; /* setup to receive! */ } @@ -1397,7 +1509,6 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done) DEBUGASSERT(conn); DEBUGASSERT(conn->handler); - DEBUGASSERT(conn->data == data); if(conn->handler->do_it) /* generic protocol-specific function pointer set in curl_connect() */ @@ -1578,31 +1689,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, process_pending_handles(multi); /* multiplexed */ } - if(data->mstate > CURLM_STATE_CONNECT && - data->mstate < CURLM_STATE_COMPLETED) { + if(data->mstate > MSTATE_CONNECT && + data->mstate < MSTATE_COMPLETED) { /* Make sure we set the connection's current owner */ DEBUGASSERT(data->conn); if(!data->conn) return CURLM_INTERNAL_ERROR; - data->conn->data = data; } if(data->conn && - (data->mstate >= CURLM_STATE_CONNECT) && - (data->mstate < CURLM_STATE_COMPLETED)) { + (data->mstate >= MSTATE_CONNECT) && + (data->mstate < MSTATE_COMPLETED)) { /* we need to wait for the connect state as only then is the start time stored, but we must not check already completed handles */ timeout_ms = Curl_timeleft(data, nowp, - (data->mstate <= CURLM_STATE_DO)? + (data->mstate <= MSTATE_DO)? TRUE:FALSE); if(timeout_ms < 0) { /* Handle timed out */ - if(data->mstate == CURLM_STATE_WAITRESOLVE) + if(data->mstate == MSTATE_RESOLVING) failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T " milliseconds", Curl_timediff(*nowp, data->progress.t_startsingle)); - else if(data->mstate == CURLM_STATE_WAITCONNECT) + else if(data->mstate == MSTATE_CONNECTING) failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T " milliseconds", Curl_timediff(*nowp, data->progress.t_startsingle)); @@ -1625,7 +1735,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } /* Force connection closed if the connection has indeed been used */ - if(data->mstate > CURLM_STATE_DO) { + if(data->mstate > MSTATE_DO) { streamclose(data->conn, "Disconnected with pending data"); stream_error = TRUE; } @@ -1637,24 +1747,24 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } switch(data->mstate) { - case CURLM_STATE_INIT: + case MSTATE_INIT: /* init this transfer. */ result = Curl_pretransfer(data); if(!result) { /* after init, go CONNECT */ - multistate(data, CURLM_STATE_CONNECT); + multistate(data, MSTATE_CONNECT); *nowp = Curl_pgrsTime(data, TIMER_STARTOP); rc = CURLM_CALL_MULTI_PERFORM; } break; - case CURLM_STATE_CONNECT_PEND: + case MSTATE_PENDING: /* We will stay here until there is a connection available. Then - we try again in the CURLM_STATE_CONNECT state. */ + we try again in the MSTATE_CONNECT state. */ break; - case CURLM_STATE_CONNECT: + case MSTATE_CONNECT: /* Connect. We want to get a connection identifier filled in. */ /* init this transfer. */ result = Curl_preconnect(data); @@ -1672,7 +1782,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(CURLE_NO_CONNECTION_AVAILABLE == result) { /* There was no connection available. We will go to the pending state and wait for an available connection. */ - multistate(data, CURLM_STATE_CONNECT_PEND); + multistate(data, MSTATE_PENDING); /* add this handle to the list of connect-pending handles */ Curl_llist_insert_next(&multi->pending, multi->pending.tail, data, @@ -1689,7 +1799,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(!result) { if(async) /* We're now waiting for an asynchronous name lookup */ - multistate(data, CURLM_STATE_WAITRESOLVE); + multistate(data, MSTATE_RESOLVING); else { /* after the connect has been sent off, go WAITCONNECT unless the protocol connect is already done and we can go directly to @@ -1697,20 +1807,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, rc = CURLM_CALL_MULTI_PERFORM; if(protocol_connected) - multistate(data, CURLM_STATE_DO); + multistate(data, MSTATE_DO); else { #ifndef CURL_DISABLE_HTTP if(Curl_connect_ongoing(data->conn)) - multistate(data, CURLM_STATE_WAITPROXYCONNECT); + multistate(data, MSTATE_TUNNELING); else #endif - multistate(data, CURLM_STATE_WAITCONNECT); + multistate(data, MSTATE_CONNECTING); } } } break; - case CURLM_STATE_WAITRESOLVE: + case MSTATE_RESOLVING: /* awaiting an asynch name resolve to complete */ { struct Curl_dns_entry *dns = NULL; @@ -1764,14 +1874,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* call again please so that we get the next socket setup */ rc = CURLM_CALL_MULTI_PERFORM; if(protocol_connected) - multistate(data, CURLM_STATE_DO); + multistate(data, MSTATE_DO); else { #ifndef CURL_DISABLE_HTTP if(Curl_connect_ongoing(data->conn)) - multistate(data, CURLM_STATE_WAITPROXYCONNECT); + multistate(data, MSTATE_TUNNELING); else #endif - multistate(data, CURLM_STATE_WAITCONNECT); + multistate(data, MSTATE_CONNECTING); } } } @@ -1785,7 +1895,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; #ifndef CURL_DISABLE_HTTP - case CURLM_STATE_WAITPROXYCONNECT: + case MSTATE_TUNNELING: /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ DEBUGASSERT(data->conn); result = Curl_http_connect(data, &protocol_connected); @@ -1795,7 +1905,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* connect back to proxy again */ result = CURLE_OK; multi_done(data, CURLE_OK, FALSE); - multistate(data, CURLM_STATE_CONNECT); + multistate(data, MSTATE_CONNECT); } else #endif @@ -1808,7 +1918,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, Curl_connect_complete(data->conn)) { rc = CURLM_CALL_MULTI_PERFORM; /* initiate protocol connect phase */ - multistate(data, CURLM_STATE_SENDPROTOCONNECT); + multistate(data, MSTATE_PROTOCONNECT); } } else @@ -1816,7 +1926,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; #endif - case CURLM_STATE_WAITCONNECT: + case MSTATE_CONNECTING: /* awaiting a completion of an asynch TCP connect */ DEBUGASSERT(data->conn); result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected); @@ -1828,7 +1938,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) || #endif Curl_connect_ongoing(data->conn)) { - multistate(data, CURLM_STATE_WAITPROXYCONNECT); + multistate(data, MSTATE_TUNNELING); break; } #endif @@ -1836,10 +1946,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, #ifndef CURL_DISABLE_PROXY multistate(data, data->conn->bits.tunnel_proxy? - CURLM_STATE_WAITPROXYCONNECT: - CURLM_STATE_SENDPROTOCONNECT); + MSTATE_TUNNELING : MSTATE_PROTOCONNECT); #else - multistate(data, CURLM_STATE_SENDPROTOCONNECT); + multistate(data, MSTATE_PROTOCONNECT); #endif } else if(result) { @@ -1851,14 +1960,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_SENDPROTOCONNECT: + case MSTATE_PROTOCONNECT: result = protocol_connect(data, &protocol_connected); if(!result && !protocol_connected) /* switch to waiting state */ - multistate(data, CURLM_STATE_PROTOCONNECT); + multistate(data, MSTATE_PROTOCONNECTING); else if(!result) { /* protocol connect has completed, go WAITDO or DO */ - multistate(data, CURLM_STATE_DO); + multistate(data, MSTATE_DO); rc = CURLM_CALL_MULTI_PERFORM; } else { @@ -1869,12 +1978,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_PROTOCONNECT: + case MSTATE_PROTOCONNECTING: /* protocol-specific connect phase */ result = protocol_connecting(data, &protocol_connected); if(!result && protocol_connected) { /* after the connect has completed, go WAITDO or DO */ - multistate(data, CURLM_STATE_DO); + multistate(data, MSTATE_DO); rc = CURLM_CALL_MULTI_PERFORM; } else if(result) { @@ -1885,11 +1994,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_DO: + case MSTATE_DO: if(data->set.connect_only) { /* keep connection open for application to use the socket */ connkeep(data->conn, "CONNECT_ONLY"); - multistate(data, CURLM_STATE_DONE); + multistate(data, MSTATE_DONE); result = CURLE_OK; rc = CURLM_CALL_MULTI_PERFORM; } @@ -1911,7 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* if there's no connection left, skip the DONE state */ multistate(data, data->conn ? - CURLM_STATE_DONE : CURLM_STATE_COMPLETED); + MSTATE_DONE : MSTATE_COMPLETED); rc = CURLM_CALL_MULTI_PERFORM; break; } @@ -1919,7 +2028,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, #endif /* DO was not completed in one function call, we must continue DOING... */ - multistate(data, CURLM_STATE_DOING); + multistate(data, MSTATE_DOING); rc = CURLM_OK; } @@ -1927,12 +2036,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, else if(data->conn->bits.do_more) { /* we're supposed to do more, but we need to sit down, relax and wait a little while first */ - multistate(data, CURLM_STATE_DO_MORE); + multistate(data, MSTATE_DOING_MORE); rc = CURLM_OK; } else { - /* we're done with the DO, now DO_DONE */ - multistate(data, CURLM_STATE_DO_DONE); + /* we're done with the DO, now DID */ + multistate(data, MSTATE_DID); rc = CURLM_CALL_MULTI_PERFORM; } } @@ -1964,7 +2073,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, follow = FOLLOW_RETRY; drc = Curl_follow(data, newurl, follow); if(!drc) { - multistate(data, CURLM_STATE_CONNECT); + multistate(data, MSTATE_CONNECT); rc = CURLM_CALL_MULTI_PERFORM; result = CURLE_OK; } @@ -1994,7 +2103,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_DOING: + case MSTATE_DOING: /* we continue DOING until the DO phase is complete */ DEBUGASSERT(data->conn); result = protocol_doing(data, &dophase_done); @@ -2002,8 +2111,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(dophase_done) { /* after DO, go DO_DONE or DO_MORE */ multistate(data, data->conn->bits.do_more? - CURLM_STATE_DO_MORE: - CURLM_STATE_DO_DONE); + MSTATE_DOING_MORE : MSTATE_DID); rc = CURLM_CALL_MULTI_PERFORM; } /* dophase_done */ } @@ -2015,9 +2123,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_DO_MORE: + case MSTATE_DOING_MORE: /* - * When we are connected, DO MORE and then go DO_DONE + * When we are connected, DOING MORE and then go DID */ DEBUGASSERT(data->conn); result = multi_do_more(data, &control); @@ -2027,8 +2135,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* if positive, advance to DO_DONE if negative, go back to DOING */ multistate(data, control == 1? - CURLM_STATE_DO_DONE: - CURLM_STATE_DOING); + MSTATE_DID : MSTATE_DOING); rc = CURLM_CALL_MULTI_PERFORM; } else @@ -2043,7 +2150,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_DO_DONE: + case MSTATE_DID: DEBUGASSERT(data->conn); if(data->conn->bits.multiplex) /* Check if we can move pending requests to send pipe */ @@ -2053,7 +2160,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, Having both BAD is a signal to skip immediately to DONE */ if((data->conn->sockfd != CURL_SOCKET_BAD) || (data->conn->writesockfd != CURL_SOCKET_BAD)) - multistate(data, CURLM_STATE_PERFORM); + multistate(data, MSTATE_PERFORMING); else { #ifndef CURL_DISABLE_FTP if(data->state.wildcardmatch && @@ -2061,12 +2168,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, data->wildcard.state = CURLWC_DONE; } #endif - multistate(data, CURLM_STATE_DONE); + multistate(data, MSTATE_DONE); } rc = CURLM_CALL_MULTI_PERFORM; break; - case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ + case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */ DEBUGASSERT(data->conn); /* if both rates are within spec, resume transfer */ if(Curl_pgrsUpdate(data)) @@ -2084,7 +2191,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } else { send_timeout_ms = 0; - if(data->set.max_send_speed > 0) + if(data->set.max_send_speed) send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, data->progress.ul_limit_size, @@ -2093,7 +2200,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, *nowp); recv_timeout_ms = 0; - if(data->set.max_recv_speed > 0) + if(data->set.max_recv_speed) recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, data->progress.dl_limit_size, @@ -2102,7 +2209,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, *nowp); if(!send_timeout_ms && !recv_timeout_ms) { - multistate(data, CURLM_STATE_PERFORM); + multistate(data, MSTATE_PERFORMING); Curl_ratelimit(data, *nowp); } else if(send_timeout_ms >= recv_timeout_ms) @@ -2112,7 +2219,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } break; - case CURLM_STATE_PERFORM: + case MSTATE_PERFORMING: { char *newurl = NULL; bool retry = FALSE; @@ -2120,7 +2227,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, DEBUGASSERT(data->state.buffer); /* check if over send speed */ send_timeout_ms = 0; - if(data->set.max_send_speed > 0) + if(data->set.max_send_speed) send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, data->progress.ul_limit_size, data->set.max_send_speed, @@ -2129,7 +2236,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* check if over recv speed */ recv_timeout_ms = 0; - if(data->set.max_recv_speed > 0) + if(data->set.max_recv_speed) recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, data->progress.dl_limit_size, data->set.max_recv_speed, @@ -2138,7 +2245,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(send_timeout_ms || recv_timeout_ms) { Curl_ratelimit(data, *nowp); - multistate(data, CURLM_STATE_TOOFAST); + multistate(data, MSTATE_RATELIMITING); if(send_timeout_ms >= recv_timeout_ms) Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); else @@ -2168,17 +2275,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } } else if((CURLE_HTTP2_STREAM == result) && - Curl_h2_http_1_1_error(data->conn)) { + Curl_h2_http_1_1_error(data)) { CURLcode ret = Curl_retry_request(data, &newurl); if(!ret) { infof(data, "Downgrades to HTTP/1.1!\n"); - data->set.httpversion = CURL_HTTP_VERSION_1_1; + streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1"); + data->state.httpwant = CURL_HTTP_VERSION_1_1; /* clear the error message bit too as we ignore the one we got */ data->state.errorbuf = FALSE; if(!newurl) /* typically for HTTP_1_1_REQUIRED error on first flight */ - newurl = strdup(data->change.url); + newurl = strdup(data->state.url); /* if we are to retry, set the result to OK and consider the request as done */ retry = TRUE; @@ -2228,7 +2336,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* multi_done() might return CURLE_GOT_NOTHING */ result = Curl_follow(data, newurl, follow); if(!result) { - multistate(data, CURLM_STATE_CONNECT); + multistate(data, MSTATE_CONNECT); rc = CURLM_CALL_MULTI_PERFORM; } free(newurl); @@ -2251,7 +2359,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } if(!result) { - multistate(data, CURLM_STATE_DONE); + multistate(data, MSTATE_DONE); rc = CURLM_CALL_MULTI_PERFORM; } } @@ -2266,7 +2374,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; } - case CURLM_STATE_DONE: + case MSTATE_DONE: /* this state is highly transient, so run another loop after this */ rc = CURLM_CALL_MULTI_PERFORM; @@ -2289,21 +2397,21 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(data->state.wildcardmatch) { if(data->wildcard.state != CURLWC_DONE) { /* if a wildcard is set and we are not ending -> lets start again - with CURLM_STATE_INIT */ - multistate(data, CURLM_STATE_INIT); + with MSTATE_INIT */ + multistate(data, MSTATE_INIT); break; } } #endif /* after we have DONE what we're supposed to do, go COMPLETED, and it doesn't matter what the multi_done() returned! */ - multistate(data, CURLM_STATE_COMPLETED); + multistate(data, MSTATE_COMPLETED); break; - case CURLM_STATE_COMPLETED: + case MSTATE_COMPLETED: break; - case CURLM_STATE_MSGSENT: + case MSTATE_MSGSENT: data->result = result; return CURLM_OK; /* do nothing */ @@ -2312,7 +2420,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } statemachine_end: - if(data->mstate < CURLM_STATE_COMPLETED) { + if(data->mstate < MSTATE_COMPLETED) { if(result) { /* * If an error was returned, and we aren't in completed state now, @@ -2343,12 +2451,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, Curl_disconnect(data, conn, dead_connection); } } - else if(data->mstate == CURLM_STATE_CONNECT) { + else if(data->mstate == MSTATE_CONNECT) { /* Curl_connect() failed */ (void)Curl_posttransfer(data); } - multistate(data, CURLM_STATE_COMPLETED); + multistate(data, MSTATE_COMPLETED); rc = CURLM_CALL_MULTI_PERFORM; } /* if there's still a connection to use, call the progress function */ @@ -2359,13 +2467,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, streamclose(data->conn, "Aborted by callback"); /* if not yet in DONE state, go there, otherwise COMPLETED */ - multistate(data, (data->mstate < CURLM_STATE_DONE)? - CURLM_STATE_DONE: CURLM_STATE_COMPLETED); + multistate(data, (data->mstate < MSTATE_DONE)? + MSTATE_DONE: MSTATE_COMPLETED); rc = CURLM_CALL_MULTI_PERFORM; } } - if(CURLM_STATE_COMPLETED == data->mstate) { + if(MSTATE_COMPLETED == data->mstate) { if(data->set.fmultidone) { /* signal via callback instead */ data->set.fmultidone(data, result); @@ -2381,7 +2489,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, rc = multi_addmsg(multi, msg); DEBUGASSERT(!data->conn); } - multistate(data, CURLM_STATE_MSGSENT); + multistate(data, MSTATE_MSGSENT); } } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE)); @@ -2492,9 +2600,13 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_hash_destroy(&multi->hostcache); Curl_psl_destroy(&multi->psl); +#ifdef USE_WINSOCK + WSACloseEvent(multi->wsa_event); +#else #ifdef ENABLE_WAKEUP sclose(multi->wakeup_pair[0]); sclose(multi->wakeup_pair[1]); +#endif #endif free(multi); @@ -2554,7 +2666,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi, curl_socket_t s; int num; unsigned int curraction; - int actions[MAX_SOCKSPEREASYHANDLE]; + unsigned char actions[MAX_SOCKSPEREASYHANDLE]; for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) socks[i] = CURL_SOCKET_BAD; @@ -2571,9 +2683,9 @@ static CURLMcode singlesocket(struct Curl_multi *multi, for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) && (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))); i++) { - unsigned int action = CURL_POLL_NONE; - unsigned int prevaction = 0; - unsigned int comboaction; + unsigned char action = CURL_POLL_NONE; + unsigned char prevaction = 0; + int comboaction; bool sincebefore = FALSE; s = socks[i]; @@ -2631,10 +2743,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi, } comboaction = (entry->writers? CURL_POLL_OUT : 0) | - (entry->readers ? CURL_POLL_IN : 0); + (entry->readers ? CURL_POLL_IN : 0); /* socket existed before and has the same action set as before */ - if(sincebefore && (entry->action == comboaction)) + if(sincebefore && ((int)entry->action == comboaction)) /* same, continue */ continue; @@ -2667,7 +2779,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi, /* if this is NULL here, the socket has been closed and notified so already by Curl_multi_closed() */ if(entry) { - int oldactions = data->actions[i]; + unsigned char oldactions = data->actions[i]; /* this socket has been removed. Decrease user count */ entry->users--; if(oldactions & CURL_POLL_OUT) @@ -2692,7 +2804,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi, } /* for loop over numsocks */ memcpy(data->sockets, socks, num*sizeof(curl_socket_t)); - memcpy(data->actions, actions, num*sizeof(int)); + memcpy(data->actions, actions, num*sizeof(char)); data->numsocks = num; return CURLM_OK; } @@ -3344,9 +3456,9 @@ static void process_pending_handles(struct Curl_multi *multi) if(e) { struct Curl_easy *data = e->ptr; - DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND); + DEBUGASSERT(data->mstate == MSTATE_PENDING); - multistate(data, CURLM_STATE_CONNECT); + multistate(data, MSTATE_CONNECT); /* Remove this node from the list */ Curl_llist_remove(&multi->pending, e, NULL); @@ -3384,7 +3496,7 @@ void Curl_multi_dump(struct Curl_multi *multi) fprintf(stderr, "* Multi status: %d handles, %d alive\n", multi->num_easy, multi->num_alive); for(data = multi->easyp; data; data = data->next) { - if(data->mstate < CURLM_STATE_COMPLETED) { + if(data->mstate < MSTATE_COMPLETED) { /* only display handles that are not completed */ fprintf(stderr, "handle %p, state %s, %d sockets\n", (void *)data, diff --git a/lib/multihandle.h b/lib/multihandle.h index f28c5899b6b..96b84749fca 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -40,27 +40,26 @@ struct Curl_message { well! */ typedef enum { - CURLM_STATE_INIT, /* 0 - start in this state */ - CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */ - CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ - CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ - CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ - CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization - to complete and/or proxy CONNECT to - finalize */ - CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ - CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect - phase */ - CURLM_STATE_DO, /* 8 - start send off the request (part 1) */ - CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */ - CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */ - CURLM_STATE_DO_DONE, /* 11 - done sending off request */ - CURLM_STATE_PERFORM, /* 12 - transfer data */ - CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */ - CURLM_STATE_DONE, /* 14 - post data transfer operation */ - CURLM_STATE_COMPLETED, /* 15 - operation complete */ - CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */ - CURLM_STATE_LAST /* 17 - not a true state, never use this */ + MSTATE_INIT, /* 0 - start in this state */ + MSTATE_PENDING, /* 1 - no connections, waiting for one */ + MSTATE_CONNECT, /* 2 - resolve/connect has been sent off */ + MSTATE_RESOLVING, /* 3 - awaiting the resolve to finalize */ + MSTATE_CONNECTING, /* 4 - awaiting the TCP connect to finalize */ + MSTATE_TUNNELING, /* 5 - awaiting HTTPS proxy SSL initialization to + complete and/or proxy CONNECT to finalize */ + MSTATE_PROTOCONNECT, /* 6 - initiate protocol connect procedure */ + MSTATE_PROTOCONNECTING, /* 7 - completing the protocol-specific connect + phase */ + MSTATE_DO, /* 8 - start send off the request (part 1) */ + MSTATE_DOING, /* 9 - sending off the request (part 1) */ + MSTATE_DOING_MORE, /* 10 - send off the request (part 2) */ + MSTATE_DID, /* 11 - done sending off request */ + MSTATE_PERFORMING, /* 12 - transfer data */ + MSTATE_RATELIMITING, /* 13 - wait because limit-rate exceeded */ + MSTATE_DONE, /* 14 - post data transfer operation */ + MSTATE_COMPLETED, /* 15 - operation complete */ + MSTATE_MSGSENT, /* 16 - the operation complete message is sent */ + MSTATE_LAST /* 17 - not a true state, never use this */ } CURLMstate; /* we support N sockets per easy handle. Set the corresponding bit to what @@ -71,8 +70,7 @@ typedef enum { #define CURLPIPE_ANY (CURLPIPE_MULTIPLEX) -#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS) && \ - !defined(CURL_DISABLE_SOCKETPAIR) +#if !defined(CURL_DISABLE_SOCKETPAIR) #define ENABLE_WAKEUP #endif @@ -96,7 +94,7 @@ struct Curl_multi { struct Curl_llist msglist; /* a list of messages from completed transfers */ struct Curl_llist pending; /* Curl_easys that are in the - CURLM_STATE_CONNECT_PEND state */ + MSTATE_PENDING state */ /* callback function and user data pointer for the *socket() API */ curl_socket_callback socket_cb; @@ -142,9 +140,13 @@ struct Curl_multi { previous callback */ unsigned int max_concurrent_streams; +#ifdef USE_WINSOCK + WSAEVENT wsa_event; /* winsock event used for waits */ +#else #ifdef ENABLE_WAKEUP curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup 0 is used for read, 1 is used for write */ +#endif #endif /* multiplexing wanted */ bool multiplexing; diff --git a/lib/non-ascii.c b/lib/non-ascii.c index 30c240b6371..932cf89eef6 100644 --- a/lib/non-ascii.c +++ b/lib/non-ascii.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -127,7 +127,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, &output_ptr, &out_bytes); if(!data) iconv_close(tmpcd); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { + if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_to_network iconv call failed with errno %i: %s", errno, strerror(errno)); @@ -193,7 +193,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, &output_ptr, &out_bytes); if(!data) iconv_close(tmpcd); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { + if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "Curl_convert_from_network iconv call failed with errno %i: %s", errno, strerror(errno)); @@ -260,7 +260,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, &output_ptr, &out_bytes); if(!data) iconv_close(tmpcd); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { + if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", errno, strerror(errno)); diff --git a/lib/nonblock.c b/lib/nonblock.c index 4a7bde504ff..fda2e9ad792 100644 --- a/lib/nonblock.c +++ b/lib/nonblock.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,13 +47,7 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */) { -#if defined(USE_BLOCKING_SOCKETS) - (void)sockfd; - (void)nonblock; - return 0; /* returns success */ - -#elif defined(HAVE_FCNTL_O_NONBLOCK) - +#if defined(HAVE_FCNTL_O_NONBLOCK) /* most recent unix versions */ int flags; flags = sfcntl(sockfd, F_GETFL, 0); diff --git a/lib/openldap.c b/lib/openldap.c index 4070bbf88bc..0b8bc34a038 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -76,16 +76,16 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); #endif -static CURLcode ldap_setup_connection(struct Curl_easy *data, - struct connectdata *conn); -static CURLcode ldap_do(struct Curl_easy *data, bool *done); -static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool); -static CURLcode ldap_connect(struct Curl_easy *data, bool *done); -static CURLcode ldap_connecting(struct Curl_easy *data, bool *done); -static CURLcode ldap_disconnect(struct Curl_easy *data, - struct connectdata *conn, bool dead); +static CURLcode oldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn); +static CURLcode oldap_do(struct Curl_easy *data, bool *done); +static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool); +static CURLcode oldap_connect(struct Curl_easy *data, bool *done); +static CURLcode oldap_connecting(struct Curl_easy *data, bool *done); +static CURLcode oldap_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); -static Curl_recv ldap_recv; +static Curl_recv oldap_recv; /* * LDAP protocol handler. @@ -93,20 +93,21 @@ static Curl_recv ldap_recv; const struct Curl_handler Curl_handler_ldap = { "LDAP", /* scheme */ - ldap_setup_connection, /* setup_connection */ - ldap_do, /* do_it */ - ldap_done, /* done */ + oldap_setup_connection, /* setup_connection */ + oldap_do, /* do_it */ + oldap_done, /* done */ ZERO_NULL, /* do_more */ - ldap_connect, /* connect_it */ - ldap_connecting, /* connecting */ + oldap_connect, /* connect_it */ + oldap_connecting, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ - ldap_disconnect, /* disconnect */ + oldap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAP, /* defport */ CURLPROTO_LDAP, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -120,20 +121,21 @@ const struct Curl_handler Curl_handler_ldap = { const struct Curl_handler Curl_handler_ldaps = { "LDAPS", /* scheme */ - ldap_setup_connection, /* setup_connection */ - ldap_do, /* do_it */ - ldap_done, /* done */ + oldap_setup_connection, /* setup_connection */ + oldap_do, /* do_it */ + oldap_done, /* done */ ZERO_NULL, /* do_more */ - ldap_connect, /* connect_it */ - ldap_connecting, /* connecting */ + oldap_connect, /* connect_it */ + oldap_connecting, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ ZERO_NULL, /* perform_getsock */ - ldap_disconnect, /* disconnect */ + oldap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_LDAPS, /* defport */ CURLPROTO_LDAPS, /* protocol */ CURLPROTO_LDAP, /* family */ @@ -171,15 +173,15 @@ struct ldapreqinfo { int nument; }; -static CURLcode ldap_setup_connection(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode oldap_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { struct ldapconninfo *li; LDAPURLDesc *lud; int rc, proto; CURLcode status; - rc = ldap_url_parse(data->change.url, &lud); + rc = ldap_url_parse(data->state.url, &lud); if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; @@ -207,7 +209,7 @@ static CURLcode ldap_setup_connection(struct Curl_easy *data, static Sockbuf_IO ldapsb_tls; #endif -static CURLcode ldap_connect(struct Curl_easy *data, bool *done) +static CURLcode oldap_connect(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -255,7 +257,7 @@ static CURLcode ldap_connect(struct Curl_easy *data, bool *done) return CURLE_OK; } -static CURLcode ldap_connecting(struct Curl_easy *data, bool *done) +static CURLcode oldap_connecting(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -278,7 +280,7 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done) if(!li->sslinst) { Sockbuf *sb; ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); - ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); li->sslinst = TRUE; li->recv = conn->recv[FIRSTSOCKET]; li->send = conn->send[FIRSTSOCKET]; @@ -354,21 +356,28 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done) if(info) ldap_memfree(info); - conn->recv[FIRSTSOCKET] = ldap_recv; + conn->recv[FIRSTSOCKET] = oldap_recv; *done = TRUE; return CURLE_OK; } -static CURLcode ldap_disconnect(struct Curl_easy *data, - struct connectdata *conn, bool dead_connection) +static CURLcode oldap_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { struct ldapconninfo *li = conn->proto.ldapc; (void) dead_connection; - (void) data; if(li) { if(li->ld) { +#ifdef USE_SSL + if(conn->ssl[FIRSTSOCKET].use) { + Sockbuf *sb; + ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); + ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data); + } +#endif ldap_unbind_ext(li->ld, NULL, NULL); li->ld = NULL; } @@ -378,7 +387,7 @@ static CURLcode ldap_disconnect(struct Curl_easy *data, return CURLE_OK; } -static CURLcode ldap_do(struct Curl_easy *data, bool *done) +static CURLcode oldap_do(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -390,9 +399,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) connkeep(conn, "OpenLDAP do"); - infof(data, "LDAP local: %s\n", data->change.url); + infof(data, "LDAP local: %s\n", data->state.url); - rc = ldap_url_parse(data->change.url, &ludp); + rc = ldap_url_parse(data->state.url, &ludp); if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; @@ -423,8 +432,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) return CURLE_OK; } -static CURLcode ldap_done(struct Curl_easy *data, CURLcode res, - bool premature) +static CURLcode oldap_done(struct Curl_easy *data, CURLcode res, + bool premature) { struct connectdata *conn = data->conn; struct ldapreqinfo *lr = data->req.p.ldap; @@ -446,8 +455,8 @@ static CURLcode ldap_done(struct Curl_easy *data, CURLcode res, return CURLE_OK; } -static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, - size_t len, CURLcode *err) +static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf, + size_t len, CURLcode *err) { struct connectdata *conn = data->conn; struct ldapconninfo *li = conn->proto.ldapc; @@ -543,7 +552,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) { int i; - if(bv.bv_val == NULL) + if(!bv.bv_val) break; if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) @@ -551,7 +560,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, else binary = 0; - if(bvals == NULL) { + if(!bvals) { writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1); if(writeerr) { *err = writeerr; @@ -660,7 +669,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, data->req.bytecount += bvals[i].bv_len + 1; } - writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; @@ -669,14 +678,14 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf, data->req.bytecount++; } ber_memfree(bvals); - writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; } data->req.bytecount++; } - writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); + writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); if(writeerr) { *err = writeerr; return -1; @@ -716,8 +725,8 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) { (void)arg; if(opt == LBER_SB_OPT_DATA_READY) { - struct connectdata *conn = sbiod->sbiod_pvt; - return Curl_ssl_data_pending(conn, FIRSTSOCKET); + struct Curl_easy *data = sbiod->sbiod_pvt; + return Curl_ssl_data_pending(data->conn, FIRSTSOCKET); } return 0; } @@ -725,14 +734,19 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) static ber_slen_t ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { - struct connectdata *conn = sbiod->sbiod_pvt; - struct ldapconninfo *li = conn->proto.ldapc; - ber_slen_t ret; - CURLcode err = CURLE_RECV_ERROR; + struct Curl_easy *data = sbiod->sbiod_pvt; + ber_slen_t ret = 0; + if(data) { + struct connectdata *conn = data->conn; + if(conn) { + struct ldapconninfo *li = conn->proto.ldapc; + CURLcode err = CURLE_RECV_ERROR; - ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err); - if(ret < 0 && err == CURLE_AGAIN) { - SET_SOCKERRNO(EWOULDBLOCK); + ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + } } return ret; } @@ -740,14 +754,18 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) static ber_slen_t ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { - struct connectdata *conn = sbiod->sbiod_pvt; - struct ldapconninfo *li = conn->proto.ldapc; - ber_slen_t ret; - CURLcode err = CURLE_SEND_ERROR; - - ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err); - if(ret < 0 && err == CURLE_AGAIN) { - SET_SOCKERRNO(EWOULDBLOCK); + struct Curl_easy *data = sbiod->sbiod_pvt; + ber_slen_t ret = 0; + if(data) { + struct connectdata *conn = data->conn; + if(conn) { + struct ldapconninfo *li = conn->proto.ldapc; + CURLcode err = CURLE_SEND_ERROR; + ret = (li->send)(data, FIRSTSOCKET, buf, len, &err); + if(ret < 0 && err == CURLE_AGAIN) { + SET_SOCKERRNO(EWOULDBLOCK); + } + } } return ret; } diff --git a/lib/pingpong.h b/lib/pingpong.h index 4f7d7ea6b94..8f56f3f865e 100644 --- a/lib/pingpong.h +++ b/lib/pingpong.h @@ -33,10 +33,9 @@ struct connectdata; typedef enum { - FTPTRANSFER_BODY, /* yes do transfer a body */ - FTPTRANSFER_INFO, /* do still go through to get info/headers */ - FTPTRANSFER_NONE, /* don't get anything and don't get info */ - FTPTRANSFER_LAST /* end of list marker, never used */ + PPTRANSFER_BODY, /* yes do transfer a body */ + PPTRANSFER_INFO, /* do still go through to get info/headers */ + PPTRANSFER_NONE /* don't get anything and don't get info */ } curl_pp_transfer; /* diff --git a/lib/pop3.c b/lib/pop3.c index 0ed3d3ee18d..9b6ea64804c 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -131,6 +131,7 @@ const struct Curl_handler Curl_handler_pop3 = { pop3_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_POP3, /* defport */ CURLPROTO_POP3, /* protocol */ CURLPROTO_POP3, /* family */ @@ -159,6 +160,7 @@ const struct Curl_handler Curl_handler_pop3s = { pop3_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_POP3S, /* defport */ CURLPROTO_POP3S, /* protocol */ CURLPROTO_POP3, /* family */ @@ -571,12 +573,12 @@ static CURLcode pop3_perform_command(struct Curl_easy *data) const char *command = NULL; /* Calculate the default command */ - if(pop3->id[0] == '\0' || data->set.ftp_list_only) { + if(pop3->id[0] == '\0' || data->set.list_only) { command = "LIST"; if(pop3->id[0] != '\0') /* Message specific LIST so skip the BODY transfer */ - pop3->transfer = FTPTRANSFER_INFO; + pop3->transfer = PPTRANSFER_INFO; } else command = "RETR"; @@ -709,7 +711,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, for(;;) { size_t llen; size_t wordlen; - unsigned int mechbit; + unsigned short mechbit; while(len && (*line == ' ' || *line == '\t' || @@ -916,7 +918,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data, the strip counter here so that these bytes won't be delivered. */ pop3c->strip = 2; - if(pop3->transfer == FTPTRANSFER_BODY) { + if(pop3->transfer == PPTRANSFER_BODY) { /* POP3 download */ Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); @@ -1150,7 +1152,7 @@ static CURLcode pop3_done(struct Curl_easy *data, CURLcode status, Curl_safefree(pop3->custom); /* Clear the transfer mode for the next request */ - pop3->transfer = FTPTRANSFER_BODY; + pop3->transfer = PPTRANSFER_BODY; return result; } @@ -1174,7 +1176,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected, if(data->set.opt_no_body) { /* Requested no body means no transfer */ - pop3->transfer = FTPTRANSFER_INFO; + pop3->transfer = PPTRANSFER_INFO; } *dophase_done = FALSE; /* not done yet */ @@ -1515,8 +1517,17 @@ CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread) if(prev) { /* If the partial match was the CRLF and dot then only write the CRLF as the server would have inserted the dot */ - result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, - strip_dot ? prev - 1 : prev); + if(strip_dot && prev - 1 > 0) { + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, + prev - 1); + } + else if(!strip_dot) { + result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, + prev); + } + else { + result = CURLE_OK; + } if(result) return result; diff --git a/lib/progress.c b/lib/progress.c index 55e8ded04db..4bcd615ebaf 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -85,7 +85,7 @@ static char *max5data(curl_off_t bytes, char *max5) CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE, (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) ); -#if (CURL_SIZEOF_CURL_OFF_T > 4) +#if (SIZEOF_CURL_OFF_T > 4) else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE) /* 'XXXXM' is good until we're at 10000MB or above */ @@ -241,6 +241,8 @@ void Curl_pgrsStartNow(struct Curl_easy *data) data->progress.is_t_startransfer_set = false; data->progress.ul_limit_start = data->progress.start; data->progress.dl_limit_start = data->progress.start; + data->progress.ul_limit_size = 0; + data->progress.dl_limit_size = 0; data->progress.downloaded = 0; data->progress.uploaded = 0; /* clear all bits except HIDE and HEADERS_OUT */ @@ -321,14 +323,14 @@ void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) void Curl_ratelimit(struct Curl_easy *data, struct curltime now) { /* don't set a new stamp unless the time since last update is long enough */ - if(data->set.max_recv_speed > 0) { + if(data->set.max_recv_speed) { if(Curl_timediff(now, data->progress.dl_limit_start) >= MIN_RATE_LIMIT_PERIOD) { data->progress.dl_limit_start = now; data->progress.dl_limit_size = data->progress.downloaded; } } - if(data->set.max_send_speed > 0) { + if(data->set.max_send_speed) { if(Curl_timediff(now, data->progress.ul_limit_start) >= MIN_RATE_LIMIT_PERIOD) { data->progress.ul_limit_start = now; @@ -369,94 +371,82 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size) } } +/* returns the average speed in bytes / second */ +static curl_off_t trspeed(curl_off_t size, /* number of bytes */ + curl_off_t us) /* microseconds */ +{ + if(us < 1) + return size * 1000000; + return (curl_off_t)((long double)size/us * 1000000); +} + /* returns TRUE if it's time to show the progress meter */ static bool progress_calc(struct Curl_easy *data, struct curltime now) { - curl_off_t timespent; - curl_off_t timespent_ms; /* milliseconds */ - curl_off_t dl = data->progress.downloaded; - curl_off_t ul = data->progress.uploaded; bool timetoshow = FALSE; + struct Progress * const p = &data->progress; - /* The time spent so far (from the start) */ - data->progress.timespent = Curl_timediff_us(now, data->progress.start); - timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */ - timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */ - - /* The average download speed this far */ - if(dl < CURL_OFF_T_MAX/1000) - data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1)); - else - data->progress.dlspeed = (dl / (timespent>0?timespent:1)); - - /* The average upload speed this far */ - if(ul < CURL_OFF_T_MAX/1000) - data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1)); - else - data->progress.ulspeed = (ul / (timespent>0?timespent:1)); + /* The time spent so far (from the start) in microseconds */ + p->timespent = Curl_timediff_us(now, p->start); + p->dlspeed = trspeed(p->downloaded, p->timespent); + p->ulspeed = trspeed(p->uploaded, p->timespent); /* Calculations done at most once a second, unless end is reached */ - if(data->progress.lastshow != now.tv_sec) { + if(p->lastshow != now.tv_sec) { int countindex; /* amount of seconds stored in the speeder array */ - int nowindex = data->progress.speeder_c% CURR_TIME; - data->progress.lastshow = now.tv_sec; + int nowindex = p->speeder_c% CURR_TIME; + p->lastshow = now.tv_sec; timetoshow = TRUE; /* Let's do the "current speed" thing, with the dl + ul speeds combined. Store the speed at entry 'nowindex'. */ - data->progress.speeder[ nowindex ] = - data->progress.downloaded + data->progress.uploaded; + p->speeder[ nowindex ] = p->downloaded + p->uploaded; /* remember the exact time for this moment */ - data->progress.speeder_time [ nowindex ] = now; + p->speeder_time [ nowindex ] = now; /* advance our speeder_c counter, which is increased every time we get here and we expect it to never wrap as 2^32 is a lot of seconds! */ - data->progress.speeder_c++; + p->speeder_c++; /* figure out how many index entries of data we have stored in our speeder array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of transfer. Imagine, after one second we have filled in two entries, after two seconds we've filled in three entries etc. */ - countindex = ((data->progress.speeder_c >= CURR_TIME)? - CURR_TIME:data->progress.speeder_c) - 1; + countindex = ((p->speeder_c >= CURR_TIME)? CURR_TIME:p->speeder_c) - 1; /* first of all, we don't do this if there's no counted seconds yet */ if(countindex) { int checkindex; timediff_t span_ms; + curl_off_t amount; /* Get the index position to compare with the 'nowindex' position. Get the oldest entry possible. While we have less than CURR_TIME entries, the first entry will remain the oldest. */ - checkindex = (data->progress.speeder_c >= CURR_TIME)? - data->progress.speeder_c%CURR_TIME:0; + checkindex = (p->speeder_c >= CURR_TIME)? p->speeder_c%CURR_TIME:0; /* Figure out the exact time for the time span */ - span_ms = Curl_timediff(now, data->progress.speeder_time[checkindex]); + span_ms = Curl_timediff(now, p->speeder_time[checkindex]); if(0 == span_ms) span_ms = 1; /* at least one millisecond MUST have passed */ /* Calculate the average speed the last 'span_ms' milliseconds */ - { - curl_off_t amount = data->progress.speeder[nowindex]- - data->progress.speeder[checkindex]; - - if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) - /* the 'amount' value is bigger than would fit in 32 bits if - multiplied with 1000, so we use the double math for this */ - data->progress.current_speed = (curl_off_t) - ((double)amount/((double)span_ms/1000.0)); - else - /* the 'amount' value is small enough to fit within 32 bits even - when multiplied with 1000 */ - data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms; - } + amount = p->speeder[nowindex]- p->speeder[checkindex]; + + if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) + /* the 'amount' value is bigger than would fit in 32 bits if + multiplied with 1000, so we use the double math for this */ + p->current_speed = (curl_off_t) + ((double)amount/((double)span_ms/1000.0)); + else + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + p->current_speed = amount*CURL_OFF_T_C(1000)/span_ms; } else /* the first second we use the average */ - data->progress.current_speed = - data->progress.ulspeed + data->progress.dlspeed; + p->current_speed = p->ulspeed + p->dlspeed; } /* Calculations end */ return timetoshow; diff --git a/lib/rtsp.c b/lib/rtsp.c index 55766757a87..007d5c50b6a 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -109,6 +109,7 @@ const struct Curl_handler Curl_handler_rtsp = { rtsp_disconnect, /* disconnect */ rtsp_rtp_readwrite, /* readwrite */ rtsp_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_RTSP, /* defport */ CURLPROTO_RTSP, /* protocol */ CURLPROTO_RTSP, /* family */ @@ -404,8 +405,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) /* Referrer */ Curl_safefree(data->state.aptr.ref); - if(data->change.referer && !Curl_checkheaders(data, "Referer")) - data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer); + if(data->state.referer && !Curl_checkheaders(data, "Referer")) + data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer); else data->state.aptr.ref = NULL; @@ -680,7 +681,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, } } - if(rtp_dataleft != 0 && rtp[0] == '$') { + if(rtp_dataleft && rtp[0] == '$') { DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft, *readmore ? "(READMORE)" : "")); @@ -824,7 +825,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header) /* Copy the id substring into a new buffer */ data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1); - if(data->set.str[STRING_RTSP_SESSION_ID] == NULL) + if(!data->set.str[STRING_RTSP_SESSION_ID]) return CURLE_OUT_OF_MEMORY; memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen); (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0'; diff --git a/lib/select.c b/lib/select.c index d7346b195fc..52dca5a2c0b 100644 --- a/lib/select.c +++ b/lib/select.c @@ -442,7 +442,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) if(ufds[i].events & POLLPRI) ufds[i].revents |= POLLPRI; } - if(ufds[i].revents != 0) + if(ufds[i].revents) r++; } diff --git a/lib/sendf.c b/lib/sendf.c index b3c7fe33d3b..e41bb805f5c 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -65,7 +65,7 @@ static size_t convert_lineends(struct Curl_easy *data, char *inPtr, *outPtr; /* sanity check */ - if((startPtr == NULL) || (size < 1)) { + if(!startPtr || (size < 1)) { return size; } @@ -309,6 +309,18 @@ CURLcode Curl_write(struct Curl_easy *data, conn = data->conn; num = (sockfd == conn->sock[SECONDARYSOCKET]); +#ifdef CURLDEBUG + { + /* Allow debug builds to override this logic to force short sends + */ + char *p = getenv("CURL_SMALLSENDS"); + if(p) { + size_t altsize = (size_t)strtoul(p, NULL, 10); + if(altsize) + len = CURLMIN(len, altsize); + } + } +#endif bytes_written = conn->send[num](data, num, mem, len, &result); *written = bytes_written; @@ -498,9 +510,7 @@ static CURLcode pausewrite(struct Curl_easy *data, /* store this information in the state struct for later use */ Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER); s->tempwrite[i].type = type; - - if(newtype) - s->tempcount++; + s->tempcount++; } if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len)) @@ -606,7 +616,7 @@ static CURLcode chop_write(struct Curl_easy *data, /* Curl_client_write() sends data to the write callback(s) The bit pattern defines to what "streams" to write to. Body and/or header. - The defines are in sendf.h of course. + The defines are in sendf.h of course. "len" is not allowed to be 0. If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the local character encoding. This is a problem and should be changed in @@ -618,9 +628,8 @@ CURLcode Curl_client_write(struct Curl_easy *data, size_t len) { struct connectdata *conn = data->conn; - if(0 == len) - len = strlen(ptr); + DEBUGASSERT(len); DEBUGASSERT(type <= 3); /* FTP data may need conversion. */ diff --git a/lib/setopt.c b/lib/setopt.c index ce73a34a7fc..fb8b86d474a 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -177,7 +177,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_SSL_CIPHER_LIST: /* set a list of cipher we want to use in the SSL connection */ - result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], va_arg(param, char *)); break; #ifndef CURL_DISABLE_PROXY @@ -190,7 +190,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_TLS13_CIPHERS: if(Curl_ssl_tls13_ciphersuites()) { /* set preferred list of TLS 1.3 cipher suites */ - result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST], va_arg(param, char *)); } else @@ -426,6 +426,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) version_max = C_SSLVERSION_MAX_VALUE(arg); if(version < CURL_SSLVERSION_DEFAULT || + version == CURL_SSLVERSION_SSLv2 || + version == CURL_SSLVERSION_SSLv3 || version >= CURL_SSLVERSION_LAST || version_max < CURL_SSLVERSION_MAX_NONE || version_max >= CURL_SSLVERSION_MAX_LAST) @@ -653,8 +655,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.httpauth = CURLAUTH_AWS_SIGV4; break; -#endif /* CURL_DISABLE_HTTP */ - case CURLOPT_MIMEPOST: /* * Set to make us do MIME/form POST @@ -671,13 +671,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * String to set in the HTTP Referer: field. */ - if(data->change.referer_alloc) { - Curl_safefree(data->change.referer); - data->change.referer_alloc = FALSE; + if(data->state.referer_alloc) { + Curl_safefree(data->state.referer); + data->state.referer_alloc = FALSE; } result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], va_arg(param, char *)); - data->change.referer = data->set.str[STRING_SET_REFERER]; + data->state.referer = data->set.str[STRING_SET_REFERER]; break; case CURLOPT_USERAGENT: @@ -695,7 +695,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.headers = va_arg(param, struct curl_slist *); break; -#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXYHEADER: /* @@ -747,13 +746,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return CURLE_BAD_FUNCTION_ARGUMENT; /* append the cookie file name to the list of file names, and deal with them later */ - cl = curl_slist_append(data->change.cookielist, argptr); + cl = curl_slist_append(data->state.cookielist, argptr); if(!cl) { - curl_slist_free_all(data->change.cookielist); - data->change.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; return CURLE_OUT_OF_MEMORY; } - data->change.cookielist = cl; /* store the list for later use */ + data->state.cookielist = cl; /* store the list for later use */ + } + else { + /* clear the list of cookie files */ + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; + + if(!data->share || !data->share->cookies) { + /* throw away all existing cookies if this isn't a shared cookie + container */ + Curl_cookie_clearall(data->cookies); + Curl_cookie_cleanup(data->cookies); + } + /* disable the cookie engine */ + data->cookies = NULL; } break; @@ -800,7 +813,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_COOKIELIST: argptr = va_arg(param, char *); - if(argptr == NULL) + if(!argptr) break; if(strcasecompare(argptr, "ALL")) { @@ -891,7 +904,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) if(arg == CURL_HTTP_VERSION_NONE) arg = CURL_HTTP_VERSION_2TLS; #endif - data->set.httpversion = arg; + data->set.httpwant = (unsigned char)arg; break; case CURLOPT_EXPECT_100_TIMEOUT_MS: @@ -909,7 +922,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = va_arg(param, unsigned long); if(arg > 1L) return CURLE_BAD_FUNCTION_ARGUMENT; +#ifdef USE_HYPER + /* Hyper does not support HTTP/0.9 */ + if(arg) + return CURLE_BAD_FUNCTION_ARGUMENT; +#else data->set.http09_allowed = arg ? TRUE : FALSE; +#endif break; #endif /* CURL_DISABLE_HTTP */ @@ -1160,7 +1179,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * An option that changes the command to one that asks for a list only, no * file info details. Used for FTP, POP3 and SFTP. */ - data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; break; case CURLOPT_APPEND: @@ -1168,7 +1187,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * We want to upload and append to an existing file. Used for FTP and * SFTP. */ - data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE; break; #ifndef CURL_DISABLE_FTP @@ -1335,14 +1354,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * The URL to fetch. */ - if(data->change.url_alloc) { + if(data->state.url_alloc) { /* the already set URL is allocated, free it first! */ - Curl_safefree(data->change.url); - data->change.url_alloc = FALSE; + Curl_safefree(data->state.url); + data->state.url_alloc = FALSE; } result = Curl_setstropt(&data->set.str[STRING_SET_URL], va_arg(param, char *)); - data->change.url = data->set.str[STRING_SET_URL]; + data->state.url = data->set.str[STRING_SET_URL]; break; case CURLOPT_PORT: /* @@ -1416,7 +1435,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = Curl_setstropt(&data->set.str[STRING_USERNAME], va_arg(param, char *)); break; - case CURLOPT_PASSWORD: /* * authentication password to use in the operation @@ -1474,7 +1492,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * that aren't actually in use right now will be pruned immediately. */ data->set.resolve = va_arg(param, struct curl_slist *); - data->change.resolve = data->set.resolve; + data->state.resolve = data->set.resolve; break; case CURLOPT_PROGRESSFUNCTION: /* @@ -1666,14 +1684,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * String that holds file name of the SSL certificate to use */ - result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG], + result = Curl_setstropt(&data->set.str[STRING_CERT], va_arg(param, char *)); break; case CURLOPT_SSLCERT_BLOB: /* * Blob that holds file name of the SSL certificate to use */ - result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_ORIG], + result = Curl_setblobopt(&data->set.blobs[BLOB_CERT], va_arg(param, struct curl_blob *)); break; #ifndef CURL_DISABLE_PROXY @@ -1696,7 +1714,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * String that holds file type of the SSL certificate to use */ - result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG], + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE], va_arg(param, char *)); break; #ifndef CURL_DISABLE_PROXY @@ -1712,14 +1730,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * String that holds file name of the SSL key to use */ - result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG], + result = Curl_setstropt(&data->set.str[STRING_KEY], va_arg(param, char *)); break; case CURLOPT_SSLKEY_BLOB: /* * Blob that holds file name of the SSL key to use */ - result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_ORIG], + result = Curl_setblobopt(&data->set.blobs[BLOB_KEY], va_arg(param, struct curl_blob *)); break; #ifndef CURL_DISABLE_PROXY @@ -1742,7 +1760,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * String that holds file type of the SSL key to use */ - result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG], + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE], va_arg(param, char *)); break; #ifndef CURL_DISABLE_PROXY @@ -1758,7 +1776,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * String that holds the SSL or SSH private key password. */ - result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG], + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD], va_arg(param, char *)); break; #ifndef CURL_DISABLE_PROXY @@ -1852,6 +1870,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.ssl.primary.verifypeer; } break; + case CURLOPT_DOH_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying for DOH. + */ + data->set.doh_verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_SSL_VERIFYPEER: /* @@ -1884,6 +1909,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.ssl.primary.verifyhost; } break; + case CURLOPT_DOH_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate for DOH + */ + arg = va_arg(param, long); + + /* Treat both 1 and 2 as TRUE */ + data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE); + break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_SSL_VERIFYHOST: /* @@ -1919,6 +1953,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.ssl.primary.verifystatus; } break; + case CURLOPT_DOH_SSL_VERIFYSTATUS: + /* + * Enable certificate status verifying for DOH. + */ + if(!Curl_ssl_cert_status_request()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.doh_verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; case CURLOPT_SSL_CTX_FUNCTION: /* * Set a SSL_CTX callback @@ -1967,7 +2013,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) */ #ifdef USE_SSL if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) - result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], va_arg(param, char *)); else #endif @@ -1992,9 +2038,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) /* * Set CA info for SSL connection. Specify file name of the CA certificate */ - result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE], va_arg(param, char *)); break; + case CURLOPT_CAINFO_BLOB: + /* + * Blob that holds CA info for SSL connection. + * Specify entire PEM of the CA certificate + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB) + result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], + va_arg(param, struct curl_blob *)); + else +#endif + return CURLE_NOT_BUILT_IN; + + break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_CAINFO: /* @@ -2004,6 +2064,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], va_arg(param, char *)); break; + case CURLOPT_PROXY_CAINFO_BLOB: + /* + * Blob that holds CA info for SSL connection proxy. + * Specify entire PEM of the CA certificate + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB) + result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], + va_arg(param, struct curl_blob *)); + else +#endif + return CURLE_NOT_BUILT_IN; + break; #endif case CURLOPT_CAPATH: /* @@ -2013,7 +2086,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #ifdef USE_SSL if(Curl_ssl->supports & SSLSUPP_CA_PATH) /* This does not work on windows. */ - result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH], va_arg(param, char *)); else #endif @@ -2040,7 +2113,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set CRL file info for SSL connection. Specify file name of the CRL * to check certificates revocation */ - result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE], va_arg(param, char *)); break; #ifndef CURL_DISABLE_PROXY @@ -2058,14 +2131,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set Issuer certificate file * to check certificates issuer */ - result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG], + result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT], va_arg(param, char *)); break; case CURLOPT_ISSUERCERT_BLOB: /* * Blob that holds Issuer certificate to check certificates issuer */ - result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG], + result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT], va_arg(param, struct curl_blob *)); break; #ifndef CURL_DISABLE_PROXY @@ -2125,7 +2198,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) else if(arg < UPLOADBUFFER_MIN) arg = UPLOADBUFFER_MIN; - data->set.upload_buffer_size = arg; + data->set.upload_buffer_size = (unsigned int)arg; Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */ break; @@ -2238,24 +2311,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl.enable_beast = - (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN); data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT); data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); + data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT); + /* If a setting is added here it should also be added in dohprobe() + which sets its own CURLOPT_SSL_OPTIONS based on these settings. */ break; #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXY_SSL_OPTIONS: arg = va_arg(param, long); - data->set.proxy_ssl.enable_beast = - (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN); - data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); data->set.proxy_ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT); + data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); + data->set.proxy_ssl.auto_client_cert = + !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT); break; #endif @@ -2662,9 +2738,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #endif #ifdef USE_TLS_SRP case CURLOPT_TLSAUTH_USERNAME: - result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; case CURLOPT_PROXY_TLSAUTH_USERNAME: @@ -2677,9 +2753,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) #endif break; case CURLOPT_TLSAUTH_PASSWORD: - result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; case CURLOPT_PROXY_TLSAUTH_PASSWORD: @@ -2863,7 +2939,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.trailer_data = va_arg(param, void *); #endif break; -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS case CURLOPT_HSTSREADFUNCTION: data->set.hsts_read = va_arg(param, curl_hstsread_callback); break; diff --git a/lib/setup-vms.h b/lib/setup-vms.h index ba75dc295b0..a6710d90764 100644 --- a/lib/setup-vms.h +++ b/lib/setup-vms.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -87,7 +87,7 @@ static char *vms_translate_path(const char *path) /* See if the result is in VMS format, if not, we are done */ /* Assume that this is a PATH, not just some data */ test_str = strpbrk(path, ":[<^"); - if(test_str == NULL) { + if(!test_str) { return (char *)path; } @@ -119,7 +119,7 @@ static char *vms_getenv(const char *envvar) /* first use the DECC getenv() function */ result = decc$getenv(envvar); - if(result == NULL) { + if(!result) { return result; } @@ -154,7 +154,7 @@ static struct passwd *vms_getpwuid(uid_t uid) #endif my_passwd = decc_getpwuid(uid); - if(my_passwd == NULL) { + if(!my_passwd) { return my_passwd; } diff --git a/lib/sha256.c b/lib/sha256.c index d915117917f..c34f97e8f6c 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2017, Florin Petriuc, - * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -50,11 +50,10 @@ /* Please keep the SSL backend-specific #if branches in this order: * * 1. USE_OPENSSL - * 2. USE_GNUTLS_NETTLE - * 3. USE_GNUTLS - * 4. USE_MBEDTLS - * 5. USE_COMMON_CRYPTO - * 6. USE_WIN32_CRYPTO + * 2. USE_GNUTLS + * 3. USE_MBEDTLS + * 4. USE_COMMON_CRYPTO + * 5. USE_WIN32_CRYPTO * * This ensures that the same SSL branch gets activated throughout this source * file even if multiple backends are enabled at the same time. @@ -65,7 +64,7 @@ /* When OpenSSL is available we use the SHA256-function from OpenSSL */ #include -#elif defined(USE_GNUTLS_NETTLE) +#elif defined(USE_GNUTLS) #include @@ -93,35 +92,6 @@ static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) sha256_digest(ctx, SHA256_DIGEST_SIZE, digest); } -#elif defined(USE_GNUTLS) - -#include - -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -typedef gcry_md_hd_t SHA256_CTX; - -static void SHA256_Init(SHA256_CTX *ctx) -{ - gcry_md_open(ctx, GCRY_MD_SHA256, 0); -} - -static void SHA256_Update(SHA256_CTX *ctx, - const unsigned char *data, - unsigned int length) -{ - gcry_md_write(*ctx, data, length); -} - -static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) -{ - memcpy(digest, gcry_md_read(*ctx, 0), SHA256_DIGEST_LENGTH); - gcry_md_close(*ctx); -} - #elif defined(USE_MBEDTLS) #include diff --git a/lib/share.c b/lib/share.c index 4f1804dbd2b..9c43c8f7053 100644 --- a/lib/share.c +++ b/lib/share.c @@ -235,7 +235,7 @@ Curl_share_lock(struct Curl_easy *data, curl_lock_data type, { struct Curl_share *share = data->share; - if(share == NULL) + if(!share) return CURLSHE_INVALID; if(share->specifier & (1<share; - if(share == NULL) + if(!share) return CURLSHE_INVALID; if(share->specifier & (1<, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,7 +24,7 @@ #include "curl_setup.h" #if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \ - (defined(USE_OPENSSL) || defined(USE_MBEDTLS)) + (defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL)) #include struct sigpipe_ignore { diff --git a/lib/smb.c b/lib/smb.c index dd4e4fdbf6c..39facb267d9 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -24,7 +24,7 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (CURL_SIZEOF_CURL_OFF_T > 4) + (SIZEOF_CURL_OFF_T > 4) #define BUILDING_CURL_SMB_C @@ -88,6 +88,7 @@ const struct Curl_handler Curl_handler_smb = { smb_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMB, /* defport */ CURLPROTO_SMB, /* protocol */ CURLPROTO_SMB, /* family */ @@ -114,6 +115,7 @@ const struct Curl_handler Curl_handler_smbs = { smb_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMBS, /* defport */ CURLPROTO_SMBS, /* protocol */ CURLPROTO_SMB, /* family */ @@ -627,9 +629,8 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg) /* Check if there is data in the transfer buffer */ if(!smbc->send_size && smbc->upload_size) { - size_t nread = smbc->upload_size > data->set.upload_buffer_size ? - data->set.upload_buffer_size : - smbc->upload_size; + size_t nread = smbc->upload_size > (size_t)data->set.upload_buffer_size ? + (size_t)data->set.upload_buffer_size : smbc->upload_size; data->req.upload_fromhere = data->state.ulbuf; result = Curl_fillreadbuffer(data, nread, &nread); if(result && result != CURLE_AGAIN) @@ -1022,4 +1023,4 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data, } #endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE && - CURL_SIZEOF_CURL_OFF_T > 4 */ + SIZEOF_CURL_OFF_T > 4 */ diff --git a/lib/smb.h b/lib/smb.h index 907cf0c8e20..0e3c2ec112a 100644 --- a/lib/smb.h +++ b/lib/smb.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014, Bill Nagel , Exacq Technologies - * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -244,12 +244,12 @@ struct smb_tree_disconnect { #endif /* BUILDING_CURL_SMB_C */ #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (CURL_SIZEOF_CURL_OFF_T > 4) + (SIZEOF_CURL_OFF_T > 4) extern const struct Curl_handler Curl_handler_smb; extern const struct Curl_handler Curl_handler_smbs; #endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE && - CURL_SIZEOF_CURL_OFF_T > 4 */ + SIZEOF_CURL_OFF_T > 4 */ #endif /* HEADER_CURL_SMB_H */ diff --git a/lib/smtp.c b/lib/smtp.c index 1fc880065a7..feffc05bc9d 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_smtp = { smtp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMTP, /* defport */ CURLPROTO_SMTP, /* protocol */ CURLPROTO_SMTP, /* family */ @@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_smtps = { smtp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SMTPS, /* defport */ CURLPROTO_SMTPS, /* protocol */ CURLPROTO_SMTP, /* family */ @@ -894,7 +896,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data, for(;;) { size_t llen; size_t wordlen; - unsigned int mechbit; + unsigned short mechbit; while(len && (*line == ' ' || *line == '\t' || @@ -1433,7 +1435,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status, } /* Clear the transfer mode for the next request */ - smtp->transfer = FTPTRANSFER_BODY; + smtp->transfer = PPTRANSFER_BODY; return result; } @@ -1457,7 +1459,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected, if(data->set.opt_no_body) { /* Requested no body means no transfer */ - smtp->transfer = FTPTRANSFER_INFO; + smtp->transfer = PPTRANSFER_INFO; } *dophase_done = FALSE; /* not done yet */ @@ -1564,7 +1566,7 @@ static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected) (void)connected; - if(smtp->transfer != FTPTRANSFER_BODY) + if(smtp->transfer != PPTRANSFER_BODY) /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); @@ -1821,7 +1823,7 @@ CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread) return CURLE_OUT_OF_MEMORY; } } - DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread); + DEBUGASSERT((size_t)data->set.upload_buffer_size >= (size_t)nread); /* Have we already sent part of the EOB? */ eob_sent = smtp->eob; diff --git a/lib/socketpair.h b/lib/socketpair.h index 033a235aa2c..cdcc0b921eb 100644 --- a/lib/socketpair.h +++ b/lib/socketpair.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2019 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,7 +30,4 @@ int Curl_socketpair(int domain, int type, int protocol, #define Curl_socketpair(a,b,c,d) socketpair(a,b,c,d) #endif -/* Defined here to allow specific build configs to disable it completely */ -#define USE_SOCKETPAIR 1 - #endif /* HEADER_CURL_SOCKETPAIR_H */ diff --git a/lib/socks.c b/lib/socks.c index d1c2a2ed147..5cde4a46a12 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -426,7 +426,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, */ /* wrong version ? */ - if(socksreq[0] != 0) { + if(socksreq[0]) { failf(data, "SOCKS4 reply has wrong version, version should be 0."); return CURLPX_BAD_VERSION; @@ -742,7 +742,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, return CURLPX_OK; } /* ignore the first (VER) byte */ - else if(socksreq[1] != 0) { /* status */ + else if(socksreq[1]) { /* status */ failf(data, "User was rejected by the SOCKS5 server (%d %d).", socksreq[0], socksreq[1]); return CURLPX_USER_REJECTED; @@ -927,7 +927,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, "SOCKS5 reply has wrong version, version should be 5."); return CURLPX_BAD_VERSION; } - else if(socksreq[1] != 0) { /* Anything besides 0 is an error */ + else if(socksreq[1]) { /* Anything besides 0 is an error */ CURLproxycode rc = CURLPX_REPLY_UNASSIGNED; int code = socksreq[1]; failf(data, "Can't complete SOCKS5 connection to %s. (%d)", diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index 3ab786d0bd7..10b942a984b 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -195,7 +195,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(gss_send_token.length != 0) { + if(gss_send_token.length) { socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 1; /* authentication message type */ us_length = htons((short)gss_send_token.length); diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index b343538f0c2..813c6be574e 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -198,7 +198,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_COULDNT_CONNECT; } - if(sspi_send_token.cbBuffer != 0) { + if(sspi_send_token.cbBuffer) { socksreq[0] = 1; /* GSS-API subnegotiation version */ socksreq[1] = 1; /* authentication message type */ us_length = htons((short)sspi_send_token.cbBuffer); diff --git a/lib/splay.c b/lib/splay.c index 98baf5d871c..a94e2c85e91 100644 --- a/lib/splay.c +++ b/lib/splay.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1997 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1997 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -42,7 +42,7 @@ struct Curl_tree *Curl_splay(struct curltime i, { struct Curl_tree N, *l, *r, *y; - if(t == NULL) + if(!t) return t; N.smaller = N.larger = NULL; l = r = &N; @@ -50,14 +50,14 @@ struct Curl_tree *Curl_splay(struct curltime i, for(;;) { long comp = compare(i, t->key); if(comp < 0) { - if(t->smaller == NULL) + if(!t->smaller) break; if(compare(i, t->smaller->key) < 0) { y = t->smaller; /* rotate smaller */ t->smaller = y->larger; y->larger = t; t = y; - if(t->smaller == NULL) + if(!t->smaller) break; } r->smaller = t; /* link smaller */ @@ -65,14 +65,14 @@ struct Curl_tree *Curl_splay(struct curltime i, t = t->smaller; } else if(comp > 0) { - if(t->larger == NULL) + if(!t->larger) break; if(compare(i, t->larger->key) > 0) { y = t->larger; /* rotate larger */ t->larger = y->smaller; y->smaller = t; t = y; - if(t->larger == NULL) + if(!t->larger) break; } l->larger = t; /* link larger */ @@ -104,7 +104,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i, (time_t)-1, (unsigned int)-1 }; /* will *NEVER* appear */ - if(node == NULL) + if(!node) return t; if(t != NULL) { @@ -125,7 +125,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i, } } - if(t == NULL) { + if(!t) { node->smaller = node->larger = NULL; } else if(compare(i, t->key) < 0) { @@ -262,7 +262,7 @@ int Curl_splayremove(struct Curl_tree *t, } else { /* Remove the root node */ - if(t->smaller == NULL) + if(!t->smaller) x = t->larger; else { x = Curl_splay(removenode->key, t->smaller); diff --git a/lib/strerror.c b/lib/strerror.c index 3862aabd6fb..5298a0d76c1 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -320,9 +320,12 @@ curl_easy_strerror(CURLcode error) case CURLE_QUIC_CONNECT_ERROR: return "QUIC connection error"; - case CURLE_PROXY: + case CURLE_PROXY: return "proxy handshake error"; + case CURLE_SSL_CLIENTCERT: + return "SSL Client Certificate required"; + /* error codes not used by current libcurl */ case CURLE_OBSOLETE20: case CURLE_OBSOLETE24: diff --git a/lib/system_win32.c b/lib/system_win32.c index 2132f43ef75..2939fd0d74b 100644 --- a/lib/system_win32.c +++ b/lib/system_win32.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2016 - 2020, Steve Holme, . + * Copyright (C) 2016 - 2021, Steve Holme, . * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -58,7 +58,7 @@ CURLcode Curl_win32_init(long flags) wVersionRequested = MAKEWORD(2, 2); res = WSAStartup(wVersionRequested, &wsaData); - if(res != 0) + if(res) /* Tell the user that we couldn't find a usable */ /* winsock.dll. */ return CURLE_FAILED_INIT; diff --git a/lib/telnet.c b/lib/telnet.c index f96a4cb4c5f..fdd137fb0c0 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -185,6 +185,7 @@ const struct Curl_handler Curl_handler_telnet = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_TELNET, /* defport */ CURLPROTO_TELNET, /* protocol */ CURLPROTO_TELNET, /* family */ @@ -921,7 +922,7 @@ static void suboption(struct Curl_easy *data) size_t tmplen = (strlen(v->data) + 1); /* Add the variable only if it fits */ if(len + tmplen < (int)sizeof(temp)-6) { - if(sscanf(v->data, "%127[^,],%127s", varname, varval)) { + if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) { msnprintf((char *)&temp[len], sizeof(temp) - len, "%c%s%c%s", CURL_NEW_ENV_VAR, varname, CURL_NEW_ENV_VALUE, varval); diff --git a/lib/tftp.c b/lib/tftp.c index 3f1d1b51b7c..11150af3614 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -129,8 +129,6 @@ struct tftp_state_data { int retries; int retry_time; int retry_max; - time_t start_time; - time_t max_time; time_t rx_time; struct Curl_sockaddr_storage local_addr; struct Curl_sockaddr_storage remote_addr; @@ -184,6 +182,7 @@ const struct Curl_handler Curl_handler_tftp = { tftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_TFTP, /* defport */ CURLPROTO_TFTP, /* protocol */ CURLPROTO_TFTP, /* family */ @@ -206,8 +205,6 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state) timediff_t timeout_ms; bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; - time(&state->start_time); - /* Compute drop-dead time */ timeout_ms = Curl_timeleft(state->data, NULL, start); @@ -217,41 +214,17 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state) return CURLE_OPERATION_TIMEDOUT; } - if(start) { - + if(timeout_ms > 0) maxtime = (time_t)(timeout_ms + 500) / 1000; - state->max_time = state->start_time + maxtime; - - /* Set per-block timeout to total */ - timeout = maxtime; - - /* Average restart after 5 seconds */ - state->retry_max = (int)timeout/5; - - if(state->retry_max < 1) - /* avoid division by zero below */ - state->retry_max = 1; - - /* Compute the re-start interval to suit the timeout */ - state->retry_time = (int)timeout/state->retry_max; - if(state->retry_time<1) - state->retry_time = 1; - - } - else { - if(timeout_ms > 0) - maxtime = (time_t)(timeout_ms + 500) / 1000; - else - maxtime = 3600; + else + maxtime = 3600; /* use for calculating block timeouts */ - state->max_time = state->start_time + maxtime; + /* Set per-block timeout to total */ + timeout = maxtime; - /* Set per-block timeout to total */ - timeout = maxtime; + /* Average reposting an ACK after 5 seconds */ + state->retry_max = (int)timeout/5; - /* Average reposting an ACK after 5 seconds */ - state->retry_max = (int)timeout/5; - } /* But bound the total number */ if(state->retry_max<3) state->retry_max = 3; @@ -265,9 +238,9 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state) state->retry_time = 1; infof(state->data, - "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", - (int)state->state, (long)(state->max_time-state->start_time), - state->retry_time, state->retry_max); + "set timeouts for state %d; Total % " CURL_FORMAT_CURL_OFF_T + ", retry %d maxtry %d\n", + (int)state->state, timeout_ms, state->retry_time, state->retry_max); /* init RX time */ time(&state->rx_time); @@ -347,7 +320,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, const char *option, *value; tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); - if(tmp == NULL) { + if(!tmp) { failf(data, "Malformed ACK packet, rejecting"); return CURLE_TFTP_ILLEGAL; } @@ -460,7 +433,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, CURLcode result = CURLE_OK; /* Set ascii mode if -B flag was used */ - if(data->set.prefer_ascii) + if(data->state.prefer_ascii) mode = "netascii"; switch(event) { @@ -804,7 +777,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) return result; state->sbytes += (int)cb; state->data->req.upload_fromhere += cb; - } while(state->sbytes < state->blksize && cb != 0); + } while(state->sbytes < state->blksize && cb); sbytes = sendto(state->sockfd, (void *) state->spacket.data, 4 + state->sbytes, SEND_4TH_ARG, @@ -1215,33 +1188,32 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data) * Check if timeouts have been reached * **********************************************************/ -static long tftp_state_timeout(struct Curl_easy *data, tftp_event_t *event) +static timediff_t tftp_state_timeout(struct Curl_easy *data, + tftp_event_t *event) { time_t current; struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; + timediff_t timeout_ms; if(event) *event = TFTP_EVENT_NONE; - time(¤t); - if(current > state->max_time) { - DEBUGF(infof(data, "timeout: %ld > %ld\n", - (long)current, (long)state->max_time)); + timeout_ms = Curl_timeleft(state->data, NULL, + (state->state == TFTP_STATE_START)); + if(timeout_ms < 0) { state->error = TFTP_ERR_TIMEOUT; state->state = TFTP_STATE_FIN; return 0; } + time(¤t); if(current > state->rx_time + state->retry_time) { if(event) *event = TFTP_EVENT_TIMEOUT; time(&state->rx_time); /* update even though we received nothing */ } - /* there's a typecast below here since 'time_t' may in fact be larger than - 'long', but we estimate that a 'long' will still be able to hold number - of seconds even if "only" 32 bit */ - return (long)(state->max_time - current); + return timeout_ms; } /********************************************************** @@ -1257,11 +1229,11 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done) CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; struct tftp_state_data *state = conn->proto.tftpc; - long timeout_ms = tftp_state_timeout(data, &event); + timediff_t timeout_ms = tftp_state_timeout(data, &event); *done = FALSE; - if(timeout_ms <= 0) { + if(timeout_ms < 0) { failf(data, "TFTP response timeout"); return CURLE_OPERATION_TIMEDOUT; } @@ -1285,7 +1257,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done) failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); state->event = TFTP_EVENT_ERROR; } - else if(rc != 0) { + else if(rc) { result = tftp_receive_packet(data); if(result) return result; @@ -1420,14 +1392,14 @@ static CURLcode tftp_setup_connection(struct Curl_easy *data, switch(command) { case 'A': /* ASCII mode */ case 'N': /* NETASCII mode */ - data->set.prefer_ascii = TRUE; + data->state.prefer_ascii = TRUE; break; case 'O': /* octet mode */ case 'I': /* binary mode */ default: /* switch off ASCII */ - data->set.prefer_ascii = FALSE; + data->state.prefer_ascii = FALSE; break; } } diff --git a/lib/timeval.c b/lib/timeval.c index 8523dad4009..ca98fe50e50 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -78,14 +78,16 @@ struct curltime Curl_now(void) ** code compiles but fails during run-time if clock_gettime() is ** called on unsupported OS version. */ -#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) +#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ + (HAVE_BUILTIN_AVAILABLE == 1) bool have_clock_gettime = FALSE; if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) have_clock_gettime = TRUE; #endif if( -#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1) +#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ + (HAVE_BUILTIN_AVAILABLE == 1) have_clock_gettime && #endif (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) { diff --git a/lib/transfer.c b/lib/transfer.c index 2f29b29d8e6..bca4e548fae 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -79,6 +79,7 @@ #include "strcase.h" #include "urlapi-int.h" #include "hsts.h" +#include "setopt.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -98,6 +99,8 @@ char *Curl_checkheaders(const struct Curl_easy *data, { struct curl_slist *head; size_t thislen = strlen(thisheader); + DEBUGASSERT(thislen); + DEBUGASSERT(thisheader[thislen-1] != ':'); for(head = data->set.headers; head; head = head->next) { if(strncasecompare(head->data, thisheader, thislen) && @@ -286,7 +289,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, * CRLF */ /* On non-ASCII platforms the may or may not be - translated based on set.prefer_ascii while the protocol + translated based on state.prefer_ascii while the protocol portion must always be translated to the network encoding. To further complicate matters, line end conversion might be done later on, so we need to prevent CRLFs from becoming @@ -301,7 +304,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, if( #ifdef CURL_DO_LINEEND_CONV - (data->set.prefer_ascii) || + (data->state.prefer_ascii) || #endif (data->set.crlf)) { /* \n will become \r\n later on */ @@ -348,7 +351,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, { CURLcode result; size_t length; - if(data->set.prefer_ascii) + if(data->state.prefer_ascii) /* translate the protocol and data */ length = nread; else @@ -389,7 +392,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, nread += strlen(endofline_network); /* for the added end of line */ } #ifdef CURL_DOES_CONVERSIONS - else if((data->set.prefer_ascii) && (!sending_http_headers)) { + else if((data->state.prefer_ascii) && (!sending_http_headers)) { CURLcode result; result = Curl_convert_to_network(data, data->req.upload_fromhere, nread); /* Curl_convert_to_network calls failf if unsuccessful */ @@ -494,11 +497,13 @@ static int data_pending(const struct Curl_easy *data) return Curl_quic_data_pending(data); #endif + if(conn->handler->protocol&PROTO_FAMILY_FTP) + return Curl_ssl_data_pending(conn, SECONDARYSOCKET); + /* in the case of libssh2, we can never be really sure that we have emptied its internal buffers so we MUST always try until we get EAGAIN back */ return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || #if defined(USE_NGHTTP2) - Curl_ssl_data_pending(conn, FIRSTSOCKET) || /* For HTTP/2, we may read up everything including response body with header fields in Curl_http_readwrite_headers. If no content-length is provided, curl waits for the connection @@ -506,10 +511,9 @@ static int data_pending(const struct Curl_easy *data) TRUE. The thing is if we read everything, then http2_recv won't be called and we cannot signal the HTTP/2 stream has closed. As a workaround, we return nonzero here to call http2_recv. */ - ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20); -#else - Curl_ssl_data_pending(conn, FIRSTSOCKET); + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20) || #endif + Curl_ssl_data_pending(conn, FIRSTSOCKET); } /* @@ -829,7 +833,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, Make sure that ALL_CONTENT_ENCODINGS contains all the encodings handled here. */ if(data->set.http_ce_skip || !k->writer_stack) { - if(!k->ignorebody) { + if(!k->ignorebody && nread) { #ifndef CURL_DISABLE_POP3 if(conn->handler->protocol & PROTO_FAMILY_POP3) result = Curl_pop3_write(data, k->str, nread); @@ -839,7 +843,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, nread); } } - else if(!k->ignorebody) + else if(!k->ignorebody && nread) result = Curl_unencode_write(data, k->writer_stack, k->str, nread); } k->badheader = HEADER_NORMAL; /* taken care of now */ @@ -1028,7 +1032,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, if((!sending_http_headers) && ( #ifdef CURL_DO_LINEEND_CONV /* always convert if we're FTPing in ASCII mode */ - (data->set.prefer_ascii) || + (data->state.prefer_ascii) || #endif (data->set.crlf))) { /* Do we need to allocate a scratch buffer? */ @@ -1391,20 +1395,20 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) { CURLcode result; - if(!data->change.url && !data->set.uh) { + if(!data->state.url && !data->set.uh) { /* we can't do anything without URL */ failf(data, "No URL set!"); return CURLE_URL_MALFORMAT; } /* since the URL may have been redirected in a previous use of this handle */ - if(data->change.url_alloc) { + if(data->state.url_alloc) { /* the already set URL is allocated, free it first! */ - Curl_safefree(data->change.url); - data->change.url_alloc = FALSE; + Curl_safefree(data->state.url); + data->state.url_alloc = FALSE; } - if(!data->change.url && data->set.uh) { + if(!data->state.url && data->set.uh) { CURLUcode uc; free(data->set.str[STRING_SET_URL]); uc = curl_url_get(data->set.uh, @@ -1415,8 +1419,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) } } + data->state.prefer_ascii = data->set.prefer_ascii; + data->state.list_only = data->set.list_only; data->state.httpreq = data->set.method; - data->change.url = data->set.str[STRING_SET_URL]; + data->state.url = data->set.str[STRING_SET_URL]; /* Init the SSL session ID cache here. We do it here since we want to do it after the *_setopt() calls (that could specify the size of the cache) but @@ -1426,11 +1432,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) return result; data->state.wildcardmatch = data->set.wildcard_enabled; - data->set.followlocation = 0; /* reset the location-follow counter */ + data->state.followlocation = 0; /* reset the location-follow counter */ data->state.this_is_a_follow = FALSE; /* reset this */ data->state.errorbuf = FALSE; /* no error has occurred */ - data->state.httpversion = 0; /* don't assume any particular server version */ - + data->state.httpwant = data->set.httpwant; + data->state.httpversion = 0; data->state.authproblem = FALSE; data->state.authhost.want = data->set.httpauth; data->state.authproxy.want = data->set.proxyauth; @@ -1448,11 +1454,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) data->state.infilesize = 0; /* If there is a list of cookie files to read, do it now! */ - if(data->change.cookielist) + if(data->state.cookielist) Curl_cookie_loadfiles(data); /* If there is a list of host pairs to deal with */ - if(data->change.resolve) + if(data->state.resolve) result = Curl_loadhostpairs(data); if(!result) { @@ -1506,6 +1512,19 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; } + if(!result) + result = Curl_setstropt(&data->state.aptr.user, + data->set.str[STRING_USERNAME]); + if(!result) + result = Curl_setstropt(&data->state.aptr.passwd, + data->set.str[STRING_PASSWORD]); + if(!result) + result = Curl_setstropt(&data->state.aptr.proxyuser, + data->set.str[STRING_PROXYUSERNAME]); + if(!result) + result = Curl_setstropt(&data->state.aptr.proxypasswd, + data->set.str[STRING_PROXYPASSWORD]); + data->req.headerbytecount = 0; return result; } @@ -1553,7 +1572,7 @@ CURLcode Curl_follow(struct Curl_easy *data, if(type == FOLLOW_REDIR) { if((data->set.maxredirs != -1) && - (data->set.followlocation >= data->set.maxredirs)) { + (data->state.followlocation >= data->set.maxredirs)) { reachedmax = TRUE; type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected to URL */ @@ -1562,22 +1581,43 @@ CURLcode Curl_follow(struct Curl_easy *data, /* mark the next request as a followed location: */ data->state.this_is_a_follow = TRUE; - data->set.followlocation++; /* count location-followers */ + data->state.followlocation++; /* count location-followers */ if(data->set.http_auto_referer) { + CURLU *u; + char *referer = NULL; + /* We are asked to automatically set the previous URL as the referer when we get the next URL. We pick the ->url field, which may or may not be 100% correct */ - if(data->change.referer_alloc) { - Curl_safefree(data->change.referer); - data->change.referer_alloc = FALSE; + if(data->state.referer_alloc) { + Curl_safefree(data->state.referer); + data->state.referer_alloc = FALSE; } - data->change.referer = strdup(data->change.url); - if(!data->change.referer) + /* Make a copy of the URL without crenditals and fragment */ + u = curl_url(); + if(!u) + return CURLE_OUT_OF_MEMORY; + + uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0); + if(!uc) + uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0); + if(!uc) + uc = curl_url_set(u, CURLUPART_USER, NULL, 0); + if(!uc) + uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0); + if(!uc) + uc = curl_url_get(u, CURLUPART_URL, &referer, 0); + + curl_url_cleanup(u); + + if(uc || !referer) return CURLE_OUT_OF_MEMORY; - data->change.referer_alloc = TRUE; /* yes, free this later */ + + data->state.referer = referer; + data->state.referer_alloc = TRUE; /* yes, free this later */ } } } @@ -1625,13 +1665,13 @@ CURLcode Curl_follow(struct Curl_easy *data, if(disallowport) data->state.allow_port = FALSE; - if(data->change.url_alloc) - Curl_safefree(data->change.url); + if(data->state.url_alloc) + Curl_safefree(data->state.url); - data->change.url = newurl; - data->change.url_alloc = TRUE; + data->state.url = newurl; + data->state.url_alloc = TRUE; - infof(data, "Issue another request to this URL: '%s'\n", data->change.url); + infof(data, "Issue another request to this URL: '%s'\n", data->state.url); /* * We get here when the HTTP code is 300-399 (and 401). We need to perform @@ -1792,7 +1832,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) } infof(data, "Connection died, retrying a fresh connect\ (retry count: %d)\n", data->state.retrycount); - *url = strdup(data->change.url); + *url = strdup(data->state.url); if(!*url) return CURLE_OUT_OF_MEMORY; diff --git a/lib/url.c b/lib/url.c index c02d2c2019d..1ee38af0d56 100644 --- a/lib/url.c +++ b/lib/url.c @@ -234,7 +234,7 @@ static const struct Curl_handler * const protocols[] = { #endif #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (CURL_SIZEOF_CURL_OFF_T > 4) + (SIZEOF_CURL_OFF_T > 4) &Curl_handler_smb, #ifdef USE_SSL &Curl_handler_smbs, @@ -292,6 +292,7 @@ static const struct Curl_handler Curl_handler_dummy = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ 0, /* defport */ 0, /* protocol */ 0, /* family */ @@ -312,16 +313,16 @@ void Curl_freeset(struct Curl_easy *data) Curl_safefree(data->set.blobs[j]); } - if(data->change.referer_alloc) { - Curl_safefree(data->change.referer); - data->change.referer_alloc = FALSE; + if(data->state.referer_alloc) { + Curl_safefree(data->state.referer); + data->state.referer_alloc = FALSE; } - data->change.referer = NULL; - if(data->change.url_alloc) { - Curl_safefree(data->change.url); - data->change.url_alloc = FALSE; + data->state.referer = NULL; + if(data->state.url_alloc) { + Curl_safefree(data->state.url); + data->state.url_alloc = FALSE; } - data->change.url = NULL; + data->state.url = NULL; Curl_mime_cleanpart(&data->set.mimepost); } @@ -405,11 +406,11 @@ CURLcode Curl_close(struct Curl_easy **datap) free(data->req.newurl); data->req.newurl = NULL; - if(data->change.referer_alloc) { - Curl_safefree(data->change.referer); - data->change.referer_alloc = FALSE; + if(data->state.referer_alloc) { + Curl_safefree(data->state.referer); + data->state.referer_alloc = FALSE; } - data->change.referer = NULL; + data->state.referer = NULL; up_free(data); Curl_safefree(data->state.buffer); @@ -449,6 +450,10 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->state.aptr.host); Curl_safefree(data->state.aptr.cookiehost); Curl_safefree(data->state.aptr.rtsp_transport); + Curl_safefree(data->state.aptr.user); + Curl_safefree(data->state.aptr.passwd); + Curl_safefree(data->state.aptr.proxyuser); + Curl_safefree(data->state.aptr.proxypasswd); #ifndef CURL_DISABLE_DOH if(data->req.doh) { @@ -530,6 +535,8 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) * libcurl 7.10 introduced SSL verification *by default*! This needs to be * switched off unless wanted. */ + set->doh_verifyhost = TRUE; + set->doh_verifypeer = TRUE; set->ssl.primary.verifypeer = TRUE; set->ssl.primary.verifyhost = TRUE; #ifdef USE_TLS_SRP @@ -569,7 +576,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) */ if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) { #if defined(CURL_CA_BUNDLE) - result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE); + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE); if(result) return result; @@ -579,7 +586,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) return result; #endif #if defined(CURL_CA_PATH) - result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH); + result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH); if(result) return result; @@ -609,7 +616,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ set->maxage_conn = 118; set->http09_allowed = FALSE; - set->httpversion = + set->httpwant = #ifdef USE_NGHTTP2 CURL_HTTP_VERSION_2TLS #else @@ -837,7 +844,7 @@ CURLcode Curl_disconnect(struct Curl_easy *data, dead_connection = TRUE; /* temporarily attach the connection to this transfer handle for the - disonnect and shutdown */ + disconnect and shutdown */ Curl_attach_connnection(data, conn); if(conn->handler->disconnect) @@ -887,7 +894,7 @@ static int IsMultiplexingPossible(const struct Curl_easy *handle, (!conn->bits.protoconnstart || !conn->bits.close)) { if(Curl_multiplex_wanted(handle->multi) && - (handle->set.httpversion >= CURL_HTTP_VERSION_2)) + (handle->state.httpwant >= CURL_HTTP_VERSION_2)) /* allows HTTP/2 */ avail |= CURLPIPE_MULTIPLEX; } @@ -917,14 +924,14 @@ socks_proxy_info_matches(const struct proxy_info *data, /* the user information is case-sensitive or at least it is not defined as case-insensitive see https://tools.ietf.org/html/rfc3986#section-3.2.1 */ - if((data->user == NULL) != (needle->user == NULL)) + if(!data->user != !needle->user) return FALSE; /* curl_strequal does a case insentive comparison, so do not use it here! */ if(data->user && needle->user && strcmp(data->user, needle->user) != 0) return FALSE; - if((data->passwd == NULL) != (needle->passwd == NULL)) + if(!data->passwd != !needle->passwd) return FALSE; /* curl_strequal does a case insentive comparison, so do not use it here! */ if(data->passwd && @@ -986,12 +993,12 @@ static bool extract_if_dead(struct connectdata *conn, /* briefly attach the connection to this transfer for the purpose of checking it */ Curl_attach_connnection(data, conn); - conn->data = data; /* find the way back if necessary */ + state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD); dead = (state & CONNRESULT_DEAD); /* detach the connection again */ Curl_detach_connnection(data); - conn->data = NULL; /* clear it again */ + } else { /* Use the general method for determining the death of a connection */ @@ -1092,13 +1099,13 @@ ConnectionExists(struct Curl_easy *data, #ifdef USE_NTLM bool wantNTLMhttp = ((data->state.authhost.want & - (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && - (needle->handler->protocol & PROTO_FAMILY_HTTP)); + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP)); #ifndef CURL_DISABLE_PROXY bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd && - ((data->state.authproxy.want & - (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && - (needle->handler->protocol & PROTO_FAMILY_HTTP))); + ((data->state.authproxy.want & + (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && + (needle->handler->protocol & PROTO_FAMILY_HTTP))); #else bool wantProxyNTLMhttp = FALSE; #endif @@ -1165,6 +1172,12 @@ ConnectionExists(struct Curl_easy *data, continue; } + if(data->set.ipver != CURL_IPRESOLVE_WHATEVER + && data->set.ipver != check->ip_version) { + /* skip because the connection is not via the requested IP version */ + continue; + } + if(bundle->multiuse == BUNDLE_MULTIPLEX) multiplexed = CONN_INUSE(check); @@ -1266,17 +1279,19 @@ ConnectionExists(struct Curl_easy *data, } #endif - DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data)); - - if(!canmultiplex && check->data) + if(!canmultiplex && CONN_INUSE(check)) /* this request can't be multiplexed but the checked connection is already in use so we skip it */ continue; - if(check->data && (check->data->multi != needle->data->multi)) - /* this could be subject for multiplex use, but only if they belong to - * the same multi handle */ - continue; + if(CONN_INUSE(check)) { + /* Subject for multiplex use if 'checks' belongs to the same multi + handle as 'data' is. */ + struct Curl_llist_element *e = check->easyq.head; + struct Curl_easy *entry = e->ptr; + if(entry->multi != data->multi) + continue; + } if(needle->localdev || needle->localport) { /* If we are bound to a specific local end (IP+port), we must not @@ -1307,6 +1322,13 @@ ConnectionExists(struct Curl_easy *data, } } + /* If multiplexing isn't enabled on the h2 connection and h1 is + explicitly requested, handle it: */ + if((needle->handler->protocol & PROTO_FAMILY_HTTP) && + (check->httpversion >= 20) && + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + continue; + if((needle->handler->flags&PROTOPT_SSL) #ifndef CURL_DISABLE_PROXY || !needle->bits.httpproxy || needle->bits.tunnel_proxy @@ -1435,7 +1457,7 @@ ConnectionExists(struct Curl_easy *data, continue; } else if(multiplexed >= - Curl_multi_max_concurrent_streams(needle->data->multi)) { + Curl_multi_max_concurrent_streams(data->multi)) { infof(data, "client side MAX_CONCURRENT_STREAMS reached" ", skip (%zu)\n", multiplexed); @@ -1459,7 +1481,6 @@ ConnectionExists(struct Curl_easy *data, if(chosen) { /* mark it as used before releasing the lock */ - chosen->data = data; /* own it! */ Curl_attach_connnection(data, chosen); CONNCACHE_UNLOCK(data); *usethis = chosen; @@ -1674,9 +1695,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) /* Store current time to give a baseline to keepalive connection times. */ conn->keepalive = Curl_now(); - conn->data = data; /* Setup the association between this connection - and the Curl_easy */ - #ifndef CURL_DISABLE_PROXY conn->http_proxy.proxytype = data->set.proxytype; conn->socks_proxy.proxytype = CURLPROXY_SOCKS4; @@ -1699,11 +1717,11 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) } conn->bits.proxy_user_passwd = - (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE; + (data->state.aptr.proxyuser) ? TRUE : FALSE; conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; #endif /* CURL_DISABLE_PROXY */ - conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE; + conn->bits.user_passwd = (data->state.aptr.user) ? TRUE : FALSE; #ifndef CURL_DISABLE_FTP conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; @@ -1896,28 +1914,27 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; if(data->set.str[STRING_DEFAULT_PROTOCOL] && - !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) { - char *url; - if(data->change.url_alloc) - free(data->change.url); - url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL], - data->change.url); + !Curl_is_absolute_url(data->state.url, NULL, MAX_SCHEME_LEN)) { + char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL], + data->state.url); if(!url) return CURLE_OUT_OF_MEMORY; - data->change.url = url; - data->change.url_alloc = TRUE; + if(data->state.url_alloc) + free(data->state.url); + data->state.url = url; + data->state.url_alloc = TRUE; } if(!use_set_uh) { char *newurl; - uc = curl_url_set(uh, CURLUPART_URL, data->change.url, + uc = curl_url_set(uh, CURLUPART_URL, data->state.url, CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME | (data->set.disallow_username_in_url ? CURLU_DISALLOW_USER : 0) | (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)); if(uc) { - DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url)); + DEBUGF(infof(data, "curl_url_set rejected %s\n", data->state.url)); return Curl_uc_to_curlcode(uc); } @@ -1925,10 +1942,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0); if(uc) return Curl_uc_to_curlcode(uc); - if(data->change.url_alloc) - free(data->change.url); - data->change.url = newurl; - data->change.url_alloc = TRUE; + if(data->state.url_alloc) + free(data->state.url); + data->state.url = newurl; + data->state.url_alloc = TRUE; } uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0); @@ -1941,7 +1958,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS if(data->hsts && strcasecompare("http", data->state.up.scheme)) { if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) { char *url; @@ -1949,19 +1966,21 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0); if(uc) return Curl_uc_to_curlcode(uc); - if(data->change.url_alloc) - Curl_safefree(data->change.url); + if(data->state.url_alloc) + Curl_safefree(data->state.url); /* after update, get the updated version */ uc = curl_url_get(uh, CURLUPART_URL, &url, 0); if(uc) return Curl_uc_to_curlcode(uc); uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0); - if(uc) + if(uc) { + free(url); return Curl_uc_to_curlcode(uc); - data->change.url = url; - data->change.url_alloc = TRUE; + } + data->state.url = url; + data->state.url_alloc = TRUE; infof(data, "Switched from HTTP to HTTPS due to HSTS => %s\n", - data->change.url); + data->state.url); } } #endif @@ -1970,36 +1989,50 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, if(result) return result; - /* we don't use the URL API's URL decoder option here since it rejects - control codes and we want to allow them for some schemes in the user and - password fields */ - uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0); - if(!uc) { - char *decoded; - result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL, - conn->handler->flags&PROTOPT_USERPWDCTRL ? - REJECT_ZERO : REJECT_CTRL); - if(result) - return result; - conn->user = decoded; - conn->bits.user_passwd = TRUE; + /* + * User name and password set with their own options override the + * credentials possibly set in the URL. + */ + if(!data->state.aptr.user) { + /* we don't use the URL API's URL decoder option here since it rejects + control codes and we want to allow them for some schemes in the user + and password fields */ + uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0); + if(!uc) { + char *decoded; + result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL, + conn->handler->flags&PROTOPT_USERPWDCTRL ? + REJECT_ZERO : REJECT_CTRL); + if(result) + return result; + conn->user = decoded; + conn->bits.user_passwd = TRUE; + result = Curl_setstropt(&data->state.aptr.user, decoded); + if(result) + return result; + } + else if(uc != CURLUE_NO_USER) + return Curl_uc_to_curlcode(uc); } - else if(uc != CURLUE_NO_USER) - return Curl_uc_to_curlcode(uc); - uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0); - if(!uc) { - char *decoded; - result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL, - conn->handler->flags&PROTOPT_USERPWDCTRL ? - REJECT_ZERO : REJECT_CTRL); - if(result) - return result; - conn->passwd = decoded; - conn->bits.user_passwd = TRUE; + if(!data->state.aptr.passwd) { + uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0); + if(!uc) { + char *decoded; + result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL, + conn->handler->flags&PROTOPT_USERPWDCTRL ? + REJECT_ZERO : REJECT_CTRL); + if(result) + return result; + conn->passwd = decoded; + conn->bits.user_passwd = TRUE; + result = Curl_setstropt(&data->state.aptr.passwd, decoded); + if(result) + return result; + } + else if(uc != CURLUE_NO_PASSWORD) + return Curl_uc_to_curlcode(uc); } - else if(uc != CURLUE_NO_PASSWORD) - return Curl_uc_to_curlcode(uc); uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options, CURLU_URLDECODE); @@ -2385,11 +2418,20 @@ static CURLcode parse_proxy(struct Curl_easy *data, proxyinfo->proxytype = proxytype; /* Is there a username and password given in this proxy url? */ - curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE); - curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE); + uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE); + if(uc && (uc != CURLUE_NO_USER)) + goto error; + uc = curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE); + if(uc && (uc != CURLUE_NO_PASSWORD)) + goto error; + if(proxyuser || proxypasswd) { Curl_safefree(proxyinfo->user); proxyinfo->user = proxyuser; + result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser); + proxyuser = NULL; + if(result) + goto error; Curl_safefree(proxyinfo->passwd); if(!proxypasswd) { proxypasswd = strdup(""); @@ -2399,6 +2441,10 @@ static CURLcode parse_proxy(struct Curl_easy *data, } } proxyinfo->passwd = proxypasswd; + result = Curl_setstropt(&data->state.aptr.proxypasswd, proxypasswd); + proxypasswd = NULL; + if(result) + goto error; conn->bits.proxy_user_passwd = TRUE; /* enable it */ } @@ -2444,6 +2490,8 @@ static CURLcode parse_proxy(struct Curl_easy *data, proxyinfo->host.name = host; error: + free(proxyuser); + free(proxypasswd); free(scheme); curl_url_cleanup(uhp); return result; @@ -2455,18 +2503,26 @@ static CURLcode parse_proxy(struct Curl_easy *data, static CURLcode parse_proxy_auth(struct Curl_easy *data, struct connectdata *conn) { - const char *proxyuser = data->set.str[STRING_PROXYUSERNAME] ? - data->set.str[STRING_PROXYUSERNAME] : ""; - const char *proxypasswd = data->set.str[STRING_PROXYPASSWORD] ? - data->set.str[STRING_PROXYPASSWORD] : ""; + const char *proxyuser = data->state.aptr.proxyuser ? + data->state.aptr.proxyuser : ""; + const char *proxypasswd = data->state.aptr.proxypasswd ? + data->state.aptr.proxypasswd : ""; CURLcode result = CURLE_OK; - if(proxyuser) + if(proxyuser) { result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL, REJECT_ZERO); - if(!result && proxypasswd) + if(!result) + result = Curl_setstropt(&data->state.aptr.proxyuser, + conn->http_proxy.user); + } + if(!result && proxypasswd) { result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd, NULL, REJECT_ZERO); + if(!result) + result = Curl_setstropt(&data->state.aptr.proxypasswd, + conn->http_proxy.passwd); + } return result; } @@ -2808,44 +2864,19 @@ static CURLcode parse_remote_port(struct Curl_easy *data, * option or a .netrc file, if applicable. */ static CURLcode override_login(struct Curl_easy *data, - struct connectdata *conn, - char **userp, char **passwdp, char **optionsp) + struct connectdata *conn) { - bool user_changed = FALSE; - bool passwd_changed = FALSE; CURLUcode uc; + char **userp = &conn->user; + char **passwdp = &conn->passwd; + char **optionsp = &conn->options; if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) { - /* ignore user+password in the URL */ - if(*userp) { - Curl_safefree(*userp); - user_changed = TRUE; - } - if(*passwdp) { - Curl_safefree(*passwdp); - passwd_changed = TRUE; - } + Curl_safefree(*userp); + Curl_safefree(*passwdp); conn->bits.user_passwd = FALSE; /* disable user+password */ } - if(data->set.str[STRING_USERNAME]) { - free(*userp); - *userp = strdup(data->set.str[STRING_USERNAME]); - if(!*userp) - return CURLE_OUT_OF_MEMORY; - conn->bits.user_passwd = TRUE; /* enable user+password */ - user_changed = TRUE; - } - - if(data->set.str[STRING_PASSWORD]) { - free(*passwdp); - *passwdp = strdup(data->set.str[STRING_PASSWORD]); - if(!*passwdp) - return CURLE_OUT_OF_MEMORY; - conn->bits.user_passwd = TRUE; /* enable user+password */ - passwd_changed = TRUE; - } - if(data->set.str[STRING_OPTIONS]) { free(*optionsp); *optionsp = strdup(data->set.str[STRING_OPTIONS]); @@ -2854,8 +2885,7 @@ static CURLcode override_login(struct Curl_easy *data, } conn->bits.netrc = FALSE; - if(data->set.use_netrc != CURL_NETRC_IGNORED && - (!*userp || !**userp || !*passwdp || !**passwdp)) { + if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) { bool netrc_user_changed = FALSE; bool netrc_passwd_changed = FALSE; int ret; @@ -2865,8 +2895,8 @@ static CURLcode override_login(struct Curl_easy *data, &netrc_user_changed, &netrc_passwd_changed, data->set.str[STRING_NETRC_FILE]); if(ret > 0) { - infof(data, "Couldn't find host %s in the .netrc file; using defaults\n", - conn->host.name); + infof(data, "Couldn't find host %s in the %s file; using defaults\n", + conn->host.name, data->set.str[STRING_NETRC_FILE]); } else if(ret < 0) { return CURLE_OUT_OF_MEMORY; @@ -2877,29 +2907,44 @@ static CURLcode override_login(struct Curl_easy *data, different host or similar. */ conn->bits.netrc = TRUE; conn->bits.user_passwd = TRUE; /* enable user+password */ - - if(netrc_user_changed) { - user_changed = TRUE; - } - if(netrc_passwd_changed) { - passwd_changed = TRUE; - } } } /* for updated strings, we update them in the URL */ - if(user_changed) { - uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, + if(*userp) { + CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp); + if(result) + return result; + } + if(data->state.aptr.user) { + uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user, CURLU_URLENCODE); if(uc) return Curl_uc_to_curlcode(uc); + if(!*userp) { + *userp = strdup(data->state.aptr.user); + if(!*userp) + return CURLE_OUT_OF_MEMORY; + } } - if(passwd_changed) { - uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, - CURLU_URLENCODE); + + if(*passwdp) { + CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp); + if(result) + return result; + } + if(data->state.aptr.passwd) { + uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, + data->state.aptr.passwd, CURLU_URLENCODE); if(uc) return Curl_uc_to_curlcode(uc); + if(!*passwdp) { + *passwdp = strdup(data->state.aptr.passwd); + if(!*passwdp) + return CURLE_OUT_OF_MEMORY; + } } + return CURLE_OK; } @@ -3315,7 +3360,7 @@ static CURLcode resolve_server(struct Curl_easy *data, result = CURLE_OPERATION_TIMEDOUT; else if(!hostaddr) { - failf(data, "Couldn't resolve host '%s'", connhost->dispname); + failf(data, "Could not resolve host: %s", connhost->dispname); result = CURLE_COULDNT_RESOLVE_HOST; /* don't return yet, we need to clean up the timeout first */ } @@ -3367,7 +3412,7 @@ static void reuse_conn(struct Curl_easy *data, ip address and port number whenever an outgoing connection is **established** from the primary socket to a remote address. */ char local_ip[MAX_IPADR_LEN] = ""; - long local_port = -1; + int local_port = -1; #ifndef CURL_DISABLE_PROXY Curl_free_idnconverted_hostname(&old_conn->http_proxy.host); Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host); @@ -3380,8 +3425,6 @@ static void reuse_conn(struct Curl_easy *data, allocated in vain and is targeted for destruction */ Curl_free_primary_ssl_config(&old_conn->ssl_config); - conn->data = data; - /* get the user+password information from the old_conn struct since it may * be new for this request even when we re-use an existing connection */ conn->bits.user_passwd = old_conn->bits.user_passwd; @@ -3469,7 +3512,6 @@ static void reuse_conn(struct Curl_easy *data, * @param async is set TRUE when an async DNS resolution is pending * @see Curl_setup_conn() * - * *NOTE* this function assigns the conn->data pointer! */ static CURLcode create_conn(struct Curl_easy *data, @@ -3492,7 +3534,7 @@ static CURLcode create_conn(struct Curl_easy *data, /************************************************************* * Check input data *************************************************************/ - if(!data->change.url) { + if(!data->state.url) { result = CURLE_URL_MALFORMAT; goto out; } @@ -3528,7 +3570,7 @@ static CURLcode create_conn(struct Curl_easy *data, #ifdef USE_UNIX_SOCKETS if(data->set.str[STRING_UNIX_SOCKET_PATH]) { conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); - if(conn->unix_domain_socket == NULL) { + if(!conn->unix_domain_socket) { result = CURLE_OUT_OF_MEMORY; goto out; } @@ -3560,8 +3602,7 @@ static CURLcode create_conn(struct Curl_easy *data, /* Check for overridden login details and set them accordingly so they they are known when protocol->setup_connection is called! */ - result = override_login(data, conn, &conn->user, &conn->passwd, - &conn->options); + result = override_login(data, conn); if(result) goto out; @@ -3693,17 +3734,18 @@ static CURLcode create_conn(struct Curl_easy *data, that will be freed as part of the Curl_easy struct, but all cloned copies will be separately allocated. */ - data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG]; - data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG]; + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; data->set.ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST_ORIG]; + data->set.str[STRING_SSL_CIPHER_LIST]; data->set.ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST_ORIG]; + data->set.str[STRING_SSL_CIPHER13_LIST]; data->set.ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; - data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG]; + data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; + data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; #ifndef CURL_DISABLE_PROXY @@ -3719,6 +3761,8 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; + data->set.proxy_ssl.primary.ca_info_blob = + data->set.blobs[BLOB_CAINFO_PROXY]; data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; @@ -3728,24 +3772,24 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; #endif - data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; - data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG]; - data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG]; - data->set.ssl.key = data->set.str[STRING_KEY_ORIG]; - data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG]; - data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG]; - data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG]; + data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE]; + data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; + data->set.ssl.key = data->set.str[STRING_KEY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT]; #ifdef USE_TLS_SRP - data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; - data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; #ifndef CURL_DISABLE_PROXY data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; #endif #endif - data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG]; - data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG]; + data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; + data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, &conn->ssl_config)) { @@ -3952,10 +3996,7 @@ static CURLcode create_conn(struct Curl_easy *data, * create_conn() is all done. * * Curl_setup_conn() also handles reused connections - * - * conn->data MUST already have been setup fine (in create_conn) */ - CURLcode Curl_setup_conn(struct Curl_easy *data, bool *protocol_done) { diff --git a/lib/urlapi.c b/lib/urlapi.c index e3a788221bc..6483208ec73 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -667,6 +667,94 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) #define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#')) +/* + * Handle partial IPv4 numerical addresses and different bases, like + * '16843009', '0x7f', '0x7f.1' '0177.1.1.1' etc. + * + * If the given input string is syntactically wrong or any part for example is + * too big, this function returns FALSE and doesn't create any output. + * + * Output the "normalized" version of that input string in plain quad decimal + * integers and return TRUE. + */ +static bool ipv4_normalize(const char *hostname, char *outp, size_t olen) +{ + bool done = FALSE; + int n = 0; + const char *c = hostname; + unsigned long parts[4] = {0, 0, 0, 0}; + + while(!done) { + char *endp; + unsigned long l; + if((*c < '0') || (*c > '9')) + /* most importantly this doesn't allow a leading plus or minus */ + return FALSE; + l = strtoul(c, &endp, 0); + + /* overflow or nothing parsed at all */ + if(((l == ULONG_MAX) && (errno == ERANGE)) || (endp == c)) + return FALSE; + +#if SIZEOF_LONG > 4 + /* a value larger than 32 bits */ + if(l > UINT_MAX) + return FALSE; +#endif + + parts[n] = l; + c = endp; + + switch (*c) { + case '.' : + if(n == 3) + return FALSE; + n++; + c++; + break; + + case '\0': + done = TRUE; + break; + + default: + return FALSE; + } + } + + /* this is deemed a valid IPv4 numerical address */ + + switch(n) { + case 0: /* a -- 32 bits */ + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0] >> 24, (parts[0] >> 16) & 0xff, + (parts[0] >> 8) & 0xff, parts[0] & 0xff); + break; + case 1: /* a.b -- 8.24 bits */ + if((parts[0] > 0xff) || (parts[1] > 0xffffff)) + return FALSE; + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0], (parts[1] >> 16) & 0xff, + (parts[1] >> 8) & 0xff, parts[1] & 0xff); + break; + case 2: /* a.b.c -- 8.8.16 bits */ + if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff)) + return FALSE; + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0], parts[1], (parts[2] >> 8) & 0xff, + parts[2] & 0xff); + break; + case 3: /* a.b.c.d -- 8.8.8.8 bits */ + if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) || + (parts[3] > 0xff)) + return FALSE; + msnprintf(outp, olen, "%u.%u.%u.%u", + parts[0], parts[1], parts[2], parts[3]); + break; + } + return TRUE; +} + static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) { char *path; @@ -899,6 +987,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) } if(hostname) { + char normalized_ipv4[sizeof("255.255.255.255") + 1]; /* * Parse the login details and strip them out of the host name. */ @@ -922,7 +1011,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) return result; } - u->host = strdup(hostname); + if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4))) + u->host = strdup(normalized_ipv4); + else + u->host = strdup(hostname); if(!u->host) return CURLUE_OUT_OF_MEMORY; diff --git a/lib/urldata.h b/lib/urldata.h index f7d60b249bb..fb905c36c57 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -253,6 +253,7 @@ struct ssl_primary_config { char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ char *pinned_key; struct curl_blob *cert_blob; + struct curl_blob *ca_info_blob; char *curves; /* list of curves to use */ BIT(verifypeer); /* set TRUE if this is desired */ BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */ @@ -286,6 +287,8 @@ struct ssl_config_data { BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation list errors */ BIT(native_ca_store); /* use the native ca store of operating system */ + BIT(auto_client_cert); /* automatically locate and use a client + certificate for authentication (Schannel) */ }; struct ssl_general_config { @@ -371,6 +374,15 @@ struct kerberos5data { }; #endif +/* Struct used for SCRAM-SHA-1 authentication */ +#ifdef USE_GSASL +#include +struct gsasldata { + Gsasl *ctx; + Gsasl_session *client; +}; +#endif + /* Struct used for NTLM challenge-response authentication */ #if defined(USE_NTLM) struct ntlmdata { @@ -782,12 +794,16 @@ struct Curl_handler { struct connectdata *conn, unsigned int checks_to_perform); + /* attach() attaches this transfer to this connection */ + void (*attach)(struct Curl_easy *data, struct connectdata *conn); + int defport; /* Default port. */ unsigned int protocol; /* See CURLPROTO_* - this needs to be the single specific protocol bit */ unsigned int family; /* single bit for protocol family; basically the non-TLS name of the protocol this is */ unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ + }; #define PROTOPT_NONE 0 /* nothing extra */ @@ -846,25 +862,8 @@ struct proxy_info { char *passwd; /* proxy password string, allocated */ }; -/* struct for HTTP CONNECT state data */ -struct http_connect_state { - struct dynbuf rcvbuf; - enum keeponval { - KEEPON_DONE, - KEEPON_CONNECT, - KEEPON_IGNORE - } keepon; - curl_off_t cl; /* size of content to read and ignore */ - enum { - TUNNEL_INIT, /* init/default/no tunnel state */ - TUNNEL_CONNECT, /* CONNECT has been sent off */ - TUNNEL_COMPLETE /* CONNECT response received completely */ - } tunnel_state; - BIT(chunked_encoding); - BIT(close_connection); -}; - struct ldapconninfo; +struct http_connect_state; /* for the (SOCKS) connect state machine */ enum connect_t { @@ -902,10 +901,6 @@ struct connstate { * unique for an entire connection. */ struct connectdata { - /* 'data' is the CURRENT Curl_easy using this connection -- take great - caution that this might very well vary between different times this - connection is used! */ - struct Curl_easy *data; struct connstate cnnct; struct Curl_llist_element bundle_node; /* conncache */ @@ -981,12 +976,8 @@ struct connectdata { char *user; /* user name string, allocated */ char *passwd; /* password string, allocated */ char *options; /* options string, allocated */ - char *sasl_authzid; /* authorisation identity string, allocated */ - - int httpversion; /* the HTTP version*10 reported by the server */ - int rtspversion; /* the RTSP version*10 reported by the server */ - + unsigned char httpversion; /* the HTTP version*10 reported by the server */ struct curltime now; /* "current" time */ struct curltime created; /* creation time */ struct curltime lastused; /* when returned to the connection cache */ @@ -1065,6 +1056,10 @@ struct connectdata { CtxtHandle *sslContext; #endif +#ifdef USE_GSASL + struct gsasldata gsasl; +#endif + #if defined(USE_NTLM) curlntlm http_ntlm_state; curlntlm proxy_ntlm_state; @@ -1157,9 +1152,9 @@ struct PureInfo { reused, in the connection cache. */ char conn_primary_ip[MAX_IPADR_LEN]; - long conn_primary_port; + int conn_primary_port; char conn_local_ip[MAX_IPADR_LEN]; - long conn_local_port; + int conn_local_port; const char *conn_scheme; unsigned int conn_protocol; struct curl_certinfo certs; /* info about the certs, only populated in @@ -1316,8 +1311,6 @@ struct urlpieces { struct UrlState { /* Points to the connection cache */ struct conncache *conn_cache; - int retrycount; /* number of retries on a new connection */ - /* buffers to store authentication data in, as parsed from input options */ struct curltime keeps_speed; /* for the progress meter really */ @@ -1334,6 +1327,7 @@ struct UrlState { following not keep sending user+password... This is strdup() data. */ + int retrycount; /* number of retries on a new connection */ int first_remote_port; /* remote port of the first (not followed) request */ struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ long sessionage; /* number of the most recent session */ @@ -1341,6 +1335,7 @@ struct UrlState { unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ int os_errno; /* filled in with errno whenever an error occurs */ char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ + long followlocation; /* redirect counter */ #ifdef HAVE_SIGNAL /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ void (*prev_signal)(int sig); @@ -1365,9 +1360,10 @@ struct UrlState { /* a place to store the most recently set FTP entrypath */ char *most_recent_ftp_entrypath; - - int httpversion; /* the lowest HTTP version*10 reported by any server - involved in this request */ + unsigned char httpwant; /* when non-zero, a specific HTTP version requested + to be used in the library's request(s) */ + unsigned char httpversion; /* the lowest HTTP version*10 reported by any + server involved in this request */ #if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) /* do FTP line-end conversions on most platforms */ @@ -1400,9 +1396,13 @@ struct UrlState { int stream_weight; CURLU *uh; /* URL handle for the current parsed URL */ struct urlpieces up; -#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT) Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ -#endif + char *url; /* work URL, copied from UserDefined */ + char *referer; /* referer string */ + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ + struct curl_slist *resolve; /* set to point to the set.resolve list when + this should be dealt with in pretransfer */ #ifndef CURL_DISABLE_HTTP size_t trailers_bytes_sent; struct dynbuf trailers_buf; /* a buffer containing the compiled trailing @@ -1427,6 +1427,12 @@ struct UrlState { char *cookiehost; char *rtsp_transport; char *te; /* TE: request header */ + + /* transfer credentials */ + char *user; + char *passwd; + char *proxyuser; + char *proxypasswd; } aptr; #ifdef CURLDEBUG @@ -1454,32 +1460,16 @@ struct UrlState { BIT(use_range); BIT(rangestringalloc); /* the range string is malloc()'ed */ BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE - when multi_done() is called, to prevent multi_done() to get - invoked twice when the multi interface is used. */ + when multi_done() is called, to prevent multi_done() to get + invoked twice when the multi interface is used. */ BIT(stream_depends_e); /* set or don't set the Exclusive bit */ BIT(previouslypending); /* this transfer WAS in the multi->pending queue */ BIT(cookie_engine); -}; - - -/* - * This 'DynamicStatic' struct defines dynamic states that actually change - * values in the 'UserDefined' area, which MUST be taken into consideration - * if the UserDefined struct is cloned or similar. You can probably just - * copy these, but each one indicate a special action on other data. - */ - -struct DynamicStatic { - char *url; /* work URL, copied from UserDefined */ - char *referer; /* referer string */ - struct curl_slist *cookielist; /* list of cookie files set by - curl_easy_setopt(COOKIEFILE) calls */ - struct curl_slist *resolve; /* set to point to the set.resolve list when - this should be dealt with in pretransfer */ + BIT(prefer_ascii); /* ASCII rather than binary */ + BIT(list_only); /* list directory contents */ BIT(url_alloc); /* URL string is malloc()'ed */ BIT(referer_alloc); /* referer string is malloc()ed */ - BIT(wildcard_resolve); /* Set to true if any resolve change is a - wildcard */ + BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */ }; /* @@ -1502,9 +1492,9 @@ struct Curl_multi; /* declared and used only in multi.c */ * are catered for in curl_easy_setopt_ccsid() */ enum dupstring { - STRING_CERT_ORIG, /* client certificate file name */ + STRING_CERT, /* client certificate file name */ STRING_CERT_PROXY, /* client certificate file name */ - STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/ + STRING_CERT_TYPE, /* format for certificate (default: PEM)*/ STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/ STRING_COOKIE, /* HTTP cookie string to send */ STRING_COOKIEJAR, /* dump all cookies to this file */ @@ -1515,11 +1505,11 @@ enum dupstring { STRING_FTP_ACCOUNT, /* ftp account data */ STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ STRING_FTPPORT, /* port to send with the FTP PORT command */ - STRING_KEY_ORIG, /* private key file name */ + STRING_KEY, /* private key file name */ STRING_KEY_PROXY, /* private key file name */ - STRING_KEY_PASSWD_ORIG, /* plain text private key password */ + STRING_KEY_PASSWD, /* plain text private key password */ STRING_KEY_PASSWD_PROXY, /* plain text private key password */ - STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */ + STRING_KEY_TYPE, /* format for private key (default: PEM) */ STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */ STRING_KRB_LEVEL, /* krb security level */ STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find @@ -1529,22 +1519,22 @@ enum dupstring { STRING_SET_RANGE, /* range, if used */ STRING_SET_REFERER, /* custom string for the HTTP referer field */ STRING_SET_URL, /* what original URL to work on */ - STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */ STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ - STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ + STRING_SSL_CAFILE, /* certificate file to verify peer against */ STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ - STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */ STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ - STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ + STRING_SSL_CIPHER_LIST, /* list of ciphers to use */ STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ - STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_CIPHER13_LIST, /* list of TLS 1.3 ciphers to use */ STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */ STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ STRING_USERAGENT, /* User-Agent string */ - STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */ + STRING_SSL_CRLFILE, /* crl file to check certificate */ STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ - STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */ + STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ STRING_SSL_ENGINE, /* name of ssl engine */ STRING_USERNAME, /* , if used */ @@ -1565,9 +1555,9 @@ enum dupstring { STRING_SERVICE_NAME, /* Service name */ STRING_MAIL_FROM, STRING_MAIL_AUTH, - STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth */ + STRING_TLSAUTH_USERNAME, /* TLS auth */ STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth */ - STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth */ + STRING_TLSAUTH_PASSWORD, /* TLS auth */ STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth */ STRING_BEARER, /* , if used */ STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */ @@ -1596,12 +1586,14 @@ enum dupstring { }; enum dupblob { - BLOB_CERT_ORIG, + BLOB_CERT, BLOB_CERT_PROXY, - BLOB_KEY_ORIG, + BLOB_KEY, BLOB_KEY_PROXY, - BLOB_SSL_ISSUERCERT_ORIG, + BLOB_SSL_ISSUERCERT, BLOB_SSL_ISSUERCERT_PROXY, + BLOB_CAINFO, + BLOB_CAINFO_PROXY, BLOB_LAST }; @@ -1625,7 +1617,6 @@ struct UserDefined { unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */ unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */ unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */ - long followlocation; /* as in HTTP Location: */ long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1 for infinity */ @@ -1665,7 +1656,7 @@ struct UserDefined { curl_conv_callback convtonetwork; /* function to convert from UTF-8 encoding: */ curl_conv_callback convfromutf8; -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS curl_hstsread_callback hsts_read; void *hsts_read_userp; curl_hstswrite_callback hsts_write; @@ -1708,11 +1699,9 @@ struct UserDefined { curl_TimeCond timecondition; /* kind of time/date comparison */ curl_proxytype proxytype; /* what kind of proxy that is in use */ time_t timevalue; /* what time to compare with */ -#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT) Curl_HttpReq method; /* what kind of HTTP request (if any) is this */ -#endif - long httpversion; /* when non-zero, a specific HTTP version requested to - be used in the library's request(s) */ + unsigned char httpwant; /* when non-zero, a specific HTTP version requested + to be used in the library's request(s) */ struct ssl_config_data ssl; /* user defined SSL stuff */ #ifndef CURL_DISABLE_PROXY struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ @@ -1720,8 +1709,8 @@ struct UserDefined { struct ssl_general_config general_ssl; /* general user defined SSL stuff */ long dns_cache_timeout; /* DNS cache timeout */ long buffer_size; /* size of receive buffer to use */ - size_t upload_buffer_size; /* size of upload buffer to use, - keep it >= CURL_MAX_WRITE_SIZE */ + unsigned int upload_buffer_size; /* size of upload buffer to use, + keep it >= CURL_MAX_WRITE_SIZE */ void *private_data; /* application-private data */ struct curl_slist *http200aliases; /* linked list of aliases for http200 */ unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header @@ -1800,8 +1789,8 @@ struct UserDefined { BIT(get_filetime); /* get the time and get of the remote file */ BIT(tunnel_thru_httpproxy); /* use CONNECT through a HTTP proxy */ BIT(prefer_ascii); /* ASCII rather than binary */ - BIT(ftp_append); /* append, not overwrite, on upload */ - BIT(ftp_list_only); /* switch FTP command for listing directories */ + BIT(remote_append); /* append, not overwrite, on upload */ + BIT(list_only); /* list directory */ #ifndef CURL_DISABLE_FTP BIT(ftp_use_port); /* use the FTP PORT command */ BIT(ftp_use_epsv); /* if EPSV is to be attempted or not */ @@ -1858,6 +1847,9 @@ struct UserDefined { BIT(disallow_username_in_url); /* disallow username in url */ BIT(doh); /* DNS-over-HTTPS enabled */ BIT(doh_get); /* use GET for DoH requests, instead of POST */ + BIT(doh_verifypeer); /* DOH certificate peer verification */ + BIT(doh_verifyhost); /* DOH certificate hostname verification */ + BIT(doh_verifystatus); /* DOH certificate status verification */ BIT(http09_allowed); /* allow HTTP/0.9 responses */ BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some recipients */ @@ -1905,8 +1897,8 @@ struct Curl_easy { the state etc are also kept. This array is mostly used to detect when a socket is to be removed from the hash. See singlesocket(). */ curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; - int actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in - sockets[] */ + unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in + sockets[] */ int numsocks; struct Names dns; @@ -1922,12 +1914,11 @@ struct Curl_easy { #endif struct SingleRequest req; /* Request-specific data */ struct UserDefined set; /* values set by the libcurl user */ - struct DynamicStatic change; /* possibly modified userdefined data */ struct CookieInfo *cookies; /* the cookies, read from files and servers. NOTE that the 'cookie' field in the UserDefined struct defines if the "engine" is to be used or not. */ -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS struct hsts *hsts; #endif #ifndef CURL_DISABLE_ALTSVC diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c index 620dba03ef7..d17e16f1084 100644 --- a/lib/vauth/cleartext.c +++ b/lib/vauth/cleartext.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,7 +32,6 @@ #include "urldata.h" #include "vauth/vauth.h" -#include "curl_base64.h" #include "curl_md5.h" #include "warnless.h" #include "strtok.h" @@ -51,31 +50,24 @@ * * Parameters: * - * data [in] - The session handle. * authzid [in] - The authorization identity. * authcid [in] - The authentication identity. * passwd [in] - The password. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, - const char *authzid, +CURLcode Curl_auth_create_plain_message(const char *authzid, const char *authcid, const char *passwd, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result; char *plainauth; + size_t plainlen; size_t zlen; size_t clen; size_t plen; - size_t plainlen; - *outlen = 0; - *outptr = NULL; zlen = (authzid == NULL ? 0 : strlen(authzid)); clen = strlen(authcid); plen = strlen(passwd); @@ -86,23 +78,20 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; plainlen = zlen + clen + plen + 2; - plainauth = malloc(plainlen); + plainauth = malloc(plainlen + 1); if(!plainauth) return CURLE_OUT_OF_MEMORY; /* Calculate the reply */ - if(zlen != 0) + if(zlen) memcpy(plainauth, authzid, zlen); plainauth[zlen] = '\0'; memcpy(plainauth + zlen + 1, authcid, clen); plainauth[zlen + clen + 1] = '\0'; memcpy(plainauth + zlen + clen + 2, passwd, plen); - - /* Base64 encode the reply */ - result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen); - free(plainauth); - - return result; + plainauth[plainlen] = '\0'; + Curl_bufref_set(out, plainauth, plainlen, curl_free); + return CURLE_OK; } /* @@ -113,34 +102,15 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, * * Parameters: * - * data [in] - The session handle. * valuep [in] - The user name or user's password. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_login_message(struct Curl_easy *data, - const char *valuep, char **outptr, - size_t *outlen) +CURLcode Curl_auth_create_login_message(const char *valuep, struct bufref *out) { - size_t vlen = strlen(valuep); - - if(!vlen) { - /* Calculate an empty reply */ - *outptr = strdup("="); - if(*outptr) { - *outlen = (size_t) 1; - return CURLE_OK; - } - - *outlen = 0; - return CURLE_OUT_OF_MEMORY; - } - - /* Base64 encode the value */ - return Curl_base64_encode(data, valuep, vlen, outptr, outlen); + Curl_bufref_set(out, valuep, strlen(valuep), NULL); + return CURLE_OK; } /* @@ -151,20 +121,16 @@ CURLcode Curl_auth_create_login_message(struct Curl_easy *data, * * Parameters: * - * data [in] - The session handle. * user [in] - The user name. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_external_message(struct Curl_easy *data, - const char *user, char **outptr, - size_t *outlen) +CURLcode Curl_auth_create_external_message(const char *user, + struct bufref *out) { /* This is the same formatting as the login message */ - return Curl_auth_create_login_message(data, user, outptr, outlen); + return Curl_auth_create_login_message(user, out); } #endif /* if no users */ diff --git a/lib/vauth/cram.c b/lib/vauth/cram.c index 1a376259a82..9ddb0ac379e 100644 --- a/lib/vauth/cram.c +++ b/lib/vauth/cram.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,7 +30,6 @@ #include "urldata.h" #include "vauth/vauth.h" -#include "curl_base64.h" #include "curl_hmac.h" #include "curl_md5.h" #include "warnless.h" @@ -40,69 +39,31 @@ #include "curl_memory.h" #include "memdebug.h" -/* - * Curl_auth_decode_cram_md5_message() - * - * This is used to decode an already encoded CRAM-MD5 challenge message. - * - * Parameters: - * - * chlg64 [in] - The base64 encoded challenge message. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. - * - * Returns CURLE_OK on success. - */ -CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, - size_t *outlen) -{ - CURLcode result = CURLE_OK; - size_t chlg64len = strlen(chlg64); - - *outptr = NULL; - *outlen = 0; - - /* Decode the challenge if necessary */ - if(chlg64len && *chlg64 != '=') - result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen); - - return result; -} /* * Curl_auth_create_cram_md5_message() * - * This is used to generate an already encoded CRAM-MD5 response message ready - * for sending to the recipient. + * This is used to generate a CRAM-MD5 response message ready for sending to + * the recipient. * * Parameters: * - * data [in] - The session handle. * chlg [in] - The challenge. * userp [in] - The user name. * passwdp [in] - The user's password. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, - const char *chlg, +CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg, const char *userp, const char *passwdp, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; - size_t chlglen = 0; struct HMAC_context *ctxt; unsigned char digest[MD5_DIGEST_LEN]; char *response; - if(chlg) - chlglen = strlen(chlg); - /* Compute the digest using the password as the key */ ctxt = Curl_HMAC_init(Curl_HMAC_MD5, (const unsigned char *) passwdp, @@ -111,9 +72,9 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; /* Update the digest with the given challenge */ - if(chlglen > 0) - Curl_HMAC_update(ctxt, (const unsigned char *) chlg, - curlx_uztoui(chlglen)); + if(Curl_bufref_len(chlg)) + Curl_HMAC_update(ctxt, Curl_bufref_ptr(chlg), + curlx_uztoui(Curl_bufref_len(chlg))); /* Finalise the digest */ Curl_HMAC_final(ctxt, digest); @@ -127,12 +88,8 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, if(!response) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the response */ - result = Curl_base64_encode(data, response, 0, outptr, outlen); - - free(response); - - return result; + Curl_bufref_set(out, response, strlen(response), curl_free); + return CURLE_OK; } #endif /* !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c index 559852fcba3..a04ffab6fb3 100644 --- a/lib/vauth/digest.c +++ b/lib/vauth/digest.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -254,7 +254,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) * * Parameters: * - * chlg64 [in] - The base64 encoded challenge message. + * chlgref [in] - The challenge message. * nonce [in/out] - The buffer where the nonce will be stored. * nlen [in] - The length of the nonce buffer. * realm [in/out] - The buffer where the realm will be stored. @@ -266,55 +266,35 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) * * Returns CURLE_OK on success. */ -static CURLcode auth_decode_digest_md5_message(const char *chlg64, +static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref, char *nonce, size_t nlen, char *realm, size_t rlen, char *alg, size_t alen, char *qop, size_t qlen) { - CURLcode result = CURLE_OK; - unsigned char *chlg = NULL; - size_t chlglen = 0; - size_t chlg64len = strlen(chlg64); - - /* Decode the base-64 encoded challenge message */ - if(chlg64len && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } + const char *chlg = (const char *) Curl_bufref_ptr(chlgref); /* Ensure we have a valid challenge message */ - if(!chlg) + if(!Curl_bufref_len(chlgref)) return CURLE_BAD_CONTENT_ENCODING; /* Retrieve nonce string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "nonce=\"", nonce, nlen, - '\"')) { - free(chlg); + if(!auth_digest_get_key_value(chlg, "nonce=\"", nonce, nlen, '\"')) return CURLE_BAD_CONTENT_ENCODING; - } /* Retrieve realm string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "realm=\"", realm, rlen, - '\"')) { + if(!auth_digest_get_key_value(chlg, "realm=\"", realm, rlen, '\"')) { /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ strcpy(realm, ""); } /* Retrieve algorithm string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "algorithm=", alg, alen, ',')) { - free(chlg); + if(!auth_digest_get_key_value(chlg, "algorithm=", alg, alen, ',')) return CURLE_BAD_CONTENT_ENCODING; - } /* Retrieve qop-options string from the challenge */ - if(!auth_digest_get_key_value((char *) chlg, "qop=\"", qop, qlen, '\"')) { - free(chlg); + if(!auth_digest_get_key_value(chlg, "qop=\"", qop, qlen, '\"')) return CURLE_BAD_CONTENT_ENCODING; - } - - free(chlg); return CURLE_OK; } @@ -342,22 +322,20 @@ bool Curl_auth_is_digest_supported(void) * Parameters: * * data [in] - The session handle. - * chlg64 [in] - The base64 encoded challenge message. + * chlg [in] - The challenge message. * userp [in] - The user name. * passwdp [in] - The user's password. * service [in] - The service type such as http, smtp, pop or imap. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, const char *userp, const char *passwdp, const char *service, - char **outptr, size_t *outlen) + struct bufref *out) { size_t i; struct MD5_context *ctxt; @@ -378,9 +356,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, char *spn = NULL; /* Decode the challenge message */ - CURLcode result = auth_decode_digest_md5_message(chlg64, nonce, - sizeof(nonce), realm, - sizeof(realm), algorithm, + CURLcode result = auth_decode_digest_md5_message(chlg, + nonce, sizeof(nonce), + realm, sizeof(realm), + algorithm, sizeof(algorithm), qop_options, sizeof(qop_options)); @@ -500,11 +479,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(!response) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the response */ - result = Curl_base64_encode(data, response, 0, outptr, outlen); - - free(response); - + /* Return the response. */ + Curl_bufref_set(out, response, strlen(response), curl_free); return result; } diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c index dad947a37e8..2602ffd363f 100644 --- a/lib/vauth/digest_sspi.c +++ b/lib/vauth/digest_sspi.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014 - 2016, Steve Holme, . - * Copyright (C) 2015 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2015 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,7 +32,6 @@ #include "vauth/vauth.h" #include "vauth/digest.h" #include "urldata.h" -#include "curl_base64.h" #include "warnless.h" #include "curl_multibyte.h" #include "sendf.h" @@ -79,28 +78,24 @@ bool Curl_auth_is_digest_supported(void) * Parameters: * * data [in] - The session handle. - * chlg64 [in] - The base64 encoded challenge message. + * chlg [in] - The challenge message. * userp [in] - The user name in the format User or Domain\User. * passwdp [in] - The user's password. * service [in] - The service type such as http, smtp, pop or imap. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, const char *userp, const char *passwdp, const char *service, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; TCHAR *spn = NULL; - size_t chlglen = 0; size_t token_max = 0; - unsigned char *input_token = NULL; unsigned char *output_token = NULL; CredHandle credentials; CtxtHandle context; @@ -115,17 +110,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, unsigned long attrs; TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ - /* Decode the base-64 encoded challenge message */ - if(strlen(chlg64) && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &input_token, &chlglen); - if(result) - return result; - } - /* Ensure we have a valid challenge message */ - if(!input_token) { + if(!Curl_bufref_len(chlg)) { infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -133,8 +120,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST), &SecurityPackage); if(status != SEC_E_OK) { - free(input_token); - failf(data, "SSPI: couldn't get auth info"); return CURLE_AUTH_ERROR; } @@ -146,18 +131,13 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Allocate our response buffer */ output_token = malloc(token_max); - if(!output_token) { - free(input_token); - + if(!output_token) return CURLE_OUT_OF_MEMORY; - } /* Generate our SPN */ spn = Curl_auth_build_spn(service, data->conn->host.name, NULL); if(!spn) { free(output_token); - free(input_token); - return CURLE_OUT_OF_MEMORY; } @@ -167,8 +147,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(result) { free(spn); free(output_token); - free(input_token); - return result; } @@ -190,8 +168,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_sspi_free_identity(p_identity); free(spn); free(output_token); - free(input_token); - return CURLE_LOGIN_DENIED; } @@ -200,8 +176,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, chlg_desc.cBuffers = 1; chlg_desc.pBuffers = &chlg_buf; chlg_buf.BufferType = SECBUFFER_TOKEN; - chlg_buf.pvBuffer = input_token; - chlg_buf.cbBuffer = curlx_uztoul(chlglen); + chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg); + chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg)); /* Setup the response "output" security buffer */ resp_desc.ulVersion = SECBUFFER_VERSION; @@ -227,7 +203,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_sspi_free_identity(p_identity); free(spn); free(output_token); - free(input_token); if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; @@ -238,9 +213,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, return CURLE_AUTH_ERROR; } - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) output_token, resp_buf.cbBuffer, - outptr, outlen); + /* Return the response. */ + Curl_bufref_set(out, output_token, resp_buf.cbBuffer, curl_free); /* Free our handles */ s_pSecFn->DeleteSecurityContext(&context); @@ -252,12 +226,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Free the SPN */ free(spn); - /* Free the response buffer */ - free(output_token); - - /* Free the decoded challenge message */ - free(input_token); - return result; } diff --git a/lib/vauth/gsasl.c b/lib/vauth/gsasl.c new file mode 100644 index 00000000000..40fef53c935 --- /dev/null +++ b/lib/vauth/gsasl.c @@ -0,0 +1,124 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2020 - 2021, Simon Josefsson, , 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. + * + * RFC5802 SCRAM-SHA-1 authentication + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GSASL + +#include + +#include "vauth/vauth.h" +#include "urldata.h" +#include "sendf.h" + +#include + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +bool Curl_auth_gsasl_is_supported(struct Curl_easy *data, + const char *mech, + struct gsasldata *gsasl) +{ + int res; + + res = gsasl_init(&gsasl->ctx); + if(res != GSASL_OK) { + failf(data, "gsasl init: %s\n", gsasl_strerror(res)); + return FALSE; + } + + res = gsasl_client_start(gsasl->ctx, mech, &gsasl->client); + if(res != GSASL_OK) { + gsasl_done(gsasl->ctx); + return FALSE; + } + + return true; +} + +CURLcode Curl_auth_gsasl_start(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct gsasldata *gsasl) +{ +#if GSASL_VERSION_NUMBER >= 0x010b00 + int res; + res = +#endif + gsasl_property_set(gsasl->client, GSASL_AUTHID, userp); +#if GSASL_VERSION_NUMBER >= 0x010b00 + if(res != GSASL_OK) { + failf(data, "setting AUTHID failed: %s\n", gsasl_strerror(res)); + return CURLE_OUT_OF_MEMORY; + } +#endif + +#if GSASL_VERSION_NUMBER >= 0x010b00 + res = +#endif + gsasl_property_set(gsasl->client, GSASL_PASSWORD, passwdp); +#if GSASL_VERSION_NUMBER >= 0x010b00 + if(res != GSASL_OK) { + failf(data, "setting PASSWORD failed: %s\n", gsasl_strerror(res)); + return CURLE_OUT_OF_MEMORY; + } +#endif + + (void)data; + + return CURLE_OK; +} + +CURLcode Curl_auth_gsasl_token(struct Curl_easy *data, + const struct bufref *chlg, + struct gsasldata *gsasl, + struct bufref *out) +{ + int res; + char *response; + size_t outlen; + + res = gsasl_step(gsasl->client, + (const char *) Curl_bufref_ptr(chlg), Curl_bufref_len(chlg), + &response, &outlen); + if(res != GSASL_OK && res != GSASL_NEEDS_MORE) { + failf(data, "GSASL step: %s\n", gsasl_strerror(res)); + return CURLE_BAD_CONTENT_ENCODING; + } + + Curl_bufref_set(out, response, outlen, gsasl_free); + return CURLE_OK; +} + +void Curl_auth_gsasl_cleanup(struct gsasldata *gsasl) +{ + gsasl_finish(gsasl->client); + gsasl->client = NULL; + + gsasl_done(gsasl->ctx); + gsasl->ctx = NULL; +} +#endif diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c index 0412815e931..b43982b9bd6 100644 --- a/lib/vauth/krb5_gssapi.c +++ b/lib/vauth/krb5_gssapi.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014 - 2019, Steve Holme, . - * Copyright (C) 2015 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2015 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,7 +32,6 @@ #include "vauth/vauth.h" #include "curl_sasl.h" #include "urldata.h" -#include "curl_base64.h" #include "curl_gssapi.h" #include "sendf.h" #include "curl_printf.h" @@ -70,12 +69,9 @@ bool Curl_auth_is_gssapi_supported(void) * host [in[ - The host name. * mutual_auth [in] - Flag specifying whether or not mutual authentication * is enabled. - * chlg64 [in] - Pointer to the optional base64 encoded challenge - * message. + * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -85,13 +81,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, const char *service, const char *host, const bool mutual_auth, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; - size_t chlglen = 0; - unsigned char *chlg = NULL; OM_uint32 major_status; OM_uint32 minor_status; OM_uint32 unused_status; @@ -127,24 +121,13 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, free(spn); } - if(chlg64 && *chlg64) { - /* Decode the base-64 encoded challenge message */ - if(*chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty challenge message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } - - /* Setup the challenge "input" security buffer */ - input_token.value = chlg; - input_token.length = chlglen; + input_token.value = (void *) Curl_bufref_ptr(chlg); + input_token.length = Curl_bufref_len(chlg); } major_status = Curl_gss_init_sec_context(data, @@ -158,9 +141,6 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, mutual_auth, NULL); - /* Free the decoded challenge as it is not required anymore */ - free(input_token.value); - if(GSS_ERROR(major_status)) { if(output_token.value) gss_release_buffer(&unused_status, &output_token); @@ -172,17 +152,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, } if(output_token.value && output_token.length) { - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) output_token.value, - output_token.length, outptr, outlen); - + result = Curl_bufref_memdup(out, output_token.value, output_token.length); gss_release_buffer(&unused_status, &output_token); } - else if(mutual_auth) { - *outptr = strdup(""); - if(!*outptr) - result = CURLE_OUT_OF_MEMORY; - } + else + Curl_bufref_set(out, mutual_auth? "": NULL, 0, NULL); return result; } @@ -196,24 +170,19 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * chlg64 [in] - Pointer to the optional base64 encoded challenge message. + * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, - size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; - size_t chlglen = 0; size_t messagelen = 0; - unsigned char *chlg = NULL; unsigned char *message = NULL; OM_uint32 major_status; OM_uint32 minor_status; @@ -228,17 +197,9 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, gss_name_t username = GSS_C_NO_NAME; gss_buffer_desc username_token; - /* Decode the base-64 encoded input message */ - if(strlen(chlg64) && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -249,9 +210,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_inquire_context() failed: ", major_status, minor_status); - - free(chlg); - return CURLE_AUTH_ERROR; } @@ -261,15 +219,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_display_name() failed: ", major_status, minor_status); - - free(chlg); - return CURLE_AUTH_ERROR; } /* Setup the challenge "input" security buffer */ - input_token.value = chlg; - input_token.length = chlglen; + input_token.value = (void *) Curl_bufref_ptr(chlg); + input_token.length = Curl_bufref_len(chlg); /* Decrypt the inbound challenge and obtain the qop */ major_status = gss_unwrap(&minor_status, krb5->context, &input_token, @@ -277,27 +232,20 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_unwrap() failed: ", major_status, minor_status); - gss_release_buffer(&unused_status, &username_token); - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(output_token.length != 4) { infof(data, "GSSAPI handshake failure (invalid security data)\n"); - gss_release_buffer(&unused_status, &username_token); - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Copy the data out and free the challenge as it is not required anymore */ memcpy(&indata, output_token.value, 4); gss_release_buffer(&unused_status, &output_token); - free(chlg); /* Extract the security layer */ sec_layer = indata & 0x000000FF; @@ -305,7 +253,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, infof(data, "GSSAPI handshake failure (invalid security layer)\n"); gss_release_buffer(&unused_status, &username_token); - return CURLE_BAD_CONTENT_ENCODING; } @@ -323,7 +270,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, message = malloc(messagelen); if(!message) { gss_release_buffer(&unused_status, &username_token); - return CURLE_OUT_OF_MEMORY; } @@ -352,16 +298,12 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_wrap() failed: ", major_status, minor_status); - free(message); - return CURLE_AUTH_ERROR; } - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) output_token.value, - output_token.length, outptr, outlen); - + /* Return the response. */ + result = Curl_bufref_memdup(out, output_token.value, output_token.length); /* Free the output buffer */ gss_release_buffer(&unused_status, &output_token); diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c index b2d16353438..e110644225d 100644 --- a/lib/vauth/krb5_sspi.c +++ b/lib/vauth/krb5_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2020, Steve Holme, . + * Copyright (C) 2014 - 2021, Steve Holme, . * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,7 +30,6 @@ #include "vauth/vauth.h" #include "urldata.h" -#include "curl_base64.h" #include "warnless.h" #include "curl_multibyte.h" #include "sendf.h" @@ -81,11 +80,9 @@ bool Curl_auth_is_gssapi_supported(void) * host [in] - The host name. * mutual_auth [in] - Flag specifying whether or not mutual authentication * is enabled. - * chlg64 [in] - The optional base64 encoded challenge message. + * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -95,13 +92,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, const char *service, const char *host, const bool mutual_auth, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; - size_t chlglen = 0; - unsigned char *chlg = NULL; CtxtHandle context; PSecPkgInfo SecurityPackage; SecBuffer chlg_buf; @@ -176,18 +171,9 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } - if(chlg64 && *chlg64) { - /* Decode the base-64 encoded challenge message */ - if(*chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty challenge message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -196,8 +182,8 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, chlg_desc.cBuffers = 1; chlg_desc.pBuffers = &chlg_buf; chlg_buf.BufferType = SECBUFFER_TOKEN; - chlg_buf.pvBuffer = chlg; - chlg_buf.cbBuffer = curlx_uztoul(chlglen); + chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg); + chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg)); } /* Setup the response "output" security buffer */ @@ -220,16 +206,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, &resp_desc, &attrs, &expiry); - /* Free the decoded challenge as it is not required anymore */ - free(chlg); - - if(status == SEC_E_INSUFFICIENT_MEMORY) { + if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; - } - if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) return CURLE_AUTH_ERROR; - } if(memcmp(&context, krb5->context, sizeof(context))) { s_pSecFn->DeleteSecurityContext(krb5->context); @@ -238,15 +219,12 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, } if(resp_buf.cbBuffer) { - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) resp_buf.pvBuffer, - resp_buf.cbBuffer, outptr, outlen); - } - else if(mutual_auth) { - *outptr = strdup(""); - if(!*outptr) - result = CURLE_OUT_OF_MEMORY; + result = Curl_bufref_memdup(out, resp_buf.pvBuffer, resp_buf.cbBuffer); } + else if(mutual_auth) + Curl_bufref_set(out, "", 0, NULL); + else + Curl_bufref_set(out, NULL, 0, NULL); return result; } @@ -260,26 +238,20 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * chlg64 [in] - The optional base64 encoded challenge message. + * chlg [in] - The optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, - size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; size_t offset = 0; - size_t chlglen = 0; size_t messagelen = 0; size_t appdatalen = 0; - unsigned char *chlg = NULL; unsigned char *trailer = NULL; unsigned char *message = NULL; unsigned char *padding = NULL; @@ -298,17 +270,9 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, SECURITY_STATUS status; char *user_name; - /* Decode the base-64 encoded input message */ - if(strlen(chlg64) && *chlg64 != '=') { - result = Curl_base64_decode(chlg64, &chlg, &chlglen); - if(result) - return result; - } - /* Ensure we have a valid challenge message */ - if(!chlg) { + if(!Curl_bufref_len(chlg)) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -316,35 +280,31 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, status = s_pSecFn->QueryContextAttributes(krb5->context, SECPKG_ATTR_SIZES, &sizes); - if(status != SEC_E_OK) { - free(chlg); - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; + if(status == SEC_E_INSUFFICIENT_MEMORY) + return CURLE_OUT_OF_MEMORY; + if(status != SEC_E_OK) return CURLE_AUTH_ERROR; - } /* Get the fully qualified username back from the context */ status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, SECPKG_CRED_ATTR_NAMES, &names); - if(status != SEC_E_OK) { - free(chlg); - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; + if(status == SEC_E_INSUFFICIENT_MEMORY) + return CURLE_OUT_OF_MEMORY; + if(status != SEC_E_OK) return CURLE_AUTH_ERROR; - } /* Setup the "input" security buffer */ input_desc.ulVersion = SECBUFFER_VERSION; input_desc.cBuffers = 2; input_desc.pBuffers = input_buf; input_buf[0].BufferType = SECBUFFER_STREAM; - input_buf[0].pvBuffer = chlg; - input_buf[0].cbBuffer = curlx_uztoul(chlglen); + input_buf[0].pvBuffer = (void *) Curl_bufref_ptr(chlg); + input_buf[0].cbBuffer = curlx_uztoul(Curl_bufref_len(chlg)); input_buf[1].BufferType = SECBUFFER_DATA; input_buf[1].pvBuffer = NULL; input_buf[1].cbBuffer = 0; @@ -353,31 +313,23 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop); if(status != SEC_E_OK) { infof(data, "GSSAPI handshake failure (empty security message)\n"); - - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(input_buf[1].cbBuffer != 4) { infof(data, "GSSAPI handshake failure (invalid security data)\n"); - - free(chlg); - return CURLE_BAD_CONTENT_ENCODING; } /* Copy the data out and free the challenge as it is not required anymore */ memcpy(&indata, input_buf[1].pvBuffer, 4); s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); - free(chlg); /* Extract the security layer */ sec_layer = indata & 0x000000FF; if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { infof(data, "GSSAPI handshake failure (invalid security layer)\n"); - return CURLE_BAD_CONTENT_ENCODING; } @@ -479,17 +431,14 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, offset += wrap_buf[1].cbBuffer; memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer); - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) appdata, appdatalen, outptr, - outlen); - /* Free all of our local buffers */ - free(appdata); free(padding); free(message); free(trailer); - return result; + /* Return the response. */ + Curl_bufref_set(out, appdata, appdatalen, curl_free); + return CURLE_OK; } /* diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index a3117f3feec..47e53572cb1 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -36,7 +36,6 @@ #include "urldata.h" #include "non-ascii.h" #include "sendf.h" -#include "curl_base64.h" #include "curl_ntlm_core.h" #include "curl_gethostname.h" #include "curl_multibyte.h" @@ -64,10 +63,6 @@ /* "NTLMSSP" signature is always in ASCII regardless of the platform */ #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" -#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)) -#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \ - ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff)) - #if DEBUG_ME # define DEBUG_OUT(x) x static void ntlm_print_flags(FILE *handle, unsigned long flags) @@ -161,31 +156,31 @@ static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) * Parameters: * * data [in] - The session handle. - * buffer [in] - The decoded type-2 message. - * size [in] - The input buffer size, at least 32 bytes. + * type2ref [in] - The type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, - unsigned char *buffer, - size_t size, + const struct bufref *type2ref, struct ntlmdata *ntlm) { unsigned short target_info_len = 0; unsigned int target_info_offset = 0; + const unsigned char *type2 = Curl_bufref_ptr(type2ref); + size_t type2len = Curl_bufref_len(type2ref); #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) data; #endif - if(size >= 48) { - target_info_len = Curl_read16_le(&buffer[40]); - target_info_offset = Curl_read32_le(&buffer[44]); + if(type2len >= 48) { + target_info_len = Curl_read16_le(&type2[40]); + target_info_offset = Curl_read32_le(&type2[44]); if(target_info_len > 0) { - if((target_info_offset >= size) || - ((target_info_offset + target_info_len) > size) || - (target_info_offset < 48)) { + if((target_info_offset > type2len) || + (target_info_offset + target_info_len) > type2len || + target_info_offset < 48) { infof(data, "NTLM handshake failure (bad type-2 message). " "Target Info Offset Len is set incorrect by the peer\n"); return CURLE_BAD_CONTENT_ENCODING; @@ -196,7 +191,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, if(!ntlm->target_info) return CURLE_OUT_OF_MEMORY; - memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); + memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len); } } @@ -238,21 +233,20 @@ bool Curl_auth_is_ntlm_supported(void) /* * Curl_auth_decode_ntlm_type2_message() * - * This is used to decode an already encoded NTLM type-2 message. The message - * is first decoded from a base64 string into a raw NTLM message and checked - * for validity before the appropriate data for creating a type-3 message is - * written to the given NTLM data structure. + * This is used to decode an NTLM type-2 message. The raw NTLM message is + * checked * for validity before the appropriate data for creating a type-3 + * message is * written to the given NTLM data structure. * * Parameters: * * data [in] - The session handle. - * type2msg [in] - The base64 encoded type-2 message. + * type2ref [in] - The type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, - const char *type2msg, + const struct bufref *type2ref, struct ntlmdata *ntlm) { static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; @@ -274,8 +268,8 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, */ CURLcode result = CURLE_OK; - unsigned char *type2 = NULL; - size_t type2_len = 0; + const unsigned char *type2 = Curl_bufref_ptr(type2ref); + size_t type2len = Curl_bufref_len(type2ref); #if defined(NTLM_NEEDS_NSS_INIT) /* Make sure the crypto backend is initialized */ @@ -286,26 +280,12 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, (void)data; #endif - /* Decode the base-64 encoded type-2 message */ - if(strlen(type2msg) && *type2msg != '=') { - result = Curl_base64_decode(type2msg, &type2, &type2_len); - if(result) - return result; - } - - /* Ensure we have a valid type-2 message */ - if(!type2) { - infof(data, "NTLM handshake failure (empty type-2 message)\n"); - return CURLE_BAD_CONTENT_ENCODING; - } - ntlm->flags = 0; - if((type2_len < 32) || + if((type2len < 32) || (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { /* This was not a good enough type-2 message */ - free(type2); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return CURLE_BAD_CONTENT_ENCODING; } @@ -314,9 +294,8 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, memcpy(ntlm->nonce, &type2[24], 8); if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { - result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); + result = ntlm_decode_type2_target(data, type2ref, ntlm); if(result) { - free(type2); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return result; } @@ -331,8 +310,6 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, fprintf(stderr, "**** Header %s\n ", header); }); - free(type2); - return result; } @@ -350,8 +327,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length) /* * Curl_auth_create_ntlm_type1_message() * - * This is used to generate an already encoded NTLM type-1 message ready for - * sending to the recipient using the appropriate compile time crypto API. + * This is used to generate an NTLM type-1 message ready for sending to the + * recipient using the appropriate compile time crypto API. * * Parameters: * @@ -361,9 +338,7 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length) * service [in] - The service type such as http, smtp, pop or imap. * host [in] - The host name. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -373,7 +348,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, const char *service, const char *hostname, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { /* NTLM type-1 message structure: @@ -391,7 +366,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, size_t size; - unsigned char ntlmbuf[NTLM_BUFSIZE]; + char *ntlmbuf; const char *host = ""; /* empty */ const char *domain = ""; /* empty */ size_t hostlen = 0; @@ -399,6 +374,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, size_t hostoff = 0; size_t domoff = hostoff + hostlen; /* This is 0: remember that host and domain are empty */ + (void)data; (void)userp; (void)passwdp; (void)service, @@ -407,43 +383,46 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, /* Clean up any former leftovers and initialise to defaults */ Curl_auth_cleanup_ntlm(ntlm); -#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) +#if defined(USE_NTRESPONSES) && \ + (defined(USE_NTLM2SESSION) || defined(USE_NTLM_V2)) #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY #else #define NTLM2FLAG 0 #endif - msnprintf((char *)ntlmbuf, NTLM_BUFSIZE, - NTLMSSP_SIGNATURE "%c" - "\x01%c%c%c" /* 32-bit type = 1 */ - "%c%c%c%c" /* 32-bit NTLM flag field */ - "%c%c" /* domain length */ - "%c%c" /* domain allocated space */ - "%c%c" /* domain name offset */ - "%c%c" /* 2 zeroes */ - "%c%c" /* host length */ - "%c%c" /* host allocated space */ - "%c%c" /* host name offset */ - "%c%c" /* 2 zeroes */ - "%s" /* host name */ - "%s", /* domain string */ - 0, /* trailing zero */ - 0, 0, 0, /* part of type-1 long */ - - LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | - NTLMFLAG_REQUEST_TARGET | - NTLMFLAG_NEGOTIATE_NTLM_KEY | - NTLM2FLAG | - NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), - SHORTPAIR(domlen), - SHORTPAIR(domlen), - SHORTPAIR(domoff), - 0, 0, - SHORTPAIR(hostlen), - SHORTPAIR(hostlen), - SHORTPAIR(hostoff), - 0, 0, - host, /* this is empty */ - domain /* this is empty */); + ntlmbuf = aprintf(NTLMSSP_SIGNATURE "%c" + "\x01%c%c%c" /* 32-bit type = 1 */ + "%c%c%c%c" /* 32-bit NTLM flag field */ + "%c%c" /* domain length */ + "%c%c" /* domain allocated space */ + "%c%c" /* domain name offset */ + "%c%c" /* 2 zeroes */ + "%c%c" /* host length */ + "%c%c" /* host allocated space */ + "%c%c" /* host name offset */ + "%c%c" /* 2 zeroes */ + "%s" /* host name */ + "%s", /* domain string */ + 0, /* trailing zero */ + 0, 0, 0, /* part of type-1 long */ + + LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | + NTLMFLAG_REQUEST_TARGET | + NTLMFLAG_NEGOTIATE_NTLM_KEY | + NTLM2FLAG | + NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), + SHORTPAIR(domlen), + SHORTPAIR(domlen), + SHORTPAIR(domoff), + 0, 0, + SHORTPAIR(hostlen), + SHORTPAIR(hostlen), + SHORTPAIR(hostoff), + 0, 0, + host, /* this is empty */ + domain /* this is empty */); + + if(!ntlmbuf) + return CURLE_OUT_OF_MEMORY; /* Initial packet length */ size = 32 + hostlen + domlen; @@ -470,8 +449,8 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, fprintf(stderr, "\n****\n"); }); - /* Return with binary blob encoded into base64 */ - return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); + Curl_bufref_set(out, ntlmbuf, size, curl_free); + return CURLE_OK; } /* @@ -486,9 +465,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, * userp [in] - The user name in the format User or Domain\User. * passwdp [in] - The user's password. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -496,7 +473,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, const char *userp, const char *passwdp, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { /* NTLM type-3 message structure: @@ -563,12 +540,20 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, hostlen = strlen(host); } -#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2) +#if defined(USE_NTRESPONSES) && \ + (defined(USE_NTLM2SESSION) || defined(USE_NTLM_V2)) + /* We don't support NTLM2 or extended security if we don't have + USE_NTRESPONSES */ if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { +# if defined(USE_NTLM_V2) unsigned char ntbuffer[0x18]; unsigned char entropy[8]; unsigned char ntlmv2hash[0x18]; + /* Full NTLM version 2 + Although this cannot be negotiated, it is used here if available, as + servers featuring extended security are likely supporting also + NTLMv2. */ result = Curl_rand(data, entropy, 8); if(result) return result; @@ -595,21 +580,14 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, return result; ptr_ntresp = ntlmv2resp; - } - else -#endif - -#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) - -#define CURL_MD5_DIGEST_LENGTH 16 /* fixed size */ - - /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ - if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) { +# else /* defined(USE_NTLM_V2) */ unsigned char ntbuffer[0x18]; unsigned char tmp[0x18]; - unsigned char md5sum[CURL_MD5_DIGEST_LENGTH]; + unsigned char md5sum[MD5_DIGEST_LEN]; unsigned char entropy[8]; + /* NTLM version 1 with extended security. */ + /* Need to create 8 bytes random data */ result = Curl_rand(data, entropy, 8); if(result) @@ -639,6 +617,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, /* NTLM v2 session security is a misnomer because it is not NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2 */ +# endif /* defined(USE_NTLM_V2) */ } else #endif @@ -649,6 +628,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, #endif unsigned char lmbuffer[0x18]; + /* NTLM version 1 */ + #ifdef USE_NTRESPONSES result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(result) @@ -662,6 +643,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, return result; Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); + ntlm->flags &= ~NTLMFLAG_NEGOTIATE_NTLM2_KEY; /* A safer but less compatible alternative is: * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); @@ -845,8 +827,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, if(result) return CURLE_CONV_FAILED; - /* Return with binary blob encoded into base64 */ - result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen); + /* Return the binary blob. */ + result = Curl_bufref_memdup(out, ntlmbuf, size); Curl_auth_cleanup_ntlm(ntlm); diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c index 07dc97398e0..1b1a1763017 100644 --- a/lib/vauth/ntlm_sspi.c +++ b/lib/vauth/ntlm_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,7 +28,6 @@ #include "vauth/vauth.h" #include "urldata.h" -#include "curl_base64.h" #include "curl_ntlm_core.h" #include "warnless.h" #include "curl_multibyte.h" @@ -78,9 +77,7 @@ bool Curl_auth_is_ntlm_supported(void) * service [in] - The service type such as http, smtp, pop or imap. * host [in] - The host name. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -90,7 +87,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, const char *service, const char *host, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { PSecPkgInfo SecurityPackage; SecBuffer type_1_buf; @@ -181,9 +178,9 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) return CURLE_AUTH_ERROR; - /* Base64 encode the response */ - return Curl_base64_encode(data, (char *) ntlm->output_token, - type_1_buf.cbBuffer, outptr, outlen); + /* Return the response. */ + Curl_bufref_set(out, ntlm->output_token, type_1_buf.cbBuffer, NULL); + return CURLE_OK; } /* @@ -194,42 +191,34 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * type2msg [in] - The base64 encoded type-2 message. + * type2 [in] - The type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, - const char *type2msg, + const struct bufref *type2, struct ntlmdata *ntlm) { - CURLcode result = CURLE_OK; - unsigned char *type2 = NULL; - size_t type2_len = 0; - #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) data; #endif - /* Decode the base-64 encoded type-2 message */ - if(strlen(type2msg) && *type2msg != '=') { - result = Curl_base64_decode(type2msg, &type2, &type2_len); - if(result) - return result; - } - /* Ensure we have a valid type-2 message */ - if(!type2) { + if(!Curl_bufref_len(type2)) { infof(data, "NTLM handshake failure (empty type-2 message)\n"); - return CURLE_BAD_CONTENT_ENCODING; } - /* Simply store the challenge for use later */ - ntlm->input_token = type2; - ntlm->input_token_len = type2_len; + /* Store the challenge for later use */ + ntlm->input_token = malloc(Curl_bufref_len(type2) + 1); + if(!ntlm->input_token) + return CURLE_OUT_OF_MEMORY; + memcpy(ntlm->input_token, Curl_bufref_ptr(type2), Curl_bufref_len(type2)); + ntlm->input_token[Curl_bufref_len(type2)] = '\0'; + ntlm->input_token_len = Curl_bufref_len(type2); - return result; + return CURLE_OK; } /* @@ -245,9 +234,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, * userp [in] - The user name in the format User or Domain\User. * passwdp [in] - The user's password. * ntlm [in/out] - The NTLM data struct being used and modified. - * outptr [in/out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen [out] - The length of the output message. + * out [out] - The result storage. * * Returns CURLE_OK on success. */ @@ -255,7 +242,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, const char *userp, const char *passwdp, struct ntlmdata *ntlm, - char **outptr, size_t *outlen) + struct bufref *out) { CURLcode result = CURLE_OK; SecBuffer type_2_bufs[2]; @@ -331,12 +318,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, return CURLE_AUTH_ERROR; } - /* Base64 encode the response */ - result = Curl_base64_encode(data, (char *) ntlm->output_token, - type_3_buf.cbBuffer, outptr, outlen); - + /* Return the response. */ + result = Curl_bufref_memdup(out, ntlm->output_token, type_3_buf.cbBuffer); Curl_auth_cleanup_ntlm(ntlm); - return result; } diff --git a/lib/vauth/oauth2.c b/lib/vauth/oauth2.c index ca5842a7c0c..a5f16a0bf4c 100644 --- a/lib/vauth/oauth2.c +++ b/lib/vauth/oauth2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,7 +31,6 @@ #include "urldata.h" #include "vauth/vauth.h" -#include "curl_base64.h" #include "warnless.h" #include "curl_printf.h" @@ -42,31 +41,26 @@ /* * Curl_auth_create_oauth_bearer_message() * - * This is used to generate an already encoded OAuth 2.0 message ready for - * sending to the recipient. + * This is used to generate an OAuth 2.0 message ready for sending to the + * recipient. * * Parameters: * - * data[in] - The session handle. * user[in] - The user name. * host[in] - The host name. * port[in] - The port(when not Port 80). * bearer[in] - The bearer token. - * outptr[in / out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen[out] - The length of the output message. + * out[out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_oauth_bearer_message(const char *user, const char *host, const long port, const char *bearer, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; - char *oauth = NULL; + char *oauth; /* Generate the message */ if(port == 0 || port == 80) @@ -78,49 +72,34 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, if(!oauth) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the reply */ - result = Curl_base64_encode(data, oauth, strlen(oauth), outptr, outlen); - - free(oauth); - - return result; + Curl_bufref_set(out, oauth, strlen(oauth), curl_free); + return CURLE_OK; } /* * Curl_auth_create_xoauth_bearer_message() * - * This is used to generate an already encoded XOAuth 2.0 message ready for - * sending to the recipient. + * This is used to generate a XOAuth 2.0 message ready for * sending to the + * recipient. * * Parameters: * - * data[in] - The session handle. * user[in] - The user name. * bearer[in] - The bearer token. - * outptr[in / out] - The address where a pointer to newly allocated memory - * holding the result will be stored upon completion. - * outlen[out] - The length of the output message. + * out[out] - The result storage. * * Returns CURLE_OK on success. */ -CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_xoauth_bearer_message(const char *user, const char *bearer, - char **outptr, size_t *outlen) + struct bufref *out) { - CURLcode result = CURLE_OK; - /* Generate the message */ char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); if(!xoauth) return CURLE_OUT_OF_MEMORY; - /* Base64 encode the reply */ - result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen); - - free(xoauth); - - return result; + Curl_bufref_set(out, xoauth, strlen(xoauth), curl_free); + return CURLE_OK; } #endif /* disabled, no users */ - diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c index 129b8f8b577..3624fb0c4a0 100644 --- a/lib/vauth/vauth.c +++ b/lib/vauth/vauth.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2020, Steve Holme, . + * Copyright (C) 2014 - 2021, Steve Holme, . * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -72,6 +72,7 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, { char *utf8_spn = NULL; TCHAR *tchar_spn = NULL; + TCHAR *dupe_tchar_spn = NULL; (void) realm; @@ -84,23 +85,19 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, /* Generate our UTF8 based SPN */ utf8_spn = aprintf("%s/%s", service, host); - if(!utf8_spn) { + if(!utf8_spn) return NULL; - } - /* Allocate our TCHAR based SPN */ + /* Allocate and return a TCHAR based SPN. Since curlx_convert_UTF8_to_tchar + must be freed by curlx_unicodefree we'll dupe the result so that the + pointer this function returns can be normally free'd. */ tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn); - if(!tchar_spn) { - free(utf8_spn); - + free(utf8_spn); + if(!tchar_spn) return NULL; - } - - /* Release the UTF8 variant when operating with Unicode */ - curlx_unicodefree(utf8_spn); - - /* Return our newly allocated SPN */ - return tchar_spn; + dupe_tchar_spn = _tcsdup(tchar_spn); + curlx_unicodefree(tchar_spn); + return dupe_tchar_spn; } #endif /* USE_WINDOWS_SSPI */ diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h index f25cfc329f8..ec5b0007f50 100644 --- a/lib/vauth/vauth.h +++ b/lib/vauth/vauth.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2020, Steve Holme, . + * Copyright (C) 2014 - 2021, Steve Holme, . * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,6 +24,8 @@ #include +#include "bufref.h" + struct Curl_easy; #if !defined(CURL_DISABLE_CRYPTO_AUTH) @@ -42,6 +44,10 @@ struct kerberos5data; struct negotiatedata; #endif +#if defined(USE_GSASL) +struct gsasldata; +#endif + #if defined(USE_WINDOWS_SSPI) #define GSS_ERROR(status) ((status) & 0x80000000) #endif @@ -58,45 +64,37 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, /* This is used to test if the user contains a Windows domain name */ bool Curl_auth_user_contains_domain(const char *user); -/* This is used to generate a base64 encoded PLAIN cleartext message */ -CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, - const char *authzid, +/* This is used to generate a PLAIN cleartext message */ +CURLcode Curl_auth_create_plain_message(const char *authzid, const char *authcid, const char *passwd, - char **outptr, size_t *outlen); + struct bufref *out); -/* This is used to generate a base64 encoded LOGIN cleartext message */ -CURLcode Curl_auth_create_login_message(struct Curl_easy *data, - const char *valuep, char **outptr, - size_t *outlen); +/* This is used to generate a LOGIN cleartext message */ +CURLcode Curl_auth_create_login_message(const char *value, + struct bufref *out); -/* This is used to generate a base64 encoded EXTERNAL cleartext message */ -CURLcode Curl_auth_create_external_message(struct Curl_easy *data, - const char *user, char **outptr, - size_t *outlen); +/* This is used to generate an EXTERNAL cleartext message */ +CURLcode Curl_auth_create_external_message(const char *user, + struct bufref *out); #if !defined(CURL_DISABLE_CRYPTO_AUTH) -/* This is used to decode a CRAM-MD5 challenge message */ -CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, - size_t *outlen); - /* This is used to generate a CRAM-MD5 response message */ -CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, - const char *chlg, +CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg, const char *userp, const char *passwdp, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to evaluate if DIGEST is supported */ bool Curl_auth_is_digest_supported(void); /* This is used to generate a base64 encoded DIGEST-MD5 response message */ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, - const char *chlg64, + const struct bufref *chlg, const char *userp, const char *passwdp, const char *service, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to decode a HTTP DIGEST challenge message */ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, @@ -115,6 +113,27 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, void Curl_auth_digest_cleanup(struct digestdata *digest); #endif /* !CURL_DISABLE_CRYPTO_AUTH */ +#ifdef USE_GSASL +/* This is used to evaluate if MECH is supported by gsasl */ +bool Curl_auth_gsasl_is_supported(struct Curl_easy *data, + const char *mech, + struct gsasldata *gsasl); +/* This is used to start a gsasl method */ +CURLcode Curl_auth_gsasl_start(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct gsasldata *gsasl); + +/* This is used to process and generate a new SASL token */ +CURLcode Curl_auth_gsasl_token(struct Curl_easy *data, + const struct bufref *chlg, + struct gsasldata *gsasl, + struct bufref *out); + +/* This is used to clean up the gsasl specific data */ +void Curl_auth_gsasl_cleanup(struct gsasldata *digest); +#endif + #if defined(USE_NTLM) /* This is used to evaluate if NTLM is supported */ bool Curl_auth_is_ntlm_supported(void); @@ -126,12 +145,11 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, const char *service, const char *host, struct ntlmdata *ntlm, - char **outptr, - size_t *outlen); + struct bufref *out); /* This is used to decode a base64 encoded NTLM type-2 message */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, - const char *type2msg, + const struct bufref *type2, struct ntlmdata *ntlm); /* This is used to generate a base64 encoded NTLM type-3 message */ @@ -139,25 +157,23 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, const char *userp, const char *passwdp, struct ntlmdata *ntlm, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to clean up the NTLM specific data */ void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm); #endif /* USE_NTLM */ /* This is used to generate a base64 encoded OAuth 2.0 message */ -CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_oauth_bearer_message(const char *user, const char *host, const long port, const char *bearer, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to generate a base64 encoded XOAuth 2.0 message */ -CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data, - const char *user, +CURLcode Curl_auth_create_xoauth_bearer_message(const char *user, const char *bearer, - char **outptr, size_t *outlen); + struct bufref *out); #if defined(USE_KERBEROS5) /* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ @@ -171,17 +187,16 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, const char *service, const char *host, const bool mutual, - const char *chlg64, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, size_t *outlen); + struct bufref *out); /* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security token message */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, - const char *input, + const struct bufref *chlg, struct kerberos5data *krb5, - char **outptr, - size_t *outlen); + struct bufref *out); /* This is used to clean up the GSSAPI specific data */ void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5); diff --git a/lib/version.c b/lib/version.c index a9102ec1ea5..b67b9a46605 100644 --- a/lib/version.c +++ b/lib/version.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -66,6 +66,14 @@ #include #endif +#ifdef USE_GSASL +#include +#endif + +#ifdef USE_OPENLDAP +#include +#endif + #ifdef HAVE_BROTLI static size_t brotli_version(char *buf, size_t bufsz) { @@ -100,7 +108,7 @@ static size_t zstd_version(char *buf, size_t bufsz) * zeros in the data. */ -#define VERSION_PARTS 15 /* number of substrings we can concatenate */ +#define VERSION_PARTS 17 /* number of substrings we can concatenate */ char *curl_version(void) { @@ -146,6 +154,12 @@ char *curl_version(void) #endif #ifdef USE_HYPER char hyper_buf[30]; +#endif +#ifdef USE_GSASL + char gsasl_buf[30]; +#endif +#ifdef USE_OPENLDAP + char ldap_buf[30]; #endif int i = 0; int j; @@ -235,6 +249,29 @@ char *curl_version(void) msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version()); src[i++] = hyper_buf; #endif +#ifdef USE_GSASL + msnprintf(gsasl_buf, sizeof(gsasl_buf), "libgsasl/%s", + gsasl_check_version(NULL)); + src[i++] = gsasl_buf; +#endif +#ifdef USE_OPENLDAP + { + LDAPAPIInfo api; + api.ldapai_info_version = LDAP_API_INFO_VERSION; + + if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) { + unsigned int patch = api.ldapai_vendor_version % 100; + unsigned int major = api.ldapai_vendor_version / 10000; + unsigned int minor = + ((api.ldapai_vendor_version - major * 10000) - patch) / 100; + msnprintf(ldap_buf, sizeof(ldap_buf), "%s/%u.%u.%u", + api.ldapai_vendor_name, major, minor, patch); + src[i++] = ldap_buf; + ldap_memfree(api.ldapai_vendor_name); + ber_memvfree((void **)api.ldapai_extensions); + } + } +#endif DEBUGASSERT(i <= VERSION_PARTS); @@ -326,7 +363,7 @@ static const char * const protocols[] = { "sftp", #endif #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (CURL_SIZEOF_CURL_OFF_T > 4) + (SIZEOF_CURL_OFF_T > 4) "smb", # ifdef USE_SSL "smbs", @@ -391,7 +428,7 @@ static curl_version_info_data version_info = { #ifdef CURLRES_ASYNCH | CURL_VERSION_ASYNCHDNS #endif -#if (CURL_SIZEOF_CURL_OFF_T > 4) && \ +#if (SIZEOF_CURL_OFF_T > 4) && \ ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) | CURL_VERSION_LARGEFILE #endif @@ -428,8 +465,11 @@ static curl_version_info_data version_info = { #ifndef CURL_DISABLE_ALTSVC | CURL_VERSION_ALTSVC #endif -#if defined(USE_HSTS) +#ifndef CURL_DISABLE_HSTS | CURL_VERSION_HSTS +#endif +#if defined(USE_GSASL) + | CURL_VERSION_GSASL #endif , NULL, /* ssl_version */ @@ -458,7 +498,8 @@ static curl_version_info_data version_info = { #endif 0, /* zstd_ver_num */ NULL, /* zstd version */ - NULL /* Hyper version */ + NULL, /* Hyper version */ + NULL /* gsasl version */ }; curl_version_info_data *curl_version_info(CURLversion stamp) @@ -562,6 +603,12 @@ curl_version_info_data *curl_version_info(CURLversion stamp) } #endif +#ifdef USE_GSASL + { + version_info.gsasl_version = gsasl_check_version(NULL); + } +#endif + (void)stamp; /* avoid compiler warnings, we don't use this */ return &version_info; } diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c index d4d0e8bf436..7f076759b8f 100644 --- a/lib/vquic/ngtcp2.c +++ b/lib/vquic/ngtcp2.c @@ -57,6 +57,8 @@ #define H3BUGF(x) do { } while(0) #endif +#define H3_ALPN_H3_29 "\x5h3-29" + /* * This holds outgoing HTTP/3 stream data that is used by nghttp3 until acked. * It is used as a circular buffer. Add new bytes at the end until it reaches @@ -224,7 +226,7 @@ static int write_client_handshake(struct quicsocket *qs, int rv; crypto_data = &qs->crypto_data[level]; - if(crypto_data->buf == NULL) { + if(!crypto_data->buf) { crypto_data->buf = malloc(4096); if(!crypto_data->buf) return 0; @@ -351,8 +353,8 @@ static int quic_init_ssl(struct quicsocket *qs) SSL_set_app_data(qs->ssl, qs); SSL_set_connect_state(qs->ssl); - alpn = (const uint8_t *)NGHTTP3_ALPN_H3; - alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1; + alpn = (const uint8_t *)H3_ALPN_H3_29; + alpnlen = sizeof(H3_ALPN_H3_29) - 1; if(alpn) SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen); @@ -529,8 +531,8 @@ static int quic_init_ssl(struct quicsocket *qs) } /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */ - alpn.data = (unsigned char *)NGHTTP3_ALPN_H3 + 1; - alpn.size = sizeof(NGHTTP3_ALPN_H3) - 2; + alpn.data = (unsigned char *)H3_ALPN_H3_29 + 1; + alpn.size = sizeof(H3_ALPN_H3_29) - 2; if(alpn.data) gnutls_alpn_set_protocols(qs->ssl, &alpn, 1, 0); @@ -580,7 +582,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, { struct quicsocket *qs = (struct quicsocket *)user_data; ssize_t nconsumed; - int fin = flags & NGTCP2_STREAM_DATA_FLAG_FIN ? 1 : 0; + int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0; (void)offset; (void)stream_user_data; @@ -601,7 +603,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, static int cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, - uint64_t offset, size_t datalen, void *user_data, + uint64_t offset, uint64_t datalen, void *user_data, void *stream_user_data) { struct quicsocket *qs = (struct quicsocket *)user_data; @@ -613,7 +615,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -632,7 +634,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id, rv = nghttp3_conn_close_stream(qs->h3conn, stream_id, app_error_code); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -651,7 +653,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -680,7 +682,7 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id); - if(rv != 0) { + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -739,7 +741,10 @@ static ngtcp2_callbacks ng_callbacks = { NULL, /* handshake_confirmed */ NULL, /* recv_new_token */ ngtcp2_crypto_delete_crypto_aead_ctx_cb, - ngtcp2_crypto_delete_crypto_cipher_ctx_cb + ngtcp2_crypto_delete_crypto_cipher_ctx_cb, + NULL, /* recv_datagram */ + NULL, /* ack_datagram */ + NULL /* lost_datagram */ }; /* @@ -758,7 +763,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, ngtcp2_path path; /* TODO: this must be initialized properly */ struct quicsocket *qs = &conn->hequic[sockindex]; char ipbuf[40]; - long port; + int port; int qfd; if(qs->conn) @@ -773,7 +778,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, return CURLE_BAD_FUNCTION_ARGUMENT; } - infof(data, "Connect socket %d over QUIC to %s:%ld\n", + infof(data, "Connect socket %d over QUIC to %s:%d\n", sockfd, ipbuf, port); qs->version = NGTCP2_PROTO_VER_MAX; @@ -807,8 +812,8 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, return CURLE_QUIC_CONNECT_ERROR; ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr, - qs->local_addrlen, NULL); - ngtcp2_addr_init(&path.remote, addr, addrlen, NULL); + qs->local_addrlen); + ngtcp2_addr_init(&path.remote, addr, addrlen); rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, NGTCP2_PROTO_VER_MIN, &ng_callbacks, @@ -827,7 +832,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, */ int Curl_quic_ver(char *p, size_t len) { - ngtcp2_info *ng2 = ngtcp2_version(0); + const ngtcp2_info *ng2 = ngtcp2_version(0); nghttp3_info *ht3 = nghttp3_version(0); return msnprintf(p, len, "ngtcp2/%s nghttp3/%s", ng2->version_str, ht3->version_str); @@ -870,8 +875,10 @@ static void qs_disconnect(struct quicsocket *qs) #endif qs->ssl = NULL; #ifdef USE_GNUTLS - if(qs->cred) + if(qs->cred) { gnutls_certificate_free_credentials(qs->cred); + qs->cred = NULL; + } #endif for(i = 0; i < 3; i++) Curl_safefree(qs->crypto_data[i].buf); @@ -927,6 +934,7 @@ static const struct Curl_handler Curl_handler_http3 = { ng_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ng_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -1291,7 +1299,6 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, { struct Curl_easy *data = stream_user_data; struct HTTP *stream = data->req.p.http; - int rv; (void)user_data; if(!data->set.postfields) { @@ -1302,8 +1309,8 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE); if(stream->h3out->used == 0) { - rv = nghttp3_conn_resume_stream(conn, stream_id); - if(rv != 0) { + int rv = nghttp3_conn_resume_stream(conn, stream_id); + if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } } @@ -1539,7 +1546,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, } /* :authority must come before non-pseudo header fields */ - if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + if(authority_idx && authority_idx != AUTHORITY_DST_IDX) { nghttp3_nv authority = nva[authority_idx]; for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { nva[i] = nva[i - 1]; @@ -1730,12 +1737,12 @@ static CURLcode ng_process_ingress(struct Curl_easy *data, } ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr, - qs->local_addrlen, NULL); + qs->local_addrlen); ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr, - remote_addrlen, NULL); + remote_addrlen); rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts); - if(rv != 0) { + if(rv) { /* TODO Send CONNECTION_CLOSE if possible */ return CURLE_RECV_ERROR; } @@ -1779,7 +1786,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, } rv = ngtcp2_conn_handle_expiry(qs->qconn, ts); - if(rv != 0) { + if(rv) { failf(data, "ngtcp2_conn_handle_expiry returned error: %s", ngtcp2_strerror(rv)); return CURLE_SEND_ERROR; @@ -1788,7 +1795,6 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, ngtcp2_path_storage_zero(&ps); for(;;) { - outlen = -1; veccnt = 0; stream_id = -1; fin = 0; @@ -1816,7 +1822,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, outlen == NGTCP2_ERR_STREAM_SHUT_WR) { assert(ndatalen == -1); rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); - if(rv != 0) { + if(rv) { failf(data, "nghttp3_conn_block_stream returned error: %s\n", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; @@ -1826,7 +1832,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, else if(outlen == NGTCP2_ERR_WRITE_MORE) { assert(ndatalen >= 0); rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); - if(rv != 0) { + if(rv) { failf(data, "nghttp3_conn_add_write_offset returned error: %s\n", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; @@ -1842,7 +1848,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, } else if(ndatalen >= 0) { rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); - if(rv != 0) { + if(rv) { failf(data, "nghttp3_conn_add_write_offset returned error: %s\n", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c index d138dd3a244..b62d88437a1 100644 --- a/lib/vquic/quiche.c +++ b/lib/vquic/quiche.c @@ -157,6 +157,7 @@ static const struct Curl_handler Curl_handler_http3 = { quiche_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ quiche_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ @@ -180,7 +181,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, struct quicsocket *qs = &conn->hequic[sockindex]; char *keylog_file = NULL; char ipbuf[40]; - long port; + int port; #ifdef DEBUG_QUICHE /* initialize debug log callback only once */ @@ -225,7 +226,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, quiche_config_log_keys(qs->cfg); qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid, - sizeof(qs->scid), qs->cfg); + sizeof(qs->scid), addr, addrlen, qs->cfg); if(!qs->conn) { failf(data, "can't create quiche connection"); return CURLE_OUT_OF_MEMORY; @@ -359,22 +360,34 @@ static CURLcode process_ingress(struct Curl_easy *data, int sockfd, ssize_t recvd; uint8_t *buf = (uint8_t *)data->state.buffer; size_t bufsize = data->set.buffer_size; + struct sockaddr_storage from; + socklen_t from_len; + quiche_recv_info recv_info; + + DEBUGASSERT(qs->conn); /* in case the timeout expired */ quiche_conn_on_timeout(qs->conn); do { - recvd = recv(sockfd, buf, bufsize, 0); + from_len = sizeof(from); + + recvd = recvfrom(sockfd, buf, bufsize, 0, + (struct sockaddr *)&from, &from_len); + if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK))) break; if(recvd < 0) { - failf(data, "quiche: recv() unexpectedly returned %zd " + failf(data, "quiche: recvfrom() unexpectedly returned %zd " "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd); return CURLE_RECV_ERROR; } - recvd = quiche_conn_recv(qs->conn, buf, recvd); + recv_info.from = (struct sockaddr *) &from; + recv_info.from_len = from_len; + + recvd = quiche_conn_recv(qs->conn, buf, recvd, &recv_info); if(recvd == QUICHE_ERR_DONE) break; @@ -397,9 +410,10 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd, ssize_t sent; uint8_t out[1200]; int64_t timeout_ns; + quiche_send_info send_info; do { - sent = quiche_conn_send(qs->conn, out, sizeof(out)); + sent = quiche_conn_send(qs->conn, out, sizeof(out), &send_info); if(sent == QUICHE_ERR_DONE) break; @@ -408,9 +422,10 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd, return CURLE_SEND_ERROR; } - sent = send(sockfd, out, sent, 0); + sent = sendto(sockfd, out, sent, 0, + (struct sockaddr *)&send_info.to, send_info.to_len); if(sent < 0) { - failf(data, "send() returned %zd", sent); + failf(data, "sendto() returned %zd", sent); return CURLE_SEND_ERROR; } } while(1); @@ -748,7 +763,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, } /* :authority must come before non-pseudo header fields */ - if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) { + if(authority_idx && authority_idx != AUTHORITY_DST_IDX) { quiche_h3_header authority = nva[authority_idx]; for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) { nva[i] = nva[i - 1]; diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c index 08896ab5b1c..d146d15fdfd 100644 --- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -159,6 +159,7 @@ const struct Curl_handler Curl_handler_scp = { scp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ CURLPROTO_SCP, /* family */ @@ -185,6 +186,7 @@ const struct Curl_handler Curl_handler_sftp = { sftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ @@ -549,49 +551,48 @@ static int myssh_is_known(struct Curl_easy *data) return rc; } -#define MOVE_TO_ERROR_STATE(_r) { \ - state(data, SSH_SESSION_DISCONNECT); \ - sshc->actualcode = _r; \ - rc = SSH_ERROR; \ - break; \ -} +#define MOVE_TO_ERROR_STATE(_r) do { \ + state(data, SSH_SESSION_DISCONNECT); \ + sshc->actualcode = _r; \ + rc = SSH_ERROR; \ + } while(0) -#define MOVE_TO_SFTP_CLOSE_STATE() { \ - state(data, SSH_SFTP_CLOSE); \ - sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ - rc = SSH_ERROR; \ - break; \ -} +#define MOVE_TO_SFTP_CLOSE_STATE() do { \ + state(data, SSH_SFTP_CLOSE); \ + sshc->actualcode = \ + sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \ + rc = SSH_ERROR; \ + } while(0) -#define MOVE_TO_LAST_AUTH \ - if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ - rc = SSH_OK; \ - state(data, SSH_AUTH_PASS_INIT); \ - break; \ - } \ - else { \ - MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ - } +#define MOVE_TO_LAST_AUTH do { \ + if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ + rc = SSH_OK; \ + state(data, SSH_AUTH_PASS_INIT); \ + } \ + else { \ + MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ + } \ + } while(0) -#define MOVE_TO_TERTIARY_AUTH \ - if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ - rc = SSH_OK; \ - state(data, SSH_AUTH_KEY_INIT); \ - break; \ - } \ - else { \ - MOVE_TO_LAST_AUTH; \ - } +#define MOVE_TO_TERTIARY_AUTH do { \ + if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ + rc = SSH_OK; \ + state(data, SSH_AUTH_KEY_INIT); \ + } \ + else { \ + MOVE_TO_LAST_AUTH; \ + } \ + } while(0) -#define MOVE_TO_SECONDARY_AUTH \ - if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ - rc = SSH_OK; \ - state(data, SSH_AUTH_GSSAPI); \ - break; \ - } \ - else { \ - MOVE_TO_TERTIARY_AUTH; \ - } +#define MOVE_TO_SECONDARY_AUTH do { \ + if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ + rc = SSH_OK; \ + state(data, SSH_AUTH_GSSAPI); \ + } \ + else { \ + MOVE_TO_TERTIARY_AUTH; \ + } \ + } while(0) static int myssh_auth_interactive(struct connectdata *conn) @@ -629,7 +630,7 @@ int myssh_auth_interactive(struct connectdata *conn) rc = SSH_OK; else if(rc == SSH_AUTH_INFO) { nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); - if(nprompts != 0) + if(nprompts) return SSH_ERROR; sshc->kbd_state = 2; @@ -704,6 +705,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc != SSH_OK) { failf(data, "Failure establishing ssh session"); MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT); + break; } state(data, SSH_HOSTKEY); @@ -714,6 +716,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) rc = myssh_is_known(data); if(rc != SSH_OK) { MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION); + break; } state(data, SSH_AUTHLIST); @@ -735,6 +738,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else if(rc == SSH_AUTH_ERROR) { MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; } sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); @@ -753,6 +757,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else { /* unsupported authentication method */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; } break; @@ -760,6 +765,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_AUTH_PKEY_INIT: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) { MOVE_TO_SECONDARY_AUTH; + break; } /* Two choices, (1) private key was given on CMD, @@ -775,6 +781,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc != SSH_OK) { MOVE_TO_SECONDARY_AUTH; + break; } } @@ -833,6 +840,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_AUTH_GSSAPI: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) { MOVE_TO_TERTIARY_AUTH; + break; } rc = ssh_userauth_gssapi(sshc->ssh_session); @@ -879,6 +887,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) { /* Host key authentication is intentionally not implemented */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); + break; } state(data, SSH_AUTH_PASS); /* FALLTHROUGH */ @@ -951,8 +960,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) * Get the "home" directory */ sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, "."); - if(sshc->homedir == NULL) { + if(!sshc->homedir) { MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + break; } data->state.most_recent_ftp_entrypath = sshc->homedir; @@ -1025,7 +1035,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_SETSTAT: rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2, sshc->quote_attrs); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Attempt to set SFTP stats failed: %s", @@ -1044,7 +1054,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_SYMLINK: rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2, sshc->quote_path1); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "symlink command failed: %s", @@ -1060,7 +1070,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_MKDIR: rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1, (mode_t)data->set.new_directory_perms); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", ssh_get_error(sshc->ssh_session)); @@ -1075,7 +1085,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_RENAME: rc = sftp_rename(sshc->sftp_session, sshc->quote_path1, sshc->quote_path2); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "rename command failed: %s", @@ -1090,7 +1100,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_RMDIR: rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", ssh_get_error(sshc->ssh_session)); @@ -1104,7 +1114,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_QUOTE_UNLINK: rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1); - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", ssh_get_error(sshc->ssh_session)); @@ -1179,7 +1189,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) sftp_attributes attrs; attrs = sftp_stat(sshc->sftp_session, protop->path); - if(attrs != 0) { + if(attrs) { data->info.filetime = attrs->mtime; sftp_attributes_free(attrs); } @@ -1203,16 +1213,17 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) { int flags; - if(data->state.resume_from != 0) { + if(data->state.resume_from) { sftp_attributes attrs; if(data->state.resume_from < 0) { attrs = sftp_stat(sshc->sftp_session, protop->path); - if(attrs != 0) { + if(attrs) { curl_off_t size = attrs->size; if(size < 0) { failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME); + break; } data->state.resume_from = attrs->size; @@ -1224,7 +1235,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } } - if(data->set.ftp_append) + if(data->set.remote_append) /* Try to open for append, but create if nonexisting */ flags = O_WRONLY|O_CREAT|O_APPEND; else if(data->state.resume_from > 0) @@ -1254,6 +1265,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } @@ -1292,8 +1304,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) CURL_READFUNC_ABORT return code still aborts */ failf(data, "Failed to read data"); MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST); + break; } } while(passed < data->state.resume_from); + if(rc) + break; } /* now, decrease the size of the read */ @@ -1304,8 +1319,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); - if(rc != 0) { + if(rc) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } if(data->state.infilesize > 0) { @@ -1375,6 +1391,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) (err != SSH_FX_FAILURE) && (err != SSH_FX_PERMISSION_DENIED)) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } rc = 0; /* clear rc and continue */ } @@ -1398,6 +1415,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) failf(data, "Could not open directory for reading: %s", ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); + break; } state(data, SSH_SFTP_READDIR); break; @@ -1413,11 +1431,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) sshc->readdir_longentry = sshc->readdir_attrs->longname; sshc->readdir_len = strlen(sshc->readdir_filename); - if(data->set.ftp_list_only) { + if(data->set.list_only) { char *tmpLine; tmpLine = aprintf("%s\n", sshc->readdir_filename); - if(tmpLine == NULL) { + if(!tmpLine) { state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; @@ -1453,16 +1471,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) && ((sshc->readdir_attrs->permissions & S_IFMT) == S_IFLNK)) { - sshc->readdir_linkPath = malloc(PATH_MAX + 1); - if(sshc->readdir_linkPath == NULL) { + sshc->readdir_linkPath = aprintf("%s%s", protop->path, + sshc->readdir_filename); + + if(!sshc->readdir_linkPath) { state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path, - sshc->readdir_filename); - state(data, SSH_SFTP_READDIR_LINK); break; } @@ -1492,12 +1509,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) failf(data, "Could not read symlink for reading: %s", ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); + break; } - if(sshc->readdir_link_attrs->name == NULL) { + if(!sshc->readdir_link_attrs->name) { sshc->readdir_tmp = sftp_readlink(sshc->sftp_session, sshc->readdir_linkPath); - if(sshc->readdir_filename == NULL) + if(!sshc->readdir_filename) sshc->readdir_len = 0; else sshc->readdir_len = strlen(sshc->readdir_tmp); @@ -1587,6 +1605,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) ssh_get_error(sshc->ssh_session)); MOVE_TO_SFTP_CLOSE_STATE(); + break; } state(data, SSH_SFTP_DOWNLOAD_STAT); @@ -1662,8 +1681,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } rc = sftp_seek64(sshc->sftp_file, from); - if(rc != 0) { + if(rc) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } data->req.size = size; @@ -1700,8 +1720,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) size - data->state.resume_from); rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); - if(rc != 0) { + if(rc) { MOVE_TO_SFTP_CLOSE_STATE(); + break; } } } @@ -1796,6 +1817,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) failf(data, "SCP requires a known file size for upload"); sshc->actualcode = CURLE_UPLOAD_FAILED; MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + break; } sshc->scp_session = @@ -1823,6 +1845,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) err_msg = ssh_get_error(sshc->ssh_session); failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + break; } rc = ssh_scp_push_file(sshc->scp_session, protop->path, @@ -1832,6 +1855,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) err_msg = ssh_get_error(sshc->ssh_session); failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED); + break; } /* upload data */ @@ -1860,6 +1884,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) err_msg = ssh_get_error(sshc->ssh_session); failf(data, "%s", err_msg); MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT); + break; } state(data, SSH_SCP_DOWNLOAD); /* FALLTHROUGH */ @@ -2164,7 +2189,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) ssh = &conn->proto.sshc; ssh->ssh_session = ssh_new(); - if(ssh->ssh_session == NULL) { + if(!ssh->ssh_session) { failf(data, "Failure initialising ssh session"); return CURLE_FAILED_INIT; } @@ -2662,7 +2687,7 @@ static void sftp_quote(struct Curl_easy *data) * command with a space so we can check for it unconditionally */ cp = strchr(cmd, ' '); - if(cp == NULL) { + if(!cp) { failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); state(data, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; @@ -2811,7 +2836,7 @@ static void sftp_quote_stat(struct Curl_easy *data) if(sshc->quote_attrs) sftp_attributes_free(sshc->quote_attrs); sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2); - if(sshc->quote_attrs == NULL) { + if(!sshc->quote_attrs) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); failf(data, "Attempt to get SFTP stats failed: %d", diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index 3130dcc74d5..8a6345b9487 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -121,6 +121,7 @@ static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn, curl_socket_t *sock); static CURLcode ssh_setup_connection(struct Curl_easy *data, struct connectdata *conn); +static void ssh_attach(struct Curl_easy *data, struct connectdata *conn); /* * SCP protocol handler. @@ -142,6 +143,7 @@ const struct Curl_handler Curl_handler_scp = { scp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ssh_attach, PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ CURLPROTO_SCP, /* family */ @@ -170,6 +172,7 @@ const struct Curl_handler Curl_handler_sftp = { sftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ssh_attach, PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ @@ -184,7 +187,7 @@ kbd_callback(const char *name, int name_len, const char *instruction, LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract) { - struct connectdata *conn = (struct connectdata *)*abstract; + struct Curl_easy *data = (struct Curl_easy *)*abstract; #ifdef CURL_LIBSSH2_DEBUG fprintf(stderr, "name=%s\n", name); @@ -199,11 +202,11 @@ kbd_callback(const char *name, int name_len, const char *instruction, (void)instruction_len; #endif /* CURL_LIBSSH2_DEBUG */ if(num_prompts == 1) { + struct connectdata *conn = data->conn; responses[0].text = strdup(conn->passwd); responses[0].length = curlx_uztoui(strlen(conn->passwd)); } (void)prompts; - (void)abstract; } /* kbd_callback */ static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err) @@ -956,7 +959,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) out_of_memory = TRUE; } - if(out_of_memory || sshc->rsa == NULL) { + if(out_of_memory || !sshc->rsa) { Curl_safefree(sshc->rsa); Curl_safefree(sshc->rsa_pub); state(data, SSH_SESSION_FREE); @@ -1359,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) * command with a space so we can check for it unconditionally */ cp = strchr(cmd, ' '); - if(cp == NULL) { + if(!cp) { failf(data, "Syntax error command '%s'. Missing parameter!", cmd); state(data, SSH_SFTP_CLOSE); @@ -1534,7 +1537,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ + if(rc && !sshc->acceptfail) { /* get those attributes */ sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1633,7 +1636,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1656,7 +1659,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1677,7 +1680,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", @@ -1702,7 +1705,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1722,7 +1725,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", @@ -1741,7 +1744,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr)); @@ -1764,7 +1767,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - if(rc != 0 && !sshc->acceptfail) { + if(rc && !sshc->acceptfail) { sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "statvfs command failed: %s", @@ -1857,7 +1860,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) * same name as the last directory in the path. */ - if(data->state.resume_from != 0) { + if(data->state.resume_from) { LIBSSH2_SFTP_ATTRIBUTES attrs; if(data->state.resume_from < 0) { rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, @@ -1880,7 +1883,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) } } - if(data->set.ftp_append) + if(data->set.remote_append) /* Try to open for append, but create if nonexisting */ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; else if(data->state.resume_from > 0) @@ -2143,7 +2146,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) readdir_len = (size_t) rc; sshp->readdir_filename[readdir_len] = '\0'; - if(data->set.ftp_list_only) { + if(data->set.list_only) { result = Curl_client_write(data, CLIENTWRITE_BODY, sshp->readdir_filename, readdir_len); @@ -2931,7 +2934,7 @@ static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done) static CURLcode ssh_block_statemach(struct Curl_easy *data, struct connectdata *conn, - bool duringconnect) + bool disconnect) { struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; @@ -2945,17 +2948,19 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, if(result) break; - if(Curl_pgrsUpdate(data)) - return CURLE_ABORTED_BY_CALLBACK; + if(!disconnect) { + if(Curl_pgrsUpdate(data)) + return CURLE_ABORTED_BY_CALLBACK; - result = Curl_speedcheck(data, now); - if(result) - break; + result = Curl_speedcheck(data, now); + if(result) + break; - left = Curl_timeleft(data, NULL, duringconnect); - if(left < 0) { - failf(data, "Operation timed out"); - return CURLE_OPERATION_TIMEDOUT; + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } } if(block) { @@ -3054,17 +3059,15 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) #ifdef CURL_LIBSSH2_DEBUG curl_socket_t sock; #endif - struct SSHPROTO *sshp = data->req.p.ssh; struct ssh_conn *sshc; CURLcode result; struct connectdata *conn = data->conn; /* initialize per-handle data if not already */ - if(!sshp) { + if(!data->req.p.ssh) { result = ssh_setup_connection(data, conn); if(result) return result; - sshp = data->req.p.ssh; } /* We default to persistent connections. We set this already in this connect @@ -3086,7 +3089,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, my_libssh2_free, my_libssh2_realloc, data); - if(sshc->ssh_session == NULL) { + if(!sshc->ssh_session) { failf(data, "Failure initialising ssh session"); return CURLE_FAILED_INIT; } @@ -3159,6 +3162,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) sshc->kh = libssh2_knownhost_init(sshc->ssh_session); if(!sshc->kh) { libssh2_session_free(sshc->ssh_session); + sshc->ssh_session = NULL; return CURLE_FAILED_INIT; } @@ -3279,10 +3283,8 @@ static CURLcode scp_disconnect(struct Curl_easy *data, if(sshc->ssh_session) { /* only if there's a session still around to use! */ - state(data, SSH_SESSION_DISCONNECT); - - result = ssh_block_statemach(data, conn, FALSE); + result = ssh_block_statemach(data, conn, TRUE); } return result; @@ -3296,10 +3298,9 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status) struct SSHPROTO *sshp = data->req.p.ssh; struct connectdata *conn = data->conn; - if(!status) { + if(!status) /* run the state-machine */ result = ssh_block_statemach(data, conn, FALSE); - } else result = status; @@ -3439,7 +3440,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, if(sshc->ssh_session) { /* only if there's a session still around to use! */ state(data, SSH_SFTP_SHUTDOWN); - result = ssh_block_statemach(data, conn, FALSE); + result = ssh_block_statemach(data, conn, TRUE); } DEBUGF(infof(data, "SSH DISCONNECT is done\n")); @@ -3606,4 +3607,21 @@ size_t Curl_ssh_version(char *buffer, size_t buflen) return msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION); } +/* The SSH session is associated with the *CONNECTION* but the callback user + * pointer is an easy handle pointer. This function allows us to reassign the + * user pointer to the *CURRENT* (new) easy handle. + */ +static void ssh_attach(struct Curl_easy *data, struct connectdata *conn) +{ + DEBUGASSERT(data); + DEBUGASSERT(conn); + if(conn->handler->protocol & PROTO_FAMILY_SSH) { + struct ssh_conn *sshc = &conn->proto.sshc; + if(sshc->ssh_session) { + /* only re-attach if the session already exists */ + void **abstract = libssh2_session_abstract(sshc->ssh_session); + *abstract = data; + } + } +} #endif /* USE_LIBSSH2 */ diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h index 52e1ee6c201..505b0787c5f 100644 --- a/lib/vssh/ssh.h +++ b/lib/vssh/ssh.h @@ -263,9 +263,12 @@ extern const struct Curl_handler Curl_handler_sftp; CURLcode Curl_ssh_init(void); void Curl_ssh_cleanup(void); size_t Curl_ssh_version(char *buffer, size_t buflen); +void Curl_ssh_attach(struct Curl_easy *data, + struct connectdata *conn); #else /* for non-SSH builds */ #define Curl_ssh_cleanup() +#define Curl_ssh_attach(x,y) #endif #endif /* HEADER_CURL_SSH_H */ diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c index 6020180a5ed..9f3266a24d8 100644 --- a/lib/vssh/wolfssh.c +++ b/lib/vssh/wolfssh.c @@ -91,6 +91,7 @@ const struct Curl_handler Curl_handler_scp = { wscp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION @@ -119,6 +120,7 @@ const struct Curl_handler Curl_handler_sftp = { wsftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ @@ -388,7 +390,7 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done) } sshc->ssh_session = wolfSSH_new(sshc->ctx); - if(sshc->ssh_session == NULL) { + if(!sshc->ssh_session) { failf(data, "No wolfSSH session"); goto error; } @@ -585,7 +587,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) } } - if(data->set.ftp_append) + if(data->set.remote_append) /* Try to open for append, but create if nonexisting */ flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND; else if(data->state.resume_from > 0) @@ -859,9 +861,9 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) result = CURLE_OK; while(name) { char *line = aprintf("%s\n", - data->set.ftp_list_only ? + data->set.list_only ? name->fName : name->lName); - if(line == NULL) { + if(!line) { state(data, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c index 29b08c0e6dc..7f729713d89 100644 --- a/lib/vtls/bearssl.c +++ b/lib/vtls/bearssl.c @@ -300,12 +300,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); -#ifndef CURL_DISABLE_PROXY - const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - const char *hostname = conn->host.name; -#endif + const char * const hostname = SSL_HOST_NAME(); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const bool verifyhost = SSL_CONN_CONFIG(verifyhost); CURLcode ret; @@ -375,7 +370,8 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, void *session; Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, &session, NULL, sockindex)) { + if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, + &session, NULL, sockindex)) { br_ssl_engine_set_session_parameters(&backend->ctx.eng, session); infof(data, "BearSSL: re-using session ID\n"); } @@ -389,14 +385,14 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, * protocols array in `struct ssl_backend_data`. */ -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + backend->protocols[cur++] = ALPN_H2; + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -544,8 +540,8 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, if(protocol) { infof(data, "ALPN, server accepted to use %s\n", protocol); -#ifdef USE_NGHTTP2 - if(!strcmp(protocol, NGHTTP2_PROTO_VERSION_ID)) +#ifdef USE_HTTP2 + if(!strcmp(protocol, ALPN_H2)) conn->negnpn = CURL_HTTP_VERSION_2; else #endif @@ -571,10 +567,13 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, br_ssl_engine_get_session_parameters(&backend->ctx.eng, session); Curl_ssl_sessionid_lock(data); incache = !(Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, &oldsession, NULL, sockindex)); if(incache) Curl_ssl_delsessionid(data, oldsession); - ret = Curl_ssl_addsessionid(data, conn, session, 0, sockindex); + ret = Curl_ssl_addsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, + session, 0, sockindex); Curl_ssl_sessionid_unlock(data); if(ret) { free(session); @@ -855,6 +854,7 @@ const struct Curl_ssl Curl_ssl_bearssl = { Curl_none_cert_status_request, bearssl_connect, bearssl_connect_nonblocking, + Curl_ssl_getsock, bearssl_get_internals, bearssl_close, Curl_none_close_all, diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c index 9b5f649f7d5..ca953769d1b 100644 --- a/lib/vtls/gskit.c +++ b/lib/vtls/gskit.c @@ -101,8 +101,10 @@ struct ssl_backend_data { gsk_handle handle; int iocport; +#ifndef CURL_DISABLE_PROXY int localfd; int remotefd; +#endif }; #define BACKEND connssl->backend @@ -302,8 +304,9 @@ static CURLcode set_callback(struct Curl_easy *data, static CURLcode set_ciphers(struct Curl_easy *data, - gsk_handle h, unsigned int *protoflags) + gsk_handle h, unsigned int *protoflags) { + struct connectdata *conn = data->conn; const char *cipherlist = SSL_CONN_CONFIG(cipher_list); const char *clp; const struct gskit_cipher *ctp; @@ -515,6 +518,7 @@ static void close_async_handshake(struct ssl_connect_data *connssl) static int pipe_ssloverssl(struct connectdata *conn, int sockindex, int directions) { +#ifndef CURL_DISABLE_PROXY struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; fd_set fds_read; @@ -583,6 +587,9 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, } return ret; /* OK */ +#else + return 0; +#endif } @@ -596,6 +603,7 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) ; BACKEND->handle = (gsk_handle) NULL; +#ifndef CURL_DISABLE_PROXY if(BACKEND->localfd >= 0) { close(BACKEND->localfd); BACKEND->localfd = -1; @@ -604,13 +612,14 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, close(BACKEND->remotefd); BACKEND->remotefd = -1; } +#endif } if(BACKEND->iocport >= 0) close_async_handshake(connssl); } -static ssize_t gskit_send(struct connectdata *conn, int sockindex, +static ssize_t gskit_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { struct connectdata *conn = data->conn; @@ -665,6 +674,7 @@ static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf, static CURLcode set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data) { + struct connectdata *conn = data->conn; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); long i = ssl_version; @@ -700,26 +710,28 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gsk_handle envir; CURLcode result; - int rc; const char * const keyringfile = SSL_CONN_CONFIG(CAfile); const char * const keyringpwd = SSL_SET_OPTION(key_passwd); const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert); const long int ssl_version = SSL_CONN_CONFIG(version); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); - const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: - conn->host.name; + const char * const hostname = SSL_HOST_NAME(); const char *sni; unsigned int protoflags = 0; Qso_OverlappedIO_t commarea; +#ifndef CURL_DISABLE_PROXY int sockpair[2]; static const int sobufsize = CURL_MAX_WRITE_SIZE; +#endif /* Create SSL environment, start (preferably asynchronous) handshake. */ BACKEND->handle = (gsk_handle) NULL; BACKEND->iocport = -1; +#ifndef CURL_DISABLE_PROXY BACKEND->localfd = -1; BACKEND->remotefd = -1; +#endif /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system @@ -758,6 +770,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, if(result) return result; +#ifndef CURL_DISABLE_PROXY /* Establish a pipelining socket pair for SSL over SSL. */ if(conn->proxy_ssl[sockindex].use) { if(Curl_socketpair(0, 0, 0, sockpair)) @@ -775,6 +788,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, curlx_nonblock(BACKEND->localfd, TRUE); curlx_nonblock(BACKEND->remotefd, TRUE); } +#endif /* Determine which SSL/TLS version should be enabled. */ sni = hostname; @@ -827,8 +841,13 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, if(!result) result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1); if(!result) +#ifndef CURL_DISABLE_PROXY result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? BACKEND->localfd: conn->sock[sockindex]); +#else + result = set_numeric(data, BACKEND->handle, GSK_FD, + conn->sock[sockindex]); +#endif if(!result) result = set_ciphers(data, BACKEND->handle, &protoflags); if(!protoflags) { @@ -897,10 +916,12 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); +#ifndef CURL_DISABLE_PROXY else if(conn->proxy_ssl[sockindex].use) { /* Cannot pipeline while handshaking synchronously. */ result = CURLE_SSL_CONNECT_ERROR; } +#endif else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle), @@ -1036,8 +1057,7 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, } /* Check pinned public key. */ - ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + ptr = SSL_PINNED_PUB_KEY(); if(!result && ptr) { curl_X509certificate x509; curl_asn1Element *p; @@ -1159,7 +1179,9 @@ static void gskit_close(struct Curl_easy *data, struct connectdata *conn, int sockindex) { close_one(&conn->ssl[sockindex], data, conn, sockindex); +#ifndef CURL_DISABLE_PROXY close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex); +#endif } @@ -1282,7 +1304,9 @@ const struct Curl_ssl Curl_ssl_gskit = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_GSKIT */ diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 3ddee197423..ecde5c44dee 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -35,14 +35,8 @@ #include #include #include - -#ifdef USE_GNUTLS_NETTLE #include -#include #include -#else -#include -#endif #include "urldata.h" #include "sendf.h" @@ -269,7 +263,7 @@ static CURLcode handshake(struct Curl_easy *data, strerr = gnutls_alert_get_name(alert); } - if(strerr == NULL) + if(!strerr) strerr = gnutls_strerror(rc); infof(data, "gnutls_handshake() warning: %s\n", strerr); @@ -283,7 +277,7 @@ static CURLcode handshake(struct Curl_easy *data, strerr = gnutls_alert_get_name(alert); } - if(strerr == NULL) + if(!strerr) strerr = gnutls_strerror(rc); failf(data, "gnutls_handshake() failed: %s", strerr); @@ -314,15 +308,29 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type) #define GNUTLS_SRP "+SRP" static CURLcode -set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data) +set_ssl_version_min_max(struct Curl_easy *data, + const char **prioritylist, + const char *tls13support) { struct connectdata *conn = data->conn; long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); - if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) { + if((ssl_version == CURL_SSLVERSION_DEFAULT) || + (ssl_version == CURL_SSLVERSION_TLSv1)) + ssl_version = CURL_SSLVERSION_TLSv1_0; + if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT; + if(!tls13support) { + /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a + prioritylist involving that since it will make GnuTLS return an en + error back at us */ + if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) || + (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) { + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + } } + switch(ssl_version | ssl_version_max) { case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" @@ -401,6 +409,7 @@ gtls_connect_step1(struct Curl_easy *data, const char *err = NULL; const char * const hostname = SSL_HOST_NAME(); long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult); + const char *tls13support; if(connssl->state == ssl_connection_complete) /* to make us tolerant against being called more than once for the @@ -548,36 +557,34 @@ gtls_connect_step1(struct Curl_easy *data, if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; + /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */ + tls13support = gnutls_check_version("3.6.5"); + /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ switch(SSL_CONN_CONFIG(version)) { - case CURL_SSLVERSION_SSLv3: - prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; - break; + case CURL_SSLVERSION_TLSv1_3: + if(!tls13support) { + failf(data, "This GnuTLS installation does not support TLS 1.3"); + return CURLE_SSL_CONNECT_ERROR; + } + /* FALLTHROUGH */ case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: - prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0" -#ifdef HAS_TLS13 - ":+VERS-TLS1.3" -#endif - ; - break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { - CURLcode result = set_ssl_version_min_max(&prioritylist, data); - if(result != CURLE_OK) - return result; - break; - } + case CURL_SSLVERSION_TLSv1_2: { + CURLcode result = set_ssl_version_min_max(data, &prioritylist, + tls13support); + if(result) + return result; + break; + } case CURL_SSLVERSION_SSLv2: - failf(data, "GnuTLS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv3: default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + failf(data, "GnuTLS does not support SSLv2 or SSLv3"); return CURLE_SSL_CONNECT_ERROR; } @@ -592,7 +599,6 @@ gtls_connect_step1(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; strcpy(prioritysrp, prioritylist); strcpy(prioritysrp + len, ":" GNUTLS_SRP); - rc = gnutls_priority_set_direct(session, prioritysrp, &err); free(prioritysrp); @@ -617,16 +623,16 @@ gtls_connect_step1(struct Curl_easy *data, int cur = 0; gnutls_datum_t protocols[2]; -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; - protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[cur].data = (unsigned char *)ALPN_H2; + protocols[cur].size = ALPN_H2_LENGTH; cur++; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + infof(data, "ALPN, offering %.*s\n", ALPN_H2_LENGTH, ALPN_H2); } #endif @@ -733,6 +739,7 @@ gtls_connect_step1(struct Curl_easy *data, Curl_ssl_sessionid_lock(data); if(!Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, &ssl_sessionid, &ssl_idsize, sockindex)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); @@ -1183,8 +1190,7 @@ gtls_connect_step3(struct Curl_easy *data, infof(data, "\t server certificate activation date OK\n"); } - ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + ptr = SSL_PINNED_PUB_KEY(); if(ptr) { result = pkp_pin_peer_pubkey(data, x509_cert, ptr); if(result != CURLE_OK) { @@ -1248,10 +1254,10 @@ gtls_connect_step3(struct Curl_easy *data, infof(data, "ALPN, server accepted to use %.*s\n", proto.size, proto.data); -#ifdef USE_NGHTTP2 - if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, - NGHTTP2_PROTO_VERSION_ID_LEN)) { +#ifdef USE_HTTP2 + if(proto.size == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, proto.data, + ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -1292,8 +1298,9 @@ gtls_connect_step3(struct Curl_easy *data, gnutls_session_get_data(session, connect_sessionid, &connect_idsize); Curl_ssl_sessionid_lock(data); - incache = !(Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, - sockindex)); + incache = !(Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, + &ssl_sessionid, NULL, sockindex)); if(incache) { /* there was one before in the cache, so instead of risking that the previous one was rejected, we just kill that and store the new */ @@ -1301,8 +1308,10 @@ gtls_connect_step3(struct Curl_easy *data, } /* store this session id */ - result = Curl_ssl_addsessionid(data, conn, connect_sessionid, - connect_idsize, sockindex); + result = Curl_ssl_addsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, + connect_sessionid, connect_idsize, + sockindex); Curl_ssl_sessionid_unlock(data); if(result) { free(connect_sessionid); @@ -1583,39 +1592,14 @@ static size_t gtls_version(char *buffer, size_t size) return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); } -#ifndef USE_GNUTLS_NETTLE -static int gtls_seed(struct Curl_easy *data) -{ - /* we have the "SSL is seeded" boolean static to prevent multiple - time-consuming seedings in vain */ - static bool ssl_seeded = FALSE; - - /* Quickly add a bit of entropy */ - gcry_fast_random_poll(); - - if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || - data->set.str[STRING_SSL_EGDSOCKET]) { - ssl_seeded = TRUE; - } - return 0; -} -#endif - /* data might be NULL! */ static CURLcode gtls_random(struct Curl_easy *data, unsigned char *entropy, size_t length) { -#if defined(USE_GNUTLS_NETTLE) int rc; (void)data; rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); return rc?CURLE_FAILED_INIT:CURLE_OK; -#elif defined(USE_GNUTLS) - if(data) - gtls_seed(data); /* Initiate the seed if not already done */ - gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); -#endif - return CURLE_OK; } static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */ @@ -1623,18 +1607,10 @@ static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */ unsigned char *sha256sum, /* output */ size_t sha256len) { -#if defined(USE_GNUTLS_NETTLE) struct sha256_ctx SHA256pw; sha256_init(&SHA256pw); sha256_update(&SHA256pw, (unsigned int)tmplen, tmp); sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum); -#elif defined(USE_GNUTLS) - gcry_md_hd_t SHA256pw; - gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0); - gcry_md_write(SHA256pw, tmp, tmplen); - memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len); - gcry_md_close(SHA256pw); -#endif return CURLE_OK; } @@ -1671,6 +1647,7 @@ const struct Curl_ssl Curl_ssl_gnutls = { gtls_cert_status_request, /* cert_status_request */ gtls_connect, /* connect */ gtls_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ gtls_get_internals, /* get_internals */ gtls_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -1679,7 +1656,9 @@ const struct Curl_ssl Curl_ssl_gnutls = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - gtls_sha256sum /* sha256sum */ + gtls_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_GNUTLS */ diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index fc3a948d1e6..3a0be0f04b4 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -251,22 +251,16 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, const char * const ssl_capath = SSL_CONN_CONFIG(CApath); char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); int ret = -1; char errorbuf[128]; errorbuf[0] = 0; - /* mbedTLS only supports SSLv3 and TLSv1 */ - if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { - failf(data, "mbedTLS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; + if((SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) || + (SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)) { + failf(data, "Not supported SSL version"); + return CURLE_NOT_BUILT_IN; } #ifdef THREADING_SUPPORT @@ -414,13 +408,6 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; - case CURL_SSLVERSION_SSLv3: - mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_0); - mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_0); - infof(data, "mbedTLS: Set SSL version to SSLv3\n"); - break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: @@ -463,7 +450,9 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, void *old_session = NULL; Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, &old_session, NULL, sockindex)) { + if(!Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, + &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&backend->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(data); @@ -495,7 +484,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, if(conn->bits.tls_enable_alpn) { const char **p = &backend->protocols[0]; #ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2) + if(data->state.httpwant >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; @@ -547,14 +536,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; const mbedtls_x509_crt *peercert; -#ifndef CURL_DISABLE_PROXY - const char * const pinnedpubkey = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; -#else - const char * const pinnedpubkey = - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; -#endif + const char * const pinnedpubkey = SSL_PINNED_PUB_KEY(); conn->recv[sockindex] = mbed_recv; conn->send[sockindex] = mbed_send; @@ -724,6 +706,7 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn, int ret; mbedtls_ssl_session *our_ssl_sessionid; void *old_ssl_sessionid = NULL; + bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE; our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); if(!our_ssl_sessionid) @@ -742,11 +725,12 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn, /* If there's already a matching session in the cache, delete it */ Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex)) + if(!Curl_ssl_getsessionid(data, conn, isproxy, &old_ssl_sessionid, NULL, + sockindex)) Curl_ssl_delsessionid(data, old_ssl_sessionid); - retcode = Curl_ssl_addsessionid(data, conn, - our_ssl_sessionid, 0, sockindex); + retcode = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, + 0, sockindex); Curl_ssl_sessionid_unlock(data); if(retcode) { mbedtls_ssl_session_free(our_ssl_sessionid); @@ -1100,6 +1084,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = { Curl_none_cert_status_request, /* cert_status_request */ mbedtls_connect, /* connect */ mbedtls_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ mbedtls_get_internals, /* get_internals */ mbedtls_close, /* close_one */ mbedtls_close_all, /* close_all */ @@ -1108,7 +1093,9 @@ const struct Curl_ssl Curl_ssl_mbedtls = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - mbedtls_sha256sum /* sha256sum */ + mbedtls_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_MBEDTLS */ diff --git a/lib/vtls/mesalink.c b/lib/vtls/mesalink.c index b6d1005ec1b..bf8600d3230 100644 --- a/lib/vtls/mesalink.c +++ b/lib/vtls/mesalink.c @@ -98,8 +98,7 @@ mesalink_connect_step1(struct Curl_easy *data, #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif - const char *const hostname = - SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + const char * const hostname = SSL_HOST_NAME(); size_t hostname_len = strlen(hostname); SSL_METHOD *req_method = NULL; @@ -261,7 +260,9 @@ mesalink_connect_step1(struct Curl_easy *data, void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) { + if(!Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, + &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(data); @@ -345,13 +346,14 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex) bool incache; SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; + bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE; our_ssl_sessionid = SSL_get_session(BACKEND->handle); Curl_ssl_sessionid_lock(data); incache = - !(Curl_ssl_getsessionid(data, conn, - &old_ssl_sessionid, NULL, sockindex)); + !(Curl_ssl_getsessionid(data, conn, isproxy, &old_ssl_sessionid, NULL, + sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); @@ -361,8 +363,9 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex) } if(!incache) { - result = Curl_ssl_addsessionid( - data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex); + result = + Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, 0, + sockindex); if(result) { Curl_ssl_sessionid_unlock(data); failf(data, "failed to store ssl session"); @@ -654,6 +657,7 @@ const struct Curl_ssl Curl_ssl_mesalink = { Curl_none_cert_status_request, /* cert_status_request */ mesalink_connect, /* connect */ mesalink_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ mesalink_get_internals, /* get_internals */ mesalink_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -662,7 +666,9 @@ const struct Curl_ssl Curl_ssl_mesalink = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index e5ab71cdf6a..1582b1e580a 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -139,9 +139,15 @@ static const struct cipher_s cipherlist[] = { {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, + {"dhe_rsa_3des_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, + {"dhe_dss_3des_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA}, + {"dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA}, + {"dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA}, /* TLS 1.0: Exportable 56-bit Cipher Suites. */ {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, + /* Ephemeral DH with RC4 bulk encryption */ + {"dhe_dss_rc4_128_sha", TLS_DHE_DSS_WITH_RC4_128_SHA}, /* AES ciphers. */ {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, @@ -219,6 +225,25 @@ static const struct cipher_s cipherlist[] = { {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384}, {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256}, #endif +#ifdef TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 + /* AES CBC cipher suites in RFC 5246. Introduced in NSS release 3.20 */ + {"dhe_dss_aes_128_sha_256", TLS_DHE_DSS_WITH_AES_128_CBC_SHA256}, + {"dhe_dss_aes_256_sha_256", TLS_DHE_DSS_WITH_AES_256_CBC_SHA256}, +#endif +#ifdef TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + /* Camellia cipher suites in RFC 4132/5932. + Introduced in NSS release 3.12 */ + {"dhe_rsa_camellia_128_sha", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA}, + {"dhe_dss_camellia_128_sha", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA}, + {"dhe_rsa_camellia_256_sha", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA}, + {"dhe_dss_camellia_256_sha", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA}, + {"rsa_camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA}, + {"rsa_camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA}, +#endif +#ifdef TLS_RSA_WITH_SEED_CBC_SHA + /* SEED cipher suite in RFC 4162. Introduced in NSS release 3.12.3 */ + {"rsa_seed_sha", TLS_RSA_WITH_SEED_CBC_SHA}, +#endif }; #if defined(WIN32) @@ -312,7 +337,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, while((*cipher) && (ISSPACE(*cipher))) ++cipher; - cipher_list = strchr(cipher, ','); + cipher_list = strpbrk(cipher, ":, "); if(cipher_list) { *cipher_list++ = '\0'; } @@ -380,7 +405,7 @@ static int is_file(const char *filename) { struct_stat st; - if(filename == NULL) + if(!filename) return 0; if(stat(filename, &st) == 0) @@ -542,7 +567,6 @@ static CURLcode nss_load_cert(struct ssl_connect_data *ssl, if(!result && !cacert) { /* we have successfully loaded a client certificate */ - CERTCertificate *cert; char *nickname = NULL; char *n = strrchr(filename, '/'); if(n) @@ -554,7 +578,7 @@ static CURLcode nss_load_cert(struct ssl_connect_data *ssl, * . */ nickname = aprintf("PEM Token #1:%s", n); if(nickname) { - cert = PK11_FindCertFromNickname(nickname, NULL); + CERTCertificate *cert = PK11_FindCertFromNickname(nickname, NULL); if(cert) CERT_DestroyCertificate(cert); @@ -846,8 +870,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) } #ifdef USE_NGHTTP2 - if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { + if(buflen == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -957,7 +981,6 @@ static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock) CERTCertificate *cert2; CERTCertificate *cert3; PRTime now; - int i; if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) == SECSuccess && channel.length == sizeof(channel) && @@ -978,8 +1001,8 @@ static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock) } else { /* Count certificates in chain. */ + int i = 1; now = PR_Now(); - i = 1; if(!cert->isRoot) { cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); while(cert2) { @@ -1425,7 +1448,7 @@ static CURLcode nss_setup(struct Curl_easy *data) static int nss_init(void) { /* curl_global_init() is not thread-safe so this test is ok */ - if(nss_initlock == NULL) { + if(!nss_initlock) { PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); nss_initlock = PR_NewLock(); nss_crllock = PR_NewLock(); @@ -1701,8 +1724,7 @@ static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version) return CURLE_OK; case CURL_SSLVERSION_SSLv3: - *nssver = SSL_LIBRARY_VERSION_3_0; - return CURLE_OK; + return CURLE_NOT_BUILT_IN; case CURL_SSLVERSION_TLSv1_0: *nssver = SSL_LIBRARY_VERSION_TLS_1_0; @@ -1782,12 +1804,11 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, struct Curl_easy *data, CURLcode curlerr) { - PRErrorCode err = 0; struct ssl_backend_data *backend = connssl->backend; if(is_nss_error(curlerr)) { /* read NSPR error code */ - err = PR_GetError(); + PRErrorCode err = PR_GetError(); if(is_cc_error(err)) curlerr = CURLE_SSL_CERTPROBLEM; @@ -1809,7 +1830,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, struct Curl_easy *data, bool blocking) { - static PRSocketOptionData sock_opt; + PRSocketOptionData sock_opt; struct ssl_backend_data *backend = connssl->backend; sock_opt.option = PR_SockOpt_Nonblocking; sock_opt.value.non_blocking = !blocking; @@ -2082,16 +2103,15 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, int cur = 0; unsigned char protocols[128]; -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; - memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN); - cur += NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[cur++] = ALPN_H2_LENGTH; + memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; } #endif protocols[cur++] = ALPN_HTTP_1_1_LENGTH; @@ -2435,6 +2455,7 @@ const struct Curl_ssl Curl_ssl_nss = { nss_cert_status_request, /* cert_status_request */ nss_connect, /* connect */ nss_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ nss_get_internals, /* get_internals */ nss_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -2444,7 +2465,9 @@ const struct Curl_ssl Curl_ssl_nss = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ nss_false_start, /* false_start */ - nss_sha256sum /* sha256sum */ + nss_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_NSS */ diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 784d9f70e0f..ebd7abc3b4a 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -122,12 +122,6 @@ #define HAVE_ERR_REMOVE_THREAD_STATE 1 #endif -#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \ - OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0+ has no SSLv2 */ -#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */ -#define OPENSSL_NO_SSL2 -#endif - #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \ !(defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) @@ -234,6 +228,8 @@ #endif struct ssl_backend_data { + struct Curl_easy *logger; /* transfer handle to pass trace logs to, only + using sockindex 0 */ /* these ones requires specific SSL-types */ SSL_CTX* ctx; SSL* handle; @@ -244,6 +240,10 @@ struct ssl_backend_data { #endif }; +static void ossl_associate_connection(struct Curl_easy *data, + struct connectdata *conn, + int sockindex); + /* * Number of bytes to read from the random number seed file. This must be * a finite value (because some entropy "files" like /dev/urandom have @@ -391,12 +391,23 @@ static int ossl_get_ssl_conn_index(void) */ static int ossl_get_ssl_sockindex_index(void) { - static int ssl_ex_data_sockindex_index = -1; - if(ssl_ex_data_sockindex_index < 0) { - ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, - NULL); + static int sockindex_index = -1; + if(sockindex_index < 0) { + sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + } + return sockindex_index; +} + +/* Return an extra data index for proxy boolean. + * This index can be used with SSL_get_ex_data() and SSL_set_ex_data(). + */ +static int ossl_get_proxy_index(void) +{ + static int proxy_index = -1; + if(proxy_index < 0) { + proxy_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); } - return ssl_ex_data_sockindex_index; + return proxy_index; } static int passwd_callback(char *buf, int num, int encrypting, @@ -587,11 +598,16 @@ static bool is_pkcs11_uri(const char *string) static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine); static int -SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type, - const char *key_passwd) +SSL_CTX_use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob, + int type, const char *key_passwd) { int ret = 0; X509 *x = NULL; + /* the typecast of blob->len is fine since it is guaranteed to never be + larger than CURL_MAX_INPUT_LENGTH */ + BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len)); + if(!in) + return CURLE_OUT_OF_MEMORY; if(type == SSL_FILETYPE_ASN1) { /* j = ERR_R_ASN1_LIB; */ @@ -607,7 +623,7 @@ SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type, goto end; } - if(x == NULL) { + if(!x) { ret = 0; goto end; } @@ -615,15 +631,19 @@ SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type, ret = SSL_CTX_use_certificate(ctx, x); end: X509_free(x); + BIO_free(in); return ret; } static int -SSL_CTX_use_PrivateKey_bio(SSL_CTX *ctx, BIO* in, int type, - const char *key_passwd) +SSL_CTX_use_PrivateKey_blob(SSL_CTX *ctx, const struct curl_blob *blob, + int type, const char *key_passwd) { int ret = 0; EVP_PKEY *pkey = NULL; + BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len)); + if(!in) + return CURLE_OUT_OF_MEMORY; if(type == SSL_FILETYPE_PEM) pkey = PEM_read_bio_PrivateKey(in, NULL, passwd_callback, @@ -634,19 +654,20 @@ SSL_CTX_use_PrivateKey_bio(SSL_CTX *ctx, BIO* in, int type, ret = 0; goto end; } - if(pkey == NULL) { + if(!pkey) { ret = 0; goto end; } ret = SSL_CTX_use_PrivateKey(ctx, pkey); EVP_PKEY_free(pkey); end: + BIO_free(in); return ret; } static int -SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in, - const char *key_passwd) +SSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, + const char *key_passwd) { /* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */ #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \ @@ -655,13 +676,16 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in, int ret = 0; X509 *x = NULL; void *passwd_callback_userdata = (void *)key_passwd; + BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len)); + if(!in) + return CURLE_OUT_OF_MEMORY; ERR_clear_error(); x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback, (void *)key_passwd); - if(x == NULL) { + if(!x) { ret = 0; goto end; } @@ -669,7 +693,7 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in, ret = SSL_CTX_use_certificate(ctx, x); if(ERR_peek_error() != 0) - ret = 0; + ret = 0; if(ret) { X509 *ca; @@ -701,10 +725,11 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in, end: X509_free(x); + BIO_free(in); return ret; #else (void)ctx; /* unused */ - (void)in; /* unused */ + (void)blob; /* unused */ (void)key_passwd; /* unused */ return 0; #endif @@ -714,10 +739,10 @@ static int cert_stuff(struct Curl_easy *data, SSL_CTX* ctx, char *cert_file, - BIO *cert_bio, + const struct curl_blob *cert_blob, const char *cert_type, char *key_file, - BIO* key_bio, + const struct curl_blob *key_blob, const char *key_type, char *key_passwd) { @@ -726,7 +751,7 @@ int cert_stuff(struct Curl_easy *data, int file_type = do_file_type(cert_type); - if(cert_file || cert_bio || (file_type == SSL_FILETYPE_ENGINE)) { + if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE)) { SSL *ssl; X509 *x509; int cert_done = 0; @@ -743,9 +768,9 @@ int cert_stuff(struct Curl_easy *data, switch(file_type) { case SSL_FILETYPE_PEM: /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ - cert_use_result = cert_bio ? - SSL_CTX_use_certificate_chain_bio(ctx, cert_bio, key_passwd) : - SSL_CTX_use_certificate_chain_file(ctx, cert_file); + cert_use_result = cert_blob ? + SSL_CTX_use_certificate_chain_blob(ctx, cert_blob, key_passwd) : + SSL_CTX_use_certificate_chain_file(ctx, cert_file); if(cert_use_result != 1) { failf(data, "could not load PEM client certificate, " OSSL_PACKAGE @@ -762,10 +787,10 @@ int cert_stuff(struct Curl_easy *data, we use the case above for PEM so this can only be performed with ASN1 files. */ - cert_use_result = cert_bio ? - SSL_CTX_use_certificate_bio(ctx, cert_bio, - file_type, key_passwd) : - SSL_CTX_use_certificate_file(ctx, cert_file, file_type); + cert_use_result = cert_blob ? + SSL_CTX_use_certificate_blob(ctx, cert_blob, + file_type, key_passwd) : + SSL_CTX_use_certificate_file(ctx, cert_file, file_type); if(cert_use_result != 1) { failf(data, "could not load ASN1 client certificate, " OSSL_PACKAGE @@ -842,13 +867,24 @@ int cert_stuff(struct Curl_easy *data, case SSL_FILETYPE_PKCS12: { - BIO *fp = NULL; + BIO *cert_bio = NULL; PKCS12 *p12 = NULL; EVP_PKEY *pri; STACK_OF(X509) *ca = NULL; - if(!cert_bio) { - fp = BIO_new(BIO_s_file()); - if(fp == NULL) { + if(cert_blob) { + cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len)); + if(!cert_bio) { + failf(data, + "BIO_new_mem_buf NULL, " OSSL_PACKAGE + " error %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); + return 0; + } + } + else { + cert_bio = BIO_new(BIO_s_file()); + if(!cert_bio) { failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s", @@ -857,20 +893,19 @@ int cert_stuff(struct Curl_easy *data, return 0; } - if(BIO_read_filename(fp, cert_file) <= 0) { + if(BIO_read_filename(cert_bio, cert_file) <= 0) { failf(data, "could not open PKCS12 file '%s'", cert_file); - BIO_free(fp); + BIO_free(cert_bio); return 0; } } - p12 = d2i_PKCS12_bio(cert_bio ? cert_bio : fp, NULL); - if(fp) - BIO_free(fp); + p12 = d2i_PKCS12_bio(cert_bio, NULL); + BIO_free(cert_bio); if(!p12) { failf(data, "error reading PKCS12 file '%s'", - cert_bio ? "(memory blob)" : cert_file); + cert_blob ? "(memory blob)" : cert_file); return 0; } @@ -951,9 +986,9 @@ int cert_stuff(struct Curl_easy *data, return 0; } - if((!key_file) && (!key_bio)) { + if((!key_file) && (!key_blob)) { key_file = cert_file; - key_bio = cert_bio; + key_blob = cert_blob; } else file_type = do_file_type(key_type); @@ -964,8 +999,8 @@ int cert_stuff(struct Curl_easy *data, break; /* FALLTHROUGH */ case SSL_FILETYPE_ASN1: - cert_use_result = key_bio ? - SSL_CTX_use_PrivateKey_bio(ctx, key_bio, file_type, key_passwd) : + cert_use_result = key_blob ? + SSL_CTX_use_PrivateKey_blob(ctx, key_blob, file_type, key_passwd) : SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type); if(cert_use_result != 1) { failf(data, "unable to set private key file: '%s' type %s", @@ -1172,7 +1207,7 @@ static int ossl_init(void) /* Initialize the extra data indexes */ if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 || - ossl_get_ssl_sockindex_index() < 0) + ossl_get_ssl_sockindex_index() < 0 || ossl_get_proxy_index() < 0) return 0; return 1; @@ -1356,10 +1391,16 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data) return list; } -static void ossl_closeone(struct ssl_connect_data *connssl) +#define set_logger(conn, data) \ + conn->ssl[0].backend->logger = data + +static void ossl_closeone(struct Curl_easy *data, + struct connectdata *conn, + struct ssl_connect_data *connssl) { struct ssl_backend_data *backend = connssl->backend; if(backend->handle) { + set_logger(conn, data); (void)SSL_shutdown(backend->handle); SSL_set_connect_state(backend->handle); @@ -1378,10 +1419,9 @@ static void ossl_closeone(struct ssl_connect_data *connssl) static void ossl_close(struct Curl_easy *data, struct connectdata *conn, int sockindex) { - (void) data; - ossl_closeone(&conn->ssl[sockindex]); + ossl_closeone(data, conn, &conn->ssl[sockindex]); #ifndef CURL_DISABLE_PROXY - ossl_closeone(&conn->proxy_ssl[sockindex]); + ossl_closeone(data, conn, &conn->proxy_ssl[sockindex]); #endif } @@ -2055,25 +2095,24 @@ static const char *tls_rt_type(int type) } } - /* * Our callback from the SSL/TLS layers. */ -static void ssl_tls_trace(int direction, int ssl_ver, int content_type, - const void *buf, size_t len, SSL *ssl, - void *userp) +static void ossl_trace(int direction, int ssl_ver, int content_type, + const void *buf, size_t len, SSL *ssl, + void *userp) { - struct Curl_easy *data; char unknown[32]; const char *verstr = NULL; struct connectdata *conn = userp; + struct ssl_connect_data *connssl = &conn->ssl[0]; + struct ssl_backend_data *backend = connssl->backend; + struct Curl_easy *data = backend->logger; - if(!conn || !conn->data || !conn->data->set.fdebug || + if(!conn || !data || !data->set.fdebug || (direction != 0 && direction != 1)) return; - data = conn->data; - switch(ssl_ver) { #ifdef SSL2_VERSION /* removed in recent versions */ case SSL2_VERSION: @@ -2221,12 +2260,10 @@ select_next_proto_cb(SSL *ssl, struct connectdata *conn = data->conn; (void)ssl; -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 && - !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN)) { - infof(data, "NPN, negotiated HTTP2 (%s)\n", - NGHTTP2_PROTO_VERSION_ID); +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2 && + !select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) { + infof(data, "NPN, negotiated HTTP2 (%s)\n", ALPN_H2); conn->negnpn = CURL_HTTP_VERSION_2; return SSL_TLSEXT_ERR_OK; } @@ -2248,35 +2285,6 @@ select_next_proto_cb(SSL *ssl, } #endif /* HAS_NPN */ -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static const char * -get_ssl_version_txt(SSL *ssl) -{ - if(!ssl) - return ""; - - switch(SSL_version(ssl)) { -#ifdef TLS1_3_VERSION - case TLS1_3_VERSION: - return "TLSv1.3"; -#endif -#if OPENSSL_VERSION_NUMBER >= 0x1000100FL - case TLS1_2_VERSION: - return "TLSv1.2"; - case TLS1_1_VERSION: - return "TLSv1.1"; -#endif - case TLS1_VERSION: - return "TLSv1.0"; - case SSL3_VERSION: - return "SSLv3"; - case SSL2_VERSION: - return "SSLv2"; - } - return "unknown"; -} -#endif - #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ static CURLcode set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) @@ -2455,8 +2463,10 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) int data_idx = ossl_get_ssl_data_index(); int connectdata_idx = ossl_get_ssl_conn_index(); int sockindex_idx = ossl_get_ssl_sockindex_index(); + int proxy_idx = ossl_get_proxy_index(); + bool isproxy; - if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0) + if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0 || proxy_idx < 0) return 0; conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx); @@ -2469,13 +2479,18 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx); sockindex = (int)(sockindex_ptr - conn->sock); + isproxy = SSL_get_ex_data(ssl, proxy_idx) ? TRUE : FALSE; + if(SSL_SET_OPTION(primary.sessionid)) { bool incache; void *old_ssl_sessionid = NULL; Curl_ssl_sessionid_lock(data); - incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, - sockindex)); + if(isproxy) + incache = FALSE; + else + incache = !(Curl_ssl_getsessionid(data, conn, isproxy, + &old_ssl_sessionid, NULL, sockindex)); if(incache) { if(old_ssl_sessionid != ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); @@ -2485,8 +2500,8 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) } if(!incache) { - if(!Curl_ssl_addsessionid(data, conn, ssl_sessionid, - 0 /* unknown size */, sockindex)) { + if(!Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid, + 0 /* unknown size */, sockindex)) { /* the session has been put into the session cache */ res = 1; } @@ -2499,6 +2514,67 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) return res; } +static CURLcode load_cacert_from_memory(SSL_CTX *ctx, + const struct curl_blob *ca_info_blob) +{ + /* these need freed at the end */ + BIO *cbio = NULL; + STACK_OF(X509_INFO) *inf = NULL; + + /* everything else is just a reference */ + int i, count = 0; + X509_STORE *cts = NULL; + X509_INFO *itmp = NULL; + + if(ca_info_blob->len > (size_t)INT_MAX) + return CURLE_SSL_CACERT_BADFILE; + + cts = SSL_CTX_get_cert_store(ctx); + if(!cts) + return CURLE_OUT_OF_MEMORY; + + cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len); + if(!cbio) + return CURLE_OUT_OF_MEMORY; + + inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL); + if(!inf) { + BIO_free(cbio); + return CURLE_SSL_CACERT_BADFILE; + } + + /* add each entry from PEM file to x509_store */ + for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) { + itmp = sk_X509_INFO_value(inf, i); + if(itmp->x509) { + if(X509_STORE_add_cert(cts, itmp->x509)) { + ++count; + } + else { + /* set count to 0 to return an error */ + count = 0; + break; + } + } + if(itmp->crl) { + if(X509_STORE_add_crl(cts, itmp->crl)) { + ++count; + } + else { + /* set count to 0 to return an error */ + count = 0; + break; + } + } + } + + sk_X509_INFO_pop_free(inf, X509_INFO_free); + BIO_free(cbio); + + /* if we didn't end up importing anything, treat that as an error */ + return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE); +} + static CURLcode ossl_connect_step1(struct Curl_easy *data, struct connectdata *conn, int sockindex) { @@ -2509,6 +2585,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ctx_option_t ctx_options = 0; + void *ssl_sessionid = NULL; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME bool sni; @@ -2526,8 +2603,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile)); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); @@ -2562,31 +2642,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, use_sni(TRUE); break; case CURL_SSLVERSION_SSLv2: -#ifdef OPENSSL_NO_SSL2 - failf(data, OSSL_PACKAGE " was built without SSLv2 support"); + failf(data, "No SSLv2 support"); return CURLE_NOT_BUILT_IN; -#else -#ifdef USE_OPENSSL_SRP - if(ssl_authtype == CURL_TLSAUTH_SRP) - return CURLE_SSL_CONNECT_ERROR; -#endif - req_method = SSLv2_client_method(); - use_sni(FALSE); - break; -#endif case CURL_SSLVERSION_SSLv3: -#ifdef OPENSSL_NO_SSL3_METHOD - failf(data, OSSL_PACKAGE " was built without SSLv3 support"); + failf(data, "No SSLv3 support"); return CURLE_NOT_BUILT_IN; -#else -#ifdef USE_OPENSSL_SRP - if(ssl_authtype == CURL_TLSAUTH_SRP) - return CURLE_SSL_CONNECT_ERROR; -#endif - req_method = SSLv3_client_method(); - use_sni(FALSE); - break; -#endif default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -2609,8 +2669,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #ifdef SSL_CTRL_SET_MSG_CALLBACK if(data->set.fdebug && data->set.verbose) { /* the SSL trace callback is only used for verbose logging */ - SSL_CTX_set_msg_callback(backend->ctx, ssl_tls_trace); + SSL_CTX_set_msg_callback(backend->ctx, ossl_trace); SSL_CTX_set_msg_callback_arg(backend->ctx, conn); + set_logger(conn, data); } #endif @@ -2673,41 +2734,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif switch(ssl_version) { - /* "--sslv2" option means SSLv2 only, disable all others */ case CURL_SSLVERSION_SSLv2: -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - SSL_CTX_set_min_proto_version(backend->ctx, SSL2_VERSION); - SSL_CTX_set_max_proto_version(backend->ctx, SSL2_VERSION); -#else - ctx_options |= SSL_OP_NO_SSLv3; - ctx_options |= SSL_OP_NO_TLSv1; -# if OPENSSL_VERSION_NUMBER >= 0x1000100FL - ctx_options |= SSL_OP_NO_TLSv1_1; - ctx_options |= SSL_OP_NO_TLSv1_2; -# ifdef TLS1_3_VERSION - ctx_options |= SSL_OP_NO_TLSv1_3; -# endif -# endif -#endif - break; - - /* "--sslv3" option means SSLv3 only, disable all others */ case CURL_SSLVERSION_SSLv3: -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ - SSL_CTX_set_min_proto_version(backend->ctx, SSL3_VERSION); - SSL_CTX_set_max_proto_version(backend->ctx, SSL3_VERSION); -#else - ctx_options |= SSL_OP_NO_SSLv2; - ctx_options |= SSL_OP_NO_TLSv1; -# if OPENSSL_VERSION_NUMBER >= 0x1000100FL - ctx_options |= SSL_OP_NO_TLSv1_1; - ctx_options |= SSL_OP_NO_TLSv1_2; -# ifdef TLS1_3_VERSION - ctx_options |= SSL_OP_NO_TLSv1_3; -# endif -# endif -#endif - break; + return CURLE_NOT_BUILT_IN; /* "--tlsv" options mean TLS >= version */ case CURL_SSLVERSION_DEFAULT: @@ -2748,18 +2777,17 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, int cur = 0; unsigned char protocols[128]; -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) #endif ) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; + protocols[cur++] = ALPN_H2_LENGTH; - memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN); - cur += NGHTTP2_PROTO_VERSION_ID_LEN; - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -2771,37 +2799,20 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, /* expects length prefixed preference ordered list of protocols in wire * format */ - SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur); + if(SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur)) { + failf(data, "Error setting ALPN"); + return CURLE_SSL_CONNECT_ERROR; + } } #endif if(ssl_cert || ssl_cert_blob || ssl_cert_type) { - BIO *ssl_cert_bio = NULL; - BIO *ssl_key_bio = NULL; - if(ssl_cert_blob) { - /* the typecast of blob->len is fine since it is guaranteed to never be - larger than CURL_MAX_INPUT_LENGTH */ - ssl_cert_bio = BIO_new_mem_buf(ssl_cert_blob->data, - (int)ssl_cert_blob->len); - if(!ssl_cert_bio) - result = CURLE_OUT_OF_MEMORY; - } - if(!result && SSL_SET_OPTION(key_blob)) { - ssl_key_bio = BIO_new_mem_buf(SSL_SET_OPTION(key_blob)->data, - (int)SSL_SET_OPTION(key_blob)->len); - if(!ssl_key_bio) - result = CURLE_OUT_OF_MEMORY; - } if(!result && !cert_stuff(data, backend->ctx, - ssl_cert, ssl_cert_bio, ssl_cert_type, - SSL_SET_OPTION(key), ssl_key_bio, + ssl_cert, ssl_cert_blob, ssl_cert_type, + SSL_SET_OPTION(key), SSL_SET_OPTION(key_blob), SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd))) result = CURLE_SSL_CERTPROBLEM; - if(ssl_cert_bio) - BIO_free(ssl_cert_bio); - if(ssl_key_bio) - BIO_free(ssl_key_bio); if(result) /* failf() is already done in cert_stuff() */ return result; @@ -2882,8 +2893,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) && (SSL_SET_OPTION(native_ca_store))) { X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx); - HCERTSTORE hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, - TEXT("ROOT")); + HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT")); if(hStore) { PCCERT_CONTEXT pContext = NULL; @@ -3020,6 +3030,19 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } #endif + if(ca_info_blob) { + result = load_cacert_from_memory(backend->ctx, ca_info_blob); + if(result) { + if(result == CURLE_OUT_OF_MEMORY || + (verifypeer && !imported_native_ca)) { + failf(data, "error importing CA certificate blob"); + return result; + } + /* Only warning if no certificate verification is required. */ + infof(data, "error importing CA certificate blob, continuing anyway\n"); + } + } + #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ { @@ -3076,7 +3099,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif #ifdef CURL_CA_FALLBACK - if(verifypeer && !ssl_cafile && !ssl_capath && !imported_native_ca) { + if(verifypeer && + !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) { /* verifying the peer without any CA certificates won't work so use openssl's built in default as fallback */ SSL_CTX_set_default_verify_paths(backend->ctx); @@ -3206,36 +3230,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } #endif - /* Check if there's a cached ID we can/should use here! */ - if(SSL_SET_OPTION(primary.sessionid)) { - void *ssl_sessionid = NULL; - int data_idx = ossl_get_ssl_data_index(); - int connectdata_idx = ossl_get_ssl_conn_index(); - int sockindex_idx = ossl_get_ssl_sockindex_index(); + ossl_associate_connection(data, conn, sockindex); - if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0) { - /* Store the data needed for the "new session" callback. - * The sockindex is stored as a pointer to an array element. */ - SSL_set_ex_data(backend->handle, data_idx, data); - SSL_set_ex_data(backend->handle, connectdata_idx, conn); - SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex); - } - - Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) { - /* we got a session id, use it! */ - if(!SSL_set_session(backend->handle, ssl_sessionid)) { - Curl_ssl_sessionid_unlock(data); - failf(data, "SSL: SSL_set_session failed: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - return CURLE_SSL_CONNECT_ERROR; - } - /* Informational message */ - infof(data, "SSL re-using session ID\n"); + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, + &ssl_sessionid, NULL, sockindex)) { + /* we got a session id, use it! */ + if(!SSL_set_session(backend->handle, ssl_sessionid)) { + Curl_ssl_sessionid_unlock(data); + failf(data, "SSL: SSL_set_session failed: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return CURLE_SSL_CONNECT_ERROR; } - Curl_ssl_sessionid_unlock(data); + /* Informational message */ + infof(data, "SSL re-using session ID\n"); } + Curl_ssl_sessionid_unlock(data); #ifndef CURL_DISABLE_PROXY if(conn->proxy_ssl[sockindex].use) { @@ -3340,6 +3351,19 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, error_buffer */ strcpy(error_buffer, "SSL certificate verification failed"); } +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL)) + /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on + OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */ + else if((lib == ERR_LIB_SSL) && + (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) { + /* If client certificate is required, communicate the + error to client */ + result = CURLE_SSL_CLIENTCERT; + ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); + } +#endif else { result = CURLE_SSL_CONNECT_ERROR; ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); @@ -3353,11 +3377,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { const char * const hostname = SSL_HOST_NAME(); -#ifndef CURL_DISABLE_PROXY - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const long int port = conn->remote_port; -#endif + const long int port = SSL_HOST_PORT(); char extramsg[80]=""; int sockerr = SOCKERRNO; if(sockerr && detail == SSL_ERROR_SYSCALL) @@ -3380,7 +3400,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, /* Informational message */ infof(data, "SSL connection using %s / %s\n", - get_ssl_version_txt(backend->handle), + SSL_get_version(backend->handle), SSL_get_cipher(backend->handle)); #ifdef HAS_ALPN @@ -3391,12 +3411,12 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, const unsigned char *neg_protocol; unsigned int len; SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len); - if(len != 0) { + if(len) { infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); -#ifdef USE_NGHTTP2 - if(len == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) { +#ifdef USE_HTTP2 + if(len == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, neg_protocol, len)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -3515,6 +3535,12 @@ typedef size_t numcert_t; typedef int numcert_t; #endif +#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) +#define OSSL3_CONST const +#else +#define OSSL3_CONST +#endif + static CURLcode get_cert_chain(struct Curl_easy *data, struct ssl_connect_data *connssl) { @@ -3622,7 +3648,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data, switch(pktype) { case EVP_PKEY_RSA: { - RSA *rsa; + OSSL3_CONST RSA *rsa; #ifdef HAVE_OPAQUE_EVP_PKEY rsa = EVP_PKEY_get0_RSA(pubkey); #else @@ -3652,7 +3678,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data, case EVP_PKEY_DSA: { #ifndef OPENSSL_NO_DSA - DSA *dsa; + OSSL3_CONST DSA *dsa; #ifdef HAVE_OPAQUE_EVP_PKEY dsa = EVP_PKEY_get0_DSA(pubkey); #else @@ -3684,7 +3710,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data, } case EVP_PKEY_DH: { - DH *dh; + OSSL3_CONST DH *dh; #ifdef HAVE_OPAQUE_EVP_PKEY dh = EVP_PKEY_get0_DH(pubkey); #else @@ -3877,7 +3903,7 @@ static CURLcode servercert(struct Curl_easy *data, (int)SSL_SET_OPTION(issuercert_blob)->len); else { fp = BIO_new(BIO_s_file()); - if(fp == NULL) { + if(!fp) { failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s", @@ -3964,8 +3990,7 @@ static CURLcode servercert(struct Curl_easy *data, /* when not strict, we don't bother about the verify cert problems */ result = CURLE_OK; - ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + ptr = SSL_PINNED_PUB_KEY(); if(!result && ptr) { result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr); if(result) @@ -4176,6 +4201,7 @@ static ssize_t ossl_send(struct Curl_easy *data, ERR_clear_error(); memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; + set_logger(conn, data); rc = SSL_write(backend->handle, mem, memlen); if(rc <= 0) { @@ -4254,6 +4280,7 @@ static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */ ERR_clear_error(); buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + set_logger(conn, data); nread = (ssize_t)SSL_read(backend->handle, buf, buffsize); if(nread <= 0) { /* failed SSL_read */ @@ -4453,10 +4480,95 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl, (void *)backend->ctx : (void *)backend->handle; } +static void ossl_associate_connection(struct Curl_easy *data, + struct connectdata *conn, + int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; + + /* If we don't have SSL context, do nothing. */ + if(!backend->handle) + return; + + if(SSL_SET_OPTION(primary.sessionid)) { + int data_idx = ossl_get_ssl_data_index(); + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + int proxy_idx = ossl_get_proxy_index(); + + if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && + proxy_idx >= 0) { + /* Store the data needed for the "new session" callback. + * The sockindex is stored as a pointer to an array element. */ + SSL_set_ex_data(backend->handle, data_idx, data); + SSL_set_ex_data(backend->handle, connectdata_idx, conn); + SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex); +#ifndef CURL_DISABLE_PROXY + SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1: + NULL); +#else + SSL_set_ex_data(backend->handle, proxy_idx, NULL); +#endif + } + } +} + +/* + * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after + * the handshake. If the transfer that sets up the callback gets killed before + * this callback arrives, we must make sure to properly clear the data to + * avoid UAF problems. A future optimization could be to instead store another + * transfer that might still be using the same connection. + */ + +static void ossl_disassociate_connection(struct Curl_easy *data, + int sockindex) +{ + struct connectdata *conn = data->conn; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; + + /* If we don't have SSL context, do nothing. */ + if(!backend->handle) + return; + + if(SSL_SET_OPTION(primary.sessionid)) { + bool isproxy = FALSE; + bool incache; + void *old_ssl_sessionid = NULL; + int data_idx = ossl_get_ssl_data_index(); + int connectdata_idx = ossl_get_ssl_conn_index(); + int sockindex_idx = ossl_get_ssl_sockindex_index(); + int proxy_idx = ossl_get_proxy_index(); + + if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && + proxy_idx >= 0) { + /* Invalidate the session cache entry, if any */ + isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE; + + /* Disable references to data in "new session" callback to avoid + * accessing a stale pointer. */ + SSL_set_ex_data(backend->handle, data_idx, NULL); + SSL_set_ex_data(backend->handle, connectdata_idx, NULL); + SSL_set_ex_data(backend->handle, sockindex_idx, NULL); + SSL_set_ex_data(backend->handle, proxy_idx, NULL); + } + + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, isproxy, + &old_ssl_sessionid, NULL, sockindex)); + if(incache) + Curl_ssl_delsessionid(data, old_ssl_sessionid); + Curl_ssl_sessionid_unlock(data); + } +} + const struct Curl_ssl Curl_ssl_openssl = { { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ SSLSUPP_CA_PATH | + SSLSUPP_CAINFO_BLOB | SSLSUPP_CERTINFO | SSLSUPP_PINNEDPUBKEY | SSLSUPP_SSL_CTX | @@ -4477,6 +4589,7 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_cert_status_request, /* cert_status_request */ ossl_connect, /* connect */ ossl_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ ossl_get_internals, /* get_internals */ ossl_close, /* close_one */ ossl_close_all, /* close_all */ @@ -4486,10 +4599,12 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) - ossl_sha256sum /* sha256sum */ + ossl_sha256sum, /* sha256sum */ #else - NULL /* sha256sum */ + NULL, /* sha256sum */ #endif + ossl_associate_connection, /* associate_connection */ + ossl_disassociate_connection /* disassociate_connection */ }; #endif /* USE_OPENSSL */ diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c new file mode 100644 index 00000000000..d5247f936ad --- /dev/null +++ b/lib/vtls/rustls.c @@ -0,0 +1,583 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2020 - 2021, Jacob Hoffman-Andrews, + * + * + * 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. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_RUSTLS + +#include "curl_printf.h" + +#include +#include + +#include "inet_pton.h" +#include "urldata.h" +#include "sendf.h" +#include "vtls.h" +#include "select.h" + +#include "multiif.h" + +struct ssl_backend_data +{ + const struct rustls_client_config *config; + struct rustls_connection *conn; + bool data_pending; +}; + +/* For a given rustls_result error code, return the best-matching CURLcode. */ +static CURLcode map_error(rustls_result r) +{ + if(rustls_result_is_cert_error(r)) { + return CURLE_PEER_FAILED_VERIFICATION; + } + switch(r) { + case RUSTLS_RESULT_OK: + return CURLE_OK; + case RUSTLS_RESULT_NULL_PARAMETER: + return CURLE_BAD_FUNCTION_ARGUMENT; + default: + return CURLE_READ_ERROR; + } +} + +static bool +cr_data_pending(const struct connectdata *conn, int sockindex) +{ + const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; + return backend->data_pending; +} + +static CURLcode +cr_connect(struct Curl_easy *data UNUSED_PARAM, + struct connectdata *conn UNUSED_PARAM, + int sockindex UNUSED_PARAM) +{ + infof(data, "rustls_connect: unimplemented\n"); + return CURLE_SSL_CONNECT_ERROR; +} + +static int +read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n) +{ + ssize_t n = sread(*(int *)userdata, buf, len); + if(n < 0) { + return SOCKERRNO; + } + *out_n = n; + return 0; +} + +static int +write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) +{ + ssize_t n = swrite(*(int *)userdata, buf, len); + if(n < 0) { + return SOCKERRNO; + } + *out_n = n; + return 0; +} + +/* + * On each run: + * - Read a chunk of bytes from the socket into rustls' TLS input buffer. + * - Tell rustls to process any new packets. + * - Read out as many plaintext bytes from rustls as possible, until hitting + * error, EOF, or EAGAIN/EWOULDBLOCK, or plainbuf/plainlen is filled up. + * + * It's okay to call this function with plainbuf == NULL and plainlen == 0. + * In that case, it will copy bytes from the socket into rustls' TLS input + * buffer, and process packets, but won't consume bytes from rustls' plaintext + * output buffer. + */ +static ssize_t +cr_recv(struct Curl_easy *data, int sockindex, + char *plainbuf, size_t plainlen, CURLcode *err) +{ + struct connectdata *conn = data->conn; + struct ssl_connect_data *const connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *const backend = connssl->backend; + struct rustls_connection *const rconn = backend->conn; + size_t n = 0; + size_t tls_bytes_read = 0; + size_t plain_bytes_copied = 0; + rustls_result rresult = 0; + char errorbuf[255]; + rustls_io_result io_error; + + io_error = rustls_connection_read_tls(rconn, read_cb, + &conn->sock[sockindex], &tls_bytes_read); + if(io_error == EAGAIN || io_error == EWOULDBLOCK) { + infof(data, "sread: EAGAIN or EWOULDBLOCK\n"); + } + else if(io_error) { + failf(data, "reading from socket: %s", strerror(io_error)); + *err = CURLE_READ_ERROR; + return -1; + } + else if(tls_bytes_read == 0) { + failf(data, "connection closed without TLS close_notify alert"); + *err = CURLE_READ_ERROR; + return -1; + } + + infof(data, "cr_recv read %ld bytes from the network\n", tls_bytes_read); + + rresult = rustls_connection_process_new_packets(rconn); + if(rresult != RUSTLS_RESULT_OK) { + rustls_error(rresult, errorbuf, sizeof(errorbuf), &n); + failf(data, "%.*s", n, errorbuf); + *err = map_error(rresult); + return -1; + } + + backend->data_pending = TRUE; + + while(plain_bytes_copied < plainlen) { + rresult = rustls_connection_read(rconn, + (uint8_t *)plainbuf + plain_bytes_copied, + plainlen - plain_bytes_copied, + &n); + if(rresult == RUSTLS_RESULT_ALERT_CLOSE_NOTIFY) { + *err = CURLE_OK; + return 0; + } + else if(rresult != RUSTLS_RESULT_OK) { + failf(data, "error in rustls_connection_read"); + *err = CURLE_READ_ERROR; + return -1; + } + else if(n == 0) { + /* rustls returns 0 from connection_read to mean "all currently + available data has been read." If we bring in more ciphertext with + read_tls, more plaintext will become available. So don't tell curl + this is an EOF. Instead, say "come back later." */ + infof(data, "cr_recv got 0 bytes of plaintext\n"); + backend->data_pending = FALSE; + break; + } + else { + infof(data, "cr_recv copied out %ld bytes of plaintext\n", n); + plain_bytes_copied += n; + } + } + + /* If we wrote out 0 plaintext bytes, it might just mean we haven't yet + read a full TLS record. Return CURLE_AGAIN so curl doesn't treat this + as EOF. */ + if(plain_bytes_copied == 0) { + *err = CURLE_AGAIN; + return -1; + } + + return plain_bytes_copied; +} + +/* + * On each call: + * - Copy `plainlen` bytes into rustls' plaintext input buffer (if > 0). + * - Fully drain rustls' plaintext output buffer into the socket until + * we get either an error or EAGAIN/EWOULDBLOCK. + * + * It's okay to call this function with plainbuf == NULL and plainlen == 0. + * In that case, it won't read anything into rustls' plaintext input buffer. + * It will only drain rustls' plaintext output buffer into the socket. + */ +static ssize_t +cr_send(struct Curl_easy *data, int sockindex, + const void *plainbuf, size_t plainlen, CURLcode *err) +{ + struct connectdata *conn = data->conn; + struct ssl_connect_data *const connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *const backend = connssl->backend; + struct rustls_connection *const rconn = backend->conn; + size_t plainwritten = 0; + size_t tlswritten = 0; + size_t tlswritten_total = 0; + rustls_result rresult; + rustls_io_result io_error; + + infof(data, "cr_send %ld bytes of plaintext\n", plainlen); + + if(plainlen > 0) { + rresult = rustls_connection_write(rconn, plainbuf, plainlen, + &plainwritten); + if(rresult != RUSTLS_RESULT_OK) { + failf(data, "error in rustls_connection_write"); + *err = CURLE_WRITE_ERROR; + return -1; + } + else if(plainwritten == 0) { + failf(data, "EOF in rustls_connection_write"); + *err = CURLE_WRITE_ERROR; + return -1; + } + } + + while(rustls_connection_wants_write(rconn)) { + io_error = rustls_connection_write_tls(rconn, write_cb, + &conn->sock[sockindex], &tlswritten); + if(io_error == EAGAIN || io_error == EWOULDBLOCK) { + infof(data, "swrite: EAGAIN after %ld bytes\n", tlswritten_total); + *err = CURLE_AGAIN; + return -1; + } + else if(io_error) { + failf(data, "writing to socket: %s", strerror(io_error)); + *err = CURLE_WRITE_ERROR; + return -1; + } + if(tlswritten == 0) { + failf(data, "EOF in swrite"); + *err = CURLE_WRITE_ERROR; + return -1; + } + infof(data, "cr_send wrote %ld bytes to network\n", tlswritten); + tlswritten_total += tlswritten; + } + + return plainwritten; +} + +/* A server certificate verify callback for rustls that always returns + RUSTLS_RESULT_OK, or in other words disable certificate verification. */ +static enum rustls_result +cr_verify_none(void *userdata UNUSED_PARAM, + const rustls_verify_server_cert_params *params UNUSED_PARAM) +{ + return RUSTLS_RESULT_OK; +} + +static bool +cr_hostname_is_ip(const char *hostname) +{ + struct in_addr in; +#ifdef ENABLE_IPV6 + struct in6_addr in6; + if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) { + return true; + } +#endif /* ENABLE_IPV6 */ + if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { + return true; + } + return false; +} + +static CURLcode +cr_init_backend(struct Curl_easy *data, struct connectdata *conn, + struct ssl_backend_data *const backend) +{ + struct rustls_connection *rconn = backend->conn; + struct rustls_client_config_builder *config_builder = NULL; + const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char *hostname = conn->host.name; + char errorbuf[256]; + size_t errorlen; + int result; + rustls_slice_bytes alpn[2] = { + { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH }, + { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH }, + }; + + config_builder = rustls_client_config_builder_new(); +#ifdef USE_HTTP2 + infof(data, "offering ALPN for HTTP/1.1 and HTTP/2\n"); + rustls_client_config_builder_set_protocols(config_builder, alpn, 2); +#else + infof(data, "offering ALPN for HTTP/1.1 only\n"); + rustls_client_config_builder_set_protocols(config_builder, alpn, 1); +#endif + if(!verifypeer) { + rustls_client_config_builder_dangerous_set_certificate_verifier( + config_builder, cr_verify_none); + /* rustls doesn't support IP addresses (as of 0.19.0), and will reject + * connections created with an IP address, even when certificate + * verification is turned off. Set a placeholder hostname and disable + * SNI. */ + if(cr_hostname_is_ip(hostname)) { + rustls_client_config_builder_set_enable_sni(config_builder, false); + hostname = "example.invalid"; + } + } + else if(ssl_cafile) { + result = rustls_client_config_builder_load_roots_from_file( + config_builder, ssl_cafile); + if(result != RUSTLS_RESULT_OK) { + failf(data, "failed to load trusted certificates"); + rustls_client_config_free( + rustls_client_config_builder_build(config_builder)); + return CURLE_SSL_CACERT_BADFILE; + } + } + else { + result = rustls_client_config_builder_load_native_roots(config_builder); + if(result != RUSTLS_RESULT_OK) { + failf(data, "failed to load trusted certificates"); + rustls_client_config_free( + rustls_client_config_builder_build(config_builder)); + return CURLE_SSL_CACERT_BADFILE; + } + } + + backend->config = rustls_client_config_builder_build(config_builder); + DEBUGASSERT(rconn == NULL); + result = rustls_client_connection_new(backend->config, hostname, &rconn); + if(result != RUSTLS_RESULT_OK) { + rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen); + failf(data, "rustls_client_connection_new: %.*s", errorlen, errorbuf); + return CURLE_COULDNT_CONNECT; + } + rustls_connection_set_userdata(rconn, backend); + backend->conn = rconn; + return CURLE_OK; +} + +static void +cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn, + const struct rustls_connection *rconn) +{ + const uint8_t *protocol = NULL; + size_t len = 0; + + rustls_connection_get_alpn_protocol(rconn, &protocol, &len); + if(NULL == protocol) { + infof(data, "ALPN, server did not agree to a protocol\n"); + return; + } + +#ifdef USE_HTTP2 + if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) { + infof(data, "ALPN, negotiated h2\n"); + conn->negnpn = CURL_HTTP_VERSION_2; + } + else +#endif + if(len == ALPN_HTTP_1_1_LENGTH && + 0 == memcmp(ALPN_HTTP_1_1, protocol, len)) { + infof(data, "ALPN, negotiated http/1.1\n"); + conn->negnpn = CURL_HTTP_VERSION_1_1; + } + else { + infof(data, "ALPN, negotiated an unrecognized protocol\n"); + } + + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); +} + +static CURLcode +cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, + int sockindex, bool *done) +{ + struct ssl_connect_data *const connssl = &conn->ssl[sockindex]; + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_backend_data *const backend = connssl->backend; + struct rustls_connection *rconn = NULL; + CURLcode tmperr = CURLE_OK; + int result; + int what; + bool wants_read; + bool wants_write; + curl_socket_t writefd; + curl_socket_t readfd; + + if(ssl_connection_none == connssl->state) { + result = cr_init_backend(data, conn, connssl->backend); + if(result != CURLE_OK) { + return result; + } + connssl->state = ssl_connection_negotiating; + } + + rconn = backend->conn; + + /* Read/write data until the handshake is done or the socket would block. */ + for(;;) { + /* + * Connection has been established according to rustls. Set send/recv + * handlers, and update the state machine. + * This check has to come last because is_handshaking starts out false, + * then becomes true when we first write data, then becomes false again + * once the handshake is done. + */ + if(!rustls_connection_is_handshaking(rconn)) { + infof(data, "Done handshaking\n"); + /* Done with the handshake. Set up callbacks to send/receive data. */ + connssl->state = ssl_connection_complete; + + cr_set_negotiated_alpn(data, conn, rconn); + + conn->recv[sockindex] = cr_recv; + conn->send[sockindex] = cr_send; + *done = TRUE; + return CURLE_OK; + } + + wants_read = rustls_connection_wants_read(rconn); + wants_write = rustls_connection_wants_write(rconn); + DEBUGASSERT(wants_read || wants_write); + writefd = wants_write?sockfd:CURL_SOCKET_BAD; + readfd = wants_read?sockfd:CURL_SOCKET_BAD; + + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0); + if(what < 0) { + /* fatal error */ + failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); + return CURLE_SSL_CONNECT_ERROR; + } + if(0 == what) { + infof(data, "Curl_socket_check: %s would block\n", + wants_read&&wants_write ? + "writing and reading" : + wants_write ? + "writing" : + "reading"); + *done = FALSE; + return CURLE_OK; + } + /* socket is readable or writable */ + + if(wants_write) { + infof(data, "rustls_connection wants us to write_tls.\n"); + cr_send(data, sockindex, NULL, 0, &tmperr); + if(tmperr == CURLE_AGAIN) { + infof(data, "writing would block\n"); + /* fall through */ + } + else if(tmperr != CURLE_OK) { + return tmperr; + } + } + + if(wants_read) { + infof(data, "rustls_connection wants us to read_tls.\n"); + + cr_recv(data, sockindex, NULL, 0, &tmperr); + if(tmperr == CURLE_AGAIN) { + infof(data, "reading would block\n"); + /* fall through */ + } + else if(tmperr != CURLE_OK) { + if(tmperr == CURLE_READ_ERROR) { + return CURLE_SSL_CONNECT_ERROR; + } + else { + return tmperr; + } + } + } + } + + /* We should never fall through the loop. We should return either because + the handshake is done or because we can't read/write without blocking. */ + DEBUGASSERT(false); +} + +/* returns a bitmap of flags for this connection's first socket indicating + whether we want to read or write */ +static int +cr_getsock(struct connectdata *conn, curl_socket_t *socks) +{ + struct ssl_connect_data *const connssl = &conn->ssl[FIRSTSOCKET]; + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; + struct ssl_backend_data *const backend = connssl->backend; + struct rustls_connection *rconn = backend->conn; + + if(rustls_connection_wants_write(rconn)) { + socks[0] = sockfd; + return GETSOCK_WRITESOCK(0); + } + if(rustls_connection_wants_read(rconn)) { + socks[0] = sockfd; + return GETSOCK_READSOCK(0); + } + + return GETSOCK_BLANK; +} + +static void * +cr_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + struct ssl_backend_data *backend = connssl->backend; + return &backend->conn; +} + +static void +cr_close(struct Curl_easy *data, struct connectdata *conn, + int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_backend_data *backend = connssl->backend; + CURLcode tmperr = CURLE_OK; + ssize_t n = 0; + + if(backend->conn) { + rustls_connection_send_close_notify(backend->conn); + n = cr_send(data, sockindex, NULL, 0, &tmperr); + if(n < 0) { + failf(data, "error sending close notify: %d", tmperr); + } + + rustls_connection_free(backend->conn); + backend->conn = NULL; + } + if(backend->config) { + rustls_client_config_free(backend->config); + backend->config = NULL; + } +} + +const struct Curl_ssl Curl_ssl_rustls = { + { CURLSSLBACKEND_RUSTLS, "rustls" }, + SSLSUPP_TLS13_CIPHERSUITES, /* supports */ + sizeof(struct ssl_backend_data), + + Curl_none_init, /* init */ + Curl_none_cleanup, /* cleanup */ + rustls_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + cr_data_pending, /* data_pending */ + Curl_none_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + cr_connect, /* connect */ + cr_connect_nonblocking, /* connect_nonblocking */ + cr_getsock, /* cr_getsock */ + cr_get_internals, /* get_internals */ + cr_close, /* close_one */ + Curl_none_close_all, /* close_all */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ +}; + +#endif /* USE_RUSTLS */ diff --git a/lib/vtls/rustls.h b/lib/vtls/rustls.h new file mode 100644 index 00000000000..056211dd8b9 --- /dev/null +++ b/lib/vtls/rustls.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2020 - 2021, Jacob Hoffman-Andrews, + * + * + * 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. + * + ***************************************************************************/ +#ifndef HEADER_CURL_RUSTLS_H +#define HEADER_CURL_RUSTLS_H + +#include "curl_setup.h" + +#ifdef USE_RUSTLS + +extern const struct Curl_ssl Curl_ssl_rustls; + +#endif /* USE_RUSTLS */ +#endif /* HEADER_CURL_RUSTLS_H */ diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 0668f98f29d..2bcf11db257 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -117,6 +117,10 @@ #define SP_PROT_TLS1_2_CLIENT 0x00000800 #endif +#ifndef SCH_USE_STRONG_CRYPTO +#define SCH_USE_STRONG_CRYPTO 0x00400000 +#endif + #ifndef SECBUFFER_ALERT #define SECBUFFER_ALERT 17 #endif @@ -324,17 +328,22 @@ get_alg_id_by_name(char *name) } static CURLcode -set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers) +set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, + ALG_ID *algIds) { char *startCur = ciphers; int algCount = 0; - static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/ - while(startCur && (0 != *startCur) && (algCount < 45)) { + while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) { long alg = strtol(startCur, 0, 0); if(!alg) alg = get_alg_id_by_name(startCur); if(alg) algIds[algCount++] = alg; + else if(!strncmp(startCur, "USE_STRONG_CRYPTO", + sizeof("USE_STRONG_CRYPTO") - 1) || + !strncmp(startCur, "SCH_USE_STRONG_CRYPTO", + sizeof("SCH_USE_STRONG_CRYPTO") - 1)) + schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO; else return CURLE_SSL_CIPHER; startCur = strchr(startCur, ':'); @@ -358,7 +367,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, size_t store_name_len; sep = _tcschr(path, TEXT('\\')); - if(sep == NULL) + if(!sep) return CURLE_SSL_CERTPROBLEM; store_name_len = sep - path; @@ -388,7 +397,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, store_path_start = sep + 1; sep = _tcschr(store_path_start, TEXT('\\')); - if(sep == NULL) + if(!sep) return CURLE_SSL_CERTPROBLEM; *thumbprint = sep + 1; @@ -398,7 +407,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, *sep = TEXT('\0'); *store_path = _tcsdup(store_path_start); *sep = TEXT('\\'); - if(*store_path == NULL) + if(!*store_path) return CURLE_OUT_OF_MEMORY; return CURLE_OK; @@ -428,12 +437,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif TCHAR *host_name; CURLcode result; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", @@ -469,7 +473,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif #else #ifdef HAS_MANUAL_VERIFY_API - if(SSL_CONN_CONFIG(CAfile)) { + if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) { if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { BACKEND->use_manual_cred_validation = true; @@ -483,7 +487,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, else BACKEND->use_manual_cred_validation = false; #else - if(SSL_CONN_CONFIG(CAfile)) { + if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) { failf(data, "schannel: CA cert support not built in"); return CURLE_NOT_BUILT_IN; } @@ -496,6 +500,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, if(SSL_SET_OPTION(primary.sessionid)) { Curl_ssl_sessionid_lock(data); if(!Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); @@ -522,14 +527,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - if(data->set.ssl.no_revoke) { + if(SSL_SET_OPTION(no_revoke)) { schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; DEBUGF(infof(data, "schannel: disabled server certificate revocation " "checks\n")); } - else if(data->set.ssl.revoke_best_effort) { + else if(SSL_SET_OPTION(revoke_best_effort)) { schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; @@ -557,6 +562,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, "names in server certificates.\n")); } + if(!SSL_SET_OPTION(auto_client_cert)) { + schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS; + schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + infof(data, "schannel: disabled automatic use of client certificate\n"); + } + else + infof(data, "schannel: enabled automatic use of client certificate\n"); + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: @@ -571,18 +584,17 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, break; } case CURL_SSLVERSION_SSLv3: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; - break; case CURL_SSLVERSION_SSLv2: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } if(SSL_CONN_CONFIG(cipher_list)) { - result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list)); + result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list), + BACKEND->algIds); if(CURLE_OK != result) { failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); return result; @@ -699,7 +711,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, } if(!blob) free(certdata); - if(cert_store == NULL) { + if(!cert_store) { DWORD errorcode = GetLastError(); if(errorcode == ERROR_INVALID_PASSWORD) failf(data, "schannel: Failed to import cert file %s, " @@ -716,7 +728,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); - if(client_certs[0] == NULL) { + if(!client_certs[0]) { failf(data, "schannel: Failed to get certificate from file %s" ", last error is 0x%x", cert_showfilename_error, GetLastError()); @@ -860,11 +872,11 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, list_start_index = cur; -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2) { - memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); - cur += NGHTTP2_PROTO_ALPN_LEN; - infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2) { + memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; + infof(data, "schannel: ALPN, offering %s\n", ALPN_H2); } #endif @@ -892,11 +904,15 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, &outbuf, 1); - /* setup request flags */ + /* security request flags */ BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; + if(!SSL_SET_OPTION(auto_client_cert)) { + BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; + } + /* allocate memory for the security context handle */ BACKEND->ctxt = (struct Curl_schannel_ctxt *) calloc(1, sizeof(struct Curl_schannel_ctxt)); @@ -996,12 +1012,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, SECURITY_STATUS sspi_status = SEC_E_OK; CURLcode result; bool doread; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); const char *pubkey_ptr; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; @@ -1014,23 +1025,23 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; /* buffer to store previously received and decrypted data */ - if(BACKEND->decdata_buffer == NULL) { + if(!BACKEND->decdata_buffer) { BACKEND->decdata_offset = 0; BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); - if(BACKEND->decdata_buffer == NULL) { + if(!BACKEND->decdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } } /* buffer to store previously received and encrypted data */ - if(BACKEND->encdata_buffer == NULL) { + if(!BACKEND->encdata_buffer) { BACKEND->encdata_is_incomplete = false; BACKEND->encdata_offset = 0; BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); - if(BACKEND->encdata_buffer == NULL) { + if(!BACKEND->encdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1045,7 +1056,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { failf(data, "schannel: unable to re-allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1100,7 +1111,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, outbuf, 3); - if(inbuf[0].pvBuffer == NULL) { + if(!inbuf[0].pvBuffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1250,9 +1261,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); } - pubkey_ptr = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + pubkey_ptr = SSL_PINNED_PUB_KEY(); if(pubkey_ptr) { result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr); if(result) { @@ -1337,9 +1346,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; + bool isproxy = SSL_IS_PROXY(); #ifdef DEBUGBUILD - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; + const char * const hostname = SSL_HOST_NAME(); #endif #ifdef HAS_ALPN SecPkgContext_ApplicationProtocol alpn_result; @@ -1387,10 +1396,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, infof(data, "schannel: ALPN, server accepted to use %.*s\n", alpn_result.ProtocolIdSize, alpn_result.ProtocolId); -#ifdef USE_NGHTTP2 - if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, - NGHTTP2_PROTO_VERSION_ID_LEN)) { +#ifdef USE_HTTP2 + if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -1414,8 +1422,8 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, struct Curl_schannel_cred *old_cred = NULL; Curl_ssl_sessionid_lock(data); - incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL, - sockindex)); + incache = !(Curl_ssl_getsessionid(data, conn, isproxy, (void **)&old_cred, + NULL, sockindex)); if(incache) { if(old_cred != BACKEND->cred) { DEBUGF(infof(data, @@ -1426,7 +1434,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, } } if(!incache) { - result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred, + result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred, sizeof(struct Curl_schannel_cred), sockindex); if(result) { @@ -1451,7 +1459,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); - if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { + if((sspi_status != SEC_E_OK) || !ccert_context) { failf(data, "schannel: failed to retrieve remote cert context"); return CURLE_PEER_FAILED_VERIFICATION; } @@ -1803,7 +1811,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; @@ -1892,7 +1900,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } reallocated_buffer = realloc(BACKEND->decdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; @@ -2126,12 +2134,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, * Shutting Down an Schannel Connection */ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); DEBUGASSERT(data); @@ -2294,7 +2297,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pCertContextServer); - if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || !pCertContextServer) { char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); @@ -2404,6 +2407,9 @@ const struct Curl_ssl Curl_ssl_schannel = { { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ SSLSUPP_CERTINFO | +#ifdef HAS_MANUAL_VERIFY_API + SSLSUPP_CAINFO_BLOB | +#endif SSLSUPP_PINNEDPUBKEY, sizeof(struct ssl_backend_data), @@ -2418,6 +2424,7 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_cert_status_request, /* cert_status_request */ schannel_connect, /* connect */ schannel_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ schannel_get_internals, /* get_internals */ schannel_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -2426,7 +2433,9 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - schannel_sha256sum /* sha256sum */ + schannel_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_SCHANNEL */ diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h index 2952caa1a5a..77853aa30f9 100644 --- a/lib/vtls/schannel.h +++ b/lib/vtls/schannel.h @@ -71,6 +71,8 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, #endif #endif +#define NUMOF_CIPHERS 45 /* There are 45 listed in the MS headers */ + struct Curl_schannel_cred { CredHandle cred_handle; TimeStamp time_stamp; @@ -102,6 +104,7 @@ struct ssl_backend_data { #ifdef HAS_MANUAL_VERIFY_API bool use_manual_cred_validation; /* true if manual cred validation is used */ #endif + ALG_ID algIds[NUMOF_CIPHERS]; }; #endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */ diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index 2ef39cc0f44..25d47b8087f 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -77,21 +77,156 @@ static int is_cr_or_lf(char c) return c == '\r' || c == '\n'; } -static CURLcode add_certs_to_store(HCERTSTORE trust_store, - const char *ca_file, - struct Curl_easy *data) +/* Search the substring needle,needlelen into string haystack,haystacklen + * Strings don't need to be terminated by a '\0'. + * Similar of OSX/Linux memmem (not available on Visual Studio). + * Return position of beginning of first occurence or NULL if not found + */ +static const char *c_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen) +{ + const char *p; + char first; + const char *str_limit = (const char *)haystack + haystacklen; + if(!needlelen || needlelen > haystacklen) + return NULL; + first = *(const char *)needle; + for(p = (const char *)haystack; p <= (str_limit - needlelen); p++) + if(((*p) == first) && (memcmp(p, needle, needlelen) == 0)) + return p; + + return NULL; +} + +static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, + const char *ca_buffer, + size_t ca_buffer_size, + const char *ca_file_text, + struct Curl_easy *data) +{ + const size_t begin_cert_len = strlen(BEGIN_CERT); + const size_t end_cert_len = strlen(END_CERT); + CURLcode result = CURLE_OK; + int num_certs = 0; + bool more_certs = 1; + const char *current_ca_file_ptr = ca_buffer; + const char *ca_buffer_limit = ca_buffer + ca_buffer_size; + + while(more_certs && (current_ca_file_ptrdwAltNameChoice != CERT_ALT_NAME_DNS_NAME) { continue; } - if(entry->pwszDNSName == NULL) { + if(!entry->pwszDNSName) { infof(data, "schannel: Empty DNS name."); continue; } @@ -536,27 +575,22 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, const CERT_CHAIN_CONTEXT *pChainContext = NULL; HCERTCHAINENGINE cert_chain_engine = NULL; HCERTSTORE trust_store = NULL; -#ifndef CURL_DISABLE_PROXY - const char * const conn_hostname = SSL_IS_PROXY() ? - conn->http_proxy.host.name : - conn->host.name; -#else - const char * const conn_hostname = conn->host.name; -#endif + const char * const conn_hostname = SSL_HOST_NAME(); sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pCertContextServer); - if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || !pCertContextServer) { char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); result = CURLE_PEER_FAILED_VERIFICATION; } - if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) && + if(result == CURLE_OK && + (SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) && BACKEND->use_manual_cred_validation) { /* * Create a chain engine that uses the certificates in the CA file as @@ -582,8 +616,19 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, result = CURLE_SSL_CACERT_BADFILE; } else { - result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile), - data); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); + if(ca_info_blob) { + result = add_certs_data_to_store(trust_store, + (const char *)ca_info_blob->data, + ca_info_blob->len, + "(memory blob)", + data); + } + else { + result = add_certs_file_to_store(trust_store, + SSL_CONN_CONFIG(CAfile), + data); + } } } @@ -624,7 +669,7 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data, NULL, pCertContextServer->hCertStore, &ChainPara, - (data->set.ssl.no_revoke ? 0 : + (SSL_SET_OPTION(no_revoke) ? 0 : CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c index 9a8f7de8d51..edd375ea7d7 100644 --- a/lib/vtls/sectransp.c +++ b/lib/vtls/sectransp.c @@ -67,6 +67,7 @@ #define CURL_BUILD_IOS_7 0 #define CURL_BUILD_IOS_9 0 #define CURL_BUILD_IOS_11 0 +#define CURL_BUILD_IOS_13 0 #define CURL_BUILD_MAC 1 /* This is the maximum API level we are allowed to use when building: */ #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 @@ -76,6 +77,7 @@ #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +#define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 /* These macros mean "the following code is present to allow runtime backward compatibility with at least this cat or earlier": (You set this at build-time using the compiler command line option @@ -91,6 +93,7 @@ #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 +#define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 #define CURL_BUILD_MAC 0 #define CURL_BUILD_MAC_10_5 0 #define CURL_BUILD_MAC_10_6 0 @@ -99,6 +102,7 @@ #define CURL_BUILD_MAC_10_9 0 #define CURL_BUILD_MAC_10_11 0 #define CURL_BUILD_MAC_10_13 0 +#define CURL_BUILD_MAC_10_15 0 #define CURL_SUPPORT_MAC_10_5 0 #define CURL_SUPPORT_MAC_10_6 0 #define CURL_SUPPORT_MAC_10_7 0 @@ -138,6 +142,636 @@ struct ssl_backend_data { size_t ssl_write_buffered_length; }; +struct st_cipher { + const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */ + const char *alias_name; /* Alias name is the same as OpenSSL cipher name */ + SSLCipherSuite num; /* Cipher suite code/number defined in IANA registry */ + bool weak; /* Flag to mark cipher as weak based on previous implementation + of Secure Transport back-end by CURL */ +}; + +/* Macro to initialize st_cipher data structure: stringify id to name, cipher + number/id, 'weak' suite flag + */ +#define CIPHER_DEF(num, alias, weak) \ + { #num, alias, num, weak } + +/* + Macro to initialize st_cipher data structure with name, code (IANA cipher + number/id value), and 'weak' suite flag. The first 28 cipher suite numbers + have the same IANA code for both SSL and TLS standards: numbers 0x0000 to + 0x001B. They have different names though. The first 4 letters of the cipher + suite name are the protocol name: "SSL_" or "TLS_", rest of the IANA name is + the same for both SSL and TLS cipher suite name. + The second part of the problem is that macOS/iOS SDKs don't define all TLS + codes but only 12 of them. The SDK defines all SSL codes though, i.e. SSL_NUM + constant is always defined for those 28 ciphers while TLS_NUM is defined only + for 12 of the first 28 ciphers. Those 12 TLS cipher codes match to + corresponding SSL enum value and represent the same cipher suite. Therefore + we'll use the SSL enum value for those cipher suites because it is defined + for all 28 of them. + We make internal data consistent and based on TLS names, i.e. all st_cipher + item names start with the "TLS_" prefix. + Summarizing all the above, those 28 first ciphers are presented in our table + with both TLS and SSL names. Their cipher numbers are assigned based on the + SDK enum value for the SSL cipher, which matches to IANA TLS number. + */ +#define CIPHER_DEF_SSLTLS(num_wo_prefix, alias, weak) \ + { "TLS_" #num_wo_prefix, alias, SSL_##num_wo_prefix, weak } + +/* + Cipher suites were marked as weak based on the following: + RC4 encryption - rfc7465, the document contains a list of deprecated ciphers. + Marked in the code below as weak. + RC2 encryption - many mentions, was found vulnerable to a relatively easy + attack https://link.springer.com/chapter/10.1007%2F3-540-69710-1_14 + Marked in the code below as weak. + DES and IDEA encryption - rfc5469, has a list of deprecated ciphers. + Marked in the code below as weak. + Anonymous Diffie-Hellman authentication and anonymous elliptic curve + Diffie-Hellman - vulnerable to a man-in-the-middle attack. Deprecated by + RFC 4346 aka TLS 1.1 (section A.5, page 60) + Null bulk encryption suites - not encrypted communication + Export ciphers, i.e. ciphers with restrictions to be used outside the US for + software exported to some countries, they were excluded from TLS 1.1 + version. More precisely, they were noted as ciphers which MUST NOT be + negotiated in RFC 4346 aka TLS 1.1 (section A.5, pages 60 and 61). + All of those filters were considered weak because they contain a weak + algorithm like DES, RC2 or RC4, and already considered weak by other + criteria. + 3DES - NIST deprecated it and is going to retire it by 2023 + https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA + OpenSSL https://www.openssl.org/blog/blog/2016/08/24/sweet32/ also + deprecated those ciphers. Some other libraries also consider it + vulnerable or at least not strong enough. + + CBC ciphers are vulnerable with SSL3.0 and TLS1.0: + https://www.cisco.com/c/en/us/support/docs/security/email-security-appliance + /118518-technote-esa-00.html + We don't take care of this issue because it is resolved by later TLS + versions and for us, it requires more complicated checks, we need to + check a protocol version also. Vulnerability doesn't look very critical + and we do not filter out those cipher suites. + */ + +#define CIPHER_WEAK_NOT_ENCRYPTED TRUE +#define CIPHER_WEAK_RC_ENCRYPTION TRUE +#define CIPHER_WEAK_DES_ENCRYPTION TRUE +#define CIPHER_WEAK_IDEA_ENCRYPTION TRUE +#define CIPHER_WEAK_ANON_AUTH TRUE +#define CIPHER_WEAK_3DES_ENCRYPTION TRUE +#define CIPHER_STRONG_ENOUGH FALSE + +/* Please do not change the order of the first ciphers available for SSL. + Do not insert and do not delete any of them. Code below + depends on their order and continuity. + If you add a new cipher, please maintain order by number, i.e. + insert in between existing items to appropriate place based on + cipher suite IANA number +*/ +const static struct st_cipher ciphertable[] = { + /* SSL version 3.0 and initial TLS 1.0 cipher suites. + Defined since SDK 10.2.8 */ + CIPHER_DEF_SSLTLS(NULL_WITH_NULL_NULL, /* 0x0000 */ + NULL, + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF_SSLTLS(RSA_WITH_NULL_MD5, /* 0x0001 */ + "NULL-MD5", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF_SSLTLS(RSA_WITH_NULL_SHA, /* 0x0002 */ + "NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC4_40_MD5, /* 0x0003 */ + "EXP-RC4-MD5", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_MD5, /* 0x0004 */ + "RC4-MD5", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_SHA, /* 0x0005 */ + "RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* 0x0006 */ + "EXP-RC2-CBC-MD5", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_IDEA_CBC_SHA, /* 0x0007 */ + "IDEA-CBC-SHA", + CIPHER_WEAK_IDEA_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0008 */ + "EXP-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_DES_CBC_SHA, /* 0x0009 */ + "DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */ + "DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x000B */ + "EXP-DH-DSS-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_DSS_WITH_DES_CBC_SHA, /* 0x000C */ + "DH-DSS-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x000D */ + "DH-DSS-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x000E */ + "EXP-DH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_RSA_WITH_DES_CBC_SHA, /* 0x000F */ + "DH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0010 */ + "DH-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x0011 */ + "EXP-EDH-DSS-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_DSS_WITH_DES_CBC_SHA, /* 0x0012 */ + "EDH-DSS-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x0013 */ + "DHE-DSS-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0014 */ + "EXP-EDH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_RSA_WITH_DES_CBC_SHA, /* 0x0015 */ + "EDH-RSA-DES-CBC-SHA", + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0016 */ + "DHE-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_RC4_40_MD5, /* 0x0017 */ + "EXP-ADH-RC4-MD5", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_WITH_RC4_128_MD5, /* 0x0018 */ + "ADH-RC4-MD5", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_DES40_CBC_SHA, /* 0x0019 */ + "EXP-ADH-DES-CBC-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_WITH_DES_CBC_SHA, /* 0x001A */ + "ADH-DES-CBC-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF_SSLTLS(DH_anon_WITH_3DES_EDE_CBC_SHA, /* 0x001B */ + "ADH-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* 0x001C */ + NULL, + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* 0x001D */ + NULL, + CIPHER_STRONG_ENOUGH), + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption */ + CIPHER_DEF(TLS_PSK_WITH_NULL_SHA, /* 0x002C */ + "PSK-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA, /* 0x002D */ + "DHE-PSK-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA, /* 0x002E */ + "RSA-PSK-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* TLS addenda using AES, per RFC 3268. Defined since SDK 10.4u */ + CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */ + "AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA, /* 0x0030 */ + "DH-DSS-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA, /* 0x0031 */ + "DH-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* 0x0032 */ + "DHE-DSS-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* 0x0033 */ + "DHE-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA, /* 0x0034 */ + "ADH-AES128-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */ + "AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA, /* 0x0036 */ + "DH-DSS-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA, /* 0x0037 */ + "DH-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* 0x0038 */ + "DHE-DSS-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* 0x0039 */ + "DHE-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA, /* 0x003A */ + "ADH-AES256-SHA", + CIPHER_WEAK_ANON_AUTH), + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* TLS 1.2 addenda, RFC 5246 */ + /* Server provided RSA certificate for key exchange. */ + CIPHER_DEF(TLS_RSA_WITH_NULL_SHA256, /* 0x003B */ + "NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */ + "AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */ + "AES256-SHA256", + CIPHER_STRONG_ENOUGH), + /* Server-authenticated (and optionally client-authenticated) + Diffie-Hellman. */ + CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA256, /* 0x003E */ + "DH-DSS-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA256, /* 0x003F */ + "DH-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, /* 0x0040 */ + "DHE-DSS-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + + /* TLS 1.2 addenda, RFC 5246 */ + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */ + "DHE-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA256, /* 0x0068 */ + "DH-DSS-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA256, /* 0x0069 */ + "DH-RSA-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, /* 0x006A */ + "DHE-DSS-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */ + "DHE-RSA-AES256-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA256, /* 0x006C */ + "ADH-AES128-SHA256", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA256, /* 0x006D */ + "ADH-AES256-SHA256", + CIPHER_WEAK_ANON_AUTH), +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* Addendum from RFC 4279, TLS PSK */ + CIPHER_DEF(TLS_PSK_WITH_RC4_128_SHA, /* 0x008A */ + "PSK-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008B */ + "PSK-3DES-EDE-CBC-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA, /* 0x008C */ + "PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA, /* 0x008D */ + "PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_RC4_128_SHA, /* 0x008E */ + "DHE-PSK-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008F */ + "DHE-PSK-3DES-EDE-CBC-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA, /* 0x0090 */ + "DHE-PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA, /* 0x0091 */ + "DHE-PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_RC4_128_SHA, /* 0x0092 */ + "RSA-PSK-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x0093 */ + "RSA-PSK-3DES-EDE-CBC-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA, /* 0x0094 */ + "RSA-PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA, /* 0x0095 */ + "RSA-PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites + for TLS. */ + CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */ + "AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */ + "AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */ + "DHE-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */ + "DHE-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_GCM_SHA256, /* 0x00A0 */ + "DH-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_GCM_SHA384, /* 0x00A1 */ + "DH-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A2 */ + "DHE-DSS-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A3 */ + "DHE-DSS-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A4 */ + "DH-DSS-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A5 */ + "DH-DSS-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_128_GCM_SHA256, /* 0x00A6 */ + "ADH-AES128-GCM-SHA256", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_DH_anon_WITH_AES_256_GCM_SHA384, /* 0x00A7 */ + "ADH-AES256-GCM-SHA384", + CIPHER_WEAK_ANON_AUTH), +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 + /* RFC 5487 - PSK with SHA-256/384 and AES GCM */ + CIPHER_DEF(TLS_PSK_WITH_AES_128_GCM_SHA256, /* 0x00A8 */ + "PSK-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_256_GCM_SHA384, /* 0x00A9 */ + "PSK-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AA */ + "DHE-PSK-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AB */ + "DHE-PSK-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AC */ + "RSA-PSK-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AD */ + "RSA-PSK-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA256, /* 0x00AE */ + "PSK-AES128-CBC-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA384, /* 0x00AF */ + "PSK-AES256-CBC-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_PSK_WITH_NULL_SHA256, /* 0x00B0 */ + "PSK-NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_PSK_WITH_NULL_SHA384, /* 0x00B1 */ + "PSK-NULL-SHA384", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B2 */ + "DHE-PSK-AES128-CBC-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B3 */ + "DHE-PSK-AES256-CBC-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA256, /* 0x00B4 */ + "DHE-PSK-NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA384, /* 0x00B5 */ + "DHE-PSK-NULL-SHA384", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B6 */ + "RSA-PSK-AES128-CBC-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B7 */ + "RSA-PSK-AES256-CBC-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA256, /* 0x00B8 */ + "RSA-PSK-NULL-SHA256", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA384, /* 0x00B9 */ + "RSA-PSK-NULL-SHA384", + CIPHER_WEAK_NOT_ENCRYPTED), +#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ + + /* RFC 5746 - Secure Renegotiation. This is not a real suite, + it is a response to initiate negotiation again */ + CIPHER_DEF(TLS_EMPTY_RENEGOTIATION_INFO_SCSV, /* 0x00FF */ + NULL, + CIPHER_STRONG_ENOUGH), + +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* TLS 1.3 standard cipher suites for ChaCha20+Poly1305. + Note: TLS 1.3 ciphersuites do not specify the key exchange + algorithm -- they only specify the symmetric ciphers. + Cipher alias name matches to OpenSSL cipher name, and for + TLS 1.3 ciphers */ + CIPHER_DEF(TLS_AES_128_GCM_SHA256, /* 0x1301 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_AES_256_GCM_SHA384, /* 0x1302 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_AES_128_CCM_SHA256, /* 0x1304 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_AES_128_CCM_8_SHA256, /* 0x1305 */ + NULL, /* The OpenSSL cipher name matches to the IANA name */ + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + +#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS + /* ECDSA addenda, RFC 4492 */ + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_NULL_SHA, /* 0xC001 */ + "ECDH-ECDSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* 0xC002 */ + "ECDH-ECDSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */ + "ECDH-ECDSA-DES-CBC3-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */ + "ECDH-ECDSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */ + "ECDH-ECDSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_NULL_SHA, /* 0xC006 */ + "ECDHE-ECDSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, /* 0xC007 */ + "ECDHE-ECDSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */ + "ECDHE-ECDSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */ + "ECDHE-ECDSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */ + "ECDHE-ECDSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_NULL_SHA, /* 0xC00B */ + "ECDH-RSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDH_RSA_WITH_RC4_128_SHA, /* 0xC00C */ + "ECDH-RSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */ + "ECDH-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */ + "ECDH-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */ + "ECDH-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_NULL_SHA, /* 0xC010 */ + "ECDHE-RSA-NULL-SHA", + CIPHER_WEAK_NOT_ENCRYPTED), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_RC4_128_SHA, /* 0xC011 */ + "ECDHE-RSA-RC4-SHA", + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */ + "ECDHE-RSA-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */ + "ECDHE-RSA-AES128-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */ + "ECDHE-RSA-AES256-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_anon_WITH_NULL_SHA, /* 0xC015 */ + "AECDH-NULL-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_ECDH_anon_WITH_RC4_128_SHA, /* 0xC016 */ + "AECDH-RC4-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, /* 0xC017 */ + "AECDH-DES-CBC3-SHA", + CIPHER_WEAK_3DES_ENCRYPTION), + CIPHER_DEF(TLS_ECDH_anon_WITH_AES_128_CBC_SHA, /* 0xC018 */ + "AECDH-AES128-SHA", + CIPHER_WEAK_ANON_AUTH), + CIPHER_DEF(TLS_ECDH_anon_WITH_AES_256_CBC_SHA, /* 0xC019 */ + "AECDH-AES256-SHA", + CIPHER_WEAK_ANON_AUTH), +#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with + HMAC SHA-256/384. */ + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */ + "ECDHE-ECDSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */ + "ECDHE-ECDSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */ + "ECDH-ECDSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */ + "ECDH-ECDSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */ + "ECDHE-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */ + "ECDHE-RSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */ + "ECDH-RSA-AES128-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */ + "ECDH-RSA-AES256-SHA384", + CIPHER_STRONG_ENOUGH), + /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with + SHA-256/384 and AES Galois Counter Mode (GCM) */ + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */ + "ECDHE-ECDSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */ + "ECDHE-ECDSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */ + "ECDH-ECDSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */ + "ECDH-ECDSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */ + "ECDHE-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */ + "ECDHE-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */ + "ECDH-RSA-AES128-GCM-SHA256", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */ + "ECDH-RSA-AES256-GCM-SHA384", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + +#if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 + /* ECDHE_PSK Cipher Suites for Transport Layer Security (TLS), RFC 5489 */ + CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, /* 0xC035 */ + "ECDHE-PSK-AES128-CBC-SHA", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, /* 0xC036 */ + "ECDHE-PSK-AES256-CBC-SHA", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */ + +#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 + /* Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS). */ + CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */ + "ECDHE-RSA-CHACHA20-POLY1305", + CIPHER_STRONG_ENOUGH), + CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */ + "ECDHE-ECDSA-CHACHA20-POLY1305", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + +#if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 + /* ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS), + RFC 7905 */ + CIPHER_DEF(TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCAB */ + "PSK-CHACHA20-POLY1305", + CIPHER_STRONG_ENOUGH), +#endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */ + + /* Tags for SSL 2 cipher kinds which are not specified for SSL 3. + Defined since SDK 10.2.8 */ + CIPHER_DEF(SSL_RSA_WITH_RC2_CBC_MD5, /* 0xFF80 */ + NULL, + CIPHER_WEAK_RC_ENCRYPTION), + CIPHER_DEF(SSL_RSA_WITH_IDEA_CBC_MD5, /* 0xFF81 */ + NULL, + CIPHER_WEAK_IDEA_ENCRYPTION), + CIPHER_DEF(SSL_RSA_WITH_DES_CBC_MD5, /* 0xFF82 */ + NULL, + CIPHER_WEAK_DES_ENCRYPTION), + CIPHER_DEF(SSL_RSA_WITH_3DES_EDE_CBC_MD5, /* 0xFF83 */ + NULL, + CIPHER_WEAK_3DES_ENCRYPTION), +}; + +#define NUM_OF_CIPHERS sizeof(ciphertable)/sizeof(ciphertable[0]) + + /* pinned public key support tests */ /* version 1 supports macOS 10.12+ and iOS 10+ */ @@ -295,586 +929,23 @@ static OSStatus SocketWrite(SSLConnectionRef connection, } #ifndef CURL_DISABLE_VERBOSE_STRINGS -CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) -{ - switch(cipher) { - /* SSL version 3.0 */ - case SSL_RSA_WITH_NULL_MD5: - return "SSL_RSA_WITH_NULL_MD5"; - break; - case SSL_RSA_WITH_NULL_SHA: - return "SSL_RSA_WITH_NULL_SHA"; - break; - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: - return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; - break; - case SSL_RSA_WITH_RC4_128_MD5: - return "SSL_RSA_WITH_RC4_128_MD5"; - break; - case SSL_RSA_WITH_RC4_128_SHA: - return "SSL_RSA_WITH_RC4_128_SHA"; - break; - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: - return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; - break; - case SSL_RSA_WITH_IDEA_CBC_SHA: - return "SSL_RSA_WITH_IDEA_CBC_SHA"; - break; - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_RSA_WITH_DES_CBC_SHA: - return "SSL_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_DSS_WITH_DES_CBC_SHA: - return "SSL_DH_DSS_WITH_DES_CBC_SHA"; - break; - case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_RSA_WITH_DES_CBC_SHA: - return "SSL_DH_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DHE_DSS_WITH_DES_CBC_SHA: - return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; - break; - case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DHE_RSA_WITH_DES_CBC_SHA: - return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; - break; - case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: - return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; - break; - case SSL_DH_anon_WITH_RC4_128_MD5: - return "SSL_DH_anon_WITH_RC4_128_MD5"; - break; - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: - return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; - break; - case SSL_DH_anon_WITH_DES_CBC_SHA: - return "SSL_DH_anon_WITH_DES_CBC_SHA"; - break; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; - break; - case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: - return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; - break; - /* TLS 1.0 with AES (RFC 3268) - (Apparently these are used in SSLv3 implementations as well.) */ - case TLS_RSA_WITH_AES_128_CBC_SHA: - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - return "TLS_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - break; - /* SSL version 2.0 */ - case SSL_RSA_WITH_RC2_CBC_MD5: - return "SSL_RSA_WITH_RC2_CBC_MD5"; - break; - case SSL_RSA_WITH_IDEA_CBC_MD5: - return "SSL_RSA_WITH_IDEA_CBC_MD5"; - break; - case SSL_RSA_WITH_DES_CBC_MD5: - return "SSL_RSA_WITH_DES_CBC_MD5"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_MD5: - return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; - break; - } - return "SSL_NULL_WITH_NULL_NULL"; -} - CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { - switch(cipher) { - /* TLS 1.0 with AES (RFC 3268) */ - case TLS_RSA_WITH_AES_128_CBC_SHA: - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - return "TLS_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - break; -#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS - /* TLS 1.0 with ECDSA (RFC 4492) */ - case TLS_ECDH_ECDSA_WITH_NULL_SHA: - return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_NULL_SHA: - return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_NULL_SHA: - return "TLS_ECDH_RSA_WITH_NULL_SHA"; - break; - case TLS_ECDH_RSA_WITH_RC4_128_SHA: - return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_NULL_SHA: - return "TLS_ECDHE_RSA_WITH_NULL_SHA"; - break; - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; - break; - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_NULL_SHA: - return "TLS_ECDH_anon_WITH_NULL_SHA"; - break; - case TLS_ECDH_anon_WITH_RC4_128_SHA: - return "TLS_ECDH_anon_WITH_RC4_128_SHA"; - break; - case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: - return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; - break; - case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: - return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; - break; -#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS - /* TLS 1.2 (RFC 5246) */ - case TLS_RSA_WITH_NULL_MD5: - return "TLS_RSA_WITH_NULL_MD5"; - break; - case TLS_RSA_WITH_NULL_SHA: - return "TLS_RSA_WITH_NULL_SHA"; - break; - case TLS_RSA_WITH_RC4_128_MD5: - return "TLS_RSA_WITH_RC4_128_MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - return "TLS_RSA_WITH_RC4_128_SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_RSA_WITH_NULL_SHA256: - return "TLS_RSA_WITH_NULL_SHA256"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; - break; - case TLS_DH_anon_WITH_RC4_128_MD5: - return "TLS_DH_anon_WITH_RC4_128_MD5"; - break; - case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA256: - return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DH_anon_WITH_AES_256_CBC_SHA256: - return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; - break; - /* TLS 1.2 with AES GCM (RFC 5288) */ - case TLS_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DH_anon_WITH_AES_128_GCM_SHA256: - return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DH_anon_WITH_AES_256_GCM_SHA384: - return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; - break; - /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; - break; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; - break; - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; - break; - case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: - return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; - break; -#else - case SSL_RSA_WITH_NULL_MD5: - return "TLS_RSA_WITH_NULL_MD5"; - break; - case SSL_RSA_WITH_NULL_SHA: - return "TLS_RSA_WITH_NULL_SHA"; - break; - case SSL_RSA_WITH_RC4_128_MD5: - return "TLS_RSA_WITH_RC4_128_MD5"; - break; - case SSL_RSA_WITH_RC4_128_SHA: - return "TLS_RSA_WITH_RC4_128_SHA"; - break; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - break; - case SSL_DH_anon_WITH_RC4_128_MD5: - return "TLS_DH_anon_WITH_RC4_128_MD5"; - break; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - break; -#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ -#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 - /* TLS PSK (RFC 4279): */ - case TLS_PSK_WITH_RC4_128_SHA: - return "TLS_PSK_WITH_RC4_128_SHA"; - break; - case TLS_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_PSK_WITH_AES_128_CBC_SHA: - return "TLS_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_PSK_WITH_AES_256_CBC_SHA: - return "TLS_PSK_WITH_AES_256_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_RC4_128_SHA: - return "TLS_DHE_PSK_WITH_RC4_128_SHA"; - break; - case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_RC4_128_SHA: - return "TLS_RSA_PSK_WITH_RC4_128_SHA"; - break; - case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; - break; - case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; - break; - /* More TLS PSK (RFC 4785): */ - case TLS_PSK_WITH_NULL_SHA: - return "TLS_PSK_WITH_NULL_SHA"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA: - return "TLS_DHE_PSK_WITH_NULL_SHA"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA: - return "TLS_RSA_PSK_WITH_NULL_SHA"; - break; - /* Even more TLS PSK (RFC 5487): */ - case TLS_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; - break; - case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - break; - case TLS_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_PSK_WITH_NULL_SHA256: - return "TLS_PSK_WITH_NULL_SHA256"; - break; - case TLS_PSK_WITH_NULL_SHA384: - return "TLS_PSK_WITH_NULL_SHA384"; - break; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA256: - return "TLS_DHE_PSK_WITH_NULL_SHA256"; - break; - case TLS_DHE_PSK_WITH_NULL_SHA384: - return "TLS_RSA_PSK_WITH_NULL_SHA384"; - break; - case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; - break; - case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA256: - return "TLS_RSA_PSK_WITH_NULL_SHA256"; - break; - case TLS_RSA_PSK_WITH_NULL_SHA384: - return "TLS_RSA_PSK_WITH_NULL_SHA384"; - break; -#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ -#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 - /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ - case TLS_AES_128_GCM_SHA256: - return "TLS_AES_128_GCM_SHA256"; - break; - case TLS_AES_256_GCM_SHA384: - return "TLS_AES_256_GCM_SHA384"; - break; - case TLS_CHACHA20_POLY1305_SHA256: - return "TLS_CHACHA20_POLY1305_SHA256"; - break; - case TLS_AES_128_CCM_SHA256: - return "TLS_AES_128_CCM_SHA256"; - break; - case TLS_AES_128_CCM_8_SHA256: - return "TLS_AES_128_CCM_8_SHA256"; - break; - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; - break; - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; - break; -#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ + /* The first ciphers in the ciphertable are continuos. Here we do small + optimization and instead of loop directly get SSL name by cipher number. + */ + if(cipher <= SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) { + return ciphertable[cipher].name; + } + /* Iterate through the rest of the ciphers */ + for(size_t i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1; + i < NUM_OF_CIPHERS; + ++i) { + if(ciphertable[i].num == cipher) { + return ciphertable[i].name; + } } - return "TLS_NULL_WITH_NULL_NULL"; + return ciphertable[SSL_NULL_WITH_NULL_NULL].name; } #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ @@ -1087,12 +1158,14 @@ static OSStatus CopyIdentityWithLabel(char *label, (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i); err = SecIdentityCopyCertificate(identity, &cert); if(err == noErr) { + OSStatus copy_status = noErr; #if CURL_BUILD_IOS common_name = SecCertificateCopySubjectSummary(cert); #elif CURL_BUILD_MAC_10_7 - SecCertificateCopyCommonName(cert, &common_name); + copy_status = SecCertificateCopyCommonName(cert, &common_name); #endif - if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) { + if(copy_status == noErr && + CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) { CFRelease(cert); CFRelease(common_name); CFRetain(identity); @@ -1253,7 +1326,7 @@ CF_INLINE bool is_file(const char *filename) { struct_stat st; - if(filename == NULL) + if(!filename) return false; if(stat(filename, &st) == 0) @@ -1386,6 +1459,200 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } +static bool is_cipher_suite_strong(SSLCipherSuite suite_num) +{ + for(size_t i = 0; i < NUM_OF_CIPHERS; ++i) { + if(ciphertable[i].num == suite_num) { + return !ciphertable[i].weak; + } + } + /* If the cipher is not in our list, assume it is a new one + and therefore strong. Previous implementation was the same, + if cipher suite is not in the list, it was considered strong enough */ + return true; +} + +static bool is_separator(char c) +{ + /* Return whether character is a cipher list separator. */ + switch(c) { + case ' ': + case '\t': + case ':': + case ',': + case ';': + return true; + } + return false; +} + +static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data, + SSLContextRef ssl_ctx) +{ + size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; + SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + OSStatus err = noErr; + +#if CURL_BUILD_MAC + int darwinver_maj = 0, darwinver_min = 0; + + GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); +#endif /* CURL_BUILD_MAC */ + + /* Disable cipher suites that ST supports but are not safe. These ciphers + are unlikely to be used in any case since ST gives other ciphers a much + higher priority, but it's probably better that we not connect at all than + to give the user a false sense of security if the server only supports + insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ + err = SSLGetNumberSupportedCiphers(ssl_ctx, &all_ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", + err); + return CURLE_SSL_CIPHER; + } + all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!all_ciphers) { + failf(data, "SSL: Failed to allocate memory for all ciphers"); + return CURLE_OUT_OF_MEMORY; + } + allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); + if(!allowed_ciphers) { + Curl_safefree(all_ciphers); + failf(data, "SSL: Failed to allocate memory for allowed ciphers"); + return CURLE_OUT_OF_MEMORY; + } + err = SSLGetSupportedCiphers(ssl_ctx, all_ciphers, + &all_ciphers_count); + if(err != noErr) { + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + return CURLE_SSL_CIPHER; + } + for(i = 0UL ; i < all_ciphers_count ; i++) { +#if CURL_BUILD_MAC + /* There's a known bug in early versions of Mountain Lion where ST's ECC + ciphers (cipher suite 0xC001 through 0xC032) simply do not work. + Work around the problem here by disabling those ciphers if we are + running in an affected version of OS X. */ + if(darwinver_maj == 12 && darwinver_min <= 3 && + all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { + continue; + } +#endif /* CURL_BUILD_MAC */ + if(is_cipher_suite_strong(all_ciphers[i])) { + allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; + } + } + err = SSLSetEnabledCiphers(ssl_ctx, allowed_ciphers, + allowed_ciphers_count); + Curl_safefree(all_ciphers); + Curl_safefree(allowed_ciphers); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + return CURLE_OK; +} + +static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data, + SSLContextRef ssl_ctx, + const char *ciphers) +{ + size_t ciphers_count = 0; + const char *cipher_start = ciphers; + OSStatus err = noErr; + SSLCipherSuite selected_ciphers[NUM_OF_CIPHERS]; + + if(!ciphers) + return CURLE_OK; + + while(is_separator(*ciphers)) /* Skip initial separators. */ + ciphers++; + if(!*ciphers) + return CURLE_OK; + + cipher_start = ciphers; + while(*cipher_start && ciphers_count < NUM_OF_CIPHERS) { + bool cipher_found = FALSE; + size_t cipher_len = 0; + const char *cipher_end = NULL; + bool tls_name = FALSE; + + /* Skip separators */ + while(is_separator(*cipher_start)) + cipher_start++; + if(*cipher_start == '\0') { + break; + } + /* Find last position of a cipher in the ciphers string */ + cipher_end = cipher_start; + while (*cipher_end != '\0' && !is_separator(*cipher_end)) { + ++cipher_end; + } + + /* IANA cipher names start with the TLS_ or SSL_ prefix. + If the 4th symbol of the cipher is '_' we look for a cipher in the + table by its (TLS) name. + Otherwise, we try to match cipher by an alias. */ + if(cipher_start[3] == '_') { + tls_name = TRUE; + } + /* Iterate through the cipher table and look for the cipher, starting + the cipher number 0x01 because the 0x00 is not the real cipher */ + cipher_len = cipher_end - cipher_start; + for(size_t i = 1; i < NUM_OF_CIPHERS; ++i) { + const char *table_cipher_name = NULL; + if(tls_name) { + table_cipher_name = ciphertable[i].name; + } + else if(ciphertable[i].alias_name != NULL) { + table_cipher_name = ciphertable[i].alias_name; + } + else { + continue; + } + /* Compare a part of the string between separators with a cipher name + in the table and make sure we matched the whole cipher name */ + if(strncmp(cipher_start, table_cipher_name, cipher_len) == 0 + && table_cipher_name[cipher_len] == '\0') { + selected_ciphers[ciphers_count] = ciphertable[i].num; + ++ciphers_count; + cipher_found = TRUE; + break; + } + } + if(!cipher_found) { + /* It would be more human-readable if we print the wrong cipher name + but we don't want to allocate any additional memory and copy the name + into it, then add it into logs. + Also, we do not modify an original cipher list string. We just point + to positions where cipher starts and ends in the cipher list string. + The message is a bit cryptic and longer than necessary but can be + understood by humans. */ + failf(data, "SSL: cipher string \"%s\" contains unsupported cipher name" + " starting position %d and ending position %d", + ciphers, + cipher_start - ciphers, + cipher_end - ciphers); + return CURLE_SSL_CIPHER; + } + if(*cipher_end) { + cipher_start = cipher_end + 1; + } + else { + break; + } + } + /* All cipher suites in the list are found. Report to logs as-is */ + infof(data, "SSL: Setting cipher suites list \"%s\"\n", ciphers); + + err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count); + if(err != noErr) { + failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + return CURLE_SSL_CIPHER; + } + return CURLE_OK; +} static CURLcode sectransp_connect_step1(struct Curl_easy *data, struct connectdata *conn, @@ -1394,26 +1661,22 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); - const struct curl_blob *ssl_cablob = NULL; + const struct curl_blob *ssl_cablob = SSL_CONN_CONFIG(ca_info_blob); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ssl_cablob ? NULL : SSL_CONN_CONFIG(CAfile)); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; -#else - const char * const hostname = conn->host.name; - const long int port = conn->remote_port; -#endif + bool isproxy = SSL_IS_PROXY(); + const char * const hostname = SSL_HOST_NAME(); + const long int port = SSL_HOST_PORT(); #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif /* ENABLE_IPV6 */ - size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; - SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; + char *ciphers; OSStatus err = noErr; #if CURL_BUILD_MAC int darwinver_maj = 0, darwinver_min = 0; @@ -1484,21 +1747,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, break; } case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3); - break; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2); - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -1533,23 +1784,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, break; } case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -1581,23 +1818,9 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, failf(data, "Your version of the OS does not support TLSv1.3"); return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -1610,14 +1833,14 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2 #ifndef CURL_DISABLE_PROXY - && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) + && (!isproxy || !conn->bits.tunnel_proxy) #endif ) { - CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); + CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2)); + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -1788,7 +2011,8 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile); if(!(is_cert_file || is_cert_data)) { - failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); + failf(data, "SSL: can't load CA certificate file %s", + ssl_cafile ? ssl_cafile : "(blob memory)"); return CURLE_SSL_CACERT_BADFILE; } } @@ -1818,121 +2042,16 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); } - /* Disable cipher suites that ST supports but are not safe. These ciphers - are unlikely to be used in any case since ST gives other ciphers a much - higher priority, but it's probably better that we not connect at all than - to give the user a false sense of security if the server only supports - insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ - err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count); - if(err != noErr) { - failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", - err); - return CURLE_SSL_CIPHER; - } - all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); - if(!all_ciphers) { - failf(data, "SSL: Failed to allocate memory for all ciphers"); - return CURLE_OUT_OF_MEMORY; - } - allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); - if(!allowed_ciphers) { - Curl_safefree(all_ciphers); - failf(data, "SSL: Failed to allocate memory for allowed ciphers"); - return CURLE_OUT_OF_MEMORY; - } - err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers, - &all_ciphers_count); - if(err != noErr) { - Curl_safefree(all_ciphers); - Curl_safefree(allowed_ciphers); - return CURLE_SSL_CIPHER; + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { + err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers); } - for(i = 0UL ; i < all_ciphers_count ; i++) { -#if CURL_BUILD_MAC - /* There's a known bug in early versions of Mountain Lion where ST's ECC - ciphers (cipher suite 0xC001 through 0xC032) simply do not work. - Work around the problem here by disabling those ciphers if we are - running in an affected version of OS X. */ - if(darwinver_maj == 12 && darwinver_min <= 3 && - all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { - continue; - } -#endif /* CURL_BUILD_MAC */ - switch(all_ciphers[i]) { - /* Disable NULL ciphersuites: */ - case SSL_NULL_WITH_NULL_NULL: - case SSL_RSA_WITH_NULL_MD5: - case SSL_RSA_WITH_NULL_SHA: - case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ - case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ - case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ - case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ - case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ - case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ - case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ - case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ - case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ - case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ - case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ - case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ - case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ - /* Disable anonymous ciphersuites: */ - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: - case SSL_DH_anon_WITH_RC4_128_MD5: - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_anon_WITH_DES_CBC_SHA: - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - case TLS_DH_anon_WITH_AES_256_CBC_SHA: - case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ - case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ - case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ - case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ - case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ - case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ - case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ - case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ - case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ - /* Disable weak key ciphersuites: */ - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: - case SSL_RSA_WITH_DES_CBC_SHA: - case SSL_DH_DSS_WITH_DES_CBC_SHA: - case SSL_DH_RSA_WITH_DES_CBC_SHA: - case SSL_DHE_DSS_WITH_DES_CBC_SHA: - case SSL_DHE_RSA_WITH_DES_CBC_SHA: - /* Disable IDEA: */ - case SSL_RSA_WITH_IDEA_CBC_SHA: - case SSL_RSA_WITH_IDEA_CBC_MD5: - /* Disable RC4: */ - case SSL_RSA_WITH_RC4_128_MD5: - case SSL_RSA_WITH_RC4_128_SHA: - case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ - case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ - case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ - case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ - case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ - case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ - case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ - break; - default: /* enable everything else */ - allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; - break; - } + else { + err = sectransp_set_default_ciphers(data, backend->ssl_ctx); } - err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers, - allowed_ciphers_count); - Curl_safefree(all_ciphers); - Curl_safefree(allowed_ciphers); if(err != noErr) { - failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); + failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. " + "Error code: %d", err); return CURLE_SSL_CIPHER; } @@ -1941,7 +2060,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, specifically doesn't want us doing that: */ if(SSLSetSessionOption != NULL) { SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord, - !data->set.ssl.enable_beast); + !SSL_SET_OPTION(enable_beast)); SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart, data->set.ssl.falsestart); /* false start support */ } @@ -1953,7 +2072,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, size_t ssl_sessionid_len; Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, (void **)&ssl_sessionid, + if(!Curl_ssl_getsessionid(data, conn, isproxy, (void **)&ssl_sessionid, &ssl_sessionid_len, sockindex)) { /* we got a session id, use it! */ err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); @@ -1970,7 +2089,8 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, else { CURLcode result; ssl_sessionid = - aprintf("%s:%d:%d:%s:%ld", ssl_cafile, + aprintf("%s:%d:%d:%s:%ld", + ssl_cafile ? ssl_cafile : "(blob memory)", verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); ssl_sessionid_len = strlen(ssl_sessionid); @@ -1981,7 +2101,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } - result = Curl_ssl_addsessionid(data, conn, ssl_sessionid, + result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid, ssl_sessionid_len, sockindex); Curl_ssl_sessionid_unlock(data); if(result) { @@ -2021,21 +2141,21 @@ static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) /* Jump through the separators at the beginning of the certificate. */ sep_start = strstr(in, "-----"); - if(sep_start == NULL) + if(!sep_start) return 0; cert_start = strstr(sep_start + 1, "-----"); - if(cert_start == NULL) + if(!cert_start) return -1; cert_start += 5; /* Find separator after the end of the certificate. */ cert_end = strstr(cert_start, "-----"); - if(cert_end == NULL) + if(!cert_end) return -1; sep_end = strstr(cert_end + 1, "-----"); - if(sep_end == NULL) + if(!sep_end) return -1; sep_end += 5; @@ -2110,7 +2230,7 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen) } static int append_cert_to_array(struct Curl_easy *data, - unsigned char *buf, size_t buflen, + const unsigned char *buf, size_t buflen, CFMutableArrayRef array) { CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); @@ -2148,18 +2268,14 @@ static int append_cert_to_array(struct Curl_easy *data, return CURLE_OK; } -static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, - SSLContextRef ctx) +static CURLcode verify_cert_buf(struct Curl_easy *data, + const unsigned char *certbuf, size_t buflen, + SSLContextRef ctx) { int n = 0, rc; long res; - unsigned char *certbuf, *der; - size_t buflen, derlen, offset = 0; - - if(read_cert(cafile, &certbuf, &buflen) < 0) { - failf(data, "SSL: failed to read or invalid CA certificate"); - return CURLE_SSL_CACERT_BADFILE; - } + unsigned char *der; + size_t derlen, offset = 0; /* * Certbuf now contains the contents of the certificate file, which can be @@ -2172,8 +2288,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, */ CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - if(array == NULL) { - free(certbuf); + if(!array) { failf(data, "SSL: out of memory creating CA certificate array"); return CURLE_OUT_OF_MEMORY; } @@ -2187,7 +2302,6 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, */ res = pem_to_der((const char *)certbuf + offset, &der, &derlen); if(res < 0) { - free(certbuf); CFRelease(array); failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle", n, offset); @@ -2198,7 +2312,6 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, if(res == 0 && offset == 0) { /* This is not a PEM file, probably a certificate in DER format. */ rc = append_cert_to_array(data, certbuf, buflen, array); - free(certbuf); if(rc != CURLE_OK) { CFRelease(array); return rc; @@ -2207,14 +2320,12 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, } else if(res == 0) { /* No more certificates in the bundle. */ - free(certbuf); break; } rc = append_cert_to_array(data, der, derlen, array); free(der); if(rc != CURLE_OK) { - free(certbuf); CFRelease(array); return rc; } @@ -2222,7 +2333,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, SecTrustRef trust; OSStatus ret = SSLCopyPeerTrust(ctx, &trust); - if(trust == NULL) { + if(!trust) { failf(data, "SSL: error getting certificate chain"); CFRelease(array); return CURLE_PEER_FAILED_VERIFICATION; @@ -2271,6 +2382,38 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, } } +static CURLcode verify_cert(struct Curl_easy *data, const char *cafile, + const struct curl_blob *ca_info_blob, + SSLContextRef ctx) +{ + int result; + unsigned char *certbuf; + size_t buflen; + + if(ca_info_blob) { + certbuf = (unsigned char *)malloc(ca_info_blob->len + 1); + if(!certbuf) { + return CURLE_OUT_OF_MEMORY; + } + buflen = ca_info_blob->len; + memcpy(certbuf, ca_info_blob->data, ca_info_blob->len); + certbuf[ca_info_blob->len]='\0'; + } + else if(cafile) { + if(read_cert(cafile, &certbuf, &buflen) < 0) { + failf(data, "SSL: failed to read or invalid CA certificate"); + return CURLE_SSL_CACERT_BADFILE; + } + } + else + return CURLE_SSL_CACERT_BADFILE; + + result = verify_cert_buf(data, certbuf, buflen, ctx); + free(certbuf); + return result; +} + + #ifdef SECTRANSP_PINNEDPUBKEY static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SSLContextRef ctx, @@ -2295,19 +2438,19 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, do { SecTrustRef trust; OSStatus ret = SSLCopyPeerTrust(ctx, &trust); - if(ret != noErr || trust == NULL) + if(ret != noErr || !trust) break; SecKeyRef keyRef = SecTrustCopyPublicKey(trust); CFRelease(trust); - if(keyRef == NULL) + if(!keyRef) break; #ifdef SECTRANSP_PINNEDPUBKEY_V1 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); CFRelease(keyRef); - if(publicKeyBits == NULL) + if(!publicKeyBits) break; #elif SECTRANSP_PINNEDPUBKEY_V2 @@ -2315,7 +2458,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, &publicKeyBits); CFRelease(keyRef); - if(success != errSecSuccess || publicKeyBits == NULL) + if(success != errSecSuccess || !publicKeyBits) break; #endif /* SECTRANSP_PINNEDPUBKEY_V2 */ @@ -2387,12 +2530,7 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, OSStatus err; SSLCipherSuite cipher; SSLProtocol protocol = 0; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - const char * const hostname = conn->host.name; -#endif + const char * const hostname = SSL_HOST_NAME(); DEBUGASSERT(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state @@ -2411,8 +2549,10 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, /* The below is errSSLServerAuthCompleted; it's not defined in Leopard's headers */ case -9841: - if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { - CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, + if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) && + SSL_CONN_CONFIG(verifypeer)) { + CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(ca_info_blob), backend->ssl_ctx); if(result) return result; @@ -2599,8 +2739,9 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, #if CURL_BUILD_MAC_10_6 /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ case errSSLClientCertRequested: - failf(data, "The server has requested a client certificate"); - break; + failf(data, "Server requested a client certificate during the " + "handshake"); + return CURLE_SSL_CLIENTCERT; #endif #if CURL_BUILD_MAC_10_9 /* Alias for errSSLLast, end of error range */ @@ -2621,9 +2762,10 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, connssl->connecting_state = ssl_connect_3; #ifdef SECTRANSP_PINNEDPUBKEY - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { - CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx, - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + CURLcode result = + pkp_pin_peer_pubkey(data, backend->ssl_ctx, + data->set.str[STRING_SSL_PINNEDPUBLICKEY]); if(result) { failf(data, "SSL: public key does not match pinned public key!"); return result; @@ -2637,11 +2779,11 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, switch(protocol) { case kSSLProtocol2: infof(data, "SSL 2.0 connection using %s\n", - SSLCipherNameForNumber(cipher)); + TLSCipherNameForNumber(cipher)); break; case kSSLProtocol3: infof(data, "SSL 3.0 connection using %s\n", - SSLCipherNameForNumber(cipher)); + TLSCipherNameForNumber(cipher)); break; case kTLSProtocol1: infof(data, "TLS 1.0 connection using %s\n", @@ -2678,10 +2820,9 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(chosenProtocol && - !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), - 0)) { + !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -3255,8 +3396,10 @@ static ssize_t sectransp_recv(struct Curl_easy *data, /* The below is errSSLPeerAuthCompleted; it's not defined in Leopard's headers */ case -9841: - if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { - CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, + if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) && + SSL_CONN_CONFIG(verifypeer)) { + CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(ca_info_blob), backend->ssl_ctx); if(result) return result; @@ -3283,6 +3426,7 @@ static void *sectransp_get_internals(struct ssl_connect_data *connssl, const struct Curl_ssl Curl_ssl_sectransp = { { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ + SSLSUPP_CAINFO_BLOB | #ifdef SECTRANSP_PINNEDPUBKEY SSLSUPP_PINNEDPUBKEY, #else @@ -3301,6 +3445,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_cert_status_request, /* cert_status_request */ sectransp_connect, /* connect */ sectransp_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ sectransp_get_internals, /* get_internals */ sectransp_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -3309,7 +3454,9 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ sectransp_false_start, /* false_start */ - sectransp_sha256sum /* sha256sum */ + sectransp_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #ifdef __clang__ diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index b8ab7494fda..65f4f773dd6 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -135,6 +135,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, (data->verifyhost == needle->verifyhost) && (data->verifystatus == needle->verifystatus) && blobcmp(data->cert_blob, needle->cert_blob) && + blobcmp(data->ca_info_blob, needle->ca_info_blob) && Curl_safe_strcasecompare(data->CApath, needle->CApath) && Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && @@ -161,6 +162,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, dest->sessionid = source->sessionid; CLONE_BLOB(cert_blob); + CLONE_BLOB(ca_info_blob); CLONE_STRING(CApath); CLONE_STRING(CAfile); CLONE_STRING(clientcert); @@ -185,6 +187,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) Curl_safefree(sslc->cipher_list13); Curl_safefree(sslc->pinned_key); Curl_safefree(sslc->cert_blob); + Curl_safefree(sslc->ca_info_blob); Curl_safefree(sslc->curves); } @@ -315,6 +318,8 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, if(!result) Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ + else + conn->ssl[sockindex].use = FALSE; return result; } @@ -338,7 +343,9 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, /* mark this is being ssl requested from here on. */ conn->ssl[sockindex].use = TRUE; result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done); - if(!result && *done) + if(result) + conn->ssl[sockindex].use = FALSE; + else if(*done) Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ return result; } @@ -367,6 +374,7 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data) */ bool Curl_ssl_getsessionid(struct Curl_easy *data, struct connectdata *conn, + const bool isProxy, void **ssl_sessionid, size_t *idsize, /* set 0 if unknown */ int sockindex) @@ -377,7 +385,6 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data, bool no_match = TRUE; #ifndef CURL_DISABLE_PROXY - const bool isProxy = CONNECT_PROXY_SSL(); struct ssl_primary_config * const ssl_config = isProxy ? &conn->proxy_ssl_config : &conn->ssl_config; @@ -389,10 +396,15 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data, struct ssl_primary_config * const ssl_config = &conn->ssl_config; const char * const name = conn->host.name; int port = conn->remote_port; - (void)sockindex; #endif + (void)sockindex; *ssl_sessionid = NULL; +#ifdef CURL_DISABLE_PROXY + if(isProxy) + return TRUE; +#endif + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); if(!SSL_SET_OPTION(primary.sessionid)) @@ -480,6 +492,7 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid) */ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, struct connectdata *conn, + bool isProxy, void *ssl_sessionid, size_t idsize, int sockindex) @@ -492,19 +505,16 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, int conn_to_port; long *general_age; #ifndef CURL_DISABLE_PROXY - const bool isProxy = CONNECT_PROXY_SSL(); struct ssl_primary_config * const ssl_config = isProxy ? &conn->proxy_ssl_config : &conn->ssl_config; const char *hostname = isProxy ? conn->http_proxy.host.name : conn->host.name; #else - /* proxy support disabled */ - const bool isProxy = FALSE; struct ssl_primary_config * const ssl_config = &conn->ssl_config; const char *hostname = conn->host.name; - (void)sockindex; #endif + (void)sockindex; DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); clone_host = strdup(hostname); @@ -576,6 +586,25 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, return CURLE_OK; } +void Curl_ssl_associate_conn(struct Curl_easy *data, + struct connectdata *conn) +{ + if(Curl_ssl->associate_connection) { + Curl_ssl->associate_connection(data, conn, FIRSTSOCKET); + if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted) + Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET); + } +} + +void Curl_ssl_detach_conn(struct Curl_easy *data, + struct connectdata *conn) +{ + if(Curl_ssl->disassociate_connection) { + Curl_ssl->disassociate_connection(data, FIRSTSOCKET); + if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted) + Curl_ssl->disassociate_connection(data, SECONDARYSOCKET); + } +} void Curl_ssl_close_all(struct Curl_easy *data) { @@ -593,9 +622,6 @@ void Curl_ssl_close_all(struct Curl_easy *data) Curl_ssl->close_all(data); } -#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_SECTRANSP) || defined(USE_NSS) || \ - defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_BEARSSL) int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; @@ -613,16 +639,6 @@ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks) return GETSOCK_BLANK; } -#else -int Curl_ssl_getsock(struct connectdata *conn, - curl_socket_t *socks) -{ - (void)conn; - (void)socks; - return GETSOCK_BLANK; -} -/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ -#endif void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn, int sockindex) @@ -1170,6 +1186,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_easy *data, return Curl_ssl->connect_nonblocking(data, conn, sockindex, done); } +static int multissl_getsock(struct connectdata *conn, curl_socket_t *socks) +{ + if(multissl_setup(NULL)) + return 0; + return Curl_ssl->getsock(conn, socks); +} + static void *multissl_get_internals(struct ssl_connect_data *connssl, CURLINFO info) { @@ -1201,6 +1224,7 @@ static const struct Curl_ssl Curl_ssl_multi = { Curl_none_cert_status_request, /* cert_status_request */ multissl_connect, /* connect */ multissl_connect_nonblocking, /* connect_nonblocking */ + multissl_getsock, /* getsock */ multissl_get_internals, /* get_internals */ multissl_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -1209,7 +1233,9 @@ static const struct Curl_ssl Curl_ssl_multi = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - NULL /* sha256sum */ + NULL, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; const struct Curl_ssl *Curl_ssl = @@ -1227,6 +1253,8 @@ const struct Curl_ssl *Curl_ssl = &Curl_ssl_mbedtls; #elif defined(USE_NSS) &Curl_ssl_nss; +#elif defined(USE_RUSTLS) + &Curl_ssl_rustls; #elif defined(USE_OPENSSL) &Curl_ssl_openssl; #elif defined(USE_SCHANNEL) @@ -1269,6 +1297,9 @@ static const struct Curl_ssl *available_backends[] = { #endif #if defined(USE_BEARSSL) &Curl_ssl_bearssl, +#endif +#if defined(USE_RUSTLS) + &Curl_ssl_rustls, #endif NULL }; diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 9666682ec2c..7f93e7aedb2 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -32,6 +32,7 @@ struct ssl_connect_data; #define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */ #define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */ #define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */ +#define SSLSUPP_CAINFO_BLOB (1<<6) struct Curl_ssl { /* @@ -62,6 +63,14 @@ struct Curl_ssl { CURLcode (*connect_nonblocking)(struct Curl_easy *data, struct connectdata *conn, int sockindex, bool *done); + + /* If the SSL backend wants to read or write on this connection during a + handshake, set socks[0] to the connection's FIRSTSOCKET, and return + a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or + GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK. + Mandatory. */ + int (*getsock)(struct connectdata *conn, curl_socket_t *socks); + void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); void (*close_one)(struct Curl_easy *data, struct connectdata *conn, int sockindex); @@ -75,6 +84,11 @@ struct Curl_ssl { bool (*false_start)(void); CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, unsigned char *sha256sum, size_t sha256sumlen); + + void (*associate_connection)(struct Curl_easy *data, + struct connectdata *conn, + int sockindex); + void (*disassociate_connection)(struct Curl_easy *data, int sockindex); }; #ifdef USE_SSL @@ -108,6 +122,7 @@ bool Curl_ssl_tls13_ciphersuites(void); #include "mbedtls.h" /* mbedTLS versions */ #include "mesalink.h" /* MesaLink versions */ #include "bearssl.h" /* BearSSL versions */ +#include "rustls.h" /* rustls versions */ #ifndef MAX_PINNED_PUBKEY_SIZE #define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ @@ -117,9 +132,11 @@ bool Curl_ssl_tls13_ciphersuites(void); #define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ #endif -/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +/* see https://www.iana.org/assignments/tls-extensiontype-values/ */ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" +#define ALPN_H2_LENGTH 2 +#define ALPN_H2 "h2" /* set of helper macros for the backends to access the correct fields. For the proxy or for the remote host - to properly support HTTPS proxy */ @@ -139,9 +156,11 @@ bool Curl_ssl_tls13_ciphersuites(void); (SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name) #define SSL_HOST_DISPNAME() \ (SSL_IS_PROXY() ? conn->http_proxy.host.dispname : conn->host.dispname) +#define SSL_HOST_PORT() \ + (SSL_IS_PROXY() ? conn->port : conn->remote_port) #define SSL_PINNED_PUB_KEY() (SSL_IS_PROXY() \ ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] \ - : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) + : data->set.str[STRING_SSL_PINNEDPUBLICKEY]) #else #define SSL_IS_PROXY() FALSE #define SSL_SET_OPTION(var) data->set.ssl.var @@ -149,8 +168,9 @@ bool Curl_ssl_tls13_ciphersuites(void); #define SSL_CONN_CONFIG(var) conn->ssl_config.var #define SSL_HOST_NAME() conn->host.name #define SSL_HOST_DISPNAME() conn->host.dispname +#define SSL_HOST_PORT() conn->remote_port #define SSL_PINNED_PUB_KEY() \ - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG] + data->set.str[STRING_SSL_PINNEDPUBLICKEY] #endif bool Curl_ssl_config_matches(struct ssl_primary_config *data, @@ -158,6 +178,10 @@ bool Curl_ssl_config_matches(struct ssl_primary_config *data, bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, struct ssl_primary_config *dest); void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc); +/* An implementation of the getsock field of Curl_ssl that relies + on the ssl_connect_state enum. Asks for read or write depending + on whether conn->state is ssl_connect_2_reading or + ssl_connect_2_writing. */ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks); int Curl_ssl_backend(void); @@ -222,6 +246,7 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data); */ bool Curl_ssl_getsessionid(struct Curl_easy *data, struct connectdata *conn, + const bool isproxy, void **ssl_sessionid, size_t *idsize, /* set 0 if unknown */ int sockindex); @@ -232,6 +257,7 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data, */ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, struct connectdata *conn, + const bool isProxy, void *ssl_sessionid, size_t idsize, int sockindex); @@ -262,6 +288,11 @@ bool Curl_ssl_cert_status_request(void); bool Curl_ssl_false_start(void); +void Curl_ssl_associate_conn(struct Curl_easy *data, + struct connectdata *conn); +void Curl_ssl_detach_conn(struct Curl_easy *data, + struct connectdata *conn); + #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ #else /* if not USE_SSL */ @@ -288,6 +319,8 @@ bool Curl_ssl_false_start(void); #define Curl_ssl_cert_status_request() FALSE #define Curl_ssl_false_start() FALSE #define Curl_ssl_tls13_ciphersuites() FALSE +#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt +#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt #endif #endif /* HEADER_CURL_VTLS_H */ diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index e1fa4592659..60e27e36625 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -47,16 +47,6 @@ #endif #endif -/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in - options.h, but is only seen in >= 3.6.6 since that's when they started - disabling SSLv3 by default. */ -#ifndef WOLFSSL_ALLOW_SSLV3 -#if (LIBWOLFSSL_VERSION_HEX < 0x03006006) || \ - defined(HAVE_WOLFSSLV3_CLIENT_METHOD) -#define WOLFSSL_ALLOW_SSLV3 -#endif -#endif - #include #include "urldata.h" @@ -285,18 +275,6 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, failf(data, "wolfSSL: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; #endif - case CURL_SSLVERSION_SSLv3: -#ifdef WOLFSSL_ALLOW_SSLV3 - req_method = SSLv3_client_method(); - use_sni(FALSE); -#else - failf(data, "wolfSSL does not support SSLv3"); - return CURLE_NOT_BUILT_IN; -#endif - break; - case CURL_SSLVERSION_SSLv2: - failf(data, "wolfSSL does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; @@ -418,12 +396,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - const char * const hostname = conn->host.name; -#endif + const char * const hostname = SSL_HOST_NAME(); size_t hostname_len = strlen(hostname); if((hostname_len < USHRT_MAX) && (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && @@ -474,10 +447,10 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, /* wolfSSL's ALPN protocol name list format is a comma separated string of protocols in descending order of preference, eg: "h2,http/1.1" */ -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2) { - strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); - infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2) { + strcpy(protocols + strlen(protocols), ALPN_H2 ","); + infof(data, "ALPN, offering %s\n", ALPN_H2); } #endif @@ -516,7 +489,9 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) { + if(!Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, + &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(backend->handle, ssl_sessionid)) { char error_buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -550,20 +525,9 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, int ret = -1; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; -#ifndef CURL_DISABLE_PROXY - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; - const char * const dispname = SSL_IS_PROXY() ? - conn->http_proxy.host.dispname : conn->host.dispname; - const char * const pinnedpubkey = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; -#else - const char * const hostname = conn->host.name; - const char * const dispname = conn->host.dispname; - const char * const pinnedpubkey = - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; -#endif + const char * const hostname = SSL_HOST_NAME(); + const char * const dispname = SSL_HOST_DISPNAME(); + const char * const pinnedpubkey = SSL_PINNED_PUB_KEY(); conn->recv[sockindex] = wolfssl_recv; conn->send[sockindex] = wolfssl_send; @@ -723,11 +687,10 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(protocol_len == ALPN_HTTP_1_1_LENGTH && !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) conn->negnpn = CURL_HTTP_VERSION_1_1; -#ifdef USE_NGHTTP2 - else if(data->set.httpversion >= CURL_HTTP_VERSION_2 && - protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN)) +#ifdef USE_HTTP2 + else if(data->state.httpwant >= CURL_HTTP_VERSION_2 && + protocol_len == ALPN_H2_LENGTH && + !memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH)) conn->negnpn = CURL_HTTP_VERSION_2; #endif else @@ -770,32 +733,33 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn, if(SSL_SET_OPTION(primary.sessionid)) { bool incache; - SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; - - our_ssl_sessionid = SSL_get_session(backend->handle); - - Curl_ssl_sessionid_lock(data); - incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, - sockindex)); - if(incache) { - if(old_ssl_sessionid != our_ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(data, old_ssl_sessionid); - incache = FALSE; + SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle); + bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE; + + if(our_ssl_sessionid) { + Curl_ssl_sessionid_lock(data); + incache = !(Curl_ssl_getsessionid(data, conn, isproxy, + &old_ssl_sessionid, NULL, sockindex)); + if(incache) { + if(old_ssl_sessionid != our_ssl_sessionid) { + infof(data, "old SSL session ID is stale, removing\n"); + Curl_ssl_delsessionid(data, old_ssl_sessionid); + incache = FALSE; + } } - } - if(!incache) { - result = Curl_ssl_addsessionid(data, conn, our_ssl_sessionid, - 0 /* unknown size */, sockindex); - if(result) { - Curl_ssl_sessionid_unlock(data); - failf(data, "failed to store ssl session"); - return result; + if(!incache) { + result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, + 0, sockindex); + if(result) { + Curl_ssl_sessionid_unlock(data); + failf(data, "failed to store ssl session"); + return result; + } } + Curl_ssl_sessionid_unlock(data); } - Curl_ssl_sessionid_unlock(data); } connssl->connecting_state = ssl_connect_done; @@ -817,7 +781,7 @@ static ssize_t wolfssl_send(struct Curl_easy *data, int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; int rc = SSL_write(backend->handle, mem, memlen); - if(rc < 0) { + if(rc <= 0) { int err = SSL_get_error(backend->handle, rc); switch(err) { @@ -1152,6 +1116,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = { Curl_none_cert_status_request, /* cert_status_request */ wolfssl_connect, /* connect */ wolfssl_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ wolfssl_get_internals, /* get_internals */ wolfssl_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -1160,7 +1125,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - wolfssl_sha256sum /* sha256sum */ + wolfssl_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif diff --git a/lib/x509asn1.c b/lib/x509asn1.c index f29aa05b874..281c97248b2 100644 --- a/lib/x509asn1.c +++ b/lib/x509asn1.c @@ -1145,10 +1145,8 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, int matched = -1; size_t addrlen = (size_t) -1; ssize_t len; - const char *const hostname = SSL_IS_PROXY()? - conn->http_proxy.host.name : conn->host.name; - const char *const dispname = SSL_IS_PROXY()? - conn->http_proxy.host.dispname : conn->host.dispname; + const char * const hostname = SSL_HOST_NAME(); + const char * const dispname = SSL_HOST_DISPNAME(); #ifdef ENABLE_IPV6 struct in6_addr addr; #else From e609afeb5f4385755a6d0f2fdb45fcdfb0a01b7a Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 27 May 2021 14:14:49 -0400 Subject: [PATCH 0528/1519] WriteBasicConfigVersion supports version strings such as 21.07.04 Fixes #22207 --- .../BasicConfigVersion-ExactVersion.cmake.in | 37 +- ...sicConfigVersion-SameMajorVersion.cmake.in | 3 + ...sicConfigVersion-SameMinorVersion.cmake.in | 14 + .../LeadingZeroes.cmake | 898 ++++++++++++++++++ .../RunCMakeTest.cmake | 1 + .../RunCMake/find_package/RunCMakeTest.cmake | 1 + .../VersionRangeCfgConfigVersion.cmake | 6 +- .../find_package/VersionRangeConfig02.cmake | 23 + 8 files changed, 977 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake create mode 100644 Tests/RunCMake/find_package/VersionRangeConfig02.cmake diff --git a/Modules/BasicConfigVersion-ExactVersion.cmake.in b/Modules/BasicConfigVersion-ExactVersion.cmake.in index 3507a2283cc..c8d26950070 100644 --- a/Modules/BasicConfigVersion-ExactVersion.cmake.in +++ b/Modules/BasicConfigVersion-ExactVersion.cmake.in @@ -18,14 +18,43 @@ endif() set(PACKAGE_VERSION "@CVF_VERSION@") -if("@CVF_VERSION@" MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\.") # strip the tweak version - set(CVF_VERSION_NO_TWEAK "${CMAKE_MATCH_1}") +if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") # strip the tweak version + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CVF_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CVF_VERSION_PATCH "${CMAKE_MATCH_3}") + + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + if(NOT CVF_VERSION_MINOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MINOR "${CVF_VERSION_MINOR}") + endif() + if(NOT CVF_VERSION_PATCH VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_PATCH "${CVF_VERSION_PATCH}") + endif() + + set(CVF_VERSION_NO_TWEAK "${CVF_VERSION_MAJOR}.${CVF_VERSION_MINOR}.${CVF_VERSION_PATCH}") else() set(CVF_VERSION_NO_TWEAK "@CVF_VERSION@") endif() -if(PACKAGE_FIND_VERSION MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\.") # strip the tweak version - set(REQUESTED_VERSION_NO_TWEAK "${CMAKE_MATCH_1}") +if(PACKAGE_FIND_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") # strip the tweak version + set(REQUESTED_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(REQUESTED_VERSION_MINOR "${CMAKE_MATCH_2}") + set(REQUESTED_VERSION_PATCH "${CMAKE_MATCH_3}") + + if(NOT REQUESTED_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_MAJOR "${REQUESTED_VERSION_MAJOR}") + endif() + if(NOT REQUESTED_VERSION_MINOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_MINOR "${REQUESTED_VERSION_MINOR}") + endif() + if(NOT REQUESTED_VERSION_PATCH VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_PATCH "${REQUESTED_VERSION_PATCH}") + endif() + + set(REQUESTED_VERSION_NO_TWEAK + "${REQUESTED_VERSION_MAJOR}.${REQUESTED_VERSION_MINOR}.${REQUESTED_VERSION_PATCH}") else() set(REQUESTED_VERSION_NO_TWEAK "${PACKAGE_FIND_VERSION}") endif() diff --git a/Modules/BasicConfigVersion-SameMajorVersion.cmake.in b/Modules/BasicConfigVersion-SameMajorVersion.cmake.in index dc04e54cd0d..cf73f603d42 100644 --- a/Modules/BasicConfigVersion-SameMajorVersion.cmake.in +++ b/Modules/BasicConfigVersion-SameMajorVersion.cmake.in @@ -17,6 +17,9 @@ else() if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.") set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() else() set(CVF_VERSION_MAJOR "@CVF_VERSION@") endif() diff --git a/Modules/BasicConfigVersion-SameMinorVersion.cmake.in b/Modules/BasicConfigVersion-SameMinorVersion.cmake.in index 9bb2efcfca2..ef21df60f93 100644 --- a/Modules/BasicConfigVersion-SameMinorVersion.cmake.in +++ b/Modules/BasicConfigVersion-SameMinorVersion.cmake.in @@ -19,6 +19,13 @@ else() if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.([0-9]+)") set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") set(CVF_VERSION_MINOR "${CMAKE_MATCH_2}") + + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + if(NOT CVF_VERSION_MINOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MINOR "${CVF_VERSION_MINOR}") + endif() else() set(CVF_VERSION_MAJOR "@CVF_VERSION@") set(CVF_VERSION_MINOR "") @@ -44,6 +51,13 @@ else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() else() + if(NOT PACKAGE_FIND_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" PACKAGE_FIND_VERSION_MAJOR "${PACKAGE_FIND_VERSION_MAJOR}") + endif() + if(NOT PACKAGE_FIND_VERSION_MINOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" PACKAGE_FIND_VERSION_MINOR "${PACKAGE_FIND_VERSION_MINOR}") + endif() + if((PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) AND (PACKAGE_FIND_VERSION_MINOR STREQUAL CVF_VERSION_MINOR)) set(PACKAGE_VERSION_COMPATIBLE TRUE) diff --git a/Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake b/Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake new file mode 100644 index 00000000000..9f4674c2e0e --- /dev/null +++ b/Tests/RunCMake/WriteBasicConfigVersionFile/LeadingZeroes.cmake @@ -0,0 +1,898 @@ +# Hard-code architecture for test without a real compiler. +set(CMAKE_SIZEOF_VOID_P 4) + +include(WriteBasicConfigVersionFile) + +set(COMPATIBILITIES AnyNewerVersion + SameMajorVersion + SameMinorVersion + ExactVersion + ) + +function(TEST_WRITE_BASIC_CONFIG_VERSION_FILE_PREPARE _version_installed) + set(_same_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) + set(_no_CMAKE_SIZEOF_VOID_P "") + math(EXPR _diff_CMAKE_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P} + 1") + foreach(_compat ${COMPATIBILITIES}) + set(_pkg ${_compat}${_version_installed}) + string(REPLACE "." "" _pkg ${_pkg}) + set(_filename "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}ConfigVersion.cmake") + set(_filename_novoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}NoVoidConfigVersion.cmake") + set(_filename_diffvoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}DiffVoidConfigVersion.cmake") + + set(CMAKE_SIZEOF_VOID_P ${_same_CMAKE_SIZEOF_VOID_P}) + write_basic_config_version_file("${_filename}" + VERSION ${_version_installed} + COMPATIBILITY ${_compat}) + + # Test that an empty CMAKE_SIZEOF_VOID_P is accepted: + set(CMAKE_SIZEOF_VOID_P ${_no_CMAKE_SIZEOF_VOID_P}) + write_basic_config_version_file("${_filename_novoid}" + VERSION ${_version_installed} + COMPATIBILITY ${_compat}) + + # Test that a different CMAKE_SIZEOF_VOID_P results in + # PACKAGE_VERSION_UNSUITABLE + set(CMAKE_SIZEOF_VOID_P ${_diff_CMAKE_SIZEOF_VOID_P}) + write_basic_config_version_file("${_filename_diffvoid}" + VERSION ${_version_installed} + COMPATIBILITY ${_compat}) + endforeach() +endfunction() + +macro(TEST_WRITE_BASIC_CONFIG_VERSION_FILE_CHECK _filename) + include("${_filename}") + + message(STATUS "_expected_compatible: ${_expected_compatible}") + message(STATUS "_expected_unsuitable: ${_expected_unsuitable}") + if(_expected_compatible AND NOT PACKAGE_VERSION_COMPATIBLE) + message(SEND_ERROR "Did not find package with version ${_version_installed} (${_version_requested} was requested)!") + elseif(NOT _expected_compatible AND PACKAGE_VERSION_COMPATIBLE) + message(SEND_ERROR "Found package with version ${_version_installed}, but ${_version_requested} was requested!") + endif() + + if(${_expected_unsuitable} AND NOT PACKAGE_VERSION_UNSUITABLE) + message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, although it should not be!") + elseif(NOT ${_expected_unsuitable} AND PACKAGE_VERSION_UNSUITABLE) + message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE not set, although it should be!") + endif() + + unset(PACKAGE_VERSION_COMPATIBLE) + unset(PACKAGE_VERSION_EXACT) + unset(PACKAGE_VERSION_UNSUITABLE) +endmacro() + +function(TEST_WRITE_BASIC_CONFIG_VERSION_FILE _version_installed + _version_requested + _expected_compatible_AnyNewerVersion + _expected_compatible_SameMajorVersion + _expected_compatible_SameMinorVersion + _expected_compatible_ExactVersion) + if("${_version_requested}" MATCHES [[^([0-9]+(\.[0-9]+)*)\.\.\.(<)?([0-9]+(\.[0-9]+)*)$]]) + set (_compatibilities ${COMPATIBILITIES}) + # ExactVersion must not be tested + list(POP_BACK _compatibilities) + set(PACKAGE_FIND_VERSION_RANGE TRUE) + set(PACKAGE_FIND_VERSION_RANGE_MIN INCLUDE) + if ("${CMAKE_MATCH_3}" STREQUAL "<") + set(PACKAGE_FIND_VERSION_RANGE_MAX EXCLUDE) + else() + set(PACKAGE_FIND_VERSION_RANGE_MAX INCLUDE) + endif() + set(PACKAGE_FIND_VERSION_MIN "${CMAKE_MATCH_1}") + set(PACKAGE_FIND_VERSION_MAX "${CMAKE_MATCH_4}") + if("${PACKAGE_FIND_VERSION_MIN}" MATCHES [[(^([0-9]+)(\.([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?)?)?$]]) + set(PACKAGE_FIND_VERSION_MIN_MAJOR "${CMAKE_MATCH_2}") + set(PACKAGE_FIND_VERSION_MIN_MINOR "${CMAKE_MATCH_4}") + set(PACKAGE_FIND_VERSION_MIN_PATCH "${CMAKE_MATCH_6}") + set(PACKAGE_FIND_VERSION_MIN_TWEAK "${CMAKE_MATCH_8}") + else() + message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version range") + endif() + set(PACKAGE_FIND_VERSION "${PACKAGE_FIND_VERSION_MIN}") + set(PACKAGE_FIND_VERSION_MAJOR "${PACKAGE_FIND_VERSION_MIN_MAJOR}") + set(PACKAGE_FIND_VERSION_MINOR "${PACKAGE_FIND_VERSION_MIN_MINOR}") + set(PACKAGE_FIND_VERSION_PATCH "${PACKAGE_FIND_VERSION_MIN_PATCH}") + set(PACKAGE_FIND_VERSION_TWEAK "${PACKAGE_FIND_VERSION_MIN_TWEAK}") + if("${PACKAGE_FIND_VERSION_MAX}" MATCHES [[(^([0-9]+)(\.([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?)?)?$]]) + set(PACKAGE_FIND_VERSION_MAX_MAJOR "${CMAKE_MATCH_2}") + set(PACKAGE_FIND_VERSION_MAX_MINOR "${CMAKE_MATCH_4}") + set(PACKAGE_FIND_VERSION_MAX_PATCH "${CMAKE_MATCH_6}") + set(PACKAGE_FIND_VERSION_MAX_TWEAK "${CMAKE_MATCH_8}") + else() + message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version range") + endif() + else() + set (_compatibilities ${COMPATIBILITIES}) + set(PACKAGE_FIND_VERSION ${_version_requested}) + if("${PACKAGE_FIND_VERSION}" MATCHES [[(^([0-9]+)(\.([0-9]+)(\.([0-9]+)(\.([0-9]+))?)?)?)?$]]) + set(PACKAGE_FIND_VERSION_MAJOR "${CMAKE_MATCH_2}") + set(PACKAGE_FIND_VERSION_MINOR "${CMAKE_MATCH_4}") + set(PACKAGE_FIND_VERSION_PATCH "${CMAKE_MATCH_6}") + set(PACKAGE_FIND_VERSION_TWEAK "${CMAKE_MATCH_8}") + else() + message(FATAL_ERROR "_version_requested (${_version_requested}) should be a version number") + endif() + + endif() + + unset(PACKAGE_VERSION_COMPATIBLE) + unset(PACKAGE_VERSION_EXACT) + unset(PACKAGE_VERSION_UNSUITABLE) + + foreach(_compat ${_compatibilities}) + set(_pkg ${_compat}${_version_installed}) + string(REPLACE "." "" _pkg ${_pkg}) + set(_filename "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}ConfigVersion.cmake") + set(_filename_novoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}NoVoidConfigVersion.cmake") + set(_filename_diffvoid "${CMAKE_CURRENT_BINARY_DIR}/${_pkg}DiffVoidConfigVersion.cmake") + + set(_expected_compatible ${_expected_compatible_${_compat}}) + + # Test "normal" version + set(_expected_unsuitable 0) + message(STATUS "TEST write_basic_config_version_file(VERSION ${_version_installed} \ +COMPATIBILITY ${_compat}) vs. ${_version_requested} \ +(expected compatible = ${_expected_compatible}, unsuitable = ${_expected_unsuitable})") + test_write_basic_config_version_file_check("${_filename}") + + # test empty CMAKE_SIZEOF_VOID_P version: + set(_expected_unsuitable 0) + message(STATUS "TEST write_basic_config_version_file(VERSION ${_version_installed} \ +COMPATIBILITY ${_compat}) vs. ${_version_requested} (no CMAKE_SIZEOF_VOID_P) \ +(expected compatible = ${_expected_compatible}, unsuitable = ${_expected_unsuitable})") + test_write_basic_config_version_file_check("${_filename_novoid}") + + # test different CMAKE_SIZEOF_VOID_P version: + set(_expected_unsuitable 1) + message(STATUS "TEST write_basic_config_version_file(VERSION ${_version_installed} \ +COMPATIBILITY ${_compat}) vs. ${_version_requested} (different CMAKE_SIZEOF_VOID_P) \ +(expected compatible = ${_expected_compatible}, unsuitable = ${_expected_unsuitable})") + test_write_basic_config_version_file_check("${_filename_diffvoid}") + + endforeach() +endfunction() + + +test_write_basic_config_version_file_prepare(4) +test_write_basic_config_version_file_prepare(4.05) +test_write_basic_config_version_file_prepare(4.5.06) +test_write_basic_config_version_file_prepare(4.05.06.007) + +# AnyNewerVersion +# | SameMajorVersion +# | | SameMinorVersion +# | | | ExactVersion +# | | | | +test_write_basic_config_version_file(4.05 0 1 0 0 0) # Request 0 +test_write_basic_config_version_file(4.05 2 1 0 0 0) # Request [older major] +test_write_basic_config_version_file(4.05 4 1 1 0 0) # Request [same major] +test_write_basic_config_version_file(4.05 9 0 0 0 0) # Request [newer major] + +test_write_basic_config_version_file(4.05 0.0 1 0 0 0) # Request 0.0 +test_write_basic_config_version_file(4.05 0.2 1 0 0 0) # Request 0.[older minor] +test_write_basic_config_version_file(4.05 0.5 1 0 0 0) # Request 0.[same minor] +test_write_basic_config_version_file(4.05 0.9 1 0 0 0) # Request 0.[newer minor] +test_write_basic_config_version_file(4.05 2.0 1 0 0 0) # Request [older major].0 +test_write_basic_config_version_file(4.05 2.2 1 0 0 0) # Request [older major].[older minor] +test_write_basic_config_version_file(4.05 2.5 1 0 0 0) # Request [older major].[same minor] +test_write_basic_config_version_file(4.05 2.9 1 0 0 0) # Request [older major].[newer minor] +test_write_basic_config_version_file(4.05 4.0 1 1 0 0) # Request [same major].0 +test_write_basic_config_version_file(4.05 4.2 1 1 0 0) # Request [same major].[older minor] +test_write_basic_config_version_file(4.05 4.05 1 1 1 1) # Request [same major].[same minor] +test_write_basic_config_version_file(4.05 4.9 0 0 0 0) # Request [same major].[newer minor] +test_write_basic_config_version_file(4.05 9.0 0 0 0 0) # Request [newer major].0 +test_write_basic_config_version_file(4.05 9.1 0 0 0 0) # Request [newer major].[older minor] +test_write_basic_config_version_file(4.05 9.5 0 0 0 0) # Request [newer major].[same minor] +test_write_basic_config_version_file(4.05 9.9 0 0 0 0) # Request [newer major].[newer minor] + +test_write_basic_config_version_file(4.05 0.0.0 1 0 0 0) # Request 0.0.0 +test_write_basic_config_version_file(4.05 0.0.9 1 0 0 0) # Request 0.0.[newer patch] +test_write_basic_config_version_file(4.05 0.2.0 1 0 0 0) # Request 0.[older minor].0 +test_write_basic_config_version_file(4.05 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch] +test_write_basic_config_version_file(4.05 0.5.0 1 0 0 0) # Request 0.[same minor].0 +test_write_basic_config_version_file(4.05 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch] +test_write_basic_config_version_file(4.05 0.9.0 1 0 0 0) # Request 0.[newer minor].0 +test_write_basic_config_version_file(4.05 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch] +test_write_basic_config_version_file(4.05 2.0.0 1 0 0 0) # Request [older major].0.0 +test_write_basic_config_version_file(4.05 2.0.9 1 0 0 0) # Request [older major].0.[newer patch] +test_write_basic_config_version_file(4.05 2.2.0 1 0 0 0) # Request [older major].[older minor].0 +test_write_basic_config_version_file(4.05 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch] +test_write_basic_config_version_file(4.05 2.5.0 1 0 0 0) # Request [older major].[same minor].0 +test_write_basic_config_version_file(4.05 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch] +test_write_basic_config_version_file(4.05 2.9.0 1 0 0 0) # Request [older major].[newer minor].0 +test_write_basic_config_version_file(4.05 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch] +test_write_basic_config_version_file(4.05 4.0.0 1 1 0 0) # Request [same major].0.0 +test_write_basic_config_version_file(4.05 4.0.9 1 1 0 0) # Request [same major].0.[newer patch] +test_write_basic_config_version_file(4.05 4.2.0 1 1 0 0) # Request [same major].[older minor].0 +test_write_basic_config_version_file(4.05 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch] +test_write_basic_config_version_file(4.05 4.05.0 1 1 1 0) # Request [same major].[same minor].0 +test_write_basic_config_version_file(4.05 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch] +test_write_basic_config_version_file(4.05 4.9.0 0 0 0 0) # Request [same major].[newer minor].0 +test_write_basic_config_version_file(4.05 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch] +test_write_basic_config_version_file(4.05 9.0.0 0 0 0 0) # Request [newer major].0.0 +test_write_basic_config_version_file(4.05 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch] +test_write_basic_config_version_file(4.05 9.2.0 0 0 0 0) # Request [newer major].[older minor].0 +test_write_basic_config_version_file(4.05 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch] +test_write_basic_config_version_file(4.05 9.5.0 0 0 0 0) # Request [newer major].[same minor].0 +test_write_basic_config_version_file(4.05 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch] +test_write_basic_config_version_file(4.05 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0 +test_write_basic_config_version_file(4.05 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch] + +test_write_basic_config_version_file(4.05 0.0.0.0 1 0 0 0) # Request 0.0.0.0 +test_write_basic_config_version_file(4.05 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak] +test_write_basic_config_version_file(4.05 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0 +test_write_basic_config_version_file(4.05 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0 +test_write_basic_config_version_file(4.05 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0 +test_write_basic_config_version_file(4.05 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0 +test_write_basic_config_version_file(4.05 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 2.0.0.0 1 0 0 0) # Request [older major].0.0.0 +test_write_basic_config_version_file(4.05 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak] +test_write_basic_config_version_file(4.05 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0 +test_write_basic_config_version_file(4.05 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0 +test_write_basic_config_version_file(4.05 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0 +test_write_basic_config_version_file(4.05 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0 +test_write_basic_config_version_file(4.05 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 4.0.0.0 1 1 0 0) # Request [same major].0.0.0 +test_write_basic_config_version_file(4.05 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak] +test_write_basic_config_version_file(4.05 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0 +test_write_basic_config_version_file(4.05 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0 +test_write_basic_config_version_file(4.05 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0 +test_write_basic_config_version_file(4.05 4.5.0.9 0 0 0 0) # Request [same major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0 +test_write_basic_config_version_file(4.05 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0 +test_write_basic_config_version_file(4.05 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak] +test_write_basic_config_version_file(4.05 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0 +test_write_basic_config_version_file(4.05 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0 +test_write_basic_config_version_file(4.05 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0 +test_write_basic_config_version_file(4.05 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0 +test_write_basic_config_version_file(4.05 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak] + + +test_write_basic_config_version_file(4.5.06 0 1 0 0 0) # Request 0 +test_write_basic_config_version_file(4.5.06 2 1 0 0 0) # Request [older major] +test_write_basic_config_version_file(4.5.06 4 1 1 0 0) # Request [same major] +test_write_basic_config_version_file(4.5.06 9 0 0 0 0) # Request [newer major] + +test_write_basic_config_version_file(4.5.06 0.0 1 0 0 0) # Request 0.0 +test_write_basic_config_version_file(4.5.06 0.2 1 0 0 0) # Request 0.[older minor] +test_write_basic_config_version_file(4.5.06 0.5 1 0 0 0) # Request 0.[same minor] +test_write_basic_config_version_file(4.5.06 0.9 1 0 0 0) # Request 0.[newer minor] +test_write_basic_config_version_file(4.5.06 2.0 1 0 0 0) # Request [older major].0 +test_write_basic_config_version_file(4.5.06 2.2 1 0 0 0) # Request [older major].[older minor] +test_write_basic_config_version_file(4.5.06 2.5 1 0 0 0) # Request [older major].[same minor] +test_write_basic_config_version_file(4.5.06 2.9 1 0 0 0) # Request [older major].[newer minor] +test_write_basic_config_version_file(4.5.06 4.0 1 1 0 0) # Request [same major].0 +test_write_basic_config_version_file(4.5.06 4.2 1 1 0 0) # Request [same major].[older minor] +test_write_basic_config_version_file(4.5.06 4.5 1 1 1 0) # Request [same major].[same minor] +test_write_basic_config_version_file(4.5.06 4.9 0 0 0 0) # Request [same major].[newer minor] +test_write_basic_config_version_file(4.5.06 9.0 0 0 0 0) # Request [newer major].0 +test_write_basic_config_version_file(4.5.06 9.1 0 0 0 0) # Request [newer major].[older minor] +test_write_basic_config_version_file(4.5.06 9.5 0 0 0 0) # Request [newer major].[same minor] +test_write_basic_config_version_file(4.5.06 9.9 0 0 0 0) # Request [newer major].[newer minor] + +test_write_basic_config_version_file(4.5.06 0.0.0 1 0 0 0) # Request 0.0.0 +test_write_basic_config_version_file(4.5.06 0.0.2 1 0 0 0) # Request 0.0.[older patch] +test_write_basic_config_version_file(4.5.06 0.0.6 1 0 0 0) # Request 0.0.[same patch] +test_write_basic_config_version_file(4.5.06 0.0.9 1 0 0 0) # Request 0.0.[newer patch] +test_write_basic_config_version_file(4.5.06 0.2.0 1 0 0 0) # Request 0.[older minor].0 +test_write_basic_config_version_file(4.5.06 0.2.2 1 0 0 0) # Request 0.[older minor].[older patch] +test_write_basic_config_version_file(4.5.06 0.2.6 1 0 0 0) # Request 0.[older minor].[same patch] +test_write_basic_config_version_file(4.5.06 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch] +test_write_basic_config_version_file(4.5.06 0.5.0 1 0 0 0) # Request 0.[same minor].0 +test_write_basic_config_version_file(4.5.06 0.5.2 1 0 0 0) # Request 0.[same minor].[older patch] +test_write_basic_config_version_file(4.5.06 0.5.6 1 0 0 0) # Request 0.[same minor].[same patch] +test_write_basic_config_version_file(4.5.06 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch] +test_write_basic_config_version_file(4.5.06 0.9.0 1 0 0 0) # Request 0.[newer minor].0 +test_write_basic_config_version_file(4.5.06 0.9.2 1 0 0 0) # Request 0.[newer minor].[older patch] +test_write_basic_config_version_file(4.5.06 0.9.6 1 0 0 0) # Request 0.[newer minor].[same patch] +test_write_basic_config_version_file(4.5.06 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch] +test_write_basic_config_version_file(4.5.06 2.0.0 1 0 0 0) # Request [older major].0.0 +test_write_basic_config_version_file(4.5.06 2.0.2 1 0 0 0) # Request [older major].0.[older patch] +test_write_basic_config_version_file(4.5.06 2.0.6 1 0 0 0) # Request [older major].0.[same patch] +test_write_basic_config_version_file(4.5.06 2.0.9 1 0 0 0) # Request [older major].0.[newer patch] +test_write_basic_config_version_file(4.5.06 2.2.0 1 0 0 0) # Request [older major].[older minor].0 +test_write_basic_config_version_file(4.5.06 2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch] +test_write_basic_config_version_file(4.5.06 2.2.6 1 0 0 0) # Request [older major].[older minor].[same patch] +test_write_basic_config_version_file(4.5.06 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch] +test_write_basic_config_version_file(4.5.06 2.5.0 1 0 0 0) # Request [older major].[same minor].0 +test_write_basic_config_version_file(4.5.06 2.5.2 1 0 0 0) # Request [older major].[same minor].[older patch] +test_write_basic_config_version_file(4.5.06 2.5.6 1 0 0 0) # Request [older major].[same minor].[same patch] +test_write_basic_config_version_file(4.5.06 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch] +test_write_basic_config_version_file(4.5.06 2.9.0 1 0 0 0) # Request [older major].[newer minor].0 +test_write_basic_config_version_file(4.5.06 2.9.2 1 0 0 0) # Request [older major].[newer minor].[older patch] +test_write_basic_config_version_file(4.5.06 2.9.6 1 0 0 0) # Request [older major].[newer minor].[same patch] +test_write_basic_config_version_file(4.5.06 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch] +test_write_basic_config_version_file(4.5.06 4.0.0 1 1 0 0) # Request [same major].0.0 +test_write_basic_config_version_file(4.5.06 4.0.2 1 1 0 0) # Request [same major].0.[older patch] +test_write_basic_config_version_file(4.5.06 4.0.6 1 1 0 0) # Request [same major].0.[same patch] +test_write_basic_config_version_file(4.5.06 4.0.9 1 1 0 0) # Request [same major].0.[newer patch] +test_write_basic_config_version_file(4.5.06 4.2.0 1 1 0 0) # Request [same major].[older minor].0 +test_write_basic_config_version_file(4.5.06 4.2.2 1 1 0 0) # Request [same major].[older minor].[older patch] +test_write_basic_config_version_file(4.5.06 4.2.6 1 1 0 0) # Request [same major].[older minor].[same patch] +test_write_basic_config_version_file(4.5.06 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch] +test_write_basic_config_version_file(4.5.06 4.5.0 1 1 1 0) # Request [same major].[same minor].0 +test_write_basic_config_version_file(4.5.06 4.5.2 1 1 1 0) # Request [same major].[same minor].[older patch] +test_write_basic_config_version_file(4.5.06 4.5.06 1 1 1 1) # Request [same major].[same minor].[same patch] +test_write_basic_config_version_file(4.5.06 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch] +test_write_basic_config_version_file(4.5.06 4.9.0 0 0 0 0) # Request [same major].[newer minor].0 +test_write_basic_config_version_file(4.5.06 4.9.2 0 0 0 0) # Request [same major].[newer minor].[older patch] +test_write_basic_config_version_file(4.5.06 4.9.6 0 0 0 0) # Request [same major].[newer minor].[same patch] +test_write_basic_config_version_file(4.5.06 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch] +test_write_basic_config_version_file(4.5.06 9.0.0 0 0 0 0) # Request [newer major].0.0 +test_write_basic_config_version_file(4.5.06 9.0.2 0 0 0 0) # Request [newer major].0.[older patch] +test_write_basic_config_version_file(4.5.06 9.0.6 0 0 0 0) # Request [newer major].0.[same patch] +test_write_basic_config_version_file(4.5.06 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch] +test_write_basic_config_version_file(4.5.06 9.2.0 0 0 0 0) # Request [newer major].[older minor].0 +test_write_basic_config_version_file(4.5.06 9.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch] +test_write_basic_config_version_file(4.5.06 9.2.6 0 0 0 0) # Request [newer major].[older minor].[same patch] +test_write_basic_config_version_file(4.5.06 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch] +test_write_basic_config_version_file(4.5.06 9.5.0 0 0 0 0) # Request [newer major].[same minor].0 +test_write_basic_config_version_file(4.5.06 9.5.2 0 0 0 0) # Request [newer major].[same minor].[older patch] +test_write_basic_config_version_file(4.5.06 9.5.6 0 0 0 0) # Request [newer major].[same minor].[same patch] +test_write_basic_config_version_file(4.5.06 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch] +test_write_basic_config_version_file(4.5.06 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0 +test_write_basic_config_version_file(4.5.06 9.9.2 0 0 0 0) # Request [newer major].[newer minor].[older patch] +test_write_basic_config_version_file(4.5.06 9.9.6 0 0 0 0) # Request [newer major].[newer minor].[same patch] +test_write_basic_config_version_file(4.5.06 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch] + +test_write_basic_config_version_file(4.5.06 0.0.0.0 1 0 0 0) # Request 0.0.0.0 +test_write_basic_config_version_file(4.5.06 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak] +test_write_basic_config_version_file(4.5.06 0.0.2.0 1 0 0 0) # Request 0.0.[older patch].0 +test_write_basic_config_version_file(4.5.06 0.0.2.9 1 0 0 0) # Request 0.0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.0.6.0 1 0 0 0) # Request 0.0.[same patch].0 +test_write_basic_config_version_file(4.5.06 0.0.6.9 1 0 0 0) # Request 0.0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0 +test_write_basic_config_version_file(4.5.06 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0 +test_write_basic_config_version_file(4.5.06 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 0.2.2.0 1 0 0 0) # Request 0.[older minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 0.2.2.9 1 0 0 0) # Request 0.[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.2.6.0 1 0 0 0) # Request 0.[older minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 0.2.6.9 1 0 0 0) # Request 0.[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0 +test_write_basic_config_version_file(4.5.06 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 0.5.2.0 1 0 0 0) # Request 0.[same minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 0.5.2.9 1 0 0 0) # Request 0.[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.5.6.0 1 0 0 0) # Request 0.[same minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 0.5.6.9 1 0 0 0) # Request 0.[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0 +test_write_basic_config_version_file(4.5.06 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 0.9.2.0 1 0 0 0) # Request 0.[newer minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 0.9.2.9 1 0 0 0) # Request 0.[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.9.6.0 1 0 0 0) # Request 0.[newer minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 0.9.6.9 1 0 0 0) # Request 0.[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.0.0.0 1 0 0 0) # Request [older major].0.0.0 +test_write_basic_config_version_file(4.5.06 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak] +test_write_basic_config_version_file(4.5.06 2.0.2.0 1 0 0 0) # Request [older major].0.[older patch].0 +test_write_basic_config_version_file(4.5.06 2.0.2.9 1 0 0 0) # Request [older major].0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.0.6.0 1 0 0 0) # Request [older major].0.[same patch].0 +test_write_basic_config_version_file(4.5.06 2.0.6.9 1 0 0 0) # Request [older major].0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0 +test_write_basic_config_version_file(4.5.06 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0 +test_write_basic_config_version_file(4.5.06 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 2.2.2.0 1 0 0 0) # Request [older major].[older minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 2.2.2.9 1 0 0 0) # Request [older major].[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.2.6.0 1 0 0 0) # Request [older major].[older minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 2.2.6.9 1 0 0 0) # Request [older major].[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0 +test_write_basic_config_version_file(4.5.06 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 2.5.2.0 1 0 0 0) # Request [older major].[same minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 2.5.2.9 1 0 0 0) # Request [older major].[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.5.6.0 1 0 0 0) # Request [older major].[same minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 2.5.6.9 1 0 0 0) # Request [older major].[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0 +test_write_basic_config_version_file(4.5.06 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 2.9.2.0 1 0 0 0) # Request [older major].[newer minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 2.9.2.9 1 0 0 0) # Request [older major].[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.9.6.0 1 0 0 0) # Request [older major].[newer minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 2.9.6.9 1 0 0 0) # Request [older major].[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.0.0.0 1 1 0 0) # Request [same major].0.0.0 +test_write_basic_config_version_file(4.5.06 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak] +test_write_basic_config_version_file(4.5.06 4.0.2.0 1 1 0 0) # Request [same major].0.[older patch].0 +test_write_basic_config_version_file(4.5.06 4.0.2.9 1 1 0 0) # Request [same major].0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.0.6.0 1 1 0 0) # Request [same major].0.[same patch].0 +test_write_basic_config_version_file(4.5.06 4.0.6.9 1 1 0 0) # Request [same major].0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0 +test_write_basic_config_version_file(4.5.06 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0 +test_write_basic_config_version_file(4.5.06 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 4.2.2.0 1 1 0 0) # Request [same major].[older minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 4.2.2.9 1 1 0 0) # Request [same major].[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.2.6.0 1 1 0 0) # Request [same major].[older minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 4.2.6.9 1 1 0 0) # Request [same major].[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0 +test_write_basic_config_version_file(4.5.06 4.5.0.9 1 1 1 0) # Request [same major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 4.5.2.0 1 1 1 0) # Request [same major].[same minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 4.5.2.9 1 1 1 0) # Request [same major].[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.5.06.0 1 1 1 1) # Request [same major].[same minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 4.5.06.9 0 0 0 1) # Request [same major].[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0 +test_write_basic_config_version_file(4.5.06 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 4.9.2.0 0 0 0 0) # Request [same major].[newer minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 4.9.2.9 0 0 0 0) # Request [same major].[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.9.6.0 0 0 0 0) # Request [same major].[newer minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 4.9.6.9 0 0 0 0) # Request [same major].[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0 +test_write_basic_config_version_file(4.5.06 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak] +test_write_basic_config_version_file(4.5.06 9.0.2.0 0 0 0 0) # Request [newer major].0.[older patch].0 +test_write_basic_config_version_file(4.5.06 9.0.2.9 0 0 0 0) # Request [newer major].0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.0.6.0 0 0 0 0) # Request [newer major].0.[same patch].0 +test_write_basic_config_version_file(4.5.06 9.0.6.9 0 0 0 0) # Request [newer major].0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0 +test_write_basic_config_version_file(4.5.06 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0 +test_write_basic_config_version_file(4.5.06 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 9.2.2.0 0 0 0 0) # Request [newer major].[older minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 9.2.2.9 0 0 0 0) # Request [newer major].[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.2.6.0 0 0 0 0) # Request [newer major].[older minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 9.2.6.9 0 0 0 0) # Request [newer major].[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0 +test_write_basic_config_version_file(4.5.06 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 9.5.2.0 0 0 0 0) # Request [newer major].[same minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 9.5.2.9 0 0 0 0) # Request [newer major].[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.5.6.0 0 0 0 0) # Request [newer major].[same minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 9.5.6.9 0 0 0 0) # Request [newer major].[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0 +test_write_basic_config_version_file(4.5.06 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.5.06 9.9.2.0 0 0 0 0) # Request [newer major].[newer minor].[older patch].0 +test_write_basic_config_version_file(4.5.06 9.9.2.9 0 0 0 0) # Request [newer major].[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.9.6.0 0 0 0 0) # Request [newer major].[newer minor].[same patch].0 +test_write_basic_config_version_file(4.5.06 9.9.6.9 0 0 0 0) # Request [newer major].[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.5.06 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.5.06 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak] + + +test_write_basic_config_version_file(4.05.06.007 0 1 0 0 0) # Request 0 +test_write_basic_config_version_file(4.05.06.007 2 1 0 0 0) # Request [older major] +test_write_basic_config_version_file(4.05.06.007 4 1 1 0 0) # Request [same major] +test_write_basic_config_version_file(4.05.06.007 9 0 0 0 0) # Request [newer major] + +test_write_basic_config_version_file(4.05.06.007 0.0 1 0 0 0) # Request 0.0 +test_write_basic_config_version_file(4.05.06.007 0.2 1 0 0 0) # Request 0.[older minor] +test_write_basic_config_version_file(4.05.06.007 0.5 1 0 0 0) # Request 0.[same minor] +test_write_basic_config_version_file(4.05.06.007 0.9 1 0 0 0) # Request 0.[newer minor] +test_write_basic_config_version_file(4.05.06.007 2.0 1 0 0 0) # Request [older major].0 +test_write_basic_config_version_file(4.05.06.007 2.2 1 0 0 0) # Request [older major].[older minor] +test_write_basic_config_version_file(4.05.06.007 2.5 1 0 0 0) # Request [older major].[same minor] +test_write_basic_config_version_file(4.05.06.007 2.9 1 0 0 0) # Request [older major].[newer minor] +test_write_basic_config_version_file(4.05.06.007 4.0 1 1 0 0) # Request [same major].0 +test_write_basic_config_version_file(4.05.06.007 4.2 1 1 0 0) # Request [same major].[older minor] +test_write_basic_config_version_file(4.05.06.007 4.5 1 1 1 0) # Request [same major].[same minor] +test_write_basic_config_version_file(4.05.06.007 4.9 0 0 0 0) # Request [same major].[newer minor] +test_write_basic_config_version_file(4.05.06.007 9.0 0 0 0 0) # Request [newer major].0 +test_write_basic_config_version_file(4.05.06.007 9.1 0 0 0 0) # Request [newer major].[older minor] +test_write_basic_config_version_file(4.05.06.007 9.5 0 0 0 0) # Request [newer major].[same minor] +test_write_basic_config_version_file(4.05.06.007 9.9 0 0 0 0) # Request [newer major].[newer minor] + +test_write_basic_config_version_file(4.05.06.007 0.0.0 1 0 0 0) # Request 0.0.0 +test_write_basic_config_version_file(4.05.06.007 0.0.2 1 0 0 0) # Request 0.0.[older patch] +test_write_basic_config_version_file(4.05.06.007 0.0.6 1 0 0 0) # Request 0.0.[same patch] +test_write_basic_config_version_file(4.05.06.007 0.0.9 1 0 0 0) # Request 0.0.[newer patch] +test_write_basic_config_version_file(4.05.06.007 0.2.0 1 0 0 0) # Request 0.[older minor].0 +test_write_basic_config_version_file(4.05.06.007 0.2.2 1 0 0 0) # Request 0.[older minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 0.2.6 1 0 0 0) # Request 0.[older minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 0.2.9 1 0 0 0) # Request 0.[older minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 0.5.0 1 0 0 0) # Request 0.[same minor].0 +test_write_basic_config_version_file(4.05.06.007 0.5.2 1 0 0 0) # Request 0.[same minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 0.5.6 1 0 0 0) # Request 0.[same minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 0.5.9 1 0 0 0) # Request 0.[same minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 0.9.0 1 0 0 0) # Request 0.[newer minor].0 +test_write_basic_config_version_file(4.05.06.007 0.9.2 1 0 0 0) # Request 0.[newer minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 0.9.6 1 0 0 0) # Request 0.[newer minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 0.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 2.0.0 1 0 0 0) # Request [older major].0.0 +test_write_basic_config_version_file(4.05.06.007 2.0.2 1 0 0 0) # Request [older major].0.[older patch] +test_write_basic_config_version_file(4.05.06.007 2.0.6 1 0 0 0) # Request [older major].0.[same patch] +test_write_basic_config_version_file(4.05.06.007 2.0.9 1 0 0 0) # Request [older major].0.[newer patch] +test_write_basic_config_version_file(4.05.06.007 2.2.0 1 0 0 0) # Request [older major].[older minor].0 +test_write_basic_config_version_file(4.05.06.007 2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 2.2.6 1 0 0 0) # Request [older major].[older minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 2.2.9 1 0 0 0) # Request [older major].[older minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 2.5.0 1 0 0 0) # Request [older major].[same minor].0 +test_write_basic_config_version_file(4.05.06.007 2.5.2 1 0 0 0) # Request [older major].[same minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 2.5.6 1 0 0 0) # Request [older major].[same minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 2.5.9 1 0 0 0) # Request [older major].[same minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 2.9.0 1 0 0 0) # Request [older major].[newer minor].0 +test_write_basic_config_version_file(4.05.06.007 2.9.2 1 0 0 0) # Request [older major].[newer minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 2.9.6 1 0 0 0) # Request [older major].[newer minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 2.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 4.0.0 1 1 0 0) # Request [same major].0.0 +test_write_basic_config_version_file(4.05.06.007 4.0.2 1 1 0 0) # Request [same major].0.[older patch] +test_write_basic_config_version_file(4.05.06.007 4.0.6 1 1 0 0) # Request [same major].0.[same patch] +test_write_basic_config_version_file(4.05.06.007 4.0.9 1 1 0 0) # Request [same major].0.[newer patch] +test_write_basic_config_version_file(4.05.06.007 4.2.0 1 1 0 0) # Request [same major].[older minor].0 +test_write_basic_config_version_file(4.05.06.007 4.2.2 1 1 0 0) # Request [same major].[older minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 4.2.6 1 1 0 0) # Request [same major].[older minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 4.2.9 1 1 0 0) # Request [same major].[older minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 4.5.0 1 1 1 0) # Request [same major].[same minor].0 +test_write_basic_config_version_file(4.05.06.007 4.5.2 1 1 1 0) # Request [same major].[same minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 4.05.06 1 1 1 1) # Request [same major].[same minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 4.5.9 0 0 0 0) # Request [same major].[same minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 4.9.0 0 0 0 0) # Request [same major].[newer minor].0 +test_write_basic_config_version_file(4.05.06.007 4.9.2 0 0 0 0) # Request [same major].[newer minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 4.9.6 0 0 0 0) # Request [same major].[newer minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 4.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 9.0.0 0 0 0 0) # Request [newer major].0.0 +test_write_basic_config_version_file(4.05.06.007 9.0.2 0 0 0 0) # Request [newer major].0.[older patch] +test_write_basic_config_version_file(4.05.06.007 9.0.6 0 0 0 0) # Request [newer major].0.[same patch] +test_write_basic_config_version_file(4.05.06.007 9.0.9 0 0 0 0) # Request [newer major].0.[newer patch] +test_write_basic_config_version_file(4.05.06.007 9.2.0 0 0 0 0) # Request [newer major].[older minor].0 +test_write_basic_config_version_file(4.05.06.007 9.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 9.2.6 0 0 0 0) # Request [newer major].[older minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 9.2.9 0 0 0 0) # Request [newer major].[older minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 9.5.0 0 0 0 0) # Request [newer major].[same minor].0 +test_write_basic_config_version_file(4.05.06.007 9.5.2 0 0 0 0) # Request [newer major].[same minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 9.5.6 0 0 0 0) # Request [newer major].[same minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 9.5.9 0 0 0 0) # Request [newer major].[same minor].[newer patch] +test_write_basic_config_version_file(4.05.06.007 9.9.0 0 0 0 0) # Request [newer major].[newer minor].0 +test_write_basic_config_version_file(4.05.06.007 9.9.2 0 0 0 0) # Request [newer major].[newer minor].[older patch] +test_write_basic_config_version_file(4.05.06.007 9.9.6 0 0 0 0) # Request [newer major].[newer minor].[same patch] +test_write_basic_config_version_file(4.05.06.007 9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch] + +test_write_basic_config_version_file(4.05.06.007 0.0.0.0 1 0 0 0) # Request 0.0.0.0 +test_write_basic_config_version_file(4.05.06.007 0.0.0.2 1 0 0 0) # Request 0.0.0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.0.7 1 0 0 0) # Request 0.0.0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.0.9 1 0 0 0) # Request 0.0.0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.2.0 1 0 0 0) # Request 0.0.[older patch].0 +test_write_basic_config_version_file(4.05.06.007 0.0.2.2 1 0 0 0) # Request 0.0.[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.2.7 1 0 0 0) # Request 0.0.[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.2.9 1 0 0 0) # Request 0.0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.6.0 1 0 0 0) # Request 0.0.[same patch].0 +test_write_basic_config_version_file(4.05.06.007 0.0.6.2 1 0 0 0) # Request 0.0.[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.6.7 1 0 0 0) # Request 0.0.[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.6.9 1 0 0 0) # Request 0.0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.9.0 1 0 0 0) # Request 0.0.[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 0.0.9.2 1 0 0 0) # Request 0.0.[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.9.7 1 0 0 0) # Request 0.0.[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.0.9.9 1 0 0 0) # Request 0.0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.0.0 1 0 0 0) # Request 0.[older minor].0.0 +test_write_basic_config_version_file(4.05.06.007 0.2.0.2 1 0 0 0) # Request 0.[older minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.0.7 1 0 0 0) # Request 0.[older minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.0.9 1 0 0 0) # Request 0.[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.2.0 1 0 0 0) # Request 0.[older minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 0.2.2.2 1 0 0 0) # Request 0.[older minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.2.7 1 0 0 0) # Request 0.[older minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.2.9 1 0 0 0) # Request 0.[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.6.0 1 0 0 0) # Request 0.[older minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 0.2.6.2 1 0 0 0) # Request 0.[older minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.6.7 1 0 0 0) # Request 0.[older minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.6.9 1 0 0 0) # Request 0.[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.9.0 1 0 0 0) # Request 0.[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 0.2.9.2 1 0 0 0) # Request 0.[older minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.9.7 1 0 0 0) # Request 0.[older minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.2.9.9 1 0 0 0) # Request 0.[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.0.0 1 0 0 0) # Request 0.[same minor].0.0 +test_write_basic_config_version_file(4.05.06.007 0.5.0.2 1 0 0 0) # Request 0.[same minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.0.7 1 0 0 0) # Request 0.[same minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.0.9 1 0 0 0) # Request 0.[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.2.0 1 0 0 0) # Request 0.[same minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 0.5.2.2 1 0 0 0) # Request 0.[same minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.2.7 1 0 0 0) # Request 0.[same minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.2.9 1 0 0 0) # Request 0.[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.6.0 1 0 0 0) # Request 0.[same minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 0.5.6.2 1 0 0 0) # Request 0.[same minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.6.7 1 0 0 0) # Request 0.[same minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.6.9 1 0 0 0) # Request 0.[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.9.0 1 0 0 0) # Request 0.[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 0.5.9.2 1 0 0 0) # Request 0.[same minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.9.7 1 0 0 0) # Request 0.[same minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.5.9.9 1 0 0 0) # Request 0.[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.0.0 1 0 0 0) # Request 0.[newer minor].0.0 +test_write_basic_config_version_file(4.05.06.007 0.9.0.2 1 0 0 0) # Request 0.[newer minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.0.7 1 0 0 0) # Request 0.[newer minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.0.9 1 0 0 0) # Request 0.[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.2.0 1 0 0 0) # Request 0.[newer minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 0.9.2.2 1 0 0 0) # Request 0.[newer minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.2.7 1 0 0 0) # Request 0.[newer minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.2.9 1 0 0 0) # Request 0.[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.6.0 1 0 0 0) # Request 0.[newer minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 0.9.6.2 1 0 0 0) # Request 0.[newer minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.6.7 1 0 0 0) # Request 0.[newer minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.6.9 1 0 0 0) # Request 0.[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.9.0 1 0 0 0) # Request 0.[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 0.9.9.2 1 0 0 0) # Request 0.[newer minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.9.7 1 0 0 0) # Request 0.[newer minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 0.9.9.9 1 0 0 0) # Request 0.[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.0.0 1 0 0 0) # Request [older major].0.0.0 +test_write_basic_config_version_file(4.05.06.007 2.0.0.2 1 0 0 0) # Request [older major].0.0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.0.7 1 0 0 0) # Request [older major].0.0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.0.9 1 0 0 0) # Request [older major].0.0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.2.0 1 0 0 0) # Request [older major].0.[older patch].0 +test_write_basic_config_version_file(4.05.06.007 2.0.2.2 1 0 0 0) # Request [older major].0.[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.2.7 1 0 0 0) # Request [older major].0.[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.2.9 1 0 0 0) # Request [older major].0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.6.0 1 0 0 0) # Request [older major].0.[same patch].0 +test_write_basic_config_version_file(4.05.06.007 2.0.6.2 1 0 0 0) # Request [older major].0.[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.6.7 1 0 0 0) # Request [older major].0.[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.6.9 1 0 0 0) # Request [older major].0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.9.0 1 0 0 0) # Request [older major].0.[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 2.0.9.2 1 0 0 0) # Request [older major].0.[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.9.7 1 0 0 0) # Request [older major].0.[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.0.9.9 1 0 0 0) # Request [older major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.0.0 1 0 0 0) # Request [older major].[older minor].0.0 +test_write_basic_config_version_file(4.05.06.007 2.2.0.2 1 0 0 0) # Request [older major].[older minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.0.7 1 0 0 0) # Request [older major].[older minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.0.9 1 0 0 0) # Request [older major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.2.0 1 0 0 0) # Request [older major].[older minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 2.2.2.2 1 0 0 0) # Request [older major].[older minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.2.7 1 0 0 0) # Request [older major].[older minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.2.9 1 0 0 0) # Request [older major].[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.6.0 1 0 0 0) # Request [older major].[older minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 2.2.6.2 1 0 0 0) # Request [older major].[older minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.6.7 1 0 0 0) # Request [older major].[older minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.6.9 1 0 0 0) # Request [older major].[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.9.0 1 0 0 0) # Request [older major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 2.2.9.2 1 0 0 0) # Request [older major].[older minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.9.7 1 0 0 0) # Request [older major].[older minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.2.9.9 1 0 0 0) # Request [older major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.0.0 1 0 0 0) # Request [older major].[same minor].0.0 +test_write_basic_config_version_file(4.05.06.007 2.5.0.2 1 0 0 0) # Request [older major].[same minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.0.7 1 0 0 0) # Request [older major].[same minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.0.9 1 0 0 0) # Request [older major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.2.0 1 0 0 0) # Request [older major].[same minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 2.5.2.2 1 0 0 0) # Request [older major].[same minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.2.7 1 0 0 0) # Request [older major].[same minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.2.9 1 0 0 0) # Request [older major].[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.6.0 1 0 0 0) # Request [older major].[same minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 2.5.6.2 1 0 0 0) # Request [older major].[same minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.6.7 1 0 0 0) # Request [older major].[same minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.6.9 1 0 0 0) # Request [older major].[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.9.0 1 0 0 0) # Request [older major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 2.5.9.2 1 0 0 0) # Request [older major].[same minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.9.7 1 0 0 0) # Request [older major].[same minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.5.9.9 1 0 0 0) # Request [older major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.0.0 1 0 0 0) # Request [older major].[newer minor].0.0 +test_write_basic_config_version_file(4.05.06.007 2.9.0.2 1 0 0 0) # Request [older major].[newer minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.0.7 1 0 0 0) # Request [older major].[newer minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.0.9 1 0 0 0) # Request [older major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.2.0 1 0 0 0) # Request [older major].[newer minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 2.9.2.2 1 0 0 0) # Request [older major].[newer minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.2.7 1 0 0 0) # Request [older major].[newer minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.2.9 1 0 0 0) # Request [older major].[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.6.0 1 0 0 0) # Request [older major].[newer minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 2.9.6.2 1 0 0 0) # Request [older major].[newer minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.6.7 1 0 0 0) # Request [older major].[newer minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.6.9 1 0 0 0) # Request [older major].[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.9.0 1 0 0 0) # Request [older major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 2.9.9.2 1 0 0 0) # Request [older major].[newer minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.9.7 1 0 0 0) # Request [older major].[newer minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 2.9.9.9 1 0 0 0) # Request [older major].[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.0.0 1 1 0 0) # Request [same major].0.0.0 +test_write_basic_config_version_file(4.05.06.007 4.0.0.2 1 1 0 0) # Request [same major].0.0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.0.7 1 1 0 0) # Request [same major].0.0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.0.9 1 1 0 0) # Request [same major].0.0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.2.0 1 1 0 0) # Request [same major].0.[older patch].0 +test_write_basic_config_version_file(4.05.06.007 4.0.2.2 1 1 0 0) # Request [same major].0.[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.2.7 1 1 0 0) # Request [same major].0.[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.2.9 1 1 0 0) # Request [same major].0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.6.0 1 1 0 0) # Request [same major].0.[same patch].0 +test_write_basic_config_version_file(4.05.06.007 4.0.6.2 1 1 0 0) # Request [same major].0.[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.6.7 1 1 0 0) # Request [same major].0.[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.6.9 1 1 0 0) # Request [same major].0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.9.0 1 1 0 0) # Request [same major].0.[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 4.0.9.2 1 1 0 0) # Request [same major].0.[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.9.7 1 1 0 0) # Request [same major].0.[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.0.9.9 1 1 0 0) # Request [same major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.0.0 1 1 0 0) # Request [same major].[older minor].0.0 +test_write_basic_config_version_file(4.05.06.007 4.2.0.2 1 1 0 0) # Request [same major].[older minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.0.7 1 1 0 0) # Request [same major].[older minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.0.9 1 1 0 0) # Request [same major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.2.0 1 1 0 0) # Request [same major].[older minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 4.2.2.2 1 1 0 0) # Request [same major].[older minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.2.7 1 1 0 0) # Request [same major].[older minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.2.9 1 1 0 0) # Request [same major].[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.6.0 1 1 0 0) # Request [same major].[older minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 4.2.6.2 1 1 0 0) # Request [same major].[older minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.6.7 1 1 0 0) # Request [same major].[older minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.6.9 1 1 0 0) # Request [same major].[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.9.0 1 1 0 0) # Request [same major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 4.2.9.2 1 1 0 0) # Request [same major].[older minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.9.7 1 1 0 0) # Request [same major].[older minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.2.9.9 1 1 0 0) # Request [same major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.0.0 1 1 1 0) # Request [same major].[same minor].0.0 +test_write_basic_config_version_file(4.05.06.007 4.5.0.2 1 1 1 0) # Request [same major].[same minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.0.7 1 1 1 0) # Request [same major].[same minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.0.9 1 1 1 0) # Request [same major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.2.0 1 1 1 0) # Request [same major].[same minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 4.5.2.2 1 1 1 0) # Request [same major].[same minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.2.7 1 1 1 0) # Request [same major].[same minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.2.9 1 1 1 0) # Request [same major].[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.05.06.007 1 1 1 1) # Request [same major].[same minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 4.05.06.2 1 1 1 1) # Request [same major].[same minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.05.06.7 1 1 1 1) # Request [same major].[same minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.05.06.9 0 0 0 1) # Request [same major].[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.9.0 0 0 0 0) # Request [same major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 4.5.9.2 0 0 0 0) # Request [same major].[same minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.9.7 0 0 0 0) # Request [same major].[same minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.5.9.9 0 0 0 0) # Request [same major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.0.0 0 0 0 0) # Request [same major].[newer minor].0.0 +test_write_basic_config_version_file(4.05.06.007 4.9.0.2 0 0 0 0) # Request [same major].[newer minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.0.7 0 0 0 0) # Request [same major].[newer minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.0.9 0 0 0 0) # Request [same major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.2.0 0 0 0 0) # Request [same major].[newer minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 4.9.2.2 0 0 0 0) # Request [same major].[newer minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.2.7 0 0 0 0) # Request [same major].[newer minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.2.9 0 0 0 0) # Request [same major].[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.6.0 0 0 0 0) # Request [same major].[newer minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 4.9.6.2 0 0 0 0) # Request [same major].[newer minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.6.7 0 0 0 0) # Request [same major].[newer minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.6.9 0 0 0 0) # Request [same major].[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.9.0 0 0 0 0) # Request [same major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 4.9.9.2 0 0 0 0) # Request [same major].[newer minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.9.7 0 0 0 0) # Request [same major].[newer minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 4.9.9.9 0 0 0 0) # Request [same major].[newer minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.0.0 0 0 0 0) # Request [newer major].0.0.0 +test_write_basic_config_version_file(4.05.06.007 9.0.0.2 0 0 0 0) # Request [newer major].0.0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.0.7 0 0 0 0) # Request [newer major].0.0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.0.9 0 0 0 0) # Request [newer major].0.0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.2.0 0 0 0 0) # Request [newer major].0.[older patch].0 +test_write_basic_config_version_file(4.05.06.007 9.0.2.2 0 0 0 0) # Request [newer major].0.[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.2.7 0 0 0 0) # Request [newer major].0.[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.2.9 0 0 0 0) # Request [newer major].0.[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.6.0 0 0 0 0) # Request [newer major].0.[same patch].0 +test_write_basic_config_version_file(4.05.06.007 9.0.6.2 0 0 0 0) # Request [newer major].0.[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.6.7 0 0 0 0) # Request [newer major].0.[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.6.9 0 0 0 0) # Request [newer major].0.[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.9.0 0 0 0 0) # Request [newer major].0.[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 9.0.9.2 0 0 0 0) # Request [newer major].0.[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.9.7 0 0 0 0) # Request [newer major].0.[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.0.9.9 0 0 0 0) # Request [newer major].0.[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.0.0 0 0 0 0) # Request [newer major].[older minor].0.0 +test_write_basic_config_version_file(4.05.06.007 9.2.0.2 0 0 0 0) # Request [newer major].[older minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.0.7 0 0 0 0) # Request [newer major].[older minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.0.9 0 0 0 0) # Request [newer major].[older minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.2.0 0 0 0 0) # Request [newer major].[older minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 9.2.2.2 0 0 0 0) # Request [newer major].[older minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.2.7 0 0 0 0) # Request [newer major].[older minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.2.9 0 0 0 0) # Request [newer major].[older minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.6.0 0 0 0 0) # Request [newer major].[older minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 9.2.6.2 0 0 0 0) # Request [newer major].[older minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.6.7 0 0 0 0) # Request [newer major].[older minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.6.9 0 0 0 0) # Request [newer major].[older minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.9.0 0 0 0 0) # Request [newer major].[older minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 9.2.9.2 0 0 0 0) # Request [newer major].[older minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.9.7 0 0 0 0) # Request [newer major].[older minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.2.9.9 0 0 0 0) # Request [newer major].[older minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.0.0 0 0 0 0) # Request [newer major].[same minor].0.0 +test_write_basic_config_version_file(4.05.06.007 9.5.0.2 0 0 0 0) # Request [newer major].[same minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.0.7 0 0 0 0) # Request [newer major].[same minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.0.9 0 0 0 0) # Request [newer major].[same minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.2.0 0 0 0 0) # Request [newer major].[same minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 9.5.2.2 0 0 0 0) # Request [newer major].[same minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.2.7 0 0 0 0) # Request [newer major].[same minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.2.9 0 0 0 0) # Request [newer major].[same minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.6.0 0 0 0 0) # Request [newer major].[same minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 9.5.6.2 0 0 0 0) # Request [newer major].[same minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.6.7 0 0 0 0) # Request [newer major].[same minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.6.9 0 0 0 0) # Request [newer major].[same minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.9.0 0 0 0 0) # Request [newer major].[same minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 9.5.9.2 0 0 0 0) # Request [newer major].[same minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.9.7 0 0 0 0) # Request [newer major].[same minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.5.9.9 0 0 0 0) # Request [newer major].[same minor].[newer patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.0.0 0 0 0 0) # Request [newer major].[newer minor].0.0 +test_write_basic_config_version_file(4.05.06.007 9.9.0.2 0 0 0 0) # Request [newer major].[newer minor].0.[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.0.7 0 0 0 0) # Request [newer major].[newer minor].0.[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.0.9 0 0 0 0) # Request [newer major].[newer minor].0.[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.2.0 0 0 0 0) # Request [newer major].[newer minor].[older patch].0 +test_write_basic_config_version_file(4.05.06.007 9.9.2.2 0 0 0 0) # Request [newer major].[newer minor].[older patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.2.7 0 0 0 0) # Request [newer major].[newer minor].[older patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.2.9 0 0 0 0) # Request [newer major].[newer minor].[older patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.6.0 0 0 0 0) # Request [newer major].[newer minor].[same patch].0 +test_write_basic_config_version_file(4.05.06.007 9.9.6.2 0 0 0 0) # Request [newer major].[newer minor].[same patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.6.7 0 0 0 0) # Request [newer major].[newer minor].[same patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.6.9 0 0 0 0) # Request [newer major].[newer minor].[same patch].[newer tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.9.0 0 0 0 0) # Request [newer major].[newer minor].[newer patch].0 +test_write_basic_config_version_file(4.05.06.007 9.9.9.2 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[older tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.9.7 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[same tweak] +test_write_basic_config_version_file(4.05.06.007 9.9.9.9 0 0 0 0) # Request [newer major].[newer minor].[newer patch].[newer tweak] + +test_write_basic_config_version_file(4 0...5 1 0 0 0) +test_write_basic_config_version_file(4 2...5 1 0 0 0) +test_write_basic_config_version_file(4 2...4 1 0 0 0) +test_write_basic_config_version_file(4 4...<5 1 1 0 0) +test_write_basic_config_version_file(4 9...10 0 0 0 0) + +test_write_basic_config_version_file(4 0.1...5 1 0 0 0) +test_write_basic_config_version_file(4 2.1...5 1 0 0 0) +test_write_basic_config_version_file(4 2.8...5 1 0 0 0) +test_write_basic_config_version_file(4 2.1...4 1 0 0 0) +test_write_basic_config_version_file(4 2.8...4 1 0 0 0) +test_write_basic_config_version_file(4 4.0...<5 1 1 0 0) +test_write_basic_config_version_file(4 4.8...<5 0 0 0 0) +test_write_basic_config_version_file(4 4.1...5 0 0 0 0) +test_write_basic_config_version_file(4 4.8...5 0 0 0 0) +test_write_basic_config_version_file(4 9.1...10 0 0 0 0) +test_write_basic_config_version_file(4 9.8...10 0 0 0 0) + + +test_write_basic_config_version_file(4.05 0.1...5 1 0 0 0) +test_write_basic_config_version_file(4.05 2.1...5 1 0 0 0) +test_write_basic_config_version_file(4.05 2.8...5 1 0 0 0) +test_write_basic_config_version_file(4.05 2.1...4 0 0 0 0) +test_write_basic_config_version_file(4.05 2.8...4 0 0 0 0) +test_write_basic_config_version_file(4.05 2.8...4.8 1 0 0 0) +test_write_basic_config_version_file(4.05 4.1...<5 1 1 0 0) +test_write_basic_config_version_file(4.05 4.8...<5 0 0 0 0) +test_write_basic_config_version_file(4.05 4.5...4.5.8 1 1 1 0) +test_write_basic_config_version_file(4.05 4.5...<4.6 1 1 1 0) +test_write_basic_config_version_file(4.05 4.1...5 1 0 0 0) +test_write_basic_config_version_file(4.05 4.8...5 0 0 0 0) +test_write_basic_config_version_file(4.05 9.1...10 0 0 0 0) +test_write_basic_config_version_file(4.05 9.8...10 0 0 0 0) + + +test_write_basic_config_version_file(4.5.06 0.1...5 1 0 0 0) +test_write_basic_config_version_file(4.5.06 2.1...5 1 0 0 0) +test_write_basic_config_version_file(4.5.06 2.8...5 1 0 0 0) +test_write_basic_config_version_file(4.5.06 2.1...4 0 0 0 0) +test_write_basic_config_version_file(4.5.06 2.8...4 0 0 0 0) +test_write_basic_config_version_file(4.5.06 2.8...4.8 1 0 0 0) +test_write_basic_config_version_file(4.5.06 4.1...<5 1 1 0 0) +test_write_basic_config_version_file(4.5.06 4.8...<5 0 0 0 0) +test_write_basic_config_version_file(4.5.06 4.5...4.5.4 0 0 0 0) +test_write_basic_config_version_file(4.5.06 4.5...4.5.8 1 1 1 0) +test_write_basic_config_version_file(4.5.06 4.5...<4.6 1 1 1 0) +test_write_basic_config_version_file(4.5.06 4.1...5 1 0 0 0) +test_write_basic_config_version_file(4.5.06 4.8...5 0 0 0 0) +test_write_basic_config_version_file(4.5.06 9.1...10 0 0 0 0) +test_write_basic_config_version_file(4.5.06 9.8...10 0 0 0 0) diff --git a/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake b/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake index 5db33f7f281..8a9db15648a 100644 --- a/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake +++ b/Tests/RunCMake/WriteBasicConfigVersionFile/RunCMakeTest.cmake @@ -2,3 +2,4 @@ include(RunCMake) run_cmake(All) run_cmake(ArchIndependent) +run_cmake(LeadingZeroes) diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index 72ffcce6ccd..3ba04c8bd77 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -38,6 +38,7 @@ run_cmake(VersionRange3) run_cmake(VersionRange4) run_cmake(VersionRangeConfig) run_cmake(VersionRangeConfig2) +run_cmake(VersionRangeConfig02) run_cmake(VersionRangeConfigStd) run_cmake(VersionRangeConfigStd2) if(UNIX diff --git a/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake b/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake index e9f60768570..1d0adfe3f80 100644 --- a/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake +++ b/Tests/RunCMake/find_package/VersionRangeCfg/VersionRangeCfgConfigVersion.cmake @@ -1,6 +1,7 @@ if (NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.2.3.4...5.6.7.8" - AND NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.2.3.4...<5.6.7.8") + AND NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.2.3.4...<5.6.7.8" + AND NOT PACKAGE_FIND_VERSION_COMPLETE STREQUAL "1.02.03.04...<5.06.07.08") message (SEND_ERROR "Wrong value for PACKAGE_FIND_VERSION_COMPLETE: ${PACKAGE_FIND_VERSION_COMPLETE}") endif() @@ -21,7 +22,8 @@ if (NOT PACKAGE_FIND_VERSION_TWEAK VERSION_EQUAL "4") endif() if (NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.2.3.4...5.6.7.8" - AND NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.2.3.4...<5.6.7.8") + AND NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.2.3.4...<5.6.7.8" + AND NOT PACKAGE_FIND_VERSION_RANGE STREQUAL "1.02.03.04...<5.06.07.08") message (SEND_ERROR "Wrong value for PACKAGE_FIND_VERSION_RANGE: ${PACKAGE_FIND_VERSION_RANGE}") endif() diff --git a/Tests/RunCMake/find_package/VersionRangeConfig02.cmake b/Tests/RunCMake/find_package/VersionRangeConfig02.cmake new file mode 100644 index 00000000000..6522f6de9b5 --- /dev/null +++ b/Tests/RunCMake/find_package/VersionRangeConfig02.cmake @@ -0,0 +1,23 @@ +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +find_package(VersionRange 1.02.03.04...<5.06.07.08 CONFIG NAMES VersionRangeCfg) + +if (NOT VersionRange_FOUND) + message (FATAL_ERROR "Package VersionRange not found in CONFIG mode.") +endif() + +if (NOT VersionRange_VERSION VERSION_EQUAL "2.3.4.5") + message (SEND_ERROR "Wrong version : ${VersionRange_VERSION}") +endif() +if (NOT VersionRange_VERSION_MAJOR VERSION_EQUAL "2") + message (SEND_ERROR "Wrong major version : ${VersionRange_VERSION_MAJOR}") +endif() +if (NOT VersionRange_VERSION_MINOR VERSION_EQUAL "3") + message (SEND_ERROR "Wrong minor version : ${VersionRange_VERSION_MINOR}") +endif() +if (NOT VersionRange_VERSION_PATCH VERSION_EQUAL "4") + message (SEND_ERROR "Wrong patch version : ${VersionRange_VERSION_PATCH}") +endif() +if (NOT VersionRange_VERSION_TWEAK VERSION_EQUAL "5") + message (SEND_ERROR "Wrong tweak version : ${VersionRange_VERSION_TWEAK}") +endif() From f361cb1fb375b213a0a187a238bc1490d514560c Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 15:29:46 -0400 Subject: [PATCH 0529/1519] Utilities: Update hard-coded try_compile results for curl 1.77.0 --- Utilities/cmThirdPartyChecks.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake index 4ccfdfc7251..52e2dd97ded 100644 --- a/Utilities/cmThirdPartyChecks.cmake +++ b/Utilities/cmThirdPartyChecks.cmake @@ -83,6 +83,7 @@ if(WIN32) set(HAVE_GETPAGESIZE 0) set(HAVE_GETPEERNAME 1) set(HAVE_GETPID 1) + set(HAVE_GETPPID 0) set(HAVE_GETPROTOBYNAME 1) set(HAVE_GETPWNAM_R 0) set(HAVE_GETPWUID_R 0) @@ -165,6 +166,8 @@ if(WIN32) set(HAVE_SIG_ATOMIC_T_NOT_VOLATILE 1) set(HAVE_SIGINTERRUPT 0) set(HAVE_SIGNAL_H 1) + set(HAVE_SIZEOF_ADDRESS_FAMILY 0) + set(HAVE_SIZEOF_SA_FAMILY_T 0) set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0) set(HAVE_SPAWN_H 0) set(HAVE_SSL_H 0) @@ -249,6 +252,7 @@ if(WIN32) set(HAVE_WINSOCK2_H 1) set(HAVE_WINSOCK_H 1) set(HAVE_WS2TCPIP_H 1) + set(USE_WINCRYPT 1) # We do not need to build as a Windows App. # UNIX integer id types do not exist on Windows. set(HAVE_ID_T 0) From d199fc4bf895bfc250054b51332f342fca41a09b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 15:53:40 -0400 Subject: [PATCH 0530/1519] Utilities: Add missing hard-coded try_compile results for libarchive --- Utilities/cmThirdPartyChecks.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake index 52e2dd97ded..bab30463f96 100644 --- a/Utilities/cmThirdPartyChecks.cmake +++ b/Utilities/cmThirdPartyChecks.cmake @@ -288,13 +288,16 @@ if(WIN32) set(ARCHIVE_CRYPTO_SHA256_LIBC3 0) set(ARCHIVE_CRYPTO_SHA256_LIBMD 0) set(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 0) + set(ARCHIVE_CRYPTO_SHA256_WIN 0) set(ARCHIVE_CRYPTO_SHA384_LIBC 0) set(ARCHIVE_CRYPTO_SHA384_LIBC2 0) set(ARCHIVE_CRYPTO_SHA384_LIBC3 0) set(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 0) + set(ARCHIVE_CRYPTO_SHA384_WIN 0) set(ARCHIVE_CRYPTO_SHA512_LIBC 0) set(ARCHIVE_CRYPTO_SHA512_LIBC2 0) set(ARCHIVE_CRYPTO_SHA512_LIBC3 0) set(ARCHIVE_CRYPTO_SHA512_LIBMD 0) set(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 0) + set(ARCHIVE_CRYPTO_SHA512_WIN 0) endif() From a60141feaafcbbe3c46211095ec71c797e6fbcd4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 27 May 2021 16:50:55 -0400 Subject: [PATCH 0531/1519] VS: Add special case for '-T version=14.29.16.10' under VS 16.10 Extend the table of special cases from commit 58a50a3a0a (VS: Fix '-T version=14.28' under VS 16.9, 2021-03-11, v3.19.7~1^2~1). Add a special case for the name VS 16.11 will use for VS 16.10's default toolset, so that it can be used with VS 16.10 too. Using '-T version=14.29.16.10' actually works under VS 16.10 without this change, but only because there is only one 14.29 toolset so the two-component prefix happens to match the right one. Make it explicit. Issue: #21922 --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 9a9a4658f4b..c11ab1bf82c 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -504,6 +504,9 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset( if (version == "14.28.16.9" && vcToolsetVersion == "14.28.29910") { return AuxToolset::Default; } + if (version == "14.29.16.10" && vcToolsetVersion == "14.29.30037") { + return AuxToolset::Default; + } // The first two components of the default toolset version typically // match the name used by later VS versions for the SxS props files. From c186dfcd01cfda600cca12c2326d5105d8017da8 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 28 May 2021 00:01:11 -0400 Subject: [PATCH 0532/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 84523ca9a54..2dda0ce1c20 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210527) +set(CMake_VERSION_PATCH 20210528) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9054cd05e6e3a267146c1690745e9b8c2d3d9c72 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 May 2021 11:48:30 -0400 Subject: [PATCH 0533/1519] VS: Add flag table entries for '/external:W*' flags in VS 16.10 Fixes: #22255 --- Templates/MSBuild/FlagTables/v142_CL.json | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 7c2d291f9a1..3305e5643a9 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -532,6 +532,41 @@ "value": "All", "flags": [] }, + { + "name": "ExternalWarningLevel", + "switch": "external:W0", + "comment": "Turn Off All Warnings", + "value": "TurnOffAllWarnings", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W1", + "comment": "Level1", + "value": "Level1", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W2", + "comment": "Level2", + "value": "Level2", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W3", + "comment": "Level3", + "value": "Level3", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W4", + "comment": "Level4", + "value": "Level4", + "flags": [] + }, { "name": "CallingConvention", "switch": "Gd", From d93bfd95f8661d399f71dca3b3a3907101939617 Mon Sep 17 00:00:00 2001 From: Bobby D Reynolds Date: Tue, 18 May 2021 08:44:27 -0700 Subject: [PATCH 0534/1519] Tests/CompilerLauncher: Fix file names and clarify comment --- ...nv-launch-Build-stdout.txt => C-launch-env-Build-stdout.txt} | 0 ...launch-Build-stdout.txt => CUDA-launch-env-Build-stdout.txt} | 0 ...-launch-Build-stdout.txt => CXX-launch-env-Build-stdout.txt} | 0 ...nch-Build-stdout.txt => Fortran-launch-env-Build-stdout.txt} | 0 ...launch-Build-stdout.txt => ISPC-launch-env-Build-stdout.txt} | 0 Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake | 2 +- 6 files changed, 1 insertion(+), 1 deletion(-) rename Tests/RunCMake/CompilerLauncher/{C-env-launch-Build-stdout.txt => C-launch-env-Build-stdout.txt} (100%) rename Tests/RunCMake/CompilerLauncher/{CUDA-env-launch-Build-stdout.txt => CUDA-launch-env-Build-stdout.txt} (100%) rename Tests/RunCMake/CompilerLauncher/{CXX-env-launch-Build-stdout.txt => CXX-launch-env-Build-stdout.txt} (100%) rename Tests/RunCMake/CompilerLauncher/{Fortran-env-launch-Build-stdout.txt => Fortran-launch-env-Build-stdout.txt} (100%) rename Tests/RunCMake/CompilerLauncher/{ISPC-env-launch-Build-stdout.txt => ISPC-launch-env-Build-stdout.txt} (100%) diff --git a/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-launch-env-Build-stdout.txt similarity index 100% rename from Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt rename to Tests/RunCMake/CompilerLauncher/C-launch-env-Build-stdout.txt diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env-Build-stdout.txt similarity index 100% rename from Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt rename to Tests/RunCMake/CompilerLauncher/CUDA-launch-env-Build-stdout.txt diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-launch-env-Build-stdout.txt similarity index 100% rename from Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt rename to Tests/RunCMake/CompilerLauncher/CXX-launch-env-Build-stdout.txt diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env-Build-stdout.txt similarity index 100% rename from Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt rename to Tests/RunCMake/CompilerLauncher/Fortran-launch-env-Build-stdout.txt diff --git a/Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/ISPC-launch-env-Build-stdout.txt similarity index 100% rename from Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt rename to Tests/RunCMake/CompilerLauncher/ISPC-launch-env-Build-stdout.txt diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake index 293d7119940..787282a8189 100644 --- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -1,7 +1,7 @@ include(RunCMake) function(run_compiler_launcher lang) - # Use a single build tree for tests without cleaning. + # Preserve build tree so we can reuse it for the ${lang}-Build subtest below set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-build) set(RunCMake_TEST_NO_CLEAN 1) file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") From 92c8b83641eae61700d16602e0b60d9c9c6f3b15 Mon Sep 17 00:00:00 2001 From: Bobby D Reynolds Date: Tue, 18 May 2021 08:53:12 -0700 Subject: [PATCH 0535/1519] cmNinjaNormalTargetGenerator: Fix "Language" rule variable Fixes: commit 3bc63e99e4 (Refactor: Prepare Ninja generator for multi-config, 2019-11-14, v3.17.0-rc1~290^2~3) --- Source/cmNinjaNormalTargetGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 4c33334aeb1..03fc0b4a6d6 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -368,7 +368,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str(); std::string lang = this->TargetLinkLanguage(config); - vars.Language = config.c_str(); + vars.Language = lang.c_str(); vars.AIXExports = "$AIX_EXPORTS"; if (this->TargetLinkLanguage(config) == "Swift") { From ae108418ae45aff7740605bb7add3843b050d226 Mon Sep 17 00:00:00 2001 From: Bobby D Reynolds Date: Tue, 18 May 2021 08:57:02 -0700 Subject: [PATCH 0536/1519] Launchers: Support setting linker launchers Fixes: #18316 --- Auxiliary/vim/syntax/cmake.vim | 4 ++ Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst | 13 +++++++ Help/manual/cmake-env-variables.7.rst | 1 + Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/LANG_LINKER_LAUNCHER.rst | 16 ++++++++ Help/release/dev/linker-launcher.rst | 7 ++++ Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst | 11 ++++++ Modules/CMakeCInformation.cmake | 5 +++ Modules/CMakeCXXInformation.cmake | 5 +++ Modules/CMakeOBJCInformation.cmake | 5 +++ Modules/CMakeOBJCXXInformation.cmake | 5 +++ Source/cmCommonTargetGenerator.cxx | 22 +++++++++++ Source/cmCommonTargetGenerator.h | 2 + .../cmMakefileExecutableTargetGenerator.cxx | 6 +++ Source/cmMakefileLibraryTargetGenerator.cxx | 6 +++ Source/cmNinjaNormalTargetGenerator.cxx | 5 +++ Source/cmRulePlaceholderExpander.cxx | 20 +++++++++- Source/cmRulePlaceholderExpander.h | 1 + Source/cmTarget.cxx | 4 ++ Tests/RunCMake/CMakeLists.txt | 2 + .../LinkerLauncher/C-Build-stdout.txt | 1 + Tests/RunCMake/LinkerLauncher/C-common.cmake | 3 ++ .../LinkerLauncher/C-env-Build-stdout.txt | 1 + Tests/RunCMake/LinkerLauncher/C-env.cmake | 1 + .../LinkerLauncher/C-launch-Build-stdout.txt | 1 + .../C-launch-env-Build-stdout.txt | 1 + .../LinkerLauncher/C-launch-env.cmake | 3 ++ Tests/RunCMake/LinkerLauncher/C-launch.cmake | 3 ++ Tests/RunCMake/LinkerLauncher/C.cmake | 2 + Tests/RunCMake/LinkerLauncher/CMakeLists.txt | 3 ++ .../LinkerLauncher/CXX-Build-stdout.txt | 1 + .../RunCMake/LinkerLauncher/CXX-common.cmake | 3 ++ .../LinkerLauncher/CXX-env-Build-stdout.txt | 1 + Tests/RunCMake/LinkerLauncher/CXX-env.cmake | 1 + .../CXX-launch-Build-stdout.txt | 1 + .../CXX-launch-env-Build-stdout.txt | 1 + .../LinkerLauncher/CXX-launch-env.cmake | 3 ++ .../RunCMake/LinkerLauncher/CXX-launch.cmake | 3 ++ Tests/RunCMake/LinkerLauncher/CXX.cmake | 2 + .../LinkerLauncher/OBJC-Build-stdout.txt | 1 + .../RunCMake/LinkerLauncher/OBJC-common.cmake | 3 ++ .../LinkerLauncher/OBJC-env-Build-stdout.txt | 1 + Tests/RunCMake/LinkerLauncher/OBJC-env.cmake | 1 + .../OBJC-launch-Build-stdout.txt | 1 + .../OBJC-launch-env-Build-stdout.txt | 1 + .../LinkerLauncher/OBJC-launch-env.cmake | 3 ++ .../RunCMake/LinkerLauncher/OBJC-launch.cmake | 3 ++ Tests/RunCMake/LinkerLauncher/OBJC.cmake | 2 + .../LinkerLauncher/OBJCXX-Build-stdout.txt | 1 + .../LinkerLauncher/OBJCXX-common.cmake | 3 ++ .../OBJCXX-env-Build-stdout.txt | 1 + .../RunCMake/LinkerLauncher/OBJCXX-env.cmake | 1 + .../OBJCXX-launch-Build-stdout.txt | 1 + .../OBJCXX-launch-env-Build-stdout.txt | 1 + .../LinkerLauncher/OBJCXX-launch-env.cmake | 3 ++ .../LinkerLauncher/OBJCXX-launch.cmake | 3 ++ Tests/RunCMake/LinkerLauncher/OBJCXX.cmake | 2 + .../LinkerLauncher/RunCMakeTest.cmake | 37 +++++++++++++++++++ Tests/RunCMake/LinkerLauncher/main.c | 4 ++ Tests/RunCMake/LinkerLauncher/main.cxx | 4 ++ Tests/RunCMake/LinkerLauncher/main.m | 4 ++ Tests/RunCMake/LinkerLauncher/main.mm | 4 ++ 63 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst create mode 100644 Help/prop_tgt/LANG_LINKER_LAUNCHER.rst create mode 100644 Help/release/dev/linker-launcher.rst create mode 100644 Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst create mode 100644 Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/C-common.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/C-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/C-launch-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/C-launch.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/C.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/CMakeLists.txt create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-common.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/CXX-launch.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/CXX.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-common.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJC.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/OBJCXX.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/LinkerLauncher/main.c create mode 100644 Tests/RunCMake/LinkerLauncher/main.cxx create mode 100644 Tests/RunCMake/LinkerLauncher/main.m create mode 100644 Tests/RunCMake/LinkerLauncher/main.mm diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 611f72a05c0..d2a04fec2b7 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -905,6 +905,7 @@ syn keyword cmakeVariable contained \ CMAKE_CXX_INCLUDE_WHAT_YOU_USE \ CMAKE_CXX_INIT \ CMAKE_CXX_LIBRARY_ARCHITECTURE + \ CMAKE_CXX_LINKER_LAUNCHER \ CMAKE_CXX_LINKER_PREFERENCE \ CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES \ CMAKE_CXX_LINKER_WRAPPER_FLAG @@ -970,6 +971,7 @@ syn keyword cmakeVariable contained \ CMAKE_C_INCLUDE_WHAT_YOU_USE \ CMAKE_C_INIT \ CMAKE_C_LIBRARY_ARCHITECTURE + \ CMAKE_C_LINKER_LAUNCHER \ CMAKE_C_LINKER_PREFERENCE \ CMAKE_C_LINKER_PREFERENCE_PROPAGATES \ CMAKE_C_LINKER_WRAPPER_FLAG @@ -1263,10 +1265,12 @@ syn keyword cmakeVariable contained \ CMAKE_NO_SYSTEM_FROM_IMPORTED \ CMAKE_OBJCXX_CLANG_TIDY \ CMAKE_OBJCXX_EXTENSIONS + \ CMAKE_OBJCXX_LINKER_LAUNCHER \ CMAKE_OBJCXX_STANDARD \ CMAKE_OBJCXX_STANDARD_REQUIRED \ CMAKE_OBJC_CLANG_TIDY \ CMAKE_OBJC_EXTENSIONS + \ CMAKE_OBJC_LINKER_LAUNCHER \ CMAKE_OBJC_STANDARD \ CMAKE_OBJC_STANDARD_REQUIRED \ CMAKE_OBJECT_PATH_MAX diff --git a/Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst b/Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst new file mode 100644 index 00000000000..6251d9c75d0 --- /dev/null +++ b/Help/envvar/CMAKE_LANG_LINKER_LAUNCHER.rst @@ -0,0 +1,13 @@ +CMAKE__LINKER_LAUNCHER +---------------------------- + +.. versionadded:: 3.21 + +.. include:: ENV_VAR.txt + +Default launcher to use when linking a target of the specified language. Will +only be used by CMake to initialize the variable on the first configuration. +Afterwards, it is available through the cache setting of the variable of the +same name. For any configuration run (including the first), the environment +variable will be ignored if the :variable:`CMAKE__LINKER_LAUNCHER` +variable is defined. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index bc1fa1d8526..8932abf7e42 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -37,6 +37,7 @@ Environment Variables that Control the Build /envvar/CMAKE_GENERATOR_PLATFORM /envvar/CMAKE_GENERATOR_TOOLSET /envvar/CMAKE_LANG_COMPILER_LAUNCHER + /envvar/CMAKE_LANG_LINKER_LAUNCHER /envvar/CMAKE_MSVCIDE_RUN_PATH /envvar/CMAKE_NO_VERBOSE /envvar/CMAKE_OSX_ARCHITECTURES diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 4f2c1b0290b..0a3e36b3ceb 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -272,6 +272,7 @@ Properties on Targets /prop_tgt/LANG_CPPCHECK /prop_tgt/LANG_CPPLINT /prop_tgt/LANG_INCLUDE_WHAT_YOU_USE + /prop_tgt/LANG_LINKER_LAUNCHER /prop_tgt/LANG_VISIBILITY_PRESET /prop_tgt/LIBRARY_OUTPUT_DIRECTORY /prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 0720d49dc56..873bd89eac1 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -424,6 +424,7 @@ Variables that Control the Build /variable/CMAKE_LANG_CPPCHECK /variable/CMAKE_LANG_CPPLINT /variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE + /variable/CMAKE_LANG_LINKER_LAUNCHER /variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG /variable/CMAKE_LANG_LINK_LIBRARY_FLAG /variable/CMAKE_LANG_VISIBILITY_PRESET diff --git a/Help/prop_tgt/LANG_LINKER_LAUNCHER.rst b/Help/prop_tgt/LANG_LINKER_LAUNCHER.rst new file mode 100644 index 00000000000..f6ca5ad43d7 --- /dev/null +++ b/Help/prop_tgt/LANG_LINKER_LAUNCHER.rst @@ -0,0 +1,16 @@ +_LINKER_LAUNCHER +---------------------- + +.. versionadded:: 3.21 + +This property is implemented only when ```` is ``C``, ``CXX``, +``OBJC``, or ``OBJCXX`` + +Specify a :ref:`semicolon-separated list ` containing a +command line for a linker launching tool. The :ref:`Makefile Generators` and the +:generator:`Ninja` generator will run this tool and pass the linker and its +arguments to the tool. This is useful for tools such as static analyzers. + +This property is initialized by the value of the +:variable:`CMAKE__LINKER_LAUNCHER` variable if it is set when a target is +created. diff --git a/Help/release/dev/linker-launcher.rst b/Help/release/dev/linker-launcher.rst new file mode 100644 index 00000000000..6563347b11e --- /dev/null +++ b/Help/release/dev/linker-launcher.rst @@ -0,0 +1,7 @@ +linker-launcher +--------------- + +* The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to + add linker launcher tools along with the linker for ``C``, ``CXX``, ``OBJC``, and + ``OBJCXX`` languages. See the :variable:`CMAKE__LINKER_LAUNCHER` variable + and :prop_tgt:`_LINKER_LAUNCHER` target property for details. diff --git a/Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst new file mode 100644 index 00000000000..b76b9391b1e --- /dev/null +++ b/Help/variable/CMAKE_LANG_LINKER_LAUNCHER.rst @@ -0,0 +1,11 @@ +CMAKE__LINKER_LAUNCHER +---------------------------- + +.. versionadded:: 3.21 + +Default value for :prop_tgt:`_LINKER_LAUNCHER` target property. This +variable is used to initialize the property on each target as it is created. +This is done only when ```` is ``C``, ``CXX``, ``OBJC``, or ``OBJCXX``. + +This variable is initialized to the :envvar:`CMAKE__LINKER_LAUNCHER` +environment variable if it is set. diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index f6d620f40e9..6be1865755a 100644 --- a/Modules/CMakeCInformation.cmake +++ b/Modules/CMakeCInformation.cmake @@ -115,6 +115,11 @@ if(NOT CMAKE_C_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_C_COMPILER_LAUNCHER}) CACHE STRING "Compiler launcher for C.") endif() +if(NOT CMAKE_C_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_C_LINKER_LAUNCHER}) + set(CMAKE_C_LINKER_LAUNCHER "$ENV{CMAKE_C_LINKER_LAUNCHER}" + CACHE STRING "Linker launcher for C.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rule variables diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake index dbb4366757c..944d236097c 100644 --- a/Modules/CMakeCXXInformation.cmake +++ b/Modules/CMakeCXXInformation.cmake @@ -212,6 +212,11 @@ if(NOT CMAKE_CXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_CXX_COMPILER_LAUNCHER}) CACHE STRING "Compiler launcher for CXX.") endif() +if(NOT CMAKE_CXX_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_CXX_LINKER_LAUNCHER}) + set(CMAKE_CXX_LINKER_LAUNCHER "$ENV{CMAKE_CXX_LINKER_LAUNCHER}" + CACHE STRING "Linker launcher for CXX.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rules: diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake index d5301917532..ac67d013cc4 100644 --- a/Modules/CMakeOBJCInformation.cmake +++ b/Modules/CMakeOBJCInformation.cmake @@ -115,6 +115,11 @@ if(NOT CMAKE_OBJC_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_OBJC_COMPILER_LAUNCHER CACHE STRING "Compiler launcher for OBJC.") endif() +if(NOT CMAKE_OBJC_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_OBJC_LINKER_LAUNCHER}) + set(CMAKE_OBJC_LINKER_LAUNCHER "$ENV{CMAKE_OBJC_LINKER_LAUNCHER}" + CACHE STRING "Linker launcher for OBJC.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rule variables diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake index 7a3b9d7d078..70e8579a90b 100644 --- a/Modules/CMakeOBJCXXInformation.cmake +++ b/Modules/CMakeOBJCXXInformation.cmake @@ -208,6 +208,11 @@ if(NOT CMAKE_OBJCXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_OBJCXX_COMPILER_LAUN CACHE STRING "Compiler launcher for OBJCXX.") endif() +if(NOT CMAKE_OBJCXX_LINKER_LAUNCHER AND DEFINED ENV{CMAKE_OBJCXX_LINKER_LAUNCHER}) + set(CMAKE_OBJCXX_LINKER_LAUNCHER "$ENV{CMAKE_OBJCXX_LINKER_LAUNCHER}" + CACHE STRING "Linker launcher for OBJCXX.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rules: diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 0c5a7dfae2a..7c2e20c0164 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -15,6 +15,7 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmProperty.h" +#include "cmRange.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -291,3 +292,24 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, this->LocalCommonGenerator->AppendFlags(flags, vflag.str()); } } + +std::string cmCommonTargetGenerator::GetLinkerLauncher( + const std::string& config) +{ + std::string lang = this->GeneratorTarget->GetLinkerLanguage(config); + cmProp launcherProp = + this->GeneratorTarget->GetProperty(lang + "_LINKER_LAUNCHER"); + if (cmNonempty(launcherProp)) { + // Convert ;-delimited list to single string + std::vector args = cmExpandedList(*launcherProp, true); + if (!args.empty()) { + args[0] = this->LocalCommonGenerator->ConvertToOutputFormat( + args[0], cmOutputConverter::SHELL); + for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) { + i = this->LocalCommonGenerator->EscapeForShell(i); + } + return cmJoin(args, " "); + } + } + return std::string(); +} diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index fba6b0a5fcf..a156a41aff0 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -64,6 +64,8 @@ class cmCommonTargetGenerator const std::string& config) const; std::string ComputeTargetCompilePDB(const std::string& config) const; + std::string GetLinkerLauncher(const std::string& config); + private: using ByLanguageMap = std::map; struct ByConfig diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 2940b8b8e9c..3a2744e3feb 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -571,6 +571,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.LinkFlags = linkFlags.c_str(); vars.Manifests = manifests.c_str(); + std::string linkerLauncher = + this->GetLinkerLauncher(this->GetConfigName()); + if (cmNonempty(linkerLauncher)) { + vars.Launcher = linkerLauncher.c_str(); + } + if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { std::string cmakeCommand = cmStrCat(this->LocalGenerator->ConvertToOutputFormat( diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index f96bcdee40e..d0e3837dd57 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -804,6 +804,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.LanguageCompileFlags = langFlags.c_str(); + std::string linkerLauncher = + this->GetLinkerLauncher(this->GetConfigName()); + if (cmNonempty(linkerLauncher)) { + vars.Launcher = linkerLauncher.c_str(); + } + std::string launcher; cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, "RULE_LAUNCH_LINK"); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 03fc0b4a6d6..9a48047be0c 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -456,6 +456,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, vars.LanguageCompileFlags = langFlags.c_str(); } + std::string linkerLauncher = this->GetLinkerLauncher(config); + if (cmNonempty(linkerLauncher)) { + vars.Launcher = linkerLauncher.c_str(); + } + std::string launcher; cmProp val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index d00bbdf0444..7480aebe243 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -6,6 +6,7 @@ #include #include "cmOutputConverter.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmRulePlaceholderExpander::cmRulePlaceholderExpander( @@ -280,6 +281,13 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( this->VariableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_SYSROOT"]; + if (compIt->second == replaceValues.Language && replaceValues.Launcher) { + // Add launcher as part of expansion so that it always appears + // immediately before the command itself, regardless of whether the + // overall rule template contains other content at the front. + ret = cmStrCat(replaceValues.Launcher, " ", ret); + } + // if there are required arguments to the compiler add it // to the compiler string if (!compilerArg1.empty()) { @@ -317,7 +325,17 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( auto mapIt = this->VariableMappings.find(variable); if (mapIt != this->VariableMappings.end()) { if (variable.find("_FLAG") == std::string::npos) { - return outputConverter->ConvertToOutputForExisting(mapIt->second); + std::string ret = + outputConverter->ConvertToOutputForExisting(mapIt->second); + + if (replaceValues.Launcher && variable == "CMAKE_LINKER") { + // Add launcher as part of expansion so that it always appears + // immediately before the command itself, regardless of whether the + // overall rule template contains other content at the front. + ret = cmStrCat(replaceValues.Launcher, " ", ret); + } + + return ret; } return mapIt->second; } diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index f8dc36837f8..c22e0fa9fb3 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -67,6 +67,7 @@ class cmRulePlaceholderExpander const char* ISPCHeader = nullptr; const char* Fatbinary = nullptr; const char* RegisterFile = nullptr; + const char* Launcher = nullptr; }; // Expand rule variables in CMake of the type found in language rules diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 29e361c3673..6f2e44779ee 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -354,11 +354,13 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("C_CPPLINT"); initProp("C_CPPCHECK"); initProp("C_INCLUDE_WHAT_YOU_USE"); + initProp("C_LINKER_LAUNCHER"); initProp("LINK_WHAT_YOU_USE"); initProp("CXX_CLANG_TIDY"); initProp("CXX_CPPLINT"); initProp("CXX_CPPCHECK"); initProp("CXX_INCLUDE_WHAT_YOU_USE"); + initProp("CXX_LINKER_LAUNCHER"); initProp("CUDA_SEPARABLE_COMPILATION"); initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); initProp("CUDA_RUNTIME_LIBRARY"); @@ -374,7 +376,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("LINK_SEARCH_START_STATIC"); initProp("LINK_SEARCH_END_STATIC"); initProp("OBJC_CLANG_TIDY"); + initProp("OBJC_LINKER_LAUNCHER"); initProp("OBJCXX_CLANG_TIDY"); + initProp("OBJCXX_LINKER_LAUNCHER"); initProp("Swift_LANGUAGE_VERSION"); initProp("Swift_MODULE_DIRECTORY"); initProp("VS_JUST_MY_CODE_DEBUGGING"); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 14a7fa3cbcf..d02d7a2fd57 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -732,12 +732,14 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") endif() if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU") list(APPEND CompilerLauncher_ARGS -DCMake_TEST_OBJC=1) + list(APPEND LinkerLauncher_ARGS -DCMake_TEST_OBJC=1) endif() add_RunCMake_test(CompilerLauncher) set_property(TEST RunCMake.CompilerLauncher APPEND PROPERTY LABELS "CUDA;ISPC") add_RunCMake_test(ctest_labels_for_subprojects) add_RunCMake_test(CompilerArgs) + add_RunCMake_test(LinkerLauncher) endif() set(cpack_tests diff --git a/Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/C-common.cmake b/Tests/RunCMake/LinkerLauncher/C-common.cmake new file mode 100644 index 00000000000..96b004bda9a --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-common.cmake @@ -0,0 +1,3 @@ +enable_language(C) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.c) diff --git a/Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/C-env.cmake b/Tests/RunCMake/LinkerLauncher/C-env.cmake new file mode 100644 index 00000000000..09b5167b03f --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-env.cmake @@ -0,0 +1 @@ +include(C-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-launch-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/C-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/C-launch-env.cmake new file mode 100644 index 00000000000..68abcb53b95 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(C-env.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/C-launch.cmake b/Tests/RunCMake/LinkerLauncher/C-launch.cmake new file mode 100644 index 00000000000..e66ca203e2f --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(C.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/C.cmake b/Tests/RunCMake/LinkerLauncher/C.cmake new file mode 100644 index 00000000000..b55ca8e57fb --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/C.cmake @@ -0,0 +1,2 @@ +set(CMAKE_C_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(C-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/CMakeLists.txt b/Tests/RunCMake/LinkerLauncher/CMakeLists.txt new file mode 100644 index 00000000000..7cabeb68b2f --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.20) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/CXX-common.cmake b/Tests/RunCMake/LinkerLauncher/CXX-common.cmake new file mode 100644 index 00000000000..3d2ee001274 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-common.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.cxx) diff --git a/Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/CXX-env.cmake b/Tests/RunCMake/LinkerLauncher/CXX-env.cmake new file mode 100644 index 00000000000..db36956a762 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-env.cmake @@ -0,0 +1 @@ +include(CXX-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-launch-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake new file mode 100644 index 00000000000..a65cc898511 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(CXX-env.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/CXX-launch.cmake b/Tests/RunCMake/LinkerLauncher/CXX-launch.cmake new file mode 100644 index 00000000000..3002c9d688c --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(CXX.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/CXX.cmake b/Tests/RunCMake/LinkerLauncher/CXX.cmake new file mode 100644 index 00000000000..4326614acd6 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/CXX.cmake @@ -0,0 +1,2 @@ +set(CMAKE_CXX_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(CXX-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-common.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-common.cmake new file mode 100644 index 00000000000..7b565f4caf3 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-common.cmake @@ -0,0 +1,3 @@ +enable_language(OBJC) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.m) diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-env.cmake new file mode 100644 index 00000000000..949e88d312f --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-env.cmake @@ -0,0 +1 @@ +include(OBJC-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake new file mode 100644 index 00000000000..1cf13d3df6d --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJC-env.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake b/Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake new file mode 100644 index 00000000000..43e852164ce --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJC.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJC.cmake b/Tests/RunCMake/LinkerLauncher/OBJC.cmake new file mode 100644 index 00000000000..e0360b386ac --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJC.cmake @@ -0,0 +1,2 @@ +set(CMAKE_OBJC_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(OBJC-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake new file mode 100644 index 00000000000..e2ee4eb2dfd --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-common.cmake @@ -0,0 +1,3 @@ +enable_language(OBJCXX) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.mm) diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake new file mode 100644 index 00000000000..3ed966d1905 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-env.cmake @@ -0,0 +1 @@ +include(OBJCXX-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake new file mode 100644 index 00000000000..04c916a18a5 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJCXX-env.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake new file mode 100644 index 00000000000..5a54bffeb38 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(OBJCXX.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/OBJCXX.cmake b/Tests/RunCMake/LinkerLauncher/OBJCXX.cmake new file mode 100644 index 00000000000..3667745378a --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/OBJCXX.cmake @@ -0,0 +1,2 @@ +set(CMAKE_OBJCXX_LINKER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(OBJCXX-common.cmake) diff --git a/Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake new file mode 100644 index 00000000000..8f2bf63f4c3 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/RunCMakeTest.cmake @@ -0,0 +1,37 @@ +include(RunCMake) + +function(run_linker_launcher lang) + # Preserve build tree so we can reuse it for the ${lang}-Build subtest below + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${lang}-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${lang}) + + set(RunCMake_TEST_OUTPUT_MERGE 1) + if("${RunCMake_GENERATOR}" MATCHES "Ninja") + set(verbose_args -- -v) + endif() + run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args}) +endfunction() + +function(run_linker_launcher_env lang) + string(REGEX REPLACE "-.*" "" core_lang "${lang}") + set(ENV{CMAKE_${core_lang}_LINKER_LAUNCHER} "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") + run_linker_launcher(${lang}) + unset(ENV{CMAKE_${core_lang}_LINKER_LAUNCHER}) +endfunction() + +set(langs C CXX) +if(CMake_TEST_OBJC) + list(APPEND langs OBJC OBJCXX) +endif() + +foreach(lang ${langs}) + run_linker_launcher(${lang}) + run_linker_launcher_env(${lang}-env) + if(NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") + run_linker_launcher(${lang}-launch) + run_linker_launcher_env(${lang}-launch-env) + endif() +endforeach() diff --git a/Tests/RunCMake/LinkerLauncher/main.c b/Tests/RunCMake/LinkerLauncher/main.c new file mode 100644 index 00000000000..8488f4e58fe --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/LinkerLauncher/main.cxx b/Tests/RunCMake/LinkerLauncher/main.cxx new file mode 100644 index 00000000000..f8b643afbf2 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/main.cxx @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/LinkerLauncher/main.m b/Tests/RunCMake/LinkerLauncher/main.m new file mode 100644 index 00000000000..8488f4e58fe --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/main.m @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/LinkerLauncher/main.mm b/Tests/RunCMake/LinkerLauncher/main.mm new file mode 100644 index 00000000000..f8b643afbf2 --- /dev/null +++ b/Tests/RunCMake/LinkerLauncher/main.mm @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} From 59d9fa713158610b6183b214841d0f272ee6f900 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 May 2021 10:57:17 -0400 Subject: [PATCH 0537/1519] gitlab-ci: Update Windows builds to MSVC 19.29-16.10 toolset --- .gitlab/os-windows.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index cd2f1682c6d..fb72ff14ee8 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -38,7 +38,7 @@ CMAKE_CONFIGURATION: windows_vs2019_x64_ninja VCVARSALL: "${VS160COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat" VCVARSPLATFORM: "x64" - VCVARSVERSION: "14.28.29910" + VCVARSVERSION: "14.29.30037" ### External testing @@ -49,7 +49,7 @@ CMAKE_CONFIGURATION: windows_vs2019_x64 CMAKE_GENERATOR: "Visual Studio 16 2019" CMAKE_GENERATOR_PLATFORM: "x64" - CMAKE_GENERATOR_TOOLSET: "v142,version=14.28.29910" + CMAKE_GENERATOR_TOOLSET: "v142,version=14.29.30037" CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true" ## Tags @@ -60,7 +60,7 @@ - windows - shell - vs2019 - - msvc-19.28-16.9 + - msvc-19.29-16.10 - nonconcurrent .windows_builder_ext_tags: @@ -69,7 +69,7 @@ - windows - shell - vs2019 - - msvc-19.28-16.9 + - msvc-19.29-16.10 - concurrent ## Windows-specific scripts From 18e42d3e63f7807495be8fc4c2159629a30c1144 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:36:07 -0400 Subject: [PATCH 0538/1519] cmGeneratorExpressionNode: Constify local variable --- Source/cmGeneratorExpressionNode.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 71251705a89..8030b6466af 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1681,7 +1681,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode // Create the cmSourceFile instances in the referencing directory. cmMakefile* mf = context->LG->GetMakefile(); - for (std::string& o : objects) { + for (std::string const& o : objects) { mf->AddTargetObject(tgtName, o); } From ddffbb8adbfb12ecc2ab920434006a40bfeae326 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:37:03 -0400 Subject: [PATCH 0539/1519] cmMakefile: Register explicit object sources more efficiently `AddTargetObject` knows the location of object files. --- Source/cmMakefile.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ffe94bad413..908b3f0d25a 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3454,7 +3454,8 @@ void cmMakefile::CreateGeneratedOutputs( void cmMakefile::AddTargetObject(std::string const& tgtName, std::string const& objFile) { - cmSourceFile* sf = this->GetOrCreateSource(objFile, true); + cmSourceFile* sf = + this->GetOrCreateSource(objFile, true, cmSourceFileLocationKind::Known); sf->SetObjectLibrary(tgtName); sf->SetProperty("EXTERNAL_OBJECT", "1"); #if !defined(CMAKE_BOOTSTRAP) From 96809a8541513c7adb52a65766154d417281227e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:43:47 -0400 Subject: [PATCH 0540/1519] cmGeneratorTarget: Give temporary link impl item an explicit name --- Source/cmGeneratorTarget.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a7d825deb96..ca18f5326e1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -7490,8 +7490,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg), - evaluated != *le); + cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg); + impl.Libraries.emplace_back(std::move(item), evaluated != *le); } std::set const& seenProps = cge->GetSeenTargetProperties(); From 7f506b95a78a3238d3481539810441ca955a0901 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:44:41 -0400 Subject: [PATCH 0541/1519] cmGeneratorTarget: Refactor link item lookup Look up items individually so the call sites can do something with the result besides appending to a vector. --- Source/cmGeneratorTarget.cxx | 37 +++++++++++++++---------- Source/cmGeneratorTarget.h | 5 ++-- Source/cmTargetLinkLibrariesCommand.cxx | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ca18f5326e1..51742cf67f9 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6255,22 +6255,21 @@ bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, return false; } -void cmGeneratorTarget::LookupLinkItems(std::vector const& names, - cmListFileBacktrace const& bt, - std::vector& items) const +cm::optional cmGeneratorTarget::LookupLinkItem( + std::string const& n, cmListFileBacktrace const& bt) const { + cm::optional maybeItem; cmLocalGenerator const* lg = this->LocalGenerator; - for (std::string const& n : names) { - if (this->IsLinkLookupScope(n, lg)) { - continue; - } + if (this->IsLinkLookupScope(n, lg)) { + return maybeItem; + } - std::string name = this->CheckCMP0004(n); - if (name == this->GetName() || name.empty()) { - continue; - } - items.push_back(this->ResolveLinkItem(name, bt, lg)); + std::string name = this->CheckCMP0004(n); + if (name == this->GetName() || name.empty()) { + return maybeItem; } + maybeItem = this->ResolveLinkItem(name, bt, lg); + return maybeItem; } void cmGeneratorTarget::ExpandLinkItems( @@ -6295,7 +6294,12 @@ void cmGeneratorTarget::ExpandLinkItems( cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this, headTarget->LinkerLanguage), libs); - this->LookupLinkItems(libs, cge->GetBacktrace(), items); + for (std::string const& lib : libs) { + if (cm::optional maybeItem = + this->LookupLinkItem(lib, cge->GetBacktrace())) { + items.emplace_back(std::move(*maybeItem)); + } + } hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition(); hadLinkLanguageSensitiveCondition = @@ -6903,7 +6907,12 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); std::vector deps = cmExpandedList(info->SharedDeps); - this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); + for (std::string const& dep : deps) { + if (cm::optional maybeItem = + this->LookupLinkItem(dep, cmListFileBacktrace())) { + iface.SharedDeps.emplace_back(std::move(*maybeItem)); + } + } } return &iface; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 2935e0bce0c..dbc47b8f7e1 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1039,9 +1039,8 @@ class cmGeneratorTarget bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const; - void LookupLinkItems(std::vector const& names, - cmListFileBacktrace const& bt, - std::vector& items) const; + cm::optional LookupLinkItem(std::string const& n, + cmListFileBacktrace const& bt) const; std::vector> GetSourceFilePaths( std::string const& config) const; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index aecc18e3ac6..3423b30dcd4 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -565,7 +565,7 @@ void TLL::AffectsProperty(std::string const& prop) if (!this->EncodeRemoteReference) { return; } - // Add a wrapper to the expression to tell LookupLinkItems to look up + // Add a wrapper to the expression to tell LookupLinkItem to look up // names in the caller's directory. if (this->Props.insert(prop).second) { this->Target->AppendProperty(prop, this->DirectoryId); From 83ad066ed10ccabc4331c4b620ad6a4fa0cd36ba Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 May 2021 14:58:11 -0400 Subject: [PATCH 0542/1519] cmComputeTargetDepends: Factor out helper to add object library dependency --- Source/cmComputeTargetDepends.cxx | 49 ++++++++++++++++++------------- Source/cmComputeTargetDepends.h | 3 ++ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 85a9d9cf12e..0f234170f84 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -233,26 +233,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::vector objectFiles; depender->GetExternalObjects(objectFiles, it); for (cmSourceFile const* o : objectFiles) { - std::string const& objLib = o->GetObjectLibrary(); - if (!objLib.empty()) { - cmLinkItem const& objItem = - depender->ResolveLinkItem(objLib, cmListFileBacktrace()); - if (emitted.insert(objItem).second) { - if (depender->GetType() != cmStateEnums::EXECUTABLE && - depender->GetType() != cmStateEnums::STATIC_LIBRARY && - depender->GetType() != cmStateEnums::SHARED_LIBRARY && - depender->GetType() != cmStateEnums::MODULE_LIBRARY && - depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { - this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - "Only executables and libraries may reference target objects.", - depender->GetBacktrace()); - return; - } - const_cast(depender)->Target->AddUtility( - objLib, false); - } - } + this->AddObjectDepends(depender_index, o, emitted); } } } @@ -319,6 +300,34 @@ void cmComputeTargetDepends::AddInterfaceDepends( } } +void cmComputeTargetDepends::AddObjectDepends(int depender_index, + cmSourceFile const* o, + std::set& emitted) +{ + std::string const& objLib = o->GetObjectLibrary(); + if (objLib.empty()) { + return; + } + cmGeneratorTarget const* depender = this->Targets[depender_index]; + cmLinkItem const& objItem = + depender->ResolveLinkItem(objLib, cmListFileBacktrace()); + if (emitted.insert(objItem).second) { + if (depender->GetType() != cmStateEnums::EXECUTABLE && + depender->GetType() != cmStateEnums::STATIC_LIBRARY && + depender->GetType() != cmStateEnums::SHARED_LIBRARY && + depender->GetType() != cmStateEnums::MODULE_LIBRARY && + depender->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "Only executables and libraries may reference target objects.", + depender->GetBacktrace()); + return; + } + const_cast(depender)->Target->AddUtility(objLib, + false); + } +} + void cmComputeTargetDepends::AddTargetDepend(int depender_index, cmLinkItem const& dependee_name, bool linking, bool cross) diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 3517844d6b9..0eab3683d9e 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -16,6 +16,7 @@ class cmComputeComponentGraph; class cmGeneratorTarget; class cmGlobalGenerator; class cmLinkItem; +class cmSourceFile; class cmTargetDependSet; /** \class cmComputeTargetDepends @@ -71,6 +72,8 @@ class cmComputeTargetDepends cmListFileBacktrace const& dependee_backtrace, const std::string& config, std::set& emitted); + void AddObjectDepends(int depender_index, cmSourceFile const* o, + std::set& emitted); cmGlobalGenerator* GlobalGenerator; bool DebugMode; bool NoCycles; From 316cbbe8d570775eb08683a72808ee07bddcd3e0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 May 2021 15:28:25 -0400 Subject: [PATCH 0543/1519] Makefiles: Fix CMAKE_EXPORT_COMPILE_COMMANDS crash with custom compile rule Extend the fix from commit 67e2130c96 (Makefiles: Fix CMAKE_EXPORT_COMPILE_COMMANDS crash with custom compile rule, 2020-11-20, v3.19.1~8^2) to work for the `` placeholder too. Also fix the test case to actually enable `EXPORT_COMPILE_COMMANDS` on the test target. Fixes: #22261 --- Source/cmMakefileTargetGenerator.cxx | 7 +++++-- .../RunCMake/ExportCompileCommands/CustomCompileRule.cmake | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4918bf676a8..5f7f3dc5b16 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -926,8 +926,11 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( compileCommand, vars); std::string workingDirectory = this->LocalGenerator->GetCurrentBinaryDirectory(); - compileCommand.replace(compileCommand.find(langFlags), langFlags.size(), - this->GetFlags(lang, this->GetConfigName())); + std::string::size_type lfPos = compileCommand.find(langFlags); + if (lfPos != std::string::npos) { + compileCommand.replace(lfPos, langFlags.size(), + this->GetFlags(lang, this->GetConfigName())); + } std::string langDefines = std::string("$(") + lang + "_DEFINES)"; std::string::size_type ldPos = compileCommand.find(langDefines); if (ldPos != std::string::npos) { diff --git a/Tests/RunCMake/ExportCompileCommands/CustomCompileRule.cmake b/Tests/RunCMake/ExportCompileCommands/CustomCompileRule.cmake index 12368a29bd7..b1b120f76eb 100644 --- a/Tests/RunCMake/ExportCompileCommands/CustomCompileRule.cmake +++ b/Tests/RunCMake/ExportCompileCommands/CustomCompileRule.cmake @@ -1,5 +1,6 @@ enable_language(C) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) add_library(empty STATIC empty.c) string(REPLACE "" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}") string(REPLACE "" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}") -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +string(REPLACE "" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}") From 7676e11943a6446e3cdc60370a37e4ce9cc548d3 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 29 May 2021 00:01:14 -0400 Subject: [PATCH 0544/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2dda0ce1c20..5252b25a5ba 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210528) +set(CMake_VERSION_PATCH 20210529) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3aaf1d91bf353559aef7ec56ad35924383ed613a Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 29 May 2021 12:45:01 +0300 Subject: [PATCH 0545/1519] MSVC: C++20 final flag, C++23 support Microsoft intends to ship the final C++20 flag in VS 16.11 albeit with a few parts missing due planned ABI breaking changes. The current 16.11 Preview 1 toolchain version is 19.29.30129.3, so let's restrict based on that. --- Modules/Compiler/MSVC-CXX.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 1dfc760f001..f1c7450fad9 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -18,6 +18,7 @@ if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "") set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std:c++14") set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std:c++14") + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.11.25505) set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON) @@ -27,7 +28,13 @@ if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std:c++latest") set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std:c++latest") endif() - if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.12.25835) + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30129) + set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std:c++20") + set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std:c++20") + set(CMAKE_CXX23_STANDARD_COMPILE_OPTION "-std:c++latest") + set(CMAKE_CXX23_EXTENSION_COMPILE_OPTION "-std:c++latest") + elseif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.12.25835) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std:c++latest") set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std:c++latest") endif() From 9411766c352bd7096b9dc286d8763b8236645756 Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 29 May 2021 08:07:28 -0400 Subject: [PATCH 0546/1519] BinUtils: Avoid llvm-objdump versions older than Clang 9 Since commit cf82300a63 (BinUtils: Clarify search logic and make it more consistent, 2021-05-27) we correctly prefer the more-specific name `llvm-objdump` over `objdump` when using Clang. However, this breaks `file(GET_RUNTIME_DEPENDENCIES)` with `llvm-objdump` from Clang 8 and below. Avoid those older versions of `llvm-objdump`. --- Modules/CMakeFindBinUtils.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 9dac4a9b4ef..ec6bc8d8ce3 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -126,7 +126,10 @@ else() list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") list(PREPEND _CMAKE_STRIP_NAMES "llvm-strip") list(PREPEND _CMAKE_NM_NAMES "llvm-nm") - list(PREPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump") + if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}" VERSION_GREATER_EQUAL 9) + # llvm-objdump versions prior to 9 did not support everything we need. + list(PREPEND _CMAKE_OBJDUMP_NAMES "llvm-objdump") + endif() list(PREPEND _CMAKE_OBJCOPY_NAMES "llvm-objcopy") list(PREPEND _CMAKE_READELF_NAMES "llvm-readelf") list(PREPEND _CMAKE_DLLTOOL_NAMES "llvm-dlltool") From 8a4ca110e49c64c4892a37ffe08a91a5a5219acf Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 29 May 2021 09:21:20 -0400 Subject: [PATCH 0547/1519] cmComputeLinkInformation: Improve type safety of item IsPath member Use an enum to avoid implicit conversions to bool. --- Source/cmComputeLinkInformation.cxx | 25 +++++++++++----------- Source/cmComputeLinkInformation.h | 13 ++++++++--- Source/cmGlobalXCodeGenerator.cxx | 8 ++++--- Source/cmLinkLineComputer.cxx | 2 +- Source/cmLinkLineDeviceComputer.cxx | 2 +- Source/cmLocalVisualStudio7Generator.cxx | 2 +- Source/cmVisualStudio10TargetGenerator.cxx | 7 +++--- 7 files changed, 35 insertions(+), 24 deletions(-) diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 5473316daf9..6371286dc06 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -659,14 +659,14 @@ void cmComputeLinkInformation::AddItem(BT const& item, std::string exe = tgt->GetFullPath(config, artifact, true); linkItem += exe; - this->Items.emplace_back(BT(linkItem, item.Backtrace), true, - tgt); + this->Items.emplace_back(BT(linkItem, item.Backtrace), + ItemIsPath::Yes, tgt); this->Depends.push_back(std::move(exe)); } else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Add the interface library as an item so it can be considered as part // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore // this for the actual link line. - this->Items.emplace_back(std::string(), false, tgt); + this->Items.emplace_back(std::string(), ItemIsPath::No, tgt); // Also add the item the interface specifies to be used in its place. std::string const& libName = tgt->GetImportedLibName(config); @@ -1038,10 +1038,10 @@ void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt) if (this->LinkTypeEnabled) { switch (this->CurrentLinkType) { case LinkStatic: - this->Items.emplace_back(this->StaticLinkTypeFlag, false); + this->Items.emplace_back(this->StaticLinkTypeFlag, ItemIsPath::No); break; case LinkShared: - this->Items.emplace_back(this->SharedLinkTypeFlag, false); + this->Items.emplace_back(this->SharedLinkTypeFlag, ItemIsPath::No); break; default: break; @@ -1084,7 +1084,7 @@ void cmComputeLinkInformation::AddTargetItem(BT const& item, } // Now add the full path to the library. - this->Items.emplace_back(item, true, target); + this->Items.emplace_back(item, ItemIsPath::Yes, target); } void cmComputeLinkInformation::AddFullItem(BT const& item) @@ -1138,7 +1138,7 @@ void cmComputeLinkInformation::AddFullItem(BT const& item) } // Now add the full path to the library. - this->Items.emplace_back(item, true); + this->Items.emplace_back(item, ItemIsPath::Yes); } bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) @@ -1226,7 +1226,7 @@ void cmComputeLinkInformation::AddUserItem(BT const& item, this->SetCurrentLinkType(this->StartLinkType); // Use the item verbatim. - this->Items.emplace_back(item, false); + this->Items.emplace_back(item, ItemIsPath::No); return; } @@ -1296,7 +1296,8 @@ void cmComputeLinkInformation::AddUserItem(BT const& item, // Create an option to ask the linker to search for the library. std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix); - this->Items.emplace_back(BT(out, item.Backtrace), false); + this->Items.emplace_back(BT(out, item.Backtrace), + ItemIsPath::No); // Here we could try to find the library the linker will find and // add a runtime information entry for it. It would probably not be @@ -1328,13 +1329,13 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) if (this->GlobalGenerator->IsXcode()) { // Add framework path - it will be handled by Xcode after it's added to // "Link Binary With Libraries" build phase - this->Items.emplace_back(item, true); + this->Items.emplace_back(item, ItemIsPath::Yes); } else { // Add the item using the -framework option. - this->Items.emplace_back(std::string("-framework"), false); + this->Items.emplace_back(std::string("-framework"), ItemIsPath::No); cmOutputConverter converter(this->Makefile->GetStateSnapshot()); fw = converter.EscapeForShell(fw); - this->Items.emplace_back(fw, false); + this->Items.emplace_back(fw, ItemIsPath::No); } } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 4acb99f742a..9afa0eb7a7c 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -35,17 +35,24 @@ class cmComputeLinkInformation ~cmComputeLinkInformation(); bool Compute(); + enum class ItemIsPath + { + No, + Yes, + }; + struct Item { Item() = default; - Item(BT v, bool p, cmGeneratorTarget const* target = nullptr) + Item(BT v, ItemIsPath isPath, + cmGeneratorTarget const* target = nullptr) : Value(std::move(v)) - , IsPath(p) + , IsPath(isPath) , Target(target) { } BT Value; - bool IsPath = true; + ItemIsPath IsPath = ItemIsPath::Yes; cmGeneratorTarget const* Target = nullptr; }; using ItemVector = std::vector; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 009d133805a..693a11c9a1b 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3454,7 +3454,9 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) libItem.Target->GetType() == cmStateEnums::SHARED_LIBRARY || libItem.Target->GetType() == cmStateEnums::MODULE_LIBRARY || libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY)) || - (!libItem.Target && libItem.IsPath && forceLinkPhase))) { + (!libItem.Target && + libItem.IsPath == cmComputeLinkInformation::ItemIsPath::Yes && + forceLinkPhase))) { std::string libName; bool canUseLinkPhase = true; if (libItem.Target) { @@ -3565,7 +3567,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) auto* libTarget = FindXCodeTarget(libItem->Target); cmXCodeObject* buildFile; if (!libTarget) { - if (libItem->IsPath) { + if (libItem->IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { // Get or create a direct file ref in the root project auto cleanPath = libItem->Value.Value; if (cmSystemTools::FileIsFullPath(cleanPath)) { @@ -3724,7 +3726,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) BuildObjectListOrString libPaths(this, true); for (auto const& libItem : configItemMap[configName]) { auto const& libName = *libItem; - if (libName.IsPath) { + if (libName.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { auto cleanPath = libName.Value.Value; if (cmSystemTools::FileIsFullPath(cleanPath)) { cleanPath = cmSystemTools::CollapseFullPath(cleanPath); diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index a3f2968b1c9..6eb8d75a6dc 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -74,7 +74,7 @@ void cmLinkLineComputer::ComputeLinkLibs( } BT linkLib; - if (item.IsPath) { + if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { linkLib.Value += cli.GetLibLinkFileFlag(); linkLib.Value += this->ConvertToOutputFormat( this->ConvertToLinkReference(item.Value.Value)); diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 9cae9266988..2ffff96b9dc 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -111,7 +111,7 @@ void cmLinkLineDeviceComputer::ComputeLinkLibraries( } BT linkLib; - if (item.IsPath) { + if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { // nvcc understands absolute paths to libraries ending in '.a' or '.lib'. // These should be passed to nvlink. Other extensions need to be left // out because nvlink may not understand or need them. Even though it diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index c50cc5dbff1..151470b4e5f 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1254,7 +1254,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( { cmLocalVisualStudio7Generator* lg = this->LocalGenerator; for (auto const& lib : libs) { - if (lib.IsPath) { + if (lib.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string rel = lg->MaybeRelativeToCurBinDir(lib.Value.Value); fout << lg->ConvertToXMLOutputPath(rel) << " "; } else if (!lib.Target || diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1c8b672d227..98d56df32a5 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3391,7 +3391,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( } } - if (l.IsPath) { + if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string path = this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); @@ -3945,7 +3945,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions( using ItemVector = cmComputeLinkInformation::ItemVector; const ItemVector& libs = cli.GetItems(); for (cmComputeLinkInformation::Item const& l : libs) { - if (l.IsPath && cmVS10IsTargetsFile(l.Value.Value)) { + if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes && + cmVS10IsTargetsFile(l.Value.Value)) { std::string path = this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); @@ -4028,7 +4029,7 @@ void cmVisualStudio10TargetGenerator::AddLibraries( } } - if (l.IsPath) { + if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { std::string path = this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value); ConvertToWindowsSlash(path); From f530b3a26729d0820c804e312b72e0061d6eeb4b Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 29 May 2021 08:26:45 -0400 Subject: [PATCH 0548/1519] OpenWatcom: Add infrastructure to link to object files --- Modules/Compiler/OpenWatcom.cmake | 1 + Source/cmComputeLinkDepends.h | 1 + Source/cmComputeLinkInformation.cxx | 27 +++++++++++++++++++-------- Source/cmComputeLinkInformation.h | 20 ++++++++++++++++++-- Source/cmLinkLineComputer.cxx | 6 +++++- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/Modules/Compiler/OpenWatcom.cmake b/Modules/Compiler/OpenWatcom.cmake index ec369081af6..8cfe6838ddb 100644 --- a/Modules/Compiler/OpenWatcom.cmake +++ b/Modules/Compiler/OpenWatcom.cmake @@ -7,6 +7,7 @@ include_guard() set(CMAKE_LIBRARY_PATH_FLAG "libpath ") set(CMAKE_LINK_LIBRARY_FLAG "library ") set(CMAKE_LINK_LIBRARY_FILE_FLAG "library ") +set(CMAKE_LINK_OBJECT_FILE_FLAG "file ") if(CMAKE_VERBOSE_MAKEFILE) set(CMAKE_WCL_QUIET) diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 902500aaf3b..00fbd597299 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -42,6 +42,7 @@ class cmComputeLinkDepends cmGeneratorTarget const* Target = nullptr; bool IsSharedDep = false; bool IsFlag = false; + bool IsObject = false; }; using EntryVector = std::vector; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 6371286dc06..2647998ce12 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -309,6 +309,13 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->LibLinkSuffix = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); } + if (cmProp flag = this->Makefile->GetDefinition( + "CMAKE_" + this->LinkLanguage + "_LINK_OBJECT_FILE_FLAG")) { + this->ObjLinkFileFlag = *flag; + } else { + this->ObjLinkFileFlag = + this->Makefile->GetSafeDefinition("CMAKE_LINK_OBJECT_FILE_FLAG"); + } // Get options needed to specify RPATHs. this->RuntimeUseChrpath = false; @@ -514,7 +521,8 @@ bool cmComputeLinkInformation::Compute() if (linkEntry.IsSharedDep) { this->AddSharedDepItem(linkEntry.Item, linkEntry.Target); } else { - this->AddItem(linkEntry.Item, linkEntry.Target); + this->AddItem(linkEntry.Item, linkEntry.Target, + linkEntry.IsObject ? ItemIsObject::Yes : ItemIsObject::No); } } @@ -634,7 +642,8 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) } void cmComputeLinkInformation::AddItem(BT const& item, - cmGeneratorTarget const* tgt) + cmGeneratorTarget const* tgt, + ItemIsObject isObject) { // Compute the proper name to use to link this library. const std::string& config = this->Config; @@ -660,13 +669,14 @@ void cmComputeLinkInformation::AddItem(BT const& item, std::string exe = tgt->GetFullPath(config, artifact, true); linkItem += exe; this->Items.emplace_back(BT(linkItem, item.Backtrace), - ItemIsPath::Yes, tgt); + ItemIsPath::Yes, ItemIsObject::No, tgt); this->Depends.push_back(std::move(exe)); } else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Add the interface library as an item so it can be considered as part // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore // this for the actual link line. - this->Items.emplace_back(std::string(), ItemIsPath::No, tgt); + this->Items.emplace_back(std::string(), ItemIsPath::No, ItemIsObject::No, + tgt); // Also add the item the interface specifies to be used in its place. std::string const& libName = tgt->GetImportedLibName(config); @@ -719,7 +729,7 @@ void cmComputeLinkInformation::AddItem(BT const& item, } else { // Use the full path given to the library file. this->Depends.push_back(item.Value); - this->AddFullItem(item); + this->AddFullItem(item, isObject); this->AddLibraryRuntimeInfo(item.Value); } } else { @@ -1084,10 +1094,11 @@ void cmComputeLinkInformation::AddTargetItem(BT const& item, } // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes, target); + this->Items.emplace_back(item, ItemIsPath::Yes, ItemIsObject::No, target); } -void cmComputeLinkInformation::AddFullItem(BT const& item) +void cmComputeLinkInformation::AddFullItem(BT const& item, + ItemIsObject isObject) { // Check for the implicit link directory special case. if (this->CheckImplicitDirItem(item.Value)) { @@ -1138,7 +1149,7 @@ void cmComputeLinkInformation::AddFullItem(BT const& item) } // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes); + this->Items.emplace_back(item, ItemIsPath::Yes, isObject); } bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 9afa0eb7a7c..7fe30b3bb61 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -41,18 +41,27 @@ class cmComputeLinkInformation Yes, }; + enum class ItemIsObject + { + No, + Yes, + }; + struct Item { Item() = default; Item(BT v, ItemIsPath isPath, + ItemIsObject isObject = ItemIsObject::No, cmGeneratorTarget const* target = nullptr) : Value(std::move(v)) , IsPath(isPath) + , IsObject(isObject) , Target(target) { } BT Value; ItemIsPath IsPath = ItemIsPath::Yes; + ItemIsObject IsObject = ItemIsObject::No; cmGeneratorTarget const* Target = nullptr; }; using ItemVector = std::vector; @@ -81,6 +90,11 @@ class cmComputeLinkInformation return this->LibLinkFileFlag; } + std::string const& GetObjLinkFileFlag() const + { + return this->ObjLinkFileFlag; + } + std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; } std::string GetRPathLinkString() const; @@ -89,7 +103,8 @@ class cmComputeLinkInformation const cmGeneratorTarget* GetTarget() { return this->Target; } private: - void AddItem(BT const& item, const cmGeneratorTarget* tgt); + void AddItem(BT const& item, const cmGeneratorTarget* tgt, + ItemIsObject isObject = ItemIsObject::No); void AddSharedDepItem(BT const& item, cmGeneratorTarget const* tgt); void AddRuntimeDLL(cmGeneratorTarget const* tgt); @@ -125,6 +140,7 @@ class cmComputeLinkInformation const char* LoaderFlag; std::string LibLinkFlag; std::string LibLinkFileFlag; + std::string ObjLinkFileFlag; std::string LibLinkSuffix; std::string RuntimeFlag; std::string RuntimeSep; @@ -166,7 +182,7 @@ class cmComputeLinkInformation // Handling of link items. void AddTargetItem(BT const& item, const cmGeneratorTarget* target); - void AddFullItem(BT const& item); + void AddFullItem(BT const& item, ItemIsObject isObject); bool CheckImplicitDirItem(std::string const& item); void AddUserItem(BT const& item, bool pathNotKnown); void AddFrameworkItem(std::string const& item); diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 6eb8d75a6dc..5646368b715 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -75,7 +75,11 @@ void cmLinkLineComputer::ComputeLinkLibs( BT linkLib; if (item.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { - linkLib.Value += cli.GetLibLinkFileFlag(); + if (item.IsObject == cmComputeLinkInformation::ItemIsObject::Yes) { + linkLib.Value += cli.GetObjLinkFileFlag(); + } else { + linkLib.Value += cli.GetLibLinkFileFlag(); + } linkLib.Value += this->ConvertToOutputFormat( this->ConvertToLinkReference(item.Value.Value)); linkLib.Backtrace = item.Value.Backtrace; From 3941555d935afad8343c66f39579bfc611201a6f Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 26 May 2021 10:56:10 -0400 Subject: [PATCH 0549/1519] target_link_libraries: Place $ before libraries Linkers always use object files explicitly specified on the command line regardless of where they appear. Move them to the front of the list of linked libraries in so that symbols required by the object files can be resolved by any library. Issue: #22149 --- Help/command/target_link_libraries.rst | 85 +++++++++++++++++++ Help/release/dev/link-objects-first.rst | 8 ++ Source/cmComputeLinkDepends.cxx | 36 ++++++++ Source/cmComputeLinkDepends.h | 5 ++ Source/cmComputeTargetDepends.cxx | 13 +++ Source/cmGeneratorTarget.cxx | 38 +++++++-- Source/cmGeneratorTarget.h | 1 + Source/cmLinkItem.h | 6 ++ Tests/ObjectLibrary/CMakeLists.txt | 2 + .../ObjectLibrary/LinkObjects/CMakeLists.txt | 45 ++++++++++ Tests/ObjectLibrary/LinkObjects/a_dep.c | 7 ++ Tests/ObjectLibrary/LinkObjects/a_obj.c | 8 ++ Tests/ObjectLibrary/LinkObjects/b_dep.c | 7 ++ Tests/ObjectLibrary/LinkObjects/b_obj.c | 8 ++ Tests/ObjectLibrary/LinkObjects/c_dep.c | 7 ++ Tests/ObjectLibrary/LinkObjects/c_obj.c | 8 ++ Tests/ObjectLibrary/LinkObjects/d_dep.c | 7 ++ Tests/ObjectLibrary/LinkObjects/d_obj.c | 8 ++ Tests/ObjectLibrary/LinkObjects/e_dep.c | 7 ++ Tests/ObjectLibrary/LinkObjects/e_lib.c | 5 ++ Tests/ObjectLibrary/LinkObjects/e_obj.c | 8 ++ Tests/ObjectLibrary/LinkObjects/main.c | 24 ++++++ 22 files changed, 338 insertions(+), 5 deletions(-) create mode 100644 Help/release/dev/link-objects-first.rst create mode 100644 Tests/ObjectLibrary/LinkObjects/CMakeLists.txt create mode 100644 Tests/ObjectLibrary/LinkObjects/a_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/a_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/b_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/b_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/c_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/c_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/d_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/d_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/e_dep.c create mode 100644 Tests/ObjectLibrary/LinkObjects/e_lib.c create mode 100644 Tests/ObjectLibrary/LinkObjects/e_obj.c create mode 100644 Tests/ObjectLibrary/LinkObjects/main.c diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst index 872e264e99a..ac231bc8f2b 100644 --- a/Help/command/target_link_libraries.rst +++ b/Help/command/target_link_libraries.rst @@ -289,6 +289,91 @@ treated as :ref:`Interface Libraries`, but when they appear in a target's :prop_tgt:`LINK_LIBRARIES` property their object files will be included in the link too. +.. _`Linking Object Libraries via $`: + +Linking Object Libraries via $ +"""""""""""""""""""""""""""""""""""""""""""""" + +.. versionadded:: 3.21 + +The object files associated with an object library may be referenced +by the :genex:`$` generator expression. Such object +files are placed on the link line *before* all libraries, regardless +of their relative order. Additionally, an ordering dependency will be +added to the build sysstem to make sure the object library is up-to-date +before the dependent target links. For example, the code + +.. code-block:: cmake + + add_library(obj3 OBJECT obj3.c) + target_compile_definitions(obj3 PUBLIC OBJ3) + + add_executable(main3 main3.c) + target_link_libraries(main3 PRIVATE a3 $ b3) + +links executable ``main3`` with object files from ``main3.c`` +and ``obj3.c`` followed by the ``a3`` and ``b3`` libraries. +``main3.c`` is *not* compiled with usage requirements from ``obj3``, +such as ``-DOBJ3``. + +This approach can be used to achieve transitive inclusion of object +files in link lines as usage requirements. Continuing the above +example, the code + +.. code-block:: cmake + + add_library(iface_obj3 INTERFACE) + target_link_libraries(iface_obj3 INTERFACE obj3 $) + +creates an interface library ``iface_obj3`` that forwards the ``obj3`` +usage requirements and adds the ``obj3`` object files to dependents' +link lines. The code + +.. code-block:: cmake + + add_executable(use_obj3 use_obj3.c) + target_link_libraries(use_obj3 PRIVATE iface_obj3) + +compiles ``use_obj3.c`` with ``-DOBJ3`` and links executable ``use_obj3`` +with object files from ``use_obj3.c`` and ``obj3.c``. + +This also works transitively through a static library. Since a static +library does not link, it does not consume the object files from +object libraries referenced this way. Instead, the object files +become transitive link dependencies of the static library. +Continuing the above example, the code + +.. code-block:: cmake + + add_library(static3 STATIC static3.c) + target_link_libraries(static3 PRIVATE iface_obj3) + + add_executable(use_static3 use_static3.c) + target_link_libraries(use_static3 PRIVATE static3) + +compiles ``static3.c`` with ``-DOBJ3`` and creates ``libstatic3.a`` +using only its own object file. ``use_static3.c`` is compiled *without* +``-DOBJ3`` because the usage requirement is not transitive through +the private dependency of ``static3``. However, the link dependencies +of ``static3`` are propagated, including the ``iface_obj3`` reference +to ``$``. The ``use_static3`` executable is +created with object files from ``use_static3.c`` and ``obj3.c``, and +linked to library ``libstatic3.a``. + +When using this approach, it is the project's responsibility to avoid +linking multiple dependent binaries to ``iface_obj3``, because they will +all get the ``obj3`` object files on their link lines. + +.. note:: + + Referencing :genex:`$` in ``target_link_libraries`` + calls worked in versions of CMake prior to 3.21 for some cases, + but was not fully supported: + + * It did not place the object files before libraries on link lines. + * It did not add an ordering dependency on the object library. + * It did not work in Xcode with multiple architectures. + Cyclic Dependencies of Static Libraries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/link-objects-first.rst b/Help/release/dev/link-objects-first.rst new file mode 100644 index 00000000000..0c622e7ae19 --- /dev/null +++ b/Help/release/dev/link-objects-first.rst @@ -0,0 +1,8 @@ +link-objects-first +------------------ + +* :command:`target_link_libraries` calls referencing object libraries + via the :genex:`TARGET_OBJECTS` generator expression now place the + object files before all libraries on the link line, regardless of + their specified order. See documentation on + :ref:`Linking Object Libraries via \$\` for details. diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 5341e8d8c11..4a6518fde4a 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -263,6 +263,12 @@ cmComputeLinkDepends::Compute() this->FinalLinkEntries.push_back(e); } } + // Place explicitly linked object files in the front. The linker will + // always use them anyway, and they may depend on symbols from libraries. + // Append in reverse order since we reverse the final order below. + for (int i : cmReverseRange(this->ObjectEntries)) { + this->FinalLinkEntries.emplace_back(this->EntryList[i]); + } // Reverse the resulting order since we iterated in reverse. std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end()); @@ -328,6 +334,27 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) return index; } +void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item) +{ + // Check if the item entry has already been added. + auto lei = this->LinkEntryIndex.find(item); + if (lei != this->LinkEntryIndex.end()) { + return; + } + + // Allocate a spot for the item entry. + lei = this->AllocateLinkEntry(item); + + // Initialize the item entry. + int index = lei->second; + LinkEntry& entry = this->EntryList[index]; + entry.Item = BT(item.AsStr(), item.Backtrace); + entry.IsObject = true; + + // Record explicitly linked object files separately. + this->ObjectEntries.emplace_back(index); +} + void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) { // Get this entry representation. @@ -343,6 +370,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) entry.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY; // This target provides its own link interface information. this->AddLinkEntries(depender_index, iface->Libraries); + this->AddLinkObjects(iface->Objects); if (isIface) { return; @@ -487,6 +515,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries() cmLinkImplementation const* impl = this->Target->GetLinkImplementation(this->Config); this->AddLinkEntries(-1, impl->Libraries); + this->AddLinkObjects(impl->Objects); for (cmLinkItem const& wi : impl->WrongConfigLibraries) { this->CheckWrongConfigItem(wi); } @@ -546,6 +575,13 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, } } +void cmComputeLinkDepends::AddLinkObjects(std::vector const& objs) +{ + for (cmLinkItem const& obj : objs) { + this->AddLinkObject(obj); + } +} + cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, const std::string& name) { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 00fbd597299..72316f1aac6 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -66,10 +66,12 @@ class cmComputeLinkDepends std::map::iterator AllocateLinkEntry( cmLinkItem const& item); int AddLinkEntry(cmLinkItem const& item); + void AddLinkObject(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); template void AddLinkEntries(int depender_index, std::vector const& libs); + void AddLinkObjects(std::vector const& objs); cmLinkItem ResolveLinkItem(int depender_index, const std::string& name); // One entry for each unique item. @@ -154,6 +156,9 @@ class cmComputeLinkDepends std::set OldWrongConfigItems; void CheckWrongConfigItem(cmLinkItem const& item); + // Record of explicitly linked object files. + std::vector ObjectEntries; + int ComponentOrderId; cmTargetLinkLibraryType LinkType; bool HasConfig; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 0f234170f84..76712f4eb18 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -20,6 +20,7 @@ #include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -227,6 +228,12 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) this->AddInterfaceDepends(depender_index, lib, it, emitted); } } + for (cmLinkItem const& obj : impl->Objects) { + if (cmSourceFile const* o = depender->Makefile->GetSource( + obj.AsStr(), cmSourceFileLocationKind::Known)) { + this->AddObjectDepends(depender_index, o, emitted); + } + } } // Add dependencies on object libraries not otherwise handled above. @@ -274,6 +281,12 @@ void cmComputeTargetDepends::AddInterfaceDepends( this->AddInterfaceDepends(depender_index, libBT, config, emitted); } } + for (cmLinkItem const& obj : iface->Objects) { + if (cmSourceFile const* o = depender->Makefile->GetSource( + obj.AsStr(), cmSourceFileLocationKind::Known)) { + this->AddObjectDepends(depender_index, o, emitted); + } + } } } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 51742cf67f9..5deb2dfe45c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6275,8 +6275,8 @@ cm::optional cmGeneratorTarget::LookupLinkItem( void cmGeneratorTarget::ExpandLinkItems( std::string const& prop, std::string const& value, std::string const& config, cmGeneratorTarget const* headTarget, bool usage_requirements_only, - std::vector& items, bool& hadHeadSensitiveCondition, - bool& hadContextSensitiveCondition, + std::vector& items, std::vector& objects, + bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const { // Keep this logic in sync with ComputeLinkImplementationLibraries. @@ -6294,9 +6294,22 @@ void cmGeneratorTarget::ExpandLinkItems( cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this, headTarget->LinkerLanguage), libs); + cmMakefile const* mf = this->LocalGenerator->GetMakefile(); for (std::string const& lib : libs) { if (cm::optional maybeItem = this->LookupLinkItem(lib, cge->GetBacktrace())) { + if (!maybeItem->Target) { + // Report explicitly linked object files separately. + std::string const& maybeObj = maybeItem->AsStr(); + if (cmSystemTools::FileIsFullPath(maybeObj)) { + cmSourceFile const* sf = + mf->GetSource(maybeObj, cmSourceFileLocationKind::Known); + if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { + objects.emplace_back(std::move(*maybeItem)); + continue; + } + } + } items.emplace_back(std::move(*maybeItem)); } } @@ -6804,7 +6817,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, - iface.HadHeadSensitiveCondition, + iface.Objects, iface.HadHeadSensitiveCondition, iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); return; @@ -6828,6 +6841,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // Compare the link implementation fallback link interface to the // preferred new link interface property and warn if different. std::vector ifaceLibs; + std::vector ifaceObjects; static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if (cmProp newExplicitLibraries = this->GetProperty(newProp)) { bool hadHeadSensitiveConditionDummy = false; @@ -6835,7 +6849,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( bool hadLinkLanguageSensitiveConditionDummy = false; this->ExpandLinkItems(newProp, *newExplicitLibraries, config, headTarget, usage_requirements_only, ifaceLibs, - hadHeadSensitiveConditionDummy, + ifaceObjects, hadHeadSensitiveConditionDummy, hadContextSensitiveConditionDummy, hadLinkLanguageSensitiveConditionDummy); } @@ -6903,7 +6917,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( cmExpandList(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, iface.Libraries, - iface.HadHeadSensitiveCondition, + iface.Objects, iface.HadHeadSensitiveCondition, iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); std::vector deps = cmExpandedList(info->SharedDeps); @@ -7425,6 +7439,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorTarget const* head) const { cmLocalGenerator const* lg = this->LocalGenerator; + cmMakefile const* mf = lg->GetMakefile(); cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); cmBacktraceRange::const_iterator btIt = btRange.begin(); @@ -7500,6 +7515,19 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( // The entry is meant for this configuration. cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg); + if (!item.Target) { + // Report explicitly linked object files separately. + std::string const& maybeObj = item.AsStr(); + if (cmSystemTools::FileIsFullPath(maybeObj)) { + cmSourceFile const* sf = + mf->GetSource(maybeObj, cmSourceFileLocationKind::Known); + if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { + impl.Objects.emplace_back(std::move(item)); + continue; + } + } + } + impl.Libraries.emplace_back(std::move(item), evaluated != *le); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index dbc47b8f7e1..be36f3f206e 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1036,6 +1036,7 @@ class cmGeneratorTarget const cmGeneratorTarget* headTarget, bool usage_requirements_only, std::vector& items, + std::vector& objects, bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const; diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 5a90e7ec65c..db44938a377 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -50,6 +50,9 @@ struct cmLinkImplementationLibraries // Libraries linked directly in this configuration. std::vector Libraries; + // Object files linked directly in this configuration. + std::vector Objects; + // Libraries linked directly in other configurations. // Needed only for OLD behavior of CMP0003. std::vector WrongConfigLibraries; @@ -63,6 +66,9 @@ struct cmLinkInterfaceLibraries // Libraries listed in the interface. std::vector Libraries; + // Object files listed in the interface. + std::vector Objects; + // Whether the list depends on a genex referencing the head target. bool HadHeadSensitiveCondition = false; diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt index 74f34e4d02d..06167a83f4c 100644 --- a/Tests/ObjectLibrary/CMakeLists.txt +++ b/Tests/ObjectLibrary/CMakeLists.txt @@ -74,4 +74,6 @@ target_link_libraries(UseABstaticObjs ABstatic) add_subdirectory(ExportLanguages) +add_subdirectory(LinkObjects) + add_subdirectory(Transitive) diff --git a/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt b/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt new file mode 100644 index 00000000000..899be451845 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/CMakeLists.txt @@ -0,0 +1,45 @@ +add_executable(LinkObjects main.c) + +# Link TARGET_OBJECTS through LINK_LIBRARIES. +add_library(LinkObjectsAObj OBJECT a_obj.c) +add_library(LinkObjectsADep STATIC a_dep.c) +target_compile_definitions(LinkObjectsAObj PUBLIC OBJA) +target_link_libraries(LinkObjects PRIVATE LinkObjectsADep $) + +# Link TARGET_OBJECTS through INTERFACE_LINK_LIBRARIES with usage requirements. +add_library(LinkObjectsB INTERFACE) +add_library(LinkObjectsBObj OBJECT b_obj.c) +add_library(LinkObjectsBDep STATIC b_dep.c) +target_compile_definitions(LinkObjectsBObj PUBLIC OBJB) +target_link_libraries(LinkObjectsB INTERFACE LinkObjectsBObj $) +target_link_libraries(LinkObjectsBObj PRIVATE LinkObjectsBDep) +target_link_libraries(LinkObjects PRIVATE LinkObjectsB) + +# Link TARGET_OBJECTS through INTERFACE_LINK_LIBRARIES without usage requirements. +add_library(LinkObjectsC INTERFACE) +add_library(LinkObjectsCObj OBJECT c_obj.c) +add_library(LinkObjectsCDep STATIC c_dep.c) +target_compile_definitions(LinkObjectsCObj PUBLIC OBJC) +target_link_libraries(LinkObjectsC INTERFACE LinkObjectsCDep $) +target_link_libraries(LinkObjectsCObj PRIVATE LinkObjectsCDep) +target_link_libraries(LinkObjects PRIVATE LinkObjectsC) + +# Link TARGET_OBJECTS through both LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES, deduplicated. +add_library(LinkObjectsD INTERFACE) +add_library(LinkObjectsDObj OBJECT d_obj.c) +add_library(LinkObjectsDDep STATIC d_dep.c) +target_compile_definitions(LinkObjectsDObj PUBLIC OBJD) +target_link_libraries(LinkObjectsD INTERFACE LinkObjectsDObj $) +target_link_libraries(LinkObjectsDObj PRIVATE LinkObjectsDDep) +target_link_libraries(LinkObjects PRIVATE $ LinkObjectsD) + +# Link TARGET_OBJECTS through STATIC library private dependency. +add_library(LinkObjectsE INTERFACE) +add_library(LinkObjectsEObj OBJECT e_obj.c) +add_library(LinkObjectsEDep STATIC e_dep.c) +add_library(LinkObjectsEStatic STATIC e_lib.c) +target_compile_definitions(LinkObjectsEObj PUBLIC OBJE) +target_link_libraries(LinkObjectsE INTERFACE LinkObjectsEObj $) +target_link_libraries(LinkObjectsEObj PRIVATE LinkObjectsEDep) +target_link_libraries(LinkObjectsEStatic PRIVATE LinkObjectsE) +target_link_libraries(LinkObjects PRIVATE LinkObjectsEStatic) diff --git a/Tests/ObjectLibrary/LinkObjects/a_dep.c b/Tests/ObjectLibrary/LinkObjects/a_dep.c new file mode 100644 index 00000000000..01287405c86 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/a_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJA +# error "OBJA is defined, but should not be" +#endif +int a_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/a_obj.c b/Tests/ObjectLibrary/LinkObjects/a_obj.c new file mode 100644 index 00000000000..5e79c60c5ac --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/a_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJA +# error "OBJA is not defined, but should be" +#endif +extern int a_dep(void); +int a_obj(void) +{ + return a_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/b_dep.c b/Tests/ObjectLibrary/LinkObjects/b_dep.c new file mode 100644 index 00000000000..ad5d36737ee --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/b_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJB +# error "OBJB is defined, but should not be" +#endif +int b_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/b_obj.c b/Tests/ObjectLibrary/LinkObjects/b_obj.c new file mode 100644 index 00000000000..d0f426a241a --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/b_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJB +# error "OBJB is not defined, but should be" +#endif +extern int b_dep(void); +int b_obj(void) +{ + return b_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/c_dep.c b/Tests/ObjectLibrary/LinkObjects/c_dep.c new file mode 100644 index 00000000000..1d99ab874e4 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/c_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJC +# error "OBJC is defined, but should not be" +#endif +int c_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/c_obj.c b/Tests/ObjectLibrary/LinkObjects/c_obj.c new file mode 100644 index 00000000000..08fa5f5bdbf --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/c_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJC +# error "OBJC is not defined, but should be" +#endif +extern int c_dep(void); +int c_obj(void) +{ + return c_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/d_dep.c b/Tests/ObjectLibrary/LinkObjects/d_dep.c new file mode 100644 index 00000000000..cf09314115c --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/d_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJD +# error "OBJD is defined, but should not be" +#endif +int d_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/d_obj.c b/Tests/ObjectLibrary/LinkObjects/d_obj.c new file mode 100644 index 00000000000..d14ce660ebe --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/d_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJD +# error "OBJD is not defined, but should be" +#endif +extern int d_dep(void); +int d_obj(void) +{ + return d_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/e_dep.c b/Tests/ObjectLibrary/LinkObjects/e_dep.c new file mode 100644 index 00000000000..7fb70c10ad2 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/e_dep.c @@ -0,0 +1,7 @@ +#ifdef OBJE +# error "OBJE is defined, but should not be" +#endif +int e_dep(void) +{ + return 0; +} diff --git a/Tests/ObjectLibrary/LinkObjects/e_lib.c b/Tests/ObjectLibrary/LinkObjects/e_lib.c new file mode 100644 index 00000000000..9bb3a44355c --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/e_lib.c @@ -0,0 +1,5 @@ +extern int e_obj(void); +int e_lib(void) +{ + return e_obj(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/e_obj.c b/Tests/ObjectLibrary/LinkObjects/e_obj.c new file mode 100644 index 00000000000..02624ebfc2c --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/e_obj.c @@ -0,0 +1,8 @@ +#ifndef OBJE +# error "OBJE is not defined, but should be" +#endif +extern int e_dep(void); +int e_obj(void) +{ + return e_dep(); +} diff --git a/Tests/ObjectLibrary/LinkObjects/main.c b/Tests/ObjectLibrary/LinkObjects/main.c new file mode 100644 index 00000000000..c09c4f11bd4 --- /dev/null +++ b/Tests/ObjectLibrary/LinkObjects/main.c @@ -0,0 +1,24 @@ +#ifdef OBJA +# error "OBJA is defined, but should not be" +#endif +#ifndef OBJB +# error "OBJB is not defined, but should be" +#endif +#ifdef OBJC +# error "OBJC is defined, but should not be" +#endif +#ifndef OBJD +# error "OBJD is not defined, but should be" +#endif +#ifdef OBJE +# error "OBJE is defined, but should not be" +#endif +extern int a_obj(void); +extern int b_obj(void); +extern int c_obj(void); +extern int d_obj(void); +extern int e_lib(void); +int main(void) +{ + return a_obj() + b_obj() + c_obj() + d_obj() + e_lib(); +} From 886e27062b130ed3ba1d70971f8d33570e821c33 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 29 May 2021 19:41:03 +0300 Subject: [PATCH 0550/1519] Clang/MSVC: C++20 final flag, C++23 support Added in LLVM commit a8f75d497daa2684a03909d7c31d5bce11b427e1, will be released in 13.0. --- Modules/Compiler/Clang.cmake | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index 9f93d4188b3..7035d934604 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -194,16 +194,25 @@ macro(__compiler_clang_cxx_standards lang) set(CMAKE_${lang}11_EXTENSION_COMPILE_OPTION "") set(CMAKE_${lang}14_STANDARD_COMPILE_OPTION "-std:c++14") set(CMAKE_${lang}14_EXTENSION_COMPILE_OPTION "-std:c++14") - if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) set(CMAKE_${lang}17_STANDARD_COMPILE_OPTION "-std:c++17") set(CMAKE_${lang}17_EXTENSION_COMPILE_OPTION "-std:c++17") - set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "-std:c++latest") - set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "-std:c++latest") else() set(CMAKE_${lang}17_STANDARD_COMPILE_OPTION "-std:c++latest") set(CMAKE_${lang}17_EXTENSION_COMPILE_OPTION "-std:c++latest") endif() + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + set(CMAKE_${lang}23_STANDARD_COMPILE_OPTION "-std:c++latest") + set(CMAKE_${lang}23_EXTENSION_COMPILE_OPTION "-std:c++latest") + set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "-std:c++20") + set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "-std:c++20") + elseif(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "-std:c++latest") + set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "-std:c++latest") + endif() + __compiler_check_default_language_standard(${lang} 3.9 14) else() # This version of clang-cl, or the MSVC version it simulates, does not have From bf4e49477360e4423eb3ab5dca46314919fb977e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 30 May 2021 00:01:09 -0400 Subject: [PATCH 0551/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5252b25a5ba..1923152c818 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210529) +set(CMake_VERSION_PATCH 20210530) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a42add6cd6673c573e5f5257b55421a1d077befd Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sun, 30 May 2021 14:50:11 +0200 Subject: [PATCH 0552/1519] UseJava: Add version for RESOURCES option --- Modules/UseJava.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index baed7ef2535..30b40a079a6 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -34,9 +34,12 @@ the jar file. Source files can be java files or listing files (prefixed by ``@``). If only resource files are given then just a jar file is created. -The ``RESOURCES`` parameter adds the named ```` files to the jar -by stripping the source file path and placing the file beneath ```` -within the jar. For example:: +.. versionadded:: 3.21 + The ``RESOURCES`` parameter adds the named ```` files to the jar + by stripping the source file path and placing the file beneath ```` + within the jar. + +For example:: RESOURCES NAMESPACE "/com/my/namespace" "a/path/to/resource.txt" @@ -49,7 +52,8 @@ paths must be relative to ``CMAKE_CURRENT_SOURCE_DIR``. Adding resources without using the ``RESOURCES`` parameter in out of source builds will almost certainly result in confusion. -.. note:: SOURCES +.. note:: + Adding resources via the ``SOURCES`` parameter relies upon a hard-coded list of file extensions which are tested to determine whether they compile (e.g. File.java). ``SOURCES`` files which match the extensions are compiled. From 7ed2a1a66ff3a44857e24748806fdd74e5a886cc Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 31 May 2021 00:01:22 -0400 Subject: [PATCH 0553/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1923152c818..fb2a862e4e1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210530) +set(CMake_VERSION_PATCH 20210531) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1cb4f592a09752972d89785c0e8f1e160d5b5c4e Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sat, 19 Dec 2020 14:14:18 +0200 Subject: [PATCH 0554/1519] add_custom_command: Target-dependent generator expression support OUTPUT variant with a TARGET given to allow resolving target-based generator expressions wouldn't work because OUTPUT is resolved before generator targets are created, i.e. FindGeneratorTargetToUse() returns nullptr. This is a known limitation, see #21364. Implements #21336. --- Help/command/add_custom_command.rst | 5 +++++ .../dev/add_custom_command-TARGET-genex.rst | 5 +++++ Source/cmCustomCommand.cxx | 10 ++++++++++ Source/cmCustomCommand.h | 5 +++++ Source/cmCustomCommandGenerator.cxx | 18 +++++++++++------- Source/cmCustomCommandGenerator.h | 1 + Source/cmLocalGenerator.cxx | 1 + .../add_custom_command/RunCMakeTest.cmake | 17 +++++++++++++++++ .../add_custom_command/TargetGenexEvent.cmake | 10 ++++++++++ 9 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/add_custom_command-TARGET-genex.rst create mode 100644 Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 569f1e853b3..a053e59f792 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -338,6 +338,8 @@ will re-run whenever ``in.txt`` changes. where ```` is the build configuration, and then compile the generated source as part of a library. +.. _`add_custom_command(TARGET)`: + Build Events ^^^^^^^^^^^^ @@ -388,6 +390,9 @@ of the following is specified: This allows to add individual build events for every configuration. +.. versionadded:: 3.21 + Support for target-dependent generator expressions. + Examples: Build Events ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/add_custom_command-TARGET-genex.rst b/Help/release/dev/add_custom_command-TARGET-genex.rst new file mode 100644 index 00000000000..86f8b36be56 --- /dev/null +++ b/Help/release/dev/add_custom_command-TARGET-genex.rst @@ -0,0 +1,5 @@ +add_custom_command-TARGET-genex +------------------------------- + +* The :ref:`add_custom_command(TARGET) ` command + gained support for resolving target-dependent generator expressions. diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index f6b99898485..ec60ff7559e 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -150,3 +150,13 @@ void cmCustomCommand::SetCMP0116Status(cmPolicies::PolicyStatus cmp0116) { this->CMP0116Status = cmp0116; } + +const std::string& cmCustomCommand::GetTarget() const +{ + return this->Target; +} + +void cmCustomCommand::SetTarget(const std::string& target) +{ + this->Target = target; +} diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index e22c7a4064c..5cbd3d17a9e 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -100,6 +100,10 @@ class cmCustomCommand cmPolicies::PolicyStatus GetCMP0116Status() const; void SetCMP0116Status(cmPolicies::PolicyStatus cmp0116); + /** Set/Get the associated target */ + const std::string& GetTarget() const; + void SetTarget(const std::string& target); + private: std::vector Outputs; std::vector Byproducts; @@ -107,6 +111,7 @@ class cmCustomCommand cmCustomCommandLines CommandLines; cmListFileBacktrace Backtrace; cmImplicitDependsList ImplicitDepends; + std::string Target; std::string Comment; std::string WorkingDirectory; std::string Depfile; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 1054beb375f..77779ba7810 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -29,7 +29,7 @@ namespace { std::string EvaluateSplitConfigGenex( cm::string_view input, cmGeneratorExpression const& ge, cmLocalGenerator* lg, bool useOutputConfig, std::string const& outputConfig, - std::string const& commandConfig, + std::string const& commandConfig, cmGeneratorTarget const* target, std::set>>* utils = nullptr) { std::string result; @@ -87,7 +87,7 @@ std::string EvaluateSplitConfigGenex( // Evaluate this genex in the selected configuration. std::unique_ptr cge = ge.Parse(std::string(genex)); - result += cge->Evaluate(lg, *config); + result += cge->Evaluate(lg, *config, target); // Record targets referenced by the genex. if (utils) { @@ -114,7 +114,8 @@ std::vector EvaluateDepends(std::vector const& paths, std::string const& ep = EvaluateSplitConfigGenex(p, ge, lg, /*useOutputConfig=*/true, /*outputConfig=*/outputConfig, - /*commandConfig=*/commandConfig); + /*commandConfig=*/commandConfig, + /*target=*/nullptr); cm::append(depends, cmExpandedList(ep)); } for (std::string& p : depends) { @@ -157,6 +158,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( : CC(&cc) , OutputConfig(crossConfig ? *crossConfig : config) , CommandConfig(std::move(config)) + , Target(cc.GetTarget()) , LG(lg) , OldStyle(cc.GetEscapeOldStyle()) , MakeVars(cc.GetEscapeAllowMakeVars()) @@ -171,6 +173,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( } cmGeneratorExpression ge(cc.GetBacktrace()); + cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse( + this->Target) }; const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines(); for (cmCustomCommandLine const& cmdline : cmdlines) { @@ -180,7 +184,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( for (std::string const& clarg : cmdline) { std::string parsed_arg = EvaluateSplitConfigGenex( clarg, ge, this->LG, useOutputConfig, this->OutputConfig, - this->CommandConfig, &this->Utilities); + this->CommandConfig, target, &this->Utilities); if (this->CC->GetCommandExpandLists()) { cm::append(argv, cmExpandedList(parsed_arg)); } else { @@ -249,9 +253,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( const std::string& workingdirectory = this->CC->GetWorkingDirectory(); if (!workingdirectory.empty()) { - this->WorkingDirectory = - EvaluateSplitConfigGenex(workingdirectory, ge, this->LG, true, - this->OutputConfig, this->CommandConfig); + this->WorkingDirectory = EvaluateSplitConfigGenex( + workingdirectory, ge, this->LG, true, this->OutputConfig, + this->CommandConfig, target); // Convert working directory to a full path. if (!this->WorkingDirectory.empty()) { std::string const& build_dir = this->LG->GetCurrentBinaryDirectory(); diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index e70909a74a0..73a8d387dea 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -25,6 +25,7 @@ class cmCustomCommandGenerator cmCustomCommand const* CC; std::string OutputConfig; std::string CommandConfig; + std::string Target; cmLocalGenerator* LG; bool OldStyle; bool MakeVars; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 0c686aa2963..6a49b84a797 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -4096,6 +4096,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg, cc.SetDepfile(depfile); cc.SetJobPool(job_pool); cc.SetCMP0116Status(cmp0116); + cc.SetTarget(target->GetName()); switch (type) { case cmCustomCommandType::PRE_BUILD: target->AddPreBuildCommand(std::move(cc)); diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake index 9c59b4b75e5..ad6b2586c55 100644 --- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake @@ -43,3 +43,20 @@ if(NOT RunCMake_GENERATOR STREQUAL "Ninja Multi-Config") unset(RunCMake_TEST_BINARY_DIR) unset(RunCMake_TEST_NO_CLEAN) endif() + +function(test_genex name) + run_cmake(${name}) + + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}-build") + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .) + + if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/wdir/touched") + message(SEND_ERROR "File not created by target-dependent add_custom_command()!") + endif() + + unset(RunCMake_TEST_NO_CLEAN) + unset(RunCMake_TEST_BINARY_DIR) +endfunction() + +test_genex(TargetGenexEvent) diff --git a/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake b/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake new file mode 100644 index 00000000000..8591b74fce6 --- /dev/null +++ b/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake @@ -0,0 +1,10 @@ +add_custom_target(target ALL) +set_target_properties(target PROPERTIES COMPILE_DEFINITIONS "touched" COMPILE_OPTIONS "${CMAKE_BINARY_DIR}/wdir") +file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/wdir") + +add_custom_command( + TARGET target + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E touch $ + WORKING_DIRECTORY $ +) From 60e752ced8e9b604591082ee3b21d545fafa8ad8 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Tue, 25 May 2021 16:18:49 -0400 Subject: [PATCH 0555/1519] Refactor: Move common methods into cmInstallGenerator --- Source/cmInstallExportGenerator.cxx | 5 +- Source/cmInstallGenerator.cxx | 63 +++++++++++++++++++++++-- Source/cmInstallGenerator.h | 16 ++++++- Source/cmInstallTargetGenerator.cxx | 73 +++++------------------------ Source/cmInstallTargetGenerator.h | 9 ---- 5 files changed, 88 insertions(+), 78 deletions(-) diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index ccefd92c220..d932fd9e6f4 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -184,9 +184,8 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, Indent indent) { // Remove old per-configuration export files if the main changes. - std::string installedDir = - cmStrCat("$ENV{DESTDIR}", - this->ConvertToAbsoluteDestination(this->Destination), '/'); + std::string installedDir = cmStrCat( + "$ENV{DESTDIR}", ConvertToAbsoluteDestination(this->Destination), '/'); std::string installedFile = cmStrCat(installedDir, this->FileName); os << indent << "if(EXISTS \"" << installedFile << "\")\n"; Indent indentN = indent.Next(); diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index cf5f45e3db4..9f0d119e4cf 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -2,10 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallGenerator.h" -#include +#include #include #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmInstallGenerator::cmInstallGenerator( @@ -98,7 +99,7 @@ void cmInstallGenerator::AddInstallRule( << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; os << indent << "endif()\n"; } - std::string absDest = this->ConvertToAbsoluteDestination(dest); + std::string absDest = ConvertToAbsoluteDestination(dest); os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype; if (optional) { os << " OPTIONAL"; @@ -183,7 +184,7 @@ bool cmInstallGenerator::InstallsForConfig(const std::string& config) } std::string cmInstallGenerator::ConvertToAbsoluteDestination( - std::string const& dest) const + std::string const& dest) { std::string result; if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) { @@ -211,3 +212,59 @@ cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel( } return MessageDefault; } + +std::string cmInstallGenerator::GetDestDirPath(std::string const& file) +{ + // Construct the path of the file on disk after installation on + // which tweaks may be performed. + std::string toDestDirPath = "$ENV{DESTDIR}"; + if (file[0] != '/' && file[0] != '$') { + toDestDirPath += "/"; + } + toDestDirPath += file; + return toDestDirPath; +} + +void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent, + const std::string& config, + std::string const& file, + const TweakMethod& tweak) +{ + std::ostringstream tw; + tweak(tw, indent.Next(), config, file); + std::string tws = tw.str(); + if (!tws.empty()) { + os << indent << "if(EXISTS \"" << file << "\" AND\n" + << indent << " NOT IS_SYMLINK \"" << file << "\")\n"; + os << tws; + os << indent << "endif()\n"; + } +} + +void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent, + const std::string& config, + std::string const& dir, + std::vector const& files, + const TweakMethod& tweak) +{ + if (files.size() == 1) { + // Tweak a single file. + AddTweak(os, indent, config, GetDestDirPath(cmStrCat(dir, files[0])), + tweak); + } else { + // Generate a foreach loop to tweak multiple files. + std::ostringstream tw; + AddTweak(tw, indent.Next(), config, "${file}", tweak); + std::string tws = tw.str(); + if (!tws.empty()) { + Indent indent2 = indent.Next().Next(); + os << indent << "foreach(file\n"; + for (std::string const& f : files) { + os << indent2 << "\"" << GetDestDirPath(cmStrCat(dir, f)) << "\"\n"; + } + os << indent2 << ")\n"; + os << tws; + os << indent << "endforeach()\n"; + } + } +} diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 0117617cdbf..97acb88e838 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include #include #include #include @@ -53,7 +54,7 @@ class cmInstallGenerator : public cmScriptGenerator /** Get the install destination as it should appear in the installation script. */ - std::string ConvertToAbsoluteDestination(std::string const& dest) const; + static std::string ConvertToAbsoluteDestination(std::string const& dest); /** Test if this generator installs something for a given configuration. */ bool InstallsForConfig(const std::string& config); @@ -70,12 +71,25 @@ class cmInstallGenerator : public cmScriptGenerator cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } + static std::string GetDestDirPath(std::string const& file); + protected: void GenerateScript(std::ostream& os) override; std::string CreateComponentTest(const std::string& component, bool exclude_from_all); + using TweakMethod = + std::function; + static void AddTweak(std::ostream& os, Indent indent, + const std::string& config, std::string const& file, + const TweakMethod& tweak); + static void AddTweak(std::ostream& os, Indent indent, + const std::string& config, std::string const& dir, + std::vector const& files, + const TweakMethod& tweak); + // Information shared by most generator types. std::string const Destination; std::string const Component; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 3e79ad8b096..35165cf7210 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -77,12 +77,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( } // Tweak files located in the destination directory. - std::string toDir = cmStrCat(this->ConvertToAbsoluteDestination(dest), '/'); + std::string toDir = cmStrCat(ConvertToAbsoluteDestination(dest), '/'); // Add pre-installation tweaks. if (!files.NoTweak) { - this->AddTweak(os, indent, config, toDir, files.To, - &cmInstallTargetGenerator::PreReplacementTweaks); + AddTweak(os, indent, config, toDir, files.To, + [this](std::ostream& o, Indent i, const std::string& c, + const std::string& f) { + this->PreReplacementTweaks(o, i, c, f); + }); } // Write code to install the target file. @@ -102,8 +105,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( // Add post-installation tweaks. if (!files.NoTweak) { - this->AddTweak(os, indent, config, toDir, files.To, - &cmInstallTargetGenerator::PostReplacementTweaks); + AddTweak(os, indent, config, toDir, files.To, + [this](std::ostream& o, Indent i, const std::string& c, + const std::string& f) { + this->PostReplacementTweaks(o, i, c, f); + }); } } @@ -461,63 +467,6 @@ bool cmInstallTargetGenerator::Compute(cmLocalGenerator* lg) return true; } -void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent, - const std::string& config, - std::string const& file, - TweakMethod tweak) -{ - std::ostringstream tw; - (this->*tweak)(tw, indent.Next(), config, file); - std::string tws = tw.str(); - if (!tws.empty()) { - os << indent << "if(EXISTS \"" << file << "\" AND\n" - << indent << " NOT IS_SYMLINK \"" << file << "\")\n"; - os << tws; - os << indent << "endif()\n"; - } -} - -void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent, - const std::string& config, - std::string const& dir, - std::vector const& files, - TweakMethod tweak) -{ - if (files.size() == 1) { - // Tweak a single file. - this->AddTweak(os, indent, config, - this->GetDestDirPath(cmStrCat(dir, files[0])), tweak); - } else { - // Generate a foreach loop to tweak multiple files. - std::ostringstream tw; - this->AddTweak(tw, indent.Next(), config, "${file}", tweak); - std::string tws = tw.str(); - if (!tws.empty()) { - Indent indent2 = indent.Next().Next(); - os << indent << "foreach(file\n"; - for (std::string const& f : files) { - os << indent2 << "\"" << this->GetDestDirPath(cmStrCat(dir, f)) - << "\"\n"; - } - os << indent2 << ")\n"; - os << tws; - os << indent << "endforeach()\n"; - } - } -} - -std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file) -{ - // Construct the path of the file on disk after installation on - // which tweaks may be performed. - std::string toDestDirPath = "$ENV{DESTDIR}"; - if (file[0] != '/' && file[0] != '$') { - toDestDirPath += "/"; - } - toDestDirPath += file; - return toDestDirPath; -} - void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os, Indent indent, const std::string& config, diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 84fce4231b3..6173f2c3e32 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -93,15 +93,6 @@ class cmInstallTargetGenerator : public cmInstallGenerator protected: void GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent indent) override; - using TweakMethod = void (cmInstallTargetGenerator::*)(std::ostream&, Indent, - const std::string&, - const std::string&); - void AddTweak(std::ostream& os, Indent indent, const std::string& config, - std::string const& file, TweakMethod tweak); - void AddTweak(std::ostream& os, Indent indent, const std::string& config, - std::string const& dir, std::vector const& files, - TweakMethod tweak); - std::string GetDestDirPath(std::string const& file); void PreReplacementTweaks(std::ostream& os, Indent indent, const std::string& config, std::string const& file); From df7040a2718a0de2b074a6e55c5ce960d85d8d6f Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 26 May 2021 13:30:32 -0400 Subject: [PATCH 0556/1519] install(): Add IMPORTED_RUNTIME_ARTIFACTS mode --- Help/command/install.rst | 33 +++ .../install-imported-runtime-artifacts.rst | 5 + Source/CMakeLists.txt | 2 + Source/cmInstallCommand.cxx | 224 ++++++++++++++++++ ...stallImportedRuntimeArtifactsGenerator.cxx | 146 ++++++++++++ ...InstallImportedRuntimeArtifactsGenerator.h | 44 ++++ Tests/ExportImport/CMakeLists.txt | 28 ++- Tests/ExportImport/Export/CMakeLists.txt | 6 + Tests/ExportImport/Import/CMakeLists.txt | 3 + .../CMakeLists.txt | 30 +++ .../check_installed.cmake | 57 +++++ bootstrap | 1 + 12 files changed, 572 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/install-imported-runtime-artifacts.rst create mode 100644 Source/cmInstallImportedRuntimeArtifactsGenerator.cxx create mode 100644 Source/cmInstallImportedRuntimeArtifactsGenerator.h create mode 100644 Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt create mode 100644 Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake diff --git a/Help/command/install.rst b/Help/command/install.rst index 2259176d746..2865e1df49c 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -9,6 +9,7 @@ Synopsis .. parsed-literal:: install(`TARGETS`_ ... [...]) + install(`IMPORTED_RUNTIME_ARTIFACTS`_ ... [...]) install({`FILES`_ | `PROGRAMS`_} ... [...]) install(`DIRECTORY`_ ... [...]) install(`SCRIPT`_ [...]) @@ -382,6 +383,38 @@ set to ``TRUE`` has undefined behavior. to ensure that such out-of-directory targets are built before the subdirectory-specific install rules are run. +Installing Imported Runtime Artifacts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _`install(IMPORTED_RUNTIME_ARTIFACTS)`: +.. _IMPORTED_RUNTIME_ARTIFACTS: + +.. versionadded:: 3.21 + +.. code-block:: cmake + + install(IMPORTED_RUNTIME_ARTIFACTS targets... + [[LIBRARY|RUNTIME|FRAMEWORK|BUNDLE] + [DESTINATION ] + [PERMISSIONS permissions...] + [CONFIGURATIONS [Debug|Release|...]] + [COMPONENT ] + [OPTIONAL] [EXCLUDE_FROM_ALL] + ] [...] + ) + +The ``IMPORTED_RUNTIME_ARTIFACTS`` form specifies rules for installing the +runtime artifacts of imported targets. Projects may do this if they want to +bundle outside executables or modules inside their installation. The +``LIBRARY``, ``RUNTIME``, ``FRAMEWORK``, and ``BUNDLE`` arguments have the +same semantics that they do in the `TARGETS`_ mode. Only the runtime artifacts +of imported targets are installed (except in the case of :prop_tgt:`FRAMEWORK` +libraries, :prop_tgt:`MACOSX_BUNDLE` executables, and :prop_tgt:`BUNDLE` +CFBundles.) For example, headers and import libraries associated with DLLs are +not installed. In the case of :prop_tgt:`FRAMEWORK` libraries, +:prop_tgt:`MACOSX_BUNDLE` executables, and :prop_tgt:`BUNDLE` CFBundles, the +entire directory is installed. + Installing Files ^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/install-imported-runtime-artifacts.rst b/Help/release/dev/install-imported-runtime-artifacts.rst new file mode 100644 index 00000000000..e2821c15c12 --- /dev/null +++ b/Help/release/dev/install-imported-runtime-artifacts.rst @@ -0,0 +1,5 @@ +install-imported-runtime-artifacts +---------------------------------- + +* The :command:`install` command gained a new ``IMPORTED_RUNTIME_ARTIFACTS`` + mode, which can be used to install the runtime artifacts of imported targets. diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index bd9e4c2d824..844a2ee87fe 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -350,6 +350,8 @@ set(SRCS cmInstalledFile.cxx cmInstallFilesGenerator.h cmInstallFilesGenerator.cxx + cmInstallImportedRuntimeArtifactsGenerator.h + cmInstallImportedRuntimeArtifactsGenerator.cxx cmInstallScriptGenerator.h cmInstallScriptGenerator.cxx cmInstallSubdirectoryGenerator.h diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index e973764814f..c9bb467b36c 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallCommand.h" +#include #include #include #include @@ -22,6 +23,7 @@ #include "cmInstallExportGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallImportedRuntimeArtifactsGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmListFileCache.h" @@ -865,6 +867,227 @@ bool HandleTargetsMode(std::vector const& args, return true; } +bool HandleImportedRuntimeArtifactsMode(std::vector const& args, + cmExecutionStatus& status) +{ + Helper helper(status); + + // This is the IMPORTED_RUNTIME_ARTIFACTS mode. + std::vector targets; + + struct ArgVectors + { + std::vector Library; + std::vector Runtime; + std::vector Framework; + std::vector Bundle; + }; + + static auto const argHelper = cmArgumentParser{} + .Bind("LIBRARY"_s, &ArgVectors::Library) + .Bind("RUNTIME"_s, &ArgVectors::Runtime) + .Bind("FRAMEWORK"_s, &ArgVectors::Framework) + .Bind("BUNDLE"_s, &ArgVectors::Bundle); + + std::vector genericArgVector; + ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector); + + // now parse the generic args (i.e. the ones not specialized on LIBRARY, + // RUNTIME etc. (see above) + std::vector targetList; + std::vector unknownArgs; + cmInstallCommandArguments genericArgs(helper.DefaultComponentName); + genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList); + genericArgs.Parse(genericArgVector, &unknownArgs); + bool success = genericArgs.Finalize(); + + cmInstallCommandArguments libraryArgs(helper.DefaultComponentName); + cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName); + cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName); + cmInstallCommandArguments bundleArgs(helper.DefaultComponentName); + + // now parse the args for specific parts of the target (e.g. LIBRARY, + // RUNTIME etc. + libraryArgs.Parse(argVectors.Library, &unknownArgs); + runtimeArgs.Parse(argVectors.Runtime, &unknownArgs); + frameworkArgs.Parse(argVectors.Framework, &unknownArgs); + bundleArgs.Parse(argVectors.Bundle, &unknownArgs); + + if (!unknownArgs.empty()) { + // Unknown argument. + status.SetError( + cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given unknown argument \"", + unknownArgs[0], "\".")); + return false; + } + + // apply generic args + libraryArgs.SetGenericArguments(&genericArgs); + runtimeArgs.SetGenericArguments(&genericArgs); + frameworkArgs.SetGenericArguments(&genericArgs); + bundleArgs.SetGenericArguments(&genericArgs); + + success = success && libraryArgs.Finalize(); + success = success && runtimeArgs.Finalize(); + success = success && frameworkArgs.Finalize(); + success = success && bundleArgs.Finalize(); + + if (!success) { + return false; + } + + // Check if there is something to do. + if (targetList.empty()) { + return true; + } + + for (std::string const& tgt : targetList) { + if (helper.Makefile->IsAlias(tgt)) { + status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", + tgt, "\" which is an alias.")); + return false; + } + // Lookup this target in the current directory. + cmTarget* target = helper.Makefile->FindTargetToUse(tgt); + if (!target || !target->IsImported()) { + // If no local target has been found, find it in the global scope. + cmTarget* const global_target = + helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + if (global_target && global_target->IsImported()) { + target = global_target; + } + } + if (target) { + // Found the target. Check its type. + if (target->GetType() != cmStateEnums::EXECUTABLE && + target->GetType() != cmStateEnums::SHARED_LIBRARY && + target->GetType() != cmStateEnums::MODULE_LIBRARY) { + status.SetError( + cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", tgt, + "\" which is not an executable, library, or module.")); + return false; + } + // Store the target in the list to be installed. + targets.push_back(target); + } else { + // Did not find the target. + status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given target \"", + tgt, "\" which does not exist.")); + return false; + } + } + + // Keep track of whether we will be performing an installation of + // any files of the given type. + bool installsLibrary = false; + bool installsRuntime = false; + bool installsFramework = false; + bool installsBundle = false; + + auto const createInstallGenerator = + [helper](cmTarget& target, const cmInstallCommandArguments& typeArgs, + const std::string& destination) + -> std::unique_ptr { + return cm::make_unique( + target.GetName(), destination, typeArgs.GetPermissions(), + typeArgs.GetConfigurations(), typeArgs.GetComponent(), + cmInstallGenerator::SelectMessageLevel(helper.Makefile), + typeArgs.GetExcludeFromAll(), typeArgs.GetOptional(), + helper.Makefile->GetBacktrace()); + }; + + // Generate install script code to install the given targets. + for (cmTarget* ti : targets) { + // Handle each target type. + cmTarget& target = *ti; + std::unique_ptr + libraryGenerator; + std::unique_ptr + runtimeGenerator; + std::unique_ptr + frameworkGenerator; + std::unique_ptr + bundleGenerator; + + switch (target.GetType()) { + case cmStateEnums::SHARED_LIBRARY: + if (target.IsDLLPlatform()) { + runtimeGenerator = createInstallGenerator( + target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs)); + } else if (target.IsFrameworkOnApple()) { + if (frameworkArgs.GetDestination().empty()) { + status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no " + "FRAMEWORK DESTINATION for shared " + "library FRAMEWORK target \"", + target.GetName(), "\".")); + return false; + } + frameworkGenerator = createInstallGenerator( + target, frameworkArgs, frameworkArgs.GetDestination()); + } else { + libraryGenerator = createInstallGenerator( + target, libraryArgs, helper.GetLibraryDestination(&libraryArgs)); + } + break; + case cmStateEnums::MODULE_LIBRARY: + libraryGenerator = createInstallGenerator( + target, libraryArgs, helper.GetLibraryDestination(&libraryArgs)); + break; + case cmStateEnums::EXECUTABLE: + if (target.IsAppBundleOnApple()) { + if (bundleArgs.GetDestination().empty()) { + status.SetError( + cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no BUNDLE " + "DESTINATION for MACOSX_BUNDLE executable target \"", + target.GetName(), "\".")); + return false; + } + bundleGenerator = createInstallGenerator( + target, bundleArgs, bundleArgs.GetDestination()); + } else { + runtimeGenerator = createInstallGenerator( + target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs)); + } + break; + default: + assert(false && "This should never happen"); + break; + } + + // Keep track of whether we're installing anything in each category + installsLibrary = installsLibrary || libraryGenerator; + installsRuntime = installsRuntime || runtimeGenerator; + installsFramework = installsFramework || frameworkGenerator; + installsBundle = installsBundle || bundleGenerator; + + helper.Makefile->AddInstallGenerator(std::move(libraryGenerator)); + helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator)); + helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator)); + helper.Makefile->AddInstallGenerator(std::move(bundleGenerator)); + } + + // Tell the global generator about any installation component names + // specified + if (installsLibrary) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + libraryArgs.GetComponent()); + } + if (installsRuntime) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + runtimeArgs.GetComponent()); + } + if (installsFramework) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + frameworkArgs.GetComponent()); + } + if (installsBundle) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + bundleArgs.GetComponent()); + } + + return true; +} + bool HandleFilesMode(std::vector const& args, cmExecutionStatus& status) { @@ -1705,6 +1928,7 @@ bool cmInstallCommand(std::vector const& args, { "SCRIPT"_s, HandleScriptMode }, { "CODE"_s, HandleScriptMode }, { "TARGETS"_s, HandleTargetsMode }, + { "IMPORTED_RUNTIME_ARTIFACTS"_s, HandleImportedRuntimeArtifactsMode }, { "FILES"_s, HandleFilesMode }, { "PROGRAMS"_s, HandleFilesMode }, { "DIRECTORY"_s, HandleDirectoryMode }, diff --git a/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx b/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx new file mode 100644 index 00000000000..01980ac1a23 --- /dev/null +++ b/Source/cmInstallImportedRuntimeArtifactsGenerator.cxx @@ -0,0 +1,146 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallImportedRuntimeArtifactsGenerator.h" + +#include +#include +#include +#include + +#include "cmsys/RegularExpression.hxx" + +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmInstallType.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" +#include "cmStateTypes.h" +#include "cmStringAlgorithms.h" + +namespace { +const cmsys::RegularExpression FrameworkRegularExpression( + "^(.*/)?([^/]*)\\.framework/(.*)$"); + +const cmsys::RegularExpression BundleRegularExpression( + "^(.*/)?([^/]*)\\.app/(.*)$"); + +const cmsys::RegularExpression CFBundleRegularExpression( + "^(.*/)?([^/]*)\\.bundle/(.*)$"); +} + +cmInstallImportedRuntimeArtifactsGenerator:: + cmInstallImportedRuntimeArtifactsGenerator( + std::string targetName, std::string const& dest, + std::string file_permissions, + std::vector const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, + bool optional, cmListFileBacktrace backtrace) + : cmInstallGenerator(dest, configurations, component, message, + exclude_from_all, false, std::move(backtrace)) + , TargetName(std::move(targetName)) + , FilePermissions(std::move(file_permissions)) + , Optional(optional) +{ + this->ActionsPerConfig = true; +} + +bool cmInstallImportedRuntimeArtifactsGenerator::Compute(cmLocalGenerator* lg) +{ + // Lookup this target in the current directory. + this->Target = lg->FindGeneratorTargetToUse(this->TargetName); + if (!this->Target || !this->Target->IsImported()) { + // If no local target has been found, find it in the global scope. + this->Target = + lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName); + } + + return true; +} + +std::string cmInstallImportedRuntimeArtifactsGenerator::GetDestination( + std::string const& config) const +{ + return cmGeneratorExpression::Evaluate( + this->Destination, this->Target->GetLocalGenerator(), config); +} + +void cmInstallImportedRuntimeArtifactsGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + auto location = this->Target->GetFullPath(config); + + switch (this->Target->GetType()) { + case cmStateEnums::EXECUTABLE: + if (this->Target->IsBundleOnApple()) { + cmsys::RegularExpressionMatch match; + if (BundleRegularExpression.find(location.c_str(), match)) { + auto bundleDir = match.match(1); + auto bundleName = match.match(2); + auto bundlePath = cmStrCat(bundleDir, bundleName, ".app"); + this->AddInstallRule(os, this->GetDestination(config), + cmInstallType_DIRECTORY, { bundlePath }, + this->Optional, nullptr, + this->FilePermissions.c_str(), nullptr, + " USE_SOURCE_PERMISSIONS", indent); + } + } else { + this->AddInstallRule(os, this->GetDestination(config), + cmInstallType_EXECUTABLE, { location }, + this->Optional, this->FilePermissions.c_str(), + nullptr, nullptr, nullptr, indent); + } + break; + case cmStateEnums::SHARED_LIBRARY: + if (this->Target->IsFrameworkOnApple()) { + cmsys::RegularExpressionMatch match; + if (FrameworkRegularExpression.find(location.c_str(), match)) { + auto frameworkDir = match.match(1); + auto frameworkName = match.match(2); + auto frameworkPath = + cmStrCat(frameworkDir, frameworkName, ".framework"); + this->AddInstallRule(os, this->GetDestination(config), + cmInstallType_DIRECTORY, { frameworkPath }, + this->Optional, nullptr, + this->FilePermissions.c_str(), nullptr, + " USE_SOURCE_PERMISSIONS", indent); + } + } else { + std::vector files{ location }; + auto soName = this->Target->GetSOName(config); + auto soNameFile = + cmStrCat(this->Target->GetDirectory(config), '/', soName); + if (!soName.empty() && soNameFile != location) { + files.push_back(soNameFile); + } + this->AddInstallRule(os, this->GetDestination(config), + cmInstallType_SHARED_LIBRARY, files, + this->Optional, this->FilePermissions.c_str(), + nullptr, nullptr, nullptr, indent); + } + break; + case cmStateEnums::MODULE_LIBRARY: + if (this->Target->IsCFBundleOnApple()) { + cmsys::RegularExpressionMatch match; + if (CFBundleRegularExpression.find(location.c_str(), match)) { + auto bundleDir = match.match(1); + auto bundleName = match.match(2); + auto bundlePath = cmStrCat(bundleDir, bundleName, ".bundle"); + this->AddInstallRule(os, this->GetDestination(config), + cmInstallType_DIRECTORY, { bundlePath }, + this->Optional, nullptr, + this->FilePermissions.c_str(), nullptr, + " USE_SOURCE_PERMISSIONS", indent); + } + } else { + this->AddInstallRule(os, this->GetDestination(config), + cmInstallType_MODULE_LIBRARY, { location }, + this->Optional, this->FilePermissions.c_str(), + nullptr, nullptr, nullptr, indent); + } + break; + default: + assert(false && "This should never happen"); + break; + } +} diff --git a/Source/cmInstallImportedRuntimeArtifactsGenerator.h b/Source/cmInstallImportedRuntimeArtifactsGenerator.h new file mode 100644 index 00000000000..9e045ee725d --- /dev/null +++ b/Source/cmInstallImportedRuntimeArtifactsGenerator.h @@ -0,0 +1,44 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include +#include + +#include "cmInstallGenerator.h" +#include "cmListFileCache.h" +#include "cmScriptGenerator.h" + +class cmGeneratorTarget; +class cmLocalGenerator; + +class cmInstallImportedRuntimeArtifactsGenerator : public cmInstallGenerator +{ +public: + cmInstallImportedRuntimeArtifactsGenerator( + std::string targetName, std::string const& dest, + std::string file_permissions, + std::vector const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, + bool optional, cmListFileBacktrace backtrace = cmListFileBacktrace()); + ~cmInstallImportedRuntimeArtifactsGenerator() override = default; + + bool Compute(cmLocalGenerator* lg) override; + + cmGeneratorTarget* GetTarget() const { return this->Target; } + + bool GetOptional() const { return this->Optional; } + + std::string GetDestination(std::string const& config) const; + +protected: + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + +private: + std::string const TargetName; + cmGeneratorTarget* Target; + std::string const FilePermissions; + bool const Optional; +}; diff --git a/Tests/ExportImport/CMakeLists.txt b/Tests/ExportImport/CMakeLists.txt index d88eb11bbf0..4999612ff2d 100644 --- a/Tests/ExportImport/CMakeLists.txt +++ b/Tests/ExportImport/CMakeLists.txt @@ -16,14 +16,12 @@ set_property( ) get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(_isMultiConfig) - set(NESTED_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}") +if(_isMultiConfig OR CMAKE_BUILD_TYPE) + set(NESTED_CONFIG_TYPE -C "$") + set(NESTED_CONFIG_INSTALL_TYPE --config "$") else() - if(CMAKE_BUILD_TYPE) - set(NESTED_CONFIG_TYPE -C "${CMAKE_BUILD_TYPE}") - else() - set(NESTED_CONFIG_TYPE) - endif() + set(NESTED_CONFIG_TYPE) + set(NESTED_CONFIG_INSTALL_TYPE) endif() if(MINGW OR MSYS) @@ -79,5 +77,21 @@ set_property( PROPERTY SYMBOLIC 1 ) +# Install the imported targets. +add_custom_command( + OUTPUT ${ExportImport_BINARY_DIR}/ImportInstall + COMMAND ${CMAKE_COMMAND} -E rm -rf ${ExportImport_BINARY_DIR}/Import/install + COMMAND ${CMAKE_COMMAND} + --install ${ExportImport_BINARY_DIR}/Import + --prefix ${ExportImport_BINARY_DIR}/Import/install + ${NESTED_CONFIG_INSTALL_TYPE} + ) +add_custom_target(ImportInstallTarget ALL DEPENDS ${ExportImport_BINARY_DIR}/ImportInstall) +add_dependencies(ImportInstallTarget ImportTarget) +set_property( + SOURCE ${ExportImport_BINARY_DIR}/ImportInstall + PROPERTY SYMBOLIC 1 + ) + add_executable(ExportImport main.c) add_dependencies(ExportImport ImportTarget) diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 6d9b4ab4f57..fa0016b2447 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -395,6 +395,10 @@ target_include_directories(systemlib $ ) +add_library(testMod1 MODULE empty.cpp) +add_library(testMod2 MODULE empty.cpp) +set_property(TARGET testMod2 PROPERTY BUNDLE 1) + install(TARGETS testLibRequired EXPORT RequiredExp DESTINATION lib INCLUDES DESTINATION @@ -523,6 +527,7 @@ install( testLibDeprecation testLibCycleA testLibCycleB testLibNoSONAME + testMod1 testMod2 cmp0022NEW cmp0022OLD TopDirLib SubDirLinkA systemlib @@ -595,6 +600,7 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 te testLib4lib testLib4libdbg testLib4libopt testLibCycleA testLibCycleB testLibNoSONAME + testMod1 testMod2 testLibPerConfigDest NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt index a8a98fcb626..e64c6b40789 100644 --- a/Tests/ExportImport/Import/CMakeLists.txt +++ b/Tests/ExportImport/Import/CMakeLists.txt @@ -26,3 +26,6 @@ add_subdirectory(Interface) # Test package version range add_subdirectory(version_range) + +# Test install(IMPORTED_RUNTIME_ARTIFACTS) +add_subdirectory(install-IMPORTED_RUNTIME_ARTIFACTS) diff --git a/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt new file mode 100644 index 00000000000..76efe2f509c --- /dev/null +++ b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/CMakeLists.txt @@ -0,0 +1,30 @@ +# Import targets from the exported build tree. +include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake) + +set(_tgts + bld_testExe1 # Ordinary executable + bld_testExe2lib # Ordinary shared library + bld_testLib3 # Shared library with version and soversion + bld_testLib4 # Framework library + bld_testExe3 # Bundle executable + bld_testMod1 # Module library + bld_testMod2 # CFBundle + ) + +install(IMPORTED_RUNTIME_ARTIFACTS ${_tgts} + RUNTIME DESTINATION aaa/executables + LIBRARY DESTINATION aaa/libraries + BUNDLE DESTINATION aaa/bundles + FRAMEWORK DESTINATION aaa/frameworks + ) + +install(IMPORTED_RUNTIME_ARTIFACTS ${_tgts} + DESTINATION bbb + ) + +install(IMPORTED_RUNTIME_ARTIFACTS ${_tgts} + BUNDLE DESTINATION zzz/bundles + FRAMEWORK DESTINATION zzz/frameworks + ) + +install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/check_installed.cmake") diff --git a/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake new file mode 100644 index 00000000000..29b298fbf39 --- /dev/null +++ b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 3.20) + +function(check_installed expect) + file(GLOB_RECURSE actual + LIST_DIRECTORIES TRUE + RELATIVE ${CMAKE_INSTALL_PREFIX} + ${CMAKE_INSTALL_PREFIX}/* + ) + if(actual) + list(SORT actual) + endif() + if(NOT "${actual}" MATCHES "${expect}") + message(FATAL_ERROR "Installed files: + ${actual} +do not match what we expected: + ${expect} +in directory: + ${CMAKE_INSTALL_PREFIX}") + endif() +endfunction() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(_dirs [[aaa;aaa/executables;aaa/executables/testExe1-4;aaa/executables/testExe3;aaa/libraries;aaa/libraries/libtestExe2lib\.so;aaa/libraries/libtestLib3lib(-d|-r)?\.so\.1\.2;aaa/libraries/libtestLib3lib(-d|-r)?\.so\.3;aaa/libraries/libtestLib4\.so;aaa/libraries/libtestMod1\.so;aaa/libraries/libtestMod2\.so]]) + set(_alldest [[bbb;bbb/libtestExe2lib\.so;bbb/libtestLib3lib(-d|-r)?\.so\.1\.2;bbb/libtestLib3lib(-d|-r)?\.so\.3;bbb/libtestLib4\.so;bbb/libtestMod1\.so;bbb/libtestMod2\.so;bbb/testExe1-4;bbb/testExe3]]) + set(_default [[bin;bin/testExe1-4;bin/testExe3;lib;lib/libtestExe2lib\.so;lib/libtestLib3lib(-d|-r)?\.so\.1\.2;lib/libtestLib3lib(-d|-r)?\.so\.3;lib/libtestLib4\.so;lib/libtestMod1\.so;lib/libtestMod2\.so]]) + check_installed("^${_dirs};${_alldest};${_default}$") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(_dirs_msvc [[aaa;aaa/executables;aaa/executables/testExe1\.exe;aaa/executables/testExe2lib\.dll;aaa/executables/testExe3\.exe;aaa/executables/testLib3dll(-d|-r)?\.dll;aaa/executables/testLib4\.dll;aaa/libraries;aaa/libraries/testMod1\.dll;aaa/libraries/testMod2\.dll]]) + set(_dirs_mingw [[aaa;aaa/executables;aaa/executables/libtestExe2lib\.dll;aaa/executables/libtestLib3dll(-d|-r)?\.dll;aaa/executables/libtestLib4\.dll;aaa/executables/testExe1\.exe;aaa/executables/testExe3\.exe;aaa/libraries;aaa/libraries/libtestMod1\.dll;aaa/libraries/libtestMod2\.dll]]) + + set(_alldest_msvc [[bbb;bbb/testExe1\.exe;bbb/testExe2lib\.dll;bbb/testExe3\.exe;bbb/testLib3dll(-d|-r)?\.dll;bbb/testLib4\.dll;bbb/testMod1\.dll;bbb/testMod2\.dll]]) + set(_alldest_mingw [[bbb;bbb/libtestExe2lib\.dll;bbb/libtestLib3dll(-d|-r)?\.dll;bbb/libtestLib4\.dll;bbb/libtestMod1\.dll;bbb/libtestMod2\.dll;bbb/testExe1\.exe;bbb/testExe3\.exe]]) + + set(_default_msvc [[bin;bin/testExe1\.exe;bin/testExe2lib\.dll;bin/testExe3\.exe;bin/testLib3dll(-d|-r)?\.dll;bin/testLib4\.dll;lib;lib/testMod1\.dll;lib/testMod2\.dll]]) + set(_default_mingw [[bin;bin/libtestExe2lib\.dll;bin/libtestLib3dll(-d|-r)?\.dll;bin/libtestLib4\.dll;bin/testExe1\.exe;bin/testExe3\.exe;lib;lib/libtestMod1\.dll;lib/libtestMod2\.dll]]) + + check_installed("^(${_dirs_msvc};${_alldest_msvc};${_default_msvc}|${_dirs_mingw};${_alldest_mingw};${_default_mingw})$") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(_bundles [[aaa/bundles;aaa/bundles/testExe3\.app;aaa/bundles/testExe3\.app/Contents;aaa/bundles/testExe3\.app/Contents/Info\.plist;aaa/bundles/testExe3\.app/Contents/MacOS;aaa/bundles/testExe3\.app/Contents/MacOS/testExe3(;aaa/bundles/testExe3\.app/Contents/PkgInfo)?(;aaa/bundles/testExe3\.app/Contents/_CodeSignature;aaa/bundles/testExe3\.app/Contents/_CodeSignature/CodeResources)?]]) + set(_executables [[aaa/executables;aaa/executables/testExe1(-4)?]]) + set(_frameworks [[aaa/frameworks;aaa/frameworks/testLib4\.framework;aaa/frameworks/testLib4\.framework/Headers;aaa/frameworks/testLib4\.framework/Headers/testLib4\.h;aaa/frameworks/testLib4\.framework/Resources;aaa/frameworks/testLib4\.framework/Versions;aaa/frameworks/testLib4\.framework/Versions/A;aaa/frameworks/testLib4\.framework/Versions/A/Resources;aaa/frameworks/testLib4\.framework/Versions/A/Resources/Info\.plist(;aaa/frameworks/testLib4\.framework/Versions/A/_CodeSignature;aaa/frameworks/testLib4\.framework/Versions/A/_CodeSignature/CodeResources)?;aaa/frameworks/testLib4\.framework/Versions/A/testLib4;aaa/frameworks/testLib4\.framework/Versions/Current;aaa/frameworks/testLib4\.framework/testLib4]]) + set(_libraries [[aaa/libraries;aaa/libraries/libtestExe2lib\.dylib;aaa/libraries/libtestLib3lib(-d|-r)?\.1\.2\.dylib;aaa/libraries/libtestLib3lib(-d|-r)?\.3\.dylib;aaa/libraries/libtestMod1\.so;aaa/libraries/testMod2\.bundle;aaa/libraries/testMod2\.bundle/Contents;aaa/libraries/testMod2\.bundle/Contents/Info\.plist;aaa/libraries/testMod2\.bundle/Contents/MacOS;aaa/libraries/testMod2\.bundle/Contents/MacOS/testMod2(;aaa/libraries/testMod2\.bundle/Contents/_CodeSignature;aaa/libraries/testMod2\.bundle/Contents/_CodeSignature/CodeResources)?]]) + set(_dirs "aaa;${_bundles};${_executables};${_frameworks};${_libraries}") + + set(_alldest [[bbb;bbb/libtestExe2lib\.dylib;bbb/libtestLib3lib(-d|-r)?\.1\.2\.dylib;bbb/libtestLib3lib(-d|-r)?\.3\.dylib;bbb/libtestMod1\.so;bbb/testExe1(-4)?;bbb/testExe3\.app;bbb/testExe3\.app/Contents;bbb/testExe3\.app/Contents/Info\.plist;bbb/testExe3\.app/Contents/MacOS;bbb/testExe3\.app/Contents/MacOS/testExe3(;bbb/testExe3\.app/Contents/PkgInfo)?(;bbb/testExe3\.app/Contents/_CodeSignature;bbb/testExe3\.app/Contents/_CodeSignature/CodeResources)?;bbb/testLib4\.framework;bbb/testLib4\.framework/Headers;bbb/testLib4\.framework/Headers/testLib4\.h;bbb/testLib4\.framework/Resources;bbb/testLib4\.framework/Versions;bbb/testLib4\.framework/Versions/A;bbb/testLib4\.framework/Versions/A/Resources;bbb/testLib4\.framework/Versions/A/Resources/Info\.plist(;bbb/testLib4\.framework/Versions/A/_CodeSignature;bbb/testLib4\.framework/Versions/A/_CodeSignature/CodeResources)?;bbb/testLib4\.framework/Versions/A/testLib4;bbb/testLib4\.framework/Versions/Current;bbb/testLib4\.framework/testLib4;bbb/testMod2\.bundle;bbb/testMod2\.bundle/Contents;bbb/testMod2\.bundle/Contents/Info\.plist;bbb/testMod2\.bundle/Contents/MacOS;bbb/testMod2\.bundle/Contents/MacOS/testMod2(;bbb/testMod2\.bundle/Contents/_CodeSignature;bbb/testMod2\.bundle/Contents/_CodeSignature/CodeResources)?]]) + + set(_default_bin [[bin;bin/testExe1(-4)?]]) + set(_default_lib [[lib;lib/libtestExe2lib\.dylib;lib/libtestLib3lib(-d|-r)?\.1\.2\.dylib;lib/libtestLib3lib(-d|-r)?\.3\.dylib;lib/libtestMod1\.so;lib/testMod2\.bundle;lib/testMod2\.bundle/Contents;lib/testMod2\.bundle/Contents/Info\.plist;lib/testMod2\.bundle/Contents/MacOS;lib/testMod2\.bundle/Contents/MacOS/testMod2(;lib/testMod2\.bundle/Contents/_CodeSignature;lib/testMod2\.bundle/Contents/_CodeSignature/CodeResources)?]]) + set(_default_bundles [[zzz/bundles;zzz/bundles/testExe3\.app;zzz/bundles/testExe3\.app/Contents;zzz/bundles/testExe3\.app/Contents/Info\.plist;zzz/bundles/testExe3\.app/Contents/MacOS;zzz/bundles/testExe3\.app/Contents/MacOS/testExe3(;zzz/bundles/testExe3\.app/Contents/PkgInfo)?(;zzz/bundles/testExe3\.app/Contents/_CodeSignature;zzz/bundles/testExe3\.app/Contents/_CodeSignature/CodeResources)?]]) + set(_default_frameworks [[zzz/frameworks;zzz/frameworks/testLib4\.framework;zzz/frameworks/testLib4\.framework/Headers;zzz/frameworks/testLib4\.framework/Headers/testLib4\.h;zzz/frameworks/testLib4\.framework/Resources;zzz/frameworks/testLib4\.framework/Versions;zzz/frameworks/testLib4\.framework/Versions/A;zzz/frameworks/testLib4\.framework/Versions/A/Resources;zzz/frameworks/testLib4\.framework/Versions/A/Resources/Info\.plist(;zzz/frameworks/testLib4\.framework/Versions/A/_CodeSignature;zzz/frameworks/testLib4\.framework/Versions/A/_CodeSignature/CodeResources)?;zzz/frameworks/testLib4\.framework/Versions/A/testLib4;zzz/frameworks/testLib4\.framework/Versions/Current;zzz/frameworks/testLib4\.framework/testLib4]]) + set(_default "${_default_bin};${_default_lib};zzz;${_default_bundles};${_default_frameworks}") + + # Need to break this up due to too many pairs of parentheses + check_installed("^${_dirs};bbb;") + check_installed(";${_alldest};bin;") + check_installed(";${_default}$") +endif() diff --git a/bootstrap b/bootstrap index aefd210e7ca..911558da062 100755 --- a/bootstrap +++ b/bootstrap @@ -387,6 +387,7 @@ CMAKE_CXX_SOURCES="\ cmInstallFilesCommand \ cmInstallFilesGenerator \ cmInstallGenerator \ + cmInstallImportedRuntimeArtifactsGenerator \ cmInstallScriptGenerator \ cmInstallSubdirectoryGenerator \ cmInstallTargetGenerator \ From f7ba3a05893279f6704db15358b08fd4ecb28814 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 28 May 2021 14:20:51 -0400 Subject: [PATCH 0557/1519] FileAPI: Populate information for IMPORTED_RUNTIME_ARTIFACTS --- Help/manual/cmake-file-api.7.rst | 5 ++ Source/cmFileAPICodemodel.cxx | 10 +++ Tests/RunCMake/FileAPI/codemodel-v2-check.py | 2 +- .../directories/imported.json | 65 ++++++++++++++++++- .../RunCMake/FileAPI/imported/CMakeLists.txt | 7 ++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 0e530bc0bd2..e7d78c3a862 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -747,6 +747,11 @@ with members: An :command:`install(CODE)` call. This type has no additional members. + ``importedRuntimeArtifacts`` + An :command:`install(IMPORTED_RUNTIME_ARTIFACTS)` call. + The ``destination`` member is populated. The ``isOptional`` member may + exist. This type has no additional members. + ``isExcludeFromAll`` Optional member that is present with boolean value ``true`` when :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option. diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 945b5475ca4..ff11f4a797b 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -29,6 +29,7 @@ #include "cmInstallExportGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallImportedRuntimeArtifactsGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" @@ -1009,6 +1010,15 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) installer["scriptFile"] = RelativeIfUnder( this->TopSource, installScript->GetScript(this->Config)); } + } else if (auto* installImportedRuntimeArtifacts = + dynamic_cast( + gen)) { + installer["type"] = "importedRuntimeArtifacts"; + installer["destination"] = + installImportedRuntimeArtifacts->GetDestination(this->Config); + if (installImportedRuntimeArtifacts->GetOptional()) { + installer["isOptional"] = true; + } } // Add fields common to all install generators. diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index b9a1fbfc6a2..9911ad5be3e 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -644,7 +644,7 @@ def gen_check_directories(c, g): if sys.platform not in ("win32", "cygwin", "msys"): for e in expected: - e["installers"] = list(filter(lambda i: "_dllExtra" not in i or not i["_dllExtra"], e["installers"])) + e["installers"] = list(filter(lambda i: not i.get("_dllExtra", False), e["installers"])) if "aix" not in sys.platform: for i in e["installers"]: if "pathsNamelink" in i: diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json index d1272740974..92b95264050 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json @@ -14,6 +14,67 @@ ], "projectName": "Imported", "minimumCMakeVersion": "3.12", - "hasInstallRule": null, - "installers": [] + "hasInstallRule": true, + "installers": [ + { + "component": "Unspecified", + "type": "importedRuntimeArtifacts", + "destination": "lib", + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^imported/CMakeLists\\.txt$", + "line": 32, + "command": "install", + "hasParent": true + }, + { + "file": "^imported/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "importedRuntimeArtifacts", + "destination": "lib2", + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": true, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^imported/CMakeLists\\.txt$", + "line": 35, + "command": "install", + "hasParent": true + }, + { + "file": "^imported/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] } diff --git a/Tests/RunCMake/FileAPI/imported/CMakeLists.txt b/Tests/RunCMake/FileAPI/imported/CMakeLists.txt index f79d87c823b..770838b6a72 100644 --- a/Tests/RunCMake/FileAPI/imported/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/imported/CMakeLists.txt @@ -28,3 +28,10 @@ endif() add_library(imported_interface_lib INTERFACE IMPORTED) add_executable(link_imported_interface_exe ../empty.c) target_link_libraries(link_imported_interface_exe PRIVATE imported_interface_lib) + +install(IMPORTED_RUNTIME_ARTIFACTS imported_shared_lib + DESTINATION lib +) +install(IMPORTED_RUNTIME_ARTIFACTS imported_shared_lib + DESTINATION lib2 OPTIONAL +) From 76d583accd300e6463f225bd1f3556993078ad0e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 1 Jun 2021 00:01:10 -0400 Subject: [PATCH 0558/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fb2a862e4e1..f0c05486c73 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210531) +set(CMake_VERSION_PATCH 20210601) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a12639e658e4c116728dd86c1ef227215303a9a2 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 28 May 2021 09:23:30 -0400 Subject: [PATCH 0559/1519] file(GET_RUNTIME_DEPENDENCIES): Add POST_{IN,EX}CLUDE_FILES arguments --- Help/command/file.rst | 32 ++++-- .../get-runtime-dependencies-file-filter.rst | 5 + Source/cmFileCommand.cxx | 34 ++++-- Source/cmRuntimeDependencyArchive.cxx | 70 +++++++----- Source/cmRuntimeDependencyArchive.h | 8 +- .../RunCMakeTest.cmake | 24 +++- .../badargs2.cmake | 2 + .../file-filter-all-check.cmake | 28 +++++ .../file-filter.cmake | 104 ++++++++++++++++++ .../linux-all-check.cmake | 18 --- .../macos-all-check.cmake | 18 --- .../windows-all-check.cmake | 18 --- 12 files changed, 258 insertions(+), 103 deletions(-) create mode 100644 Help/release/dev/get-runtime-dependencies-file-filter.rst create mode 100644 Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake create mode 100644 Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index f46e55a056c..761fcbcca5a 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -179,6 +179,8 @@ the ```` and ``UTC`` options. [PRE_EXCLUDE_REGEXES [...]] [POST_INCLUDE_REGEXES [...]] [POST_EXCLUDE_REGEXES [...]] + [POST_INCLUDE_FILES [...]] + [POST_EXCLUDE_FILES [...]] ) .. versionadded:: 3.16 @@ -276,6 +278,18 @@ be resolved. See below for a full description of how they work. List of post-exclude regexes through which to filter the names of resolved dependencies. +``POST_INCLUDE_FILES `` + .. versionadded:: 3.21 + + List of post-include filenames through which to filter the names of resolved + dependencies. Symlinks are resolved when attempting to match these filenames. + +``POST_EXCLUDE_FILES `` + .. versionadded:: 3.21 + + List of post-exclude filenames through which to filter the names of resolved + dependencies. Symlinks are resolved when attempting to match these filenames. + These arguments can be used to exclude unwanted system libraries when resolving the dependencies, or to include libraries from a specific directory. The filtering works as follows: @@ -289,16 +303,18 @@ directory. The filtering works as follows: 4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according to the linking rules of the platform (see below). 5. If the dependency is found, and its full path matches one of the - ``POST_INCLUDE_REGEXES``, the full path is added to the resolved - dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves - that library's own dependencies. Otherwise, resolution proceeds to step 6. + ``POST_INCLUDE_REGEXES`` or ``POST_INCLUDE_FILES``, the full path is added + to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` + recursively resolves that library's own dependencies. Otherwise, resolution + proceeds to step 6. 6. If the dependency is found, but its full path matches one of the - ``POST_EXCLUDE_REGEXES``, it is not added to the resolved dependencies, and - dependency resolution stops for that dependency. + ``POST_EXCLUDE_REGEXES`` or ``POST_EXCLUDE_FILES``, it is not added to the + resolved dependencies, and dependency resolution stops for that dependency. 7. If the dependency is found, and its full path does not match either - ``POST_INCLUDE_REGEXES`` or ``POST_EXCLUDE_REGEXES``, the full path is added - to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` - recursively resolves that library's own dependencies. + ``POST_INCLUDE_REGEXES``, ``POST_INCLUDE_FILES``, ``POST_EXCLUDE_REGEXES``, + or ``POST_EXCLUDE_FILES``, the full path is added to the resolved + dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves + that library's own dependencies. Different platforms have different rules for how dependencies are resolved. These specifics are described here. diff --git a/Help/release/dev/get-runtime-dependencies-file-filter.rst b/Help/release/dev/get-runtime-dependencies-file-filter.rst new file mode 100644 index 00000000000..3fc17ac7929 --- /dev/null +++ b/Help/release/dev/get-runtime-dependencies-file-filter.rst @@ -0,0 +1,5 @@ +get-runtime-dependencies-file-filter +------------------------------------ + +* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command gained new + ``POST_INCLUDE_FILES`` and ``POST_EXCLUDE_FILES`` arguments. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1088347f103..f2d4cdad4e5 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3041,6 +3041,9 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, std::vector PreExcludeRegexes; std::vector PostIncludeRegexes; std::vector PostExcludeRegexes; + std::vector PostIncludeFiles; + std::vector PostExcludeFiles; + std::vector PostExcludeFilesStrict; }; static auto const parser = @@ -3058,7 +3061,10 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, .Bind("PRE_INCLUDE_REGEXES"_s, &Arguments::PreIncludeRegexes) .Bind("PRE_EXCLUDE_REGEXES"_s, &Arguments::PreExcludeRegexes) .Bind("POST_INCLUDE_REGEXES"_s, &Arguments::PostIncludeRegexes) - .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes); + .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes) + .Bind("POST_INCLUDE_FILES"_s, &Arguments::PostIncludeFiles) + .Bind("POST_EXCLUDE_FILES"_s, &Arguments::PostExcludeFiles) + .Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict); std::vector unrecognizedArguments; std::vector keywordsMissingValues; @@ -3072,14 +3078,19 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, return false; } - const std::vector LIST_ARGS = { "DIRECTORIES", - "EXECUTABLES", - "LIBRARIES", - "MODULES", - "POST_EXCLUDE_REGEXES", - "POST_INCLUDE_REGEXES", - "PRE_EXCLUDE_REGEXES", - "PRE_INCLUDE_REGEXES" }; + const std::vector LIST_ARGS = { + "DIRECTORIES", + "EXECUTABLES", + "LIBRARIES", + "MODULES", + "POST_EXCLUDE_FILES", + "POST_EXCLUDE_FILES_STRICT", + "POST_EXCLUDE_REGEXES", + "POST_INCLUDE_FILES", + "POST_INCLUDE_REGEXES", + "PRE_EXCLUDE_REGEXES", + "PRE_INCLUDE_REGEXES", + }; auto kwbegin = keywordsMissingValues.cbegin(); auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); if (kwend != kwbegin) { @@ -3092,7 +3103,10 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, cmRuntimeDependencyArchive archive( status, parsedArgs.Directories, parsedArgs.BundleExecutable, parsedArgs.PreIncludeRegexes, parsedArgs.PreExcludeRegexes, - parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes); + parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes, + std::move(parsedArgs.PostIncludeFiles), + std::move(parsedArgs.PostExcludeFiles), + std::move(parsedArgs.PostExcludeFilesStrict)); if (!archive.Prepare()) { cmSystemTools::SetFatalErrorOccured(); return false; diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx index 472f234694c..a6ed523f22f 100644 --- a/Source/cmRuntimeDependencyArchive.cxx +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -115,7 +115,10 @@ cmRuntimeDependencyArchive::cmRuntimeDependencyArchive( const std::vector& preIncludeRegexes, const std::vector& preExcludeRegexes, const std::vector& postIncludeRegexes, - const std::vector& postExcludeRegexes) + const std::vector& postExcludeRegexes, + std::vector postIncludeFiles, + std::vector postExcludeFiles, + std::vector postExcludeFilesStrict) : Status(status) , SearchDirectories(std::move(searchDirectories)) , BundleExecutable(std::move(bundleExecutable)) @@ -123,6 +126,9 @@ cmRuntimeDependencyArchive::cmRuntimeDependencyArchive( , PreExcludeRegexes(preExcludeRegexes.size()) , PostIncludeRegexes(postIncludeRegexes.size()) , PostExcludeRegexes(postExcludeRegexes.size()) + , PostIncludeFiles(std::move(postIncludeFiles)) + , PostExcludeFiles(std::move(postExcludeFiles)) + , PostExcludeFilesStrict(std::move(postExcludeFilesStrict)) { std::transform(preIncludeRegexes.begin(), preIncludeRegexes.end(), this->PreIncludeRegexes.begin(), TransformCompile); @@ -306,39 +312,45 @@ bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand( bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name) { cmsys::RegularExpressionMatch match; - - for (auto const& regex : this->PreIncludeRegexes) { - if (regex.find(name.c_str(), match)) { - return false; - } - } - - for (auto const& regex : this->PreExcludeRegexes) { - if (regex.find(name.c_str(), match)) { - return true; - } - } - - return false; + auto const regexMatch = + [&match, name](const cmsys::RegularExpression& regex) -> bool { + return regex.find(name.c_str(), match); + }; + auto const regexSearch = + [®exMatch]( + const std::vector& regexes) -> bool { + return std::any_of(regexes.begin(), regexes.end(), regexMatch); + }; + + return !regexSearch(this->PreIncludeRegexes) && + regexSearch(this->PreExcludeRegexes); } bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) { cmsys::RegularExpressionMatch match; - - for (auto const& regex : this->PostIncludeRegexes) { - if (regex.find(name.c_str(), match)) { - return false; - } - } - - for (auto const& regex : this->PostExcludeRegexes) { - if (regex.find(name.c_str(), match)) { - return true; - } - } - - return false; + auto const regexMatch = + [&match, name](const cmsys::RegularExpression& regex) -> bool { + return regex.find(name.c_str(), match); + }; + auto const regexSearch = + [®exMatch]( + const std::vector& regexes) -> bool { + return std::any_of(regexes.begin(), regexes.end(), regexMatch); + }; + auto const fileMatch = [name](const std::string& file) -> bool { + return cmSystemTools::SameFile(file, name); + }; + auto const fileSearch = + [&fileMatch](const std::vector& files) -> bool { + return std::any_of(files.begin(), files.end(), fileMatch); + }; + + return fileSearch(this->PostExcludeFilesStrict) || + (!(regexSearch(this->PostIncludeRegexes) || + fileSearch(this->PostIncludeFiles)) && + (regexSearch(this->PostExcludeRegexes) || + fileSearch(this->PostExcludeFiles))); } void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name, diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h index 7f3b8e9bd96..1dc32618392 100644 --- a/Source/cmRuntimeDependencyArchive.h +++ b/Source/cmRuntimeDependencyArchive.h @@ -25,7 +25,10 @@ class cmRuntimeDependencyArchive const std::vector& preIncludeRegexes, const std::vector& preExcludeRegexes, const std::vector& postIncludeRegexes, - const std::vector& postExcludeRegexes); + const std::vector& postExcludeRegexes, + std::vector postIncludeFiles, + std::vector postExcludeFiles, + std::vector postExcludeFilesStrict); bool Prepare(); bool GetRuntimeDependencies(const std::vector& executables, const std::vector& libraries, @@ -62,6 +65,9 @@ class cmRuntimeDependencyArchive std::vector PreExcludeRegexes; std::vector PostIncludeRegexes; std::vector PostExcludeRegexes; + std::vector PostIncludeFiles; + std::vector PostExcludeFiles; + std::vector PostExcludeFilesStrict; std::map> ResolvedPaths; std::set UnresolvedPaths; }; diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake index 763d57ce3e4..c71b9baeda7 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake @@ -11,7 +11,26 @@ function(run_install_test case) run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug) # Check "all" components. set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-all) - run_cmake_command(${case}-all ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -P cmake_install.cmake) + run_cmake_command(${case}-all ${CMAKE_COMMAND} --install . --prefix ${CMAKE_INSTALL_PREFIX} --config Debug) +endfunction() + +# Function to check the contents of the output files. +function(check_contents filename contents_regex) + if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") + file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) + if(NOT contents MATCHES "${contents_regex}") + string(APPEND RunCMake_TEST_FAILED "File contents: + ${contents} +do not match what we expected: + ${contents_regex} +in file: + ${CMAKE_INSTALL_PREFIX}/${filename}\n") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() + else() + string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() endfunction() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") @@ -20,6 +39,7 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") run_install_test(macos-unresolved) run_install_test(macos-conflict) run_install_test(macos-notfile) + run_install_test(file-filter) endif() run_cmake(project) run_cmake(badargs1) @@ -29,6 +49,7 @@ elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") run_install_test(windows-unresolved) run_install_test(windows-conflict) run_install_test(windows-notfile) + run_install_test(file-filter) run_cmake(project) run_cmake(badargs1) run_cmake(badargs2) @@ -41,6 +62,7 @@ elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") if(NOT CMAKE_C_COMPILER_ID MATCHES "^XL") run_install_test(linux) + run_install_test(file-filter) endif() run_install_test(linux-unresolved) run_install_test(linux-conflict) diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake index ac6af85760e..f80829dc1c9 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2.cmake @@ -11,5 +11,7 @@ file(GET_RUNTIME_DEPENDENCIES PRE_EXCLUDE_REGEXES POST_INCLUDE_REGEXES POST_EXCLUDE_REGEXES + POST_INCLUDE_FILES + POST_EXCLUDE_FILES ) message(FATAL_ERROR "This message should not be displayed") diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake new file mode 100644 index 00000000000..9622f877ca0 --- /dev/null +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-all-check.cmake @@ -0,0 +1,28 @@ +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(_check + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep1\.so]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep2\.so]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep3\.so]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep4\.so]] + ) + check_contents(deps/deps.txt "^${_check}$") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(_check + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep1\.dylib]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep2\.dylib]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep3\.dylib]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/\.\./lib/libdep4\.dylib]] + ) + check_contents(deps/deps.txt "^${_check}$") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(_check + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep1\.dll]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep2\.dll]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep3\.dll]] + [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter-build/root-all/bin/(lib)?dep4\.dll]] + ) + check_contents(deps/deps.txt "^${_check}$") +endif() + +check_contents(deps/udeps.txt "^$") +check_contents(deps/cdeps.txt "^$") diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake new file mode 100644 index 00000000000..fef084b96ae --- /dev/null +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/file-filter.cmake @@ -0,0 +1,104 @@ +enable_language(C) + +set(dep_list) +set(import_list) +set(call_list) +foreach(i 1 2 3 4 5 6 7 8 9) + file(WRITE "${CMAKE_BINARY_DIR}/dep${i}.c" +"#ifdef _WIN32 +__declspec(dllexport) +#endif + void dep${i}(void) +{ +} +") + add_library(dep${i} SHARED "${CMAKE_BINARY_DIR}/dep${i}.c") + list(APPEND dep_list dep${i}) + string(APPEND import_list "EXE_IMPORT extern void dep${i}(void);\n") + string(APPEND call_list " dep${i}();\n") +endforeach() +set_target_properties(dep5 PROPERTIES + VERSION 1.2.3 + SOVERSION 1 + ) + +file(WRITE "${CMAKE_BINARY_DIR}/main.c" +"#ifdef _WIN32 +# define EXE_IMPORT __declspec(dllimport) +#else +# define EXE_IMPORT +#endif + +${import_list} +int main(void) +{ +${call_list} + return 0; +} +") + +add_executable(exe "${CMAKE_BINARY_DIR}/main.c") +target_link_libraries(exe PRIVATE ${dep_list}) + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set_property(TARGET exe PROPERTY INSTALL_RPATH "\${ORIGIN}/../lib") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_property(TARGET exe PROPERTY INSTALL_RPATH "@loader_path/../lib") +endif() + +install(TARGETS exe ${dep_list}) + +install(CODE + [[ + function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile) + file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR deps + UNRESOLVED_DEPENDENCIES_VAR udeps + CONFLICTING_DEPENDENCIES_PREFIX cdeps + PRE_INCLUDE_REGEXES "dep[123456789]" + PRE_EXCLUDE_REGEXES ".*" + POST_INCLUDE_REGEXES "dep9" + POST_INCLUDE_FILES + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/../bin/$" + "${CMAKE_INSTALL_PREFIX}/bin/../lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + POST_EXCLUDE_FILES + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/../bin/$" + "${CMAKE_INSTALL_PREFIX}/bin/../lib/$" + POST_EXCLUDE_FILES_STRICT + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + "${CMAKE_INSTALL_PREFIX}/bin/$" + "${CMAKE_INSTALL_PREFIX}/lib/$" + ${ARGN} + ) + list(SORT deps) + list(SORT udeps) + list(SORT cdeps_FILENAMES) + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "") + foreach(cdep IN LISTS cdeps_FILENAMES) + set(cdep_values ${cdeps_${cdep}}) + list(SORT cdep_values) + file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n") + endforeach() + endfunction() + + exec_get_runtime_dependencies( + deps.txt udeps.txt cdeps.txt + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/bin/$" + ) + ]]) diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake index 381b60291bf..d3d1cd6e86d 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-all-check.cmake @@ -1,21 +1,3 @@ -function(check_contents filename contents_regex) - if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") - file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) - if(NOT contents MATCHES "${contents_regex}") - string(APPEND RunCMake_TEST_FAILED "File contents: - ${contents} -do not match what we expected: - ${contents_regex} -in file: - ${CMAKE_INSTALL_PREFIX}/${filename}\n") - set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) - endif() - else() - string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") - set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) - endif() -endfunction() - set(_check [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/libtest_rpath\.so]] [[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-build/root-all/lib/libtest_runpath\.so]] diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake index e7cdbf66f6e..e9ff9f6e71d 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-all-check.cmake @@ -1,21 +1,3 @@ -function(check_contents filename contents_regex) - if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") - file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) - if(NOT contents MATCHES "${contents_regex}") - string(APPEND RunCMake_TEST_FAILED "File contents: - ${contents} -do not match what we expected: - ${contents_regex} -in file: - ${CMAKE_INSTALL_PREFIX}/${filename}\n") - set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) - endif() - else() - string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") - set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) - endif() -endfunction() - function(set_with_libsystem var) set(_tmp "${ARGN}") if(EXISTS "/usr/lib/libSystem.B.dylib") diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake index f1d70a10992..cb0e534a35f 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-all-check.cmake @@ -1,21 +1,3 @@ -function(check_contents filename contents_regex) - if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") - file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) - if(NOT contents MATCHES "${contents_regex}") - string(APPEND RunCMake_TEST_FAILED "File contents: - ${contents} -do not match what we expected: - ${contents_regex} -in file: - ${CMAKE_INSTALL_PREFIX}/${filename}\n") - set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) - endif() - else() - string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") - set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) - endif() -endfunction() - set(_check [=[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-build/root-all/bin/\.conflict/\.\./(lib)?libdir\.dll]=] [=[[^;]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-build/root-all/bin/\.search/(lib)?search\.dll]=] From 2104cfe388f5d77b98727c89edff453b1d23fed6 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 2 Jun 2021 00:01:11 -0400 Subject: [PATCH 0560/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f0c05486c73..683e90d3a07 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210601) +set(CMake_VERSION_PATCH 20210602) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f0e9d74a2d371ab2c22b3c7608bc8da1548873a0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 2 Jun 2021 07:41:05 -0400 Subject: [PATCH 0561/1519] cmake_transform_depfile: Remove unused incomplete vstlog support In commit b2c14bc774 (cmake -E: Add cmake_transform_depfile internal command, 2020-10-02, v3.20.0-rc1~684^2~2) a partial implementation for converting MSBuild "TLog" format files was added. However, it is unused and incomplete: * Does not enforce absolute paths as TLog docs require. * Does not upper-case paths as TLog docs recommend. * The TLog format semantics are not equivalent to `out: in`. Remove the unused TLog transform infrastructure to avoid confusion. Issue: #20286 --- Source/cmCustomCommandGenerator.cxx | 6 ---- Source/cmTransformDepfile.cxx | 34 ------------------- Source/cmTransformDepfile.h | 1 - Source/cmcmd.cxx | 2 -- .../TransformDepfile/RunCMakeTest.cmake | 4 --- 5 files changed, 47 deletions(-) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 77779ba7810..10a6491f932 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -227,9 +227,6 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( case cmDepfileFormat::GccDepfile: argv.emplace_back("gccdepfile"); break; - case cmDepfileFormat::VsTlog: - argv.emplace_back("vstlog"); - break; case cmDepfileFormat::MakeDepfile: argv.emplace_back("makedepfile"); break; @@ -440,9 +437,6 @@ std::string cmCustomCommandGenerator::GetInternalDepfileName( case cmDepfileFormat::MakeDepfile: extension = ".d"; break; - case cmDepfileFormat::VsTlog: - extension = ".tlog"; - break; } return cmStrCat(this->LG->GetBinaryDirectory(), "/CMakeFiles/d/", hash.HashString(depfile), extension); diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 6927300ce3f..0df9550b823 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -78,37 +78,6 @@ void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout, } } } - -// tlog format : always windows paths on Windows regardless the generator -std::string ConvertToTLogOutputPath(const std::string& path) -{ -#if defined(_WIN32) && !defined(__CYGWIN__) - return cmSystemTools::ConvertToWindowsOutputPath(path); -#else - return cmSystemTools::ConvertToOutputPath(path); -#endif -} - -void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg, - const cmGccDepfileContent& content) -{ - for (auto const& dep : content) { - fout << '^'; - bool first = true; - for (auto const& rule : dep.rules) { - if (!first) { - fout << '|'; - } - first = false; - fout << ConvertToTLogOutputPath(lg.MaybeRelativeToTopBinDir(rule)); - } - fout << "\r\n"; - for (auto const& path : dep.paths) { - fout << ConvertToTLogOutputPath(lg.MaybeRelativeToTopBinDir(path)) - << "\r\n"; - } - } -} } bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, @@ -133,9 +102,6 @@ bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, case cmDepfileFormat::MakeDepfile: WriteDepfile(format, fout, lg, content); break; - case cmDepfileFormat::VsTlog: - WriteVsTlog(fout, lg, content); - break; } return true; } diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h index c31e4abfeb4..ce7cd66fe2f 100644 --- a/Source/cmTransformDepfile.h +++ b/Source/cmTransformDepfile.h @@ -7,7 +7,6 @@ enum class cmDepfileFormat { GccDepfile, - VsTlog, MakeDepfile }; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 727e41263cd..84ac1891f5f 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1529,8 +1529,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, auto format = cmDepfileFormat::GccDepfile; if (args[3] == "gccdepfile") { format = cmDepfileFormat::GccDepfile; - } else if (args[3] == "vstlog") { - format = cmDepfileFormat::VsTlog; } else if (args[3] == "makedepfile") { format = cmDepfileFormat::MakeDepfile; } else { diff --git a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake index 9a38b957f58..1ce723b4069 100644 --- a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake +++ b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake @@ -5,10 +5,6 @@ function(run_transform_depfile name) run_cmake_command(${name}-gcc ${CMAKE_COMMAND} -E cmake_transform_depfile "${RunCMake_GENERATOR}" gccdepfile "${RunCMake_SOURCE_DIR}" "${RunCMake_SOURCE_DIR}/subdir" "${RunCMake_BINARY_DIR}" "${RunCMake_BINARY_DIR}/subdir" "${CMAKE_CURRENT_LIST_DIR}/${name}.d" out.d ) - set(RunCMake-check-file vstlog.cmake) - run_cmake_command(${name}-tlog - ${CMAKE_COMMAND} -E cmake_transform_depfile "${RunCMake_GENERATOR}" vstlog "${RunCMake_SOURCE_DIR}" "${RunCMake_SOURCE_DIR}/subdir" "${RunCMake_BINARY_DIR}" "${RunCMake_BINARY_DIR}/subdir" "${CMAKE_CURRENT_LIST_DIR}/${name}.d" out.tlog - ) endfunction() if(WIN32) From fc5b7905ed8e2ddc45de1cabe0f9dbd8c1484dbb Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Wed, 2 Jun 2021 07:24:05 -0400 Subject: [PATCH 0562/1519] KWSys 2021-06-02 (ad35b3ba) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit ad35b3bae42fe21b8ea1d35799c8f141c9d5a2ec (master). Upstream Shortlog ----------------- Adriaan de Groot (1): e65c5693 testSystemTools: apply root-check to more systems --- testSystemTools.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/testSystemTools.cxx b/testSystemTools.cxx index 700eaf7ebfc..39a19cbf241 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -332,9 +332,10 @@ static bool CheckFileOperations() // While we're at it, check proper TestFileAccess functionality. bool do_write_test = true; -#if defined(__linux__) - // If we are running as root on linux ignore this check, as - // root can always write to files +#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__NetBSD__) || defined(__DragonFly__) + // If we are running as root on POSIX-ish systems (Linux and the BSDs, + // at least), ignore this check, as root can always write to files. do_write_test = (getuid() != 0); #endif if (do_write_test && From 5d5610b04f51c780d4e5b7f2fd24268f773bea3d Mon Sep 17 00:00:00 2001 From: Joseph Snyder Date: Wed, 19 May 2021 11:46:21 -0400 Subject: [PATCH 0563/1519] CTest: Exit coverage handling early if no binary dir Check for the existence of the Binary directory string before checking for coverage files. If the directory is not specified, write an error message and do not do any checking. Fixes: #22102 --- Source/CTest/cmCTestCoverageHandler.cxx | 7 +++++++ .../CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt | 3 +++ Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake | 4 ++++ 3 files changed, 14 insertions(+) create mode 100644 Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 3d7d0312b36..57b1ddaf522 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -289,6 +289,13 @@ int cmCTestCoverageHandler::ProcessHandler() this->CTest->GetCTestConfiguration("SourceDirectory"); std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory"); + if (binaryDir.empty()) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Binary directory is not set. " + "No coverage checking will be performed." + << std::endl); + return 0; + } this->LoadLabels(); cmGeneratedFileStream ofs; diff --git a/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt b/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt new file mode 100644 index 00000000000..e6f93256b0c --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-stderr.txt @@ -0,0 +1,3 @@ +Cannot find file: [^ +]*/Tests/RunCMake/CTestCommandLine/EmptyDirCoverage-ctest-build/DartConfiguration.tcl +Binary directory is not set. No coverage checking will be performed.$ diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index afec0114aa4..4b654f85284 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -360,6 +360,10 @@ run_NoTests() # Check the configuration type variable is passed run_ctest(check-configuration-type) +run_cmake_command(EmptyDirCoverage-ctest + ${CMAKE_CTEST_COMMAND} -C Debug -M Experimental -T Coverage + ) + function(run_MemCheckSan case opts) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/MemCheckSan${case}-build) From dbe3f8eee7c76493ab8488811fdab54881b3f5ee Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 2 Jun 2021 08:57:43 -0400 Subject: [PATCH 0564/1519] Help: Clarify default value of CMAKE_CONFIGURATION_TYPES for NMC Fixes: #22266 --- Help/generator/Ninja Multi-Config.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst index 89011925f8f..e5ce4f5cd41 100644 --- a/Help/generator/Ninja Multi-Config.rst +++ b/Help/generator/Ninja Multi-Config.rst @@ -34,7 +34,9 @@ below for how to enable cross-config mode. The ``Ninja Multi-Config`` generator recognizes the following variables: :variable:`CMAKE_CONFIGURATION_TYPES` - Specifies the total set of configurations to build. + Specifies the total set of configurations to build. Unlike with other + multi-config generators, this variable has a value of + ``Debug;Release;RelWithDebInfo`` by default. :variable:`CMAKE_CROSS_CONFIGS` Specifies a :ref:`semicolon-separated list ` of From 0d210b92faf8b2c6aa3e433781c10b1397c80e62 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Sun, 30 May 2021 23:29:42 -0400 Subject: [PATCH 0565/1519] Help: links to CMake regex syntax --- Help/command/file.rst | 3 ++- Help/command/install.rst | 3 ++- Help/command/list.rst | 4 ++-- Help/manual/cmake-presets.7.rst | 3 ++- Help/manual/ctest.1.rst | 3 ++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Help/command/file.rst b/Help/command/file.rst index f46e55a056c..d8113ea2c6f 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -116,7 +116,8 @@ Parse a list of ASCII strings from ```` and store it in binary while reading unless this option is given. ``REGEX `` - Consider only strings that match the given regular expression. + Consider only strings that match the given regular expression, + as described under :ref:`string(REGEX) `. ``ENCODING `` .. versionadded:: 3.1 diff --git a/Help/command/install.rst b/Help/command/install.rst index 2259176d746..27c04b55a9e 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -540,7 +540,8 @@ any expression. For example, the code will extract and install header files from a source tree. -Some options may follow a ``PATTERN`` or ``REGEX`` expression and are applied +Some options may follow a ``PATTERN`` or ``REGEX`` expression as described +under :ref:`string(REGEX) ` and are applied only to files or directories matching them. The ``EXCLUDE`` option will skip the matched file or directory. The ``PERMISSIONS`` option overrides the permissions setting for the matched file or directory. For diff --git a/Help/command/list.rst b/Help/command/list.rst index 7accc5a39e1..f46641f0b6a 100644 --- a/Help/command/list.rst +++ b/Help/command/list.rst @@ -141,8 +141,8 @@ Appends elements to the list. Includes or removes items from the list that match the mode's pattern. In ``REGEX`` mode, items will be matched against the given regular expression. -For more information on regular expressions see also the -:command:`string` command. +For more information on regular expressions look under +:ref:`string(REGEX) `. .. _INSERT: diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 57c8ccf3d08..0bcd6910adb 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -642,7 +642,8 @@ that may contain the following fields: An optional string specifying a regex for test names. Equivalent to passing ``--tests-regex`` on the command line. This field supports - macro expansion. + macro expansion. CMake regex syntax is described under + :ref:`string(REGEX) `. ``label`` diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 811997c5548..72ef2597ad1 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -158,7 +158,8 @@ Options See `Show as JSON Object Model`_. ``-L , --label-regex `` - Run tests with labels matching regular expression. + Run tests with labels matching regular expression as described under + :ref:`string(REGEX) `. This option tells CTest to run only the tests whose labels match the given regular expression. When more than one ``-L`` option is given, From 87b71eec6257b0d9c43b446205d61f334278fe7d Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Tue, 1 Jun 2021 16:05:34 +0200 Subject: [PATCH 0566/1519] find_*: Add support for option NO_CACHE Request that find result is stored in a normal variable rather than a cache entry. Fixes: #20687 Issue: #20743 --- Help/command/FIND_XXX.txt | 21 ++- Help/release/dev/find_item-NO_CACHE.rst | 6 + Source/cmFindBase.cxx | 115 +++++++++------ Source/cmFindBase.h | 7 +- Source/cmFindLibraryCommand.cxx | 2 +- Source/cmFindPathCommand.cxx | 2 +- Source/cmFindProgramCommand.cxx | 2 +- Tests/RunCMake/find_file/NO_CACHE-stdout.txt | 18 +++ Tests/RunCMake/find_file/NO_CACHE.cmake | 129 +++++++++++++++++ Tests/RunCMake/find_file/RunCMakeTest.cmake | 1 + .../RunCMake/find_library/NO_CACHE-stdout.txt | 18 +++ Tests/RunCMake/find_library/NO_CACHE.cmake | 133 ++++++++++++++++++ .../RunCMake/find_library/RunCMakeTest.cmake | 1 + Tests/RunCMake/find_path/NO_CACHE-stdout.txt | 18 +++ Tests/RunCMake/find_path/NO_CACHE.cmake | 131 +++++++++++++++++ Tests/RunCMake/find_path/RunCMakeTest.cmake | 1 + .../RunCMake/find_program/NO_CACHE-stdout.txt | 18 +++ Tests/RunCMake/find_program/NO_CACHE.cmake | 130 +++++++++++++++++ .../RunCMake/find_program/RunCMakeTest.cmake | 1 + 19 files changed, 700 insertions(+), 54 deletions(-) create mode 100644 Help/release/dev/find_item-NO_CACHE.rst create mode 100644 Tests/RunCMake/find_file/NO_CACHE-stdout.txt create mode 100644 Tests/RunCMake/find_file/NO_CACHE.cmake create mode 100644 Tests/RunCMake/find_library/NO_CACHE-stdout.txt create mode 100644 Tests/RunCMake/find_library/NO_CACHE.cmake create mode 100644 Tests/RunCMake/find_path/NO_CACHE-stdout.txt create mode 100644 Tests/RunCMake/find_path/NO_CACHE.cmake create mode 100644 Tests/RunCMake/find_program/NO_CACHE-stdout.txt create mode 100644 Tests/RunCMake/find_program/NO_CACHE.cmake diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index aae1c382877..5b63e1cba90 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -15,6 +15,7 @@ The general signature is: [PATHS [path | ENV var]... ] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] + [NO_CACHE] [REQUIRED] [NO_DEFAULT_PATH] [NO_PACKAGE_ROOT_PATH] @@ -28,8 +29,8 @@ The general signature is: ) This command is used to find a |SEARCH_XXX_DESC|. -A cache entry named by ```` is created to store the result -of this command. +A cache entry, or a normal variable if ``NO_CACHE`` is specified, +named by ```` is created to store the result of this command. If the |SEARCH_XXX| is found the result is stored in the variable and the search will not be repeated unless the variable is cleared. If nothing is found, the result will be ``-NOTFOUND``. @@ -56,6 +57,22 @@ Options include: ``DOC`` Specify the documentation string for the ```` cache entry. +``NO_CACHE`` + .. versionadded:: 3.21 + + The result of the search will be stored in a normal variable rather than + a cache entry. + + .. note:: + + If the variable is already set before the call (as a normal or cache + variable) then the search will not occur. + + .. warning:: + + This option should be used with caution because it can greatly increase + the cost of repeated configure steps. + ``REQUIRED`` .. versionadded:: 3.18 diff --git a/Help/release/dev/find_item-NO_CACHE.rst b/Help/release/dev/find_item-NO_CACHE.rst new file mode 100644 index 00000000000..be5258c1a04 --- /dev/null +++ b/Help/release/dev/find_item-NO_CACHE.rst @@ -0,0 +1,6 @@ +find_item-NO_CACHE +------------------ + +* The :command:`find_file`, :command:`find_path`, :command:`find_program`, + and :command:`find_library` commands gained the option ``NO_CACHE`` to store + find result in normal variable. diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index c1281e3278b..1038ac29e15 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -39,12 +39,15 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) // copy argsIn into args so it can be modified, // in the process extract the DOC "documentation" + // and handle options NO_CACHE and ENV size_t size = argsIn.size(); std::vector args; bool foundDoc = false; for (unsigned int j = 0; j < size; ++j) { if (foundDoc || argsIn[j] != "DOC") { - if (argsIn[j] == "ENV") { + if (argsIn[j] == "NO_CACHE") { + this->StoreResultInCache = false; + } else if (argsIn[j] == "ENV") { if (j + 1 < size) { j++; cmSystemTools::GetPath(args, argsIn[j].c_str()); @@ -68,11 +71,10 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) return false; } this->VariableName = args[0]; - if (this->CheckForVariableInCache()) { - this->AlreadyInCache = true; + if (this->CheckForVariableDefined()) { + this->AlreadyDefined = true; return true; } - this->AlreadyInCache = false; // Find what search path locations have been enabled/disable this->SelectDefaultSearchModes(); @@ -297,12 +299,12 @@ void cmFindBase::FillUserGuessPath() paths.AddSuffixes(this->SearchPathSuffixes); } -bool cmFindBase::CheckForVariableInCache() +bool cmFindBase::CheckForVariableDefined() { - if (cmProp cacheValue = this->Makefile->GetDefinition(this->VariableName)) { + if (cmProp value = this->Makefile->GetDefinition(this->VariableName)) { cmState* state = this->Makefile->GetState(); cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName); - bool found = !cmIsNOTFOUND(*cacheValue); + bool found = !cmIsNOTFOUND(*value); bool cached = cacheEntry != nullptr; auto cacheType = cached ? state->GetCacheEntryType(this->VariableName) : cmStateEnums::UNINITIALIZED; @@ -350,41 +352,53 @@ void cmFindBase::NormalizeFindResult() } } - // If the user specifies the entry on the command line without a - // type we should add the type and docstring but keep the original - // value. - if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) { - this->Makefile->GetCMakeInstance()->AddCacheEntry( - this->VariableName, value.c_str(), this->VariableDocumentation.c_str(), - this->VariableType); - if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == - cmPolicies::NEW) { - if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) { - this->Makefile->AddDefinition(this->VariableName, value); + if (this->StoreResultInCache) { + // If the user specifies the entry on the command line without a + // type we should add the type and docstring but keep the original + // value. + if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) { + this->Makefile->GetCMakeInstance()->AddCacheEntry( + this->VariableName, value.c_str(), + this->VariableDocumentation.c_str(), this->VariableType); + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == + cmPolicies::NEW) { + if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition(this->VariableName, value); + } + } else { + // if there was a definition then remove it + // This is required to ensure same behavior as + // cmMakefile::AddCacheDefinition. + this->Makefile->RemoveDefinition(this->VariableName); } - } else { - // if there was a definition then remove it - // This is required to ensure same behavior as - // cmMakefile::AddCacheDefinition. - this->Makefile->RemoveDefinition(this->VariableName); } + } else { + // ensure a normal variable is defined. + this->Makefile->AddDefinition(this->VariableName, value); } } else { // If the user specifies the entry on the command line without a // type we should add the type and docstring but keep the original // value. - if (this->AlreadyInCacheWithoutMetaInfo) { - this->Makefile->AddCacheDefinition(this->VariableName, "", - this->VariableDocumentation.c_str(), - this->VariableType); - if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == - cmPolicies::NEW && - this->Makefile->IsNormalDefinitionSet(this->VariableName)) { - this->Makefile->AddDefinition( - this->VariableName, - *this->Makefile->GetCMakeInstance()->GetCacheDefinition( - this->VariableName)); + if (this->StoreResultInCache) { + if (this->AlreadyInCacheWithoutMetaInfo) { + this->Makefile->AddCacheDefinition(this->VariableName, "", + this->VariableDocumentation.c_str(), + this->VariableType); + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == + cmPolicies::NEW && + this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition( + this->VariableName, + *this->Makefile->GetCMakeInstance()->GetCacheDefinition( + this->VariableName)); + } } + } else { + // ensure a normal variable is defined. + this->Makefile->AddDefinition( + this->VariableName, + this->Makefile->GetSafeDefinition(this->VariableName)); } } } @@ -397,23 +411,32 @@ void cmFindBase::StoreFindResult(const std::string& value) this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW; if (!value.empty()) { - this->Makefile->AddCacheDefinition(this->VariableName, value, - this->VariableDocumentation.c_str(), - this->VariableType, force); - if (updateNormalVariable && - this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + if (this->StoreResultInCache) { + this->Makefile->AddCacheDefinition(this->VariableName, value, + this->VariableDocumentation.c_str(), + this->VariableType, force); + if (updateNormalVariable && + this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition(this->VariableName, value); + } + } else { this->Makefile->AddDefinition(this->VariableName, value); } + return; } - this->Makefile->AddCacheDefinition( - this->VariableName, cmStrCat(this->VariableName, "-NOTFOUND"), - this->VariableDocumentation.c_str(), this->VariableType, force); - if (updateNormalVariable && - this->Makefile->IsNormalDefinitionSet(this->VariableName)) { - this->Makefile->AddDefinition(this->VariableName, - cmStrCat(this->VariableName, "-NOTFOUND")); + auto notFound = cmStrCat(this->VariableName, "-NOTFOUND"); + if (this->StoreResultInCache) { + this->Makefile->AddCacheDefinition(this->VariableName, notFound, + this->VariableDocumentation.c_str(), + this->VariableType, force); + if (updateNormalVariable && + this->Makefile->IsNormalDefinitionSet(this->VariableName)) { + this->Makefile->AddDefinition(this->VariableName, notFound); + } + } else { + this->Makefile->AddDefinition(this->VariableName, notFound); } if (this->Required) { diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index c2a9288aad6..d197424db14 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -35,10 +35,10 @@ class cmFindBase : public cmFindCommon friend class cmFindBaseDebugState; void ExpandPaths(); - // see if the VariableName is already set in the cache, + // see if the VariableName is already set, // also copy the documentation from the cache to VariableDocumentation // if it has documentation in the cache - bool CheckForVariableInCache(); + bool CheckForVariableDefined(); void NormalizeFindResult(); void StoreFindResult(const std::string& value); @@ -57,8 +57,9 @@ class cmFindBase : public cmFindCommon // CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM std::string EnvironmentPath; // LIB,INCLUDE - bool AlreadyInCache = false; + bool AlreadyDefined = false; bool AlreadyInCacheWithoutMetaInfo = false; + bool StoreResultInCache = true; bool Required = false; diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index b1f4275951a..0cbe637738b 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -39,7 +39,7 @@ bool cmFindLibraryCommand::InitialPass(std::vector const& argsIn) return false; } - if (this->AlreadyInCache) { + if (this->AlreadyDefined) { this->NormalizeFindResult(); return true; } diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 126cc2f2138..3d21167f792 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -36,7 +36,7 @@ bool cmFindPathCommand::InitialPass(std::vector const& argsIn) return false; } - if (this->AlreadyInCache) { + if (this->AlreadyDefined) { this->NormalizeFindResult(); return true; } diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 76fc4a42a38..1c87625e29c 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -165,7 +165,7 @@ bool cmFindProgramCommand::InitialPass(std::vector const& argsIn) return false; } - if (this->AlreadyInCache) { + if (this->AlreadyDefined) { this->NormalizeFindResult(); return true; } diff --git a/Tests/RunCMake/find_file/NO_CACHE-stdout.txt b/Tests/RunCMake/find_file/NO_CACHE-stdout.txt new file mode 100644 index 00000000000..e7863211268 --- /dev/null +++ b/Tests/RunCMake/find_file/NO_CACHE-stdout.txt @@ -0,0 +1,18 @@ +-- FILE_exists='.+/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- FILE_doNotExists='FILE_doNotExists-NOTFOUND' +--[ ]+ +-- Policy CMP0125 = OLD +-- CACHED FILE_cache='unknown' +-- FILE_cache='unknown' +-- CACHED FILE_cache='PrefixInPATH.h' +-- FILE_cache='PrefixInPATH.h' +-- CACHED FILE_cache='PrefixInPATH.h' +-- FILE_cache='PrefixInPATH.h' +--[ ]+ +-- Policy CMP0125 = NEW +-- CACHED FILE_cache='unknown' +-- FILE_cache='unknown' +-- CACHED FILE_cache='PrefixInPATH.h' +-- FILE_cache='PrefixInPATH.h' +-- CACHED FILE_cache='PrefixInPATH.h' +-- FILE_cache='.+/Tests/RunCMake/find_file/NO_CACHE-build/PrefixInPATH.h' diff --git a/Tests/RunCMake/find_file/NO_CACHE.cmake b/Tests/RunCMake/find_file/NO_CACHE.cmake new file mode 100644 index 00000000000..65156b95877 --- /dev/null +++ b/Tests/RunCMake/find_file/NO_CACHE.cmake @@ -0,0 +1,129 @@ +find_file(FILE_exists + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (DEFINED CACHE{FILE_exists}) + message(SEND_ERROR "Cache variable defined: FILE_exists") +endif() +message(STATUS "FILE_exists='${FILE_exists}'") + + +find_file(FILE_doNotExists + NAMES doNotExists.h + NO_CACHE + ) +if (DEFINED CACHE{FILE_doNotExists}) + message(SEND_ERROR "Cache variable defined: FILE_doNotExists") +endif() +message(STATUS "FILE_doNotExists='${FILE_doNotExists}'") + + +cmake_policy(SET CMP0125 OLD) +message(STATUS "") +message(STATUS "Policy CMP0125 = OLD") +file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h") + +set(FILE_cache "unknown" CACHE FILEPATH "") +find_file(FILE_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{FILE_cache}) + message(SEND_ERROR "Cache variable not defined: FILE_cache") +endif() +message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'") +unset(FILE_cache CACHE) +message(STATUS "FILE_cache='${FILE_cache}'") + + +set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "") +unset(FILE_cache) +find_file(FILE_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{FILE_cache}) + message(SEND_ERROR "Cache variable not defined: FILE_cache") +endif() +message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'") +unset(FILE_cache CACHE) +message(STATUS "FILE_cache='${FILE_cache}'") + + +set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "") +unset(FILE_cache) +# simulate cache variable defined in command line +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}") +set_property(CACHE FILE_cache PROPERTY TYPE UNINITIALIZED) +find_file(FILE_cache + NAMES PrefixInPATH.h + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{FILE_cache}) + message(SEND_ERROR "Cache variable not defined: FILE_cache") +endif() +message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'") +unset(FILE_cache CACHE) +message(STATUS "FILE_cache='${FILE_cache}'") + + +cmake_policy(SET CMP0125 NEW) +message(STATUS "") +message(STATUS "Policy CMP0125 = NEW") +file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h") + +set(FILE_cache "unknown" CACHE FILEPATH "") +unset(FILE_cache) +find_file(FILE_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{FILE_cache}) + message(SEND_ERROR "Cache variable not defined: FILE_cache") +endif() +message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'") +unset(FILE_cache CACHE) +message(STATUS "FILE_cache='${FILE_cache}'") + + +set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "") +unset(FILE_cache) +find_file(FILE_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{FILE_cache}) + message(SEND_ERROR "Cache variable not defined: FILE_cache") +endif() +message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'") +unset(FILE_cache CACHE) +message(STATUS "FILE_cache='${FILE_cache}'") + + +set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "") +unset(FILE_cache) +# simulate cache variable defined in command line +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}") +set_property(CACHE FILE_cache PROPERTY TYPE UNINITIALIZED) +find_file(FILE_cache + NAMES PrefixInPATH.h + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{FILE_cache}) + message(SEND_ERROR "Cache variable not defined: FILE_cache") +endif() +message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'") +unset(FILE_cache CACHE) +message(STATUS "FILE_cache='${FILE_cache}'") diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake index 93dfb7870bf..95f55a5b37c 100644 --- a/Tests/RunCMake/find_file/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake @@ -4,3 +4,4 @@ run_cmake(FromPATHEnv) run_cmake(FromPrefixPath) run_cmake(PrefixInPATH) run_cmake(Required) +run_cmake(NO_CACHE) diff --git a/Tests/RunCMake/find_library/NO_CACHE-stdout.txt b/Tests/RunCMake/find_library/NO_CACHE-stdout.txt new file mode 100644 index 00000000000..1b4c2a90d66 --- /dev/null +++ b/Tests/RunCMake/find_library/NO_CACHE-stdout.txt @@ -0,0 +1,18 @@ +-- LIB_exists='.+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- LIB_doNotExists='LIB_doNotExists-NOTFOUND' +--[ ]+ +-- Policy CMP0125 = OLD +-- CACHED LIB_cache='unknown' +-- LIB_cache='unknown' +-- CACHED LIB_cache='libPrefixInPATH.a' +-- LIB_cache='libPrefixInPATH.a' +-- CACHED LIB_cache='libPrefixInPATH.a' +-- LIB_cache='libPrefixInPATH.a' +--[ ]+ +-- Policy CMP0125 = NEW +-- CACHED LIB_cache='unknown' +-- LIB_cache='unknown' +-- CACHED LIB_cache='libPrefixInPATH.a' +-- LIB_cache='libPrefixInPATH.a' +-- CACHED LIB_cache='libPrefixInPATH.a' +-- LIB_cache='.+/Tests/RunCMake/find_library/NO_CACHE-build/libPrefixInPATH.a' diff --git a/Tests/RunCMake/find_library/NO_CACHE.cmake b/Tests/RunCMake/find_library/NO_CACHE.cmake new file mode 100644 index 00000000000..a94b8284c7e --- /dev/null +++ b/Tests/RunCMake/find_library/NO_CACHE.cmake @@ -0,0 +1,133 @@ +list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib) +list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a) + +find_library(LIB_exists + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (DEFINED CACHE{LIB_exists}) + message(SEND_ERROR "Cache variable defined: LIB_exists") +endif() +message(STATUS "LIB_exists='${LIB_exists}'") + + +find_library(LIB_doNotExists + NAMES doNotExists + NO_CACHE + ) +if (DEFINED CACHE{LIB_doNotExists}) + message(SEND_ERROR "Cache variable defined: LIB_doNotExists") +endif() +message(STATUS "LIB_doNotExists='${LIB_doNotExists}'") + + +cmake_policy(SET CMP0125 OLD) +message(STATUS "") +message(STATUS "Policy CMP0125 = OLD") +file(REMOVE "${CMAKE_BINARY_DIR}/libPrefixInPATH.a") + +set(LIB_cache "unknown" CACHE FILEPATH "") +find_library(LIB_cache + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{LIB_cache}) + message(SEND_ERROR "Cache variable not defined: LIB_cache") +endif() +message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'") +unset(LIB_cache CACHE) +message(STATUS "LIB_cache='${LIB_cache}'") + + +set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "") +unset(LIB_cache) +find_library(LIB_cache + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{LIB_cache}) + message(SEND_ERROR "Cache variable not defined: LIB_cache") +endif() +message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'") +unset(LIB_cache CACHE) +message(STATUS "LIB_cache='${LIB_cache}'") + + +set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "") +unset(LIB_cache) +# simulate cache variable defined in command line +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libPrefixInPATH.a" DESTINATION "${CMAKE_BINARY_DIR}") +set_property(CACHE LIB_cache PROPERTY TYPE UNINITIALIZED) +find_library(LIB_cache + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{LIB_cache}) + message(SEND_ERROR "Cache variable not defined: LIB_cache") +endif() +message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'") +unset(LIB_cache CACHE) +message(STATUS "LIB_cache='${LIB_cache}'") + + +cmake_policy(SET CMP0125 NEW) +message(STATUS "") +message(STATUS "Policy CMP0125 = NEW") +file(REMOVE "${CMAKE_BINARY_DIR}/libPrefixInPATH.a") + +set(LIB_cache "unknown" CACHE FILEPATH "") +find_library(LIB_cache + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{LIB_cache}) + message(SEND_ERROR "Cache variable not defined: LIB_cache") +endif() +message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'") +unset(LIB_cache CACHE) +message(STATUS "LIB_cache='${LIB_cache}'") + + +set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "") +unset(LIB_cache) +find_library(LIB_cache + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{LIB_cache}) + message(SEND_ERROR "Cache variable not defined: LIB_cache") +endif() +message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'") +unset(LIB_cache CACHE) +message(STATUS "LIB_cache='${LIB_cache}'") + + +set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "") +unset(LIB_cache) +# simulate cache variable defined in command line +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libPrefixInPATH.a" DESTINATION "${CMAKE_BINARY_DIR}") +set_property(CACHE LIB_cache PROPERTY TYPE UNINITIALIZED) +find_library(LIB_cache + NAMES PrefixInPATH + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{LIB_cache}) + message(SEND_ERROR "Cache variable not defined: LIB_cache") +endif() +message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'") +unset(LIB_cache CACHE) +message(STATUS "LIB_cache='${LIB_cache}'") diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index c7d69e401fa..e2971733b24 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -9,3 +9,4 @@ if(UNIX AND NOT CYGWIN) endif() run_cmake(PrefixInPATH) run_cmake(Required) +run_cmake(NO_CACHE) diff --git a/Tests/RunCMake/find_path/NO_CACHE-stdout.txt b/Tests/RunCMake/find_path/NO_CACHE-stdout.txt new file mode 100644 index 00000000000..a41454ef33c --- /dev/null +++ b/Tests/RunCMake/find_path/NO_CACHE-stdout.txt @@ -0,0 +1,18 @@ +-- PATH_exists='.+/Tests/RunCMake/find_path/include/' +-- PATH_exists='PATH_doNotExists-NOTFOUND' +--[ ]+ +-- Policy CMP0125 = OLD +-- CACHED PATH_cache='unknown' +-- PATH_cache='unknown' +-- CACHED PATH_cache='include' +-- PATH_cache='include' +-- CACHED PATH_cache='include' +-- PATH_cache='include' +--[ ]+ +-- Policy CMP0125 = NEW +-- CACHED PATH_cache='unknown' +-- PATH_cache='unknown' +-- CACHED PATH_cache='include' +-- PATH_cache='include' +-- CACHED PATH_cache='include' +-- PATH_cache='.+/Tests/RunCMake/find_path/NO_CACHE-build/include' diff --git a/Tests/RunCMake/find_path/NO_CACHE.cmake b/Tests/RunCMake/find_path/NO_CACHE.cmake new file mode 100644 index 00000000000..4779ac8a7cd --- /dev/null +++ b/Tests/RunCMake/find_path/NO_CACHE.cmake @@ -0,0 +1,131 @@ +find_path(PATH_exists + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (DEFINED CACHE{PATH_exists}) + message(SEND_ERROR "Cache variable defined: PATH_exists") +endif() +message(STATUS "PATH_exists='${PATH_exists}'") + + +find_path(PATH_doNotExists + NAMES doNotExists.h + NO_CACHE + ) +if (DEFINED CACHE{PATH_doNotExists}) + message(SEND_ERROR "Cache variable defined: PATH_doNotExists") +endif() +message(STATUS "PATH_exists='${PATH_doNotExists}'") + + +cmake_policy(SET CMP0125 OLD) +message(STATUS "") +message(STATUS "Policy CMP0125 = OLD") +file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h") + +set(PATH_cache "unknown" CACHE PATH "") +find_path(PATH_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PATH_cache}) + message(SEND_ERROR "Cache variable defined: PATH_cache") +endif() +message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'") +unset(PATH_cache CACHE) +message(STATUS "PATH_cache='${PATH_cache}'") + + +set(PATH_cache "include" CACHE PATH "") +unset(PATH_cache) +find_path(PATH_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PATH_cache}) + message(SEND_ERROR "Cache variable defined: PATH_cache") +endif() +message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'") +unset(PATH_cache CACHE) +message(STATUS "PATH_cache='${PATH_cache}'") + + +set(PATH_cache "include" CACHE PATH "") +unset(PATH_cache) +# simulate cache variable defined in command line +file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include") +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}/include") +set_property(CACHE PATH_cache PROPERTY TYPE UNINITIALIZED) +find_path(PATH_cache + NAMES PrefixInPATH.h + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PATH_cache}) + message(SEND_ERROR "Cache variable not defined: PATH_cache") +endif() +message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'") +unset(PATH_cache CACHE) +message(STATUS "PATH_cache='${PATH_cache}'") + + +cmake_policy(SET CMP0125 NEW) +message(STATUS "") +message(STATUS "Policy CMP0125 = NEW") +file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/include") + +set(PATH_cache "unknown" CACHE PATH "") +unset(PATH_cache) +find_path(PATH_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PATH_cache}) + message(SEND_ERROR "Cache variable defined: PATH_cache") +endif() +message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'") +unset(PATH_cache CACHE) +message(STATUS "PATH_cache='${PATH_cache}'") + + +set(PATH_cache "include" CACHE PATH "") +unset(PATH_cache) +find_path(PATH_cache + NAMES PrefixInPATH.h + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PATH_cache}) + message(SEND_ERROR "Cache variable defined: PATH_cache") +endif() +message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'") +unset(PATH_cache CACHE) +message(STATUS "PATH_cache='${PATH_cache}'") + + +set(PATH_cache "include" CACHE PATH "") +unset(PATH_cache) +# simulate cache variable defined in command line +file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include") +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}/include") +set_property(CACHE PATH_cache PROPERTY TYPE UNINITIALIZED) +find_path(PATH_cache + NAMES PrefixInPATH.h + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PATH_cache}) + message(SEND_ERROR "Cache variable not defined: PATH_cache") +endif() +message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'") +unset(PATH_cache CACHE) +message(STATUS "PATH_cache='${PATH_cache}'") diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake index 5c919bb6630..90ee768cb1d 100644 --- a/Tests/RunCMake/find_path/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake @@ -4,6 +4,7 @@ run_cmake(EmptyOldStyle) run_cmake(FromPATHEnv) run_cmake(PrefixInPATH) run_cmake(Required) +run_cmake(NO_CACHE) if(APPLE) run_cmake(FrameworksWithSubdirs) diff --git a/Tests/RunCMake/find_program/NO_CACHE-stdout.txt b/Tests/RunCMake/find_program/NO_CACHE-stdout.txt new file mode 100644 index 00000000000..c235d814357 --- /dev/null +++ b/Tests/RunCMake/find_program/NO_CACHE-stdout.txt @@ -0,0 +1,18 @@ +-- PROG_A='.+/Tests/RunCMake/find_program/A/testA' +-- PROG_AandB='PROG_AandB-NOTFOUND' +--[ ]+ +-- Policy CMP0125 = OLD +-- CACHED PROG_cache='unknown' +-- PROG_cache='unknown' +-- CACHED PROG_cache='testA' +-- PROG_cache='testA' +-- CACHED PROG_cache='testA' +-- PROG_cache='testA' +--[ ]+ +-- Policy CMP0125 = NEW +-- CACHED PROG_cache='unknown' +-- PROG_cache='unknown' +-- CACHED PROG_cache='testA' +-- PROG_cache='testA' +-- CACHED PROG_cache='testA' +-- PROG_cache='.+/Tests/RunCMake/find_program/NO_CACHE-build/testA' diff --git a/Tests/RunCMake/find_program/NO_CACHE.cmake b/Tests/RunCMake/find_program/NO_CACHE.cmake new file mode 100644 index 00000000000..77a058260e9 --- /dev/null +++ b/Tests/RunCMake/find_program/NO_CACHE.cmake @@ -0,0 +1,130 @@ +find_program(PROG_A + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (DEFINED CACHE{PROG_A}) + message(SEND_ERROR "Cache variable defined: PROG_A") +endif() +message(STATUS "PROG_A='${PROG_A}'") + + +find_program(PROG_AandB + NAMES testAandB + NO_CACHE + ) +if (DEFINED CACHE{PROG_AandB}) + message(SEND_ERROR "Cache variable defined: PROG_AandN") +endif() +message(STATUS "PROG_AandB='${PROG_AandB}'") + + +cmake_policy(SET CMP0125 OLD) +message(STATUS "") +message(STATUS "Policy CMP0125 = OLD") +file(REMOVE "${CMAKE_BINARY_DIR}/testA") + +set(PROG_cache "unknown" CACHE FILEPATH "") +find_program(PROG_cache + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PROG_cache}) + message(SEND_ERROR "Cache variable not defined: PROG_cache") +endif() +message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'") +unset(PROG_cache CACHE) +message(STATUS "PROG_cache='${PROG_cache}'") + + +set(PROG_cache "testA" CACHE FILEPATH "") +unset(PROG_cache) +find_program(PROG_cache + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PROG_cache}) + message(SEND_ERROR "Cache variable not defined: PROG_cache") +endif() +message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'") +unset(PROG_cache CACHE) +message(STATUS "PROG_cache='${PROG_cache}'") + + +set(PROG_cache "testA" CACHE FILEPATH "") +unset(PROG_cache) +# simulate cache variable defined in command line +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/A/testA" DESTINATION "${CMAKE_BINARY_DIR}") +set_property(CACHE PROG_cache PROPERTY TYPE UNINITIALIZED) +find_program(PROG_cache + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PROG_cache}) + message(SEND_ERROR "Cache variable not defined: PROG_cache") +endif() +message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'") +unset(PROG_cache CACHE) +message(STATUS "PROG_cache='${PROG_cache}'") + + +cmake_policy(SET CMP0125 NEW) +message(STATUS "") +message(STATUS "Policy CMP0125 = NEW") +file(REMOVE "${CMAKE_BINARY_DIR}/testA") + +set(PROG_cache "unknown" CACHE FILEPATH "") +find_program(PROG_cache + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PROG_cache}) + message(SEND_ERROR "Cache variable not defined: PROG_cache") +endif() +message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'") +unset(PROG_cache CACHE) +message(STATUS "PROG_cache='${PROG_cache}'") + + +set(PROG_cache "testA" CACHE FILEPATH "") +unset(PROG_cache) +find_program(PROG_cache + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PROG_cache}) + message(SEND_ERROR "Cache variable not defined: PROG_cache") +endif() +message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'") +unset(PROG_cache CACHE) +message(STATUS "PROG_cache='${PROG_cache}'") + + +set(PROG_cache "testA" CACHE FILEPATH "") +unset(PROG_cache) +# simulate cache variable defined in command line +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/A/testA" DESTINATION "${CMAKE_BINARY_DIR}") +set_property(CACHE PROG_cache PROPERTY TYPE UNINITIALIZED) +find_program(PROG_cache + NAMES testA + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A + NO_CACHE + NO_DEFAULT_PATH + ) +if (NOT DEFINED CACHE{PROG_cache}) + message(SEND_ERROR "Cache variable not defined: PROG_cache") +endif() +message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'") +unset(PROG_cache CACHE) +message(STATUS "PROG_cache='${PROG_cache}'") diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake index 77c021d185e..34edc19d59c 100644 --- a/Tests/RunCMake/find_program/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake @@ -5,6 +5,7 @@ run_cmake(DirsPerName) run_cmake(NamesPerDir) run_cmake(RelAndAbsPath) run_cmake(Required) +run_cmake(NO_CACHE) if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$") run_cmake(WindowsCom) From 9d7ebb47ea30a75617778686ba187fa6d5e91f45 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 22 May 2021 19:24:04 -0400 Subject: [PATCH 0567/1519] ci: use consistent sccache builds --- .gitlab/ci/sccache.sh | 51 +++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/.gitlab/ci/sccache.sh b/.gitlab/ci/sccache.sh index 12b8f9d0d39..b6b3751eecd 100755 --- a/.gitlab/ci/sccache.sh +++ b/.gitlab/ci/sccache.sh @@ -2,57 +2,42 @@ set -e -readonly kernel="$(uname -s)-$(uname -m)" -case $kernel in - Linux-x86_64) - version="v0.2.15" - shatool="sha256sum" - sha256sum="e5d03a9aa3b9fac7e490391bbe22d4f42c840d31ef9eaf127a03101930cbb7ca" - platform="x86_64-unknown-linux-musl" - ;; +readonly version="0.2.15-background-init" +readonly build_date="20210602.0" + +case "$( uname -s )-$(uname -m)" in Linux-aarch64) - version="v0.2.15" shatool="sha256sum" - sha256sum="90d91d21a767e3f558196dbd52395f6475c08de5c4951a4c8049575fa6894489" + sha256sum="28b9ad3f591874551a3f4c5c1ff32456d3328c15d7bd8bc63b4e5948a94f1def" platform="aarch64-unknown-linux-musl" ;; - Darwin-x86_64) - version="gfe63078" - shatool="shasum -a 256" - sha256sum="60a0302b1d7227f7ef56abd82266353f570d27c6e850c56c6448bf62def38888" - platform="x86_64-apple-darwin" - url="https://paraview.org/files/dependencies" + Linux-x86_64) + shatool="sha256sum" + sha256sum="34d62d30eae1a4145f00d62b01ad21c3456e28f11f8246c936b00cccf4855016" + platform="x86_64-unknown-linux-musl" ;; - Darwin-arm64) - version="0.2.15-1-disk_cache_init" + Darwin-x86_64|Darwin-arm64) shatool="shasum -a 256" - sha256sum="f7c9ff78e701810b8b1dbc2a163c7fda1177fc3f69c71f46e7a38242657a99fd" - platform="aarch64-apple-darwin" - url="https://cmake.org/files/dependencies/sccache" + sha256sum="2fa396e98cc8d07e39429b187a77386db63d35409902251d462080bdd0087c22" + platform="universal-apple-darwin" ;; *) - echo "Unrecognized platform $kernel" + echo "Unrecognized platform $( uname -s )-$( uname -m )" exit 1 ;; esac -readonly version readonly shatool readonly sha256sum readonly platform -readonly filename="sccache-$version-$platform" -readonly tarball="$filename.tar.gz" +readonly filename="sccache-v$version-$platform" -if [ -z "$url" ]; then - url="https://github.com/mozilla/sccache/releases/download/$version" -fi -readonly url +readonly url="https://gitlab.kitware.com/api/v4/projects/6955/packages/generic/sccache/v$version-$build_date/" cd .gitlab -echo "$sha256sum $tarball" > sccache.sha256sum -curl -OL "$url/$tarball" +echo "$sha256sum $filename" > sccache.sha256sum +curl -OL "$url/$filename" $shatool --check sccache.sha256sum -tar xf "$tarball" -mv "$filename/sccache" . +mv "$filename" sccache chmod +x sccache From 2ff2085fb8b3ed4b4fb977a90b904be6faf3a7c2 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 3 Jun 2021 00:01:11 -0400 Subject: [PATCH 0568/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 683e90d3a07..7be1b9ef718 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210602) +set(CMake_VERSION_PATCH 20210603) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9d0f8c3e560f13a9d7a9a2e99e40ef7e5db6eb47 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 06:41:29 -0400 Subject: [PATCH 0569/1519] Tests: Teach RunCMake.ParseImplicitLinkInfo to match output by regex As in commit 6bc6fc2a7f (Tests: Teach RunCMake.ParseImplicitIncludeInfo to match output by regex, 2019-04-08, v3.14.2~5^2~1). --- .../ParseImplicitLinkInfo.cmake | 12 ++++++------ .../results/aix-CXX-XLClang-16.1.0.1.output | 2 +- .../results/craype-C-Cray-8.7.output | 2 +- .../results/craype-C-Cray-9.0-hlist-ad.output | 2 +- .../results/craype-C-Intel-18.0.2.20180210.output | 2 +- .../results/craype-CXX-Cray-8.7.output | 2 +- .../results/craype-CXX-Cray-9.0-hlist-ad.output | 2 +- .../results/craype-CXX-GNU-7.3.0.output | 2 +- .../results/craype-CXX-Intel-18.0.2.20180210.output | 2 +- .../results/craype-Fortran-Cray-8.7.output | 2 +- .../results/craype-Fortran-Cray-9.0-hlist-ad.output | 2 +- .../darwin-CXX-AppleClang-8.0.0.8000042.output | 2 +- ...rwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output | 2 +- .../results/freebsd-CXX-Clang-3.3.0.output | 2 +- .../results/linux-C-Intel-18.0.0.20170811.output | 2 +- .../results/linux-CUDA-NVIDIA-10.1.168-CLANG.output | 2 +- .../linux-CUDA-NVIDIA-10.1.168-XLClang-v.output | 2 +- .../results/linux-CUDA-NVIDIA-9.2.148-GCC.output | 2 +- .../results/linux-CXX-GNU-7.3.0.output | 2 +- .../results/linux-CXX-Intel-18.0.0.20170811.output | 2 +- .../results/linux-CXX-NVHPC-21.1.0.output | 2 +- .../results/linux-CXX-PGI-18.10.1.output | 2 +- .../results/linux-CXX-XL-12.1.0.output | 2 +- .../results/linux-CXX-XL-16.1.0.0.output | 2 +- .../results/linux_nostdinc-CXX-PGI-18.10.1.output | 2 +- .../results/linux_nostdinc-CXX-XL-12.1.0.output | 2 +- .../results/mingw.org-CXX-GNU-4.9.3.output | 2 +- .../results/netbsd-CXX-GNU-4.8.5.output | 2 +- .../results/netbsd_nostdinc-CXX-GNU-4.8.5.output | 2 +- .../results/openbsd-CXX-Clang-5.0.1.output | 2 +- 30 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake index 1f3468b0e94..3c7f569bbfd 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake +++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake @@ -162,12 +162,12 @@ foreach(t ${targets}) if("${state}" STREQUAL "done") message("empty parse failed: ${idirs}, log=${log}") endif() - elseif(NOT "${idirs}" STREQUAL "${idirs_output}") - message("${t} parse failed: state=${state}, '${idirs}' does not match '${idirs_output}'") - elseif(NOT "${implicit_libs}" STREQUAL "${implicit_lib_output}") - message("${t} parse failed: state=${state}, '${implicit_libs}' does not match '${implicit_lib_output}'") - elseif((library_arch OR library_arch_output) AND NOT "${library_arch}" STREQUAL "${library_arch_output}") - message("${t} parse failed: state=${state}, '${library_arch}' does not match '${library_arch_output}'") + elseif(NOT "${idirs}" MATCHES "^${idirs_output}$") + message("${t} parse failed: state=${state}, '${idirs}' does not match '^${idirs_output}$'") + elseif(NOT "${implicit_libs}" MATCHES "^${implicit_lib_output}$") + message("${t} parse failed: state=${state}, '${implicit_libs}' does not match '^${implicit_lib_output}$'") + elseif((library_arch OR library_arch_output) AND NOT "${library_arch}" MATCHES "^${library_arch_output}$") + message("${t} parse failed: state=${state}, '${library_arch}' does not match '^${library_arch_output}$'") endif() unload_compiler_info("${cmvars}") diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output index 2dc5832b32b..3a57464f0d3 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/aix-CXX-XLClang-16.1.0.1.output @@ -1,2 +1,2 @@ -libs=xlopt;xlipa;xl;c++;Ccore;pthreads;m;c +libs=xlopt;xlipa;xl;c\+\+;Ccore;pthreads;m;c dirs=/opt/IBM/xlmass/9.1.0/lib/aix61;/opt/IBM/xlc/16.1.0/lib;/opt/IBM/xlC/16.1.0/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output index 674975cbd00..0373d89a6e7 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-8.7.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c++-rts;stdc++;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c++-rts;stdc++;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c++-rts;stdc++;m;csup;rt;atomic;stdc++;pthread;c;csup;m;gcc +libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c\+\+-rts;stdc\+\+;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c\+\+-rts;stdc\+\+;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c\+\+-rts;stdc\+\+;m;csup;rt;atomic;stdc\+\+;pthread;c;csup;m;gcc dirs=/opt/gcc/6.1.0/snos/lib64;/opt/cray/pe/libsci/18.07.1/CRAY/8.6/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-cray/8.6/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/alps/6.5.28-6.0.5.0_18.6__g13a91b6.ari/lib64;/opt/cray/xpmem/2.2.4-6.0.5.1_8.26__g35d5e73.ari/lib64;/opt/cray/dmapp/7.1.1-6.0.5.0_49.8__g1125556.ari/lib64;/opt/cray/pe/pmi/5.0.14/lib64;/opt/cray/ugni/6.0.14-6.0.5.0_16.9__g19583bb.ari/lib64;/opt/cray/udreg/2.3.2-6.0.5.0_13.12__ga14955a.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/8.7.4/cce/x86_64/lib;/opt/cray/wlm_detect/1.3.2-6.0.5.0_3.1__g388ccd5.ari/lib64;/usr/lib64;/lib64;/opt/gcc/6.1.0/snos/lib/gcc/x86_64-suse-linux/6.1.0;/opt/cray/pe/cce/8.7.4/binutils/x86_64/x86_64-unknown-linux-gnu/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output index 1bf2f6d0581..0f52e8b3418 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Cray-9.0-hlist-ad.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;tcmalloc_minimal;cray-c++-rts;stdc++;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc +libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;tcmalloc_minimal;cray-c\+\+-rts;stdc\+\+;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc dirs=/opt/gcc/8.1.0/snos/lib64;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.8/gni/mpich-cray/9.0/lib;/opt/cray/pe/libsci/19.06.1/CRAY/9.0/x86_64/lib;/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/9.0.0/cce/x86_64/lib;/usr/lib64;/lib64;/opt/cray/pe/cce/9.0.0/cce-clang/x86_64/lib/clang/9.0.0/lib/linux;/opt/gcc/8.1.0/snos/lib/gcc/x86_64-suse-linux/8.1.0;/opt/cray/pe/cce/9.0.0/binutils/x86_64/x86_64-unknown-linux-gnu/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output index e9e67396f03..5b8ae8df064 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-C-Intel-18.0.2.20180210.output @@ -1,2 +1,2 @@ -libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c +libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c dirs=/opt/intel/2018.2.199/compilers_and_libraries_2018/linux/mkl/lib/intel64;/opt/intel/2018.2.199/compilers_and_libraries_2018.2.199/linux/compiler/lib/intel64_lin;/opt/gcc/6.3.0/snos/lib/gcc/x86_64-suse-linux/6.3.0;/opt/gcc/6.3.0/snos/lib64;/lib64;/usr/lib64;/opt/gcc/6.3.0/snos/lib;/lib;/usr/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output index 7daa29d40cf..00281d5c25b 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-8.7.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpichcxx_cray;rt;pthread;ugni;pmi;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c++-rts;stdc++;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c++-rts;stdc++;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c++-rts;stdc++;m;csup;rt;atomic;cray-c++-rts;stdc++;supc++;stdc++;pthread;c;csup;m;gcc +libs=AtpSigHandler;AtpSigHCommData;pthread;sci_cray_mpi_mp;m;f;sci_cray_mp;craymp;m;pthread;f;hugetlbfs;mpichcxx_cray;rt;pthread;ugni;pmi;mpich_cray;rt;pthread;ugni;pmi;pgas-dmapp;fi;u;rt;dmapp;ugni;udreg;pthread;m;cray-c\+\+-rts;stdc\+\+;xpmem;dmapp;pthread;pmi;pthread;alpslli;pthread;wlm_detect;ugni;pthread;alpsutil;pthread;rca;udreg;quadmath;m;omp;rt;craymp;pthread;rt;dl;cray-c\+\+-rts;stdc\+\+;m;modules;m;rt;fi;m;quadmath;rt;craymath;m;gfortran;quadmath;rt;f;m;pthread;rt;u;rt;dl;cray-c\+\+-rts;stdc\+\+;m;csup;rt;atomic;cray-c\+\+-rts;stdc\+\+;supc\+\+;stdc\+\+;pthread;c;csup;m;gcc dirs=/opt/gcc/6.1.0/snos/lib64;/opt/cray/pe/libsci/18.07.1/CRAY/8.6/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-cray/8.6/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/alps/6.5.28-6.0.5.0_18.6__g13a91b6.ari/lib64;/opt/cray/xpmem/2.2.4-6.0.5.1_8.26__g35d5e73.ari/lib64;/opt/cray/dmapp/7.1.1-6.0.5.0_49.8__g1125556.ari/lib64;/opt/cray/pe/pmi/5.0.14/lib64;/opt/cray/ugni/6.0.14-6.0.5.0_16.9__g19583bb.ari/lib64;/opt/cray/udreg/2.3.2-6.0.5.0_13.12__ga14955a.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/8.7.4/cce/x86_64/lib;/opt/cray/wlm_detect/1.3.2-6.0.5.0_3.1__g388ccd5.ari/lib64;/usr/lib64;/lib64;/opt/gcc/6.1.0/snos/lib/gcc/x86_64-suse-linux/6.1.0;/opt/cray/pe/cce/8.7.4/binutils/x86_64/x86_64-unknown-linux-gnu/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output index 958a6b1cf41..a7287d37a6e 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Cray-9.0-hlist-ad.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichcxx_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;cray-c++-rts;cray-c++-rts;stdc++;supc++;tcmalloc_minimal;cray-c++-rts;stdc++;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc +libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichcxx_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;atomic;cray-c\+\+-rts;cray-c\+\+-rts;stdc\+\+;supc\+\+;tcmalloc_minimal;cray-c\+\+-rts;stdc\+\+;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc dirs=/opt/gcc/8.1.0/snos/lib64;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.8/gni/mpich-cray/9.0/lib;/opt/cray/pe/libsci/19.06.1/CRAY/9.0/x86_64/lib;/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/9.0.0/cce/x86_64/lib;/usr/lib64;/lib64;/opt/cray/pe/cce/9.0.0/cce-clang/x86_64/lib/clang/9.0.0/lib/linux;/opt/gcc/8.1.0/snos/lib/gcc/x86_64-suse-linux/8.1.0;/opt/cray/pe/cce/9.0.0/binutils/x86_64/x86_64-unknown-linux-gnu/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output index 40d0047c75b..ead480425ed 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-GNU-7.3.0.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;pthread;sci_gnu_71_mpi;sci_gnu_71;pthread;hugetlbfs;mpichcxx_gnu_71;rt;ugni;pthread;pmi;mpich_gnu_71;rt;ugni;pthread;pmi;pthread;alpslli;pthread;wlm_detect;alpsutil;pthread;rca;ugni;pthread;xpmem;udreg;gfortran;quadmath;mvec;m;pthread;stdc++;m;gcc;c +libs=AtpSigHandler;AtpSigHCommData;pthread;sci_gnu_71_mpi;sci_gnu_71;pthread;hugetlbfs;mpichcxx_gnu_71;rt;ugni;pthread;pmi;mpich_gnu_71;rt;ugni;pthread;pmi;pthread;alpslli;pthread;wlm_detect;alpsutil;pthread;rca;ugni;pthread;xpmem;udreg;gfortran;quadmath;mvec;m;pthread;stdc\+\+;m;gcc;c dirs=/opt/cray/pe/libsci/18.07.1/GNU/7.1/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-gnu/7.1/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/alps/6.5.28-6.0.5.0_18.6__g13a91b6.ari/lib64;/opt/cray/xpmem/2.2.4-6.0.5.1_8.26__g35d5e73.ari/lib64;/opt/cray/pe/pmi/5.0.14/lib64;/opt/cray/ugni/6.0.14-6.0.5.0_16.9__g19583bb.ari/lib64;/opt/cray/udreg/2.3.2-6.0.5.0_13.12__ga14955a.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/wlm_detect/1.3.2-6.0.5.0_3.1__g388ccd5.ari/lib64;/opt/gcc/7.3.0/snos/lib/gcc/x86_64-suse-linux/7.3.0;/opt/gcc/7.3.0/snos/lib64;/lib64;/usr/lib64;/opt/gcc/7.3.0/snos/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output index 621284418ce..1a3b736b091 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-CXX-Intel-18.0.2.20180210.output @@ -1,2 +1,2 @@ -libs=imf;svml;irng;stdc++;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c +libs=imf;svml;irng;stdc\+\+;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c dirs=/opt/intel/2018.2.199/compilers_and_libraries_2018/linux/mkl/lib/intel64;/opt/intel/2018.2.199/compilers_and_libraries_2018.2.199/linux/compiler/lib/intel64_lin;/opt/gcc/6.3.0/snos/lib/gcc/x86_64-suse-linux/6.3.0;/opt/gcc/6.3.0/snos/lib64;/lib64;/usr/lib64;/opt/gcc/6.3.0/snos/lib;/lib;/usr/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output index 9828bf3cf43..3b26f407fb4 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-8.7.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;rca;sci_cray_mpi_mp;sci_cray_mp;mpich_cray;mpichf90_cray;pgas-dmapp;quadmath;omp;craymp;modules;fi;craymath;f;u;csup;atomic;gfortran;tcmalloc_minimal;stdc++;pthread;c;csup;m;gcc +libs=AtpSigHandler;AtpSigHCommData;rca;sci_cray_mpi_mp;sci_cray_mp;mpich_cray;mpichf90_cray;pgas-dmapp;quadmath;omp;craymp;modules;fi;craymath;f;u;csup;atomic;gfortran;tcmalloc_minimal;stdc\+\+;pthread;c;csup;m;gcc dirs=/opt/gcc/6.1.0/snos/lib64;/opt/cray/pe/libsci/18.07.1/CRAY/8.6/x86_64/lib;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.3/gni/mpich-cray/8.6/lib;/opt/cray/rca/2.2.16-6.0.5.0_15.34__g5e09e6d.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/8.7.4/cce/x86_64/lib;/usr/lib64;/lib64;/opt/gcc/6.1.0/snos/lib/gcc/x86_64-suse-linux/6.1.0;/opt/cray/pe/cce/8.7.4/binutils/x86_64/x86_64-unknown-linux-gnu/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output index 46754080fcc..d15e5a7f015 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/craype-Fortran-Cray-9.0-hlist-ad.output @@ -1,2 +1,2 @@ -libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichf90_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;gfortran;tcmalloc_minimal;cray-c++-rts;stdc++;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc +libs=AtpSigHandler;AtpSigHCommData;rca;mpich_cray_90;mpichf90_cray_90;sci_cray_mpi;sci_cray;pgas-dmapp;quadmath;modules;fi;craymath;f;u;csup;gfortran;tcmalloc_minimal;cray-c\+\+-rts;stdc\+\+;pthread;c;csup;m;clang_rt.craypgo-x86_64;gcc dirs=/opt/gcc/8.1.0/snos/lib64;/opt/cray/dmapp/default/lib64;/opt/cray/pe/mpt/7.7.8/gni/mpich-cray/9.0/lib;/opt/cray/pe/libsci/19.06.1/CRAY/9.0/x86_64/lib;/opt/cray/rca/2.2.18-6.0.7.0_33.3__g2aa4f39.ari/lib64;/opt/cray/pe/atp/2.1.3/libApp;/opt/cray/pe/cce/9.0.0/cce/x86_64/lib;/usr/lib64;/lib64;/opt/cray/pe/cce/9.0.0/cce-clang/x86_64/lib/clang/9.0.0/lib/linux;/opt/gcc/8.1.0/snos/lib/gcc/x86_64-suse-linux/8.1.0;/opt/cray/pe/cce/9.0.0/binutils/x86_64/x86_64-unknown-linux-gnu/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output index f75637c57a9..47a362a5365 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin-CXX-AppleClang-8.0.0.8000042.output @@ -1,2 +1,2 @@ -libs=c++ +libs=c\+\+ dirs=/usr/lib;/usr/local/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output index f75637c57a9..47a362a5365 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/darwin_nostdinc-CXX-AppleClang-8.0.0.8000042.output @@ -1,2 +1,2 @@ -libs=c++ +libs=c\+\+ dirs=/usr/lib;/usr/local/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output index b0b8e25b5a5..18d7cd1730a 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/freebsd-CXX-Clang-3.3.0.output @@ -1,2 +1,2 @@ -libs=c++;m;gcc;gcc_s;c;gcc;gcc_s +libs=c\+\+;m;gcc;gcc_s;c;gcc;gcc_s dirs=/usr/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output index e6132900335..d78c9f48a8e 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output @@ -1,3 +1,3 @@ -libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c +libs=imf;svml;irng;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c dirs=/opt/intel/compilers_and_libraries_2018.0.128/linux/ipp/lib/intel64;/opt/intel/compilers_and_libraries_2018.0.128/linux/compiler/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/mkl/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/tbb/lib/intel64/gcc4.7;/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib;/lib library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output index 813457aef69..be6b906d089 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output @@ -1,3 +1,3 @@ -libs=cudadevrt;cudart_static;rt;pthread;dl;stdc++;m;gcc_s;gcc;c;gcc_s;gcc +libs=cudadevrt;cudart_static;rt;pthread;dl;stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc dirs=/usr/local/cuda/targets/x86_64-linux/lib/stubs;/usr/local/cuda/targets/x86_64-linux/lib;/usr/lib/gcc/x86_64-linux-gnu/8;/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu;/lib64;/usr/lib;/usr/lib/llvm-8/lib;/lib library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output index 261785c96c6..d3f362754cc 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output @@ -1,3 +1,3 @@ -libs=cudadevrt;cudart_static;rt;pthread;dl;xlopt;xl;ibmc++;stdc++;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc +libs=cudadevrt;cudart_static;rt;pthread;dl;xlopt;xl;ibmc\+\+;stdc\+\+;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc dirs=/sw/summit/cuda/10.1.168/targets/ppc64le-linux/lib/stubs;/sw/summit/cuda/10.1.168/targets/ppc64le-linux/lib;/autofs/nccs-svm1_sw/summit/.swci/1-compute/opt/spack/20180914/linux-rhel7-ppc64le/xl-16.1.1-3/spectrum-mpi-10.3.0.1-20190611-aqjt3jo53mogrrhcrd2iufr435azcaha/lib;/autofs/nccs-svm1_sw/summit/.swci/1-compute/opt/spack/20180914/linux-rhel7-ppc64le/gcc-4.8.5/darshan-runtime-3.1.7-csygoqyym3m3ysoaperhxlhoiluvpa2u/lib;/autofs/nccs-svm1_sw/summit/xl/16.1.1-3/xlsmp/5.1.1/lib;/autofs/nccs-svm1_sw/summit/xl/16.1.1-3/xlmass/9.1.1/lib;/autofs/nccs-svm1_sw/summit/xl/16.1.1-3/xlC/16.1.1/lib;/usr/lib/gcc/ppc64le-redhat-linux/4.8.5;/usr/lib64;/lib64;/autofs/nccs-svm1_sw/peak/.swci/1-compute/opt/spack/20180914/linux-rhel7-ppc64le/gcc-4.8.5/darshan-runtime-3.1.7-ytwv7xbkub6mqnpvygdthwqa7mhjqbc5/lib;/usr/lib library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output index 275fe40c9b9..958f41daae9 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output @@ -1,3 +1,3 @@ -libs=cudadevrt;cudart_static;rt;pthread;dl;stdc++;m;gcc_s;gcc;c;gcc_s;gcc +libs=cudadevrt;cudart_static;rt;pthread;dl;stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc dirs=/usr/lib/x86_64-linux-gnu/stubs;/usr/lib/gcc/x86_64-linux-gnu/5;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output index 4957f5cd3f6..f87ecff7852 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output @@ -1,3 +1,3 @@ -libs=stdc++;m;gcc_s;gcc;c;gcc_s;gcc +libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc dirs=/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output index 678a196f5a6..832f2186717 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output @@ -1,3 +1,3 @@ -libs=imf;svml;irng;stdc++;m;ipgo;decimal;cilkrts;stdc++;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c +libs=imf;svml;irng;stdc\+\+;m;ipgo;decimal;cilkrts;stdc\+\+;gcc;gcc_s;irc;svml;c;gcc;gcc_s;irc_s;dl;c dirs=/opt/intel/compilers_and_libraries_2018.0.128/linux/ipp/lib/intel64;/opt/intel/compilers_and_libraries_2018.0.128/linux/compiler/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/mkl/lib/intel64_lin;/opt/intel/compilers_and_libraries_2018.0.128/linux/tbb/lib/intel64/gcc4.7;/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib;/lib library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output index e7f7d053604..5e93f6d337e 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-NVHPC-21.1.0.output @@ -1,3 +1,3 @@ -libs=atomic;nvhpcatm;stdc++;nvomp;dl;nvhpcatm;atomic;pthread;nvcpumath;nsnvc;nvc;m;gcc;c;gcc;gcc_s +libs=atomic;nvhpcatm;stdc\+\+;nvomp;dl;nvhpcatm;atomic;pthread;nvcpumath;nsnvc;nvc;m;gcc;c;gcc;gcc_s dirs=/opt/nvidia/hpc_sdk/Linux_x86_64/21.1/compilers/lib;/usr/lib64;/usr/lib/gcc/x86_64-linux-gnu/9 library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output index cd15054cb40..0e959615966 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output @@ -1,3 +1,3 @@ -libs=atomic;pgatm;stdc++;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s +libs=atomic;pgatm;stdc\+\+;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s dirs=/mnt/pgi/linux86-64/18.10/lib;/usr/lib64;/usr/lib/gcc/x86_64-linux-gnu/7 library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output index 45c55657f8f..34cab2ea5dd 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output @@ -1,3 +1,3 @@ -libs=xlopt;xl;ibmc++;xlopt;xl;stdc++;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc +libs=xlopt;xl;ibmc\+\+;xlopt;xl;stdc\+\+;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc dirs=/soft/compilers/ibmcmp-oct2017/xlsmp/bg/3.1/lib64;/soft/compilers/ibmcmp-oct2017/xlmass/bg/7.3/lib64;/soft/compilers/ibmcmp-oct2017/vac/bg/12.1/lib64;/soft/compilers/ibmcmp-oct2017/vacpp/bg/12.1/lib64;/usr/lib/gcc/ppc64-redhat-linux/4.4.7;/usr/lib64;/lib64;/usr/lib library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output index 9d649ecba6a..c754bda36a7 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output @@ -1,3 +1,3 @@ -libs=xlopt;xl;ibmc++;stdc++;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc +libs=xlopt;xl;ibmc\+\+;stdc\+\+;m;dl;gcc_s;gcc;pthread;m;c;gcc_s;gcc dirs=/opt/ibm/xlsmp/5.1.0/lib;/opt/ibm/xlmass/9.1.0/lib;/opt/ibm/xlC/16.1.0/lib;/usr/lib/gcc/ppc64le-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output index a7c14d27270..848e8c0e0eb 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output @@ -1,3 +1,3 @@ -libs=atomic;pgatm;stdc++;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s +libs=atomic;pgatm;stdc\+\+;pgmp;numa;pthread;pgmath;nspgc;pgc;m;gcc;c;gcc;gcc_s dirs=/mnt/pgi/linux86-64/18.10/lib;/usr/lib64;/usr/lib/gcc/x86_64-linux-gnu/7 library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output index 45c55657f8f..34cab2ea5dd 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output @@ -1,3 +1,3 @@ -libs=xlopt;xl;ibmc++;xlopt;xl;stdc++;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc +libs=xlopt;xl;ibmc\+\+;xlopt;xl;stdc\+\+;m;dl;gcc_s;gcc;m;c;gcc_s;gcc;dl;gcc_s;gcc;m;c;gcc_s;gcc dirs=/soft/compilers/ibmcmp-oct2017/xlsmp/bg/3.1/lib64;/soft/compilers/ibmcmp-oct2017/xlmass/bg/7.3/lib64;/soft/compilers/ibmcmp-oct2017/vac/bg/12.1/lib64;/soft/compilers/ibmcmp-oct2017/vacpp/bg/12.1/lib64;/usr/lib/gcc/ppc64-redhat-linux/4.4.7;/usr/lib64;/lib64;/usr/lib library_arch= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output index 5e79cc1adf0..7852bfd2bda 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/mingw.org-CXX-GNU-4.9.3.output @@ -1,2 +1,2 @@ -libs=stdc++;mingw32;gcc_s;gcc;moldname;mingwex;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex +libs=stdc\+\+;mingw32;gcc_s;gcc;moldname;mingwex;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex dirs=C:/DoesNotExist/mingw/lib/gcc/mingw32/4.9.3;C:/DoesNotExist/mingw/lib/gcc;C:/DoesNotExist/mingw/mingw32/lib;C:/DoesNotExist/mingw/lib diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output index d747e5b87ee..c6a098ef9f6 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd-CXX-GNU-4.8.5.output @@ -1,2 +1,2 @@ -libs=stdc++;m;gcc_s;gcc;c;gcc_s;gcc +libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc dirs= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output index d747e5b87ee..c6a098ef9f6 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/netbsd_nostdinc-CXX-GNU-4.8.5.output @@ -1,2 +1,2 @@ -libs=stdc++;m;gcc_s;gcc;c;gcc_s;gcc +libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc dirs= diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output index 4158973ca4f..711225ce62e 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/openbsd-CXX-Clang-5.0.1.output @@ -1,2 +1,2 @@ -libs=c++;c++abi;pthread;m;compiler_rt;c;compiler_rt +libs=c\+\+;c\+\+abi;pthread;m;compiler_rt;c;compiler_rt dirs=/usr/lib From 629eb3926bcc802de53f9982cad2005b4bf8f4ed Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 06:53:49 -0400 Subject: [PATCH 0570/1519] Tests: Extend ParseImplicit*Info with static GNU runtime library flags Generate sample input data with GNU 10.2.1 compilers using flags like `-static-libstdc++` and `-static-libgfortran`. --- .codespellrc | 2 +- .../linux-C-GNU-10.2.1-static-libgcc.input | 74 ++++++++++++++++++ ...inux-CXX-GNU-10.2.1-static-libstdc++.input | 78 +++++++++++++++++++ ...ortran-GNU-10.2.1-static-libgfortran.input | 78 +++++++++++++++++++ .../ParseImplicitIncludeInfo.cmake | 3 + .../linux-C-GNU-10.2.1-static-libgcc.output | 1 + ...nux-CXX-GNU-10.2.1-static-libstdc++.output | 1 + ...rtran-GNU-10.2.1-static-libgfortran.output | 1 + .../ParseImplicitLinkInfo.cmake | 3 + .../linux-C-GNU-10.2.1-static-libgcc.output | 3 + ...nux-CXX-GNU-10.2.1-static-libstdc++.output | 3 + ...rtran-GNU-10.2.1-static-libgfortran.output | 3 + 12 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input create mode 100644 Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input create mode 100644 Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input create mode 100644 Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output create mode 100644 Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output create mode 100644 Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output create mode 100644 Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output create mode 100644 Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output create mode 100644 Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output diff --git a/.codespellrc b/.codespellrc index ba0fba66926..a8be48762d3 100644 --- a/.codespellrc +++ b/.codespellrc @@ -5,5 +5,5 @@ count = # Disable warnings about binary files quiet-level = 2 builtin = clear,rare,en-GB_to_en-US -skip = */.git,*/build,*/Copyright.txt,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Utilities/cm* +skip = */.git,*/build,*/Copyright.txt,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Tests/RunCMake/ParseImplicitData/*.input,*/Utilities/cm* ignore-words-list = aci,ake,ans,ba,cconfiguration,conly,dependees,dne,dum,earch,ect,filetest,fo,helpfull,hiden,isnt,keypair,nd,ned,nin,nknown,ot,pard,seh,ser,te,upto,varn,vas,wee diff --git a/Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input b/Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input new file mode 100644 index 00000000000..0aaf05efdc8 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitData/linux-C-GNU-10.2.1-static-libgcc.input @@ -0,0 +1,74 @@ +CMAKE_LANG=C +CMAKE_LINKER=/usr/bin/ld +CMAKE_C_COMPILER_ABI=ELF +CMAKE_C_COMPILER_AR=/usr/bin/gcc-ar-10 +CMAKE_C_COMPILER_ARCHITECTURE_ID= +CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN= +CMAKE_C_COMPILER_ID=GNU +CMAKE_C_COMPILER_LAUNCHER= +CMAKE_C_COMPILER_LOADED=1 +CMAKE_C_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10 +CMAKE_C_COMPILER_TARGET= +CMAKE_C_COMPILER_VERSION=10.2.1 +CMAKE_C_COMPILER_VERSION_INTERAL= +Change Dir: /tmp/ii/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_2fff5/fast && /usr/bin/gmake -f CMakeFiles/cmTC_2fff5.dir/build.make CMakeFiles/cmTC_2fff5.dir/build +gmake[1]: Entering directory '/tmp/ii/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o +/usr/bin/gcc -static-libgcc -v -o CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -c "/tmp/CMake/Modules/CMakeCCompilerABI.c" +Using built-in specs. +COLLECT_GCC=/usr/bin/gcc +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.1 20210110 (Debian 10.2.1-6) +COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-o' 'CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/10/cc1 -quiet -v -imultiarch x86_64-linux-gnu /tmp/CMake/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -o /tmp/cc1V18pC.s +GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu) + compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include" +#include "..." search starts here: +#include <...> search starts here: + /usr/lib/gcc/x86_64-linux-gnu/10/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include +End of search list. +GNU C17 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu) + compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: 1f803793fa2e3418c492b25e7d3eac2f +COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-o' 'CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o /tmp/cc1V18pC.s +GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2 +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-o' 'CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' +Linking C executable cmTC_2fff5 +"/tmp/CMake/bin/cmake" -E cmake_link_script CMakeFiles/cmTC_2fff5.dir/link.txt --verbose=1 +/usr/bin/gcc -static-libgcc -v -rdynamic CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -o cmTC_2fff5 +Using built-in specs. +COLLECT_GCC=/usr/bin/gcc +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.1 20210110 (Debian 10.2.1-6) +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-rdynamic' '-o' 'cmTC_2fff5' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cc0iqkvc.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_2fff5 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_2fff5.dir/CMakeCCompilerABI.c.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o +COLLECT_GCC_OPTIONS='-static-libgcc' '-v' '-rdynamic' '-o' 'cmTC_2fff5' '-mtune=generic' '-march=x86-64' +gmake[1]: Leaving directory '/tmp/ii/CMakeFiles/CMakeTmp' diff --git a/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input b/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input new file mode 100644 index 00000000000..2582be8d46d --- /dev/null +++ b/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input @@ -0,0 +1,78 @@ +CMAKE_LANG=CXX +CMAKE_LINKER=/usr/bin/ld +CMAKE_CXX_COMPILER_ABI=ELF +CMAKE_CXX_COMPILER_AR=/usr/bin/gcc-ar-10 +CMAKE_CXX_COMPILER_ARCHITECTURE_ID= +CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN= +CMAKE_CXX_COMPILER_ID=GNU +CMAKE_CXX_COMPILER_LAUNCHER= +CMAKE_CXX_COMPILER_LOADED=1 +CMAKE_CXX_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10 +CMAKE_CXX_COMPILER_TARGET= +CMAKE_CXX_COMPILER_VERSION=10.2.1 +CMAKE_CXX_COMPILER_VERSION_INTERAL= +Change Dir: /tmp/ii/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_339dd/fast && /usr/bin/gmake -f CMakeFiles/cmTC_339dd.dir/build.make CMakeFiles/cmTC_339dd.dir/build +gmake[1]: Entering directory '/tmp/ii/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o +/usr/bin/g++ -static-libstdc++ -v -o CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -c "/tmp/CMake/Modules/CMakeCXXCompilerABI.cpp" +Using built-in specs. +COLLECT_GCC=/usr/bin/g++ +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.1 20210110 (Debian 10.2.1-6) +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/10/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /tmp/CMake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -o /tmp/ccjKk4SK.s +GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu) + compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/10" +ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include" +#include "..." search starts here: +#include <...> search starts here: + /usr/include/c++/10 + /usr/include/x86_64-linux-gnu/c++/10 + /usr/include/c++/10/backward + /usr/lib/gcc/x86_64-linux-gnu/10/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include +End of search list. +GNU C++14 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu) + compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: 048fcaee3460a99eb0d68522358720e1 +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccjKk4SK.s +GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2 +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +Linking CXX executable cmTC_339dd +"/tmp/CMake/bin/cmake" -E cmake_link_script CMakeFiles/cmTC_339dd.dir/link.txt --verbose=1 +/usr/bin/g++ -static-libstdc++ -v -rdynamic CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_339dd +Using built-in specs. +COLLECT_GCC=/usr/bin/g++ +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.1 20210110 (Debian 10.2.1-6) +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_339dd' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/cc0slq0h.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_339dd /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_339dd.dir/CMakeCXXCompilerABI.cpp.o -Bstatic -lstdc++ -Bdynamic -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_339dd' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +gmake[1]: Leaving directory '/tmp/ii/CMakeFiles/CMakeTmp' diff --git a/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input b/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input new file mode 100644 index 00000000000..8a801f74423 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input @@ -0,0 +1,78 @@ +CMAKE_LANG=Fortran +CMAKE_LINKER=/usr/bin/ld +CMAKE_Fortran_COMPILER_ABI= +CMAKE_Fortran_COMPILER_AR=/usr/bin/gcc-ar-10 +CMAKE_Fortran_COMPILER_ARCHITECTURE_ID= +CMAKE_Fortran_COMPILER_EXTERNAL_TOOLCHAIN= +CMAKE_Fortran_COMPILER_ID=GNU +CMAKE_Fortran_COMPILER_LAUNCHER= +CMAKE_Fortran_COMPILER_LOADED=1 +CMAKE_Fortran_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10 +CMAKE_Fortran_COMPILER_TARGET= +CMAKE_Fortran_COMPILER_VERSION=10.2.1 +CMAKE_Fortran_COMPILER_VERSION_INTERAL= +Change Dir: /tmp/ii/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_07a63/fast && /usr/bin/gmake -f CMakeFiles/cmTC_07a63.dir/build.make CMakeFiles/cmTC_07a63.dir/build +gmake[1]: Entering directory '/tmp/ii/CMakeFiles/CMakeTmp' +Building Fortran object CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o +/usr/bin/gfortran -static-libgfortran -v -c "/tmp/CMake/Modules/CMakeFortranCompilerABI.F" -o CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o +Using built-in specs. +COLLECT_GCC=/usr/bin/gfortran +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.1 20210110 (Debian 10.2.1-6) +COLLECT_GCC_OPTIONS='-static-libgfortran' '-v' '-c' '-o' 'CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/10/f951 /tmp/CMake/Modules/CMakeFortranCompilerABI.F -ffixed-form -cpp=/tmp/ccA5jWwS.f90 -quiet -v -imultiarch x86_64-linux-gnu /tmp/CMake/Modules/CMakeFortranCompilerABI.F -quiet -dumpbase CMakeFortranCompilerABI.F -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -version -fintrinsic-modules-path /usr/lib/gcc/x86_64-linux-gnu/10/finclude -fpre-include=/usr/include/finclude/x86_64-linux-gnu/math-vector-fortran.h -o /tmp/cclOgAvW.s +GNU Fortran (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu) + compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed" +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include" +#include "..." search starts here: +#include <...> search starts here: + /usr/lib/gcc/x86_64-linux-gnu/10/finclude + /usr/lib/gcc/x86_64-linux-gnu/10/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include +End of search list. +GNU Fortran2008 (Debian 10.2.1-6) version 10.2.1 20210110 (x86_64-linux-gnu) + compiled by GNU C version 10.2.1 20210110, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.0, isl version isl-0.23-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +COLLECT_GCC_OPTIONS='-static-libgfortran' '-v' '-c' '-o' 'CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o /tmp/cclOgAvW.s +GNU assembler version 2.35.2 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.35.2 +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-static-libgfortran' '-v' '-c' '-o' 'CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o' '-mtune=generic' '-march=x86-64' +Linking Fortran executable cmTC_07a63 +"/tmp/CMake/bin/cmake" -E cmake_link_script CMakeFiles/cmTC_07a63.dir/link.txt --verbose=1 +/usr/bin/gfortran -v -static-libgfortran CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -o cmTC_07a63 +Driving: /usr/bin/gfortran -v -static-libgfortran CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -o cmTC_07a63 -Wl,-Bstatic -l gfortran -Wl,-Bdynamic -l m -shared-libgcc +Using built-in specs. +COLLECT_GCC=/usr/bin/gfortran +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.1 20210110 (Debian 10.2.1-6) +Reading specs from /usr/lib/gcc/x86_64-linux-gnu/10/libgfortran.spec +rename spec lib to liborig +COLLECT_GCC_OPTIONS='-v' '-static-libgfortran' '-o' 'cmTC_07a63' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/10/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-static-libgfortran' '-o' 'cmTC_07a63' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccbtSp3p.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lquadmath -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_07a63 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.. CMakeFiles/cmTC_07a63.dir/CMakeFortranCompilerABI.F.o -Bstatic -lgfortran -Bdynamic -lm -lgcc_s -lgcc --as-needed -lquadmath --no-as-needed -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o +COLLECT_GCC_OPTIONS='-v' '-static-libgfortran' '-o' 'cmTC_07a63' '-shared-libgcc' '-mtune=generic' '-march=x86-64' +gmake[1]: Leaving directory '/tmp/ii/CMakeFiles/CMakeTmp' diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake b/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake index 2d3abccb69b..e501f122e5d 100644 --- a/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake @@ -23,6 +23,9 @@ set(targets hand-C-empty hand-CXX-empty hand-C-relative hand-CXX-relative linux-C-GNU-7.3.0 linux-CXX-GNU-7.3.0 linux-Fortran-GNU-7.3.0 + linux-C-GNU-10.2.1-static-libgcc + linux-CXX-GNU-10.2.1-static-libstdc++ + linux-Fortran-GNU-10.2.1-static-libgfortran linux-C-Intel-18.0.0.20170811 linux-CXX-Intel-18.0.0.20170811 linux-C-PGI-18.10.1 linux-CXX-PGI-18.10.1 linux-Fortran-PGI-18.10.1 linux_pgf77-Fortran-PGI-18.10.1 diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output new file mode 100644 index 00000000000..2f89e152417 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-C-GNU-10.2.1-static-libgcc.output @@ -0,0 +1 @@ +/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output new file mode 100644 index 00000000000..b97cdc825a8 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output @@ -0,0 +1 @@ +/usr/include/c\+\+/10;/usr/include/x86_64-linux-gnu/c\+\+/10;/usr/include/c\+\+/10/backward;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output new file mode 100644 index 00000000000..34c33a73b78 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output @@ -0,0 +1 @@ +/usr/lib/gcc/x86_64-linux-gnu/10/finclude;/usr/lib/gcc/x86_64-linux-gnu/10/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake index 3c7f569bbfd..961a3f54359 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake +++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake @@ -23,6 +23,9 @@ set(targets hand-C-empty hand-CXX-empty hand-C-relative hand-CXX-relative linux-C-GNU-7.3.0 linux-CXX-GNU-7.3.0 linux-Fortran-GNU-7.3.0 + linux-C-GNU-10.2.1-static-libgcc + linux-CXX-GNU-10.2.1-static-libstdc++ + linux-Fortran-GNU-10.2.1-static-libgfortran linux-C-Intel-18.0.0.20170811 linux-CXX-Intel-18.0.0.20170811 linux-C-PGI-18.10.1 linux-CXX-PGI-18.10.1 linux-Fortran-PGI-18.10.1 linux_pgf77-Fortran-PGI-18.10.1 diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output new file mode 100644 index 00000000000..8bcd8b23964 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-10.2.1-static-libgcc.output @@ -0,0 +1,3 @@ +libs=gcc;c;gcc +dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib +library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output new file mode 100644 index 00000000000..ac85fc71e44 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output @@ -0,0 +1,3 @@ +libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc +dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib +library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output new file mode 100644 index 00000000000..6a594d3643f --- /dev/null +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output @@ -0,0 +1,3 @@ +libs=gfortran;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc +dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib +library_arch=x86_64-linux-gnu From 1d7fddca8ea1f1ac243d824a3c61079c77be3a75 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 2 Jun 2021 10:11:13 -0400 Subject: [PATCH 0571/1519] CMakeParseImplicitLinkInfo: Honor GNU static runtime library flags With flags like `-static-libstdc++` or `-static-libgfortran`, the GNU compiler driver adds `-Bstatic ... -Bdynamic` around its language runtime library. Convert the libraries in between these to absolute paths so that mixed-language linking honors the static runtime libraries. --- Modules/CMakeParseImplicitLinkInfo.cmake | 32 +++++++++++++++++++ .../CMakeTests/ImplicitLinkInfoTest.cmake.in | 3 ++ ...inux-CXX-GNU-10.2.1-static-libstdc++.input | 1 + ...ortran-GNU-10.2.1-static-libgfortran.input | 1 + .../ParseImplicitLinkInfo.cmake | 2 +- ...nux-CXX-GNU-10.2.1-static-libstdc++.output | 2 +- ...rtran-GNU-10.2.1-static-libgfortran.output | 2 +- 7 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index e848b555495..a61f71b117b 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -72,6 +72,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj endif() endif() set(is_msvc 0) + set(search_static 0) if("${cmd}" MATCHES "${linker_regex}") string(APPEND log " link line: [${line}]\n") string(REGEX REPLACE ";-([LYz]);" ";-\\1" args "${args}") @@ -103,6 +104,10 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj elseif("${arg}" MATCHES "^-l([^:].*)$") # Unix library. set(lib "${CMAKE_MATCH_1}") + if(search_static AND lib MATCHES "^(gfortran|stdc\\+\\+)$") + # Search for the static library later, once all link dirs are known. + set(lib "SEARCH_STATIC:${lib}") + endif() list(APPEND implicit_libs_tmp ${lib}) string(APPEND log " arg [${arg}] ==> lib [${lib}]\n") elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.a$") @@ -129,6 +134,12 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj string(REPLACE ":" ";" dirs "${dirs}") list(APPEND implicit_dirs_tmp ${dirs}) string(APPEND log " arg [${arg}] ==> dirs [${dirs}]\n") + elseif("${arg}" STREQUAL "-Bstatic") + set(search_static 1) + string(APPEND log " arg [${arg}] ==> search static\n" ) + elseif("${arg}" STREQUAL "-Bdynamic") + set(search_static 0) + string(APPEND log " arg [${arg}] ==> search dynamic\n" ) elseif("${arg}" MATCHES "^-l:") # HP named library. list(APPEND implicit_libs_tmp ${arg}) @@ -172,8 +183,29 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj # We remove items that are not language-specific. set(implicit_libs "") foreach(lib IN LISTS implicit_libs_tmp) + if("x${lib}" MATCHES "^xSEARCH_STATIC:(.*)") + set(search_static 1) + set(lib "${CMAKE_MATCH_1}") + else() + set(search_static 0) + endif() if("x${lib}" MATCHES "^x(crt.*\\.o|gcc_eh.*|.*libgcc_eh.*|System.*|.*libclang_rt.*|msvcrt.*|libvcruntime.*|libucrt.*|libcmt.*)$") string(APPEND log " remove lib [${lib}]\n") + elseif(search_static) + # This library appears after a -Bstatic flag. Due to ordering + # and filtering for mixed-language link lines, we do not preserve + # the -Bstatic flag itself. Instead, use an absolute path. + # Search using a temporary variable with a distinct name + # so that our test suite does not depend on disk content. + find_library("CMAKE_${lang}_IMPLICIT_LINK_LIBRARY_${lib}" NO_CACHE NAMES "lib${lib}.a" NO_DEFAULT_PATH PATHS ${implicit_dirs_tmp}) + set(_lib_static "${CMAKE_${lang}_IMPLICIT_LINK_LIBRARY_${lib}}") + if(_lib_static) + string(APPEND log " search lib [SEARCH_STATIC:${lib}] ==> [${_lib_static}]\n") + list(APPEND implicit_libs "${_lib_static}") + else() + string(APPEND log " search lib [SEARCH_STATIC:${lib}] ==> [${lib}]\n") + list(APPEND implicit_libs "${lib}") + endif() elseif(IS_ABSOLUTE "${lib}") get_filename_component(abs "${lib}" ABSOLUTE) if(NOT "x${lib}" STREQUAL "x${abs}") diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 1254ff96244..63c234acf78 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -2,6 +2,9 @@ # test it. include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake) +set(CMAKE_FIND_LIBRARY_PREFIXES "disabled-for-test-") +set(CMAKE_FIND_LIBRARY_SUFFIXES "-disabled-for-test") + #----------------------------------------------------------------------------- # Linux diff --git a/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input b/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input index 2582be8d46d..387f1490151 100644 --- a/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input +++ b/Tests/RunCMake/ParseImplicitData/linux-CXX-GNU-10.2.1-static-libstdc++.input @@ -11,6 +11,7 @@ CMAKE_CXX_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10 CMAKE_CXX_COMPILER_TARGET= CMAKE_CXX_COMPILER_VERSION=10.2.1 CMAKE_CXX_COMPILER_VERSION_INTERAL= +CMAKE_CXX_IMPLICIT_LINK_LIBRARY_stdc++=/usr/lib/gcc/x86_64-linux-gnu/10/libstdc++.a Change Dir: /tmp/ii/CMakeFiles/CMakeTmp Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_339dd/fast && /usr/bin/gmake -f CMakeFiles/cmTC_339dd.dir/build.make CMakeFiles/cmTC_339dd.dir/build diff --git a/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input b/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input index 8a801f74423..16b38d2d007 100644 --- a/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input +++ b/Tests/RunCMake/ParseImplicitData/linux-Fortran-GNU-10.2.1-static-libgfortran.input @@ -11,6 +11,7 @@ CMAKE_Fortran_COMPILER_RANLIB=/usr/bin/gcc-ranlib-10 CMAKE_Fortran_COMPILER_TARGET= CMAKE_Fortran_COMPILER_VERSION=10.2.1 CMAKE_Fortran_COMPILER_VERSION_INTERAL= +CMAKE_Fortran_IMPLICIT_LINK_LIBRARY_gfortran=/usr/lib/gcc/x86_64-linux-gnu/10/libgfortran.a Change Dir: /tmp/ii/CMakeFiles/CMakeTmp Run Build Command(s):/usr/bin/gmake -f Makefile cmTC_07a63/fast && /usr/bin/gmake -f CMakeFiles/cmTC_07a63.dir/build.make CMakeFiles/cmTC_07a63.dir/build diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake index 961a3f54359..dcdc7f1b96c 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake +++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake @@ -70,7 +70,7 @@ function(load_compiler_info infile lang_var outcmvars_var outstr_var) string(REGEX REPLACE "\r?\n" ";" in_lines "${in}") foreach(line IN LISTS in_lines) # check for special CMAKE variable lines and parse them if found - if("${line}" MATCHES "^CMAKE_([_A-Za-z0-9]+)=(.*)$") + if("${line}" MATCHES "^CMAKE_([_A-Za-z0-9+]+)=(.*)$") if("${CMAKE_MATCH_1}" STREQUAL "LANG") # handle CMAKE_LANG here set(lang "${CMAKE_MATCH_2}") else() diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output index ac85fc71e44..d38dfeef9c1 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-10.2.1-static-libstdc++.output @@ -1,3 +1,3 @@ -libs=stdc\+\+;m;gcc_s;gcc;c;gcc_s;gcc +libs=/usr/lib/gcc/x86_64-linux-gnu/10/libstdc\+\+.a;m;gcc_s;gcc;c;gcc_s;gcc dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output index 6a594d3643f..edeb20c5a39 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-10.2.1-static-libgfortran.output @@ -1,3 +1,3 @@ -libs=gfortran;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc +libs=/usr/lib/gcc/x86_64-linux-gnu/10/libgfortran.a;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc dirs=/usr/lib/gcc/x86_64-linux-gnu/10;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib library_arch=x86_64-linux-gnu From 6c34ed9b879906d1eaadad80f37f518829017789 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 08:32:44 -0400 Subject: [PATCH 0572/1519] cmake: Allow CMAKE_TOOLCHAIN_FILE to be set by environment variable When no `CMAKE_TOOLCHAIN_FILE` is explicitly specified while creating a new build tree, check for an environment variable of the same name. --- Help/envvar/CMAKE_TOOLCHAIN_FILE.rst | 12 +++++++++ Help/manual/cmake-env-variables.7.rst | 1 + Help/release/dev/env-toolchain-file.rst | 5 ++++ Help/variable/CMAKE_TOOLCHAIN_FILE.rst | 3 +++ Source/cmake.cxx | 10 +++++++ .../CommandLine/EnvToolchain-toolchain.cmake | 1 + Tests/RunCMake/CommandLine/EnvToolchain.cmake | 3 +++ .../EnvToolchainAbsolute-stdout.txt | 5 ++++ .../CommandLine/EnvToolchainAbsolute.cmake | 1 + .../CommandLine/EnvToolchainIgnore-stdout.txt | 4 +++ .../CommandLine/EnvToolchainIgnore.cmake | 1 + .../CommandLine/EnvToolchainNone-stdout.txt | 3 +++ .../CommandLine/EnvToolchainNone.cmake | 1 + .../EnvToolchainNoneExisting-stdout.txt | 4 +++ .../EnvToolchainRelative-stdout.txt | 4 +++ .../CommandLine/EnvToolchainRelative.cmake | 1 + Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 27 +++++++++++++++++++ 17 files changed, 86 insertions(+) create mode 100644 Help/envvar/CMAKE_TOOLCHAIN_FILE.rst create mode 100644 Help/release/dev/env-toolchain-file.rst create mode 100644 Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvToolchain.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainNone.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake diff --git a/Help/envvar/CMAKE_TOOLCHAIN_FILE.rst b/Help/envvar/CMAKE_TOOLCHAIN_FILE.rst new file mode 100644 index 00000000000..7ea9cea3572 --- /dev/null +++ b/Help/envvar/CMAKE_TOOLCHAIN_FILE.rst @@ -0,0 +1,12 @@ +CMAKE_TOOLCHAIN_FILE +-------------------- + +.. versionadded:: 3.21 + +.. include:: ENV_VAR.txt + +The ``CMAKE_TOOLCHAIN_FILE`` environment variable specifies a default value +for the :variable:`CMAKE_TOOLCHAIN_FILE` 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_TOOLCHAIN_FILE`. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index 8932abf7e42..bfdc8419899 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -41,6 +41,7 @@ Environment Variables that Control the Build /envvar/CMAKE_MSVCIDE_RUN_PATH /envvar/CMAKE_NO_VERBOSE /envvar/CMAKE_OSX_ARCHITECTURES + /envvar/CMAKE_TOOLCHAIN_FILE /envvar/DESTDIR /envvar/LDFLAGS /envvar/MACOSX_DEPLOYMENT_TARGET diff --git a/Help/release/dev/env-toolchain-file.rst b/Help/release/dev/env-toolchain-file.rst new file mode 100644 index 00000000000..0bcd493a2b0 --- /dev/null +++ b/Help/release/dev/env-toolchain-file.rst @@ -0,0 +1,5 @@ +env-toolchain-file +------------------ + +* The :envvar:`CMAKE_TOOLCHAIN_FILE` environment variable was added to + provide a default value for the :variable:`CMAKE_TOOLCHAIN_FILE` variable. diff --git a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst index e462c5e8513..ff8d59a69b8 100644 --- a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst +++ b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst @@ -10,3 +10,6 @@ platform and compiler related information. Relative paths are allowed and are interpreted first as relative to the build directory, and if not found, relative to the source directory. + +This is initialized by the :envvar:`CMAKE_TOOLCHAIN_FILE` environment +variable if it is set when a new build tree is first created. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 840a9d959cf..9a866ab89bf 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2040,6 +2040,16 @@ int cmake::ActualConfigure() this->GlobalGenerator->GetExtraGeneratorName().c_str(), "Name of external makefile project generator.", cmStateEnums::INTERNAL); + + if (!this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) { + std::string envToolchain; + if (cmSystemTools::GetEnv("CMAKE_TOOLCHAIN_FILE", envToolchain) && + !envToolchain.empty()) { + this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain.c_str(), + "The CMake toolchain file", + cmStateEnums::FILEPATH); + } + } } if (cmProp instance = diff --git a/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake b/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake new file mode 100644 index 00000000000..d9fbd58387c --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake @@ -0,0 +1 @@ +set(ENV_TOOLCHAIN 1) diff --git a/Tests/RunCMake/CommandLine/EnvToolchain.cmake b/Tests/RunCMake/CommandLine/EnvToolchain.cmake new file mode 100644 index 00000000000..230051d0a2c --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchain.cmake @@ -0,0 +1,3 @@ +message(STATUS "ENV{CMAKE_TOOLCHAIN_FILE}='$ENV{CMAKE_TOOLCHAIN_FILE}'") +message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'") +message(STATUS "ENV_TOOLCHAIN='${ENV_TOOLCHAIN}'") diff --git a/Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt new file mode 100644 index 00000000000..ab4bbde9b9c --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute-stdout.txt @@ -0,0 +1,5 @@ +-- ENV{CMAKE_TOOLCHAIN_FILE}='[^ +]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake' +-- CMAKE_TOOLCHAIN_FILE='[^ +]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake' +-- ENV_TOOLCHAIN='1' diff --git a/Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake new file mode 100644 index 00000000000..0f91b5eb4d6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainAbsolute.cmake @@ -0,0 +1 @@ +include(EnvToolchain.cmake) diff --git a/Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt new file mode 100644 index 00000000000..4de9505c26c --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainIgnore-stdout.txt @@ -0,0 +1,4 @@ +-- ENV{CMAKE_TOOLCHAIN_FILE}='[^ +]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake' +-- CMAKE_TOOLCHAIN_FILE='' +-- ENV_TOOLCHAIN='' diff --git a/Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake b/Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake new file mode 100644 index 00000000000..0f91b5eb4d6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainIgnore.cmake @@ -0,0 +1 @@ +include(EnvToolchain.cmake) diff --git a/Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt new file mode 100644 index 00000000000..cfe655d762d --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainNone-stdout.txt @@ -0,0 +1,3 @@ +-- ENV{CMAKE_TOOLCHAIN_FILE}='' +-- CMAKE_TOOLCHAIN_FILE='' +-- ENV_TOOLCHAIN='' diff --git a/Tests/RunCMake/CommandLine/EnvToolchainNone.cmake b/Tests/RunCMake/CommandLine/EnvToolchainNone.cmake new file mode 100644 index 00000000000..0f91b5eb4d6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainNone.cmake @@ -0,0 +1 @@ +include(EnvToolchain.cmake) diff --git a/Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt new file mode 100644 index 00000000000..4de9505c26c --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainNoneExisting-stdout.txt @@ -0,0 +1,4 @@ +-- ENV{CMAKE_TOOLCHAIN_FILE}='[^ +]*/Tests/RunCMake/CommandLine/EnvToolchain-toolchain.cmake' +-- CMAKE_TOOLCHAIN_FILE='' +-- ENV_TOOLCHAIN='' diff --git a/Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt b/Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt new file mode 100644 index 00000000000..4bafbba7ea1 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainRelative-stdout.txt @@ -0,0 +1,4 @@ +-- ENV{CMAKE_TOOLCHAIN_FILE}='EnvToolchain-toolchain.cmake' +-- CMAKE_TOOLCHAIN_FILE='[^ +]*/Tests/RunCMake/CommandLine/EnvToolchainRelative-build/EnvToolchain-toolchain.cmake' +-- ENV_TOOLCHAIN='1' diff --git a/Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake b/Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake new file mode 100644 index 00000000000..0f91b5eb4d6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvToolchainRelative.cmake @@ -0,0 +1 @@ +include(EnvToolchain.cmake) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 2eb87842039..c4d3e4ae614 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -344,6 +344,33 @@ if(RunCMake_GENERATOR MATCHES "Unix Makefiles" OR RunCMake_GENERATOR MATCHES "Ni run_EnvironmentExportCompileCommands() endif() +function(run_EnvironmentToolchain) + set(ENV{CMAKE_TOOLCHAIN_FILE} "${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake") + run_cmake(EnvToolchainAbsolute) + run_cmake_with_options(EnvToolchainIgnore -DCMAKE_TOOLCHAIN_FILE=) + unset(ENV{CMAKE_TOOLCHAIN_FILE}) + + set(ENV{CMAKE_TOOLCHAIN_FILE} "EnvToolchain-toolchain.cmake") + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EnvToolchainRelative-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + configure_file("${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake" "${RunCMake_TEST_BINARY_DIR}/EnvToolchain-toolchain.cmake" COPYONLY) + run_cmake(EnvToolchainRelative) + unset(ENV{CMAKE_TOOLCHAIN_FILE}) + unset(RunCMake_TEST_NO_CLEAN) + + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EnvToolchainNone-build) + run_cmake(EnvToolchainNone) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}/CMakeFiles") + set(ENV{CMAKE_TOOLCHAIN_FILE} "${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake") + run_cmake_command(EnvToolchainNoneExisting ${CMAKE_COMMAND} .) + unset(ENV{CMAKE_TOOLCHAIN_FILE}) + unset(RunCMake_TEST_NO_CLEAN) +endfunction() +run_EnvironmentToolchain() + if(RunCMake_GENERATOR STREQUAL "Ninja") # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Build-build) From b613e09778260c26c6323026dc2ccb980c102f3e Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Tue, 20 Apr 2021 16:16:57 -0400 Subject: [PATCH 0573/1519] cmRuntimeDependencyArchive: Fix const-ness of method signatures --- Source/cmRuntimeDependencyArchive.cxx | 18 ++++++++++-------- Source/cmRuntimeDependencyArchive.h | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx index a6ed523f22f..57b4bd6b44c 100644 --- a/Source/cmRuntimeDependencyArchive.cxx +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -198,25 +198,26 @@ void cmRuntimeDependencyArchive::SetError(const std::string& e) this->Status.SetError(e); } -std::string cmRuntimeDependencyArchive::GetBundleExecutable() +const std::string& cmRuntimeDependencyArchive::GetBundleExecutable() const { return this->BundleExecutable; } const std::vector& -cmRuntimeDependencyArchive::GetSearchDirectories() +cmRuntimeDependencyArchive::GetSearchDirectories() const { return this->SearchDirectories; } -std::string cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool() +const std::string& cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool() + const { return this->GetMakefile()->GetSafeDefinition( "CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL"); } bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand( - const std::string& search, std::vector& command) + const std::string& search, std::vector& command) const { // First see if it was supplied by the user std::string toolCommand = this->GetMakefile()->GetSafeDefinition( @@ -309,7 +310,7 @@ bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand( return false; } -bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name) +bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name) const { cmsys::RegularExpressionMatch match; auto const regexMatch = @@ -326,7 +327,7 @@ bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name) regexSearch(this->PreExcludeRegexes); } -bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) +bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) const { cmsys::RegularExpressionMatch match; auto const regexMatch = @@ -373,18 +374,19 @@ void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name) this->UnresolvedPaths.insert(name); } -cmMakefile* cmRuntimeDependencyArchive::GetMakefile() +cmMakefile* cmRuntimeDependencyArchive::GetMakefile() const { return &this->Status.GetMakefile(); } const std::map>& -cmRuntimeDependencyArchive::GetResolvedPaths() +cmRuntimeDependencyArchive::GetResolvedPaths() const { return this->ResolvedPaths; } const std::set& cmRuntimeDependencyArchive::GetUnresolvedPaths() + const { return this->UnresolvedPaths; } diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h index 1dc32618392..3f368c5a77d 100644 --- a/Source/cmRuntimeDependencyArchive.h +++ b/Source/cmRuntimeDependencyArchive.h @@ -36,21 +36,21 @@ class cmRuntimeDependencyArchive void SetError(const std::string& e); - std::string GetBundleExecutable(); - const std::vector& GetSearchDirectories(); - std::string GetGetRuntimeDependenciesTool(); - bool GetGetRuntimeDependenciesCommand(const std::string& search, - std::vector& command); - bool IsPreExcluded(const std::string& name); - bool IsPostExcluded(const std::string& name); + const std::string& GetBundleExecutable() const; + const std::vector& GetSearchDirectories() const; + const std::string& GetGetRuntimeDependenciesTool() const; + bool GetGetRuntimeDependenciesCommand( + const std::string& search, std::vector& command) const; + bool IsPreExcluded(const std::string& name) const; + bool IsPostExcluded(const std::string& name) const; void AddResolvedPath(const std::string& name, const std::string& path, bool& unique); void AddUnresolvedPath(const std::string& name); - cmMakefile* GetMakefile(); - const std::map>& GetResolvedPaths(); - const std::set& GetUnresolvedPaths(); + cmMakefile* GetMakefile() const; + const std::map>& GetResolvedPaths() const; + const std::set& GetUnresolvedPaths() const; private: cmExecutionStatus& Status; From c48d2d8480402a75e1509b19c145f004126dda10 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 10:36:06 -0400 Subject: [PATCH 0574/1519] VS: Place per-source preprocessor definitions after target-wide ones When the VS 2010+ generators were first implemented in commit 7491f52992 (ENH: first pass at VS 10, can bootstrap CMake, but many tests still fail, 2009-06-25, v2.8.0~546), the per-source preprocessor definitions were placed before target-wide preprocessor definitions for consistency with the behavior of VS 9 2008 and below. However, those generators are not used much anymore. Instead prefer consistency with the order used by the Ninja and Makefile generators. --- Help/release/dev/compile-options-order.rst | 7 +++++++ Source/cmVisualStudioGeneratorOptions.cxx | 10 ++++------ 2 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/compile-options-order.rst diff --git a/Help/release/dev/compile-options-order.rst b/Help/release/dev/compile-options-order.rst new file mode 100644 index 00000000000..2e182cdf06e --- /dev/null +++ b/Help/release/dev/compile-options-order.rst @@ -0,0 +1,7 @@ +compile-options-order +--------------------- + +* The :ref:`Visual Studio Generators` for VS 2010 and above now place + per-source preprocessor definitions after target-wide preprocssor + definitions. This makes VS consistent with the :ref:`Ninja Generators` + and the :ref:`Makefile Generators`. diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 937b4ce4ac0..505d58ac3ad 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -418,7 +418,9 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( } std::ostringstream oss; - const char* sep = ""; + if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { + oss << "%(" << tag << ")"; + } std::vector::const_iterator de = cmRemoveDuplicates(this->Defines); for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) { @@ -437,11 +439,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( } } // Store the flag in the project file. - oss << sep << define; - sep = ";"; - } - if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { - oss << ";%(" << tag << ")"; + oss << ';' << define; } this->OutputFlag(fout, indent, tag, oss.str()); From df79fe055b010131737517c0169e4c82db42482a Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 10:52:36 -0400 Subject: [PATCH 0575/1519] Help: Remove incorrect "versionadded" for CMAKE__FLAGS_ These variables have been around for a long time, but the current form of the document was added later. --- Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst b/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst index 628b62ba2d7..1dbd03640de 100644 --- a/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst +++ b/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst @@ -1,6 +1,4 @@ CMAKE__FLAGS_ --------------------------- -.. versionadded:: 3.11 - Flags for language ```` when building for the ```` configuration. From ccc83ce1623a90c9354a940370ed8c06d2fea30b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 10:58:19 -0400 Subject: [PATCH 0576/1519] Help: Document order of flags from CMAKE__FLAGS and COMPILE_OPTIONS --- Help/prop_sf/COMPILE_FLAGS.rst | 7 +++++-- Help/prop_sf/COMPILE_OPTIONS.rst | 7 ++++--- Help/prop_tgt/COMPILE_OPTIONS.rst | 10 +++++++--- Help/variable/CMAKE_LANG_FLAGS.rst | 5 +++++ Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst | 5 +++++ 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Help/prop_sf/COMPILE_FLAGS.rst b/Help/prop_sf/COMPILE_FLAGS.rst index c211b89acac..eefe7bff3a1 100644 --- a/Help/prop_sf/COMPILE_FLAGS.rst +++ b/Help/prop_sf/COMPILE_FLAGS.rst @@ -4,8 +4,11 @@ COMPILE_FLAGS Additional flags to be added when compiling this source file. The ``COMPILE_FLAGS`` property, managed as a string, sets additional compiler -flags used to build source files. Use :prop_sf:`COMPILE_DEFINITIONS` to pass -additional preprocessor definitions. +flags used that will be added to the list of compile flags when this source +file builds. The flags will be added after target-wide flags (except in +some cases not supported by the :generator:`Visual Studio 9 2008` generator). + +Use :prop_sf:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions. Contents of ``COMPILE_FLAGS`` may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` diff --git a/Help/prop_sf/COMPILE_OPTIONS.rst b/Help/prop_sf/COMPILE_OPTIONS.rst index a694c3e61eb..84c543a2c17 100644 --- a/Help/prop_sf/COMPILE_OPTIONS.rst +++ b/Help/prop_sf/COMPILE_OPTIONS.rst @@ -5,9 +5,10 @@ COMPILE_OPTIONS List of additional options to pass to the compiler. -This property holds a :ref:`semicolon-separated list ` of options -and will be added to the list of compile flags when this -source file builds. +This property holds a :ref:`semicolon-separated list ` +of options and will be added to the list of compile flags when this source +file builds. The options will be added after target-wide options (except in +some cases not supported by the :generator:`Visual Studio 9 2008` generator). Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual diff --git a/Help/prop_tgt/COMPILE_OPTIONS.rst b/Help/prop_tgt/COMPILE_OPTIONS.rst index 4bc190abc03..0fd6aac609b 100644 --- a/Help/prop_tgt/COMPILE_OPTIONS.rst +++ b/Help/prop_tgt/COMPILE_OPTIONS.rst @@ -3,9 +3,13 @@ COMPILE_OPTIONS List of options to pass to the compiler. -This property holds a :ref:`semicolon-separated list ` of options -specified so far for its target. Use the :command:`target_compile_options` -command to append more options. +This property holds a :ref:`semicolon-separated list ` +of options specified so far for its target. Use the +:command:`target_compile_options` command to append more options. +The options will be added after after flags in the +:variable:`CMAKE__FLAGS` and :variable:`CMAKE__FLAGS_` +variables, but before those propagated from dependencies by the +:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property. This property is initialized by the :prop_dir:`COMPILE_OPTIONS` directory property when a target is created, and is used by the generators to set diff --git a/Help/variable/CMAKE_LANG_FLAGS.rst b/Help/variable/CMAKE_LANG_FLAGS.rst index 11864f8e7c0..2784397ac28 100644 --- a/Help/variable/CMAKE_LANG_FLAGS.rst +++ b/Help/variable/CMAKE_LANG_FLAGS.rst @@ -18,3 +18,8 @@ This is initialized for each language from environment variables: This value is a command-line string fragment. Therefore, multiple options should be separated by spaces, and options with spaces should be quoted. + +The flags in this variable will be passed to the compiler before those +in the per-configuration :variable:`CMAKE__FLAGS_` variant, +and before flags added by the :command:`add_compile_options` or +:command:`target_compile_options` commands. diff --git a/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst b/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst index 1dbd03640de..f0900fdc8dd 100644 --- a/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst +++ b/Help/variable/CMAKE_LANG_FLAGS_CONFIG.rst @@ -2,3 +2,8 @@ CMAKE__FLAGS_ --------------------------- Flags for language ```` when building for the ```` configuration. + +The flags in this variable will be passed to the compiler after those +in the :variable:`CMAKE__FLAGS` variable, but before flags added +by the :command:`add_compile_options` or :command:`target_compile_options` +commands. From 82584b99e32a8fc7ac46a73ee1966b973fe0c0e1 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 3 Jun 2021 14:32:45 -0400 Subject: [PATCH 0577/1519] jsoncpp: Revert "Code style: add missed explicit 'this->'" Revert the part of commit 209daa20b2 (Code style: add missed explicit 'this->', 2021-01-05, v3.20.0-rc1~213^2) that updated third-party code. --- .../cmjsoncpp/src/lib_json/json_reader.cpp | 2027 ++++++++--------- .../cmjsoncpp/src/lib_json/json_value.cpp | 1847 +++++++-------- .../cmjsoncpp/src/lib_json/json_writer.cpp | 1420 ++++++------ 3 files changed, 2411 insertions(+), 2883 deletions(-) diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp index 8362fc4cb9c..6eeba0e65e0 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp @@ -2,88 +2,74 @@ // Copyright (C) 2016 InfoTeCS JSC. All rights reserved. // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. -// See file LICENSE for detail or copy at -// http://jsoncpp.sourceforge.net/LICENSE +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include - -# include "json_tool.h" +#include +#include +#include +#include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include #include - -#include #include +#include #include +#include +#include +#include +#include +#include #if defined(_MSC_VER) -# if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && \ - _MSC_VER >= 1500 // VC++ 9.0 and above -# define snprintf sprintf_s -# elif _MSC_VER >= 1900 // VC++ 14.0 and above -# define snprintf std::snprintf -# else -# define snprintf _snprintf -# endif +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#define snprintf sprintf_s +#elif _MSC_VER >= 1900 // VC++ 14.0 and above +#define snprintf std::snprintf +#else +#define snprintf _snprintf +#endif #elif defined(__ANDROID__) || defined(__QNXNTO__) -# define snprintf snprintf +#define snprintf snprintf #elif __cplusplus >= 201103L -# if !defined(__MINGW32__) && !defined(__CYGWIN__) -# define snprintf std::snprintf -# endif +#if !defined(__MINGW32__) && !defined(__CYGWIN__) +#define snprintf std::snprintf +#endif #endif #if defined(__QNXNTO__) -# define sscanf std::sscanf +#define sscanf std::sscanf #endif #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 // Disable warning about strdup being deprecated. -# pragma warning(disable : 4996) +#pragma warning(disable : 4996) #endif -// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile -// time to change the stack limit +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) -# define JSONCPP_DEPRECATED_STACK_LIMIT 1000 +#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 #endif -static size_t const stackLimit_g = - JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() +static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) typedef std::unique_ptr CharReaderPtr; #else -typedef std::auto_ptr CharReaderPtr; +typedef std::auto_ptr CharReaderPtr; #endif // Implementation of class Features // //////////////////////////////// Features::Features() - : allowComments_(true) - , strictRoot_(false) - , allowDroppedNullPlaceholders_(false) - , allowNumericKeys_(false) -{ -} + : allowComments_(true), strictRoot_(false), + allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} -Features Features::all() -{ - return Features(); -} +Features Features::all() { return Features(); } -Features Features::strictMode() -{ +Features Features::strictMode() { Features features; features.allowComments_ = false; features.strictRoot_ = true; @@ -95,8 +81,7 @@ Features Features::strictMode() // Implementation of class Reader // //////////////////////////////// -bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) -{ +bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { for (; begin < end; ++begin) if (*begin == '\n' || *begin == '\r') return true; @@ -107,44 +92,24 @@ bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) // ////////////////////////////////////////////////////////////////// Reader::Reader() - : errors_() - , document_() - , begin_() - , end_() - , current_() - , lastValueEnd_() - , lastValue_() - , commentsBefore_() - , features_(Features::all()) - , collectComments_() -{ -} + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} Reader::Reader(const Features& features) - : errors_() - , document_() - , begin_() - , end_() - , current_() - , lastValueEnd_() - , lastValue_() - , commentsBefore_() - , features_(features) - , collectComments_() -{ + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { } -bool Reader::parse(const std::string& document, Value& root, - bool collectComments) -{ - this->document_.assign(document.begin(), document.end()); - const char* begin = this->document_.c_str(); - const char* end = begin + this->document_.length(); - return this->parse(begin, end, root, collectComments); +bool +Reader::parse(const std::string& document, Value& root, bool collectComments) { + document_.assign(document.begin(), document.end()); + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); } -bool Reader::parse(std::istream& sin, Value& root, bool collectComments) -{ +bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { // std::istream_iterator begin(sin); // std::istream_iterator end; // Those would allow streamed input from a file, if parse() were a @@ -154,263 +119,257 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments) // create an extra copy. JSONCPP_STRING doc; std::getline(sin, doc, (char)EOF); - return this->parse(doc.data(), doc.data() + doc.size(), root, - collectComments); + return parse(doc.data(), doc.data() + doc.size(), root, collectComments); } -bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root, - bool collectComments) -{ - if (!this->features_.allowComments_) { +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { collectComments = false; } - this->begin_ = beginDoc; - this->end_ = endDoc; - this->collectComments_ = collectComments; - this->current_ = this->begin_; - this->lastValueEnd_ = 0; - this->lastValue_ = 0; - this->commentsBefore_.clear(); - this->errors_.clear(); - while (!this->nodes_.empty()) - this->nodes_.pop(); - this->nodes_.push(&root); - - bool successful = this->readValue(); + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); Token token; - this->skipCommentTokens(token); - if (this->collectComments_ && !this->commentsBefore_.empty()) - root.setComment(this->commentsBefore_, commentAfter); - if (this->features_.strictRoot_) { + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token - // found in doc + // Set error location to start of doc, ideally should be first token found + // in doc token.type_ = tokenError; token.start_ = beginDoc; token.end_ = endDoc; - this->addError( - "A valid JSON document must be either an array or an object value.", - token); + addError( + "A valid JSON document must be either an array or an object value.", + token); return false; } } return successful; } -bool Reader::readValue() -{ +bool Reader::readValue() { // readValue() may call itself only if it calls readObject() or ReadArray(). - // These methods execute nodes_.push() just before and nodes_.pop)() just - // after calling readValue(). parse() executes one nodes_.push(), so > - // instead of >=. - if (this->nodes_.size() > stackLimit_g) - throwRuntimeError("Exceeded stackLimit in readValue()."); + // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). + // parse() executes one nodes_.push(), so > instead of >=. + if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; - this->skipCommentTokens(token); + skipCommentTokens(token); bool successful = true; - if (this->collectComments_ && !this->commentsBefore_.empty()) { - this->currentValue().setComment(this->commentsBefore_, commentBefore); - this->commentsBefore_.clear(); + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); } switch (token.type_) { - case tokenObjectBegin: - successful = this->readObject(token); - this->currentValue().setOffsetLimit(this->current_ - this->begin_); - break; - case tokenArrayBegin: - successful = this->readArray(token); - this->currentValue().setOffsetLimit(this->current_ - this->begin_); - break; - case tokenNumber: - successful = this->decodeNumber(token); - break; - case tokenString: - successful = this->decodeString(token); - break; - case tokenTrue: { - Value v(true); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenFalse: { - Value v(false); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenNull: { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; Value v; - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (this->features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - this->current_--; - Value v; - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(this->current_ - this->begin_ - 1); - this->currentValue().setOffsetLimit(this->current_ - this->begin_); - break; - } // Else, fall through... - default: - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - return this->addError("Syntax error: value, object or array expected.", - token); + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); } - if (this->collectComments_) { - this->lastValueEnd_ = this->current_; - this->lastValue_ = &this->currentValue(); + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); } return successful; } -void Reader::skipCommentTokens(Token& token) -{ - if (this->features_.allowComments_) { +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { do { - this->readToken(token); + readToken(token); } while (token.type_ == tokenComment); } else { - this->readToken(token); + readToken(token); } } -bool Reader::readToken(Token& token) -{ - this->skipSpaces(); - token.start_ = this->current_; - Char c = this->getNextChar(); +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); bool ok = true; switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = this->readString(); - break; - case '/': - token.type_ = tokenComment; - ok = this->readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - this->readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = this->match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = this->match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = this->match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; } if (!ok) token.type_ = tokenError; - token.end_ = this->current_; + token.end_ = current_; return true; } -void Reader::skipSpaces() -{ - while (this->current_ != this->end_) { - Char c = *this->current_; +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++this->current_; + ++current_; else break; } } -bool Reader::match(Location pattern, int patternLength) -{ - if (this->end_ - this->current_ < patternLength) +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) return false; int index = patternLength; while (index--) - if (this->current_[index] != pattern[index]) + if (current_[index] != pattern[index]) return false; - this->current_ += patternLength; + current_ += patternLength; return true; } -bool Reader::readComment() -{ - Location commentBegin = this->current_ - 1; - Char c = this->getNextChar(); +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); bool successful = false; if (c == '*') - successful = this->readCStyleComment(); + successful = readCStyleComment(); else if (c == '/') - successful = this->readCppStyleComment(); + successful = readCppStyleComment(); if (!successful) return false; - if (this->collectComments_) { + if (collectComments_) { CommentPlacement placement = commentBefore; - if (this->lastValueEnd_ && - !containsNewLine(this->lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, this->current_)) + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) placement = commentAfterOnSameLine; } - this->addComment(commentBegin, this->current_, placement); + addComment(commentBegin, current_, placement); } return true; } -JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, - Reader::Location end) -{ +JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { JSONCPP_STRING normalized; normalized.reserve(static_cast(end - begin)); Reader::Location current = begin; @@ -418,8 +377,8 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, char c = *current++; if (c == '\r') { if (current != end && *current == '\n') - // convert dos EOL - ++current; + // convert dos EOL + ++current; // convert Mac EOL normalized += '\n'; } else { @@ -429,39 +388,36 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, return normalized; } -void Reader::addComment(Location begin, Location end, - CommentPlacement placement) -{ - assert(this->collectComments_); +void +Reader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); const JSONCPP_STRING& normalized = normalizeEOL(begin, end); if (placement == commentAfterOnSameLine) { - assert(this->lastValue_ != 0); - this->lastValue_->setComment(normalized, placement); + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); } else { - this->commentsBefore_ += normalized; + commentsBefore_ += normalized; } } -bool Reader::readCStyleComment() -{ - while ((this->current_ + 1) < this->end_) { - Char c = this->getNextChar(); - if (c == '*' && *this->current_ == '/') +bool Reader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') break; } - return this->getNextChar() == '/'; + return getNextChar() == '/'; } -bool Reader::readCppStyleComment() -{ - while (this->current_ != this->end_) { - Char c = this->getNextChar(); +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); if (c == '\n') break; if (c == '\r') { // Consume DOS EOL. It will be normalized in addComment. - if (this->current_ != this->end_ && *this->current_ == '\n') - this->getNextChar(); + if (current_ != end_ && *current_ == '\n') + getNextChar(); // Break on Moc OS 9 EOL. break; } @@ -469,132 +425,127 @@ bool Reader::readCppStyleComment() return true; } -void Reader::readNumber() -{ - const char* p = this->current_; +void Reader::readNumber() { + const char *p = current_; char c = '0'; // stopgap for already consumed character // integral part while (c >= '0' && c <= '9') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; // fractional part if (c == '.') { - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; while (c >= '0' && c <= '9') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; } // exponential part if (c == 'e' || c == 'E') { - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; if (c == '+' || c == '-') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; while (c >= '0' && c <= '9') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; } } -bool Reader::readString() -{ +bool Reader::readString() { Char c = '\0'; - while (this->current_ != this->end_) { - c = this->getNextChar(); + while (current_ != end_) { + c = getNextChar(); if (c == '\\') - this->getNextChar(); + getNextChar(); else if (c == '"') break; } return c == '"'; } -bool Reader::readObject(Token& tokenStart) -{ +bool Reader::readObject(Token& tokenStart) { Token tokenName; JSONCPP_STRING name; Value init(objectValue); - this->currentValue().swapPayload(init); - this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_); - while (this->readToken(tokenName)) { + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + while (readToken(tokenName)) { bool initialTokenOk = true; while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = this->readToken(tokenName); + initialTokenOk = readToken(tokenName); if (!initialTokenOk) break; if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object return true; name.clear(); if (tokenName.type_ == tokenString) { - if (!this->decodeString(tokenName, name)) - return this->recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && - this->features_.allowNumericKeys_) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { Value numberName; - if (!this->decodeNumber(tokenName, numberName)) - return this->recoverFromError(tokenObjectEnd); + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); name = JSONCPP_STRING(numberName.asCString()); } else { break; } Token colon; - if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) { - return this->addErrorAndRecover("Missing ':' after object member name", - colon, tokenObjectEnd); + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); } - Value& value = this->currentValue()[name]; - this->nodes_.push(&value); - bool ok = this->readValue(); - this->nodes_.pop(); + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); if (!ok) // error already set - return this->recoverFromError(tokenObjectEnd); + return recoverFromError(tokenObjectEnd); Token comma; - if (!this->readToken(comma) || + if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return this->addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); } bool finalizeTokenOk = true; while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = this->readToken(comma); + finalizeTokenOk = readToken(comma); if (comma.type_ == tokenObjectEnd) return true; } - return this->addErrorAndRecover("Missing '}' or object member name", - tokenName, tokenObjectEnd); + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); } -bool Reader::readArray(Token& tokenStart) -{ +bool Reader::readArray(Token& tokenStart) { Value init(arrayValue); - this->currentValue().swapPayload(init); - this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_); - this->skipSpaces(); - if (this->current_ != this->end_ && *this->current_ == ']') // empty array + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array { Token endArray; - this->readToken(endArray); + readToken(endArray); return true; } int index = 0; for (;;) { - Value& value = this->currentValue()[index++]; - this->nodes_.push(&value); - bool ok = this->readValue(); - this->nodes_.pop(); + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); if (!ok) // error already set - return this->recoverFromError(tokenArrayEnd); + return recoverFromError(tokenArrayEnd); Token token; // Accept Comment after last item in the array. - ok = this->readToken(token); + ok = readToken(token); while (token.type_ == tokenComment && ok) { - ok = this->readToken(token); + ok = readToken(token); } bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return this->addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); } if (token.type_ == tokenArrayEnd) break; @@ -602,19 +553,17 @@ bool Reader::readArray(Token& tokenStart) return true; } -bool Reader::decodeNumber(Token& token) -{ +bool Reader::decodeNumber(Token& token) { Value decoded; - if (!this->decodeNumber(token, decoded)) + if (!decodeNumber(token, decoded)) return false; - this->currentValue().swapPayload(decoded); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); return true; } -bool Reader::decodeNumber(Token& token, Value& decoded) -{ +bool Reader::decodeNumber(Token& token, Value& decoded) { // Attempts to parse the number as an integer. If the number is // larger than the maximum supported value of an integer then // we decode the number as a double. @@ -622,17 +571,16 @@ bool Reader::decodeNumber(Token& token, Value& decoded) bool isNegative = *current == '-'; if (isNegative) ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of - // them. - Value::LargestUInt maxIntegerValue = isNegative - ? Value::LargestUInt(Value::maxLargestInt) + 1 - : Value::maxLargestUInt; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 + : Value::maxLargestUInt; Value::LargestUInt threshold = maxIntegerValue / 10; Value::LargestUInt value = 0; while (current < token.end_) { Char c = *current++; if (c < '0' || c > '9') - return this->decodeDouble(token, decoded); + return decodeDouble(token, decoded); Value::UInt digit(static_cast(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If @@ -641,7 +589,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) // Otherwise treat this number as a double to avoid overflow. if (value > threshold || current != token.end_ || digit > maxIntegerValue % 10) { - return this->decodeDouble(token, decoded); + return decodeDouble(token, decoded); } } value = value * 10 + digit; @@ -657,44 +605,40 @@ bool Reader::decodeNumber(Token& token, Value& decoded) return true; } -bool Reader::decodeDouble(Token& token) -{ +bool Reader::decodeDouble(Token& token) { Value decoded; - if (!this->decodeDouble(token, decoded)) + if (!decodeDouble(token, decoded)) return false; - this->currentValue().swapPayload(decoded); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); return true; } -bool Reader::decodeDouble(Token& token, Value& decoded) -{ +bool Reader::decodeDouble(Token& token, Value& decoded) { double value = 0; JSONCPP_STRING buffer(token.start_, token.end_); JSONCPP_ISTRINGSTREAM is(buffer); if (!(is >> value)) - return this->addError("'" + JSONCPP_STRING(token.start_, token.end_) + - "' is not a number.", - token); + return addError("'" + JSONCPP_STRING(token.start_, token.end_) + + "' is not a number.", + token); decoded = value; return true; } -bool Reader::decodeString(Token& token) -{ +bool Reader::decodeString(Token& token) { JSONCPP_STRING decoded_string; - if (!this->decodeString(token, decoded_string)) + if (!decodeString(token, decoded_string)) return false; Value decoded(decoded_string); - this->currentValue().swapPayload(decoded); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); return true; } -bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) -{ +bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { decoded.reserve(static_cast(token.end_ - token.start_ - 2)); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' @@ -704,43 +648,41 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) break; else if (c == '\\') { if (current == end) - return this->addError("Empty escape sequence in string", token, - current); + return addError("Empty escape sequence in string", token, current); Char escape = *current++; switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!this->decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return this->addError("Bad escape sequence in string", token, - current); + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); } } else { decoded += c; @@ -749,43 +691,44 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) return true; } -bool Reader::decodeUnicodeCodePoint(Token& token, Location& current, - Location end, unsigned int& unicode) -{ +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { - if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode)) + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; if (unicode >= 0xD800 && unicode <= 0xDBFF) { // surrogate pairs if (end - current < 6) - return this->addError( - "additional six characters expected to parse unicode surrogate pair.", - token, current); + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); unsigned int surrogatePair; if (*(current++) == '\\' && *(current++) == 'u') { - if (this->decodeUnicodeEscapeSequence(token, current, end, - surrogatePair)) { - unicode = - 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else return false; } else - return this->addError( - "expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, current); + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); } return true; } -bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, Location end, - unsigned int& ret_unicode) -{ + unsigned int& ret_unicode) { if (end - current < 4) - return this->addError( - "Bad unicode escape sequence in string: four digits expected.", token, - current); + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); int unicode = 0; for (int index = 0; index < 4; ++index) { Char c = *current++; @@ -797,65 +740,60 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, else if (c >= 'A' && c <= 'F') unicode += c - 'A' + 10; else - return this->addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, current); + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); } ret_unicode = static_cast(unicode); return true; } -bool Reader::addError(const JSONCPP_STRING& message, Token& token, - Location extra) -{ +bool +Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) { ErrorInfo info; info.token_ = token; info.message_ = message; info.extra_ = extra; - this->errors_.push_back(info); + errors_.push_back(info); return false; } -bool Reader::recoverFromError(TokenType skipUntilToken) -{ - size_t const errorCount = this->errors_.size(); +bool Reader::recoverFromError(TokenType skipUntilToken) { + size_t const errorCount = errors_.size(); Token skip; for (;;) { - if (!this->readToken(skip)) - this->errors_.resize(errorCount); // discard errors caused by recovery + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) break; } - this->errors_.resize(errorCount); + errors_.resize(errorCount); return false; } -bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token, - TokenType skipUntilToken) -{ - this->addError(message, token); - return this->recoverFromError(skipUntilToken); +bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); } -Value& Reader::currentValue() -{ - return *(this->nodes_.top()); -} +Value& Reader::currentValue() { return *(nodes_.top()); } -Reader::Char Reader::getNextChar() -{ - if (this->current_ == this->end_) +Reader::Char Reader::getNextChar() { + if (current_ == end_) return 0; - return *this->current_++; + return *current_++; } -void Reader::getLocationLineAndColumn(Location location, int& line, - int& column) const -{ - Location current = this->begin_; +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; Location lastLineStart = current; line = 0; - while (current < location && current != this->end_) { + while (current < location && current != end_) { Char c = *current++; if (c == '\r') { if (*current == '\n') @@ -872,96 +810,91 @@ void Reader::getLocationLineAndColumn(Location location, int& line, ++line; } -JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const -{ +JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const { int line, column; - this->getLocationLineAndColumn(location, line, column); + getLocationLineAndColumn(location, line, column); char buffer[18 + 16 + 16 + 1]; snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); return buffer; } // Deprecated. Preserved for backward compatibility -JSONCPP_STRING Reader::getFormatedErrorMessages() const -{ - return this->getFormattedErrorMessages(); +JSONCPP_STRING Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); } -JSONCPP_STRING Reader::getFormattedErrorMessages() const -{ +JSONCPP_STRING Reader::getFormattedErrorMessages() const { JSONCPP_STRING formattedMessage; - for (Errors::const_iterator itError = this->errors_.begin(); - itError != this->errors_.end(); ++itError) { + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { const ErrorInfo& error = *itError; formattedMessage += - "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n"; + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; if (error.extra_) - formattedMessage += "See " + - this->getLocationLineAndColumn(error.extra_) + " for detail.\n"; + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; } return formattedMessage; } -std::vector Reader::getStructuredErrors() const -{ +std::vector Reader::getStructuredErrors() const { std::vector allErrors; - for (Errors::const_iterator itError = this->errors_.begin(); - itError != this->errors_.end(); ++itError) { + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { const ErrorInfo& error = *itError; Reader::StructuredError structured; - structured.offset_start = error.token_.start_ - this->begin_; - structured.offset_limit = error.token_.end_ - this->begin_; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; structured.message = error.message_; allErrors.push_back(structured); } return allErrors; } -bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) -{ - ptrdiff_t const length = this->end_ - this->begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length) +bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) { + ptrdiff_t const length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; - token.start_ = this->begin_ + value.getOffsetStart(); - token.end_ = this->end_ + value.getOffsetLimit(); + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); ErrorInfo info; info.token_ = token; info.message_ = message; info.extra_ = 0; - this->errors_.push_back(info); + errors_.push_back(info); return true; } -bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, - const Value& extra) -{ - ptrdiff_t const length = this->end_ - this->begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length || - extra.getOffsetLimit() > length) +bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) { + ptrdiff_t const length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length + || extra.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; - token.start_ = this->begin_ + value.getOffsetStart(); - token.end_ = this->begin_ + value.getOffsetLimit(); + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); ErrorInfo info; info.token_ = token; info.message_ = message; - info.extra_ = this->begin_ + extra.getOffsetStart(); - this->errors_.push_back(info); + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); return true; } -bool Reader::good() const -{ - return !this->errors_.size(); +bool Reader::good() const { + return !errors_.size(); } // exact copy of Features -class OurFeatures -{ +class OurFeatures { public: static OurFeatures all(); bool allowComments_; @@ -973,48 +906,43 @@ class OurFeatures bool rejectDupKeys_; bool allowSpecialFloats_; int stackLimit_; -}; // OurFeatures +}; // OurFeatures // exact copy of Implementation of class Features // //////////////////////////////// -OurFeatures OurFeatures::all() -{ - return OurFeatures(); -} +OurFeatures OurFeatures::all() { return OurFeatures(); } // Implementation of class Reader // //////////////////////////////// // exact copy of Reader, renamed to OurReader -class OurReader -{ +class OurReader { public: typedef char Char; typedef const Char* Location; - struct StructuredError - { + struct StructuredError { ptrdiff_t offset_start; ptrdiff_t offset_limit; JSONCPP_STRING message; }; OurReader(OurFeatures const& features); - bool parse(const char* beginDoc, const char* endDoc, Value& root, + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, bool collectComments = true); JSONCPP_STRING getFormattedErrorMessages() const; std::vector getStructuredErrors() const; bool pushError(const Value& value, const JSONCPP_STRING& message); - bool pushError(const Value& value, const JSONCPP_STRING& message, - const Value& extra); + bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra); bool good() const; private: - OurReader(OurReader const&); // no impl - void operator=(OurReader const&); // no impl + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl - enum TokenType - { + enum TokenType { tokenEndOfStream = 0, tokenObjectBegin, tokenObjectEnd, @@ -1034,16 +962,14 @@ class OurReader tokenError }; - class Token - { + class Token { public: TokenType type_; Location start_; Location end_; }; - class ErrorInfo - { + class ErrorInfo { public: Token token_; JSONCPP_STRING message_; @@ -1070,20 +996,24 @@ class OurReader bool decodeString(Token& token, JSONCPP_STRING& decoded); bool decodeDouble(Token& token); bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, Location& current, - Location end, unsigned int& unicode); - bool addError(const JSONCPP_STRING& message, Token& token, - Location extra = 0); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const JSONCPP_STRING& message, Token& token, + bool addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, TokenType skipUntilToken); void skipUntilSpace(); Value& currentValue(); Char getNextChar(); - void getLocationLineAndColumn(Location location, int& line, - int& column) const; + void + getLocationLineAndColumn(Location location, int& line, int& column) const; JSONCPP_STRING getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); void skipCommentTokens(Token& token); @@ -1104,13 +1034,11 @@ class OurReader OurFeatures const features_; bool collectComments_; -}; // OurReader +}; // OurReader // complete copy of Read impl, for OurReader -bool OurReader::containsNewLine(OurReader::Location begin, - OurReader::Location end) -{ +bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) { for (; begin < end; ++begin) if (*begin == '\n' || *begin == '\r') return true; @@ -1118,322 +1046,315 @@ bool OurReader::containsNewLine(OurReader::Location begin, } OurReader::OurReader(OurFeatures const& features) - : errors_() - , document_() - , begin_() - , end_() - , current_() - , lastValueEnd_() - , lastValue_() - , commentsBefore_() - , features_(features) - , collectComments_() -{ + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), + features_(features), collectComments_() { } -bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root, - bool collectComments) -{ - if (!this->features_.allowComments_) { +bool OurReader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { collectComments = false; } - this->begin_ = beginDoc; - this->end_ = endDoc; - this->collectComments_ = collectComments; - this->current_ = this->begin_; - this->lastValueEnd_ = 0; - this->lastValue_ = 0; - this->commentsBefore_.clear(); - this->errors_.clear(); - while (!this->nodes_.empty()) - this->nodes_.pop(); - this->nodes_.push(&root); - - bool successful = this->readValue(); + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); Token token; - this->skipCommentTokens(token); - if (this->features_.failIfExtra_) { - if ((this->features_.strictRoot_ || token.type_ != tokenError) && - token.type_ != tokenEndOfStream) { - this->addError("Extra non-whitespace after JSON value.", token); + skipCommentTokens(token); + if (features_.failIfExtra_) { + if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) { + addError("Extra non-whitespace after JSON value.", token); return false; } } - if (this->collectComments_ && !this->commentsBefore_.empty()) - root.setComment(this->commentsBefore_, commentAfter); - if (this->features_.strictRoot_) { + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token - // found in doc + // Set error location to start of doc, ideally should be first token found + // in doc token.type_ = tokenError; token.start_ = beginDoc; token.end_ = endDoc; - this->addError( - "A valid JSON document must be either an array or an object value.", - token); + addError( + "A valid JSON document must be either an array or an object value.", + token); return false; } } return successful; } -bool OurReader::readValue() -{ +bool OurReader::readValue() { // To preserve the old behaviour we cast size_t to int. - if (static_cast(this->nodes_.size()) > this->features_.stackLimit_) - throwRuntimeError("Exceeded stackLimit in readValue()."); + if (static_cast(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; - this->skipCommentTokens(token); + skipCommentTokens(token); bool successful = true; - if (this->collectComments_ && !this->commentsBefore_.empty()) { - this->currentValue().setComment(this->commentsBefore_, commentBefore); - this->commentsBefore_.clear(); + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); } switch (token.type_) { - case tokenObjectBegin: - successful = this->readObject(token); - this->currentValue().setOffsetLimit(this->current_ - this->begin_); - break; - case tokenArrayBegin: - successful = this->readArray(token); - this->currentValue().setOffsetLimit(this->current_ - this->begin_); - break; - case tokenNumber: - successful = this->decodeNumber(token); - break; - case tokenString: - successful = this->decodeString(token); - break; - case tokenTrue: { - Value v(true); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenFalse: { - Value v(false); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenNull: { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNaN: + { + Value v(std::numeric_limits::quiet_NaN()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenPosInf: + { + Value v(std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNegInf: + { + Value v(-std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; Value v; - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenNaN: { - Value v(std::numeric_limits::quiet_NaN()); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenPosInf: { - Value v(std::numeric_limits::infinity()); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenNegInf: { - Value v(-std::numeric_limits::infinity()); - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - } break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (this->features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - this->current_--; - Value v; - this->currentValue().swapPayload(v); - this->currentValue().setOffsetStart(this->current_ - this->begin_ - 1); - this->currentValue().setOffsetLimit(this->current_ - this->begin_); - break; - } // else, fall through ... - default: - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); - return this->addError("Syntax error: value, object or array expected.", - token); + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // else, fall through ... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); } - if (this->collectComments_) { - this->lastValueEnd_ = this->current_; - this->lastValue_ = &this->currentValue(); + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); } return successful; } -void OurReader::skipCommentTokens(Token& token) -{ - if (this->features_.allowComments_) { +void OurReader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { do { - this->readToken(token); + readToken(token); } while (token.type_ == tokenComment); } else { - this->readToken(token); + readToken(token); } } -bool OurReader::readToken(Token& token) -{ - this->skipSpaces(); - token.start_ = this->current_; - Char c = this->getNextChar(); +bool OurReader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); bool ok = true; switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = this->readString(); - break; - case '\'': - if (this->features_.allowSingleQuotes_) { - token.type_ = tokenString; - ok = this->readStringSingleQuote(); - break; - } // else continue - case '/': - token.type_ = tokenComment; - ok = this->readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + break; + } // else continue + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token.type_ = tokenNumber; + readNumber(false); + break; + case '-': + if (readNumber(true)) { token.type_ = tokenNumber; - this->readNumber(false); - break; - case '-': - if (this->readNumber(true)) { - token.type_ = tokenNumber; - } else { - token.type_ = tokenNegInf; - ok = this->features_.allowSpecialFloats_ && this->match("nfinity", 7); - } - break; - case 't': - token.type_ = tokenTrue; - ok = this->match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = this->match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = this->match("ull", 3); - break; - case 'N': - if (this->features_.allowSpecialFloats_) { - token.type_ = tokenNaN; - ok = this->match("aN", 2); - } else { - ok = false; - } - break; - case 'I': - if (this->features_.allowSpecialFloats_) { - token.type_ = tokenPosInf; - ok = this->match("nfinity", 7); - } else { - ok = false; - } - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: + } else { + token.type_ = tokenNegInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case 'N': + if (features_.allowSpecialFloats_) { + token.type_ = tokenNaN; + ok = match("aN", 2); + } else { ok = false; - break; + } + break; + case 'I': + if (features_.allowSpecialFloats_) { + token.type_ = tokenPosInf; + ok = match("nfinity", 7); + } else { + ok = false; + } + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; } if (!ok) token.type_ = tokenError; - token.end_ = this->current_; + token.end_ = current_; return true; } -void OurReader::skipSpaces() -{ - while (this->current_ != this->end_) { - Char c = *this->current_; +void OurReader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++this->current_; + ++current_; else break; } } -bool OurReader::match(Location pattern, int patternLength) -{ - if (this->end_ - this->current_ < patternLength) +bool OurReader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) return false; int index = patternLength; while (index--) - if (this->current_[index] != pattern[index]) + if (current_[index] != pattern[index]) return false; - this->current_ += patternLength; + current_ += patternLength; return true; } -bool OurReader::readComment() -{ - Location commentBegin = this->current_ - 1; - Char c = this->getNextChar(); +bool OurReader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); bool successful = false; if (c == '*') - successful = this->readCStyleComment(); + successful = readCStyleComment(); else if (c == '/') - successful = this->readCppStyleComment(); + successful = readCppStyleComment(); if (!successful) return false; - if (this->collectComments_) { + if (collectComments_) { CommentPlacement placement = commentBefore; - if (this->lastValueEnd_ && - !containsNewLine(this->lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, this->current_)) + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) placement = commentAfterOnSameLine; } - this->addComment(commentBegin, this->current_, placement); + addComment(commentBegin, current_, placement); } return true; } -JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, - OurReader::Location end) -{ +JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) { JSONCPP_STRING normalized; normalized.reserve(static_cast(end - begin)); OurReader::Location current = begin; @@ -1441,8 +1362,8 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, char c = *current++; if (c == '\r') { if (current != end && *current == '\n') - // convert dos EOL - ++current; + // convert dos EOL + ++current; // convert Mac EOL normalized += '\n'; } else { @@ -1452,39 +1373,36 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, return normalized; } -void OurReader::addComment(Location begin, Location end, - CommentPlacement placement) -{ - assert(this->collectComments_); +void +OurReader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); const JSONCPP_STRING& normalized = normalizeEOL(begin, end); if (placement == commentAfterOnSameLine) { - assert(this->lastValue_ != 0); - this->lastValue_->setComment(normalized, placement); + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); } else { - this->commentsBefore_ += normalized; + commentsBefore_ += normalized; } } -bool OurReader::readCStyleComment() -{ - while ((this->current_ + 1) < this->end_) { - Char c = this->getNextChar(); - if (c == '*' && *this->current_ == '/') +bool OurReader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') break; } - return this->getNextChar() == '/'; + return getNextChar() == '/'; } -bool OurReader::readCppStyleComment() -{ - while (this->current_ != this->end_) { - Char c = this->getNextChar(); +bool OurReader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); if (c == '\n') break; if (c == '\r') { // Consume DOS EOL. It will be normalized in addComment. - if (this->current_ != this->end_ && *this->current_ == '\n') - this->getNextChar(); + if (current_ != end_ && *current_ == '\n') + getNextChar(); // Break on Moc OS 9 EOL. break; } @@ -1492,156 +1410,150 @@ bool OurReader::readCppStyleComment() return true; } -bool OurReader::readNumber(bool checkInf) -{ - const char* p = this->current_; - if (checkInf && p != this->end_ && *p == 'I') { - this->current_ = ++p; +bool OurReader::readNumber(bool checkInf) { + const char *p = current_; + if (checkInf && p != end_ && *p == 'I') { + current_ = ++p; return false; } char c = '0'; // stopgap for already consumed character // integral part while (c >= '0' && c <= '9') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; // fractional part if (c == '.') { - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; while (c >= '0' && c <= '9') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; } // exponential part if (c == 'e' || c == 'E') { - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; if (c == '+' || c == '-') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; while (c >= '0' && c <= '9') - c = (this->current_ = p) < this->end_ ? *p++ : '\0'; + c = (current_ = p) < end_ ? *p++ : '\0'; } return true; } -bool OurReader::readString() -{ +bool OurReader::readString() { Char c = 0; - while (this->current_ != this->end_) { - c = this->getNextChar(); + while (current_ != end_) { + c = getNextChar(); if (c == '\\') - this->getNextChar(); + getNextChar(); else if (c == '"') break; } return c == '"'; } -bool OurReader::readStringSingleQuote() -{ + +bool OurReader::readStringSingleQuote() { Char c = 0; - while (this->current_ != this->end_) { - c = this->getNextChar(); + while (current_ != end_) { + c = getNextChar(); if (c == '\\') - this->getNextChar(); + getNextChar(); else if (c == '\'') break; } return c == '\''; } -bool OurReader::readObject(Token& tokenStart) -{ +bool OurReader::readObject(Token& tokenStart) { Token tokenName; JSONCPP_STRING name; Value init(objectValue); - this->currentValue().swapPayload(init); - this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_); - while (this->readToken(tokenName)) { + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + while (readToken(tokenName)) { bool initialTokenOk = true; while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = this->readToken(tokenName); + initialTokenOk = readToken(tokenName); if (!initialTokenOk) break; if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object return true; name.clear(); if (tokenName.type_ == tokenString) { - if (!this->decodeString(tokenName, name)) - return this->recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && - this->features_.allowNumericKeys_) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { Value numberName; - if (!this->decodeNumber(tokenName, numberName)) - return this->recoverFromError(tokenObjectEnd); + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); name = numberName.asString(); } else { break; } Token colon; - if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) { - return this->addErrorAndRecover("Missing ':' after object member name", - colon, tokenObjectEnd); + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); } - if (name.length() >= (1U << 30)) - throwRuntimeError("keylength >= 2^30"); - if (this->features_.rejectDupKeys_ && - this->currentValue().isMember(name)) { + if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { JSONCPP_STRING msg = "Duplicate key: '" + name + "'"; - return this->addErrorAndRecover(msg, tokenName, tokenObjectEnd); + return addErrorAndRecover( + msg, tokenName, tokenObjectEnd); } - Value& value = this->currentValue()[name]; - this->nodes_.push(&value); - bool ok = this->readValue(); - this->nodes_.pop(); + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); if (!ok) // error already set - return this->recoverFromError(tokenObjectEnd); + return recoverFromError(tokenObjectEnd); Token comma; - if (!this->readToken(comma) || + if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return this->addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); } bool finalizeTokenOk = true; while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = this->readToken(comma); + finalizeTokenOk = readToken(comma); if (comma.type_ == tokenObjectEnd) return true; } - return this->addErrorAndRecover("Missing '}' or object member name", - tokenName, tokenObjectEnd); + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); } -bool OurReader::readArray(Token& tokenStart) -{ +bool OurReader::readArray(Token& tokenStart) { Value init(arrayValue); - this->currentValue().swapPayload(init); - this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_); - this->skipSpaces(); - if (this->current_ != this->end_ && *this->current_ == ']') // empty array + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array { Token endArray; - this->readToken(endArray); + readToken(endArray); return true; } int index = 0; for (;;) { - Value& value = this->currentValue()[index++]; - this->nodes_.push(&value); - bool ok = this->readValue(); - this->nodes_.pop(); + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); if (!ok) // error already set - return this->recoverFromError(tokenArrayEnd); + return recoverFromError(tokenArrayEnd); Token token; // Accept Comment after last item in the array. - ok = this->readToken(token); + ok = readToken(token); while (token.type_ == tokenComment && ok) { - ok = this->readToken(token); + ok = readToken(token); } bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return this->addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); } if (token.type_ == tokenArrayEnd) break; @@ -1649,19 +1561,17 @@ bool OurReader::readArray(Token& tokenStart) return true; } -bool OurReader::decodeNumber(Token& token) -{ +bool OurReader::decodeNumber(Token& token) { Value decoded; - if (!this->decodeNumber(token, decoded)) + if (!decodeNumber(token, decoded)) return false; - this->currentValue().swapPayload(decoded); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); return true; } -bool OurReader::decodeNumber(Token& token, Value& decoded) -{ +bool OurReader::decodeNumber(Token& token, Value& decoded) { // Attempts to parse the number as an integer. If the number is // larger than the maximum supported value of an integer then // we decode the number as a double. @@ -1669,17 +1579,16 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) bool isNegative = *current == '-'; if (isNegative) ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of - // them. - Value::LargestUInt maxIntegerValue = isNegative - ? Value::LargestUInt(Value::minLargestInt) - : Value::maxLargestUInt; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::minLargestInt) + : Value::maxLargestUInt; Value::LargestUInt threshold = maxIntegerValue / 10; Value::LargestUInt value = 0; while (current < token.end_) { Char c = *current++; if (c < '0' || c > '9') - return this->decodeDouble(token, decoded); + return decodeDouble(token, decoded); Value::UInt digit(static_cast(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If @@ -1688,7 +1597,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) // Otherwise treat this number as a double to avoid overflow. if (value > threshold || current != token.end_ || digit > maxIntegerValue % 10) { - return this->decodeDouble(token, decoded); + return decodeDouble(token, decoded); } } value = value * 10 + digit; @@ -1702,19 +1611,17 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) return true; } -bool OurReader::decodeDouble(Token& token) -{ +bool OurReader::decodeDouble(Token& token) { Value decoded; - if (!this->decodeDouble(token, decoded)) + if (!decodeDouble(token, decoded)) return false; - this->currentValue().swapPayload(decoded); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); return true; } -bool OurReader::decodeDouble(Token& token, Value& decoded) -{ +bool OurReader::decodeDouble(Token& token, Value& decoded) { double value = 0; const int bufferSize = 32; int count; @@ -1722,7 +1629,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) // Sanity check to avoid buffer overflow exploits. if (length < 0) { - return this->addError("Unable to parse token length", token); + return addError("Unable to parse token length", token); } size_t const ulength = static_cast(length); @@ -1745,27 +1652,25 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) } if (count != 1) - return this->addError("'" + JSONCPP_STRING(token.start_, token.end_) + - "' is not a number.", - token); + return addError("'" + JSONCPP_STRING(token.start_, token.end_) + + "' is not a number.", + token); decoded = value; return true; } -bool OurReader::decodeString(Token& token) -{ +bool OurReader::decodeString(Token& token) { JSONCPP_STRING decoded_string; - if (!this->decodeString(token, decoded_string)) + if (!decodeString(token, decoded_string)) return false; Value decoded(decoded_string); - this->currentValue().swapPayload(decoded); - this->currentValue().setOffsetStart(token.start_ - this->begin_); - this->currentValue().setOffsetLimit(token.end_ - this->begin_); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); return true; } -bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) -{ +bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { decoded.reserve(static_cast(token.end_ - token.start_ - 2)); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' @@ -1775,43 +1680,41 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) break; else if (c == '\\') { if (current == end) - return this->addError("Empty escape sequence in string", token, - current); + return addError("Empty escape sequence in string", token, current); Char escape = *current++; switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!this->decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return this->addError("Bad escape sequence in string", token, - current); + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); } } else { decoded += c; @@ -1820,44 +1723,45 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) return true; } -bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current, - Location end, unsigned int& unicode) -{ +bool OurReader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { unicode = 0; // Convince scanbuild this is always initialized before use. - if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode)) + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; if (unicode >= 0xD800 && unicode <= 0xDBFF) { // surrogate pairs if (end - current < 6) - return this->addError( - "additional six characters expected to parse unicode surrogate pair.", - token, current); + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); unsigned int surrogatePair; if (*(current++) == '\\' && *(current++) == 'u') { - if (this->decodeUnicodeEscapeSequence(token, current, end, - surrogatePair)) { - unicode = - 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else return false; } else - return this->addError( - "expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, current); + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); } return true; } -bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current, - Location end, - unsigned int& ret_unicode) -{ +bool OurReader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& ret_unicode) { if (end - current < 4) - return this->addError( - "Bad unicode escape sequence in string: four digits expected.", token, - current); + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); int unicode = 0; for (int index = 0; index < 4; ++index) { Char c = *current++; @@ -1869,65 +1773,60 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current, else if (c >= 'A' && c <= 'F') unicode += c - 'A' + 10; else - return this->addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, current); + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); } ret_unicode = static_cast(unicode); return true; } -bool OurReader::addError(const JSONCPP_STRING& message, Token& token, - Location extra) -{ +bool +OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) { ErrorInfo info; info.token_ = token; info.message_ = message; info.extra_ = extra; - this->errors_.push_back(info); + errors_.push_back(info); return false; } -bool OurReader::recoverFromError(TokenType skipUntilToken) -{ - size_t errorCount = this->errors_.size(); +bool OurReader::recoverFromError(TokenType skipUntilToken) { + size_t errorCount = errors_.size(); Token skip; for (;;) { - if (!this->readToken(skip)) - this->errors_.resize(errorCount); // discard errors caused by recovery + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) break; } - this->errors_.resize(errorCount); + errors_.resize(errorCount); return false; } -bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token, - TokenType skipUntilToken) -{ - this->addError(message, token); - return this->recoverFromError(skipUntilToken); +bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); } -Value& OurReader::currentValue() -{ - return *(this->nodes_.top()); -} +Value& OurReader::currentValue() { return *(nodes_.top()); } -OurReader::Char OurReader::getNextChar() -{ - if (this->current_ == this->end_) +OurReader::Char OurReader::getNextChar() { + if (current_ == end_) return 0; - return *this->current_++; + return *current_++; } -void OurReader::getLocationLineAndColumn(Location location, int& line, - int& column) const -{ - Location current = this->begin_; +void OurReader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; Location lastLineStart = current; line = 0; - while (current < location && current != this->end_) { + while (current < location && current != end_) { Char c = *current++; if (c == '\r') { if (*current == '\n') @@ -1944,105 +1843,101 @@ void OurReader::getLocationLineAndColumn(Location location, int& line, ++line; } -JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const -{ +JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const { int line, column; - this->getLocationLineAndColumn(location, line, column); + getLocationLineAndColumn(location, line, column); char buffer[18 + 16 + 16 + 1]; snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); return buffer; } -JSONCPP_STRING OurReader::getFormattedErrorMessages() const -{ +JSONCPP_STRING OurReader::getFormattedErrorMessages() const { JSONCPP_STRING formattedMessage; - for (Errors::const_iterator itError = this->errors_.begin(); - itError != this->errors_.end(); ++itError) { + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { const ErrorInfo& error = *itError; formattedMessage += - "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n"; + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; if (error.extra_) - formattedMessage += "See " + - this->getLocationLineAndColumn(error.extra_) + " for detail.\n"; + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; } return formattedMessage; } -std::vector OurReader::getStructuredErrors() const -{ +std::vector OurReader::getStructuredErrors() const { std::vector allErrors; - for (Errors::const_iterator itError = this->errors_.begin(); - itError != this->errors_.end(); ++itError) { + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { const ErrorInfo& error = *itError; OurReader::StructuredError structured; - structured.offset_start = error.token_.start_ - this->begin_; - structured.offset_limit = error.token_.end_ - this->begin_; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; structured.message = error.message_; allErrors.push_back(structured); } return allErrors; } -bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) -{ - ptrdiff_t length = this->end_ - this->begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length) +bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) { + ptrdiff_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; - token.start_ = this->begin_ + value.getOffsetStart(); - token.end_ = this->end_ + value.getOffsetLimit(); + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); ErrorInfo info; info.token_ = token; info.message_ = message; info.extra_ = 0; - this->errors_.push_back(info); + errors_.push_back(info); return true; } -bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, - const Value& extra) -{ - ptrdiff_t length = this->end_ - this->begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length || - extra.getOffsetLimit() > length) +bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) { + ptrdiff_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length + || extra.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; - token.start_ = this->begin_ + value.getOffsetStart(); - token.end_ = this->begin_ + value.getOffsetLimit(); + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); ErrorInfo info; info.token_ = token; info.message_ = message; - info.extra_ = this->begin_ + extra.getOffsetStart(); - this->errors_.push_back(info); + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); return true; } -bool OurReader::good() const -{ - return !this->errors_.size(); +bool OurReader::good() const { + return !errors_.size(); } -class OurCharReader : public CharReader -{ + +class OurCharReader : public CharReader { bool const collectComments_; OurReader reader_; - public: - OurCharReader(bool collectComments, OurFeatures const& features) - : collectComments_(collectComments) - , reader_(features) - { - } - bool parse(char const* beginDoc, char const* endDoc, Value* root, - JSONCPP_STRING* errs) JSONCPP_OVERRIDE - { - bool ok = - this->reader_.parse(beginDoc, endDoc, *root, this->collectComments_); + OurCharReader( + bool collectComments, + OurFeatures const& features) + : collectComments_(collectComments) + , reader_(features) + {} + bool parse( + char const* beginDoc, char const* endDoc, + Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); if (errs) { - *errs = this->reader_.getFormattedErrorMessages(); + *errs = reader_.getFormattedErrorMessages(); } return ok; } @@ -2050,26 +1945,23 @@ class OurCharReader : public CharReader CharReaderBuilder::CharReaderBuilder() { - setDefaults(&this->settings_); + setDefaults(&settings_); } CharReaderBuilder::~CharReaderBuilder() -{ -} +{} CharReader* CharReaderBuilder::newCharReader() const { - bool collectComments = this->settings_["collectComments"].asBool(); + bool collectComments = settings_["collectComments"].asBool(); OurFeatures features = OurFeatures::all(); - features.allowComments_ = this->settings_["allowComments"].asBool(); - features.strictRoot_ = this->settings_["strictRoot"].asBool(); - features.allowDroppedNullPlaceholders_ = - this->settings_["allowDroppedNullPlaceholders"].asBool(); - features.allowNumericKeys_ = this->settings_["allowNumericKeys"].asBool(); - features.allowSingleQuotes_ = this->settings_["allowSingleQuotes"].asBool(); - features.stackLimit_ = this->settings_["stackLimit"].asInt(); - features.failIfExtra_ = this->settings_["failIfExtra"].asBool(); - features.rejectDupKeys_ = this->settings_["rejectDupKeys"].asBool(); - features.allowSpecialFloats_ = - this->settings_["allowSpecialFloats"].asBool(); + features.allowComments_ = settings_["allowComments"].asBool(); + features.strictRoot_ = settings_["strictRoot"].asBool(); + features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); + features.stackLimit_ = settings_["stackLimit"].asInt(); + features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); + features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); return new OurCharReader(collectComments, features); } static void getValidReaderKeys(std::set* valid_keys) @@ -2089,29 +1981,28 @@ static void getValidReaderKeys(std::set* valid_keys) bool CharReaderBuilder::validate(Json::Value* invalid) const { Json::Value my_invalid; - if (!invalid) - invalid = &my_invalid; // so we do not need to test for NULL + if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL Json::Value& inv = *invalid; std::set valid_keys; getValidReaderKeys(&valid_keys); - Value::Members keys = this->settings_.getMemberNames(); + Value::Members keys = settings_.getMemberNames(); size_t n = keys.size(); for (size_t i = 0; i < n; ++i) { JSONCPP_STRING const& key = keys[i]; if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = this->settings_[key]; + inv[key] = settings_[key]; } } return 0u == inv.size(); } Value& CharReaderBuilder::operator[](JSONCPP_STRING key) { - return this->settings_[key]; + return settings_[key]; } // static void CharReaderBuilder::strictMode(Json::Value* settings) { - //! [CharReaderBuilderStrictMode] +//! [CharReaderBuilderStrictMode] (*settings)["allowComments"] = false; (*settings)["strictRoot"] = true; (*settings)["allowDroppedNullPlaceholders"] = false; @@ -2121,12 +2012,12 @@ void CharReaderBuilder::strictMode(Json::Value* settings) (*settings)["failIfExtra"] = true; (*settings)["rejectDupKeys"] = true; (*settings)["allowSpecialFloats"] = false; - //! [CharReaderBuilderStrictMode] +//! [CharReaderBuilderStrictMode] } // static void CharReaderBuilder::setDefaults(Json::Value* settings) { - //! [CharReaderBuilderDefaults] +//! [CharReaderBuilderDefaults] (*settings)["collectComments"] = true; (*settings)["allowComments"] = true; (*settings)["strictRoot"] = false; @@ -2137,14 +2028,15 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) (*settings)["failIfExtra"] = false; (*settings)["rejectDupKeys"] = false; (*settings)["allowSpecialFloats"] = false; - //! [CharReaderBuilderDefaults] +//! [CharReaderBuilderDefaults] } ////////////////////////////////// // global functions -bool parseFromStream(CharReader::Factory const& fact, JSONCPP_ISTREAM& sin, - Value* root, JSONCPP_STRING* errs) +bool parseFromStream( + CharReader::Factory const& fact, JSONCPP_ISTREAM& sin, + Value* root, JSONCPP_STRING* errs) { JSONCPP_OSTRINGSTREAM ssin; ssin << sin.rdbuf(); @@ -2156,13 +2048,14 @@ bool parseFromStream(CharReader::Factory const& fact, JSONCPP_ISTREAM& sin, return reader->parse(begin, end, root, errs); } -JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) -{ +JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) { CharReaderBuilder b; JSONCPP_STRING errs; bool ok = parseFromStream(b, sin, &root, &errs); if (!ok) { - fprintf(stderr, "Error from reader: %s", errs.c_str()); + fprintf(stderr, + "Error from reader: %s", + errs.c_str()); throwRuntimeError(errs); } diff --git a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp index eadb1c375e3..f271e5731f5 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp @@ -1,25 +1,23 @@ // Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. -// See file LICENSE for detail or copy at -// http://jsoncpp.sourceforge.net/LICENSE +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) -# include -# include -# include +#include +#include +#include #endif // if !defined(JSON_IS_AMALGAMATION) +#include #include #include - -#include -#include #include +#include #ifdef JSON_USE_CPPTL -# include +#include #endif +#include // size_t #include // min() -#include // size_t #define JSON_ASSERT_UNREACHABLE assert(false) @@ -29,24 +27,24 @@ namespace Json { // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of // 8 (instead of 4) as a bit of future-proofing. #if defined(__ARMEL__) -# define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) #else -# define ALIGNAS(byte_alignment) +#define ALIGNAS(byte_alignment) #endif -// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -// const unsigned char& kNullRef = kNull[0]; -// const Value& Value::null = reinterpret_cast(kNullRef); -// const Value& Value::nullRef = null; +//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +//const unsigned char& kNullRef = kNull[0]; +//const Value& Value::null = reinterpret_cast(kNullRef); +//const Value& Value::nullRef = null; // static Value const& Value::nullSingleton() { - static Value const nullStatic; - return nullStatic; + static Value const nullStatic; + return nullStatic; } -// for backwards compatibility, we'll leave these global references around, but -// DO NOT use them in JSONCPP library code any more! +// for backwards compatibility, we'll leave these global references around, but DO NOT +// use them in JSONCPP library code any more! Value const& Value::null = Value::nullSingleton(); Value const& Value::nullRef = Value::nullSingleton(); @@ -68,29 +66,23 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1); #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) template -static inline bool InRange(double d, T min, U max) -{ +static inline bool InRange(double d, T min, U max) { // The casts can lose precision, but we are looking only for // an approximate range. Might fail on edge cases though. ~cdunn - // return d >= static_cast(min) && d <= static_cast(max); + //return d >= static_cast(min) && d <= static_cast(max); return d >= min && d <= max; } #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double integerToDouble(Json::UInt64 value) -{ - return static_cast(Int64(value / 2)) * 2.0 + - static_cast(Int64(value & 1)); +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + static_cast(Int64(value & 1)); } -template -static inline double integerToDouble(T value) -{ +template static inline double integerToDouble(T value) { return static_cast(value); } template -static inline bool InRange(double d, T min, U max) -{ +static inline bool InRange(double d, T min, U max) { return d >= integerToDouble(min) && d <= integerToDouble(max); } #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) @@ -102,7 +94,8 @@ static inline bool InRange(double d, T min, U max) * computed using strlen(value). * @return Pointer on the duplicate instance of string. */ -static inline char* duplicateStringValue(const char* value, size_t length) +static inline char* duplicateStringValue(const char* value, + size_t length) { // Avoid an integer overflow in the call to malloc below by limiting length // to a sane value. @@ -111,8 +104,9 @@ static inline char* duplicateStringValue(const char* value, size_t length) char* newString = static_cast(malloc(length + 1)); if (newString == NULL) { - throwRuntimeError("in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); + throwRuntimeError( + "in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); } memcpy(newString, value, length); newString[length] = 0; @@ -121,30 +115,30 @@ static inline char* duplicateStringValue(const char* value, size_t length) /* Record the length as a prefix. */ -static inline char* duplicateAndPrefixStringValue(const char* value, - unsigned int length) +static inline char* duplicateAndPrefixStringValue( + const char* value, + unsigned int length) { // Avoid an integer overflow in the call to malloc below by limiting length // to a sane value. - JSON_ASSERT_MESSAGE(length <= static_cast(Value::maxInt) - - sizeof(unsigned) - 1U, + JSON_ASSERT_MESSAGE(length <= static_cast(Value::maxInt) - sizeof(unsigned) - 1U, "in Json::Value::duplicateAndPrefixStringValue(): " "length too big for prefixing"); - unsigned actualLength = - length + static_cast(sizeof(unsigned)) + 1U; + unsigned actualLength = length + static_cast(sizeof(unsigned)) + 1U; char* newString = static_cast(malloc(actualLength)); if (newString == 0) { - throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " - "Failed to allocate string value buffer"); + throwRuntimeError( + "in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); } *reinterpret_cast(newString) = length; memcpy(newString + sizeof(unsigned), value, length); - newString[actualLength - 1U] = - 0; // to avoid buffer over-run accidents by users later + newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later return newString; } -inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, - unsigned* length, char const** value) +inline static void decodePrefixedString( + bool isPrefixed, char const* prefixed, + unsigned* length, char const** value) { if (!isPrefixed) { *length = static_cast(strlen(prefixed)); @@ -154,12 +148,10 @@ inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, *value = prefixed + sizeof(unsigned); } } -/** Free the string duplicated by - * duplicateStringValue()/duplicateAndPrefixStringValue(). +/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). */ #if JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) -{ +static inline void releasePrefixedStringValue(char* value) { unsigned length = 0; char const* valueDecoded; decodePrefixedString(true, value, &length, &valueDecoded); @@ -167,20 +159,17 @@ static inline void releasePrefixedStringValue(char* value) memset(value, 0, size); free(value); } -static inline void releaseStringValue(char* value, unsigned length) -{ +static inline void releaseStringValue(char* value, unsigned length) { // length==0 => we allocated the strings memory - size_t size = (length == 0) ? strlen(value) : length; + size_t size = (length==0) ? strlen(value) : length; memset(value, 0, size); free(value); } -#else // !JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) -{ +#else // !JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { free(value); } -static inline void releaseStringValue(char* value, unsigned) -{ +static inline void releaseStringValue(char* value, unsigned) { free(value); } #endif // JSONCPP_USING_SECURE_MEMORY @@ -196,30 +185,26 @@ static inline void releaseStringValue(char* value, unsigned) // ////////////////////////////////////////////////////////////////// #if !defined(JSON_IS_AMALGAMATION) -# include "json_valueiterator.inl" +#include "json_valueiterator.inl" #endif // if !defined(JSON_IS_AMALGAMATION) namespace Json { Exception::Exception(JSONCPP_STRING const& msg) : msg_(msg) -{ -} +{} Exception::~Exception() JSONCPP_NOEXCEPT -{ -} +{} char const* Exception::what() const JSONCPP_NOEXCEPT { - return this->msg_.c_str(); + return msg_.c_str(); } RuntimeError::RuntimeError(JSONCPP_STRING const& msg) : Exception(msg) -{ -} +{} LogicError::LogicError(JSONCPP_STRING const& msg) : Exception(msg) -{ -} +{} JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg) { throw RuntimeError(msg); @@ -237,29 +222,25 @@ JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg) // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -Value::CommentInfo::CommentInfo() - : comment_(0) -{ -} +Value::CommentInfo::CommentInfo() : comment_(0) +{} -Value::CommentInfo::~CommentInfo() -{ - if (this->comment_) - releaseStringValue(this->comment_, 0u); +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_, 0u); } -void Value::CommentInfo::setComment(const char* text, size_t len) -{ - if (this->comment_) { - releaseStringValue(this->comment_, 0u); - this->comment_ = 0; +void Value::CommentInfo::setComment(const char* text, size_t len) { + if (comment_) { + releaseStringValue(comment_, 0u); + comment_ = 0; } JSON_ASSERT(text != 0); JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); // It seems that /**/ style comments are acceptable as well. - this->comment_ = duplicateStringValue(text, len); + comment_ = duplicateStringValue(text, len); } // ////////////////////////////////////////////////////////////////// @@ -273,130 +254,91 @@ void Value::CommentInfo::setComment(const char* text, size_t len) // Notes: policy_ indicates if the string was allocated when // a string is stored. -Value::CZString::CZString(ArrayIndex aindex) - : cstr_(0) - , index_(aindex) -{ -} +Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} -Value::CZString::CZString(char const* str, unsigned ulength, - DuplicationPolicy allocate) - : cstr_(str) -{ +Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) + : cstr_(str) { // allocate != duplicate - this->storage_.policy_ = allocate & 0x3; - this->storage_.length_ = ulength & 0x3FFFFFFF; + storage_.policy_ = allocate & 0x3; + storage_.length_ = ulength & 0x3FFFFFFF; } -Value::CZString::CZString(const CZString& other) -{ - this->cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue(other.cstr_, other.storage_.length_) - : other.cstr_); - this->storage_.policy_ = - static_cast( - other.cstr_ ? (static_cast(other.storage_.policy_) == - noDuplication - ? noDuplication - : duplicate) - : static_cast(other.storage_.policy_)) & - 3U; - this->storage_.length_ = other.storage_.length_; +Value::CZString::CZString(const CZString& other) { + cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_); + storage_.policy_ = static_cast(other.cstr_ + ? (static_cast(other.storage_.policy_) == noDuplication + ? noDuplication : duplicate) + : static_cast(other.storage_.policy_)) & 3U; + storage_.length_ = other.storage_.length_; } #if JSON_HAS_RVALUE_REFERENCES Value::CZString::CZString(CZString&& other) - : cstr_(other.cstr_) - , index_(other.index_) -{ + : cstr_(other.cstr_), index_(other.index_) { other.cstr_ = nullptr; } #endif -Value::CZString::~CZString() -{ - if (this->cstr_ && this->storage_.policy_ == duplicate) { - releaseStringValue(const_cast(this->cstr_), - this->storage_.length_ + - 1u); //+1 for null terminating character for sake of - //completeness but not actually necessary +Value::CZString::~CZString() { + if (cstr_ && storage_.policy_ == duplicate) { + releaseStringValue(const_cast(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary } } -void Value::CZString::swap(CZString& other) -{ - std::swap(this->cstr_, other.cstr_); - std::swap(this->index_, other.index_); +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); } -Value::CZString& Value::CZString::operator=(const CZString& other) -{ - this->cstr_ = other.cstr_; - this->index_ = other.index_; +Value::CZString& Value::CZString::operator=(const CZString& other) { + cstr_ = other.cstr_; + index_ = other.index_; return *this; } #if JSON_HAS_RVALUE_REFERENCES -Value::CZString& Value::CZString::operator=(CZString&& other) -{ - this->cstr_ = other.cstr_; - this->index_ = other.index_; +Value::CZString& Value::CZString::operator=(CZString&& other) { + cstr_ = other.cstr_; + index_ = other.index_; other.cstr_ = nullptr; return *this; } #endif -bool Value::CZString::operator<(const CZString& other) const -{ - if (!this->cstr_) - return this->index_ < other.index_; - // return strcmp(cstr_, other.cstr_) < 0; +bool Value::CZString::operator<(const CZString& other) const { + if (!cstr_) return index_ < other.index_; + //return strcmp(cstr_, other.cstr_) < 0; // Assume both are strings. unsigned this_len = this->storage_.length_; unsigned other_len = other.storage_.length_; unsigned min_len = std::min(this_len, other_len); JSON_ASSERT(this->cstr_ && other.cstr_); int comp = memcmp(this->cstr_, other.cstr_, min_len); - if (comp < 0) - return true; - if (comp > 0) - return false; + if (comp < 0) return true; + if (comp > 0) return false; return (this_len < other_len); } -bool Value::CZString::operator==(const CZString& other) const -{ - if (!this->cstr_) - return this->index_ == other.index_; - // return strcmp(cstr_, other.cstr_) == 0; +bool Value::CZString::operator==(const CZString& other) const { + if (!cstr_) return index_ == other.index_; + //return strcmp(cstr_, other.cstr_) == 0; // Assume both are strings. unsigned this_len = this->storage_.length_; unsigned other_len = other.storage_.length_; - if (this_len != other_len) - return false; + if (this_len != other_len) return false; JSON_ASSERT(this->cstr_ && other.cstr_); int comp = memcmp(this->cstr_, other.cstr_, this_len); return comp == 0; } -ArrayIndex Value::CZString::index() const -{ - return this->index_; -} +ArrayIndex Value::CZString::index() const { return index_; } -// const char* Value::CZString::c_str() const { return cstr_; } -const char* Value::CZString::data() const -{ - return this->cstr_; -} -unsigned Value::CZString::length() const -{ - return this->storage_.length_; -} -bool Value::CZString::isStaticString() const -{ - return this->storage_.policy_ == noDuplication; -} +//const char* Value::CZString::c_str() const { return cstr_; } +const char* Value::CZString::data() const { return cstr_; } +unsigned Value::CZString::length() const { return storage_.length_; } +bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -410,238 +352,210 @@ bool Value::CZString::isStaticString() const * memset( this, 0, sizeof(Value) ) * This optimization is used in ValueInternalMap fast allocator. */ -Value::Value(ValueType vtype) -{ +Value::Value(ValueType vtype) { static char const emptyString[] = ""; - this->initBasic(vtype); + initBasic(vtype); switch (vtype) { - case nullValue: - break; - case intValue: - case uintValue: - this->value_.int_ = 0; - break; - case realValue: - this->value_.real_ = 0.0; - break; - case stringValue: - // allocated_ == false, so this is safe. - this->value_.string_ = - const_cast(static_cast(emptyString)); - break; - case arrayValue: - case objectValue: - this->value_.map_ = new ObjectValues(); - break; - case booleanValue: - this->value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + // allocated_ == false, so this is safe. + value_.string_ = const_cast(static_cast(emptyString)); + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; } } -Value::Value(Int value) -{ - this->initBasic(intValue); - this->value_.int_ = value; +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; } -Value::Value(UInt value) -{ - this->initBasic(uintValue); - this->value_.uint_ = value; +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; } #if defined(JSON_HAS_INT64) -Value::Value(Int64 value) -{ - this->initBasic(intValue); - this->value_.int_ = value; +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; } -Value::Value(UInt64 value) -{ - this->initBasic(uintValue); - this->value_.uint_ = value; +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; } #endif // defined(JSON_HAS_INT64) -Value::Value(double value) -{ - this->initBasic(realValue); - this->value_.real_ = value; +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; } -Value::Value(const char* value) -{ - this->initBasic(stringValue, true); +Value::Value(const char* value) { + initBasic(stringValue, true); JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor"); - this->value_.string_ = - duplicateAndPrefixStringValue(value, static_cast(strlen(value))); + value_.string_ = duplicateAndPrefixStringValue(value, static_cast(strlen(value))); } -Value::Value(const char* beginValue, const char* endValue) -{ - this->initBasic(stringValue, true); - this->value_.string_ = duplicateAndPrefixStringValue( - beginValue, static_cast(endValue - beginValue)); +Value::Value(const char* beginValue, const char* endValue) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(beginValue, static_cast(endValue - beginValue)); } -Value::Value(const JSONCPP_STRING& value) -{ - this->initBasic(stringValue, true); - this->value_.string_ = duplicateAndPrefixStringValue( - value.data(), static_cast(value.length())); +Value::Value(const JSONCPP_STRING& value) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(value.data(), static_cast(value.length())); } -Value::Value(const StaticString& value) -{ - this->initBasic(stringValue); - this->value_.string_ = const_cast(value.c_str()); +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); } #ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) -{ +Value::Value(const CppTL::ConstString& value) { initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue( - value, static_cast(value.length())); + value_.string_ = duplicateAndPrefixStringValue(value, static_cast(value.length())); } #endif -Value::Value(bool value) -{ - this->initBasic(booleanValue); - this->value_.bool_ = value; +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; } Value::Value(Value const& other) - : type_(other.type_) - , allocated_(false) - , comments_(0) - , start_(other.start_) - , limit_(other.limit_) -{ - switch (this->type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - this->value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.allocated_) { - unsigned len; - char const* str; - decodePrefixedString(other.allocated_, other.value_.string_, &len, - &str); - this->value_.string_ = duplicateAndPrefixStringValue(str, len); - this->allocated_ = true; - } else { - this->value_.string_ = other.value_.string_; - this->allocated_ = false; - } - break; - case arrayValue: - case objectValue: - this->value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; + : type_(other.type_), allocated_(false) + , + comments_(0), start_(other.start_), limit_(other.limit_) +{ + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, + &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + allocated_ = false; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; } if (other.comments_) { - this->comments_ = new CommentInfo[numberOfCommentPlacement]; + comments_ = new CommentInfo[numberOfCommentPlacement]; for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { const CommentInfo& otherComment = other.comments_[comment]; if (otherComment.comment_) - this->comments_[comment].setComment(otherComment.comment_, - strlen(otherComment.comment_)); + comments_[comment].setComment( + otherComment.comment_, strlen(otherComment.comment_)); } } } #if JSON_HAS_RVALUE_REFERENCES // Move constructor -Value::Value(Value&& other) -{ - this->initBasic(nullValue); - this->swap(other); +Value::Value(Value&& other) { + initBasic(nullValue); + swap(other); } #endif -Value::~Value() -{ - switch (this->type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (this->allocated_) - releasePrefixedStringValue(this->value_.string_); - break; - case arrayValue: - case objectValue: - delete this->value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; +Value::~Value() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; } - delete[] this->comments_; + delete[] comments_; - this->value_.uint_ = 0; + value_.uint_ = 0; } -Value& Value::operator=(Value other) -{ - this->swap(other); +Value& Value::operator=(Value other) { + swap(other); return *this; } -void Value::swapPayload(Value& other) -{ - ValueType temp = this->type_; - this->type_ = other.type_; +void Value::swapPayload(Value& other) { + ValueType temp = type_; + type_ = other.type_; other.type_ = temp; - std::swap(this->value_, other.value_); - int temp2 = this->allocated_; - this->allocated_ = other.allocated_; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; other.allocated_ = temp2 & 0x1; } -void Value::copyPayload(const Value& other) -{ - this->type_ = other.type_; - this->value_ = other.value_; - this->allocated_ = other.allocated_; +void Value::copyPayload(const Value& other) { + type_ = other.type_; + value_ = other.value_; + allocated_ = other.allocated_; } -void Value::swap(Value& other) -{ - this->swapPayload(other); - std::swap(this->comments_, other.comments_); - std::swap(this->start_, other.start_); - std::swap(this->limit_, other.limit_); +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); } -void Value::copy(const Value& other) -{ - this->copyPayload(other); - this->comments_ = other.comments_; - this->start_ = other.start_; - this->limit_ = other.limit_; +void Value::copy(const Value& other) { + copyPayload(other); + comments_ = other.comments_; + start_ = other.start_; + limit_ = other.limit_; } -ValueType Value::type() const -{ - return this->type_; -} +ValueType Value::type() const { return type_; } -int Value::compare(const Value& other) const -{ +int Value::compare(const Value& other) const { if (*this < other) return -1; if (*this > other) @@ -649,568 +563,509 @@ int Value::compare(const Value& other) const return 0; } -bool Value::operator<(const Value& other) const -{ - int typeDelta = this->type_ - other.type_; +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; if (typeDelta) return typeDelta < 0 ? true : false; - switch (this->type_) { - case nullValue: - return false; - case intValue: - return this->value_.int_ < other.value_.int_; - case uintValue: - return this->value_.uint_ < other.value_.uint_; - case realValue: - return this->value_.real_ < other.value_.real_; - case booleanValue: - return this->value_.bool_ < other.value_.bool_; - case stringValue: { - if ((this->value_.string_ == 0) || (other.value_.string_ == 0)) { - if (other.value_.string_) - return true; - else - return false; - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, - &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, - &other_str); - unsigned min_len = std::min(this_len, other_len); - JSON_ASSERT(this_str && other_str); - int comp = memcmp(this_str, other_str, min_len); - if (comp < 0) - return true; - if (comp > 0) - return false; - return (this_len < other_len); - } - case arrayValue: - case objectValue: { - int delta = int(this->value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; - return (*this->value_.map_) < (*other.value_.map_); + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + if (other.value_.string_) return true; + else return false; } - default: - JSON_ASSERT_UNREACHABLE; + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, min_len); + if (comp < 0) return true; + if (comp > 0) return false; + return (this_len < other_len); + } + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } + default: + JSON_ASSERT_UNREACHABLE; } return false; // unreachable } -bool Value::operator<=(const Value& other) const -{ - return !(other < *this); -} +bool Value::operator<=(const Value& other) const { return !(other < *this); } -bool Value::operator>=(const Value& other) const -{ - return !(*this < other); -} +bool Value::operator>=(const Value& other) const { return !(*this < other); } -bool Value::operator>(const Value& other) const -{ - return other < *this; -} +bool Value::operator>(const Value& other) const { return other < *this; } -bool Value::operator==(const Value& other) const -{ +bool Value::operator==(const Value& other) const { // if ( type_ != other.type_ ) // GCC 2.95.3 says: // attempt to take address of bit-field structure member `Json::Value::type_' // Beats me, but a temp solves the problem. int temp = other.type_; - if (this->type_ != temp) + if (type_ != temp) return false; - switch (this->type_) { - case nullValue: - return true; - case intValue: - return this->value_.int_ == other.value_.int_; - case uintValue: - return this->value_.uint_ == other.value_.uint_; - case realValue: - return this->value_.real_ == other.value_.real_; - case booleanValue: - return this->value_.bool_ == other.value_.bool_; - case stringValue: { - if ((this->value_.string_ == 0) || (other.value_.string_ == 0)) { - return (this->value_.string_ == other.value_.string_); - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, - &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, - &other_str); - if (this_len != other_len) - return false; - JSON_ASSERT(this_str && other_str); - int comp = memcmp(this_str, other_str, this_len); - return comp == 0; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + return (value_.string_ == other.value_.string_); } - case arrayValue: - case objectValue: - return this->value_.map_->size() == other.value_.map_->size() && - (*this->value_.map_) == (*other.value_.map_); - default: - JSON_ASSERT_UNREACHABLE; + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + if (this_len != other_len) return false; + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, this_len); + return comp == 0; + } + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); + default: + JSON_ASSERT_UNREACHABLE; } return false; // unreachable } -bool Value::operator!=(const Value& other) const -{ - return !(*this == other); -} +bool Value::operator!=(const Value& other) const { return !(*this == other); } -const char* Value::asCString() const -{ +const char* Value::asCString() const { JSON_ASSERT_MESSAGE(type_ == stringValue, "in Json::Value::asCString(): requires stringValue"); - if (this->value_.string_ == 0) - return 0; + if (value_.string_ == 0) return 0; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, - &this_str); + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); return this_str; } #if JSONCPP_USING_SECURE_MEMORY -unsigned Value::getCStringLength() const -{ +unsigned Value::getCStringLength() const { JSON_ASSERT_MESSAGE(type_ == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) - return 0; + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) return 0; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, - &this_str); + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); return this_len; } #endif -bool Value::getString(char const** str, char const** cend) const -{ - if (this->type_ != stringValue) - return false; - if (this->value_.string_ == 0) - return false; +bool Value::getString(char const** str, char const** cend) const { + if (type_ != stringValue) return false; + if (value_.string_ == 0) return false; unsigned length; decodePrefixedString(this->allocated_, this->value_.string_, &length, str); *cend = *str + length; return true; } -JSONCPP_STRING Value::asString() const -{ - switch (this->type_) { - case nullValue: - return ""; - case stringValue: { - if (this->value_.string_ == 0) - return ""; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, - &this_str); - return JSONCPP_STRING(this_str, this_len); - } - case booleanValue: - return this->value_.bool_ ? "true" : "false"; - case intValue: - return valueToString(this->value_.int_); - case uintValue: - return valueToString(this->value_.uint_); - case realValue: - return valueToString(this->value_.real_); - default: - JSON_FAIL_MESSAGE("Type is not convertible to string"); +JSONCPP_STRING Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: + { + if (value_.string_ == 0) return ""; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + return JSONCPP_STRING(this_str, this_len); + } + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); } } #ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const -{ +CppTL::ConstString Value::asConstString() const { unsigned len; char const* str; - decodePrefixedString(allocated_, value_.string_, &len, &str); + decodePrefixedString(allocated_, value_.string_, + &len, &str); return CppTL::ConstString(str, len); } #endif -Value::Int Value::asInt() const -{ - switch (this->type_) { - case intValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); - return Int(this->value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); - return Int(this->value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), - "double out of Int range"); - return Int(this->value_.real_); - case nullValue: - return 0; - case booleanValue: - return this->value_.bool_ ? 1 : 0; - default: - break; +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to Int."); } -Value::UInt Value::asUInt() const -{ - switch (this->type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); - return UInt(this->value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); - return UInt(this->value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), - "double out of UInt range"); - return UInt(this->value_.real_); - case nullValue: - return 0; - case booleanValue: - return this->value_.bool_ ? 1 : 0; - default: - break; +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to UInt."); } #if defined(JSON_HAS_INT64) -Value::Int64 Value::asInt64() const -{ - switch (this->type_) { - case intValue: - return Int64(this->value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); - return Int64(this->value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), - "double out of Int64 range"); - return Int64(this->value_.real_); - case nullValue: - return 0; - case booleanValue: - return this->value_.bool_ ? 1 : 0; - default: - break; +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to Int64."); } -Value::UInt64 Value::asUInt64() const -{ - switch (this->type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); - return UInt64(this->value_.int_); - case uintValue: - return UInt64(this->value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), - "double out of UInt64 range"); - return UInt64(this->value_.real_); - case nullValue: - return 0; - case booleanValue: - return this->value_.bool_ ? 1 : 0; - default: - break; +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); } #endif // if defined(JSON_HAS_INT64) -LargestInt Value::asLargestInt() const -{ +LargestInt Value::asLargestInt() const { #if defined(JSON_NO_INT64) return asInt(); #else - return this->asInt64(); + return asInt64(); #endif } -LargestUInt Value::asLargestUInt() const -{ +LargestUInt Value::asLargestUInt() const { #if defined(JSON_NO_INT64) return asUInt(); #else - return this->asUInt64(); + return asUInt64(); #endif } -double Value::asDouble() const -{ - switch (this->type_) { - case intValue: - return static_cast(this->value_.int_); - case uintValue: +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(this->value_.uint_); + return static_cast(value_.uint_); #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); + return integerToDouble(value_.uint_); #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return this->value_.real_; - case nullValue: - return 0.0; - case booleanValue: - return this->value_.bool_ ? 1.0 : 0.0; - default: - break; + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to double."); } -float Value::asFloat() const -{ - switch (this->type_) { - case intValue: - return static_cast(this->value_.int_); - case uintValue: +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(this->value_.uint_); + return static_cast(value_.uint_); #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - // This can fail (silently?) if the value is bigger than MAX_FLOAT. - return static_cast(integerToDouble(value_.uint_)); + // This can fail (silently?) if the value is bigger than MAX_FLOAT. + return static_cast(integerToDouble(value_.uint_)); #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast(this->value_.real_); - case nullValue: - return 0.0; - case booleanValue: - return this->value_.bool_ ? 1.0f : 0.0f; - default: - break; + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to float."); } -bool Value::asBool() const -{ - switch (this->type_) { - case booleanValue: - return this->value_.bool_; - case nullValue: - return false; - case intValue: - return this->value_.int_ ? true : false; - case uintValue: - return this->value_.uint_ ? true : false; - case realValue: - // This is kind of strange. Not recommended. - return (this->value_.real_ != 0.0) ? true : false; - default: - break; +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + // This is kind of strange. Not recommended. + return (value_.real_ != 0.0) ? true : false; + default: + break; } JSON_FAIL_MESSAGE("Value is not convertible to bool."); } -bool Value::isConvertibleTo(ValueType other) const -{ +bool Value::isConvertibleTo(ValueType other) const { switch (other) { - case nullValue: - return (this->isNumeric() && this->asDouble() == 0.0) || - (this->type_ == booleanValue && this->value_.bool_ == false) || - (this->type_ == stringValue && this->asString().empty()) || - (this->type_ == arrayValue && this->value_.map_->size() == 0) || - (this->type_ == objectValue && this->value_.map_->size() == 0) || - this->type_ == nullValue; - case intValue: - return this->isInt() || - (this->type_ == realValue && - InRange(this->value_.real_, minInt, maxInt)) || - this->type_ == booleanValue || this->type_ == nullValue; - case uintValue: - return this->isUInt() || - (this->type_ == realValue && - InRange(this->value_.real_, 0, maxUInt)) || - this->type_ == booleanValue || this->type_ == nullValue; - case realValue: - return this->isNumeric() || this->type_ == booleanValue || - this->type_ == nullValue; - case booleanValue: - return this->isNumeric() || this->type_ == booleanValue || - this->type_ == nullValue; - case stringValue: - return this->isNumeric() || this->type_ == booleanValue || - this->type_ == stringValue || this->type_ == nullValue; - case arrayValue: - return this->type_ == arrayValue || this->type_ == nullValue; - case objectValue: - return this->type_ == objectValue || this->type_ == nullValue; + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString().empty()) || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; } JSON_ASSERT_UNREACHABLE; return false; } /// Number of values in array or object -ArrayIndex Value::size() const -{ - switch (this->type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; - case arrayValue: // size of the array is highest index + 1 - if (!this->value_.map_->empty()) { - ObjectValues::const_iterator itLast = this->value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return ArrayIndex(this->value_.map_->size()); +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); } JSON_ASSERT_UNREACHABLE; return 0; // unreachable; } -bool Value::empty() const -{ - if (this->isNull() || this->isArray() || this->isObject()) - return this->size() == 0u; +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; else return false; } -bool Value::operator!() const -{ - return this->isNull(); -} +bool Value::operator!() const { return isNull(); } -void Value::clear() -{ +void Value::clear() { JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || - type_ == objectValue, + type_ == objectValue, "in Json::Value::clear(): requires complex value"); - this->start_ = 0; - this->limit_ = 0; - switch (this->type_) { - case arrayValue: - case objectValue: - this->value_.map_->clear(); - break; - default: - break; + start_ = 0; + limit_ = 0; + switch (type_) { + case arrayValue: + case objectValue: + value_.map_->clear(); + break; + default: + break; } } -void Value::resize(ArrayIndex newSize) -{ +void Value::resize(ArrayIndex newSize) { JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, "in Json::Value::resize(): requires arrayValue"); - if (this->type_ == nullValue) + if (type_ == nullValue) *this = Value(arrayValue); - ArrayIndex oldSize = this->size(); + ArrayIndex oldSize = size(); if (newSize == 0) - this->clear(); + clear(); else if (newSize > oldSize) (*this)[newSize - 1]; else { for (ArrayIndex index = newSize; index < oldSize; ++index) { - this->value_.map_->erase(index); + value_.map_->erase(index); } JSON_ASSERT(size() == newSize); } } -Value& Value::operator[](ArrayIndex index) -{ +Value& Value::operator[](ArrayIndex index) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (this->type_ == nullValue) + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) *this = Value(arrayValue); CZString key(index); - ObjectValues::iterator it = this->value_.map_->lower_bound(key); - if (it != this->value_.map_->end() && (*it).first == key) + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) return (*it).second; ObjectValues::value_type defaultValue(key, nullSingleton()); - it = this->value_.map_->insert(it, defaultValue); + it = value_.map_->insert(it, defaultValue); return (*it).second; } -Value& Value::operator[](int index) -{ +Value& Value::operator[](int index) { JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index): index cannot be negative"); + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); return (*this)[ArrayIndex(index)]; } -const Value& Value::operator[](ArrayIndex index) const -{ +const Value& Value::operator[](ArrayIndex index) const { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (this->type_ == nullValue) + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) return nullSingleton(); CZString key(index); - ObjectValues::const_iterator it = this->value_.map_->find(key); - if (it == this->value_.map_->end()) + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) return nullSingleton(); return (*it).second; } -const Value& Value::operator[](int index) const -{ +const Value& Value::operator[](int index) const { JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index) const: index cannot be negative"); + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); return (*this)[ArrayIndex(index)]; } -void Value::initBasic(ValueType vtype, bool allocated) -{ - this->type_ = vtype; - this->allocated_ = allocated; - this->comments_ = 0; - this->start_ = 0; - this->limit_ = 0; +void Value::initBasic(ValueType vtype, bool allocated) { + type_ = vtype; + allocated_ = allocated; + comments_ = 0; + start_ = 0; + limit_ = 0; } // Access an object value by name, create a null member if it does not exist. // @pre Type of '*this' is object or null. // @param key is null-terminated. -Value& Value::resolveReference(const char* key) -{ +Value& Value::resolveReference(const char* key) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); - if (this->type_ == nullValue) + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) *this = Value(objectValue); - CZString actualKey(key, static_cast(strlen(key)), - CZString::noDuplication); // NOTE! - ObjectValues::iterator it = this->value_.map_->lower_bound(actualKey); - if (it != this->value_.map_->end() && (*it).first == actualKey) + CZString actualKey( + key, static_cast(strlen(key)), CZString::noDuplication); // NOTE! + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; ObjectValues::value_type defaultValue(actualKey, nullSingleton()); - it = this->value_.map_->insert(it, defaultValue); + it = value_.map_->insert(it, defaultValue); Value& value = (*it).second; return value; } @@ -1219,223 +1074,198 @@ Value& Value::resolveReference(const char* key) Value& Value::resolveReference(char const* key, char const* cend) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::resolveReference(key, end): requires objectValue"); - if (this->type_ == nullValue) + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(key, end): requires objectValue"); + if (type_ == nullValue) *this = Value(objectValue); - CZString actualKey(key, static_cast(cend - key), - CZString::duplicateOnCopy); - ObjectValues::iterator it = this->value_.map_->lower_bound(actualKey); - if (it != this->value_.map_->end() && (*it).first == actualKey) + CZString actualKey( + key, static_cast(cend-key), CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; ObjectValues::value_type defaultValue(actualKey, nullSingleton()); - it = this->value_.map_->insert(it, defaultValue); + it = value_.map_->insert(it, defaultValue); Value& value = (*it).second; return value; } -Value Value::get(ArrayIndex index, const Value& defaultValue) const -{ +Value Value::get(ArrayIndex index, const Value& defaultValue) const { const Value* value = &((*this)[index]); return value == &nullSingleton() ? defaultValue : *value; } -bool Value::isValidIndex(ArrayIndex index) const -{ - return index < this->size(); -} +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } Value const* Value::find(char const* key, char const* cend) const { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, - "in Json::Value::find(key, end, found): requires " - "objectValue or nullValue"); - if (this->type_ == nullValue) - return NULL; - CZString actualKey(key, static_cast(cend - key), - CZString::noDuplication); - ObjectValues::const_iterator it = this->value_.map_->find(actualKey); - if (it == this->value_.map_->end()) - return NULL; + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::find(key, end, found): requires objectValue or nullValue"); + if (type_ == nullValue) return NULL; + CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) return NULL; return &(*it).second; } const Value& Value::operator[](const char* key) const { - Value const* found = this->find(key, key + strlen(key)); - if (!found) - return nullSingleton(); + Value const* found = find(key, key + strlen(key)); + if (!found) return nullSingleton(); return *found; } Value const& Value::operator[](JSONCPP_STRING const& key) const { - Value const* found = this->find(key.data(), key.data() + key.length()); - if (!found) - return nullSingleton(); + Value const* found = find(key.data(), key.data() + key.length()); + if (!found) return nullSingleton(); return *found; } -Value& Value::operator[](const char* key) -{ - return this->resolveReference(key, key + strlen(key)); +Value& Value::operator[](const char* key) { + return resolveReference(key, key + strlen(key)); } -Value& Value::operator[](const JSONCPP_STRING& key) -{ - return this->resolveReference(key.data(), key.data() + key.length()); +Value& Value::operator[](const JSONCPP_STRING& key) { + return resolveReference(key.data(), key.data() + key.length()); } -Value& Value::operator[](const StaticString& key) -{ - return this->resolveReference(key.c_str()); +Value& Value::operator[](const StaticString& key) { + return resolveReference(key.c_str()); } #ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) -{ +Value& Value::operator[](const CppTL::ConstString& key) { return resolveReference(key.c_str(), key.end_c_str()); } Value const& Value::operator[](CppTL::ConstString const& key) const { Value const* found = find(key.c_str(), key.end_c_str()); - if (!found) - return nullSingleton(); + if (!found) return nullSingleton(); return *found; } #endif -Value& Value::append(const Value& value) -{ - return (*this)[this->size()] = value; -} +Value& Value::append(const Value& value) { return (*this)[size()] = value; } #if JSON_HAS_RVALUE_REFERENCES -Value& Value::append(Value&& value) -{ - return (*this)[this->size()] = value; -} + Value& Value::append(Value&& value) { return (*this)[size()] = value; } #endif -Value Value::get(char const* key, char const* cend, - Value const& defaultValue) const +Value Value::get(char const* key, char const* cend, Value const& defaultValue) const { - Value const* found = this->find(key, cend); + Value const* found = find(key, cend); return !found ? defaultValue : *found; } Value Value::get(char const* key, Value const& defaultValue) const { - return this->get(key, key + strlen(key), defaultValue); + return get(key, key + strlen(key), defaultValue); } Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const { - return this->get(key.data(), key.data() + key.length(), defaultValue); + return get(key.data(), key.data() + key.length(), defaultValue); } + bool Value::removeMember(const char* key, const char* cend, Value* removed) { - if (this->type_ != objectValue) { + if (type_ != objectValue) { return false; } - CZString actualKey(key, static_cast(cend - key), - CZString::noDuplication); - ObjectValues::iterator it = this->value_.map_->find(actualKey); - if (it == this->value_.map_->end()) + CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) return false; *removed = it->second; - this->value_.map_->erase(it); + value_.map_->erase(it); return true; } bool Value::removeMember(const char* key, Value* removed) { - return this->removeMember(key, key + strlen(key), removed); + return removeMember(key, key + strlen(key), removed); } bool Value::removeMember(JSONCPP_STRING const& key, Value* removed) { - return this->removeMember(key.data(), key.data() + key.length(), removed); + return removeMember(key.data(), key.data() + key.length(), removed); } Value Value::removeMember(const char* key) { JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, "in Json::Value::removeMember(): requires objectValue"); - if (this->type_ == nullValue) + if (type_ == nullValue) return nullSingleton(); - Value removed; // null - this->removeMember(key, key + strlen(key), &removed); + Value removed; // null + removeMember(key, key + strlen(key), &removed); return removed; // still null if removeMember() did nothing } Value Value::removeMember(const JSONCPP_STRING& key) { - return this->removeMember(key.c_str()); + return removeMember(key.c_str()); } -bool Value::removeIndex(ArrayIndex index, Value* removed) -{ - if (this->type_ != arrayValue) { +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type_ != arrayValue) { return false; } CZString key(index); - ObjectValues::iterator it = this->value_.map_->find(key); - if (it == this->value_.map_->end()) { + ObjectValues::iterator it = value_.map_->find(key); + if (it == value_.map_->end()) { return false; } *removed = it->second; - ArrayIndex oldSize = this->size(); + ArrayIndex oldSize = size(); // shift left all items left, into the place of the "removed" - for (ArrayIndex i = index; i < (oldSize - 1); ++i) { + for (ArrayIndex i = index; i < (oldSize - 1); ++i){ CZString keey(i); - (*this->value_.map_)[keey] = (*this)[i + 1]; + (*value_.map_)[keey] = (*this)[i + 1]; } // erase the last one ("leftover") CZString keyLast(oldSize - 1); - ObjectValues::iterator itLast = this->value_.map_->find(keyLast); - this->value_.map_->erase(itLast); + ObjectValues::iterator itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); return true; } #ifdef JSON_USE_CPPTL Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const -{ + const Value& defaultValue) const { return get(key.c_str(), key.end_c_str(), defaultValue); } #endif bool Value::isMember(char const* key, char const* cend) const { - Value const* value = this->find(key, cend); + Value const* value = find(key, cend); return NULL != value; } bool Value::isMember(char const* key) const { - return this->isMember(key, key + strlen(key)); + return isMember(key, key + strlen(key)); } bool Value::isMember(JSONCPP_STRING const& key) const { - return this->isMember(key.data(), key.data() + key.length()); + return isMember(key.data(), key.data() + key.length()); } #ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const -{ +bool Value::isMember(const CppTL::ConstString& key) const { return isMember(key.c_str(), key.end_c_str()); } #endif -Value::Members Value::getMemberNames() const -{ +Value::Members Value::getMemberNames() const { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::getMemberNames(), value must be objectValue"); - if (this->type_ == nullValue) + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) return Value::Members(); Members members; - members.reserve(this->value_.map_->size()); - ObjectValues::const_iterator it = this->value_.map_->begin(); - ObjectValues::const_iterator itEnd = this->value_.map_->end(); + members.reserve(value_.map_->size()); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); for (; it != itEnd; ++it) { - members.push_back( - JSONCPP_STRING((*it).first.data(), (*it).first.length())); + members.push_back(JSONCPP_STRING((*it).first.data(), + (*it).first.length())); } return members; } @@ -1447,8 +1277,8 @@ Value::Members Value::getMemberNames() const // if ( type_ == objectValue ) // { // return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type() -// ), MemberNamesTransform() ) ); +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); // } // return EnumMemberNames(); //} @@ -1465,114 +1295,99 @@ Value::Members Value::getMemberNames() const // //# endif -static bool IsIntegral(double d) -{ +static bool IsIntegral(double d) { double integral_part; return modf(d, &integral_part) == 0.0; } -bool Value::isNull() const -{ - return this->type_ == nullValue; -} +bool Value::isNull() const { return type_ == nullValue; } -bool Value::isBool() const -{ - return this->type_ == booleanValue; -} +bool Value::isBool() const { return type_ == booleanValue; } -bool Value::isInt() const -{ - switch (this->type_) { - case intValue: +bool Value::isInt() const { + switch (type_) { + case intValue: #if defined(JSON_HAS_INT64) - return this->value_.int_ >= minInt && this->value_.int_ <= maxInt; + return value_.int_ >= minInt && value_.int_ <= maxInt; #else - return true; + return true; #endif - case uintValue: - return this->value_.uint_ <= UInt(maxInt); - case realValue: - return this->value_.real_ >= minInt && this->value_.real_ <= maxInt && - IsIntegral(this->value_.real_); - default: - break; + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; } return false; } -bool Value::isUInt() const -{ - switch (this->type_) { - case intValue: +bool Value::isUInt() const { + switch (type_) { + case intValue: #if defined(JSON_HAS_INT64) - return this->value_.int_ >= 0 && - LargestUInt(this->value_.int_) <= LargestUInt(maxUInt); + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); #else - return value_.int_ >= 0; + return value_.int_ >= 0; #endif - case uintValue: + case uintValue: #if defined(JSON_HAS_INT64) - return this->value_.uint_ <= maxUInt; + return value_.uint_ <= maxUInt; #else - return true; + return true; #endif - case realValue: - return this->value_.real_ >= 0 && this->value_.real_ <= maxUInt && - IsIntegral(this->value_.real_); - default: - break; + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; } return false; } -bool Value::isInt64() const -{ +bool Value::isInt64() const { #if defined(JSON_HAS_INT64) - switch (this->type_) { - case intValue: - return true; - case uintValue: - return this->value_.uint_ <= UInt64(maxInt64); - case realValue: - // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a - // double, so double(maxInt64) will be rounded up to 2^63. Therefore we - // require the value to be strictly less than the limit. - return this->value_.real_ >= double(minInt64) && - this->value_.real_ < double(maxInt64) && - IsIntegral(this->value_.real_); - default: - break; + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; } #endif // JSON_HAS_INT64 return false; } -bool Value::isUInt64() const -{ +bool Value::isUInt64() const { #if defined(JSON_HAS_INT64) - switch (this->type_) { - case intValue: - return this->value_.int_ >= 0; - case uintValue: - return true; - case realValue: - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return this->value_.real_ >= 0 && - this->value_.real_ < maxUInt64AsDouble && - IsIntegral(this->value_.real_); - default: - break; + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; } #endif // JSON_HAS_INT64 return false; } -bool Value::isIntegral() const -{ - switch (this->type_) { +bool Value::isIntegral() const { + switch (type_) { case intValue: case uintValue: return true; @@ -1581,12 +1396,9 @@ bool Value::isIntegral() const // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we // require the value to be strictly less than the limit. - return this->value_.real_ >= double(minInt64) && - this->value_.real_ < maxUInt64AsDouble && - IsIntegral(this->value_.real_); + return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); #else - return value_.real_ >= minInt && value_.real_ <= maxUInt && - IsIntegral(value_.real_); + return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_); #endif // JSON_HAS_INT64 default: break; @@ -1594,89 +1406,53 @@ bool Value::isIntegral() const return false; } -bool Value::isDouble() const -{ - return this->type_ == intValue || this->type_ == uintValue || - this->type_ == realValue; -} +bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; } -bool Value::isNumeric() const -{ - return this->isDouble(); -} +bool Value::isNumeric() const { return isDouble(); } -bool Value::isString() const -{ - return this->type_ == stringValue; -} +bool Value::isString() const { return type_ == stringValue; } -bool Value::isArray() const -{ - return this->type_ == arrayValue; -} +bool Value::isArray() const { return type_ == arrayValue; } -bool Value::isObject() const -{ - return this->type_ == objectValue; -} +bool Value::isObject() const { return type_ == objectValue; } -void Value::setComment(const char* comment, size_t len, - CommentPlacement placement) -{ - if (!this->comments_) - this->comments_ = new CommentInfo[numberOfCommentPlacement]; - if ((len > 0) && (comment[len - 1] == '\n')) { +void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + if ((len > 0) && (comment[len-1] == '\n')) { // Always discard trailing newline, to aid indentation. len -= 1; } - this->comments_[placement].setComment(comment, len); + comments_[placement].setComment(comment, len); } -void Value::setComment(const char* comment, CommentPlacement placement) -{ - this->setComment(comment, strlen(comment), placement); +void Value::setComment(const char* comment, CommentPlacement placement) { + setComment(comment, strlen(comment), placement); } -void Value::setComment(const JSONCPP_STRING& comment, - CommentPlacement placement) -{ - this->setComment(comment.c_str(), comment.length(), placement); +void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) { + setComment(comment.c_str(), comment.length(), placement); } -bool Value::hasComment(CommentPlacement placement) const -{ - return this->comments_ != 0 && this->comments_[placement].comment_ != 0; +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; } -JSONCPP_STRING Value::getComment(CommentPlacement placement) const -{ - if (this->hasComment(placement)) - return this->comments_[placement].comment_; +JSONCPP_STRING Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; return ""; } -void Value::setOffsetStart(ptrdiff_t start) -{ - this->start_ = start; -} +void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } -void Value::setOffsetLimit(ptrdiff_t limit) -{ - this->limit_ = limit; -} +void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } -ptrdiff_t Value::getOffsetStart() const -{ - return this->start_; -} +ptrdiff_t Value::getOffsetStart() const { return start_; } -ptrdiff_t Value::getOffsetLimit() const -{ - return this->limit_; -} +ptrdiff_t Value::getOffsetLimit() const { return limit_; } -JSONCPP_STRING Value::toStyledString() const -{ +JSONCPP_STRING Value::toStyledString() const { StreamWriterBuilder builder; JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : ""; @@ -1686,58 +1462,54 @@ JSONCPP_STRING Value::toStyledString() const return out; } -Value::const_iterator Value::begin() const -{ - switch (this->type_) { - case arrayValue: - case objectValue: - if (this->value_.map_) - return const_iterator(this->value_.map_->begin()); - break; - default: - break; +Value::const_iterator Value::begin() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; + default: + break; } return const_iterator(); } -Value::const_iterator Value::end() const -{ - switch (this->type_) { - case arrayValue: - case objectValue: - if (this->value_.map_) - return const_iterator(this->value_.map_->end()); - break; - default: - break; +Value::const_iterator Value::end() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; + default: + break; } return const_iterator(); } -Value::iterator Value::begin() -{ - switch (this->type_) { - case arrayValue: - case objectValue: - if (this->value_.map_) - return iterator(this->value_.map_->begin()); - break; - default: - break; +Value::iterator Value::begin() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; + default: + break; } return iterator(); } -Value::iterator Value::end() -{ - switch (this->type_) { - case arrayValue: - case objectValue: - if (this->value_.map_) - return iterator(this->value_.map_->end()); - break; - default: - break; +Value::iterator Value::end() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; + default: + break; } return iterator(); } @@ -1745,41 +1517,26 @@ Value::iterator Value::end() // class PathArgument // ////////////////////////////////////////////////////////////////// -PathArgument::PathArgument() - : key_() - , index_() - , kind_(kindNone) -{ -} +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} PathArgument::PathArgument(ArrayIndex index) - : key_() - , index_(index) - , kind_(kindIndex) -{ -} + : key_(), index_(index), kind_(kindIndex) {} PathArgument::PathArgument(const char* key) - : key_(key) - , index_() - , kind_(kindKey) -{ -} + : key_(key), index_(), kind_(kindKey) {} PathArgument::PathArgument(const JSONCPP_STRING& key) - : key_(key.c_str()) - , index_() - , kind_(kindKey) -{ -} + : key_(key.c_str()), index_(), kind_(kindKey) {} // class Path // ////////////////////////////////////////////////////////////////// -Path::Path(const JSONCPP_STRING& path, const PathArgument& a1, - const PathArgument& a2, const PathArgument& a3, - const PathArgument& a4, const PathArgument& a5) -{ +Path::Path(const JSONCPP_STRING& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { InArgs in; in.reserve(5); in.push_back(&a1); @@ -1787,11 +1544,10 @@ Path::Path(const JSONCPP_STRING& path, const PathArgument& a1, in.push_back(&a3); in.push_back(&a4); in.push_back(&a5); - this->makePath(path, in); + makePath(path, in); } -void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) -{ +void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { const char* current = path.c_str(); const char* end = current + path.length(); InArgs::const_iterator itInArg = in.begin(); @@ -1799,17 +1555,17 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) if (*current == '[') { ++current; if (*current == '%') - this->addPathInArg(path, in, itInArg, PathArgument::kindIndex); + addPathInArg(path, in, itInArg, PathArgument::kindIndex); else { ArrayIndex index = 0; for (; current != end && *current >= '0' && *current <= '9'; ++current) index = index * 10 + ArrayIndex(*current - '0'); - this->args_.push_back(index); + args_.push_back(index); } if (current == end || *++current != ']') - this->invalidPath(path, int(current - path.c_str())); + invalidPath(path, int(current - path.c_str())); } else if (*current == '%') { - this->addPathInArg(path, in, itInArg, PathArgument::kindKey); + addPathInArg(path, in, itInArg, PathArgument::kindKey); ++current; } else if (*current == '.' || *current == ']') { ++current; @@ -1817,34 +1573,31 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) const char* beginName = current; while (current != end && !strchr("[.", *current)) ++current; - this->args_.push_back(JSONCPP_STRING(beginName, current)); + args_.push_back(JSONCPP_STRING(beginName, current)); } } } -void Path::addPathInArg(const JSONCPP_STRING& /*path*/, const InArgs& in, +void Path::addPathInArg(const JSONCPP_STRING& /*path*/, + const InArgs& in, InArgs::const_iterator& itInArg, - PathArgument::Kind kind) -{ + PathArgument::Kind kind) { if (itInArg == in.end()) { // Error: missing argument %d } else if ((*itInArg)->kind_ != kind) { // Error: bad argument type } else { - this->args_.push_back(**itInArg++); + args_.push_back(**itInArg++); } } -void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) -{ +void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) { // Error: invalid path. } -const Value& Path::resolve(const Value& root) const -{ +const Value& Path::resolve(const Value& root) const { const Value* node = &root; - for (Args::const_iterator it = this->args_.begin(); it != this->args_.end(); - ++it) { + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { const PathArgument& arg = *it; if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray() || !node->isValidIndex(arg.index_)) { @@ -1868,11 +1621,9 @@ const Value& Path::resolve(const Value& root) const return *node; } -Value Path::resolve(const Value& root, const Value& defaultValue) const -{ +Value Path::resolve(const Value& root, const Value& defaultValue) const { const Value* node = &root; - for (Args::const_iterator it = this->args_.begin(); it != this->args_.end(); - ++it) { + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { const PathArgument& arg = *it; if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray() || !node->isValidIndex(arg.index_)) @@ -1889,11 +1640,9 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const return *node; } -Value& Path::make(Value& root) const -{ +Value& Path::make(Value& root) const { Value* node = &root; - for (Args::const_iterator it = this->args_.begin(); it != this->args_.end(); - ++it) { + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { const PathArgument& arg = *it; if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray()) { diff --git a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp index 803cfab0193..fc86505983c 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp @@ -1,115 +1,111 @@ // Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. -// See file LICENSE for detail or copy at -// http://jsoncpp.sourceforge.net/LICENSE +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) -# include - -# include "json_tool.h" +#include +#include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include #include #include -#include #include #include +#include +#include +#include +#include -#if defined(_MSC_VER) && _MSC_VER >= 1200 && \ - _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 -# include -# define isfinite _finite -#elif defined(__sun) && defined(__SVR4) // Solaris -# if !defined(isfinite) -# include -# define isfinite finite -# endif +#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 +#include +#define isfinite _finite +#elif defined(__sun) && defined(__SVR4) //Solaris +#if !defined(isfinite) +#include +#define isfinite finite +#endif #elif defined(_AIX) -# if !defined(isfinite) -# include -# define isfinite finite -# endif +#if !defined(isfinite) +#include +#define isfinite finite +#endif #elif defined(__hpux) -# if !defined(isfinite) && !defined(__GNUC__) -# if defined(__ia64) && !defined(finite) -# define isfinite(x) \ - ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) -# else -# include -# define isfinite finite -# endif -# endif +#if !defined(isfinite) && !defined(__GNUC__) +#if defined(__ia64) && !defined(finite) +#define isfinite(x) ((sizeof(x) == sizeof(float) ? \ + _Isfinitef(x) : _IsFinite(x))) #else -# include -# if !(defined(__QNXNTO__)) // QNX already defines isfinite -# define isfinite std::isfinite -# endif +#include +#define isfinite finite +#endif +#endif +#else +#include +#if !(defined(__QNXNTO__)) // QNX already defines isfinite +#define isfinite std::isfinite +#endif #endif #if defined(_MSC_VER) -# if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && \ - _MSC_VER >= 1500 // VC++ 9.0 and above -# define snprintf sprintf_s -# elif _MSC_VER >= 1900 // VC++ 14.0 and above -# define snprintf std::snprintf -# else -# define snprintf _snprintf -# endif +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#define snprintf sprintf_s +#elif _MSC_VER >= 1900 // VC++ 14.0 and above +#define snprintf std::snprintf +#else +#define snprintf _snprintf +#endif #elif defined(__ANDROID__) || defined(__QNXNTO__) -# define snprintf snprintf +#define snprintf snprintf #elif __cplusplus >= 201103L -# if !defined(__MINGW32__) && !defined(__CYGWIN__) -# define snprintf std::snprintf -# endif +#if !defined(__MINGW32__) && !defined(__CYGWIN__) +#define snprintf std::snprintf +#endif #endif -#if defined(__BORLANDC__) -# include -# define isfinite _finite -# define snprintf _snprintf +#if defined(__BORLANDC__) +#include +#define isfinite _finite +#define snprintf _snprintf #endif // Solaris #if defined(__sun) -# include -# if !defined(isfinite) -# define isfinite finite -# endif +# include +# if !defined(isfinite) +# define isfinite finite +# endif #endif // AIX #if defined(_AIX) -# if !defined(isfinite) -# define isfinite finite -# endif +# if !defined(isfinite) +# define isfinite finite +# endif #endif // HP-UX #if defined(__hpux) -# if !defined(isfinite) -# if defined(__ia64) && !defined(finite) && !defined(__GNUC__) -# define isfinite(x) \ - ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _Isfinite(x))) -# else -# include -# define isfinite finite -# endif +# if !defined(isfinite) +# if defined(__ia64) && !defined(finite) && !defined(__GNUC__) +# define isfinite(x) ((sizeof(x) == sizeof(float) ? \ + _Isfinitef(x) : _Isfinite(x))) +# else +# include +# define isfinite finite # endif +# endif #endif // Ancient glibc #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2 -# if !defined(isfinite) -# define isfinite __finite -# endif +# if !defined(isfinite) +# define isfinite __finite +# endif #endif #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 // Disable warning about strdup being deprecated. -# pragma warning(disable : 4996) +#pragma warning(disable : 4996) #endif namespace Json { @@ -117,11 +113,10 @@ namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) typedef std::unique_ptr StreamWriterPtr; #else -typedef std::auto_ptr StreamWriterPtr; +typedef std::auto_ptr StreamWriterPtr; #endif -static bool containsControlCharacter(const char* str) -{ +static bool containsControlCharacter(const char* str) { while (*str) { if (isControlCharacter(*(str++))) return true; @@ -129,19 +124,17 @@ static bool containsControlCharacter(const char* str) return false; } -static bool containsControlCharacter0(const char* str, unsigned len) -{ +static bool containsControlCharacter0(const char* str, unsigned len) { char const* end = str + len; while (end != str) { - if (isControlCharacter(*str) || 0 == *str) + if (isControlCharacter(*str) || 0==*str) return true; ++str; } return false; } -JSONCPP_STRING valueToString(LargestInt value) -{ +JSONCPP_STRING valueToString(LargestInt value) { UIntToStringBuffer buffer; char* current = buffer + sizeof(buffer); if (value == Value::minLargestInt) { @@ -157,8 +150,7 @@ JSONCPP_STRING valueToString(LargestInt value) return current; } -JSONCPP_STRING valueToString(LargestUInt value) -{ +JSONCPP_STRING valueToString(LargestUInt value) { UIntToStringBuffer buffer; char* current = buffer + sizeof(buffer); uintToString(value, current); @@ -168,22 +160,18 @@ JSONCPP_STRING valueToString(LargestUInt value) #if defined(JSON_HAS_INT64) -JSONCPP_STRING valueToString(Int value) -{ +JSONCPP_STRING valueToString(Int value) { return valueToString(LargestInt(value)); } -JSONCPP_STRING valueToString(UInt value) -{ +JSONCPP_STRING valueToString(UInt value) { return valueToString(LargestUInt(value)); } #endif // # if defined(JSON_HAS_INT64) namespace { -JSONCPP_STRING valueToString(double value, bool useSpecialFloats, - unsigned int precision) -{ +JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) { // Allocate a buffer that is more than large enough to store the 16 digits of // precision requested below. char buffer[36]; @@ -199,8 +187,7 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, len = snprintf(buffer, sizeof(buffer), formatString, value); fixNumericLocale(buffer, buffer + len); - // try to ensure we preserve the fact that this was given to us as a double - // on input + // try to ensure we preserve the fact that this was given to us as a double on input if (!strchr(buffer, '.') && !strchr(buffer, 'e')) { strcat(buffer, ".0"); } @@ -208,14 +195,11 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, } else { // IEEE standard states that NaN values will not compare to themselves if (value != value) { - len = - snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); + len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); } else if (value < 0) { - len = snprintf(buffer, sizeof(buffer), - useSpecialFloats ? "-Infinity" : "-1e+9999"); + len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); } else { - len = snprintf(buffer, sizeof(buffer), - useSpecialFloats ? "Infinity" : "1e+9999"); + len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); } } assert(len >= 0); @@ -223,18 +207,11 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, } } -JSONCPP_STRING valueToString(double value) -{ - return valueToString(value, false, 17); -} +JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); } -JSONCPP_STRING valueToString(bool value) -{ - return value ? "true" : "false"; -} +JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; } -JSONCPP_STRING valueToQuotedString(const char* value) -{ +JSONCPP_STRING valueToQuotedString(const char* value) { if (value == NULL) return ""; // Not sure how to handle unicode... @@ -245,50 +222,51 @@ JSONCPP_STRING valueToQuotedString(const char* value) // Appending to JSONCPP_STRING is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) JSONCPP_STRING::size_type maxsize = - strlen(value) * 2 + 3; // allescaped+quotes+NULL + strlen(value) * 2 + 3; // allescaped+quotes+NULL JSONCPP_STRING result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; for (const char* c = value; *c != 0; ++c) { switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid - // (*c); - result += oss.str(); - } else { - result += *c; - } - break; + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; } } result += "\""; @@ -296,8 +274,7 @@ JSONCPP_STRING valueToQuotedString(const char* value) } // https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp -static char const* strnpbrk(char const* s, char const* accept, size_t n) -{ +static char const* strnpbrk(char const* s, char const* accept, size_t n) { assert((s || !n) && accept); char const* const end = s + n; @@ -311,8 +288,7 @@ static char const* strnpbrk(char const* s, char const* accept, size_t n) } return NULL; } -static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) -{ +static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { if (value == NULL) return ""; // Not sure how to handle unicode... @@ -322,51 +298,53 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) // We have to walk value and escape any special characters. // Appending to JSONCPP_STRING is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) - JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL + JSONCPP_STRING::size_type maxsize = + length * 2 + 3; // allescaped+quotes+NULL JSONCPP_STRING result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; char const* end = value + length; for (const char* c = value; c != end; ++c) { switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something.) - // blep notes: actually escaping \/ may be useful in javascript to avoid - // (*c); - result += oss.str(); - } else { - result += *c; - } - break; + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something.) + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; } } result += "\""; @@ -375,98 +353,80 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) // Class Writer // ////////////////////////////////////////////////////////////////// -Writer::~Writer() -{ -} +Writer::~Writer() {} // Class FastWriter // ////////////////////////////////////////////////////////////////// FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false) - , dropNullPlaceholders_(false) - , omitEndingLineFeed_(false) -{ -} + : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), + omitEndingLineFeed_(false) {} -void FastWriter::enableYAMLCompatibility() -{ - this->yamlCompatiblityEnabled_ = true; -} +void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } -void FastWriter::dropNullPlaceholders() -{ - this->dropNullPlaceholders_ = true; -} +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } -void FastWriter::omitEndingLineFeed() -{ - this->omitEndingLineFeed_ = true; -} +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } -JSONCPP_STRING FastWriter::write(const Value& root) -{ - this->document_.clear(); - this->writeValue(root); - if (!this->omitEndingLineFeed_) - this->document_ += "\n"; - return this->document_; +JSONCPP_STRING FastWriter::write(const Value& root) { + document_.clear(); + writeValue(root); + if (!omitEndingLineFeed_) + document_ += "\n"; + return document_; } -void FastWriter::writeValue(const Value& value) -{ +void FastWriter::writeValue(const Value& value) { switch (value.type()) { - case nullValue: - if (!this->dropNullPlaceholders_) - this->document_ += "null"; - break; - case intValue: - this->document_ += valueToString(value.asLargestInt()); - break; - case uintValue: - this->document_ += valueToString(value.asLargestUInt()); - break; - case realValue: - this->document_ += valueToString(value.asDouble()); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - this->document_ += - valueToQuotedStringN(str, static_cast(end - str)); - break; + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: + { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) document_ += valueToQuotedStringN(str, static_cast(end-str)); + break; + } + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + ArrayIndex size = value.size(); + for (ArrayIndex index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); } - case booleanValue: - this->document_ += valueToString(value.asBool()); - break; - case arrayValue: { - this->document_ += '['; - ArrayIndex size = value.size(); - for (ArrayIndex index = 0; index < size; ++index) { - if (index > 0) - this->document_ += ','; - this->writeValue(value[index]); - } - this->document_ += ']'; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - this->document_ += '{'; - for (Value::Members::iterator it = members.begin(); it != members.end(); - ++it) { - const JSONCPP_STRING& name = *it; - if (it != members.begin()) - this->document_ += ','; - this->document_ += valueToQuotedStringN( - name.data(), static_cast(name.length())); - this->document_ += this->yamlCompatiblityEnabled_ ? ": " : ":"; - this->writeValue(value[name]); - } - this->document_ += '}'; - } break; + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const JSONCPP_STRING& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedStringN(name.data(), static_cast(name.length())); + document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; } } @@ -474,498 +434,454 @@ void FastWriter::writeValue(const Value& value) // ////////////////////////////////////////////////////////////////// StyledWriter::StyledWriter() - : rightMargin_(74) - , indentSize_(3) - , addChildValues_() -{ -} + : rightMargin_(74), indentSize_(3), addChildValues_() {} -JSONCPP_STRING StyledWriter::write(const Value& root) -{ - this->document_.clear(); - this->addChildValues_ = false; - this->indentString_.clear(); - this->writeCommentBeforeValue(root); - this->writeValue(root); - this->writeCommentAfterValueOnSameLine(root); - this->document_ += "\n"; - return this->document_; +JSONCPP_STRING StyledWriter::write(const Value& root) { + document_.clear(); + addChildValues_ = false; + indentString_.clear(); + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += "\n"; + return document_; } -void StyledWriter::writeValue(const Value& value) -{ +void StyledWriter::writeValue(const Value& value) { switch (value.type()) { - case nullValue: - this->pushValue("null"); - break; - case intValue: - this->pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - this->pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - this->pushValue(valueToString(value.asDouble())); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - this->pushValue( - valueToQuotedStringN(str, static_cast(end - str))); - else - this->pushValue(""); - break; - } - case booleanValue: - this->pushValue(valueToString(value.asBool())); - break; - case arrayValue: - this->writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - this->pushValue("{}"); - else { - this->writeWithIndent("{"); - this->indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const JSONCPP_STRING& name = *it; - const Value& childValue = value[name]; - this->writeCommentBeforeValue(childValue); - this->writeWithIndent(valueToQuotedString(name.c_str())); - this->document_ += " : "; - this->writeValue(childValue); - if (++it == members.end()) { - this->writeCommentAfterValueOnSameLine(childValue); - break; - } - this->document_ += ','; - this->writeCommentAfterValueOnSameLine(childValue); + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const JSONCPP_STRING& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; } - this->unindent(); - this->writeWithIndent("}"); + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); } - } break; + unindent(); + writeWithIndent("}"); + } + } break; } } -void StyledWriter::writeArrayValue(const Value& value) -{ +void StyledWriter::writeArrayValue(const Value& value) { unsigned size = value.size(); if (size == 0) - this->pushValue("[]"); + pushValue("[]"); else { - bool isArrayMultiLine = this->isMultineArray(value); + bool isArrayMultiLine = isMultineArray(value); if (isArrayMultiLine) { - this->writeWithIndent("["); - this->indent(); - bool hasChildValue = !this->childValues_.empty(); + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); unsigned index = 0; for (;;) { const Value& childValue = value[index]; - this->writeCommentBeforeValue(childValue); + writeCommentBeforeValue(childValue); if (hasChildValue) - this->writeWithIndent(this->childValues_[index]); + writeWithIndent(childValues_[index]); else { - this->writeIndent(); - this->writeValue(childValue); + writeIndent(); + writeValue(childValue); } if (++index == size) { - this->writeCommentAfterValueOnSameLine(childValue); + writeCommentAfterValueOnSameLine(childValue); break; } - this->document_ += ','; - this->writeCommentAfterValueOnSameLine(childValue); + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); } - this->unindent(); - this->writeWithIndent("]"); + unindent(); + writeWithIndent("]"); } else // output on a single line { - assert(this->childValues_.size() == size); - this->document_ += "[ "; + assert(childValues_.size() == size); + document_ += "[ "; for (unsigned index = 0; index < size; ++index) { if (index > 0) - this->document_ += ", "; - this->document_ += this->childValues_[index]; + document_ += ", "; + document_ += childValues_[index]; } - this->document_ += " ]"; + document_ += " ]"; } } } -bool StyledWriter::isMultineArray(const Value& value) -{ +bool StyledWriter::isMultineArray(const Value& value) { ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= this->rightMargin_; - this->childValues_.clear(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { const Value& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + childValue.size() > 0); } if (!isMultiLine) // check if line length > max line length { - this->childValues_.reserve(size); - this->addChildValues_ = true; + childValues_.reserve(size); + addChildValues_ = true; ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' for (ArrayIndex index = 0; index < size; ++index) { - if (this->hasCommentForValue(value[index])) { + if (hasCommentForValue(value[index])) { isMultiLine = true; } - this->writeValue(value[index]); - lineLength += - static_cast(this->childValues_[index].length()); + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); } - this->addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= this->rightMargin_; + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; } return isMultiLine; } -void StyledWriter::pushValue(const JSONCPP_STRING& value) -{ - if (this->addChildValues_) - this->childValues_.push_back(value); +void StyledWriter::pushValue(const JSONCPP_STRING& value) { + if (addChildValues_) + childValues_.push_back(value); else - this->document_ += value; + document_ += value; } -void StyledWriter::writeIndent() -{ - if (!this->document_.empty()) { - char last = this->document_[this->document_.length() - 1]; +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; if (last == ' ') // already indented return; if (last != '\n') // Comments may add new-line - this->document_ += '\n'; + document_ += '\n'; } - this->document_ += this->indentString_; + document_ += indentString_; } -void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) -{ - this->writeIndent(); - this->document_ += value; +void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) { + writeIndent(); + document_ += value; } -void StyledWriter::indent() -{ - this->indentString_ += JSONCPP_STRING(this->indentSize_, ' '); -} +void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); } -void StyledWriter::unindent() -{ - assert(this->indentString_.size() >= this->indentSize_); - this->indentString_.resize(this->indentString_.size() - this->indentSize_); +void StyledWriter::unindent() { + assert(indentString_.size() >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); } -void StyledWriter::writeCommentBeforeValue(const Value& root) -{ +void StyledWriter::writeCommentBeforeValue(const Value& root) { if (!root.hasComment(commentBefore)) return; - this->document_ += "\n"; - this->writeIndent(); + document_ += "\n"; + writeIndent(); const JSONCPP_STRING& comment = root.getComment(commentBefore); JSONCPP_STRING::const_iterator iter = comment.begin(); while (iter != comment.end()) { - this->document_ += *iter; - if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/')) - this->writeIndent(); + document_ += *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + writeIndent(); ++iter; } // Comments are stripped of trailing newlines, so add one here - this->document_ += "\n"; + document_ += "\n"; } -void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) -{ +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { if (root.hasComment(commentAfterOnSameLine)) - this->document_ += " " + root.getComment(commentAfterOnSameLine); + document_ += " " + root.getComment(commentAfterOnSameLine); if (root.hasComment(commentAfter)) { - this->document_ += "\n"; - this->document_ += root.getComment(commentAfter); - this->document_ += "\n"; + document_ += "\n"; + document_ += root.getComment(commentAfter); + document_ += "\n"; } } -bool StyledWriter::hasCommentForValue(const Value& value) -{ +bool StyledWriter::hasCommentForValue(const Value& value) { return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter); + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); } // Class StyledStreamWriter // ////////////////////////////////////////////////////////////////// StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation) - : document_(NULL) - , rightMargin_(74) - , indentation_(indentation) - , addChildValues_() -{ -} - -void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) -{ - this->document_ = &out; - this->addChildValues_ = false; - this->indentString_.clear(); - this->indented_ = true; - this->writeCommentBeforeValue(root); - if (!this->indented_) - this->writeIndent(); - this->indented_ = true; - this->writeValue(root); - this->writeCommentAfterValueOnSameLine(root); - *this->document_ << "\n"; - this->document_ = NULL; // Forget the stream, for safety. -} - -void StyledStreamWriter::writeValue(const Value& value) -{ + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_() {} + +void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_.clear(); + indented_ = true; + writeCommentBeforeValue(root); + if (!indented_) writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { switch (value.type()) { - case nullValue: - this->pushValue("null"); - break; - case intValue: - this->pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - this->pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - this->pushValue(valueToString(value.asDouble())); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - this->pushValue( - valueToQuotedStringN(str, static_cast(end - str))); - else - this->pushValue(""); - break; - } - case booleanValue: - this->pushValue(valueToString(value.asBool())); - break; - case arrayValue: - this->writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - this->pushValue("{}"); - else { - this->writeWithIndent("{"); - this->indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const JSONCPP_STRING& name = *it; - const Value& childValue = value[name]; - this->writeCommentBeforeValue(childValue); - this->writeWithIndent(valueToQuotedString(name.c_str())); - *this->document_ << " : "; - this->writeValue(childValue); - if (++it == members.end()) { - this->writeCommentAfterValueOnSameLine(childValue); - break; - } - *this->document_ << ","; - this->writeCommentAfterValueOnSameLine(childValue); + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const JSONCPP_STRING& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; } - this->unindent(); - this->writeWithIndent("}"); + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); } - } break; + unindent(); + writeWithIndent("}"); + } + } break; } } -void StyledStreamWriter::writeArrayValue(const Value& value) -{ +void StyledStreamWriter::writeArrayValue(const Value& value) { unsigned size = value.size(); if (size == 0) - this->pushValue("[]"); + pushValue("[]"); else { - bool isArrayMultiLine = this->isMultineArray(value); + bool isArrayMultiLine = isMultineArray(value); if (isArrayMultiLine) { - this->writeWithIndent("["); - this->indent(); - bool hasChildValue = !this->childValues_.empty(); + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); unsigned index = 0; for (;;) { const Value& childValue = value[index]; - this->writeCommentBeforeValue(childValue); + writeCommentBeforeValue(childValue); if (hasChildValue) - this->writeWithIndent(this->childValues_[index]); + writeWithIndent(childValues_[index]); else { - if (!this->indented_) - this->writeIndent(); - this->indented_ = true; - this->writeValue(childValue); - this->indented_ = false; + if (!indented_) writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; } if (++index == size) { - this->writeCommentAfterValueOnSameLine(childValue); + writeCommentAfterValueOnSameLine(childValue); break; } - *this->document_ << ","; - this->writeCommentAfterValueOnSameLine(childValue); + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); } - this->unindent(); - this->writeWithIndent("]"); + unindent(); + writeWithIndent("]"); } else // output on a single line { - assert(this->childValues_.size() == size); - *this->document_ << "[ "; + assert(childValues_.size() == size); + *document_ << "[ "; for (unsigned index = 0; index < size; ++index) { if (index > 0) - *this->document_ << ", "; - *this->document_ << this->childValues_[index]; + *document_ << ", "; + *document_ << childValues_[index]; } - *this->document_ << " ]"; + *document_ << " ]"; } } } -bool StyledStreamWriter::isMultineArray(const Value& value) -{ +bool StyledStreamWriter::isMultineArray(const Value& value) { ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= this->rightMargin_; - this->childValues_.clear(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { const Value& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + childValue.size() > 0); } if (!isMultiLine) // check if line length > max line length { - this->childValues_.reserve(size); - this->addChildValues_ = true; + childValues_.reserve(size); + addChildValues_ = true; ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' for (ArrayIndex index = 0; index < size; ++index) { - if (this->hasCommentForValue(value[index])) { + if (hasCommentForValue(value[index])) { isMultiLine = true; } - this->writeValue(value[index]); - lineLength += - static_cast(this->childValues_[index].length()); + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); } - this->addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= this->rightMargin_; + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; } return isMultiLine; } -void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) -{ - if (this->addChildValues_) - this->childValues_.push_back(value); +void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) { + if (addChildValues_) + childValues_.push_back(value); else - *this->document_ << value; + *document_ << value; } -void StyledStreamWriter::writeIndent() -{ +void StyledStreamWriter::writeIndent() { // blep intended this to look at the so-far-written string // to determine whether we are already indented, but // with a stream we cannot do that. So we rely on some saved state. // The caller checks indented_. - *this->document_ << '\n' << this->indentString_; + *document_ << '\n' << indentString_; } -void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) -{ - if (!this->indented_) - this->writeIndent(); - *this->document_ << value; - this->indented_ = false; +void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) { + if (!indented_) writeIndent(); + *document_ << value; + indented_ = false; } -void StyledStreamWriter::indent() -{ - this->indentString_ += this->indentation_; -} +void StyledStreamWriter::indent() { indentString_ += indentation_; } -void StyledStreamWriter::unindent() -{ - assert(this->indentString_.size() >= this->indentation_.size()); - this->indentString_.resize(this->indentString_.size() - - this->indentation_.size()); +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); } -void StyledStreamWriter::writeCommentBeforeValue(const Value& root) -{ +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { if (!root.hasComment(commentBefore)) return; - if (!this->indented_) - this->writeIndent(); + if (!indented_) writeIndent(); const JSONCPP_STRING& comment = root.getComment(commentBefore); JSONCPP_STRING::const_iterator iter = comment.begin(); while (iter != comment.end()) { - *this->document_ << *iter; - if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/')) + *document_ << *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) // writeIndent(); // would include newline - *this->document_ << this->indentString_; + *document_ << indentString_; ++iter; } - this->indented_ = false; + indented_ = false; } -void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) -{ +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { if (root.hasComment(commentAfterOnSameLine)) - *this->document_ << ' ' << root.getComment(commentAfterOnSameLine); + *document_ << ' ' << root.getComment(commentAfterOnSameLine); if (root.hasComment(commentAfter)) { - this->writeIndent(); - *this->document_ << root.getComment(commentAfter); + writeIndent(); + *document_ << root.getComment(commentAfter); } - this->indented_ = false; + indented_ = false; } -bool StyledStreamWriter::hasCommentForValue(const Value& value) -{ +bool StyledStreamWriter::hasCommentForValue(const Value& value) { return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter); + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); } ////////////////////////// // BuiltStyledStreamWriter /// Scoped enums are not available until C++11. -struct CommentStyle -{ +struct CommentStyle { /// Decide whether to write comments. - enum Enum - { - None, ///< Drop all comments. - Most, ///< Recover odd behavior of previous versions (not implemented yet). - All ///< Keep all comments. + enum Enum { + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. }; }; struct BuiltStyledStreamWriter : public StreamWriter { - BuiltStyledStreamWriter(JSONCPP_STRING const& indentation, - CommentStyle::Enum cs, - JSONCPP_STRING const& colonSymbol, - JSONCPP_STRING const& nullSymbol, - JSONCPP_STRING const& endingLineFeedSymbol, - bool useSpecialFloats, unsigned int precision); + BuiltStyledStreamWriter( + JSONCPP_STRING const& indentation, + CommentStyle::Enum cs, + JSONCPP_STRING const& colonSymbol, + JSONCPP_STRING const& nullSymbol, + JSONCPP_STRING const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision); int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE; - private: void writeValue(Value const& value); void writeArrayValue(Value const& value); @@ -995,10 +911,13 @@ struct BuiltStyledStreamWriter : public StreamWriter unsigned int precision_; }; BuiltStyledStreamWriter::BuiltStyledStreamWriter( - JSONCPP_STRING const& indentation, CommentStyle::Enum cs, - JSONCPP_STRING const& colonSymbol, JSONCPP_STRING const& nullSymbol, - JSONCPP_STRING const& endingLineFeedSymbol, bool useSpecialFloats, - unsigned int precision) + JSONCPP_STRING const& indentation, + CommentStyle::Enum cs, + JSONCPP_STRING const& colonSymbol, + JSONCPP_STRING const& nullSymbol, + JSONCPP_STRING const& endingLineFeedSymbol, + bool useSpecialFloats, + unsigned int precision) : rightMargin_(74) , indentation_(indentation) , cs_(cs) @@ -1013,276 +932,247 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter( } int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout) { - this->sout_ = sout; - this->addChildValues_ = false; - this->indented_ = true; - this->indentString_.clear(); - this->writeCommentBeforeValue(root); - if (!this->indented_) - this->writeIndent(); - this->indented_ = true; - this->writeValue(root); - this->writeCommentAfterValueOnSameLine(root); - *this->sout_ << this->endingLineFeedSymbol_; - this->sout_ = NULL; + sout_ = sout; + addChildValues_ = false; + indented_ = true; + indentString_.clear(); + writeCommentBeforeValue(root); + if (!indented_) writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *sout_ << endingLineFeedSymbol_; + sout_ = NULL; return 0; } -void BuiltStyledStreamWriter::writeValue(Value const& value) -{ +void BuiltStyledStreamWriter::writeValue(Value const& value) { switch (value.type()) { - case nullValue: - this->pushValue(this->nullSymbol_); - break; - case intValue: - this->pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - this->pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - this->pushValue(valueToString(value.asDouble(), this->useSpecialFloats_, - this->precision_)); - break; - case stringValue: { - // Is NULL is possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - this->pushValue( - valueToQuotedStringN(str, static_cast(end - str))); - else - this->pushValue(""); - break; - } - case booleanValue: - this->pushValue(valueToString(value.asBool())); - break; - case arrayValue: - this->writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - this->pushValue("{}"); - else { - this->writeWithIndent("{"); - this->indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - JSONCPP_STRING const& name = *it; - Value const& childValue = value[name]; - this->writeCommentBeforeValue(childValue); - this->writeWithIndent(valueToQuotedStringN( - name.data(), static_cast(name.length()))); - *this->sout_ << this->colonSymbol_; - this->writeValue(childValue); - if (++it == members.end()) { - this->writeCommentAfterValueOnSameLine(childValue); - break; - } - *this->sout_ << ","; - this->writeCommentAfterValueOnSameLine(childValue); + case nullValue: + pushValue(nullSymbol_); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); + break; + case stringValue: + { + // Is NULL is possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + JSONCPP_STRING const& name = *it; + Value const& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedStringN(name.data(), static_cast(name.length()))); + *sout_ << colonSymbol_; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; } - this->unindent(); - this->writeWithIndent("}"); + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); } - } break; + unindent(); + writeWithIndent("}"); + } + } break; } } -void BuiltStyledStreamWriter::writeArrayValue(Value const& value) -{ +void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { unsigned size = value.size(); if (size == 0) - this->pushValue("[]"); + pushValue("[]"); else { - bool isMultiLine = - (this->cs_ == CommentStyle::All) || this->isMultineArray(value); + bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); if (isMultiLine) { - this->writeWithIndent("["); - this->indent(); - bool hasChildValue = !this->childValues_.empty(); + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); unsigned index = 0; for (;;) { Value const& childValue = value[index]; - this->writeCommentBeforeValue(childValue); + writeCommentBeforeValue(childValue); if (hasChildValue) - this->writeWithIndent(this->childValues_[index]); + writeWithIndent(childValues_[index]); else { - if (!this->indented_) - this->writeIndent(); - this->indented_ = true; - this->writeValue(childValue); - this->indented_ = false; + if (!indented_) writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; } if (++index == size) { - this->writeCommentAfterValueOnSameLine(childValue); + writeCommentAfterValueOnSameLine(childValue); break; } - *this->sout_ << ","; - this->writeCommentAfterValueOnSameLine(childValue); + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); } - this->unindent(); - this->writeWithIndent("]"); + unindent(); + writeWithIndent("]"); } else // output on a single line { - assert(this->childValues_.size() == size); - *this->sout_ << "["; - if (!this->indentation_.empty()) - *this->sout_ << " "; + assert(childValues_.size() == size); + *sout_ << "["; + if (!indentation_.empty()) *sout_ << " "; for (unsigned index = 0; index < size; ++index) { if (index > 0) - *this->sout_ << ((!this->indentation_.empty()) ? ", " : ","); - *this->sout_ << this->childValues_[index]; + *sout_ << ((!indentation_.empty()) ? ", " : ","); + *sout_ << childValues_[index]; } - if (!this->indentation_.empty()) - *this->sout_ << " "; - *this->sout_ << "]"; + if (!indentation_.empty()) *sout_ << " "; + *sout_ << "]"; } } } -bool BuiltStyledStreamWriter::isMultineArray(Value const& value) -{ +bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= this->rightMargin_; - this->childValues_.clear(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { Value const& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + childValue.size() > 0); } if (!isMultiLine) // check if line length > max line length { - this->childValues_.reserve(size); - this->addChildValues_ = true; + childValues_.reserve(size); + addChildValues_ = true; ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' for (ArrayIndex index = 0; index < size; ++index) { if (hasCommentForValue(value[index])) { isMultiLine = true; } - this->writeValue(value[index]); - lineLength += - static_cast(this->childValues_[index].length()); + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); } - this->addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= this->rightMargin_; + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; } return isMultiLine; } -void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) -{ - if (this->addChildValues_) - this->childValues_.push_back(value); +void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) { + if (addChildValues_) + childValues_.push_back(value); else - *this->sout_ << value; + *sout_ << value; } -void BuiltStyledStreamWriter::writeIndent() -{ +void BuiltStyledStreamWriter::writeIndent() { // blep intended this to look at the so-far-written string // to determine whether we are already indented, but // with a stream we cannot do that. So we rely on some saved state. // The caller checks indented_. - if (!this->indentation_.empty()) { + if (!indentation_.empty()) { // In this case, drop newlines too. - *this->sout_ << '\n' << this->indentString_; + *sout_ << '\n' << indentString_; } } -void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) -{ - if (!this->indented_) - this->writeIndent(); - *this->sout_ << value; - this->indented_ = false; +void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) { + if (!indented_) writeIndent(); + *sout_ << value; + indented_ = false; } -void BuiltStyledStreamWriter::indent() -{ - this->indentString_ += this->indentation_; -} +void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } -void BuiltStyledStreamWriter::unindent() -{ - assert(this->indentString_.size() >= this->indentation_.size()); - this->indentString_.resize(this->indentString_.size() - - this->indentation_.size()); +void BuiltStyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); } -void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) -{ - if (this->cs_ == CommentStyle::None) - return; +void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { + if (cs_ == CommentStyle::None) return; if (!root.hasComment(commentBefore)) return; - if (!this->indented_) - this->writeIndent(); + if (!indented_) writeIndent(); const JSONCPP_STRING& comment = root.getComment(commentBefore); JSONCPP_STRING::const_iterator iter = comment.begin(); while (iter != comment.end()) { - *this->sout_ << *iter; - if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/')) + *sout_ << *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) // writeIndent(); // would write extra newline - *this->sout_ << this->indentString_; + *sout_ << indentString_; ++iter; } - this->indented_ = false; + indented_ = false; } -void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( - Value const& root) -{ - if (this->cs_ == CommentStyle::None) - return; +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { + if (cs_ == CommentStyle::None) return; if (root.hasComment(commentAfterOnSameLine)) - *this->sout_ << " " + root.getComment(commentAfterOnSameLine); + *sout_ << " " + root.getComment(commentAfterOnSameLine); if (root.hasComment(commentAfter)) { - this->writeIndent(); - *this->sout_ << root.getComment(commentAfter); + writeIndent(); + *sout_ << root.getComment(commentAfter); } } // static -bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) -{ +bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter); + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); } /////////////// // StreamWriter StreamWriter::StreamWriter() - : sout_(NULL) + : sout_(NULL) { } StreamWriter::~StreamWriter() { } StreamWriter::Factory::~Factory() -{ -} +{} StreamWriterBuilder::StreamWriterBuilder() { - setDefaults(&this->settings_); + setDefaults(&settings_); } StreamWriterBuilder::~StreamWriterBuilder() -{ -} +{} StreamWriter* StreamWriterBuilder::newStreamWriter() const { - JSONCPP_STRING indentation = this->settings_["indentation"].asString(); - JSONCPP_STRING cs_str = this->settings_["commentStyle"].asString(); - bool eyc = this->settings_["enableYAMLCompatibility"].asBool(); - bool dnp = this->settings_["dropNullPlaceholders"].asBool(); - bool usf = this->settings_["useSpecialFloats"].asBool(); - unsigned int pre = this->settings_["precision"].asUInt(); + JSONCPP_STRING indentation = settings_["indentation"].asString(); + JSONCPP_STRING cs_str = settings_["commentStyle"].asString(); + bool eyc = settings_["enableYAMLCompatibility"].asBool(); + bool dnp = settings_["dropNullPlaceholders"].asBool(); + bool usf = settings_["useSpecialFloats"].asBool(); + unsigned int pre = settings_["precision"].asUInt(); CommentStyle::Enum cs = CommentStyle::All; if (cs_str == "All") { cs = CommentStyle::All; @@ -1301,11 +1191,11 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const if (dnp) { nullSymbol.clear(); } - if (pre > 17) - pre = 17; + if (pre > 17) pre = 17; JSONCPP_STRING endingLineFeedSymbol; - return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, - endingLineFeedSymbol, usf, pre); + return new BuiltStyledStreamWriter( + indentation, cs, + colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); } static void getValidWriterKeys(std::set* valid_keys) { @@ -1320,24 +1210,23 @@ static void getValidWriterKeys(std::set* valid_keys) bool StreamWriterBuilder::validate(Json::Value* invalid) const { Json::Value my_invalid; - if (!invalid) - invalid = &my_invalid; // so we do not need to test for NULL + if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL Json::Value& inv = *invalid; std::set valid_keys; getValidWriterKeys(&valid_keys); - Value::Members keys = this->settings_.getMemberNames(); + Value::Members keys = settings_.getMemberNames(); size_t n = keys.size(); for (size_t i = 0; i < n; ++i) { JSONCPP_STRING const& key = keys[i]; if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = this->settings_[key]; + inv[key] = settings_[key]; } } return 0u == inv.size(); } Value& StreamWriterBuilder::operator[](JSONCPP_STRING key) { - return this->settings_[key]; + return settings_[key]; } // static void StreamWriterBuilder::setDefaults(Json::Value* settings) @@ -1352,17 +1241,14 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings) //! [StreamWriterBuilderDefaults] } -JSONCPP_STRING writeString(StreamWriter::Factory const& builder, - Value const& root) -{ +JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) { JSONCPP_OSTRINGSTREAM sout; StreamWriterPtr const writer(builder.newStreamWriter()); writer->write(root, &sout); return sout.str(); } -JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) -{ +JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) { StreamWriterBuilder builder; StreamWriterPtr const writer(builder.newStreamWriter()); writer->write(root, &sout); From 410bf8ed4fb225c0f202c9ccb0859ad8c66065c2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 14:51:14 -0400 Subject: [PATCH 0578/1519] cmStandardLevelResolver: Fix size assertion in constructor Assert sizes of the constructed vectors, not the moved-from inputs. --- Source/cmStandardLevelResolver.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 85411e6fe50..b198a0019fb 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -62,7 +62,7 @@ struct StanardLevelComputer , Levels(std::move(levels)) , LevelsAsStrings(std::move(levelsStr)) { - assert(levels.size() == levelsStr.size()); + assert(this->Levels.size() == this->LevelsAsStrings.size()); } std::string GetCompileOptionDef(cmMakefile* makefile, From dbfb50cd72e91000848a12e9e70a066c185828f7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 14:52:33 -0400 Subject: [PATCH 0579/1519] cmFileAPICodemodel: Assert input in DirectoryObject::DumpInstaller This tells clang-analyzer that the `gen` argument is never `nullptr`. --- Source/cmFileAPICodemodel.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index ff11f4a797b..efe1ab6fb85 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -874,6 +874,7 @@ Json::Value DirectoryObject::DumpInstallers() Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) { + assert(gen); Json::Value installer = Json::objectValue; // Exclude subdirectory installers. They are implementation details. From c1b575f4d110231617a7cb62187d553d67faad31 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 14:50:24 -0400 Subject: [PATCH 0580/1519] clang-analyzer: rename from scan-build in comments --- CTestCustom.cmake.in | 2 +- Source/LexerParser/cmCTestResourceGroupsLexer.cxx | 2 +- Source/LexerParser/cmCTestResourceGroupsLexer.in.l | 2 +- Source/LexerParser/cmCommandArgumentLexer.cxx | 2 +- Source/LexerParser/cmCommandArgumentLexer.in.l | 2 +- Source/LexerParser/cmDependsJavaLexer.cxx | 2 +- Source/LexerParser/cmDependsJavaLexer.in.l | 2 +- Source/LexerParser/cmExprLexer.cxx | 2 +- Source/LexerParser/cmExprLexer.in.l | 2 +- Source/LexerParser/cmFortranLexer.cxx | 2 +- Source/LexerParser/cmFortranLexer.in.l | 2 +- Source/LexerParser/cmGccDepfileLexer.cxx | 2 +- Source/LexerParser/cmGccDepfileLexer.in.l | 2 +- Utilities/cmjsoncpp/src/lib_json/json_reader.cpp | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index 238ca1590ba..682297e14c4 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -83,7 +83,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "compilation completed with warnings" # PGI "[0-9]+ Warning\\(s\\) detected" # SunPro - # scanbuild exceptions + # clang-analyzer exceptions "char_traits.h:.*: warning: Null pointer argument in call to string length function" "stl_construct.h:.*: warning: Forming reference to null pointer" ".*stl_uninitialized.h:75:19: warning: Forming reference to null pointer.*" diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.cxx b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx index de07c4693a3..85b379bbe24 100644 --- a/Source/LexerParser/cmCTestResourceGroupsLexer.cxx +++ b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx @@ -659,7 +659,7 @@ Modify cmCTestResourceGroupsLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include "cmCTestResourceGroupsLexerHelper.h" diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.in.l b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l index 2aabea48dbe..2befa85c8a5 100644 --- a/Source/LexerParser/cmCTestResourceGroupsLexer.in.l +++ b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l @@ -18,7 +18,7 @@ Modify cmCTestResourceGroupsLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include "cmCTestResourceGroupsLexerHelper.h" diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx index 46220ffc7cb..4b7eb798189 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.cxx +++ b/Source/LexerParser/cmCommandArgumentLexer.cxx @@ -664,7 +664,7 @@ Modify cmCommandArgumentLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include "cmCommandArgumentParserHelper.h" diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l index 8ad23351acf..6b4f9a9667d 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.in.l +++ b/Source/LexerParser/cmCommandArgumentLexer.in.l @@ -18,7 +18,7 @@ Modify cmCommandArgumentLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include "cmCommandArgumentParserHelper.h" diff --git a/Source/LexerParser/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx index d703e3c9577..bfe7e64f0c3 100644 --- a/Source/LexerParser/cmDependsJavaLexer.cxx +++ b/Source/LexerParser/cmDependsJavaLexer.cxx @@ -860,7 +860,7 @@ Modify cmDependsJavaLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include diff --git a/Source/LexerParser/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l index 3dd3c224aa3..942e0075fad 100644 --- a/Source/LexerParser/cmDependsJavaLexer.in.l +++ b/Source/LexerParser/cmDependsJavaLexer.in.l @@ -18,7 +18,7 @@ Modify cmDependsJavaLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx index 72e59b689c5..5a76590a1a5 100644 --- a/Source/LexerParser/cmExprLexer.cxx +++ b/Source/LexerParser/cmExprLexer.cxx @@ -664,7 +664,7 @@ Modify cmExprLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include "cmExprParserHelper.h" diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l index f8a42243183..90c1cc3ab12 100644 --- a/Source/LexerParser/cmExprLexer.in.l +++ b/Source/LexerParser/cmExprLexer.in.l @@ -18,7 +18,7 @@ Modify cmExprLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include "cmExprParserHelper.h" diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx index bcda77c30b9..c3d00000415 100644 --- a/Source/LexerParser/cmFortranLexer.cxx +++ b/Source/LexerParser/cmFortranLexer.cxx @@ -838,7 +838,7 @@ Modify cmFortranLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #undef YY_NO_UNPUT diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l index 3d38a7dada6..05769a1e31f 100644 --- a/Source/LexerParser/cmFortranLexer.in.l +++ b/Source/LexerParser/cmFortranLexer.in.l @@ -27,7 +27,7 @@ Modify cmFortranLexer.cxx: /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #undef YY_NO_UNPUT diff --git a/Source/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx index 3630f4ef8ec..194ae0c493d 100644 --- a/Source/LexerParser/cmGccDepfileLexer.cxx +++ b/Source/LexerParser/cmGccDepfileLexer.cxx @@ -645,7 +645,7 @@ static const flex_int16_t yy_chk[46] = /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include #include diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l index c83cb75e813..aa2351e84ee 100644 --- a/Source/LexerParser/cmGccDepfileLexer.in.l +++ b/Source/LexerParser/cmGccDepfileLexer.in.l @@ -4,7 +4,7 @@ /* IWYU pragma: no_forward_declare yyguts_t */ -#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */ +#ifndef __clang_analyzer__ /* Suppress clang-analyzer warnings */ #include #include diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp index 6eeba0e65e0..8291cc65452 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp @@ -1728,7 +1728,7 @@ bool OurReader::decodeUnicodeCodePoint(Token& token, Location end, unsigned int& unicode) { - unicode = 0; // Convince scanbuild this is always initialized before use. + unicode = 0; // Convince clang-analyzer that this is initialized before use. if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; if (unicode >= 0xD800 && unicode <= 0xDBFF) { From b6c4d93dcd85b8e2c512abf83c25c2270cead1c8 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 14:53:54 -0400 Subject: [PATCH 0581/1519] clang-analyzer: Suppress warnings in intentional use-after-move cases --- Tests/CMakeLib/testOptional.cxx | 2 ++ Tests/CMakeLib/testString.cxx | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Tests/CMakeLib/testOptional.cxx b/Tests/CMakeLib/testOptional.cxx index 2d7dd7c6873..9d4b72aa421 100644 --- a/Tests/CMakeLib/testOptional.cxx +++ b/Tests/CMakeLib/testOptional.cxx @@ -301,12 +301,14 @@ static bool testMoveConstruct(std::vector& expected) cm::optional o3{}; const cm::optional o4{ std::move(o3) }; +#ifndef __clang_analyzer__ /* cplusplus.Move */ expected = { { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, { Event::MOVE_CONSTRUCT, &*o2, &*o1, 4 }, { Event::DESTRUCT, &*o2, nullptr, 4 }, { Event::DESTRUCT, &*o1, nullptr, 4 }, }; +#endif return true; } diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx index ad800cf0626..5a9cad18bc0 100644 --- a/Tests/CMakeLib/testString.cxx +++ b/Tests/CMakeLib/testString.cxx @@ -326,12 +326,14 @@ static bool testConstructMove() std::cout << "testConstructMove()\n"; cm::String s1 = std::string("abc"); cm::String s2 = std::move(s1); +#ifndef __clang_analyzer__ /* cplusplus.Move */ ASSERT_TRUE(s1.data() == nullptr); ASSERT_TRUE(s1.size() == 0); ASSERT_TRUE(s2.size() == 3); ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0); ASSERT_TRUE(s1.is_stable()); ASSERT_TRUE(s2.is_stable()); +#endif return true; } @@ -356,12 +358,14 @@ static bool testAssignMove() cm::String s1 = std::string("abc"); cm::String s2; s2 = std::move(s1); +#ifndef __clang_analyzer__ /* cplusplus.Move */ ASSERT_TRUE(s1.data() == nullptr); ASSERT_TRUE(s1.size() == 0); ASSERT_TRUE(s2.size() == 3); ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0); ASSERT_TRUE(s1.is_stable()); ASSERT_TRUE(s2.is_stable()); +#endif return true; } From adc38da49ff3549a74afceb01b06500b40bf0ee6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 11:46:36 -0400 Subject: [PATCH 0582/1519] ci: add clang-analyzer to Fedora base image --- .gitlab/ci/docker/fedora34/install_deps.sh | 1 + .gitlab/os-linux.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index dfd7db80936..7d099feccec 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -25,6 +25,7 @@ dnf install --setopt=install_weak_deps=False -y \ # Install lint tools. dnf install --setopt=install_weak_deps=False -y \ + clang-analyzer \ codespell # Tools needed for the test suite. diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index dcaa6438470..e1a70ffd0ac 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -69,7 +69,7 @@ ### Fedora .fedora34: - image: "kitware/cmake:ci-fedora34-x86_64-2021-05-21" + image: "kitware/cmake:ci-fedora34-x86_64-2021-06-03" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" From da14f4e19e72f2d7b7ea71ed420880358715a8f2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 12:00:47 -0400 Subject: [PATCH 0583/1519] gitlab-ci: add job to build with clang-analyzer Update the exceptions in `CTestCustom.cmake.in` to match this job's needs. Drop exceptions needed only by our previous nightly build. --- .gitlab-ci.yml | 9 ++++++ .../configure_fedora34_clang_analyzer.cmake | 1 + .gitlab/ci/env_fedora34_clang_analyzer.sh | 2 ++ .gitlab/os-linux.yml | 9 ++++++ CTestCustom.cmake.in | 29 +++++++------------ 5 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 .gitlab/ci/configure_fedora34_clang_analyzer.cmake create mode 100644 .gitlab/ci/env_fedora34_clang_analyzer.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aac1d9c91ed..bf002228c4e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -129,6 +129,15 @@ lint:fedora34-sphinx: CMAKE_CI_JOB_CONTINUOUS: "true" CMAKE_CI_JOB_HELP: "true" +lint:fedora34-clang-analyzer: + extends: + - .fedora34_clang_analyzer + - .cmake_build_linux + - .linux_builder_tags_qt + - .run_automatically + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + # Linux builds build:centos6-x86_64: diff --git a/.gitlab/ci/configure_fedora34_clang_analyzer.cmake b/.gitlab/ci/configure_fedora34_clang_analyzer.cmake new file mode 100644 index 00000000000..e00f8a7b1bc --- /dev/null +++ b/.gitlab/ci/configure_fedora34_clang_analyzer.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora34_common.cmake") diff --git a/.gitlab/ci/env_fedora34_clang_analyzer.sh b/.gitlab/ci/env_fedora34_clang_analyzer.sh new file mode 100644 index 00000000000..d732c0ba20b --- /dev/null +++ b/.gitlab/ci/env_fedora34_clang_analyzer.sh @@ -0,0 +1,2 @@ +export CC=/usr/libexec/ccc-analyzer +export CXX=/usr/libexec/c++-analyzer diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index e1a70ffd0ac..a8c07d8c3e1 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -85,6 +85,15 @@ CTEST_NO_WARNINGS_ALLOWED: 1 CMake_SKIP_INSTALL: 1 +.fedora34_clang_analyzer: + extends: .fedora34 + + variables: + CMAKE_CONFIGURATION: fedora34_clang_analyzer + CMAKE_BUILD_TYPE: Debug + CTEST_NO_WARNINGS_ALLOWED: 1 + CMake_SKIP_INSTALL: 1 + .fedora34_sphinx: extends: .fedora34 diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index 682297e14c4..093c1d889e3 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -84,27 +84,20 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "[0-9]+ Warning\\(s\\) detected" # SunPro # clang-analyzer exceptions - "char_traits.h:.*: warning: Null pointer argument in call to string length function" - "stl_construct.h:.*: warning: Forming reference to null pointer" - ".*stl_uninitialized.h:75:19: warning: Forming reference to null pointer.*" - ".*stl_vector.h:.*: warning: Returning null reference.*" - "warning: Value stored to 'yymsg' is never read" - "warning: Value stored to 'yytoken' is never read" - "index_encoder.c.241.2. warning: Value stored to .out_start. is never read" - "index.c.*warning: Access to field.*results in a dereference of a null pointer.*loaded from variable.*" - "cmCommandArgumentLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes" - "cmDependsJavaLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes" - "cmExprLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes" - "cmListFileLexer.c:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes" - "cmFortranLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes" - "testProcess.*warning: Dereference of null pointer .loaded from variable .invalidAddress.." + "cmListFileLexer.c:[0-9]+:[0-9]+: warning: Array subscript is undefined" + "jsoncpp/src/.*:[0-9]+:[0-9]+: warning: Value stored to .* is never read" + "liblzma/common/index_encoder.c:[0-9]+:[0-9]+: warning: Value stored to '[^']+' during its initialization is never read" + "liblzma/liblzma/common/index.c:[0-9]+:[0-9]+: warning: Access to field '[^']+' results in a dereference of a null pointer" "liblzma/simple/x86.c:[0-9]+:[0-9]+: warning: The result of the '<<' expression is undefined" - "liblzma/common/index_encoder.c:[0-9]+:[0-9]+: warning: Value stored to .* during its initialization is never read" - "libuv/src/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer" - "libuv/src/.*:[0-9]+:[0-9]+: warning: The left operand of '==' is a garbage value" + "librhash/librhash/.*:[0-9]+:[0-9]+: warning: The left operand of '[^']+' is a garbage value" "libuv/src/.*:[0-9]+:[0-9]+: warning: 1st function call argument is an uninitialized value" + "libuv/src/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer" + "libuv/src/.*:[0-9]+:[0-9]+: warning: The left operand of '[^']+' is a garbage value" + "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Access to field '[^']+' results in a dereference of a null pointer" "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer" - "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Value stored to .* is never read" + "nghttp2/lib/.*:[0-9]+:[0-9]+: warning: Value stored to '[^']+' is never read" + "zstd/lib/.*:[0-9]+:[0-9]+: warning: Assigned value is garbage or undefined" + "zstd/lib/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer" ) if(NOT "@CMAKE_GENERATOR@" MATCHES "Xcode") From 186e6aa66f4326c7b92adcd68870620e3ffb7734 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 4 Jun 2021 00:01:10 -0400 Subject: [PATCH 0584/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7be1b9ef718..90bc5b5eb14 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210603) +set(CMake_VERSION_PATCH 20210604) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 07d639072800dcd189a9c461c4d1e0c04807e18f Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 08:30:12 -0400 Subject: [PATCH 0585/1519] Tests: Add case covering FindPkgConfig creation of empty targets --- .../FindPkgConfig/FindPkgConfig_empty_target.cmake | 13 +++++++++++++ Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake | 1 + .../FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc | 5 +++++ 3 files changed, 19 insertions(+) create mode 100644 Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake create mode 100644 Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake new file mode 100644 index 00000000000..fd774b9d654 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake @@ -0,0 +1,13 @@ +# Prepare environment to reuse empty.pc +file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pc-empty/lib/pkgconfig" PC_PATH) +if(UNIX) + string(REPLACE "\\ " " " PC_PATH "${PC_PATH}") +endif() +set(ENV{PKG_CONFIG_PATH} "${PC_PATH}") + +find_package(PkgConfig REQUIRED) +pkg_search_module(Empty REQUIRED empty IMPORTED_TARGET) + +if(NOT Empty_MODULE_NAME STREQUAL "empty") + message(FATAL_ERROR "Wrong value for Empty_MODULE_NAME. Expected: empty, got: ${Empty_MODULE_NAME}") +endif() diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index 4e6eef6f008..e7f008ca530 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -29,4 +29,5 @@ if (PKG_CONFIG_FOUND) run_cmake(FindPkgConfig_IMPORTED_TARGET) run_cmake(FindPkgConfig_VERSION_OPERATORS) run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME) + run_cmake(FindPkgConfig_empty_target) endif () diff --git a/Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc b/Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc new file mode 100644 index 00000000000..954c5f81c1f --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/pc-empty/lib/pkgconfig/empty.pc @@ -0,0 +1,5 @@ +Name: Empty +Description: Dummy package to test empty target +Version: 1.0 +Libs: +Cflags: From 6f14205e0885853184d482f901d62fa5c10ac4f9 Mon Sep 17 00:00:00 2001 From: Adam Badura Date: Wed, 5 May 2021 07:17:27 +0200 Subject: [PATCH 0586/1519] FindPkgConfig: Always create the imported target Fixes: #22180 --- Modules/FindPkgConfig.cmake | 4 +--- Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 38c8da75481..3bc9dba167a 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -265,9 +265,7 @@ endfunction() # create an imported target from all the information returned by pkg-config function(_pkg_create_imp_target _prefix _imp_target_global) - # only create the target if it is linkable, i.e. no executables - if (NOT TARGET PkgConfig::${_prefix} - AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_LDFLAGS_OTHER OR ${_prefix}_CFLAGS_OTHER )) + if (NOT TARGET PkgConfig::${_prefix}) if(${_imp_target_global}) set(_global_opt "GLOBAL") else() diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake index fd774b9d654..cb3dd69af51 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_empty_target.cmake @@ -11,3 +11,7 @@ pkg_search_module(Empty REQUIRED empty IMPORTED_TARGET) if(NOT Empty_MODULE_NAME STREQUAL "empty") message(FATAL_ERROR "Wrong value for Empty_MODULE_NAME. Expected: empty, got: ${Empty_MODULE_NAME}") endif() + +if(NOT TARGET PkgConfig::Empty) + message(FATAL_ERROR "PkgConfig::Empty target not created") +endif() From 2ef3ea394f424bf2397878b00725b93ebe04c589 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 23 Apr 2021 11:19:11 -0400 Subject: [PATCH 0587/1519] file(GET_RUNTIME_DEPENDENCIES): Add undocumented RPATH_PREFIX option --- Source/cmBinUtilsMacOSMachOLinker.cxx | 22 +++++++----- Source/cmBinUtilsMacOSMachOLinker.h | 2 ++ Source/cmFileCommand.cxx | 7 ++++ Source/cmRuntimeDependencyArchive.cxx | 13 +++++-- Source/cmRuntimeDependencyArchive.h | 4 ++- .../RunCMakeTest.cmake | 1 + .../macos-rpath.cmake | 35 +++++++++++++++++++ 7 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx index 0f47146c5e9..47f77d8b996 100644 --- a/Source/cmBinUtilsMacOSMachOLinker.cxx +++ b/Source/cmBinUtilsMacOSMachOLinker.cxx @@ -65,18 +65,18 @@ bool cmBinUtilsMacOSMachOLinker::ScanDependencies( if (!executableFile.empty()) { executablePath = cmSystemTools::GetFilenamePath(executableFile); } - return this->ScanDependencies(file, executablePath); -} - -bool cmBinUtilsMacOSMachOLinker::ScanDependencies( - std::string const& file, std::string const& executablePath) -{ std::vector libs; std::vector rpaths; if (!this->Tool->GetFileInfo(file, libs, rpaths)) { return false; } + return this->ScanDependencies(file, libs, rpaths, executablePath); +} +bool cmBinUtilsMacOSMachOLinker::ScanDependencies( + std::string const& file, std::vector const& libs, + std::vector const& rpaths, std::string const& executablePath) +{ std::string loaderPath = cmSystemTools::GetFilenamePath(file); return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths); } @@ -98,8 +98,14 @@ bool cmBinUtilsMacOSMachOLinker::GetFileDependencies( !IsMissingSystemDylib(path)) { auto filename = cmSystemTools::GetFilenameName(path); bool unique; - this->Archive->AddResolvedPath(filename, path, unique); - if (unique && !this->ScanDependencies(path, executablePath)) { + std::vector libs; + std::vector depRpaths; + if (!this->Tool->GetFileInfo(path, libs, depRpaths)) { + return false; + } + this->Archive->AddResolvedPath(filename, path, unique, depRpaths); + if (unique && + !this->ScanDependencies(path, libs, depRpaths, executablePath)) { return false; } } diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h index 1c4a5fcd3c8..eae23cc88b9 100644 --- a/Source/cmBinUtilsMacOSMachOLinker.h +++ b/Source/cmBinUtilsMacOSMachOLinker.h @@ -27,6 +27,8 @@ class cmBinUtilsMacOSMachOLinker : public cmBinUtilsLinker std::unique_ptr Tool; bool ScanDependencies(std::string const& file, + std::vector const& libs, + std::vector const& rpaths, std::string const& executablePath); bool GetFileDependencies(std::vector const& names, diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index f2d4cdad4e5..b685d14fce6 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3032,6 +3032,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, std::string ResolvedDependenciesVar; std::string UnresolvedDependenciesVar; std::string ConflictingDependenciesPrefix; + std::string RPathPrefix; std::string BundleExecutable; std::vector Executables; std::vector Libraries; @@ -3053,6 +3054,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, &Arguments::UnresolvedDependenciesVar) .Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s, &Arguments::ConflictingDependenciesPrefix) + .Bind("RPATH_PREFIX"_s, &Arguments::RPathPrefix) .Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable) .Bind("EXECUTABLES"_s, &Arguments::Executables) .Bind("LIBRARIES"_s, &Arguments::Libraries) @@ -3135,6 +3137,11 @@ bool HandleGetRuntimeDependenciesCommand(std::vector const& args, if (unique) { deps.push_back(firstPath); + if (!parsedArgs.RPathPrefix.empty()) { + status.GetMakefile().AddDefinition( + parsedArgs.RPathPrefix + "_" + firstPath, + cmJoin(archive.GetRPaths().at(firstPath), ";")); + } } else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) { conflictingDeps.push_back(val.first); std::vector paths; diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx index 57b4bd6b44c..06246d1df5f 100644 --- a/Source/cmRuntimeDependencyArchive.cxx +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -354,9 +354,9 @@ bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) const fileSearch(this->PostExcludeFiles))); } -void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name, - const std::string& path, - bool& unique) +void cmRuntimeDependencyArchive::AddResolvedPath( + const std::string& name, const std::string& path, bool& unique, + std::vector rpaths) { auto it = this->ResolvedPaths.emplace(name, std::set{}).first; unique = true; @@ -367,6 +367,7 @@ void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name, } } it->second.insert(path); + this->RPaths[path] = std::move(rpaths); } void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name) @@ -390,3 +391,9 @@ const std::set& cmRuntimeDependencyArchive::GetUnresolvedPaths() { return this->UnresolvedPaths; } + +const std::map>& +cmRuntimeDependencyArchive::GetRPaths() const +{ + return this->RPaths; +} diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h index 3f368c5a77d..20a38e203d1 100644 --- a/Source/cmRuntimeDependencyArchive.h +++ b/Source/cmRuntimeDependencyArchive.h @@ -45,12 +45,13 @@ class cmRuntimeDependencyArchive bool IsPostExcluded(const std::string& name) const; void AddResolvedPath(const std::string& name, const std::string& path, - bool& unique); + bool& unique, std::vector rpaths = {}); void AddUnresolvedPath(const std::string& name); cmMakefile* GetMakefile() const; const std::map>& GetResolvedPaths() const; const std::set& GetUnresolvedPaths() const; + const std::map>& GetRPaths() const; private: cmExecutionStatus& Status; @@ -70,4 +71,5 @@ class cmRuntimeDependencyArchive std::vector PostExcludeFilesStrict; std::map> ResolvedPaths; std::set UnresolvedPaths; + std::map> RPaths; }; diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake index c71b9baeda7..07679b711e3 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/RunCMakeTest.cmake @@ -36,6 +36,7 @@ endfunction() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") if(NOT CMake_INSTALL_NAME_TOOL_BUG) run_install_test(macos) + run_install_test(macos-rpath) run_install_test(macos-unresolved) run_install_test(macos-conflict) run_install_test(macos-notfile) diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake new file mode 100644 index 00000000000..798045f4cbd --- /dev/null +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-rpath.cmake @@ -0,0 +1,35 @@ +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/toplib.c" "extern void sublib1(void);\nextern void sublib2(void);\nvoid toplib(void)\n{\n sublib1();\n sublib2();\n}\n") +add_library(toplib SHARED "${CMAKE_BINARY_DIR}/toplib.c") +file(WRITE "${CMAKE_BINARY_DIR}/sublib1.c" "extern void sublib2(void);\nvoid sublib1(void)\n{\n sublib2();\n}\n") +add_library(sublib1 SHARED "${CMAKE_BINARY_DIR}/sublib1.c") +file(WRITE "${CMAKE_BINARY_DIR}/sublib2.c" "void sublib2(void)\n{\n}\n") +add_library(sublib2 SHARED "${CMAKE_BINARY_DIR}/sublib2.c") +target_link_libraries(toplib PRIVATE sublib1 sublib2) +target_link_libraries(sublib1 PRIVATE sublib2) +set_property(TARGET toplib PROPERTY INSTALL_RPATH "@loader_path/d1;@loader_path/d2") +set_property(TARGET sublib1 PROPERTY INSTALL_RPATH "@loader_path/;@loader_path/../d2") +install(TARGETS toplib DESTINATION lib) +install(TARGETS sublib1 DESTINATION lib/d1) +install(TARGETS sublib2 DESTINATION lib/d2) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$" + RPATH_PREFIX _rpaths + ) + + set(_expected_rpath "(^|;)@loader_path/;@loader_path/\\.\\./d2$") + set(_actual_rpath "${_rpaths_${CMAKE_INSTALL_PREFIX}/lib/d1/$}") + if(NOT _actual_rpath MATCHES "${_expected_rpath}") + message(FATAL_ERROR "Expected rpath:\n ${_expected_rpath}\nActual rpath:\n ${_actual_rpath}") + endif() + + # Since RPATH_PREFIX is an undocumented option for install(), we don't really need the rpath + # for the top files anyway. + if(DEFINED "_rpaths_${CMAKE_INSTALL_PREFIX}/lib/$") + message(FATAL_ERROR "rpath for top library should not be defined") + endif() + ]]) From 966f7250df01df7982aa6ff4117464d797b6bf10 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Tue, 4 May 2021 16:21:21 -0400 Subject: [PATCH 0588/1519] Refactor: Break up logic in cmSystemTools::ChangeRPath() --- Source/cmSystemTools.cxx | 178 ++++++++++++++++++++++++--------------- 1 file changed, 108 insertions(+), 70 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9b81bf2675b..b45228ee36d 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -14,6 +14,7 @@ #include "cmSystemTools.h" +#include #include #include @@ -65,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -2524,6 +2526,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have, #endif #if defined(CMake_USE_ELF_PARSER) +namespace { struct cmSystemToolsRPathInfo { unsigned long Position; @@ -2531,15 +2534,15 @@ struct cmSystemToolsRPathInfo std::string Name; std::string Value; }; -#endif + +using EmptyCallback = std::function; +using AdjustCallback = std::function&, const std::string&, const char*, std::string*)>; // FIXME: Dispatch if multiple formats are supported. -#if defined(CMake_USE_ELF_PARSER) -bool cmSystemTools::ChangeRPath(std::string const& file, - std::string const& oldRPath, - std::string const& newRPath, - bool removeEnvironmentRPath, std::string* emsg, - bool* changed) +bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback, + const AdjustCallback& adjustCallback, std::string* emsg, + bool* changed) { if (changed) { *changed = false; @@ -2566,17 +2569,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file, ++se_count; } if (se_count == 0) { - if (newRPath.empty()) { - // The new rpath is empty and there is no rpath anyway so it is - // okay. - return true; - } - if (emsg) { - *emsg = - cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ", - elf.GetErrorMessage()); - } - return false; + return emptyCallback(emsg, elf); } for (int i = 0; i < se_count; ++i) { @@ -2586,68 +2579,38 @@ bool cmSystemTools::ChangeRPath(std::string const& file, continue; } - // Make sure the current rpath contains the old rpath. - std::string::size_type pos = - cmSystemToolsFindRPath(se[i]->Value, oldRPath); - if (pos == std::string::npos) { - // If it contains the new rpath instead then it is okay. - if (cmSystemToolsFindRPath(se[i]->Value, newRPath) != - std::string::npos) { - remove_rpath = false; - continue; - } - if (emsg) { - std::ostringstream e; - /* clang-format off */ - e << "The current " << se_name[i] << " is:\n" - << " " << se[i]->Value << "\n" - << "which does not contain:\n" - << " " << oldRPath << "\n" - << "as was expected."; - /* clang-format on */ - *emsg = e.str(); - } - return false; - } - // Store information about the entry in the file. rp[rp_count].Position = se[i]->Position; rp[rp_count].Size = se[i]->Size; rp[rp_count].Name = se_name[i]; - std::string::size_type prefix_len = pos; - - // If oldRPath was at the end of the file's RPath, and newRPath is empty, - // we should remove the unnecessary ':' at the end. - if (newRPath.empty() && pos > 0 && se[i]->Value[pos - 1] == ':' && - pos + oldRPath.length() == se[i]->Value.length()) { - prefix_len--; - } - - // Construct the new value which preserves the part of the path - // not being changed. - if (!removeEnvironmentRPath) { - rp[rp_count].Value = se[i]->Value.substr(0, prefix_len); + // Adjust the rpath. + cm::optional outRPath; + if (!adjustCallback(outRPath, se[i]->Value, se_name[i], emsg)) { + return false; } - rp[rp_count].Value += newRPath; - rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length()); - if (!rp[rp_count].Value.empty()) { - remove_rpath = false; - } + if (outRPath) { + if (!outRPath->empty()) { + remove_rpath = false; + } - // Make sure there is enough room to store the new rpath and at - // least one null terminator. - if (rp[rp_count].Size < rp[rp_count].Value.length() + 1) { - if (emsg) { - *emsg = cmStrCat("The replacement path is too long for the ", - se_name[i], " entry."); + // Make sure there is enough room to store the new rpath and at + // least one null terminator. + if (rp[rp_count].Size < outRPath->length() + 1) { + if (emsg) { + *emsg = cmStrCat("The replacement path is too long for the ", + se_name[i], " entry."); + } + return false; } - return false; - } - // This entry is ready for update. - ++rp_count; + // This entry is ready for update. + rp[rp_count].Value = std::move(*outRPath); + ++rp_count; + } else { + remove_rpath = false; + } } } @@ -2706,6 +2669,81 @@ bool cmSystemTools::ChangeRPath(std::string const& file, } return true; } + +std::function MakeEmptyCallback( + const std::string& newRPath) +{ + return [newRPath](std::string* emsg, const cmELF& elf) -> bool { + if (newRPath.empty()) { + // The new rpath is empty and there is no rpath anyway so it is + // okay. + return true; + } + if (emsg) { + *emsg = + cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ", + elf.GetErrorMessage()); + } + return false; + }; +}; +} + +bool cmSystemTools::ChangeRPath(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, std::string* emsg, + bool* changed) +{ + auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath]( + cm::optional& outRPath, + const std::string& inRPath, const char* se_name, + std::string* emsg2) -> bool { + // Make sure the current rpath contains the old rpath. + std::string::size_type pos = cmSystemToolsFindRPath(inRPath, oldRPath); + if (pos == std::string::npos) { + // If it contains the new rpath instead then it is okay. + if (cmSystemToolsFindRPath(inRPath, newRPath) != std::string::npos) { + return true; + } + if (emsg2) { + std::ostringstream e; + /* clang-format off */ + e << "The current " << se_name << " is:\n" + << " " << inRPath << "\n" + << "which does not contain:\n" + << " " << oldRPath << "\n" + << "as was expected."; + /* clang-format on */ + *emsg2 = e.str(); + } + return false; + } + + std::string::size_type prefix_len = pos; + + // If oldRPath was at the end of the file's RPath, and newRPath is empty, + // we should remove the unnecessary ':' at the end. + if (newRPath.empty() && pos > 0 && inRPath[pos - 1] == ':' && + pos + oldRPath.length() == inRPath.length()) { + prefix_len--; + } + + // Construct the new value which preserves the part of the path + // not being changed. + outRPath.emplace(); + if (!removeEnvironmentRPath) { + *outRPath += inRPath.substr(0, prefix_len); + } + *outRPath += newRPath; + *outRPath += inRPath.substr(pos + oldRPath.length()); + + return true; + }; + + return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, + changed); +} #elif defined(CMake_USE_XCOFF_PARSER) bool cmSystemTools::ChangeRPath(std::string const& file, std::string const& oldRPath, From f73027b182710dd00524b2a4007838f9080c3ea1 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Tue, 4 May 2021 16:31:05 -0400 Subject: [PATCH 0589/1519] cmSystemTools: Add SetRPath() method --- Source/cmSystemTools.cxx | 32 ++++++++++++++++++++++++++++++++ Source/cmSystemTools.h | 6 +++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index b45228ee36d..10d2e50a4c1 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2744,6 +2744,24 @@ bool cmSystemTools::ChangeRPath(std::string const& file, return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, changed); } + +bool cmSystemTools::SetRPath(std::string const& file, + std::string const& newRPath, std::string* emsg, + bool* changed) +{ + auto adjustCallback = [newRPath](cm::optional& outRPath, + const std::string& inRPath, + const char* /*se_name*/, std::string * + /*emsg*/) -> bool { + if (inRPath != newRPath) { + outRPath = newRPath; + } + return true; + }; + + return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, + changed); +} #elif defined(CMake_USE_XCOFF_PARSER) bool cmSystemTools::ChangeRPath(std::string const& file, std::string const& oldRPath, @@ -2813,6 +2831,13 @@ bool cmSystemTools::ChangeRPath(std::string const& file, } return true; } + +bool cmSystemTools::SetRPath(std::string const& /*file*/, + std::string const& /*newRPath*/, + std::string* /*emsg*/, bool* /*changed*/) +{ + return false; +} #else bool cmSystemTools::ChangeRPath(std::string const& /*file*/, std::string const& /*oldRPath*/, @@ -2822,6 +2847,13 @@ bool cmSystemTools::ChangeRPath(std::string const& /*file*/, { return false; } + +bool cmSystemTools::SetRPath(std::string const& /*file*/, + std::string const& /*newRPath*/, + std::string* /*emsg*/, bool* /*changed*/) +{ + return false; +} #endif bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 5c3b5a9a0a9..44ccbf7a39a 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -456,13 +456,17 @@ class cmSystemTools : public cmsys::SystemTools static bool GuessLibraryInstallName(std::string const& fullPath, std::string& soname); - /** Try to set the RPATH in an ELF binary. */ + /** Try to change the RPATH in an ELF binary. */ static bool ChangeRPath(std::string const& file, std::string const& oldRPath, std::string const& newRPath, bool removeEnvironmentRPath, std::string* emsg = nullptr, bool* changed = nullptr); + /** Try to set the RPATH in an ELF binary. */ + static bool SetRPath(std::string const& file, std::string const& newRPath, + std::string* emsg = nullptr, bool* changed = nullptr); + /** Try to remove the RPATH from an ELF binary. */ static bool RemoveRPath(std::string const& file, std::string* emsg = nullptr, bool* removed = nullptr); From fac22d65962111e61a0fd7650d0efec963cc10ac Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 5 May 2021 11:32:15 -0400 Subject: [PATCH 0590/1519] Refactor: Modify file(RPATH_*) to use cmArgumentParser --- Source/cmFileCommand.cxx | 138 +++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 77 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index b685d14fce6..60a80864822 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -990,50 +990,42 @@ bool HandleRPathChangeCommand(std::vector const& args, { // Evaluate arguments. std::string file; - const char* oldRPath = nullptr; - const char* newRPath = nullptr; + std::string oldRPath; + std::string newRPath; bool removeEnvironmentRPath = false; - enum Doing - { - DoingNone, - DoingFile, - DoingOld, - DoingNew - }; - Doing doing = DoingNone; - for (unsigned int i = 1; i < args.size(); ++i) { - if (args[i] == "OLD_RPATH") { - doing = DoingOld; - } else if (args[i] == "NEW_RPATH") { - doing = DoingNew; - } else if (args[i] == "FILE") { - doing = DoingFile; - } else if (args[i] == "INSTALL_REMOVE_ENVIRONMENT_RPATH") { - removeEnvironmentRPath = true; - } else if (doing == DoingFile) { - file = args[i]; - doing = DoingNone; - } else if (doing == DoingOld) { - oldRPath = args[i].c_str(); - doing = DoingNone; - } else if (doing == DoingNew) { - newRPath = args[i].c_str(); - doing = DoingNone; - } else { - status.SetError( - cmStrCat("RPATH_CHANGE given unknown argument ", args[i])); - return false; - } + cmArgumentParser parser; + std::vector unknownArgs; + std::vector missingArgs; + std::vector parsedArgs; + parser.Bind("FILE"_s, file) + .Bind("OLD_RPATH"_s, oldRPath) + .Bind("NEW_RPATH"_s, newRPath) + .Bind("INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, removeEnvironmentRPath); + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs, + &parsedArgs); + if (!unknownArgs.empty()) { + status.SetError( + cmStrCat("RPATH_CHANGE given unknown argument ", unknownArgs.front())); + return false; + } + if (!missingArgs.empty()) { + status.SetError(cmStrCat("RPATH_CHANGE \"", missingArgs.front(), + "\" argument not given value.")); + return false; } if (file.empty()) { status.SetError("RPATH_CHANGE not given FILE option."); return false; } - if (!oldRPath) { + if (oldRPath.empty() && + std::find(parsedArgs.begin(), parsedArgs.end(), "OLD_RPATH") == + parsedArgs.end()) { status.SetError("RPATH_CHANGE not given OLD_RPATH option."); return false; } - if (!newRPath) { + if (newRPath.empty() && + std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") == + parsedArgs.end()) { status.SetError("RPATH_CHANGE not given NEW_RPATH option."); return false; } @@ -1070,23 +1062,20 @@ bool HandleRPathRemoveCommand(std::vector const& args, { // Evaluate arguments. std::string file; - enum Doing - { - DoingNone, - DoingFile - }; - Doing doing = DoingNone; - for (unsigned int i = 1; i < args.size(); ++i) { - if (args[i] == "FILE") { - doing = DoingFile; - } else if (doing == DoingFile) { - file = args[i]; - doing = DoingNone; - } else { - status.SetError( - cmStrCat("RPATH_REMOVE given unknown argument ", args[i])); - return false; - } + cmArgumentParser parser; + std::vector unknownArgs; + std::vector missingArgs; + parser.Bind("FILE"_s, file); + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs); + if (!unknownArgs.empty()) { + status.SetError( + cmStrCat("RPATH_REMOVE given unknown argument ", unknownArgs.front())); + return false; + } + if (!missingArgs.empty()) { + status.SetError(cmStrCat("RPATH_REMOVE \"", missingArgs.front(), + "\" argument not given value.")); + return false; } if (file.empty()) { status.SetError("RPATH_REMOVE not given FILE option."); @@ -1123,36 +1112,31 @@ bool HandleRPathCheckCommand(std::vector const& args, { // Evaluate arguments. std::string file; - const char* rpath = nullptr; - enum Doing - { - DoingNone, - DoingFile, - DoingRPath - }; - Doing doing = DoingNone; - for (unsigned int i = 1; i < args.size(); ++i) { - if (args[i] == "RPATH") { - doing = DoingRPath; - } else if (args[i] == "FILE") { - doing = DoingFile; - } else if (doing == DoingFile) { - file = args[i]; - doing = DoingNone; - } else if (doing == DoingRPath) { - rpath = args[i].c_str(); - doing = DoingNone; - } else { - status.SetError( - cmStrCat("RPATH_CHECK given unknown argument ", args[i])); - return false; - } + std::string rpath; + cmArgumentParser parser; + std::vector unknownArgs; + std::vector missingArgs; + std::vector parsedArgs; + parser.Bind("FILE"_s, file).Bind("RPATH"_s, rpath); + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs, + &parsedArgs); + if (!unknownArgs.empty()) { + status.SetError( + cmStrCat("RPATH_CHECK given unknown argument ", unknownArgs.front())); + return false; + } + if (!missingArgs.empty()) { + status.SetError(cmStrCat("RPATH_CHECK \"", missingArgs.front(), + "\" argument not given value.")); + return false; } if (file.empty()) { status.SetError("RPATH_CHECK not given FILE option."); return false; } - if (!rpath) { + if (rpath.empty() && + std::find(parsedArgs.begin(), parsedArgs.end(), "RPATH") == + parsedArgs.end()) { status.SetError("RPATH_CHECK not given RPATH option."); return false; } From 9f6cfe716918d7c28ddc906c49b75b922e36a8cf Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 5 May 2021 11:25:38 -0400 Subject: [PATCH 0591/1519] file: Add undocumented RPATH_SET command --- Source/cmFileCommand.cxx | 61 ++++++++++++++++++++++++++ Tests/RunCMake/file-RPATH/Common.cmake | 37 ++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 60a80864822..82546b915ec 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1057,6 +1057,66 @@ bool HandleRPathChangeCommand(std::vector const& args, return success; } +bool HandleRPathSetCommand(std::vector const& args, + cmExecutionStatus& status) +{ + // Evaluate arguments. + std::string file; + std::string newRPath; + cmArgumentParser parser; + std::vector unknownArgs; + std::vector missingArgs; + std::vector parsedArgs; + parser.Bind("FILE"_s, file).Bind("NEW_RPATH"_s, newRPath); + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs, + &parsedArgs); + if (!unknownArgs.empty()) { + status.SetError(cmStrCat("RPATH_SET given unrecognized argument \"", + unknownArgs.front(), "\".")); + return false; + } + if (!missingArgs.empty()) { + status.SetError(cmStrCat("RPATH_SET \"", missingArgs.front(), + "\" argument not given value.")); + return false; + } + if (file.empty()) { + status.SetError("RPATH_SET not given FILE option."); + return false; + } + if (newRPath.empty() && + std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") == + parsedArgs.end()) { + status.SetError("RPATH_SET not given NEW_RPATH option."); + return false; + } + if (!cmSystemTools::FileExists(file, true)) { + status.SetError( + cmStrCat("RPATH_SET given FILE \"", file, "\" that does not exist.")); + return false; + } + bool success = true; + cmFileTimes const ft(file); + std::string emsg; + bool changed; + + if (!cmSystemTools::SetRPath(file, newRPath, &emsg, &changed)) { + status.SetError(cmStrCat("RPATH_SET could not write new RPATH:\n ", + newRPath, "\nto the file:\n ", file, "\n", + emsg)); + success = false; + } + if (success) { + if (changed) { + std::string message = + cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"'); + status.GetMakefile().DisplayStatus(message, -1); + } + ft.Store(file); + } + return success; +} + bool HandleRPathRemoveCommand(std::vector const& args, cmExecutionStatus& status) { @@ -3732,6 +3792,7 @@ bool cmFileCommand(std::vector const& args, { "DIFFERENT"_s, HandleDifferentCommand }, { "RPATH_CHANGE"_s, HandleRPathChangeCommand }, { "CHRPATH"_s, HandleRPathChangeCommand }, + { "RPATH_SET"_s, HandleRPathSetCommand }, { "RPATH_CHECK"_s, HandleRPathCheckCommand }, { "RPATH_REMOVE"_s, HandleRPathRemoveCommand }, { "READ_ELF"_s, HandleReadElfCommand }, diff --git a/Tests/RunCMake/file-RPATH/Common.cmake b/Tests/RunCMake/file-RPATH/Common.cmake index cc1efb5334c..7034aadb374 100644 --- a/Tests/RunCMake/file-RPATH/Common.cmake +++ b/Tests/RunCMake/file-RPATH/Common.cmake @@ -62,3 +62,40 @@ foreach(f ${files}) message(FATAL_ERROR "RPATH_CHECK did not remove ${f}") endif() endforeach() + +# TODO Implement RPATH_SET in XCOFF. +if(format STREQUAL "ELF") + foreach(f ${names}) + file(COPY ${in}/${f} DESTINATION ${out} NO_SOURCE_PERMISSIONS) + endforeach() + + foreach(f ${files}) + # Set the RPATH. + file(RPATH_SET FILE "${f}" + NEW_RPATH "/new/rpath") + set(rpath) + file(STRINGS "${f}" rpath REGEX "/new/rpath" LIMIT_COUNT 1) + if(NOT rpath) + message(FATAL_ERROR "RPATH not set in ${f}") + endif() + file(STRINGS "${f}" rpath REGEX "/rpath/sample" LIMIT_COUNT 1) + if(rpath) + message(FATAL_EROR "RPATH not removed in ${f}") + endif() + + # Remove the RPATH. + file(RPATH_SET FILE "${f}" + NEW_RPATH "") + set(rpath) + file(STRINGS "${f}" rpath REGEX "/new/rpath" LIMIT_COUNT 1) + if(rpath) + message(FATAL_ERROR "RPATH not removed from ${f}") + endif() + + # Check again...this should remove the file. + file(RPATH_CHECK FILE "${f}" RPATH "/new/rpath") + if(EXISTS "${f}") + message(FATAL_ERROR "RPATH_CHECK did not remove ${f}") + endif() + endforeach() +endif() From f2617cf8e6aca6ec0f8c7df6999c1f713c6d7474 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 19 May 2021 10:29:17 -0400 Subject: [PATCH 0592/1519] Source: Add cmInstallRuntimeDependencySet --- Source/CMakeLists.txt | 2 + Source/cmGlobalGenerator.cxx | 24 ++++ Source/cmGlobalGenerator.h | 11 ++ Source/cmInstallRuntimeDependencySet.cxx | 95 +++++++++++++ Source/cmInstallRuntimeDependencySet.h | 163 +++++++++++++++++++++++ bootstrap | 1 + 6 files changed, 296 insertions(+) create mode 100644 Source/cmInstallRuntimeDependencySet.cxx create mode 100644 Source/cmInstallRuntimeDependencySet.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 844a2ee87fe..5bcf2233b28 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -352,6 +352,8 @@ set(SRCS cmInstallFilesGenerator.cxx cmInstallImportedRuntimeArtifactsGenerator.h cmInstallImportedRuntimeArtifactsGenerator.cxx + cmInstallRuntimeDependencySet.h + cmInstallRuntimeDependencySet.cxx cmInstallScriptGenerator.h cmInstallScriptGenerator.cxx cmInstallSubdirectoryGenerator.h diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index d7da0d33180..91937781243 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -36,6 +36,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmInstallGenerator.h" +#include "cmInstallRuntimeDependencySet.h" #include "cmLinkLineComputer.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" @@ -3332,3 +3333,26 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() return true; } + +cmInstallRuntimeDependencySet* +cmGlobalGenerator::CreateAnonymousRuntimeDependencySet() +{ + auto set = cm::make_unique(); + auto* retval = set.get(); + this->RuntimeDependencySets.push_back(std::move(set)); + return retval; +} + +cmInstallRuntimeDependencySet* cmGlobalGenerator::GetNamedRuntimeDependencySet( + const std::string& name) +{ + auto it = this->RuntimeDependencySetsByName.find(name); + if (it == this->RuntimeDependencySetsByName.end()) { + auto set = cm::make_unique(name); + it = + this->RuntimeDependencySetsByName.insert(std::make_pair(name, set.get())) + .first; + this->RuntimeDependencySets.push_back(std::move(set)); + } + return it->second; +} diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index fee0359b344..147146e134d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -42,6 +42,7 @@ class cmDirectoryId; class cmExportBuildFileGenerator; class cmExternalMakefileProjectGenerator; class cmGeneratorTarget; +class cmInstallRuntimeDependencySet; class cmLinkLineComputer; class cmLocalGenerator; class cmMakefile; @@ -528,6 +529,11 @@ class cmGlobalGenerator std::string NewDeferId(); + cmInstallRuntimeDependencySet* CreateAnonymousRuntimeDependencySet(); + + cmInstallRuntimeDependencySet* GetNamedRuntimeDependencySet( + const std::string& name); + protected: // for a project collect all its targets by following depend // information, and also collect all the targets @@ -747,6 +753,11 @@ class cmGlobalGenerator std::unordered_set GeneratedFiles; + std::vector> + RuntimeDependencySets; + std::map + RuntimeDependencySetsByName; + #if !defined(CMAKE_BOOTSTRAP) // Pool of file locks cmFileLockPool FileLockPool; diff --git a/Source/cmInstallRuntimeDependencySet.cxx b/Source/cmInstallRuntimeDependencySet.cxx new file mode 100644 index 00000000000..0cef49a2a07 --- /dev/null +++ b/Source/cmInstallRuntimeDependencySet.cxx @@ -0,0 +1,95 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallRuntimeDependencySet.h" + +#include +#include +#include + +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmInstallImportedRuntimeArtifactsGenerator.h" +#include "cmInstallTargetGenerator.h" +#include "cmStateTypes.h" +#include "cmTargetDepend.h" + +cmInstallRuntimeDependencySet::cmInstallRuntimeDependencySet(std::string name) + : Name(std::move(name)) +{ +} + +void cmInstallRuntimeDependencySet::AddExecutable( + std::unique_ptr executable) +{ + this->Executables.push_back(std::move(executable)); +} + +void cmInstallRuntimeDependencySet::AddLibrary(std::unique_ptr library) +{ + this->Libraries.push_back(std::move(library)); +} + +void cmInstallRuntimeDependencySet::AddModule(std::unique_ptr module) +{ + this->Modules.push_back(std::move(module)); +} + +bool cmInstallRuntimeDependencySet::AddBundleExecutable( + std::unique_ptr bundleExecutable) +{ + if (this->BundleExecutable) { + return false; + } + this->BundleExecutable = bundleExecutable.get(); + this->AddExecutable(std::move(bundleExecutable)); + return true; +} + +std::string cmInstallRuntimeDependencySet::TargetItem::GetItemPath( + const std::string& config) const +{ + return this->Target->GetTarget()->GetFullPath(config); +} + +namespace { +const std::set& GetTargetDependsClosure( + std::map>& + targetDepends, + const cmGeneratorTarget* tgt) +{ + auto it = targetDepends.insert({ tgt, {} }); + auto& retval = it.first->second; + if (it.second) { + auto const& deps = tgt->GetGlobalGenerator()->GetTargetDirectDepends(tgt); + for (auto const& dep : deps) { + if (!dep.IsCross() && dep.IsLink()) { + auto type = dep->GetType(); + if (type == cmStateEnums::EXECUTABLE || + type == cmStateEnums::SHARED_LIBRARY || + type == cmStateEnums::MODULE_LIBRARY) { + retval.insert(dep); + } + auto const& depDeps = GetTargetDependsClosure(targetDepends, dep); + retval.insert(depDeps.begin(), depDeps.end()); + } + } + } + return retval; +} +} + +void cmInstallRuntimeDependencySet::TargetItem::AddPostExcludeFiles( + const std::string& config, std::set& files, + cmInstallRuntimeDependencySet* set) const +{ + for (auto const* dep : GetTargetDependsClosure(set->TargetDepends, + this->Target->GetTarget())) { + files.insert(dep->GetFullPath(config)); + } +} + +std::string cmInstallRuntimeDependencySet::ImportedTargetItem::GetItemPath( + const std::string& config) const +{ + return this->Target->GetTarget()->GetFullPath(config); +} diff --git a/Source/cmInstallRuntimeDependencySet.h b/Source/cmInstallRuntimeDependencySet.h new file mode 100644 index 00000000000..7f516245857 --- /dev/null +++ b/Source/cmInstallRuntimeDependencySet.h @@ -0,0 +1,163 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +class cmGeneratorTarget; +class cmInstallImportedRuntimeArtifactsGenerator; +class cmInstallTargetGenerator; + +class cmInstallRuntimeDependencySet +{ +public: + cmInstallRuntimeDependencySet(std::string name = ""); + + cmInstallRuntimeDependencySet(const cmInstallRuntimeDependencySet&) = delete; + cmInstallRuntimeDependencySet& operator=( + const cmInstallRuntimeDependencySet&) = delete; + + cm::string_view GetName() const { return this->Name; } + + cm::string_view GetDisplayName() const + { + if (this->Name.empty()) { + return ""_s; + } + return this->Name; + } + + class Item + { + public: + virtual ~Item() = default; + + virtual std::string GetItemPath(const std::string& config) const = 0; + + virtual void AddPostExcludeFiles( + const std::string& /*config*/, std::set& /*files*/, + cmInstallRuntimeDependencySet* /*set*/) const + { + } + }; + + class TargetItem : public Item + { + public: + TargetItem(cmInstallTargetGenerator* target) + : Target(target) + { + } + + std::string GetItemPath(const std::string& config) const override; + + void AddPostExcludeFiles( + const std::string& config, std::set& files, + cmInstallRuntimeDependencySet* set) const override; + + private: + cmInstallTargetGenerator* Target; + }; + + class ImportedTargetItem : public Item + { + public: + ImportedTargetItem(cmInstallImportedRuntimeArtifactsGenerator* target) + : Target(target) + { + } + + std::string GetItemPath(const std::string& config) const override; + + private: + cmInstallImportedRuntimeArtifactsGenerator* Target; + }; + + void AddExecutable(std::unique_ptr executable); + void AddLibrary(std::unique_ptr library); + void AddModule(std::unique_ptr module); + bool AddBundleExecutable(std::unique_ptr bundleExecutable); + + void AddExecutable(cmInstallTargetGenerator* executable) + { + this->AddExecutable(cm::make_unique(executable)); + } + + void AddLibrary(cmInstallTargetGenerator* library) + { + this->AddLibrary(cm::make_unique(library)); + } + + void AddModule(cmInstallTargetGenerator* module) + { + this->AddModule(cm::make_unique(module)); + } + + bool AddBundleExecutable(cmInstallTargetGenerator* bundleExecutable) + { + return this->AddBundleExecutable( + cm::make_unique(bundleExecutable)); + } + + void AddExecutable(cmInstallImportedRuntimeArtifactsGenerator* executable) + { + this->AddExecutable(cm::make_unique(executable)); + } + + void AddLibrary(cmInstallImportedRuntimeArtifactsGenerator* library) + { + this->AddLibrary(cm::make_unique(library)); + } + + void AddModule(cmInstallImportedRuntimeArtifactsGenerator* module) + { + this->AddModule(cm::make_unique(module)); + } + + bool AddBundleExecutable( + cmInstallImportedRuntimeArtifactsGenerator* bundleExecutable) + { + return this->AddBundleExecutable( + cm::make_unique(bundleExecutable)); + } + + const std::vector>& GetExecutables() const + { + return this->Executables; + } + + const std::vector>& GetLibraries() const + { + return this->Libraries; + } + + const std::vector>& GetModules() const + { + return this->Modules; + } + + Item* GetBundleExecutable() const { return this->BundleExecutable; } + + bool Empty() const + { + return this->Executables.empty() && this->Libraries.empty() && + this->Modules.empty(); + } + +private: + std::string Name; + std::vector> Executables; + std::vector> Libraries; + std::vector> Modules; + Item* BundleExecutable = nullptr; + + std::map> + TargetDepends; +}; diff --git a/bootstrap b/bootstrap index 911558da062..720fa76b67c 100755 --- a/bootstrap +++ b/bootstrap @@ -388,6 +388,7 @@ CMAKE_CXX_SOURCES="\ cmInstallFilesGenerator \ cmInstallGenerator \ cmInstallImportedRuntimeArtifactsGenerator \ + cmInstallRuntimeDependencySet \ cmInstallScriptGenerator \ cmInstallSubdirectoryGenerator \ cmInstallTargetGenerator \ From ed3633d88cc5faa6fd7eb68fdd774d6d1f9cfdc9 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 14 Apr 2021 10:43:30 -0400 Subject: [PATCH 0593/1519] install(TARGETS): Add RUNTIME_DEPENDENCIES option --- Source/CMakeLists.txt | 4 + Source/cmFileCommand.cxx | 5 +- Source/cmInstallCommand.cxx | 186 +++++++++++- Source/cmInstallGenerator.cxx | 51 ++-- Source/cmInstallGenerator.h | 3 +- ...InstallGetRuntimeDependenciesGenerator.cxx | 206 +++++++++++++ ...cmInstallGetRuntimeDependenciesGenerator.h | 56 ++++ ...cmInstallRuntimeDependencySetGenerator.cxx | 276 ++++++++++++++++++ .../cmInstallRuntimeDependencySetGenerator.h | 74 +++++ Source/cmRuntimeDependencyArchive.cxx | 8 + Source/cmRuntimeDependencyArchive.h | 2 + Tests/RunCMake/install/RunCMakeTest.cmake | 17 +- ...GETS-RUNTIME_DEPENDENCIES-cross-result.txt | 1 + ...GETS-RUNTIME_DEPENDENCIES-cross-stderr.txt | 4 + .../TARGETS-RUNTIME_DEPENDENCIES-cross.cmake | 4 + ...RUNTIME_DEPENDENCIES-empty-all-check.cmake | 1 + .../TARGETS-RUNTIME_DEPENDENCIES-empty.cmake | 9 + ...DEPENDENCIES-macos-no-framework-result.txt | 1 + ...DEPENDENCIES-macos-no-framework-stderr.txt | 4 + ...TIME_DEPENDENCIES-macos-no-framework.cmake | 4 + ...E_DEPENDENCIES-macos-two-bundle-result.txt | 1 + ...E_DEPENDENCIES-macos-two-bundle-stderr.txt | 4 + ...UNTIME_DEPENDENCIES-macos-two-bundle.cmake | 10 + ...RUNTIME_DEPENDENCIES-nodep-all-check.cmake | 1 + .../TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake | 9 + ...UNTIME_DEPENDENCIES-unsupported-result.txt | 1 + ...UNTIME_DEPENDENCIES-unsupported-stderr.txt | 5 + ...ETS-RUNTIME_DEPENDENCIES-unsupported.cmake | 4 + bootstrap | 2 + 29 files changed, 928 insertions(+), 25 deletions(-) create mode 100644 Source/cmInstallGetRuntimeDependenciesGenerator.cxx create mode 100644 Source/cmInstallGetRuntimeDependenciesGenerator.h create mode 100644 Source/cmInstallRuntimeDependencySetGenerator.cxx create mode 100644 Source/cmInstallRuntimeDependencySetGenerator.h create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 5bcf2233b28..9a18184fd3b 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -345,6 +345,8 @@ set(SRCS cmGraphVizWriter.h cmInstallGenerator.h cmInstallGenerator.cxx + cmInstallGetRuntimeDependenciesGenerator.h + cmInstallGetRuntimeDependenciesGenerator.cxx cmInstallExportGenerator.cxx cmInstalledFile.h cmInstalledFile.cxx @@ -354,6 +356,8 @@ set(SRCS cmInstallImportedRuntimeArtifactsGenerator.cxx cmInstallRuntimeDependencySet.h cmInstallRuntimeDependencySet.cxx + cmInstallRuntimeDependencySetGenerator.h + cmInstallRuntimeDependencySetGenerator.cxx cmInstallScriptGenerator.h cmInstallScriptGenerator.cxx cmInstallSubdirectoryGenerator.h diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 82546b915ec..0ad59c7b5d3 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3044,11 +3044,10 @@ bool HandleCreateLinkCommand(std::vector const& args, bool HandleGetRuntimeDependenciesCommand(std::vector const& args, cmExecutionStatus& status) { - static const std::set supportedPlatforms = { "Windows", "Linux", - "Darwin" }; std::string platform = status.GetMakefile().GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); - if (!supportedPlatforms.count(platform)) { + if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( + platform)) { status.SetError( cmStrCat("GET_RUNTIME_DEPENDENCIES is not supported on system \"", platform, "\"")); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index c9bb467b36c..c36778d8618 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -2,8 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallCommand.h" +#include #include #include +#include #include #include #include @@ -23,7 +25,10 @@ #include "cmInstallExportGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallGetRuntimeDependenciesGenerator.h" #include "cmInstallImportedRuntimeArtifactsGenerator.h" +#include "cmInstallRuntimeDependencySet.h" +#include "cmInstallRuntimeDependencySetGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmListFileCache.h" @@ -31,6 +36,7 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmProperty.h" +#include "cmRuntimeDependencyArchive.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSubcommandTable.h" @@ -40,6 +46,29 @@ namespace { +struct RuntimeDependenciesArgs +{ + std::vector Directories; + std::vector PreIncludeRegexes; + std::vector PreExcludeRegexes; + std::vector PostIncludeRegexes; + std::vector PostExcludeRegexes; + std::vector PostIncludeFiles; + std::vector PostExcludeFiles; +}; + +auto const RuntimeDependenciesArgHelper = + cmArgumentParser{} + .Bind("DIRECTORIES"_s, &RuntimeDependenciesArgs::Directories) + .Bind("PRE_INCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreIncludeRegexes) + .Bind("PRE_EXCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreExcludeRegexes) + .Bind("POST_INCLUDE_REGEXES"_s, + &RuntimeDependenciesArgs::PostIncludeRegexes) + .Bind("POST_EXCLUDE_REGEXES"_s, + &RuntimeDependenciesArgs::PostExcludeRegexes) + .Bind("POST_INCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostIncludeFiles) + .Bind("POST_EXCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostExcludeFiles); + class Helper { public: @@ -147,12 +176,106 @@ std::unique_ptr CreateInstallFilesGenerator( args.GetDestination()); } +void AddInstallRuntimeDependenciesGenerator( + Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet, + const cmInstallCommandArguments& runtimeArgs, + const cmInstallCommandArguments& libraryArgs, + const cmInstallCommandArguments& frameworkArgs, + RuntimeDependenciesArgs runtimeDependenciesArgs, bool& installsRuntime, + bool& installsLibrary, bool& installsFramework) +{ + bool dllPlatform = + !helper.Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); + bool apple = + helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") == "Darwin"; + auto const& runtimeDependenciesArgsRef = + dllPlatform ? runtimeArgs : libraryArgs; + std::vector configurations = + runtimeDependenciesArgsRef.GetConfigurations(); + if (apple) { + std::copy(frameworkArgs.GetConfigurations().begin(), + frameworkArgs.GetConfigurations().end(), + std::back_inserter(configurations)); + } + + // Create file(GET_RUNTIME_DEPENDENCIES) generator. + auto getRuntimeDependenciesGenerator = + cm::make_unique( + runtimeDependencySet, std::move(runtimeDependenciesArgs.Directories), + std::move(runtimeDependenciesArgs.PreIncludeRegexes), + std::move(runtimeDependenciesArgs.PreExcludeRegexes), + std::move(runtimeDependenciesArgs.PostIncludeRegexes), + std::move(runtimeDependenciesArgs.PostExcludeRegexes), + std::move(runtimeDependenciesArgs.PostIncludeFiles), + std::move(runtimeDependenciesArgs.PostExcludeFiles), + runtimeDependenciesArgsRef.GetComponent(), + apple ? frameworkArgs.GetComponent() : "", true, "_CMAKE_DEPS", + "_CMAKE_RPATH", configurations, + cmInstallGenerator::SelectMessageLevel(helper.Makefile), + runtimeDependenciesArgsRef.GetExcludeFromAll() && + (apple ? frameworkArgs.GetExcludeFromAll() : true), + helper.Makefile->GetBacktrace()); + helper.Makefile->AddInstallGenerator( + std::move(getRuntimeDependenciesGenerator)); + + // Create the library dependencies generator. + auto libraryRuntimeDependenciesGenerator = + cm::make_unique( + cmInstallRuntimeDependencySetGenerator::DependencyType::Library, + runtimeDependencySet, std::vector{}, true, std::string{}, + true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP", + dllPlatform ? helper.GetRuntimeDestination(&runtimeArgs) + : helper.GetLibraryDestination(&libraryArgs), + runtimeDependenciesArgsRef.GetConfigurations(), + runtimeDependenciesArgsRef.GetComponent(), + runtimeDependenciesArgsRef.GetPermissions(), + cmInstallGenerator::SelectMessageLevel(helper.Makefile), + runtimeDependenciesArgsRef.GetExcludeFromAll(), + helper.Makefile->GetBacktrace()); + helper.Makefile->AddInstallGenerator( + std::move(libraryRuntimeDependenciesGenerator)); + if (dllPlatform) { + installsRuntime = true; + } else { + installsLibrary = true; + } + + if (apple) { + // Create the framework dependencies generator. + auto frameworkRuntimeDependenciesGenerator = + cm::make_unique( + cmInstallRuntimeDependencySetGenerator::DependencyType::Framework, + runtimeDependencySet, std::vector{}, true, std::string{}, + true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP", + frameworkArgs.GetDestination(), frameworkArgs.GetConfigurations(), + frameworkArgs.GetComponent(), frameworkArgs.GetPermissions(), + cmInstallGenerator::SelectMessageLevel(helper.Makefile), + frameworkArgs.GetExcludeFromAll(), helper.Makefile->GetBacktrace()); + helper.Makefile->AddInstallGenerator( + std::move(frameworkRuntimeDependenciesGenerator)); + installsFramework = true; + } +} + std::set const allowedTypes{ "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF", "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO", "LOCALE", "MAN", "DOC", }; +template +bool AddBundleExecutable(Helper& helper, + cmInstallRuntimeDependencySet* runtimeDependencySet, + T&& bundleExecutable) +{ + if (!runtimeDependencySet->AddBundleExecutable(bundleExecutable)) { + helper.SetError( + "A runtime dependency set may only have one bundle executable."); + return false; + } + return true; +} + bool HandleScriptMode(std::vector const& args, cmExecutionStatus& status) { @@ -289,13 +412,23 @@ bool HandleTargetsMode(std::vector const& args, // These generic args also contain the targets and the export stuff std::vector targetList; std::string exports; + std::vector runtimeDependenciesArgVector; std::vector unknownArgs; + std::vector parsedArgs; cmInstallCommandArguments genericArgs(helper.DefaultComponentName); genericArgs.Bind("TARGETS"_s, targetList); genericArgs.Bind("EXPORT"_s, exports); - genericArgs.Parse(genericArgVector, &unknownArgs); + genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector); + genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs); bool success = genericArgs.Finalize(); + bool withRuntimeDependencies = + std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") != + parsedArgs.end(); + RuntimeDependenciesArgs runtimeDependenciesArgs = + RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector, + &unknownArgs); + cmInstallCommandArguments archiveArgs(helper.DefaultComponentName); cmInstallCommandArguments libraryArgs(helper.DefaultComponentName); cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName); @@ -402,6 +535,32 @@ bool HandleTargetsMode(std::vector const& args, return false; } + cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr; + if (withRuntimeDependencies) { + auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); + if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( + system)) { + status.SetError( + cmStrCat("TARGETS RUNTIME_DEPENDENCIES is not supported on system \"", + system, '"')); + return false; + } + if (helper.Makefile->IsOn("CMAKE_CROSSCOMPILING")) { + status.SetError("TARGETS RUNTIME_DEPENDENCIES is not supported " + "when cross-compiling."); + return false; + } + if (helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") == + "Darwin" && + frameworkArgs.GetDestination().empty()) { + status.SetError( + "TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION"); + return false; + } + runtimeDependencySet = helper.Makefile->GetGlobalGenerator() + ->CreateAnonymousRuntimeDependencySet(); + } + // Select the mode for installing symlinks to versioned shared libraries. cmInstallTargetGenerator::NamelinkModeType namelinkMode = cmInstallTargetGenerator::NamelinkModeNone; @@ -546,6 +705,9 @@ bool HandleTargetsMode(std::vector const& args, target, runtimeArgs, false, helper.Makefile->GetBacktrace(), helper.GetRuntimeDestination(nullptr)); } + if (runtimeDependencySet && runtimeGenerator) { + runtimeDependencySet->AddLibrary(runtimeGenerator.get()); + } } else { // This is a non-DLL platform. // If it is marked with FRAMEWORK property use the FRAMEWORK set of @@ -591,6 +753,9 @@ bool HandleTargetsMode(std::vector const& args, namelinkOnly = (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } + if (runtimeDependencySet && libraryGenerator) { + runtimeDependencySet->AddLibrary(libraryGenerator.get()); + } } } break; case cmStateEnums::STATIC_LIBRARY: { @@ -633,6 +798,9 @@ bool HandleTargetsMode(std::vector const& args, libraryGenerator->SetNamelinkMode(namelinkMode); namelinkOnly = (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); + if (runtimeDependencySet) { + runtimeDependencySet->AddModule(libraryGenerator.get()); + } } else { status.SetError( cmStrCat("TARGETS given no LIBRARY DESTINATION for module " @@ -685,6 +853,12 @@ bool HandleTargetsMode(std::vector const& args, target.GetName(), "\".")); return false; } + if (runtimeDependencySet) { + if (!AddBundleExecutable(helper, runtimeDependencySet, + bundleGenerator.get())) { + return false; + } + } } else { // Executables use the RUNTIME properties. if (!runtimeArgs.GetDestination().empty()) { @@ -693,6 +867,9 @@ bool HandleTargetsMode(std::vector const& args, runtimeGenerator = CreateInstallTargetGenerator( target, runtimeArgs, false, helper.Makefile->GetBacktrace(), helper.GetRuntimeDestination(&runtimeArgs)); + if (runtimeDependencySet) { + runtimeDependencySet->AddExecutable(runtimeGenerator.get()); + } } // On DLL platforms an executable may also have an import @@ -821,6 +998,13 @@ bool HandleTargetsMode(std::vector const& args, helper.Makefile->AddInstallGenerator(std::move(resourceGenerator)); } + if (withRuntimeDependencies && !runtimeDependencySet->Empty()) { + AddInstallRuntimeDependenciesGenerator( + helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs, + std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary, + installsFramework); + } + // Tell the global generator about any installation component names // specified if (installsArchive) { diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 9f0d119e4cf..4cfeb477e7f 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -43,7 +43,8 @@ void cmInstallGenerator::AddInstallRule( std::vector const& files, bool optional /* = false */, const char* permissions_file /* = 0 */, const char* permissions_dir /* = 0 */, const char* rename /* = 0 */, - const char* literal_args /* = 0 */, Indent indent) + const char* literal_args /* = 0 */, Indent indent, + const char* files_var /* = 0 */) { // Use the FILE command to install the file. std::string stype; @@ -70,37 +71,46 @@ void cmInstallGenerator::AddInstallRule( stype = "FILE"; break; } - os << indent; if (cmSystemTools::FileIsFullPath(dest)) { - os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n"; - os << indent << " \""; - bool firstIteration = true; - for (std::string const& file : files) { - if (!firstIteration) { - os << ";"; + if (!files.empty()) { + os << indent << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n"; + os << indent << " \""; + bool firstIteration = true; + for (std::string const& file : files) { + if (!firstIteration) { + os << ";"; + } + os << dest << "/"; + if (rename && *rename) { + os << rename; + } else { + os << cmSystemTools::GetFilenameName(file); + } + firstIteration = false; } - os << dest << "/"; - if (rename && *rename) { - os << rename; - } else { - os << cmSystemTools::GetFilenameName(file); - } - firstIteration = false; + os << "\")\n"; + } + if (files_var) { + os << indent << "foreach(_f IN LISTS " << files_var << ")\n"; + os << indent.Next() << "get_filename_component(_fn \"${_f}\" NAME)\n"; + os << indent.Next() << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES \"" + << dest << "/${_fn}\")\n"; + os << indent << "endforeach()\n"; } - os << "\")\n"; os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n"; - os << indent << indent << "message(WARNING \"ABSOLUTE path INSTALL " + os << indent.Next() << "message(WARNING \"ABSOLUTE path INSTALL " << "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; os << indent << "endif()\n"; os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n"; - os << indent << indent << "message(FATAL_ERROR \"ABSOLUTE path INSTALL " + os << indent.Next() << "message(FATAL_ERROR \"ABSOLUTE path INSTALL " << "DESTINATION forbidden (by caller): " << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; os << indent << "endif()\n"; } std::string absDest = ConvertToAbsoluteDestination(dest); - os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype; + os << indent << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " + << stype; if (optional) { os << " OPTIONAL"; } @@ -133,6 +143,9 @@ void cmInstallGenerator::AddInstallRule( for (std::string const& f : files) { os << "\n" << indent << " \"" << f << "\""; } + if (files_var) { + os << " ${" << files_var << "}"; + } os << "\n" << indent << " "; if (!(literal_args && *literal_args)) { os << " "; diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 97acb88e838..d342c992616 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -50,7 +50,8 @@ class cmInstallGenerator : public cmScriptGenerator std::vector const& files, bool optional = false, const char* permissions_file = nullptr, const char* permissions_dir = nullptr, const char* rename = nullptr, - const char* literal_args = nullptr, Indent indent = Indent()); + const char* literal_args = nullptr, Indent indent = Indent(), + const char* files_var = nullptr); /** Get the install destination as it should appear in the installation script. */ diff --git a/Source/cmInstallGetRuntimeDependenciesGenerator.cxx b/Source/cmInstallGetRuntimeDependenciesGenerator.cxx new file mode 100644 index 00000000000..4d585cec557 --- /dev/null +++ b/Source/cmInstallGetRuntimeDependenciesGenerator.cxx @@ -0,0 +1,206 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallGetRuntimeDependenciesGenerator.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cmGeneratorExpression.h" +#include "cmInstallRuntimeDependencySet.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmOutputConverter.h" +#include "cmStringAlgorithms.h" + +namespace { +template +void WriteMultiArgument(std::ostream& os, const cm::string_view& keyword, + const std::vector& list, + cmScriptGeneratorIndent indent, F transform) +{ + bool first = true; + for (auto const& item : list) { + cm::optional result = transform(item); + if (result) { + if (first) { + os << indent << " " << keyword << "\n"; + first = false; + } + os << indent << " " << *result << "\n"; + } + } +} + +void WriteFilesArgument( + std::ostream& os, const cm::string_view& keyword, + const std::vector>& + items, + const std::string& config, cmScriptGeneratorIndent indent) +{ + WriteMultiArgument( + os, keyword, items, indent, + [config](const std::unique_ptr& i) + -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); }); +} + +void WriteGenexEvaluatorArgument(std::ostream& os, + const cm::string_view& keyword, + const std::vector& genexes, + const std::string& config, + cmLocalGenerator* lg, + cmScriptGeneratorIndent indent) +{ + WriteMultiArgument( + os, keyword, genexes, indent, + [config, lg](const std::string& genex) -> cm::optional { + std::string result = cmGeneratorExpression::Evaluate(genex, lg, config); + if (result.empty()) { + return cm::nullopt; + } + return cmOutputConverter::EscapeForCMake(result); + }); +} +} + +cmInstallGetRuntimeDependenciesGenerator:: + cmInstallGetRuntimeDependenciesGenerator( + cmInstallRuntimeDependencySet* runtimeDependencySet, + std::vector directories, + std::vector preIncludeRegexes, + std::vector preExcludeRegexes, + std::vector postIncludeRegexes, + std::vector postExcludeRegexes, + std::vector postIncludeFiles, + std::vector postExcludeFiles, std::string libraryComponent, + std::string frameworkComponent, bool noInstallRPath, const char* depsVar, + const char* rpathPrefix, std::vector const& configurations, + MessageLevel message, bool exclude_from_all, cmListFileBacktrace backtrace) + : cmInstallGenerator("", configurations, "", message, exclude_from_all, + false, std::move(backtrace)) + , RuntimeDependencySet(runtimeDependencySet) + , Directories(std::move(directories)) + , PreIncludeRegexes(std::move(preIncludeRegexes)) + , PreExcludeRegexes(std::move(preExcludeRegexes)) + , PostIncludeRegexes(std::move(postIncludeRegexes)) + , PostExcludeRegexes(std::move(postExcludeRegexes)) + , PostIncludeFiles(std::move(postIncludeFiles)) + , PostExcludeFiles(std::move(postExcludeFiles)) + , LibraryComponent(std::move(libraryComponent)) + , FrameworkComponent(std::move(frameworkComponent)) + , NoInstallRPath(noInstallRPath) + , DepsVar(depsVar) + , RPathPrefix(rpathPrefix) +{ + this->ActionsPerConfig = true; +} + +bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; + return true; +} + +void cmInstallGetRuntimeDependenciesGenerator::GenerateScript(std::ostream& os) +{ + // Track indentation. + Indent indent; + + // Begin this block of installation. + os << indent << "if("; + if (this->FrameworkComponent.empty() || + this->FrameworkComponent == this->LibraryComponent) { + os << this->CreateComponentTest(this->LibraryComponent, + this->ExcludeFromAll); + } else { + os << this->CreateComponentTest(this->LibraryComponent, true) << " OR " + << this->CreateComponentTest(this->FrameworkComponent, + this->ExcludeFromAll); + } + os << ")\n"; + + // Generate the script possibly with per-configuration code. + this->GenerateScriptConfigs(os, indent.Next()); + + // End this block of installation. + os << indent << "endif()\n\n"; +} + +void cmInstallGetRuntimeDependenciesGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + std::string installNameTool = + this->LocalGenerator->GetMakefile()->GetSafeDefinition( + "CMAKE_INSTALL_NAME_TOOL"); + + os << indent << "file(GET_RUNTIME_DEPENDENCIES\n" + << indent << " RESOLVED_DEPENDENCIES_VAR " << this->DepsVar << '\n'; + WriteFilesArgument(os, "EXECUTABLES"_s, + this->RuntimeDependencySet->GetExecutables(), config, + indent); + WriteFilesArgument(os, "LIBRARIES"_s, + this->RuntimeDependencySet->GetLibraries(), config, + indent); + WriteFilesArgument(os, "MODULES"_s, this->RuntimeDependencySet->GetModules(), + config, indent); + if (this->RuntimeDependencySet->GetBundleExecutable()) { + os << indent << " BUNDLE_EXECUTABLE \"" + << this->RuntimeDependencySet->GetBundleExecutable()->GetItemPath( + config) + << "\"\n"; + } + WriteGenexEvaluatorArgument(os, "DIRECTORIES"_s, this->Directories, config, + this->LocalGenerator, indent); + WriteGenexEvaluatorArgument(os, "PRE_INCLUDE_REGEXES"_s, + this->PreIncludeRegexes, config, + this->LocalGenerator, indent); + WriteGenexEvaluatorArgument(os, "PRE_EXCLUDE_REGEXES"_s, + this->PreExcludeRegexes, config, + this->LocalGenerator, indent); + WriteGenexEvaluatorArgument(os, "POST_INCLUDE_REGEXES"_s, + this->PostIncludeRegexes, config, + this->LocalGenerator, indent); + WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_REGEXES"_s, + this->PostExcludeRegexes, config, + this->LocalGenerator, indent); + WriteGenexEvaluatorArgument(os, "POST_INCLUDE_FILES"_s, + this->PostIncludeFiles, config, + this->LocalGenerator, indent); + WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_FILES"_s, + this->PostExcludeFiles, config, + this->LocalGenerator, indent); + + std::set postExcludeFiles; + auto const addPostExclude = + [config, &postExcludeFiles, this]( + const std::vector>& + tgts) { + for (auto const& item : tgts) { + item->AddPostExcludeFiles(config, postExcludeFiles, + this->RuntimeDependencySet); + } + }; + addPostExclude(this->RuntimeDependencySet->GetExecutables()); + addPostExclude(this->RuntimeDependencySet->GetLibraries()); + addPostExclude(this->RuntimeDependencySet->GetModules()); + bool first = true; + for (auto const& file : postExcludeFiles) { + if (first) { + os << indent << " POST_EXCLUDE_FILES_STRICT\n"; + first = false; + } + os << indent << " \"" << file << "\"\n"; + } + + if (!installNameTool.empty() && !this->NoInstallRPath) { + os << indent << " RPATH_PREFIX " << this->RPathPrefix << '\n'; + } + os << indent << " )\n"; +} diff --git a/Source/cmInstallGetRuntimeDependenciesGenerator.h b/Source/cmInstallGetRuntimeDependenciesGenerator.h new file mode 100644 index 00000000000..19f6cc6db80 --- /dev/null +++ b/Source/cmInstallGetRuntimeDependenciesGenerator.h @@ -0,0 +1,56 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include +#include + +#include "cmInstallGenerator.h" +#include "cmListFileCache.h" +#include "cmScriptGenerator.h" + +class cmLocalGenerator; +class cmInstallRuntimeDependencySet; + +class cmInstallGetRuntimeDependenciesGenerator : public cmInstallGenerator +{ +public: + cmInstallGetRuntimeDependenciesGenerator( + cmInstallRuntimeDependencySet* runtimeDependencySet, + std::vector directories, + std::vector preIncludeRegexes, + std::vector preExcludeRegexes, + std::vector postIncludeRegexes, + std::vector postExcludeRegexes, + std::vector postIncludeFiles, + std::vector postExcludeFiles, std::string libraryComponent, + std::string frameworkComponent, bool noInstallRPath, const char* depsVar, + const char* rpathPrefix, std::vector const& configurations, + MessageLevel message, bool exclude_from_all, + cmListFileBacktrace backtrace); + + bool Compute(cmLocalGenerator* lg) override; + +protected: + void GenerateScript(std::ostream& os) override; + + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + +private: + cmInstallRuntimeDependencySet* RuntimeDependencySet; + std::vector Directories; + std::vector PreIncludeRegexes; + std::vector PreExcludeRegexes; + std::vector PostIncludeRegexes; + std::vector PostExcludeRegexes; + std::vector PostIncludeFiles; + std::vector PostExcludeFiles; + std::string LibraryComponent; + std::string FrameworkComponent; + bool NoInstallRPath; + const char* DepsVar; + const char* RPathPrefix; + cmLocalGenerator* LocalGenerator = nullptr; +}; diff --git a/Source/cmInstallRuntimeDependencySetGenerator.cxx b/Source/cmInstallRuntimeDependencySetGenerator.cxx new file mode 100644 index 00000000000..44f03e1af9b --- /dev/null +++ b/Source/cmInstallRuntimeDependencySetGenerator.cxx @@ -0,0 +1,276 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallRuntimeDependencySetGenerator.h" + +#include +#include +#include +#include + +#include "cmGeneratorExpression.h" +#include "cmInstallGenerator.h" +#include "cmInstallType.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmOutputConverter.h" +#include "cmScriptGenerator.h" +#include "cmStringAlgorithms.h" +#include "cmake.h" + +cmInstallRuntimeDependencySetGenerator::cmInstallRuntimeDependencySetGenerator( + DependencyType type, cmInstallRuntimeDependencySet* dependencySet, + std::vector installRPaths, bool noInstallRPath, + std::string installNameDir, bool noInstallName, const char* depsVar, + const char* rpathPrefix, const char* tmpVarPrefix, std::string destination, + std::vector const& configurations, std::string component, + std::string permissions, MessageLevel message, bool exclude_from_all, + cmListFileBacktrace backtrace) + : cmInstallGenerator(std::move(destination), configurations, + std::move(component), message, exclude_from_all, false, + std::move(backtrace)) + , Type(type) + , DependencySet(dependencySet) + , InstallRPaths(std::move(installRPaths)) + , NoInstallRPath(noInstallRPath) + , InstallNameDir(std::move(installNameDir)) + , NoInstallName(noInstallName) + , Permissions(std::move(permissions)) + , DepsVar(depsVar) + , RPathPrefix(rpathPrefix) + , TmpVarPrefix(tmpVarPrefix) +{ + this->ActionsPerConfig = true; +} + +bool cmInstallRuntimeDependencySetGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; + return true; +} + +void cmInstallRuntimeDependencySetGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + if (!this->LocalGenerator->GetMakefile() + ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL") + .empty() && + !this->NoInstallName) { + std::string installNameDir = "@rpath/"; + if (!this->InstallNameDir.empty()) { + installNameDir = this->InstallNameDir; + cmGeneratorExpression::ReplaceInstallPrefix(installNameDir, + "${CMAKE_INSTALL_PREFIX}"); + installNameDir = cmGeneratorExpression::Evaluate( + installNameDir, this->LocalGenerator, config); + if (installNameDir.empty()) { + this->LocalGenerator->GetMakefile()->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "INSTALL_NAME_DIR argument must not evaluate to an " + "empty string", + this->Backtrace); + return; + } + if (installNameDir.back() != '/') { + installNameDir += '/'; + } + } + os << indent << "set(" << this->TmpVarPrefix << "_install_name_dir \"" + << installNameDir << "\")\n"; + } + + os << indent << "foreach(" << this->TmpVarPrefix << "_dep IN LISTS " + << this->DepsVar << ")\n"; + + if (!this->LocalGenerator->GetMakefile() + ->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL") + .empty()) { + std::vector evaluatedRPaths; + for (auto const& rpath : this->InstallRPaths) { + std::string result = + cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config); + if (!result.empty()) { + evaluatedRPaths.push_back(std::move(result)); + } + } + + switch (this->Type) { + case DependencyType::Library: + this->GenerateAppleLibraryScript(os, config, evaluatedRPaths, + indent.Next()); + break; + case DependencyType::Framework: + this->GenerateAppleFrameworkScript(os, config, evaluatedRPaths, + indent.Next()); + break; + } + } else { + std::string depVar = cmStrCat(this->TmpVarPrefix, "_dep"); + + this->AddInstallRule( + os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {}, + false, this->Permissions.c_str(), nullptr, nullptr, + " FOLLOW_SYMLINK_CHAIN", indent.Next(), depVar.c_str()); + + if (this->LocalGenerator->GetMakefile()->GetSafeDefinition( + "CMAKE_SYSTEM_NAME") == "Linux" && + !this->NoInstallRPath) { + std::string evaluatedRPath; + for (auto const& rpath : this->InstallRPaths) { + std::string result = + cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config); + if (!result.empty()) { + if (evaluatedRPath.empty()) { + evaluatedRPath = std::move(result); + } else { + evaluatedRPath += ':'; + evaluatedRPath += result; + } + } + } + + os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix + << "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n"; + if (evaluatedRPath.empty()) { + os << indent.Next() << "file(RPATH_REMOVE FILE \"" + << GetDestDirPath( + ConvertToAbsoluteDestination(this->GetDestination(config))) + << "/${" << this->TmpVarPrefix << "_dep_name}\")\n"; + } else { + os << indent.Next() << "file(RPATH_SET FILE \"" + << GetDestDirPath( + ConvertToAbsoluteDestination(this->GetDestination(config))) + << "/${" << this->TmpVarPrefix << "_dep_name}\" NEW_RPATH " + << cmOutputConverter::EscapeForCMake(evaluatedRPath) << ")\n"; + } + } + } + + os << indent << "endforeach()\n"; +} + +void cmInstallRuntimeDependencySetGenerator::GenerateAppleLibraryScript( + std::ostream& os, const std::string& config, + const std::vector& evaluatedRPaths, Indent indent) +{ + os << indent << "if(NOT " << this->TmpVarPrefix + << "_dep MATCHES \"\\\\.framework/\")\n"; + + auto depName = cmStrCat(this->TmpVarPrefix, "_dep"); + this->AddInstallRule( + os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {}, false, + this->Permissions.c_str(), nullptr, nullptr, " FOLLOW_SYMLINK_CHAIN", + indent.Next(), depName.c_str()); + + os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix + << "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n"; + auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_dep_name}"); + this->GenerateInstallNameFixup(os, config, evaluatedRPaths, + cmStrCat("${", this->TmpVarPrefix, "_dep}"), + depNameVar, indent.Next()); + + os << indent << "endif()\n"; +} + +void cmInstallRuntimeDependencySetGenerator::GenerateAppleFrameworkScript( + std::ostream& os, const std::string& config, + const std::vector& evaluatedRPaths, Indent indent) +{ + os << indent << "if(" << this->TmpVarPrefix + << "_dep MATCHES \"^(.*/)?([^/]*\\\\.framework)/(.*)$\")\n" + << indent.Next() << "set(" << this->TmpVarPrefix + << "_dir \"${CMAKE_MATCH_1}\")\n" + << indent.Next() << "set(" << this->TmpVarPrefix + << "_name \"${CMAKE_MATCH_2}\")\n" + << indent.Next() << "set(" << this->TmpVarPrefix + << "_file \"${CMAKE_MATCH_3}\")\n" + << indent.Next() << "set(" << this->TmpVarPrefix << "_path \"${" + << this->TmpVarPrefix << "_dir}${" << this->TmpVarPrefix << "_name}\")\n"; + + auto depName = cmStrCat(this->TmpVarPrefix, "_path"); + this->AddInstallRule( + os, this->GetDestination(config), cmInstallType_DIRECTORY, {}, false, + this->Permissions.c_str(), nullptr, nullptr, " USE_SOURCE_PERMISSIONS", + indent.Next(), depName.c_str()); + + auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_name}/${", + this->TmpVarPrefix, "_file}"); + this->GenerateInstallNameFixup(os, config, evaluatedRPaths, + cmStrCat("${", this->TmpVarPrefix, "_dep}"), + depNameVar, indent.Next()); + + os << indent << "endif()\n"; +} + +void cmInstallRuntimeDependencySetGenerator::GenerateInstallNameFixup( + std::ostream& os, const std::string& config, + const std::vector& evaluatedRPaths, const std::string& filename, + const std::string& depName, Indent indent) +{ + if (!(this->NoInstallRPath && this->NoInstallName)) { + auto indent2 = indent; + if (evaluatedRPaths.empty() && this->NoInstallName) { + indent2 = indent2.Next(); + os << indent << "if(" << this->RPathPrefix << "_" << filename << ")\n"; + } + os << indent2 << "set(" << this->TmpVarPrefix << "_rpath_args)\n"; + if (!this->NoInstallRPath) { + os << indent2 << "foreach(" << this->TmpVarPrefix << "_rpath IN LISTS " + << this->RPathPrefix << '_' << filename << ")\n" + << indent2.Next() << "list(APPEND " << this->TmpVarPrefix + << "_rpath_args -delete_rpath \"${" << this->TmpVarPrefix + << "_rpath}\")\n" + << indent2 << "endforeach()\n"; + } + os << indent2 << "execute_process(COMMAND \"" + << this->LocalGenerator->GetMakefile()->GetSafeDefinition( + "CMAKE_INSTALL_NAME_TOOL") + << "\" ${" << this->TmpVarPrefix << "_rpath_args}\n"; + if (!this->NoInstallRPath) { + for (auto const& rpath : evaluatedRPaths) { + os << indent2 << " -add_rpath " + << cmOutputConverter::EscapeForCMake(rpath) << "\n"; + } + } + if (!this->NoInstallName) { + os << indent2 << " -id \"${" << this->TmpVarPrefix + << "_install_name_dir}" << depName << "\"\n"; + } + os << indent2 << " \"" + << GetDestDirPath( + ConvertToAbsoluteDestination(this->GetDestination(config))) + << "/" << depName << "\")\n"; + if (evaluatedRPaths.empty() && this->NoInstallName) { + os << indent << "endif()\n"; + } + } +} + +void cmInstallRuntimeDependencySetGenerator::GenerateStripFixup( + std::ostream& os, const std::string& config, const std::string& depName, + Indent indent) +{ + std::string strip = + this->LocalGenerator->GetMakefile()->GetSafeDefinition("CMAKE_STRIP"); + if (!strip.empty()) { + os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n" + << indent.Next() << "execute_process(COMMAND \"" << strip << "\" "; + if (this->LocalGenerator->GetMakefile()->GetSafeDefinition( + "CMAKE_HOST_SYSTEM_NAME") == "Darwin") { + os << "-x "; + } + os << "\"" + << GetDestDirPath( + ConvertToAbsoluteDestination(this->GetDestination(config))) + << "/" << depName << "\")\n" + << indent << "endif()\n"; + } +} + +std::string cmInstallRuntimeDependencySetGenerator::GetDestination( + std::string const& config) const +{ + return cmGeneratorExpression::Evaluate(this->Destination, + this->LocalGenerator, config); +} diff --git a/Source/cmInstallRuntimeDependencySetGenerator.h b/Source/cmInstallRuntimeDependencySetGenerator.h new file mode 100644 index 00000000000..8e98b576247 --- /dev/null +++ b/Source/cmInstallRuntimeDependencySetGenerator.h @@ -0,0 +1,74 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include +#include +#include + +#include "cmInstallGenerator.h" +#include "cmListFileCache.h" +#include "cmScriptGenerator.h" + +class cmInstallRuntimeDependencySet; +class cmLocalGenerator; + +class cmInstallRuntimeDependencySetGenerator : public cmInstallGenerator +{ +public: + enum class DependencyType + { + Library, + Framework, + }; + + cmInstallRuntimeDependencySetGenerator( + DependencyType type, cmInstallRuntimeDependencySet* dependencySet, + std::vector installRPaths, bool noInstallRPath, + std::string installNameDir, bool noInstallName, const char* depsVar, + const char* rpathPrefix, const char* tmpVarPrefix, std::string destination, + std::vector const& configurations, std::string component, + std::string permissions, MessageLevel message, bool exclude_from_all, + cmListFileBacktrace backtrace); + + bool Compute(cmLocalGenerator* lg) override; + + DependencyType GetDependencyType() const { return this->Type; } + + cmInstallRuntimeDependencySet* GetRuntimeDependencySet() const + { + return this->DependencySet; + } + + std::string GetDestination(std::string const& config) const; + +protected: + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + +private: + DependencyType Type; + cmInstallRuntimeDependencySet* DependencySet; + std::vector InstallRPaths; + bool NoInstallRPath; + std::string InstallNameDir; + bool NoInstallName; + std::string Permissions; + const char* DepsVar; + const char* RPathPrefix; + const char* TmpVarPrefix; + cmLocalGenerator* LocalGenerator = nullptr; + + void GenerateAppleLibraryScript( + std::ostream& os, const std::string& config, + const std::vector& evaluatedRPaths, Indent indent); + void GenerateAppleFrameworkScript( + std::ostream& os, const std::string& config, + const std::vector& evaluatedRPaths, Indent indent); + void GenerateInstallNameFixup( + std::ostream& os, const std::string& config, + const std::vector& evaluatedRPaths, + const std::string& filename, const std::string& depName, Indent indent); + void GenerateStripFixup(std::ostream& os, const std::string& config, + const std::string& depName, Indent indent); +}; diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx index 06246d1df5f..26f255da01c 100644 --- a/Source/cmRuntimeDependencyArchive.cxx +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -397,3 +397,11 @@ cmRuntimeDependencyArchive::GetRPaths() const { return this->RPaths; } + +bool cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( + const std::string& platform) +{ + static const std::set supportedPlatforms = { "Windows", "Linux", + "Darwin" }; + return supportedPlatforms.count(platform); +} diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h index 20a38e203d1..b170815b4be 100644 --- a/Source/cmRuntimeDependencyArchive.h +++ b/Source/cmRuntimeDependencyArchive.h @@ -53,6 +53,8 @@ class cmRuntimeDependencyArchive const std::set& GetUnresolvedPaths() const; const std::map>& GetRPaths() const; + static bool PlatformSupportsRuntimeDependencies(const std::string& platform); + private: cmExecutionStatus& Status; std::unique_ptr Linker; diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 94887a0dbed..0f6ec708bd1 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -44,7 +44,7 @@ function(check_installed expect) do not match what we expected: ${expect} in directory: - ${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE) + ${CMAKE_INSTALL_PREFIX}\n" PARENT_SCOPE) endif() endfunction() @@ -174,6 +174,21 @@ run_install_test(FILES-PERMISSIONS) run_install_test(TARGETS-RPATH) run_install_test(InstallRequiredSystemLibraries) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle) + run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$") + run_install_test(TARGETS-RUNTIME_DEPENDENCIES-nodep) + run_install_test(TARGETS-RUNTIME_DEPENDENCIES-empty) + set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME:STRING=${CMAKE_SYSTEM_NAME}") + run_cmake(TARGETS-RUNTIME_DEPENDENCIES-cross) + unset(RunCMake_TEST_OPTIONS) +else() + run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported) +endif() + set(run_install_test_components 1) run_install_test(FILES-EXCLUDE_FROM_ALL) run_install_test(TARGETS-EXCLUDE_FROM_ALL) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt new file mode 100644 index 00000000000..b7bbb55cece --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-cross\.cmake:[0-9]+ \(install\): + install TARGETS RUNTIME_DEPENDENCIES is not supported when cross-compiling\. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake new file mode 100644 index 00000000000..36b2eb7b4d6 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-cross.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_executable(exe main.c) +install(TARGETS exe RUNTIME_DEPENDENCIES) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake new file mode 100644 index 00000000000..dafc2a48b45 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty-all-check.cmake @@ -0,0 +1 @@ +check_installed([[^static;static/(liblib\.a|lib\.lib)$]]) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake new file mode 100644 index 00000000000..e46e1d9b2a1 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-empty.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +add_library(lib STATIC obj1.c) + +install(TARGETS lib RUNTIME_DEPENDENCIES + LIBRARY DESTINATION lib + ARCHIVE DESTINATION static + FRAMEWORK DESTINATION fw + ) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt new file mode 100644 index 00000000000..6ab14f6c1bd --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework\.cmake:[0-9]+ \(install\): + install TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake new file mode 100644 index 00000000000..36b2eb7b4d6 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_executable(exe main.c) +install(TARGETS exe RUNTIME_DEPENDENCIES) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt new file mode 100644 index 00000000000..c7b49c73b93 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle\.cmake:[0-9]+ \(install\): + install A runtime dependency set may only have one bundle executable\. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake new file mode 100644 index 00000000000..a848a24c3a1 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_executable(exe1 MACOSX_BUNDLE main.c) +add_executable(exe2 MACOSX_BUNDLE main.c) + +install(TARGETS exe1 exe2 + RUNTIME_DEPENDENCIES + BUNDLE DESTINATION bundles + FRAMEWORK DESTINATION fw + ) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake new file mode 100644 index 00000000000..9f455b1ba4c --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep-all-check.cmake @@ -0,0 +1 @@ +check_installed([[^bin;bin/exe(\.exe)?$]]) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake new file mode 100644 index 00000000000..02466561d62 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-nodep.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +add_executable(exe main.c) + +install(TARGETS exe + RUNTIME_DEPENDENCIES + PRE_EXCLUDE_REGEXES ".*" + FRAMEWORK DESTINATION fw + ) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt new file mode 100644 index 00000000000..c098a4c4e27 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-unsupported\.cmake:[0-9]+ \(install\): + install TARGETS RUNTIME_DEPENDENCIES is not supported on system "[^ +]*" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake new file mode 100644 index 00000000000..36b2eb7b4d6 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCIES-unsupported.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_executable(exe main.c) +install(TARGETS exe RUNTIME_DEPENDENCIES) diff --git a/bootstrap b/bootstrap index 720fa76b67c..f8d2f693c2f 100755 --- a/bootstrap +++ b/bootstrap @@ -387,8 +387,10 @@ CMAKE_CXX_SOURCES="\ cmInstallFilesCommand \ cmInstallFilesGenerator \ cmInstallGenerator \ + cmInstallGetRuntimeDependenciesGenerator \ cmInstallImportedRuntimeArtifactsGenerator \ cmInstallRuntimeDependencySet \ + cmInstallRuntimeDependencySetGenerator \ cmInstallScriptGenerator \ cmInstallSubdirectoryGenerator \ cmInstallTargetGenerator \ From 3e7d3c252a5638d66dbbe536be79d6ed3e0e288d Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 19 May 2021 13:36:30 -0400 Subject: [PATCH 0594/1519] install(TARGETS): Add RUNTIME_DEPENDENCY_SET argument --- Source/cmInstallCommand.cxx | 19 +++++++++++++++++++ Tests/RunCMake/install/RunCMakeTest.cmake | 2 ++ ...T-RUNTIME_DEPENDENCIES-conflict-result.txt | 1 + ...T-RUNTIME_DEPENDENCIES-conflict-stderr.txt | 5 +++++ ...CY_SET-RUNTIME_DEPENDENCIES-conflict.cmake | 7 +++++++ ...TIME_DEPENDENCY_SET-unsupported-result.txt | 1 + ...TIME_DEPENDENCY_SET-unsupported-stderr.txt | 5 +++++ ...S-RUNTIME_DEPENDENCY_SET-unsupported.cmake | 4 ++++ 8 files changed, 44 insertions(+) create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index c36778d8618..5d5a5a6d655 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -413,12 +413,14 @@ bool HandleTargetsMode(std::vector const& args, std::vector targetList; std::string exports; std::vector runtimeDependenciesArgVector; + std::string runtimeDependencySetArg; std::vector unknownArgs; std::vector parsedArgs; cmInstallCommandArguments genericArgs(helper.DefaultComponentName); genericArgs.Bind("TARGETS"_s, targetList); genericArgs.Bind("EXPORT"_s, exports); genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector); + genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg); genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs); bool success = genericArgs.Finalize(); @@ -537,6 +539,11 @@ bool HandleTargetsMode(std::vector const& args, cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr; if (withRuntimeDependencies) { + if (!runtimeDependencySetArg.empty()) { + status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and " + "RUNTIME_DEPENDENCY_SET."); + return false; + } auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( system)) { @@ -559,6 +566,18 @@ bool HandleTargetsMode(std::vector const& args, } runtimeDependencySet = helper.Makefile->GetGlobalGenerator() ->CreateAnonymousRuntimeDependencySet(); + } else if (!runtimeDependencySetArg.empty()) { + auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); + if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( + system)) { + status.SetError(cmStrCat( + "TARGETS RUNTIME_DEPENDENCY_SET is not supported on system \"", system, + '"')); + return false; + } + runtimeDependencySet = + helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet( + runtimeDependencySetArg); } // Select the mode for installing symlinks to versioned shared libraries. diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 0f6ec708bd1..bfd01ac6705 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -185,8 +185,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$") set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME:STRING=${CMAKE_SYSTEM_NAME}") run_cmake(TARGETS-RUNTIME_DEPENDENCIES-cross) unset(RunCMake_TEST_OPTIONS) + run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict) else() run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported) + run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-unsupported) endif() set(run_install_test_components 1) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt new file mode 100644 index 00000000000..e2484ec3bb1 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict\.cmake:[0-9]+ \(install\): + install TARGETS cannot have both RUNTIME_DEPENDENCIES and + RUNTIME_DEPENDENCY_SET\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake new file mode 100644 index 00000000000..f373b3b396b --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict.cmake @@ -0,0 +1,7 @@ +enable_language(C) + +add_executable(exe main.c) +install(TARGETS exe + RUNTIME_DEPENDENCY_SET deps + RUNTIME_DEPENDENCIES + ) diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt new file mode 100644 index 00000000000..f660346b445 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at TARGETS-RUNTIME_DEPENDENCY_SET-unsupported\.cmake:[0-9]+ \(install\): + install TARGETS RUNTIME_DEPENDENCY_SET is not supported on system "[^ +]*" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake new file mode 100644 index 00000000000..be0f507a4ea --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-RUNTIME_DEPENDENCY_SET-unsupported.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_executable(exe main.c) +install(TARGETS exe RUNTIME_DEPENDENCY_SET deps) From bc8a4a06a488a0cfd260901acf189e91c8906dbd Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 2 Jun 2021 10:30:55 -0400 Subject: [PATCH 0595/1519] install(IMPORTED_RUNTIME_ARTIFACTS): Add RUNTIME_DEPENDENCY_SET option --- Source/cmInstallCommand.cxx | 41 ++++++++++++++++++- ...TIME_DEPENDENCY_SET-unsupported-result.txt | 1 + ...TIME_DEPENDENCY_SET-unsupported-stderr.txt | 6 +++ ...S-RUNTIME_DEPENDENCY_SET-unsupported.cmake | 2 + Tests/RunCMake/install/RunCMakeTest.cmake | 1 + 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt create mode 100644 Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt create mode 100644 Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 5d5a5a6d655..67451aad9fc 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1098,9 +1098,11 @@ bool HandleImportedRuntimeArtifactsMode(std::vector const& args, // now parse the generic args (i.e. the ones not specialized on LIBRARY, // RUNTIME etc. (see above) std::vector targetList; + std::string runtimeDependencySetArg; std::vector unknownArgs; cmInstallCommandArguments genericArgs(helper.DefaultComponentName); - genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList); + genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList) + .Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg); genericArgs.Parse(genericArgVector, &unknownArgs); bool success = genericArgs.Finalize(); @@ -1139,6 +1141,22 @@ bool HandleImportedRuntimeArtifactsMode(std::vector const& args, return false; } + cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr; + if (!runtimeDependencySetArg.empty()) { + auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); + if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( + system)) { + status.SetError( + cmStrCat("IMPORTED_RUNTIME_ARTIFACTS RUNTIME_DEPENDENCY_SET is not " + "supported on system \"", + system, '"')); + return false; + } + runtimeDependencySet = + helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet( + runtimeDependencySetArg); + } + // Check if there is something to do. if (targetList.empty()) { return true; @@ -1217,6 +1235,9 @@ bool HandleImportedRuntimeArtifactsMode(std::vector const& args, if (target.IsDLLPlatform()) { runtimeGenerator = createInstallGenerator( target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs)); + if (runtimeDependencySet) { + runtimeDependencySet->AddLibrary(runtimeGenerator.get()); + } } else if (target.IsFrameworkOnApple()) { if (frameworkArgs.GetDestination().empty()) { status.SetError(cmStrCat("IMPORTED_RUNTIME_ARTIFACTS given no " @@ -1227,14 +1248,23 @@ bool HandleImportedRuntimeArtifactsMode(std::vector const& args, } frameworkGenerator = createInstallGenerator( target, frameworkArgs, frameworkArgs.GetDestination()); + if (runtimeDependencySet) { + runtimeDependencySet->AddLibrary(frameworkGenerator.get()); + } } else { libraryGenerator = createInstallGenerator( target, libraryArgs, helper.GetLibraryDestination(&libraryArgs)); + if (runtimeDependencySet) { + runtimeDependencySet->AddLibrary(libraryGenerator.get()); + } } break; case cmStateEnums::MODULE_LIBRARY: libraryGenerator = createInstallGenerator( target, libraryArgs, helper.GetLibraryDestination(&libraryArgs)); + if (runtimeDependencySet) { + runtimeDependencySet->AddModule(libraryGenerator.get()); + } break; case cmStateEnums::EXECUTABLE: if (target.IsAppBundleOnApple()) { @@ -1247,9 +1277,18 @@ bool HandleImportedRuntimeArtifactsMode(std::vector const& args, } bundleGenerator = createInstallGenerator( target, bundleArgs, bundleArgs.GetDestination()); + if (runtimeDependencySet) { + if (!AddBundleExecutable(helper, runtimeDependencySet, + bundleGenerator.get())) { + return false; + } + } } else { runtimeGenerator = createInstallGenerator( target, runtimeArgs, helper.GetRuntimeDestination(&runtimeArgs)); + if (runtimeDependencySet) { + runtimeDependencySet->AddExecutable(runtimeGenerator.get()); + } } break; default: diff --git a/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt new file mode 100644 index 00000000000..7ae66062556 --- /dev/null +++ b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported\.cmake:[0-9]+ \(install\): + install IMPORTED_RUNTIME_ARTIFACTS RUNTIME_DEPENDENCY_SET is not supported + on system "[^ +]*" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake new file mode 100644 index 00000000000..04f199509a6 --- /dev/null +++ b/Tests/RunCMake/install/IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported.cmake @@ -0,0 +1,2 @@ +add_executable(exe IMPORTED) +install(IMPORTED_RUNTIME_ARTIFACTS exe RUNTIME_DEPENDENCY_SET deps) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index bfd01ac6705..6f6a19316a7 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -189,6 +189,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$") else() run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported) run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-unsupported) + run_cmake(IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported) endif() set(run_install_test_components 1) From 4910132d8c94ac2c08fddd3fafc79585e7423362 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 19 May 2021 15:06:15 -0400 Subject: [PATCH 0596/1519] install: Add RUNTIME_DEPENDENCY_SET mode --- Source/cmInstallCommand.cxx | 115 ++++++++++++++++++ ...TIME_DEPENDENCY_SET-unsupported-result.txt | 1 + ...TIME_DEPENDENCY_SET-unsupported-stderr.txt | 5 + .../RUNTIME_DEPENDENCY_SET-unsupported.cmake | 1 + Tests/RunCMake/install/RunCMakeTest.cmake | 1 + 5 files changed, 123 insertions(+) create mode 100644 Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt create mode 100644 Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt create mode 100644 Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 67451aad9fc..79109b50820 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1942,6 +1942,120 @@ bool HandleExportMode(std::vector const& args, return true; } +bool HandleRuntimeDependencySetMode(std::vector const& args, + cmExecutionStatus& status) +{ + Helper helper(status); + + auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); + if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies( + system)) { + status.SetError(cmStrCat( + "RUNTIME_DEPENDENCY_SET is not supported on system \"", system, '"')); + return false; + } + + // This is the RUNTIME_DEPENDENCY_SET mode. + cmInstallRuntimeDependencySet* runtimeDependencySet; + + struct ArgVectors + { + std::vector Library; + std::vector Runtime; + std::vector Framework; + }; + + static auto const argHelper = cmArgumentParser{} + .Bind("LIBRARY"_s, &ArgVectors::Library) + .Bind("RUNTIME"_s, &ArgVectors::Runtime) + .Bind("FRAMEWORK"_s, &ArgVectors::Framework); + + std::vector genericArgVector; + ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector); + + // now parse the generic args (i.e. the ones not specialized on LIBRARY, + // RUNTIME, FRAMEWORK etc. (see above) + // These generic args also contain the runtime dependency set + std::string runtimeDependencySetArg; + std::vector runtimeDependencyArgVector; + std::vector parsedArgs; + cmInstallCommandArguments genericArgs(helper.DefaultComponentName); + genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg); + genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr, + &parsedArgs); + bool success = genericArgs.Finalize(); + + cmInstallCommandArguments libraryArgs(helper.DefaultComponentName); + cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName); + cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName); + + // Now also parse the file(GET_RUNTIME_DEPENDENCY) args + std::vector unknownArgs; + auto runtimeDependencyArgs = RuntimeDependenciesArgHelper.Parse( + runtimeDependencyArgVector, &unknownArgs); + + // now parse the args for specific parts of the target (e.g. LIBRARY, + // RUNTIME, FRAMEWORK etc. + libraryArgs.Parse(argVectors.Library, &unknownArgs); + runtimeArgs.Parse(argVectors.Runtime, &unknownArgs); + frameworkArgs.Parse(argVectors.Framework, &unknownArgs); + + libraryArgs.SetGenericArguments(&genericArgs); + runtimeArgs.SetGenericArguments(&genericArgs); + frameworkArgs.SetGenericArguments(&genericArgs); + + success = success && libraryArgs.Finalize(); + success = success && runtimeArgs.Finalize(); + success = success && frameworkArgs.Finalize(); + + if (!success) { + return false; + } + + if (!unknownArgs.empty()) { + helper.SetError( + cmStrCat("RUNTIME_DEPENDENCY_SET given unknown argument \"", + unknownArgs.front(), "\".")); + return false; + } + + if (runtimeDependencySetArg.empty()) { + helper.SetError( + "RUNTIME_DEPENDENCY_SET not given a runtime dependency set."); + return false; + } + + runtimeDependencySet = + helper.Makefile->GetGlobalGenerator()->GetNamedRuntimeDependencySet( + runtimeDependencySetArg); + + bool installsRuntime = false; + bool installsLibrary = false; + bool installsFramework = false; + + AddInstallRuntimeDependenciesGenerator( + helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs, + std::move(runtimeDependencyArgs), installsRuntime, installsLibrary, + installsFramework); + + // Tell the global generator about any installation component names + // specified + if (installsLibrary) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + libraryArgs.GetComponent()); + } + if (installsRuntime) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + runtimeArgs.GetComponent()); + } + if (installsFramework) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + frameworkArgs.GetComponent()); + } + + return true; +} + bool Helper::MakeFilesFullPath(const char* modeName, const std::vector& relFiles, std::vector& absFiles) @@ -2176,6 +2290,7 @@ bool cmInstallCommand(std::vector const& args, { "DIRECTORY"_s, HandleDirectoryMode }, { "EXPORT"_s, HandleExportMode }, { "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode }, + { "RUNTIME_DEPENDENCY_SET"_s, HandleRuntimeDependencySetMode }, }; return subcommand(args[0], args, status); diff --git a/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt new file mode 100644 index 00000000000..cab309b2cbd --- /dev/null +++ b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at RUNTIME_DEPENDENCY_SET-unsupported\.cmake:[0-9]+ \(install\): + install RUNTIME_DEPENDENCY_SET is not supported on system "[^ +]*" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake new file mode 100644 index 00000000000..60772a0f342 --- /dev/null +++ b/Tests/RunCMake/install/RUNTIME_DEPENDENCY_SET-unsupported.cmake @@ -0,0 +1 @@ +install(RUNTIME_DEPENDENCY_SET deps) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 6f6a19316a7..e9a29c431c5 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -190,6 +190,7 @@ else() run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported) run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-unsupported) run_cmake(IMPORTED_RUNTIME_ARTIFACTS-RUNTIME_DEPENDENCY_SET-unsupported) + run_cmake(RUNTIME_DEPENDENCY_SET-unsupported) endif() set(run_install_test_components 1) From f9383e01402ba428aa7b26b6ec7019db08ea86d6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 09:09:52 -0400 Subject: [PATCH 0597/1519] VS: Re-order v141 and v142 CL flag table entries to match xml files better --- Templates/MSBuild/FlagTables/v141_CL.json | 28 +++++++++++------------ Templates/MSBuild/FlagTables/v142_CL.json | 28 +++++++++++------------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v141_CL.json b/Templates/MSBuild/FlagTables/v141_CL.json index 01fafe48df1..d4701f3cd19 100644 --- a/Templates/MSBuild/FlagTables/v141_CL.json +++ b/Templates/MSBuild/FlagTables/v141_CL.json @@ -588,6 +588,20 @@ "value": "Send", "flags": [] }, + { + "name": "SupportJustMyCode", + "switch": "JMC-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "SupportJustMyCode", + "switch": "JMC", + "comment": "", + "value": "true", + "flags": [] + }, { "name": "CompileAsWinRT", "switch": "ZW", @@ -1250,19 +1264,5 @@ "comment": "C++14 (GNU Dialect)", "value": "gnu++1y", "flags": [] - }, - { - "name": "SupportJustMyCode", - "switch": "JMC-", - "comment": "", - "value": "false", - "flags": [] - }, - { - "name": "SupportJustMyCode", - "switch": "JMC", - "comment": "", - "value": "true", - "flags": [] } ] diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 3305e5643a9..68dcb13097a 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -433,6 +433,20 @@ "value": "Spectre", "flags": [] }, + { + "name": "ConformanceMode", + "switch": "permissive-", + "comment": "Conformance mode enabled", + "value": "true", + "flags": [] + }, + { + "name": "ConformanceMode", + "switch": "permissive", + "comment": "Conformance mode disabled", + "value": "false", + "flags": [] + }, { "name": "LanguageStandard", "switch": "std:c++14", @@ -879,20 +893,6 @@ "value": "true", "flags": [] }, - { - "name": "ConformanceMode", - "switch": "permissive-", - "comment": "Conformance mode enabled", - "value": "true", - "flags": [] - }, - { - "name": "ConformanceMode", - "switch": "permissive", - "comment": "Conformance mode disabled", - "value": "false", - "flags": [] - }, { "name": "TreatWChar_tAsBuiltInType", "switch": "Zc:wchar_t-", From 0c3c6acaff7e59712bdfc6ef66292ccebe8c5bcb Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 2 Jun 2021 09:46:37 -0400 Subject: [PATCH 0598/1519] Tests: Add tests for new options --- Tests/CMakeLists.txt | 1 + Tests/ExportImport/CMakeLists.txt | 36 +++++---- Tests/ExportImport/Export/CMakeLists.txt | 2 + .../CMakeLists.txt | 42 +++++++++++ .../install-RUNTIME_DEPENDENCY_SET/deplib.c | 12 +++ Tests/ExportImport/Import/CMakeLists.txt | 6 ++ .../ExportImport/Import/check_installed.cmake | 20 +++++ .../check_installed.cmake | 21 +----- .../CMakeLists.txt | 74 +++++++++++++++++++ .../check_installed.cmake | 11 +++ .../Import/install-RUNTIME_DEPENDENCIES/lib.c | 12 +++ .../install-RUNTIME_DEPENDENCIES/main.c | 31 ++++++++ .../Import/install-RUNTIME_DEPENDENCIES/mod.c | 12 +++ .../install-RUNTIME_DEPENDENCIES/sublib1.c | 12 +++ .../install-RUNTIME_DEPENDENCIES/sublib2.c | 12 +++ .../CMakeLists.txt | 33 +++++++++ .../check_installed.cmake | 11 +++ .../install-RUNTIME_DEPENDENCY_SET/main.c | 15 ++++ Tests/RunCMake/install/RunCMakeTest.cmake | 1 + .../RuntimeDependencies-COMPONENTS.cmake | 39 ++++++++++ 20 files changed, 369 insertions(+), 34 deletions(-) create mode 100644 Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt create mode 100644 Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c create mode 100644 Tests/ExportImport/Import/check_installed.cmake create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake create mode 100644 Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c create mode 100644 Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 38b43014445..1005016b4f3 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -478,6 +478,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(Preprocess Preprocess) set(ExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM} -DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA} + -DCMake_INSTALL_NAME_TOOL_BUG:BOOL=${CMake_INSTALL_NAME_TOOL_BUG} ) ADD_TEST_MACRO(ExportImport ExportImport) set_property(TEST ExportImport APPEND diff --git a/Tests/ExportImport/CMakeLists.txt b/Tests/ExportImport/CMakeLists.txt index 4999612ff2d..e3f32c2cfa2 100644 --- a/Tests/ExportImport/CMakeLists.txt +++ b/Tests/ExportImport/CMakeLists.txt @@ -77,21 +77,29 @@ set_property( PROPERTY SYMBOLIC 1 ) -# Install the imported targets. -add_custom_command( - OUTPUT ${ExportImport_BINARY_DIR}/ImportInstall - COMMAND ${CMAKE_COMMAND} -E rm -rf ${ExportImport_BINARY_DIR}/Import/install - COMMAND ${CMAKE_COMMAND} - --install ${ExportImport_BINARY_DIR}/Import - --prefix ${ExportImport_BINARY_DIR}/Import/install - ${NESTED_CONFIG_INSTALL_TYPE} - ) -add_custom_target(ImportInstallTarget ALL DEPENDS ${ExportImport_BINARY_DIR}/ImportInstall) +# Run the install tests. +set(install_deps) +set(rdep_tests) +if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Windows|Darwin)$" AND NOT CMake_INSTALL_NAME_TOOL_BUG) + set(rdep_tests RUNTIME_DEPENDENCIES RUNTIME_DEPENDENCY_SET) +endif() +foreach(name IMPORTED_RUNTIME_ARTIFACTS ${rdep_tests}) + add_custom_command( + OUTPUT ${ExportImport_BINARY_DIR}/ImportInstall-${name} + COMMAND ${CMAKE_COMMAND} -E rm -rf ${ExportImport_BINARY_DIR}/Import/install-${name}/install + COMMAND ${CMAKE_COMMAND} + --install ${ExportImport_BINARY_DIR}/Import/install-${name} + --prefix ${ExportImport_BINARY_DIR}/Import/install-${name}/install + ${NESTED_CONFIG_INSTALL_TYPE} + ) + list(APPEND install_deps ${ExportImport_BINARY_DIR}/ImportInstall-${name}) + set_property( + SOURCE ${ExportImport_BINARY_DIR}/ImportInstall-${name} + PROPERTY SYMBOLIC 1 + ) +endforeach() +add_custom_target(ImportInstallTarget ALL DEPENDS ${install_deps}) add_dependencies(ImportInstallTarget ImportTarget) -set_property( - SOURCE ${ExportImport_BINARY_DIR}/ImportInstall - PROPERTY SYMBOLIC 1 - ) add_executable(ExportImport main.c) add_dependencies(ExportImport ImportTarget) diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index fa0016b2447..a2968d43346 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -690,3 +690,5 @@ if(NOT XCODE) install(TARGETS testLibFromGeneratedSource EXPORT testLibFromGeneratedSource_Export) install(EXPORT testLibFromGeneratedSource_Export DESTINATION lib) endif() + +add_subdirectory(install-RUNTIME_DEPENDENCY_SET) diff --git a/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt new file mode 100644 index 00000000000..f50cc1d4065 --- /dev/null +++ b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.20) + +set(CMAKE_SKIP_RPATH OFF) + +foreach(i 1 2 3 4 5 6 7 8 9 10 11 12) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dep${i}.c" +"#ifdef _WIN32 +__declspec(dllexport) +#endif + void dep${i}(void) +{ +} +") + add_library(dep${i} SHARED "${CMAKE_CURRENT_BINARY_DIR}/dep${i}.c") +endforeach() + +set_target_properties(dep9 PROPERTIES + FRAMEWORK TRUE + ) +set_target_properties(dep2 PROPERTIES + VERSION 1.2.3 + SOVERSION 1 + ) + +add_library(deplib SHARED deplib.c) +target_link_libraries(deplib PRIVATE dep1) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_target_properties(deplib PROPERTIES + INSTALL_RPATH "@loader_path/" + ) +endif() + +install(TARGETS dep1 dep2 dep3 dep4 dep5 dep6 dep7 dep8 dep9 dep10 dep11 dep12 deplib EXPORT install-RUNTIME_DEPENDENCY_SET + RUNTIME DESTINATION install-RUNTIME_DEPENDENCY_SET/bin + LIBRARY DESTINATION install-RUNTIME_DEPENDENCY_SET/lib + ARCHIVE DESTINATION install-RUNTIME_DEPENDENCY_SET/lib + FRAMEWORK DESTINATION install-RUNTIME_DEPENDENCY_SET/frameworks + ) +install(EXPORT install-RUNTIME_DEPENDENCY_SET + FILE targets.cmake + DESTINATION install-RUNTIME_DEPENDENCY_SET + ) diff --git a/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c new file mode 100644 index 00000000000..e5da19609e3 --- /dev/null +++ b/Tests/ExportImport/Export/install-RUNTIME_DEPENDENCY_SET/deplib.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep1(void); + +#ifdef _WIN32 +__declspec(dllexport) +#endif + void deplib(void) +{ + dep1(); +} diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt index e64c6b40789..006313091f1 100644 --- a/Tests/ExportImport/Import/CMakeLists.txt +++ b/Tests/ExportImport/Import/CMakeLists.txt @@ -29,3 +29,9 @@ add_subdirectory(version_range) # Test install(IMPORTED_RUNTIME_ARTIFACTS) add_subdirectory(install-IMPORTED_RUNTIME_ARTIFACTS) + +# Test install(RUNTIME_DEPENDENCIES) and install(RUNTIME_DEPENDENCY_SET) +if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Windows|Darwin)$") + add_subdirectory(install-RUNTIME_DEPENDENCIES) + add_subdirectory(install-RUNTIME_DEPENDENCY_SET) +endif() diff --git a/Tests/ExportImport/Import/check_installed.cmake b/Tests/ExportImport/Import/check_installed.cmake new file mode 100644 index 00000000000..6e51f9275f7 --- /dev/null +++ b/Tests/ExportImport/Import/check_installed.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.20) + +function(check_installed expect) + file(GLOB_RECURSE actual + LIST_DIRECTORIES TRUE + RELATIVE ${CMAKE_INSTALL_PREFIX} + ${CMAKE_INSTALL_PREFIX}/* + ) + if(actual) + list(SORT actual) + endif() + if(NOT "${actual}" MATCHES "${expect}") + message(FATAL_ERROR "Installed files: + ${actual} +do not match what we expected: + ${expect} +in directory: + ${CMAKE_INSTALL_PREFIX}") + endif() +endfunction() diff --git a/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake index 29b298fbf39..054ce9cc04a 100644 --- a/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake +++ b/Tests/ExportImport/Import/install-IMPORTED_RUNTIME_ARTIFACTS/check_installed.cmake @@ -1,23 +1,4 @@ -cmake_minimum_required(VERSION 3.20) - -function(check_installed expect) - file(GLOB_RECURSE actual - LIST_DIRECTORIES TRUE - RELATIVE ${CMAKE_INSTALL_PREFIX} - ${CMAKE_INSTALL_PREFIX}/* - ) - if(actual) - list(SORT actual) - endif() - if(NOT "${actual}" MATCHES "${expect}") - message(FATAL_ERROR "Installed files: - ${actual} -do not match what we expected: - ${expect} -in directory: - ${CMAKE_INSTALL_PREFIX}") - endif() -endfunction() +include("${CMAKE_CURRENT_LIST_DIR}/../check_installed.cmake") if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") set(_dirs [[aaa;aaa/executables;aaa/executables/testExe1-4;aaa/executables/testExe3;aaa/libraries;aaa/libraries/libtestExe2lib\.so;aaa/libraries/libtestLib3lib(-d|-r)?\.so\.1\.2;aaa/libraries/libtestLib3lib(-d|-r)?\.so\.3;aaa/libraries/libtestLib4\.so;aaa/libraries/libtestMod1\.so;aaa/libraries/libtestMod2\.so]]) diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt new file mode 100644 index 00000000000..d1c4ff2f9d2 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/CMakeLists.txt @@ -0,0 +1,74 @@ +set(CMAKE_SKIP_RPATH OFF) + +# Import targets from the install tree. +include(${Import_BINARY_DIR}/../Root/install-RUNTIME_DEPENDENCY_SET/targets.cmake) + +add_executable(exe1 main.c) +add_executable(exe2 main.c) + +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_target_properties(exe1 exe2 PROPERTIES + # Multiple MACOSX_BUNDLE executables are allowed on non-macOS platforms. + MACOSX_BUNDLE TRUE + ) +endif() + +add_library(sublib1 SHARED sublib1.c) +target_link_libraries(sublib1 PRIVATE dep6) + +add_library(sublib2 SHARED sublib2.c) +target_link_libraries(sublib2 PRIVATE dep7) + +foreach(i exe1 exe2) + target_link_libraries(${i} PRIVATE + dep1 + dep2 + dep3 + dep4 + dep5 + dep10 + dep11 + dep12 + sublib1 + sublib2 + ) +endforeach() + +add_library(lib SHARED lib.c) +target_link_libraries(lib PRIVATE dep8) + +add_library(mod MODULE mod.c) +target_link_libraries(mod PRIVATE dep9) +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_target_properties(mod PROPERTIES + SKIP_BUILD_RPATH TRUE + ) +endif() + +set(_framework_args) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(_framework_args FRAMEWORK DESTINATION subdir/frameworks) +endif() +install(TARGETS exe1 exe2 lib mod sublib1 + RUNTIME_DEPENDENCIES + PRE_INCLUDE_REGEXES "$<1:dep([2-9]|1[012])>" + PRE_EXCLUDE_REGEXES "$<1:.*>" + POST_INCLUDE_REGEXES "$<1:(bin|lib)/(lib)?dep3>" + POST_EXCLUDE_REGEXES "$<1:(bin|lib)/(lib)?dep[34]>" + POST_INCLUDE_FILES "$" "$" + POST_EXCLUDE_FILES "$" "$" + DIRECTORIES "$" + RUNTIME DESTINATION "$<1:subdir/bin>" + LIBRARY DESTINATION "$<1:subdir/lib>" + ${_framework_args} + ) + +install(TARGETS lib + RUNTIME_DEPENDENCIES + PRE_INCLUDE_REGEXES dep8 + PRE_EXCLUDE_REGEXES ".*" + DIRECTORIES "$" + ${_framework_args} + ) + +install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/check_installed.cmake") diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake new file mode 100644 index 00000000000..6a34697f883 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/check_installed.cmake @@ -0,0 +1,11 @@ +include("${CMAKE_CURRENT_LIST_DIR}/../check_installed.cmake") + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + check_installed([[^lib;lib/libdep8\.so;lib/liblib\.so;subdir;subdir/bin;subdir/bin/exe1;subdir/bin/exe2;subdir/lib;subdir/lib/libdep10\.so;subdir/lib/libdep11\.so;subdir/lib/libdep2\.so\.1;subdir/lib/libdep2\.so\.1\.2\.3;subdir/lib/libdep3\.so;subdir/lib/libdep5\.so;subdir/lib/libdep6\.so;subdir/lib/libdep8\.so;subdir/lib/libdep9\.so;subdir/lib/liblib\.so;subdir/lib/libmod\.so;subdir/lib/libsublib1\.so$]]) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(_msvc_check [[bin;bin/dep8\.dll;bin/lib\.dll;lib;lib/lib\.lib;subdir;subdir/bin;subdir/bin/dep10\.dll;subdir/bin/dep11\.dll;subdir/bin/dep2\.dll;subdir/bin/dep3\.dll;subdir/bin/dep5\.dll;subdir/bin/dep6\.dll;subdir/bin/dep8\.dll;subdir/bin/dep9\.dll;subdir/bin/exe1\.exe;subdir/bin/exe2\.exe;subdir/bin/lib\.dll;subdir/bin/sublib1\.dll;subdir/lib;subdir/lib/mod\.dll]]) + set(_mingw_check [[bin;bin/libdep8\.dll;bin/liblib\.dll;lib;lib/liblib\.dll\.a;lib/liblib\.lib;subdir;subdir/bin;subdir/bin/exe1\.exe;subdir/bin/exe2\.exe;subdir/bin/libdep10\.dll;subdir/bin/libdep11\.dll;subdir/bin/libdep2\.dll;subdir/bin/libdep3\.dll;subdir/bin/libdep5\.dll;subdir/bin/libdep6\.dll;subdir/bin/libdep8\.dll;subdir/bin/libdep9\.dll;subdir/bin/liblib\.dll;subdir/bin/libsublib1\.dll;subdir/lib;subdir/lib/libmod\.dll]]) + check_installed("^(${_msvc_check}|${_mingw_check})$") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + check_installed([[^lib;lib/libdep8\.dylib;lib/liblib\.dylib;subdir;subdir/bin;subdir/bin/exe1;subdir/bin/exe2;subdir/frameworks;subdir/frameworks/dep9\.framework;subdir/frameworks/dep9\.framework/Resources;subdir/frameworks/dep9\.framework/Versions;subdir/frameworks/dep9\.framework/Versions/A;subdir/frameworks/dep9\.framework/Versions/A/Resources;subdir/frameworks/dep9\.framework/Versions/A/Resources/Info\.plist(;subdir/frameworks/dep9.framework/Versions/A/_CodeSignature;subdir/frameworks/dep9.framework/Versions/A/_CodeSignature/CodeResources)?;subdir/frameworks/dep9\.framework/Versions/A/dep9;subdir/frameworks/dep9\.framework/Versions/Current;subdir/frameworks/dep9\.framework/dep9;subdir/lib;subdir/lib/libdep10\.dylib;subdir/lib/libdep11\.dylib;subdir/lib/libdep2\.1\.2\.3\.dylib;subdir/lib/libdep2\.1\.dylib;subdir/lib/libdep3\.dylib;subdir/lib/libdep5\.dylib;subdir/lib/libdep6\.dylib;subdir/lib/libdep8\.dylib;subdir/lib/liblib\.dylib;subdir/lib/libmod\.so;subdir/lib/libsublib1\.dylib$]]) +endif() diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c new file mode 100644 index 00000000000..9a648874b07 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/lib.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep8(void); + +#ifdef _WIN32 +__declspec(dllexport) +#endif + void lib(void) +{ + dep8(); +} diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c new file mode 100644 index 00000000000..94a7862d4c5 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/main.c @@ -0,0 +1,31 @@ +#ifdef _WIN32 +# define DLLIMPORT __declspec(dllimport) +#else +# define DLLIMPORT +#endif + +DLLIMPORT extern void dep1(void); +DLLIMPORT extern void dep2(void); +DLLIMPORT extern void dep3(void); +DLLIMPORT extern void dep4(void); +DLLIMPORT extern void dep5(void); +DLLIMPORT extern void dep10(void); +DLLIMPORT extern void dep11(void); +DLLIMPORT extern void dep12(void); +DLLIMPORT extern void sublib1(void); +DLLIMPORT extern void sublib2(void); + +int main(void) +{ + dep1(); + dep2(); + dep3(); + dep4(); + dep5(); + dep10(); + dep11(); + dep12(); + sublib1(); + sublib2(); + return 0; +} diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c new file mode 100644 index 00000000000..d001299bdb8 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/mod.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep9(void); + +#ifdef _WIN32 +__declspec(dllexport) +#endif + void mod(void) +{ + dep9(); +} diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c new file mode 100644 index 00000000000..f17b9026ed7 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib1.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep6(void); + +#ifdef _WIN32 +__declspec(dllexport) +#endif + void sublib1(void) +{ + dep6(); +} diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c new file mode 100644 index 00000000000..61b5c839590 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCIES/sublib2.c @@ -0,0 +1,12 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep7(void); + +#ifdef _WIN32 +__declspec(dllexport) +#endif + void sublib2(void) +{ + dep7(); +} diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt new file mode 100644 index 00000000000..516450644df --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/CMakeLists.txt @@ -0,0 +1,33 @@ +set(CMAKE_SKIP_RPATH OFF) + +# Import targets from the install tree. +include(${Import_BINARY_DIR}/../Root/install-RUNTIME_DEPENDENCY_SET/targets.cmake) + +add_executable(exe main.c) +target_link_libraries(exe PRIVATE dep3 dep4) + +install(TARGETS exe RUNTIME_DEPENDENCY_SET myset) +install(IMPORTED_RUNTIME_ARTIFACTS deplib RUNTIME_DEPENDENCY_SET myset) + +install(RUNTIME_DEPENDENCY_SET myset + PRE_INCLUDE_REGEXES "dep[134]" + PRE_EXCLUDE_REGEXES ".*" + POST_INCLUDE_REGEXES "dep[13]" + POST_EXCLUDE_REGEXES "dep[34]" + DIRECTORIES "$" + ) +install(RUNTIME_DEPENDENCY_SET myset + PRE_INCLUDE_REGEXES "dep[134]" + PRE_EXCLUDE_REGEXES ".*" + DIRECTORIES "$" + RUNTIME DESTINATION yyy/bin + LIBRARY DESTINATION yyy/lib + ) +install(RUNTIME_DEPENDENCY_SET myset + PRE_INCLUDE_REGEXES "dep[134]" + PRE_EXCLUDE_REGEXES ".*" + DIRECTORIES "$" + DESTINATION zzz + ) + +install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/check_installed.cmake") diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake new file mode 100644 index 00000000000..052ccede57b --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/check_installed.cmake @@ -0,0 +1,11 @@ +include("${CMAKE_CURRENT_LIST_DIR}/../check_installed.cmake") + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + check_installed([[^bin;bin/exe;lib;lib/libdep1\.so;lib/libdep3\.so;lib/libdeplib\.so;yyy;yyy/lib;yyy/lib/libdep1\.so;yyy/lib/libdep3\.so;yyy/lib/libdep4\.so;zzz;zzz/libdep1\.so;zzz/libdep3\.so;zzz/libdep4\.so$]]) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(_msvc_check [[bin;bin/dep1\.dll;bin/dep3\.dll;bin/deplib\.dll;bin/exe\.exe;yyy;yyy/bin;yyy/bin/dep1\.dll;yyy/bin/dep3\.dll;yyy/bin/dep4\.dll;zzz;zzz/dep1\.dll;zzz/dep3\.dll;zzz/dep4\.dll]]) + set(_mingw_check [[bin;bin/exe\.exe;bin/libdep1\.dll;bin/libdep3\.dll;bin/libdeplib\.dll;yyy;yyy/bin;yyy/bin/libdep1\.dll;yyy/bin/libdep3\.dll;yyy/bin/libdep4\.dll;zzz;zzz/libdep1\.dll;zzz/libdep3\.dll;zzz/libdep4\.dll]]) + check_installed("^(${_msvc_check}|${_mingw_check})$") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + check_installed([[^bin;bin/exe;lib;lib/libdep1\.dylib;lib/libdep3\.dylib;lib/libdeplib\.dylib;yyy;yyy/lib;yyy/lib/libdep1\.dylib;yyy/lib/libdep3\.dylib;yyy/lib/libdep4\.dylib;zzz;zzz/libdep1\.dylib;zzz/libdep3\.dylib;zzz/libdep4\.dylib$]]) +endif() diff --git a/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c new file mode 100644 index 00000000000..b359498b7c8 --- /dev/null +++ b/Tests/ExportImport/Import/install-RUNTIME_DEPENDENCY_SET/main.c @@ -0,0 +1,15 @@ +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep3(void); +#ifdef _WIN32 +__declspec(dllimport) +#endif + extern void dep4(void); + +int main(void) +{ + dep3(); + dep4(); + return 0; +} diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index e9a29c431c5..f79a3ea7454 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -186,6 +186,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$") run_cmake(TARGETS-RUNTIME_DEPENDENCIES-cross) unset(RunCMake_TEST_OPTIONS) run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-RUNTIME_DEPENDENCIES-conflict) + run_cmake(RuntimeDependencies-COMPONENTS) else() run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported) run_cmake(TARGETS-RUNTIME_DEPENDENCY_SET-unsupported) diff --git a/Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake b/Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake new file mode 100644 index 00000000000..4727de35fd3 --- /dev/null +++ b/Tests/RunCMake/install/RuntimeDependencies-COMPONENTS.cmake @@ -0,0 +1,39 @@ +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() + +install(TARGETS tgt + RUNTIME_DEPENDENCIES + RUNTIME DESTINATION bin COMPONENT bin1 + LIBRARY DESTINATION lib COMPONENT lib1 + FRAMEWORK DESTINATION fw COMPONENT fw1 + ) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + check_components("bin1;fw1;lib1") +else() + check_components("bin1;lib1") +endif() + +install(RUNTIME_DEPENDENCY_SET deps + RUNTIME DESTINATION bin COMPONENT bin2 + LIBRARY DESTINATION lib COMPONENT lib2 + FRAMEWORK DESTINATION fw COMPONENT fw2 + ) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + check_components("bin1;fw1;fw2;lib1;lib2") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + check_components("bin1;bin2;lib1") +elseif() + check_components("bin1;lib1;lib2") +endif() From 25e33a282b13ac94817f51d2bc7a1870965ba4ee Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 09:23:34 -0400 Subject: [PATCH 0599/1519] VS: Update v141 CL flag table for VS 15.9 Run the command python3 Source/cmConvertMSBuildXMLToJSON.py -t v141 \ 'c:/.../Common7/IDE/VC/VCTargets/1033/cl.xml' To generate `v141_CL.json` locally. Manually move new and updated settings over to `Templates/MSBuild/FlagTables/v141_CL.json`. --- Templates/MSBuild/FlagTables/v141_CL.json | 25 +++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v141_CL.json b/Templates/MSBuild/FlagTables/v141_CL.json index d4701f3cd19..5b18e32ea25 100644 --- a/Templates/MSBuild/FlagTables/v141_CL.json +++ b/Templates/MSBuild/FlagTables/v141_CL.json @@ -419,10 +419,31 @@ "value": "Fast", "flags": [] }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-load-cf", + "comment": "All Control Flow Loads", + "value": "SpectreLoadCF", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-load", + "comment": "All Loads", + "value": "SpectreLoad", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-", + "comment": "Disabled", + "value": "false", + "flags": [] + }, { "name": "SpectreMitigation", "switch": "Qspectre", - "comment": "Spectre mitigations", + "comment": "Enabled", "value": "Spectre", "flags": [] }, @@ -826,7 +847,7 @@ { "name": "ConformanceMode", "switch": "permissive-", - "comment": "Conformance mode enabled", + "comment": "Conformance mode", "value": "true", "flags": [] }, From 887e9df0c7f5898905c670888a44e9a8a8ca82f7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 08:44:27 -0400 Subject: [PATCH 0600/1519] VS: Update v142 CL flag table for VS 16.10 Run the command python3 Source/cmConvertMSBuildXMLToJSON.py -t v142 \ 'c:/.../MSBuild/Microsoft/VC/v160/1033/cl.xml' To generate `v142_CL.json` locally. Manually move new and updated settings over to `Templates/MSBuild/FlagTables/v142_CL.json`. Revise the `/sourceDependencies[:directives]` table entries to properly distinguish the two options (because one is a prefix of the other), and to populate both `Generate*Dependencies` and `*DependenciesFile`. --- Templates/MSBuild/FlagTables/v142_CL.json | 224 +++++++++++++++++++++- 1 file changed, 219 insertions(+), 5 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 68dcb13097a..650ff6c1809 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -384,6 +384,13 @@ "value": "AdvancedVectorExtensions2", "flags": [] }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:AVX512", + "comment": "Advanced Vector Extensions 512", + "value": "AdvancedVectorExtensions512", + "flags": [] + }, { "name": "EnableEnhancedInstructionSet", "switch": "arch:IA32", @@ -419,31 +426,45 @@ "value": "Fast", "flags": [] }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-load-cf", + "comment": "All Control Flow Loads", + "value": "SpectreLoadCF", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-load", + "comment": "All Loads", + "value": "SpectreLoad", + "flags": [] + }, { "name": "SpectreMitigation", "switch": "Qspectre-", - "comment": "Spectre mitigations disabled", + "comment": "Disabled", "value": "false", "flags": [] }, { "name": "SpectreMitigation", "switch": "Qspectre", - "comment": "Spectre mitigations enabled", + "comment": "Enabled", "value": "Spectre", "flags": [] }, { "name": "ConformanceMode", "switch": "permissive-", - "comment": "Conformance mode enabled", + "comment": "Yes", "value": "true", "flags": [] }, { "name": "ConformanceMode", "switch": "permissive", - "comment": "Conformance mode disabled", + "comment": "No", "value": "false", "flags": [] }, @@ -630,6 +651,27 @@ "value": "CompileAsCpp", "flags": [] }, + { + "name": "CompileAs", + "switch": "interface", + "comment": "Compile as C++ Module Code", + "value": "CompileAsCppModule", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "internalPartition", + "comment": "Compile as C++ Module Internal Partition", + "value": "CompileAsCppModuleInternalPartition", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "exportHeader", + "comment": "Compile as C++ Header Unit", + "value": "CompileAsHeaderUnit", + "flags": [] + }, { "name": "ErrorReporting", "switch": "errorReport:none", @@ -732,6 +774,13 @@ "Continue" ] }, + { + "name": "ForceSynchronousPDBWrites", + "switch": "FS", + "comment": "Force Synchronous PDB Writes", + "value": "true", + "flags": [] + }, { "name": "IntrinsicFunctions", "switch": "Oi", @@ -802,6 +851,20 @@ "value": "true", "flags": [] }, + { + "name": "UseStandardPreprocessor", + "switch": "Zc:preprocessor-", + "comment": "Use Standard Conforming Preprocessor", + "value": "false", + "flags": [] + }, + { + "name": "UseStandardPreprocessor", + "switch": "Zc:preprocessor", + "comment": "Use Standard Conforming Preprocessor", + "value": "true", + "flags": [] + }, { "name": "StringPooling", "switch": "GF-", @@ -886,6 +949,41 @@ "value": "true", "flags": [] }, + { + "name": "IntelJCCErratum", + "switch": "QIntel-jcc-erratum", + "comment": "Enable Intel JCC Erratum Mitigation", + "value": "true", + "flags": [] + }, + { + "name": "GuardEHContMetadata", + "switch": "guard:ehcont-", + "comment": "Enable EH Continuation Metadata", + "value": "false", + "flags": [] + }, + { + "name": "GuardEHContMetadata", + "switch": "guard:ehcont", + "comment": "Enable EH Continuation Metadata", + "value": "true", + "flags": [] + }, + { + "name": "GuardSignedReturns", + "switch": "guard:signret-", + "comment": "Enable Signed Returns", + "value": "false", + "flags": [] + }, + { + "name": "GuardSignedReturns", + "switch": "guard:signret", + "comment": "Enable Signed Returns", + "value": "true", + "flags": [] + }, { "name": "DisableLanguageExtensions", "switch": "Za", @@ -980,7 +1078,7 @@ { "name": "EnableModules", "switch": "experimental:module", - "comment": "Enable C++ Modules (experimental)", + "comment": "Enable Experimental C++ Standard Library Modules", "value": "true", "flags": [] }, @@ -998,6 +1096,15 @@ "value": "true", "flags": [] }, + { + "name": "GenerateModuleDependencies", + "switch": "sourceDependencies:directives", + "comment": "Generate Module Dependenices File", + "value": "true", + "flags": [ + "Continue" + ] + }, { "name": "GenerateXMLDocumentationFiles", "switch": "doc", @@ -1009,6 +1116,15 @@ "Continue" ] }, + { + "name": "GenerateSourceDependencies", + "switch": "sourceDependencies", + "comment": "Generate Source Dependencies File", + "value": "true", + "flags": [ + "Continue" + ] + }, { "name": "BrowseInformation", "switch": "FR", @@ -1020,6 +1136,27 @@ "Continue" ] }, + { + "name": "TreatAngleIncludeAsExternal", + "switch": "external:anglebrackets", + "comment": "Treat Files Included with Angle Brackets as External", + "value": "true", + "flags": [] + }, + { + "name": "ExternalTemplatesDiagnostics", + "switch": "external:templates-", + "comment": "Template Diagnostics in External Headers", + "value": "true", + "flags": [] + }, + { + "name": "DisableAnalyzeExternal", + "switch": "analyze:external-", + "comment": "Disable Code Analysis for External Headers", + "value": "true", + "flags": [] + }, { "name": "ShowIncludes", "switch": "showIncludes", @@ -1075,6 +1212,36 @@ "SemicolonAppendable" ] }, + { + "name": "AdditionalBMIDirectories", + "switch": "ifcSearchDir", + "comment": "Additional BMI Directories", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalModuleDependencies", + "switch": "reference", + "comment": "Additional Module Dependencies", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalHeaderUnitDependencies", + "switch": "headerUnit", + "comment": "Additional Header Unit Dependencies", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, { "name": "PreprocessorDefinitions", "switch": "D", @@ -1095,6 +1262,26 @@ "SemicolonAppendable" ] }, + { + "name": "StdIfcDirectory", + "switch": "stdIfcDir", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "ExternalDirectoriesEnv", + "switch": "external:env:", + "comment": "External Directories Environment Variables", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, { "name": "DisableSpecificWarnings", "switch": "wd", @@ -1210,6 +1397,24 @@ "UserValue" ] }, + { + "name": "ModuleOutputFile", + "switch": "ifcOutput", + "comment": "Module Output File Name", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ModuleDependenciesFile", + "switch": "sourceDependencies:directives", + "comment": "Module Dependencies File Name", + "value": "", + "flags": [ + "UserFollowing" + ] + }, { "name": "ObjectFileName", "switch": "Fo", @@ -1238,6 +1443,15 @@ "UserRequired" ] }, + { + "name": "SourceDependenciesFile", + "switch": "sourceDependencies", + "comment": "Source Dependencies File Name", + "value": "", + "flags": [ + "UserFollowing" + ] + }, { "name": "BrowseInformationFile", "switch": "FR", From ed3aad97e3d3cb27637722fabb0ae3a5611daf5c Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 12:13:29 -0400 Subject: [PATCH 0601/1519] cmGeneratorTarget: Clear cached link implementation when a source is added Adding a source file at generate time can cause the linker language or other settings to change that affect `GetLinkImplementationLibraries` and friends. --- Source/cmGeneratorTarget.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 5deb2dfe45c..6209f3e54ac 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -697,6 +697,7 @@ void cmGeneratorTarget::ClearSourcesCache() this->SourcesAreContextDependent = Tribool::Indeterminate; this->Objects.clear(); this->VisitedConfigsForObjects.clear(); + this->LinkImplMap.clear(); } void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) From 7e5e558d0f7cd0e5ac579322c13142d1fac93f0a Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 13:06:43 -0400 Subject: [PATCH 0602/1519] gitlab-ci: add job to test with clang-7 on debian10 Test with a Clang version old enough to have caught the regression fixed by commit 9411766c35 (BinUtils: Avoid llvm-objdump versions older than Clang 9, 2021-05-29). --- .gitlab-ci.yml | 10 ++++++++++ .gitlab/ci/configure_debian10_makefiles_clang.cmake | 1 + .gitlab/ci/env_debian10_makefiles_clang.sh | 2 ++ .gitlab/os-linux.yml | 9 +++++++++ 4 files changed, 22 insertions(+) create mode 100644 .gitlab/ci/configure_debian10_makefiles_clang.cmake create mode 100644 .gitlab/ci/env_debian10_makefiles_clang.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bf002228c4e..236eac9901d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -176,6 +176,16 @@ test:debian10-aarch64-ninja: variables: CMAKE_CI_NO_MR: "true" +test:debian10-makefiles-clang: + extends: + - .debian10_makefiles_clang + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_manually + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + test:fedora34-makefiles: extends: - .fedora34_makefiles diff --git a/.gitlab/ci/configure_debian10_makefiles_clang.cmake b/.gitlab/ci/configure_debian10_makefiles_clang.cmake new file mode 100644 index 00000000000..20863a2fb08 --- /dev/null +++ b/.gitlab/ci/configure_debian10_makefiles_clang.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/env_debian10_makefiles_clang.sh b/.gitlab/ci/env_debian10_makefiles_clang.sh new file mode 100644 index 00000000000..e0d5d6105b3 --- /dev/null +++ b/.gitlab/ci/env_debian10_makefiles_clang.sh @@ -0,0 +1,2 @@ +export CC=/usr/bin/clang-7 +export CXX=/usr/bin/clang++-7 diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index a8c07d8c3e1..015df4f12d6 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -149,6 +149,15 @@ CTEST_NO_WARNINGS_ALLOWED: 1 CMAKE_GENERATOR: "Unix Makefiles" +### Clang Compiler + +.debian10_makefiles_clang: + extends: .debian10 + + variables: + CMAKE_CONFIGURATION: debian10_makefiles_clang + CMAKE_GENERATOR: "Unix Makefiles" + ### Intel Compiler .intelcompiler: From c44dfdfdbb62a8ad505ceff16444f36ce2ad33b0 Mon Sep 17 00:00:00 2001 From: John Drouhard Date: Fri, 4 Jun 2021 12:22:36 -0500 Subject: [PATCH 0603/1519] FindBoost: Add check for json component header in Boost 1.75+ In commit 8293064760 (FindBoost: Add support for Boost 1.75, 2021-02-03, v3.19.5~9^2) the dependencies of the json component were added, but the header listing was left out. --- Modules/FindBoost.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index d31f925cb60..df997e1b4e6 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -1405,6 +1405,7 @@ function(_Boost_COMPONENT_HEADERS component _hdrs) set(_Boost_LOCALE_HEADERS "boost/locale.hpp") set(_Boost_LOG_HEADERS "boost/log/core.hpp") set(_Boost_LOG_SETUP_HEADERS "boost/log/detail/setup_config.hpp") + set(_Boost_JSON_HEADERS "boost/json.hpp") set(_Boost_MATH_HEADERS "boost/math_fwd.hpp") set(_Boost_MATH_C99_HEADERS "boost/math/tr1.hpp") set(_Boost_MATH_C99F_HEADERS "boost/math/tr1.hpp") From 72f2448e82d8b3e90fa733cb6c631298083ae06b Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 19 May 2021 15:19:38 -0400 Subject: [PATCH 0604/1519] Help: Add documentation for runtime dependency installation --- Help/command/install.rst | 108 ++++++++++++++++++ Help/manual/cmake-generator-expressions.7.rst | 5 +- .../dev/install-runtime-dependencies.rst | 9 ++ 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/install-runtime-dependencies.rst diff --git a/Help/command/install.rst b/Help/command/install.rst index 4d41fb30840..acfaa486d13 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -15,6 +15,7 @@ Synopsis install(`SCRIPT`_ [...]) install(`CODE`_ [...]) install(`EXPORT`_ [...]) + install(`RUNTIME_DEPENDENCY_SET`_ [...]) Introduction ^^^^^^^^^^^^ @@ -125,6 +126,7 @@ Installing Targets .. code-block:: cmake install(TARGETS targets... [EXPORT ] + [RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET ] [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE] [DESTINATION ] @@ -339,6 +341,34 @@ top level: relative path is specified, it is treated as relative to the ``$``. +``RUNTIME_DEPENDENCY_SET`` + .. versionadded:: 3.21 + + This option causes all runtime dependencies of installed executable, shared + library, and module targets to be added to the specified runtime dependency + set. This set can then be installed later on with an + `install(RUNTIME_DEPENDENCY_SET)`_ command. + + This argument and the ``RUNTIME_DEPENDENCIES`` argument are mutually + exclusive. + +``RUNTIME_DEPENDENCIES`` + .. versionadded:: 3.21 + + This option causes all runtime dependencies of installed executable, shared + library, and module targets to be installed along with the targets + themselves. The ``RUNTIME``, ``LIBRARY``, ``FRAMEWORK``, and generic + arguments are used to determine the properties (``DESTINATION``, + ``COMPONENT``, etc.) of the installation of these dependencies. + + ``RUNTIME_DEPENDENCIES`` is semantically equivalent to calling + ``install(TARGETS ... RUNTIME_DEPENDENCY_SET)`` and then + `install(RUNTIME_DEPENDENCY_SET)`_ with a randomly generated name. It accepts + all of the same options as `install(RUNTIME_DEPENDENCY_SET)`_. + + This argument and the ``RUNTIME_DEPENDENCY_SET`` argument are mutually + exclusive. + One or more groups of properties may be specified in a single call to the ``TARGETS`` form of this command. A target may be installed more than once to different locations. Consider hypothetical targets ``myExe``, @@ -394,6 +424,7 @@ Installing Imported Runtime Artifacts .. code-block:: cmake install(IMPORTED_RUNTIME_ARTIFACTS targets... + [RUNTIME_DEPENDENCY_SET ] [[LIBRARY|RUNTIME|FRAMEWORK|BUNDLE] [DESTINATION ] [PERMISSIONS permissions...] @@ -415,6 +446,15 @@ not installed. In the case of :prop_tgt:`FRAMEWORK` libraries, :prop_tgt:`MACOSX_BUNDLE` executables, and :prop_tgt:`BUNDLE` CFBundles, the entire directory is installed. +``IMPORTED_RUNTIME_ARTIFACTS`` accepts the following additional arguments: + +``RUNTIME_DEPENDENCY_SET`` + + This option causes all runtime dependencies of installed executable, shared + library, and module targets to be added to the specified runtime dependency + set. This set can then be installed later on with an + `install(RUNTIME_DEPENDENCY_SET)`_ command. + Installing Files ^^^^^^^^^^^^^^^^ @@ -773,6 +813,74 @@ executable from the installation tree using the imported target name :command:`install_files`, and :command:`install_programs` commands is not defined. +Installing Runtime Dependencies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _`install(RUNTIME_DEPENDENCY_SET)`: +.. _RUNTIME_DEPENDENCY_SET: + +.. versionadded:: 3.21 + +.. code-block:: cmake + + install(RUNTIME_DEPENDENCY_SET + [[LIBRARY|RUNTIME|FRAMEWORK] + [DESTINATION ] + [PERMISSIONS permissions...] + [CONFIGURATIONS [Debug|Release|...]] + [COMPONENT ] + [NAMELINK_COMPONENT ] + [OPTIONAL] [EXCLUDE_FROM_ALL] + ] [...] + [PRE_INCLUDE_REGEXES regexes...] + [PRE_EXCLUDE_REGEXES regexes...] + [POST_INCLUDE_REGEXES regexes...] + [POST_EXCLUDE_REGEXES regexes...] + [DIRECTORIES directories...] + ) + +Installs a runtime dependency set created by one or more +`install(TARGETS)`_ or `install(IMPORTED_RUNTIME_ARTIFACTS)`_ commands. The +dependencies of targets belonging to a runtime dependency set are installed in +the ``RUNTIME`` destination and component on DLL platforms, and in the +``LIBRARY`` destination and component on non-DLL platforms. macOS frameworks +are installed in the ``FRAMEWORK`` destination and component. The generated +install script calls :command:`file(GET_RUNTIME_DEPENDENCIES)` on the +build-tree files to calculate the runtime dependencies, with the build-tree +executable files as the ``EXECUTABLES`` argument, the build-tree shared +libraries as the ``LIBRARIES`` argument, and the build-tree modules as the +``MODULES`` argument. If one of the executables is a :prop_tgt:`MACOSX_BUNDLE` +executable on a macOS platform, that executable is passed as the +``BUNDLE_EXECUTABLE`` argument. If ``RUNTIME_DEPENDENCY_SET`` is specified on +a macOS platform, at most one :prop_tgt:`MACOSX_BUNDLE` executable may be in +the runtime dependency set. The :prop_tgt:`MACOSX_BUNDLE` property has no +effect on non-macOS platforms. Targets built within the build tree will never +be installed as runtime dependencies, nor will their own dependencies, unless +the targets themselves are installed with `install(TARGETS)`_. + +This argument accepts the following sub-arguments: + +``DIRECTORIES `` + List of directories to be passed as the ``DIRECTORIES`` argument of + :command:`file(GET_RUNTIME_DEPENDENCIES)`. This argument supports + :manual:`generator expressions `. If a + ``DIRECTORIES`` argument evaluates to an empty string, it is not passed to + :command:`file(GET_RUNTIME_DEPENDENCIES)`. + +``PRE_INCLUDE_REGEXES ``, ``PRE_EXCLUDE_REGEXES ``, ``POST_INCLUDE_REGEXES ``, ``POST_EXCLUDE_REGEXES `` + List of regular expressions to be passed as their respective arguments to + :command:`file(GET_RUNTIME_DEPENDENCIES)`. These arguments support + :manual:`generator expressions `. If an + argument evaluates to an empty string, it is not passed to + :command:`file(GET_RUNTIME_DEPENDENCIES)`. + +``POST_INCLUDE_FILES ``, ``POST_EXCLUDE_FILES `` + List of files to be passed as their respective arguments to + :command:`file(GET_RUNTIME_DEPENDENCIES)`. These arguments support + :manual:`generator expressions `. If an + argument evaluates to an empty string, it is not passed to + :command:`file(GET_RUNTIME_DEPENDENCIES)`. + Generated Installation Script ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 775067a8558..0ba41c8972a 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -966,8 +966,9 @@ which is just the string ``tgt``. .. genex:: $ Content of the install prefix when the target is exported via - :command:`install(EXPORT)`, or when evaluated in - :prop_tgt:`INSTALL_NAME_DIR`, and empty otherwise. + :command:`install(EXPORT)`, or when evaluated in the + :prop_tgt:`INSTALL_NAME_DIR` property or the ``INSTALL_NAME_DIR`` argument of + :command:`install(RUNTIME_DEPENDENCY_SET)`, and empty otherwise. Output-Related Expressions -------------------------- diff --git a/Help/release/dev/install-runtime-dependencies.rst b/Help/release/dev/install-runtime-dependencies.rst new file mode 100644 index 00000000000..58c92e6a533 --- /dev/null +++ b/Help/release/dev/install-runtime-dependencies.rst @@ -0,0 +1,9 @@ +install-runtime-dependencies +---------------------------- + +* The :command:`install(TARGETS)` command gained new ``RUNTIME_DEPENDENCIES`` + and ``RUNTIME_DEPENDENCY_SET`` arguments, which can be used to install + runtime dependencies using :command:`file(GET_RUNTIME_DEPENDENCIES)`. +* The :command:`install` command gained a new ``RUNTIME_DEPENDENCY_SET`` mode, + which can be used to install runtime dependencies using + :command:`file(GET_RUNTIME_DEPENDENCIES)`. From 8d898cb3e10d6ad44bbe542b7b219a0b788b2a0d Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 2 Jun 2021 14:55:43 -0400 Subject: [PATCH 0605/1519] FileAPI: Add integration for runtime dependency installers --- Help/manual/cmake-file-api.7.rst | 24 +++ Source/cmFileAPICodemodel.cxx | 28 ++- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 16 ++ .../codemodel-v2-data/directories/cxx.json | 163 +++++++++++++++++- .../codemodel-v2-data/targets/cxx_exe.json | 17 ++ Tests/RunCMake/FileAPI/cxx/CMakeLists.txt | 15 ++ 6 files changed, 259 insertions(+), 4 deletions(-) diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index e7d78c3a862..5e22ea9051a 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -752,6 +752,12 @@ with members: The ``destination`` member is populated. The ``isOptional`` member may exist. This type has no additional members. + ``runtimeDependencySet`` + An :command:`install(RUNTIME_DEPENDENCY_SET)` call or an + :command:`install(TARGETS)` call with ``RUNTIME_DEPENDENCIES``. The + ``destination`` member is populated. This type has additional members + ``runtimeDependencySetName`` and ``runtimeDependencySetType``. + ``isExcludeFromAll`` Optional member that is present with boolean value ``true`` when :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option. @@ -811,6 +817,24 @@ with members: An unsigned integer 0-based index into the main "codemodel" object's ``targets`` array for the target. + ``runtimeDependencySetName`` + Optional member that is present when ``type`` is ``runtimeDependencySet`` + and the installer was created by an + :command:`install(RUNTIME_DEPENDENCY_SET)` call. The value is a string + specifying the name of the runtime dependency set that was installed. + + ``runtimeDependencySetType`` + Optional member that is present when ``type`` is ``runtimeDependencySet``. + The value is a string with one of the following values: + + ``library`` + Indicates that this installer installs dependencies that are not macOS + frameworks. + + ``framework`` + Indicates that this installer installs dependencies that are macOS + frameworks. + ``scriptFile`` Optional member that is present when ``type`` is ``script``. The value is a string specifying the path to the script file on disk, diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index ff11f4a797b..2c15c254aed 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -29,7 +30,10 @@ #include "cmInstallExportGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallGetRuntimeDependenciesGenerator.h" #include "cmInstallImportedRuntimeArtifactsGenerator.h" +#include "cmInstallRuntimeDependencySet.h" +#include "cmInstallRuntimeDependencySetGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" @@ -876,8 +880,10 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) { Json::Value installer = Json::objectValue; - // Exclude subdirectory installers. They are implementation details. - if (dynamic_cast(gen)) { + // Exclude subdirectory installers and file(GET_RUNTIME_DEPENDENCIES) + // installers. They are implementation details. + if (dynamic_cast(gen) || + dynamic_cast(gen)) { return installer; } @@ -1019,6 +1025,24 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) if (installImportedRuntimeArtifacts->GetOptional()) { installer["isOptional"] = true; } + } else if (auto* installRuntimeDependencySet = + dynamic_cast(gen)) { + installer["type"] = "runtimeDependencySet"; + installer["destination"] = + installRuntimeDependencySet->GetDestination(this->Config); + std::string name( + installRuntimeDependencySet->GetRuntimeDependencySet()->GetName()); + if (!name.empty()) { + installer["runtimeDependencySetName"] = name; + } + switch (installRuntimeDependencySet->GetDependencyType()) { + case cmInstallRuntimeDependencySetGenerator::DependencyType::Framework: + installer["runtimeDependencySetType"] = "framework"; + break; + case cmInstallRuntimeDependencySetGenerator::DependencyType::Library: + installer["runtimeDependencySetType"] = "library"; + break; + } } // Add fields common to all install generators. diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 9911ad5be3e..6cf57a3a96f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -180,6 +180,14 @@ def _check(actual, expected): expected_keys.append("scriptFile") assert is_string(a["scriptFile"], e["scriptFile"]) + if e.get("runtimeDependencySetName", None) is not None: + expected_keys.append("runtimeDependencySetName") + assert is_string(a["runtimeDependencySetName"], e["runtimeDependencySetName"]) + + if e.get("runtimeDependencySetType", None) is not None: + expected_keys.append("runtimeDependencySetType") + assert is_string(a["runtimeDependencySetType"], e["runtimeDependencySetType"]) + if e["backtrace"] is not None: expected_keys.append("backtrace") check_backtrace(d, a["backtrace"], e["backtrace"]) @@ -650,6 +658,14 @@ def gen_check_directories(c, g): if "pathsNamelink" in i: i["paths"] = i["pathsNamelink"] + if sys.platform not in ("win32", "darwin") and "linux" not in sys.platform: + for e in expected: + e["installers"] = list(filter(lambda i: i["type"] != "runtimeDependencySet", e["installers"])) + + if sys.platform != "darwin": + for e in expected: + e["installers"] = list(filter(lambda i: i.get("runtimeDependencySetType", None) != "framework", e["installers"])) + return expected def check_directories(c, g): diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json index 7168306d320..8052c1a5501 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json @@ -17,6 +17,165 @@ ], "projectName": "Cxx", "minimumCMakeVersion": "3.12", - "hasInstallRule": null, - "installers": [] + "hasInstallRule": true, + "installers": [ + { + "component": "Unspecified", + "type": "target", + "destination": "lib", + "paths": [ + "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$" + ], + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": null, + "targetId": "^cxx_exe::@a56b12a3f5c0529fb296$", + "targetIndex": "cxx_exe", + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 38, + "command": "install", + "hasParent": true + }, + { + "file": "^cxx/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "runtimeDependencySet", + "destination": "lib", + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "runtimeDependencySetType": "library", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 38, + "command": "install", + "hasParent": true + }, + { + "file": "^cxx/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "runtimeDependencySet", + "destination": "fw", + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "runtimeDependencySetType": "framework", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 38, + "command": "install", + "hasParent": true + }, + { + "file": "^cxx/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "runtimeDependencySet", + "destination": "lib", + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "runtimeDependencySetType": "library", + "runtimeDependencySetName": "deps", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 43, + "command": "install", + "hasParent": true + }, + { + "file": "^cxx/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "component": "Unspecified", + "type": "runtimeDependencySet", + "destination": "fw", + "paths": null, + "isExcludeFromAll": null, + "isForAllComponents": null, + "isOptional": null, + "targetId": null, + "targetIndex": null, + "targetIsImportLibrary": null, + "targetInstallNamelink": null, + "exportName": null, + "exportTargets": null, + "scriptFile": null, + "runtimeDependencySetType": "framework", + "runtimeDependencySetName": "deps", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 43, + "command": "install", + "hasParent": true + }, + { + "file": "^cxx/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json index c9e652b2a43..385fa622dd7 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json @@ -114,6 +114,23 @@ "install": { "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$", "destinations": [ + { + "path": "lib", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 38, + "command": "install", + "hasParent": true + }, + { + "file": "^cxx/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, { "path": "bin", "backtrace": [ diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt index 95c803fb65c..3ae3b60a1e8 100644 --- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt @@ -30,3 +30,18 @@ if(CMAKE_CXX_STANDARD_DEFAULT AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION) target_compile_features(cxx_standard_compile_feature_exe PRIVATE cxx_decltype) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_std_11.txt" "") endif() + +set(_rdeps) +if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Windows|Darwin)$") + set(_rdeps RUNTIME_DEPENDENCIES) +endif() +install(TARGETS cxx_exe ${_rdeps} + DESTINATION lib + FRAMEWORK DESTINATION fw + ) +if(_rdeps) + install(RUNTIME_DEPENDENCY_SET deps + DESTINATION lib + FRAMEWORK DESTINATION fw + ) +endif() From 48b7360ede8821824111c36af64360662c28f88e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 5 Jun 2021 00:01:11 -0400 Subject: [PATCH 0606/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 90bc5b5eb14..29df1fa018f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210604) +set(CMake_VERSION_PATCH 20210605) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 42af35136f9540f984cacd3f9dfd02d82a09f1f4 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 6 Jun 2021 00:01:06 -0400 Subject: [PATCH 0607/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 29df1fa018f..fadcabc98b9 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210605) +set(CMake_VERSION_PATCH 20210606) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 41dea08423efa2b0db493c536a3af031f1a29945 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 6 Jun 2021 17:14:29 +1000 Subject: [PATCH 0608/1519] Help: Remove recommendations for using CMAKE_CFG_INTDIR Commit e71c4f7729 (CMAKE_CFG_INTDIR: Formally deprecate in favor of $, 2021-05-27) only updated the docs for CMAKE_CFG_INTDIR itself, but other parts of the docs still used it. Update the other places to avoid referring to the now-deprecated variable. --- Help/prop_tgt/IMPORTED_OBJECTS.rst | 22 ++++++++++----------- Help/variable/CMAKE_CONFIGURATION_TYPES.rst | 6 ++++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Help/prop_tgt/IMPORTED_OBJECTS.rst b/Help/prop_tgt/IMPORTED_OBJECTS.rst index f3577eb99e2..d71c2199952 100644 --- a/Help/prop_tgt/IMPORTED_OBJECTS.rst +++ b/Help/prop_tgt/IMPORTED_OBJECTS.rst @@ -68,26 +68,24 @@ architecture: # /path/to/somewhere/objects-iphonesimulator/x86_64/func.o In some cases, you may want to have configuration-specific object files -as well. The :variable:`CMAKE_CFG_INTDIR` variable can be a convenient -way of capturing this in combination with the SDK: +as well. The ``$(CONFIGURATION)`` Xcode variable is often used for this and +can be used in conjunction with the others mentioned above: .. code-block:: cmake add_library(someObjs OBJECT IMPORTED) set_property(TARGET someObjs PROPERTY IMPORTED_OBJECTS - "/path/to/somewhere/${CMAKE_CFG_INTDIR}/$(CURRENT_ARCH)/func.o" + "/path/to/somewhere/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/$(CURRENT_ARCH)/func.o" ) # Example paths: # /path/to/somewhere/Release-iphoneos/arm64/func.o # /path/to/somewhere/Debug-iphonesimulator/x86_64/func.o -When any Xcode variable or :variable:`CMAKE_CFG_INTDIR` is used, CMake is -not able to fully evaluate the path(s) at configure time. One consequence -of this is that the configuration-specific -:prop_tgt:`IMPORTED_OBJECTS_` properties cannot be used, since -CMake cannot determine whether an object file exists at a particular -```` location. The ``IMPORTED_OBJECTS`` property must be used for -these situations and the configuration-specific aspects of the path must be -handled by using :variable:`CMAKE_CFG_INTDIR` or with another Xcode variable -``$(CONFIGURATION)``. +When any Xcode variable is used, CMake is not able to fully evaluate the +path(s) at configure time. One consequence of this is that the +configuration-specific :prop_tgt:`IMPORTED_OBJECTS_` properties cannot +be used, since CMake cannot determine whether an object file exists at a +particular ```` location. The ``IMPORTED_OBJECTS`` property must be +used for these situations and the configuration-specific aspects of the path +should be handled by the ``$(CONFIGURATION)`` Xcode variable. diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst index 34e99ebf709..8fcc798696c 100644 --- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst +++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst @@ -6,5 +6,7 @@ Specifies the available build types on multi-config generators. This specifies what build types (configurations) will be available such as ``Debug``, ``Release``, ``RelWithDebInfo`` etc. This has reasonable defaults on most platforms, but can be extended to provide other build -types. See also :variable:`CMAKE_BUILD_TYPE` for details of managing -configuration data, and :variable:`CMAKE_CFG_INTDIR`. +types. + +See :variable:`CMAKE_BUILD_TYPE` for specifying the configuration with +single-config generators. From 4ee2fc28a66930836cbd1493cdf420a477b500e9 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 7 Jun 2021 00:01:16 -0400 Subject: [PATCH 0609/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fadcabc98b9..3fd94d6c638 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210606) +set(CMake_VERSION_PATCH 20210607) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ece24b343ad4ce6bfe09817116222456453a2317 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 7 Jun 2021 07:10:58 -0400 Subject: [PATCH 0610/1519] Help/cpack_gen/freebsd: improve wording for Debian fallbacks Documentation should describe what happens, and "we may as well" seems way too conversational. --- Help/cpack_gen/freebsd.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/cpack_gen/freebsd.rst b/Help/cpack_gen/freebsd.rst index 2c9356956cd..f429bc5fa9b 100644 --- a/Help/cpack_gen/freebsd.rst +++ b/Help/cpack_gen/freebsd.rst @@ -74,7 +74,7 @@ the RPM information (e.g. package license). * Default: - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already - for Debian packaging, so we may as well re-use it). + for Debian packaging, so it is used as a fallback). .. variable:: CPACK_FREEBSD_PACKAGE_WWW @@ -87,7 +87,7 @@ the RPM information (e.g. package license). - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set, :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already - for Debian packaging, so we may as well re-use it). + for Debian packaging, so it is used as a fallback). .. versionadded:: 3.12 The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable. From ed1f3a5fa58872143c084fdd9b08a6a4335186c5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 7 Jun 2021 07:11:44 -0400 Subject: [PATCH 0611/1519] CPackDeb: output the error message when no description can be made The `message` command does not support automatic dereferencing. --- Modules/Internal/CPack/CPackDeb.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index 2ef0489b662..2ceab10bc1c 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -557,7 +557,7 @@ function(cpack_deb_prepare_package_vars) string(APPEND _description_failure_message " or CPACK_DEBIAN_${_local_component_name}_DESCRIPTION") endif() - message(FATAL_ERROR _description_failure_message) + message(FATAL_ERROR "${_description_failure_message}") endif() # Ok, description has set. According to the `Debian Policy Manual`_ the first From 98fa09d5befbb970fe6230b95f49ee6821d301b1 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 7 Jun 2021 19:23:13 +0300 Subject: [PATCH 0612/1519] FindOpenSSL: Link with ws2_32 and crypt32 on Windows/static --- Modules/FindOpenSSL.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index b1afa5f4012..8474e05c517 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -123,6 +123,10 @@ function(_OpenSSL_target_add_dependencies target) set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads ) set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} ) endif() + if(WIN32 AND OPENSSL_USE_STATIC_LIBS) + set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2_32 ) + set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES crypt32 ) + endif() endfunction() if (UNIX) From 8f68bcad8fafddc82b73b69f21e122ece8603a8f Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 10:40:56 -0400 Subject: [PATCH 0613/1519] Tests: Add cases verifying flag ordering rules --- Tests/CMakeLists.txt | 5 ++++ Tests/CompileOptions/CMakeLists.txt | 28 +++++++++++++++++-- Tests/CompileOptions/main.cpp | 18 ++++++++++++ Tests/RunCMake/CMakeLists.txt | 5 +++- .../Order-build-stdout.txt | 3 ++ .../target_compile_options/Order.cmake | 19 +++++++++++++ .../target_compile_options/RunCMakeTest.cmake | 13 +++++++++ Tests/RunCMake/target_compile_options/order.c | 7 +++++ 8 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/target_compile_options/Order-build-stdout.txt create mode 100644 Tests/RunCMake/target_compile_options/Order.cmake create mode 100644 Tests/RunCMake/target_compile_options/order.c diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 38b43014445..331f6375f84 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -489,6 +489,11 @@ if(BUILD_TESTING) if(CMAKE_Fortran_COMPILER) set(CompileOptions_BUILD_OPTIONS -DTEST_FORTRAN=1) endif() + if(_isMultiConfig) + set(CompileOptions_CTEST_OPTIONS --build-config $) + else() + set(CompileOptions_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=$) + endif() ADD_TEST_MACRO(CompileOptions CompileOptions) ADD_TEST_MACRO(CompatibleInterface CompatibleInterface) ADD_TEST_MACRO(AliasTarget AliasTarget) diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt index cd6cacd757f..96bafeadd51 100644 --- a/Tests/CompileOptions/CMakeLists.txt +++ b/Tests/CompileOptions/CMakeLists.txt @@ -1,5 +1,11 @@ -cmake_minimum_required(VERSION 2.8.12) - +cmake_minimum_required(VERSION 3.0) +if(POLICY CMP0092) + cmake_policy(SET CMP0092 NEW) +endif() +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE) +endif() project(CompileOptions) add_library(testlib other.cpp) @@ -49,6 +55,24 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Borland|Embarcadero" AND NOT "${CMAK ) endif() +if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|AppleClang|MSVC)$") + target_compile_definitions(CompileOptions PRIVATE "DO_FLAG_TESTS") + if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|AppleClang)$") + string(APPEND CMAKE_CXX_FLAGS " -w") + endif() + string(APPEND CMAKE_CXX_FLAGS " -DFLAG_A=1 -DFLAG_B=1") + string(APPEND CMAKE_CXX_FLAGS_DEBUG " -DFLAG_A=2 -DFLAG_C=1") + string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DFLAG_A=2 -DFLAG_C=1") + string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DFLAG_A=2 -DFLAG_C=1") + string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DFLAG_A=2 -DFLAG_C=1") + set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS "-DFLAG_B=2" "-DFLAG_C=2" "-DFLAG_D=1") + set_property(TARGET testlib APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-DFLAG_D=2") + if(NOT CMAKE_GENERATOR MATCHES "^Visual Studio 9") + set_property(TARGET testlib APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-DFLAG_E=1") + set_property(SOURCE main.cpp PROPERTY COMPILE_OPTIONS "-DFLAG_E=2") + endif() +endif() + target_link_libraries(CompileOptions testlib) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp index ebc10176223..23ce1970f3b 100644 --- a/Tests/CompileOptions/main.cpp +++ b/Tests/CompileOptions/main.cpp @@ -37,6 +37,24 @@ # endif #endif +#ifdef DO_FLAG_TESTS +# if FLAG_A != 2 +# error "FLAG_A is not 2" +# endif +# if FLAG_B != 2 +# error "FLAG_B is not 2" +# endif +# if FLAG_C != 2 +# error "FLAG_C is not 2" +# endif +# if FLAG_D != 2 +# error "FLAG_D is not 2" +# endif +# if defined(FLAG_E) && FLAG_E != 2 +# error "FLAG_E is not 2" +# endif +#endif + #include int main() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index d02d7a2fd57..670abbcbd1a 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -595,7 +595,10 @@ set_property(TEST RunCMake.target_link_options APPEND add_RunCMake_test(target_compile_definitions) add_RunCMake_test(target_compile_features) -add_RunCMake_test(target_compile_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) +add_RunCMake_test(target_compile_options + -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} + -DCMAKE_C_SIMULATE_ID=${CMAKE_C_SIMULATE_ID} + ) add_RunCMake_test(target_include_directories) add_RunCMake_test(target_sources) add_RunCMake_test(CheckCompilerFlag -DCMake_TEST_CUDA=${CMake_TEST_CUDA} diff --git a/Tests/RunCMake/target_compile_options/Order-build-stdout.txt b/Tests/RunCMake/target_compile_options/Order-build-stdout.txt new file mode 100644 index 00000000000..c210ff213f5 --- /dev/null +++ b/Tests/RunCMake/target_compile_options/Order-build-stdout.txt @@ -0,0 +1,3 @@ +-w +-O +-O0 [^ +]*-O1 +-O2 +-O3 [^ +]*CMakeFiles[\/]order\.dir[\/](Custom[\/])?order\.c\.o diff --git a/Tests/RunCMake/target_compile_options/Order.cmake b/Tests/RunCMake/target_compile_options/Order.cmake new file mode 100644 index 00000000000..3d59b16c91a --- /dev/null +++ b/Tests/RunCMake/target_compile_options/Order.cmake @@ -0,0 +1,19 @@ +get_property (isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(isMultiConfig) + set(CMAKE_CONFIGURATION_TYPES "Custom" CACHE STRING "" FORCE) +else() + set(CMAKE_BUILD_TYPE "Custom" CACHE STRING "" FORCE) +endif() +enable_language(C) + +string(APPEND CMAKE_C_FLAGS " -w -O") +set(CMAKE_C_FLAGS_CUSTOM "-O0") + +add_executable(order order.c) +set_property(TARGET order APPEND PROPERTY COMPILE_OPTIONS -O1) + +add_library(iface INTERFACE) +set_property(TARGET iface APPEND PROPERTY INTERFACE_COMPILE_OPTIONS -O2) +target_link_libraries(order PRIVATE iface) + +set_property(SOURCE order.c PROPERTY COMPILE_OPTIONS -O3) diff --git a/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake index 9f51a9a52ad..806ae79b087 100644 --- a/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_compile_options/RunCMakeTest.cmake @@ -19,3 +19,16 @@ if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") run_cmake_target(CMP0101-BEFORE_keyword OLD CMP0101_OLD) run_cmake_target(CMP0101-BEFORE_keyword NEW CMP0101_NEW) endif() + +function(run_Order) + run_cmake_with_options(Order) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Order-build) + set(RunCMake_TEST_OUTPUT_MERGE 1) + run_cmake_command(Order-build ${CMAKE_COMMAND} --build . --verbose --config Custom) +endfunction() +if(RunCMake_GENERATOR MATCHES "Ninja|Make" AND + CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$" AND + NOT CMAKE_C_SIMULATE_ID STREQUAL "MSVC") + run_Order() +endif() diff --git a/Tests/RunCMake/target_compile_options/order.c b/Tests/RunCMake/target_compile_options/order.c new file mode 100644 index 00000000000..1bd81eafb3c --- /dev/null +++ b/Tests/RunCMake/target_compile_options/order.c @@ -0,0 +1,7 @@ +#ifndef __OPTIMIZE__ +# error "Optimizations not enabled!" +#endif +int main(void) +{ + return 0; +} From efe7ac9022b18132d33c68919c81422d738cd672 Mon Sep 17 00:00:00 2001 From: Sam Freed Date: Thu, 3 Jun 2021 15:33:58 -0700 Subject: [PATCH 0614/1519] presets: Fix buildPreset "targets" not allowing a single string Fixes: #22272 --- Source/cmCMakePresetsFileReadJSON.cxx | 17 ++++++++++------- Tests/RunCMake/CMakePresetsBuild/Good.json.in | 5 +++++ .../CMakePresetsBuild/RunCMakeTest.cmake | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx index 909a78b5ee2..489551dcf08 100644 --- a/Source/cmCMakePresetsFileReadJSON.cxx +++ b/Source/cmCMakePresetsFileReadJSON.cxx @@ -350,8 +350,8 @@ auto const PresetVectorStringHelper = ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetStringHelper); -ReadFileResult PresetInheritsHelper(std::vector& out, - const Json::Value* value) +ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector& out, + const Json::Value* value) { out.clear(); if (!value) { @@ -478,8 +478,8 @@ auto const ConfigurePresetHelper = cmJSONObjectHelper( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper) - .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper, - false) + .Bind("inherits"_s, &ConfigurePreset::Inherits, + PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false) .Bind("vendor"_s, nullptr, VendorHelper(ReadFileResult::INVALID_PRESET), false) @@ -512,7 +512,8 @@ auto const BuildPresetHelper = cmJSONObjectHelper( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &BuildPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false) + .Bind("inherits"_s, &BuildPreset::Inherits, + PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false) .Bind("vendor"_s, nullptr, VendorHelper(ReadFileResult::INVALID_PRESET), false) @@ -528,7 +529,8 @@ auto const BuildPresetHelper = &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, false) .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false) - .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false) + .Bind("targets"_s, &BuildPreset::Targets, + PresetVectorOneOrMoreStringHelper, false) .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper, false) .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper, @@ -831,7 +833,8 @@ auto const TestPresetHelper = cmJSONObjectHelper( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &TestPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false) + .Bind("inherits"_s, &TestPreset::Inherits, + PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false) .Bind("vendor"_s, nullptr, VendorHelper(ReadFileResult::INVALID_PRESET), false) diff --git a/Tests/RunCMake/CMakePresetsBuild/Good.json.in b/Tests/RunCMake/CMakePresetsBuild/Good.json.in index fd43c4e6037..3d0b838c73b 100644 --- a/Tests/RunCMake/CMakePresetsBuild/Good.json.in +++ b/Tests/RunCMake/CMakePresetsBuild/Good.json.in @@ -73,6 +73,11 @@ "vendor": { "example.com": "value" } + }, + { + "name": "singleTarget", + "inherits": "build-default", + "targets": "good" } ] } diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake index afa22eb715f..2c8d1a0f3c0 100644 --- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake @@ -62,7 +62,7 @@ endfunction() set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) -run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject") +run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject;singleTarget") run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset") run_cmake_build_presets(Condition "default" "enabled;disabled") From 590553f32246b374853c50cf7c30af3880ac02ea Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Mon, 7 Jun 2021 18:18:29 +0000 Subject: [PATCH 0615/1519] Compilers: protect use of __has_include If the compiler does not have __has_include, pretend the answer is always no --- Modules/CMakeCCompilerId.c.in | 6 ++++++ Modules/CMakeCXXCompilerId.cpp.in | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index 75e9d1ab51b..1f19c00e2ef 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -11,6 +11,12 @@ # define volatile #endif +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + @CMAKE_C_COMPILER_ID_CONTENT@ /* Construct the string literal in pieces to prevent the source from diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index a67caba2c38..7362a083740 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -5,6 +5,12 @@ # error "A C compiler has been selected for C++." #endif +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + @CMAKE_CXX_COMPILER_ID_CONTENT@ /* Construct the string literal in pieces to prevent the source from From bd844387df133897ce6e3f290af771acb0df4df9 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Fri, 28 Aug 2020 15:00:57 -0400 Subject: [PATCH 0616/1519] ROCMClang: Add the ROCm toolkit derived clang compiler to CMake --- Help/variable/CMAKE_LANG_COMPILER_ID.rst | 1 + Modules/CMakeCompilerIdDetection.cmake | 5 +++ Modules/CMakeDetermineCompilerId.cmake | 1 - Modules/Compiler/ROCMClang-ASM.cmake | 2 ++ Modules/Compiler/ROCMClang-C.cmake | 7 ++++ Modules/Compiler/ROCMClang-CXX.cmake | 7 ++++ .../ROCMClang-DetermineCompiler.cmake | 19 ++++++++++ Modules/Compiler/ROCMClang-FindBinUtils.cmake | 1 + Modules/Compiler/ROCMClang-OBJC.cmake | 7 ++++ Modules/Compiler/ROCMClang-OBJCXX.cmake | 7 ++++ Modules/Compiler/ROCMClang.cmake | 35 +++++++++++++++++++ Modules/WriteCompilerDetectionHeader.cmake | 1 + 12 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 Modules/Compiler/ROCMClang-ASM.cmake create mode 100644 Modules/Compiler/ROCMClang-C.cmake create mode 100644 Modules/Compiler/ROCMClang-CXX.cmake create mode 100644 Modules/Compiler/ROCMClang-DetermineCompiler.cmake create mode 100644 Modules/Compiler/ROCMClang-FindBinUtils.cmake create mode 100644 Modules/Compiler/ROCMClang-OBJC.cmake create mode 100644 Modules/Compiler/ROCMClang-OBJCXX.cmake create mode 100644 Modules/Compiler/ROCMClang.cmake diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index 0abedde6a56..f23b7a214a9 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -34,6 +34,7 @@ include: OpenWatcom = Open Watcom (openwatcom.org) PGI = The Portland Group (pgroup.com) PathScale = PathScale (pathscale.com) + ROCMClang = ROCm Toolkit Clang-based Compiler (rocmdocs.amd.com) SDCC = Small Device C Compiler (sdcc.sourceforge.net) SunPro = Oracle Solaris Studio (oracle.com) TI = Texas Instruments (ti.com) diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index 850fc14e044..21977900c33 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -81,6 +81,11 @@ function(compiler_id_detection outvar lang) ARMCC AppleClang ARMClang + ) + if(NOT __skip_rocmclang) + list(APPEND ordered_compilers ROCMClang) + endif() + list(APPEND ordered_compilers Clang GNU MSVC diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 448f0716e72..d656cd0e3cc 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -150,7 +150,6 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() endif() - if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" diff --git a/Modules/Compiler/ROCMClang-ASM.cmake b/Modules/Compiler/ROCMClang-ASM.cmake new file mode 100644 index 00000000000..85d1110a5e7 --- /dev/null +++ b/Modules/Compiler/ROCMClang-ASM.cmake @@ -0,0 +1,2 @@ +include(Compiler/ROCMClang) +__compiler_rocmclang(ASM) diff --git a/Modules/Compiler/ROCMClang-C.cmake b/Modules/Compiler/ROCMClang-C.cmake new file mode 100644 index 00000000000..cdfa95d9eac --- /dev/null +++ b/Modules/Compiler/ROCMClang-C.cmake @@ -0,0 +1,7 @@ +include(Compiler/ROCMClang) +__compiler_rocmclang(C) + +set(_rocm_clang_ver "${CMAKE_C_COMPILER_VERSION_INTERNAL}") +set(CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION_INTERNAL}") +include(Compiler/Clang-C) +set(CMAKE_C_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang-CXX.cmake b/Modules/Compiler/ROCMClang-CXX.cmake new file mode 100644 index 00000000000..5739c8e5942 --- /dev/null +++ b/Modules/Compiler/ROCMClang-CXX.cmake @@ -0,0 +1,7 @@ +include(Compiler/ROCMClang) +__compiler_rocmclang(CXX) + +set(_rocm_clang_ver "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") +set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") +include(Compiler/Clang-CXX) +set(CMAKE_CXX_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang-DetermineCompiler.cmake b/Modules/Compiler/ROCMClang-DetermineCompiler.cmake new file mode 100644 index 00000000000..c2fc99b6bde --- /dev/null +++ b/Modules/Compiler/ROCMClang-DetermineCompiler.cmake @@ -0,0 +1,19 @@ + +set(_compiler_id_pp_test "defined(__clang__) && __has_include()") + +set(_compiler_id_version_compute " +# if defined(__clang__) && __has_include() +# include +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(HIP_VERSION_MAJOR) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(HIP_VERSION_MINOR) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(HIP_VERSION_PATCH) +# endif") + +set(_compiler_id_simulate " +# if defined(_MSC_VER) +# define @PREFIX@SIMULATE_ID \"MSVC\" +# elif defined(__clang__) +# define @PREFIX@SIMULATE_ID \"Clang\" +# elif defined(__GNUC__) +# define @PREFIX@SIMULATE_ID \"GNU\" +# endif") diff --git a/Modules/Compiler/ROCMClang-FindBinUtils.cmake b/Modules/Compiler/ROCMClang-FindBinUtils.cmake new file mode 100644 index 00000000000..e721c8708ea --- /dev/null +++ b/Modules/Compiler/ROCMClang-FindBinUtils.cmake @@ -0,0 +1 @@ +include(Compiler/Clang-FindBinUtils) diff --git a/Modules/Compiler/ROCMClang-OBJC.cmake b/Modules/Compiler/ROCMClang-OBJC.cmake new file mode 100644 index 00000000000..794973d33ea --- /dev/null +++ b/Modules/Compiler/ROCMClang-OBJC.cmake @@ -0,0 +1,7 @@ +include(Compiler/ROCMClang) +__compiler_rocmclang(OBJC) + +set(_rocm_clang_ver "${CMAKE_OBJC_COMPILER_VERSION_INTERNAL}") +set(CMAKE_OBJC_COMPILER_VERSION "${CMAKE_OBJC_COMPILER_VERSION_INTERNAL}") +include(Compiler/Clang-OBJC) +set(CMAKE_OBJC_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang-OBJCXX.cmake b/Modules/Compiler/ROCMClang-OBJCXX.cmake new file mode 100644 index 00000000000..82238e16793 --- /dev/null +++ b/Modules/Compiler/ROCMClang-OBJCXX.cmake @@ -0,0 +1,7 @@ +include(Compiler/ROCMClang) +__compiler_rocmclang(OBJCXX) + +set(_rocm_clang_ver "${CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL}") +set(CMAKE_OBJCXX_COMPILER_VERSION "${CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL}") +include(Compiler/Clang-OBJCXX) +set(CMAKE_OBJCXX_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang.cmake b/Modules/Compiler/ROCMClang.cmake new file mode 100644 index 00000000000..6b38c2d400d --- /dev/null +++ b/Modules/Compiler/ROCMClang.cmake @@ -0,0 +1,35 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +include_guard() + +include(Compiler/CMakeCommonCompilerMacros) + +macro(__compiler_rocmclang lang) + + set(CMAKE_${lang}_VERBOSE_FLAG "-v") + + if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC") + # Feature flags. + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY -fvisibility=) + + string(APPEND CMAKE_HIP_FLAGS_INIT " ") + string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -g") + string(APPEND CMAKE_HIP_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") + string(APPEND CMAKE_HIP_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG") + string(APPEND CMAKE_HIP_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") + endif() + + set(CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS -shared) + set(CMAKE_INCLUDE_SYSTEM_FLAG_HIP "-isystem ") + + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1) + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1) + set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@") + set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@") +endmacro() diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index 0e4e0280510..54eb40ed2de 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -384,6 +384,7 @@ elseif(_WCDH_policy STREQUAL "") ) endif() +set(__skip_rocmclang TRUE) include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake) function(_load_compiler_variables CompilerId lang) From ff0d2858e1e47af8e849318b411b1fbd8579a053 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 21 Oct 2020 14:24:37 -0400 Subject: [PATCH 0617/1519] HIP: Extract clang compiler details from hipcc --- Modules/CMakeDetermineCompilerId.cmake | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index d656cd0e3cc..bd1e732530f 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -150,6 +150,41 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() endif() + # When invoked with HIPCC we need to extract the path to the underlying + # clang compiler when possible. This fixes the following issues: + # env variables can change how hipcc behaves + # allows us to properly find the binutils bundled with hip + if(CMAKE_${lang}_COMPILER_ID STREQUAL "ROCMClang" + AND CMAKE_${lang}_COMPILER MATCHES ".*hipcc") + get_filename_component(_hipcc_dir "${CMAKE_${lang}_COMPILER}" DIRECTORY) + execute_process( + COMMAND "${_hipcc_dir}/hipconfig" + --hipclangpath + OUTPUT_VARIABLE output + RESULT_VARIABLE result + ) + if(result EQUAL 0 AND EXISTS "${output}") + if(lang STREQUAL "C") + set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${output}/clang") + set(CMAKE_${lang}_COMPILER "${output}/clang" PARENT_SCOPE) + else() + set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${output}/clang++") + set(CMAKE_${lang}_COMPILER "${output}/clang++" PARENT_SCOPE) + endif() + endif() + if(lang STREQUAL "HIP") + execute_process( + COMMAND "${_hipcc_dir}/hipconfig" + --rocmpath + OUTPUT_VARIABLE output + RESULT_VARIABLE result + ) + if(result EQUAL 0) + set(_CMAKE_HIP_COMPILER_ROCM_ROOT "${output}" PARENT_SCOPE) + endif() + endif() + endif() + if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" From b50bfc89131e55685aa41146254b37d26049b4d5 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Fri, 28 Aug 2020 15:03:39 -0400 Subject: [PATCH 0618/1519] HIP: Add language to CMake --- Help/command/enable_language.rst | 5 +- Help/command/project.rst | 2 +- Help/envvar/HIPCXX.rst | 13 ++ Help/envvar/HIPFLAGS.rst | 15 ++ Help/manual/cmake-env-variables.7.rst | 2 + Help/manual/cmake-generator-expressions.7.rst | 22 +++ Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_sf/LANGUAGE.rst | 4 +- Help/prop_tgt/HIP_ARCHITECTURES.rst | 26 ++++ Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst | 2 +- Help/release/dev/hip.rst | 5 + Help/variable/CMAKE_HIP_ARCHITECTURES.rst | 11 ++ .../variable/CMAKE_LANG_COMPILER_LAUNCHER.rst | 2 +- Modules/CMakeDetermineCompileFeatures.cmake | 56 ++++++++ Modules/CMakeDetermineHIPCompiler.cmake | 96 +++++++++++++ Modules/CMakeHIPCompiler.cmake.in | 59 ++++++++ Modules/CMakeHIPCompilerABI.hip | 16 +++ Modules/CMakeHIPCompilerId.hip.in | 54 +++++++ Modules/CMakeHIPInformation.cmake | 132 ++++++++++++++++++ Modules/CMakeTestHIPCompiler.cmake | 98 +++++++++++++ .../Compiler/CMakeCommonCompilerMacros.cmake | 16 +++ Modules/Compiler/Clang-HIP.cmake | 16 +++ Modules/Compiler/ROCMClang-HIP.cmake | 45 ++++++ Modules/Internal/FeatureTesting.cmake | 14 ++ Source/cmComputeLinkInformation.cxx | 4 +- Source/cmCoreTryCompile.cxx | 21 ++- Source/cmExtraCodeBlocksGenerator.cxx | 5 +- Source/cmGeneratorExpressionNode.cxx | 7 +- Source/cmGeneratorTarget.cxx | 24 +++- Source/cmGeneratorTarget.h | 2 + Source/cmLocalGenerator.cxx | 12 +- Source/cmLocalUnixMakefileGenerator3.cxx | 8 +- Source/cmMakefileTargetGenerator.cxx | 3 +- Source/cmNinjaTargetGenerator.cxx | 3 +- Source/cmStandardLevelResolver.cxx | 18 ++- Source/cmTarget.cxx | 12 +- Source/cmake.cxx | 3 + Source/cmake.h | 11 +- Tests/CMakeLists.txt | 4 + Tests/HIP/ArchitectureOff/CMakeLists.txt | 8 ++ Tests/HIP/ArchitectureOff/main.hip | 9 ++ Tests/HIP/CMakeLists.txt | 12 ++ Tests/HIP/CompileFlags/CMakeLists.txt | 8 ++ Tests/HIP/CompileFlags/main.hip | 13 ++ Tests/HIP/EnableStandard/CMakeLists.txt | 20 +++ Tests/HIP/EnableStandard/main.hip | 23 +++ Tests/HIP/EnableStandard/shared.hip | 15 ++ Tests/HIP/EnableStandard/static.cxx | 9 ++ Tests/HIP/MathFunctions/CMakeLists.txt | 18 +++ Tests/HIP/MathFunctions/main.hip | 40 ++++++ Tests/HIP/TryCompile/CMakeLists.txt | 14 ++ Tests/HIP/TryCompile/device_function.hip | 17 +++ Tests/HIP/TryCompile/main.hip | 8 ++ Tests/HIP/WithDefs/CMakeLists.txt | 36 +++++ Tests/HIP/WithDefs/inc_hip/inc_hip.h | 1 + Tests/HIP/WithDefs/main.hip.cpp | 89 ++++++++++++ Tests/RunCMake/CMakeLists.txt | 5 +- .../CompilerLauncher/HIP-common.cmake | 5 + .../CompilerLauncher/HIP-env-Build-stdout.txt | 1 + .../HIP-env-launch-Build-stdout.txt | 1 + Tests/RunCMake/CompilerLauncher/HIP-env.cmake | 1 + .../HIP-launch-Build-stdout.txt | 1 + .../CompilerLauncher/HIP-launch-env.cmake | 3 + .../CompilerLauncher/HIP-launch.cmake | 3 + Tests/RunCMake/CompilerLauncher/HIP.cmake | 2 + .../CompilerLauncher/RunCMakeTest.cmake | 3 + Tests/RunCMake/CompilerLauncher/main.hip | 4 + 68 files changed, 1183 insertions(+), 36 deletions(-) create mode 100644 Help/envvar/HIPCXX.rst create mode 100644 Help/envvar/HIPFLAGS.rst create mode 100644 Help/prop_tgt/HIP_ARCHITECTURES.rst create mode 100644 Help/release/dev/hip.rst create mode 100644 Help/variable/CMAKE_HIP_ARCHITECTURES.rst create mode 100644 Modules/CMakeDetermineHIPCompiler.cmake create mode 100644 Modules/CMakeHIPCompiler.cmake.in create mode 100644 Modules/CMakeHIPCompilerABI.hip create mode 100644 Modules/CMakeHIPCompilerId.hip.in create mode 100644 Modules/CMakeHIPInformation.cmake create mode 100644 Modules/CMakeTestHIPCompiler.cmake create mode 100644 Modules/Compiler/Clang-HIP.cmake create mode 100644 Modules/Compiler/ROCMClang-HIP.cmake create mode 100644 Tests/HIP/ArchitectureOff/CMakeLists.txt create mode 100644 Tests/HIP/ArchitectureOff/main.hip create mode 100644 Tests/HIP/CMakeLists.txt create mode 100644 Tests/HIP/CompileFlags/CMakeLists.txt create mode 100644 Tests/HIP/CompileFlags/main.hip create mode 100644 Tests/HIP/EnableStandard/CMakeLists.txt create mode 100644 Tests/HIP/EnableStandard/main.hip create mode 100644 Tests/HIP/EnableStandard/shared.hip create mode 100644 Tests/HIP/EnableStandard/static.cxx create mode 100644 Tests/HIP/MathFunctions/CMakeLists.txt create mode 100644 Tests/HIP/MathFunctions/main.hip create mode 100644 Tests/HIP/TryCompile/CMakeLists.txt create mode 100644 Tests/HIP/TryCompile/device_function.hip create mode 100644 Tests/HIP/TryCompile/main.hip create mode 100644 Tests/HIP/WithDefs/CMakeLists.txt create mode 100644 Tests/HIP/WithDefs/inc_hip/inc_hip.h create mode 100644 Tests/HIP/WithDefs/main.hip.cpp create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-common.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-env.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/HIP-launch.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/HIP.cmake create mode 100644 Tests/RunCMake/CompilerLauncher/main.hip diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst index ce765de684c..d2acbc85c69 100644 --- a/Help/command/enable_language.rst +++ b/Help/command/enable_language.rst @@ -10,7 +10,7 @@ Enables support for the named language in CMake. This is the same as the :command:`project` command but does not create any of the extra variables that are created by the project command. Example languages are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``, -``ISPC``, and ``ASM``. +``HIP``, ``ISPC``, and ``ASM``. .. versionadded:: 3.8 Added ``CUDA`` support. @@ -21,6 +21,9 @@ are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``, .. versionadded:: 3.18 Added ``ISPC`` support. +.. versionadded:: 3.21 + Added ``HIP`` support. + If enabling ``ASM``, enable it last so that CMake can check whether compilers for other languages like ``C`` work for assembly too. diff --git a/Help/command/project.rst b/Help/command/project.rst index 8a6bc1e548d..2a9dcfe3007 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -103,7 +103,7 @@ The options are: Selects which programming languages are needed to build the project. Supported languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``, - ``OBJC`` (i.e. Objective-C), ``OBJCXX``, ``Fortran``, ``ISPC``, and ``ASM``. + ``OBJC`` (i.e. Objective-C), ``OBJCXX``, ``Fortran``, ``HIP``, ``ISPC``, and ``ASM``. By default ``C`` and ``CXX`` are enabled if no language options are given. Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages, to skip enabling any languages. diff --git a/Help/envvar/HIPCXX.rst b/Help/envvar/HIPCXX.rst new file mode 100644 index 00000000000..23329e978cb --- /dev/null +++ b/Help/envvar/HIPCXX.rst @@ -0,0 +1,13 @@ +HIPCXX +------ + +.. versionadded:: 3.21 + +.. include:: ENV_VAR.txt + +Preferred executable for compiling ``HIP`` language files. Will only be used by +CMake on the first configuration to determine ``HIP`` compiler, after which the +value for ``HIP`` is stored in the cache as +:variable:`CMAKE_HIP_COMPILER _COMPILER>`. For any configuration +run (including the first), the environment variable will be ignored if the +:variable:`CMAKE_HIP_COMPILER _COMPILER>` variable is defined. diff --git a/Help/envvar/HIPFLAGS.rst b/Help/envvar/HIPFLAGS.rst new file mode 100644 index 00000000000..0df3416e281 --- /dev/null +++ b/Help/envvar/HIPFLAGS.rst @@ -0,0 +1,15 @@ +HIPFLAGS +-------- + +.. versionadded:: 3.21 + +.. include:: ENV_VAR.txt + +Default compilation flags to be used when compiling ``HIP`` files. Will only be +used by CMake on the first configuration to determine ``HIP`` default +compilation flags, after which the value for ``HIPFLAGS`` is stored in the +cache as :variable:`CMAKE_HIP_FLAGS _FLAGS>`. For any configuration +run (including the first), the environment variable will be ignored if +the :variable:`CMAKE_HIP_FLAGS _FLAGS>` variable is defined. + +See also :variable:`CMAKE_HIP_FLAGS_INIT _FLAGS_INIT>`. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index bfdc8419899..fa38588a855 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -67,6 +67,8 @@ Environment Variables for Languages /envvar/CXXFLAGS /envvar/FC /envvar/FFLAGS + /envvar/HIPCXX + /envvar/HIPFLAGS /envvar/ISPC /envvar/ISPCFLAGS /envvar/OBJC diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 775067a8558..ee73f184f1b 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -181,6 +181,13 @@ Variable Queries of the entries in ``compiler_ids``, otherwise ``0``. See also the :variable:`CMAKE__COMPILER_ID` variable. +.. genex:: $ + + where ``compiler_ids`` is a comma-separated list. + ``1`` if the CMake's compiler id of the HIP compiler matches any one + of the entries in ``compiler_ids``, otherwise ``0``. + See also the :variable:`CMAKE__COMPILER_ID` variable. + .. genex:: $ where ``compiler_ids`` is a comma-separated list. @@ -218,6 +225,11 @@ Variable Queries ``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE__COMPILER_VERSION` variable. +.. genex:: $ + + ``1`` if the version of the HIP compiler matches ``version``, otherwise ``0``. + See also the :variable:`CMAKE__COMPILER_VERSION` variable. + .. genex:: $ ``1`` if the version of the ISPC compiler matches ``version``, otherwise ``0``. @@ -648,6 +660,11 @@ Variable Queries The CMake's compiler id of the Fortran compiler used. See also the :variable:`CMAKE__COMPILER_ID` variable. +.. genex:: $ + + The CMake's compiler id of the HIP compiler used. + See also the :variable:`CMAKE__COMPILER_ID` variable. + .. genex:: $ The CMake's compiler id of the ISPC compiler used. @@ -683,6 +700,11 @@ Variable Queries The version of the Fortran compiler used. See also the :variable:`CMAKE__COMPILER_VERSION` variable. +.. genex:: $ + + The version of the HIP compiler used. + See also the :variable:`CMAKE__COMPILER_VERSION` variable. + .. genex:: $ The version of the ISPC compiler used. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 0a3e36b3ceb..2db1ec29ed7 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -212,6 +212,7 @@ Properties on Targets /prop_tgt/GHS_NO_SOURCE_GROUP_FILE /prop_tgt/GNUtoMS /prop_tgt/HAS_CXX + /prop_tgt/HIP_ARCHITECTURES /prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM /prop_tgt/IMPORTED /prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 873bd89eac1..39fbbed39fc 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -523,6 +523,7 @@ Variables for Languages /variable/CMAKE_Fortran_MODDIR_DEFAULT /variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG + /variable/CMAKE_HIP_ARCHITECTURES /variable/CMAKE_ISPC_HEADER_DIRECTORY /variable/CMAKE_ISPC_HEADER_SUFFIX /variable/CMAKE_ISPC_INSTRUCTION_SETS diff --git a/Help/prop_sf/LANGUAGE.rst b/Help/prop_sf/LANGUAGE.rst index f14c176ca5c..a9b56387044 100644 --- a/Help/prop_sf/LANGUAGE.rst +++ b/Help/prop_sf/LANGUAGE.rst @@ -6,8 +6,8 @@ Specify the programming language in which a source file is written. A property that can be set to indicate what programming language the source file is. If it is not set the language is determined based on the file extension. Typical values are ``CXX`` (i.e. C++), ``C``, -``CSharp``, ``CUDA``, ``Fortran``, ``ISPC``, and ``ASM``. Setting this -property for a file means this file will be compiled. Do not set this +``CSharp``, ``CUDA``, ``Fortran``, ``HIP``, ``ISPC``, and ``ASM``. Setting +this property for a file means this file will be compiled. Do not set this for headers or files that should not be compiled. .. versionchanged:: 3.20 diff --git a/Help/prop_tgt/HIP_ARCHITECTURES.rst b/Help/prop_tgt/HIP_ARCHITECTURES.rst new file mode 100644 index 00000000000..052f472d363 --- /dev/null +++ b/Help/prop_tgt/HIP_ARCHITECTURES.rst @@ -0,0 +1,26 @@ +HIP_ARCHITECTURES +----------------- + +.. versionadded:: 3.21 + +List of AMD GPU architectures to generate device code for. + +An empty or false value (e.g. ``OFF``) defers architecture generation to compiler +defaults. + +This property is initialized by the value of the :variable:`CMAKE_HIP_ARCHITECTURES` +variable if it is set when a target is created. + +The HIP compilation model has two modes: whole and separable. Whole compilation +generates device code at compile time. Separable compilation generates device +code at link time. Therefore the ``HIP_ARCHITECTURES`` target property should +be set on targets that compile or link with any HIP sources. + +Examples +^^^^^^^^ + +.. code-block:: cmake + + set_property(TARGET tgt PROPERTY HIP_ARCHITECTURES gfx801 gfx900) + +Generates code for both ``gfx801`` and ``gfx900``. diff --git a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst index 16be3cd1bb6..cba8ac98ce0 100644 --- a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst +++ b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst @@ -4,7 +4,7 @@ .. versionadded:: 3.4 This property is implemented only when ```` is ``C``, ``CXX``, -``Fortran``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``. +``Fortran``, ``HIP``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``. Specify a :ref:`semicolon-separated list ` containing a command line for a compiler launching tool. The :ref:`Makefile Generators` and the diff --git a/Help/release/dev/hip.rst b/Help/release/dev/hip.rst new file mode 100644 index 00000000000..abf9a359e4d --- /dev/null +++ b/Help/release/dev/hip.rst @@ -0,0 +1,5 @@ +hip +--- + +* CMake learned to support ``HIP`` as a first-class language that can be + enabled via the :command:`project` and :command:`enable_language` commands. diff --git a/Help/variable/CMAKE_HIP_ARCHITECTURES.rst b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst new file mode 100644 index 00000000000..333f0213cbf --- /dev/null +++ b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst @@ -0,0 +1,11 @@ +CMAKE_HIP_ARCHITECTURES +----------------------- + +.. versionadded:: 3.21 + +Default value for :prop_tgt:`HIP_ARCHITECTURES` property of targets. + +This is initialized to ``OFF``. + +This variable is used to initialize the :prop_tgt:`HIP_ARCHITECTURES` property +on all targets. See the target property for additional information. diff --git a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst index 89fd7bcda5f..f16e594469e 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst @@ -6,7 +6,7 @@ CMAKE__COMPILER_LAUNCHER Default value for :prop_tgt:`_COMPILER_LAUNCHER` target property. This variable is used to initialize the property on each target as it is created. This is done only when ```` is ``C``, ``CXX``, ``Fortran``, -``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``. +``HIP``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``. This variable is initialized to the :envvar:`CMAKE__COMPILER_LAUNCHER` environment variable if it is set. diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake index ee7fedba4a4..a08e597f878 100644 --- a/Modules/CMakeDetermineCompileFeatures.cmake +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -166,6 +166,62 @@ function(cmake_determine_compile_features lang) message(CHECK_PASS "done") + elseif(lang STREQUAL HIP AND COMMAND cmake_record_hip_compile_features) + message(CHECK_START "Detecting ${lang} compile features") + + set(CMAKE_HIP98_COMPILE_FEATURES) + set(CMAKE_HIP11_COMPILE_FEATURES) + set(CMAKE_HIP14_COMPILE_FEATURES) + set(CMAKE_HIP17_COMPILE_FEATURES) + set(CMAKE_HIP20_COMPILE_FEATURES) + set(CMAKE_HIP23_COMPILE_FEATURES) + + include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") + + cmake_record_hip_compile_features() + + if(NOT _result EQUAL 0) + message(CHECK_FAIL "failed") + return() + endif() + + if (CMAKE_HIP20_COMPILE_FEATURES AND CMAKE_HIP23_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES}) + endif() + if (CMAKE_HIP17_COMPILE_FEATURES AND CMAKE_HIP20_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_HIP20_COMPILE_FEATURES ${CMAKE_HIP17_COMPILE_FEATURES}) + endif() + if (CMAKE_HIP14_COMPILE_FEATURES AND CMAKE_HIP17_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_HIP17_COMPILE_FEATURES ${CMAKE_HIP14_COMPILE_FEATURES}) + endif() + if (CMAKE_HIP11_COMPILE_FEATURES AND CMAKE_HIP14_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_HIP14_COMPILE_FEATURES ${CMAKE_HIP11_COMPILE_FEATURES}) + endif() + if (CMAKE_HIP98_COMPILE_FEATURES AND CMAKE_HIP11_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_HIP11_COMPILE_FEATURES ${CMAKE_HIP98_COMPILE_FEATURES}) + endif() + + if(NOT CMAKE_HIP_COMPILE_FEATURES) + set(CMAKE_HIP_COMPILE_FEATURES + ${CMAKE_HIP98_COMPILE_FEATURES} + ${CMAKE_HIP11_COMPILE_FEATURES} + ${CMAKE_HIP14_COMPILE_FEATURES} + ${CMAKE_HIP17_COMPILE_FEATURES} + ${CMAKE_HIP20_COMPILE_FEATURES} + ${CMAKE_HIP23_COMPILE_FEATURES} + ) + endif() + + set(CMAKE_HIP_COMPILE_FEATURES ${CMAKE_HIP_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP98_COMPILE_FEATURES ${CMAKE_HIP98_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP11_COMPILE_FEATURES ${CMAKE_HIP11_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP14_COMPILE_FEATURES ${CMAKE_HIP14_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP17_COMPILE_FEATURES ${CMAKE_HIP17_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP20_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP23_COMPILE_FEATURES} PARENT_SCOPE) + + message(CHECK_PASS "done") + endif() endfunction() diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake new file mode 100644 index 00000000000..87885c0c3cd --- /dev/null +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -0,0 +1,96 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) +include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake) + +if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR + ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) ) + message(FATAL_ERROR "HIP language not currently supported by \"${CMAKE_GENERATOR}\" generator") +endif() + + +if(NOT CMAKE_HIP_COMPILER) + set(CMAKE_HIP_COMPILER_INIT NOTFOUND) + + # prefer the environment variable HIPCXX + if(NOT $ENV{HIPCXX} STREQUAL "") + get_filename_component(CMAKE_HIP_COMPILER_INIT $ENV{HIPCXX} PROGRAM PROGRAM_ARGS CMAKE_HIP_FLAGS_ENV_INIT) + if(CMAKE_HIP_FLAGS_ENV_INIT) + set(CMAKE_HIP_COMPILER_ARG1 "${CMAKE_HIP_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CXX compiler") + endif() + if(NOT EXISTS ${CMAKE_HIP_COMPILER_INIT}) + message(FATAL_ERROR "Could not find compiler set in environment variable HIPCXX:\n$ENV{HIPCXX}.\n${CMAKE_HIP_COMPILER_INIT}") + endif() + endif() + + # finally list compilers to try + if(NOT CMAKE_HIP_COMPILER_INIT) + set(CMAKE_HIP_COMPILER_LIST hipcc clang++) + endif() + + _cmake_find_compiler(HIP) +else() + _cmake_find_compiler_path(HIP) +endif() + +mark_as_advanced(CMAKE_HIP_COMPILER) + +# Build a small source file to identify the compiler. +if(NOT CMAKE_HIP_COMPILER_ID_RUN) + set(CMAKE_HIP_COMPILER_ID_RUN 1) + + # Try to identify the compiler. + set(CMAKE_HIP_COMPILER_ID) + set(CMAKE_HIP_PLATFORM_ID) + file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in + CMAKE_HIP_COMPILER_ID_PLATFORM_CONTENT) + + list(APPEND CMAKE_HIP_COMPILER_ID_TEST_FLAGS_FIRST "-v") + + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + CMAKE_DETERMINE_COMPILER_ID(HIP HIPFLAGS CMakeHIPCompilerId.hip) + + _cmake_find_compiler_sysroot(HIP) + +endif() + +if (NOT _CMAKE_TOOLCHAIN_LOCATION) + get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_HIP_COMPILER}" PATH) +endif () + +set(_CMAKE_PROCESSING_LANGUAGE "HIP") +include(CMakeFindBinUtils) +include(Compiler/${CMAKE_HIP_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) + +if(CMAKE_HIP_COMPILER_SYSROOT) + string(CONCAT _SET_CMAKE_HIP_COMPILER_SYSROOT + "set(CMAKE_HIP_COMPILER_SYSROOT \"${CMAKE_HIP_COMPILER_SYSROOT}\")\n" + "set(CMAKE_COMPILER_SYSROOT \"${CMAKE_HIP_COMPILER_SYSROOT}\")") +else() + set(_SET_CMAKE_HIP_COMPILER_SYSROOT "") +endif() + +if(CMAKE_HIP_COMPILER_ARCHITECTURE_ID) + set(_SET_CMAKE_HIP_COMPILER_ARCHITECTURE_ID + "set(CMAKE_HIP_COMPILER_ARCHITECTURE_ID ${CMAKE_HIP_COMPILER_ARCHITECTURE_ID})") +else() + set(_SET_CMAKE_HIP_COMPILER_ARCHITECTURE_ID "") +endif() + +if(MSVC_HIP_ARCHITECTURE_ID) + set(SET_MSVC_HIP_ARCHITECTURE_ID + "set(MSVC_HIP_ARCHITECTURE_ID ${MSVC_HIP_ARCHITECTURE_ID})") +endif() + +if(NOT DEFINED CMAKE_HIP_ARCHITECTURES) + set(CMAKE_HIP_ARCHITECTURES "OFF" CACHE STRING "HIP architectures") +endif() + +# configure variables set in this file for fast reload later on +configure_file(${CMAKE_ROOT}/Modules/CMakeHIPCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPCompiler.cmake + @ONLY + ) +set(CMAKE_HIP_COMPILER_ENV_VAR "HIPCXX") diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in new file mode 100644 index 00000000000..eeb51b281a4 --- /dev/null +++ b/Modules/CMakeHIPCompiler.cmake.in @@ -0,0 +1,59 @@ +set(CMAKE_HIP_COMPILER "@CMAKE_HIP_COMPILER@") +set(CMAKE_HIP_COMPILER_ID "@CMAKE_HIP_COMPILER_ID@") +set(CMAKE_HIP_COMPILER_VERSION "@CMAKE_HIP_COMPILER_VERSION@") +set(CMAKE_HIP_STANDARD_COMPUTED_DEFAULT "@CMAKE_HIP_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_HIP_COMPILE_FEATURES "@CMAKE_HIP_COMPILE_FEATURES@") +set(CMAKE_HIP98_COMPILE_FEATURES "@CMAKE_HIP03_COMPILE_FEATURES@") +set(CMAKE_HIP11_COMPILE_FEATURES "@CMAKE_HIP11_COMPILE_FEATURES@") +set(CMAKE_HIP14_COMPILE_FEATURES "@CMAKE_HIP14_COMPILE_FEATURES@") +set(CMAKE_HIP17_COMPILE_FEATURES "@CMAKE_HIP17_COMPILE_FEATURES@") +set(CMAKE_HIP20_COMPILE_FEATURES "@CMAKE_HIP20_COMPILE_FEATURES@") +set(CMAKE_HIP23_COMPILE_FEATURES "@CMAKE_HIP23_COMPILE_FEATURES@") + +set(CMAKE_HIP_PLATFORM_ID "@CMAKE_HIP_PLATFORM_ID@") +set(CMAKE_HIP_SIMULATE_ID "@CMAKE_HIP_SIMULATE_ID@") +set(CMAKE_HIP_COMPILER_FRONTEND_VARIANT "@CMAKE_HIP_COMPILER_FRONTEND_VARIANT@") +set(CMAKE_HIP_SIMULATE_VERSION "@CMAKE_HIP_SIMULATE_VERSION@") +@SET_MSVC_HIP_ARCHITECTURE_ID@ +@_SET_CMAKE_HIP_COMPILER_SYSROOT@ + +set(CMAKE_HIP_COMPILER_ENV_VAR "HIPCXX") + +set(CMAKE_HIP_COMPILER_LOADED 1) +set(CMAKE_HIP_COMPILER_ID_RUN 1) +set(CMAKE_HIP_SOURCE_FILE_EXTENSIONS hip) +set(CMAKE_HIP_LINKER_PREFERENCE 15) +set(CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES 1) + +set(CMAKE_HIP_SIZEOF_DATA_PTR "@CMAKE_HIP_SIZEOF_DATA_PTR@") +set(CMAKE_HIP_COMPILER_ABI "@CMAKE_HIP_COMPILER_ABI@") +set(CMAKE_HIP_LIBRARY_ARCHITECTURE "@CMAKE_HIP_LIBRARY_ARCHITECTURE@") + +if(CMAKE_HIP_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_HIP_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_HIP_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_HIP_COMPILER_ABI}") +endif() + +if(CMAKE_HIP_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_HIP_LIBRARY_ARCHITECTURE@") +endif() + +set(CMAKE_HIP_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_HIP_TOOLKIT_INCLUDE_DIRECTORIES@") + +set(CMAKE_HIP_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_HIP_IMPLICIT_INCLUDE_DIRECTORIES@") +set(CMAKE_HIP_IMPLICIT_LINK_LIBRARIES "@CMAKE_HIP_IMPLICIT_LINK_LIBRARIES@") +set(CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES "@CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES@") +set(CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") + +set(CMAKE_HIP_COMPILER_DEVICE_LIBRARY_ROOT_DIR "@CMAKE_HIP_COMPILER_DEVICE_LIBRARY_ROOT_DIR@") +@_SET_CMAKE_HIP_DEVICE_LIBRARY_INCLUSION@ + +set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_HIP_COMPILER_AR "@CMAKE_HIP_COMPILER_AR@") +set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_HIP_COMPILER_RANLIB "@CMAKE_HIP_COMPILER_RANLIB@") +set(CMAKE_LINKER "@CMAKE_LINKER@") +set(CMAKE_MT "@CMAKE_MT@") diff --git a/Modules/CMakeHIPCompilerABI.hip b/Modules/CMakeHIPCompilerABI.hip new file mode 100644 index 00000000000..6c912bd1355 --- /dev/null +++ b/Modules/CMakeHIPCompilerABI.hip @@ -0,0 +1,16 @@ +#ifndef __HIP__ +# error "A C or C++ compiler has been selected for HIP" +#endif + +#include "CMakeCompilerABI.h" + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_sizeof_dptr[argc]; +#if defined(ABI_ID) + require += info_abi[argc]; +#endif + (void)argv; + return require; +} diff --git a/Modules/CMakeHIPCompilerId.hip.in b/Modules/CMakeHIPCompilerId.hip.in new file mode 100644 index 00000000000..5258efba042 --- /dev/null +++ b/Modules/CMakeHIPCompilerId.hip.in @@ -0,0 +1,54 @@ +#ifndef __HIP__ +# error "A C or C++ compiler has been selected for HIP" +#endif + +@CMAKE_HIP_COMPILER_ID_CONTENT@ + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +@CMAKE_HIP_COMPILER_ID_PLATFORM_CONTENT@ +@CMAKE_HIP_COMPILER_ID_ERROR_FOR_TEST@ + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if __cplusplus > 202002L + "23" +#elif __cplusplus > 201703L + "20" +#elif __cplusplus >= 201703L + "17" +#elif __cplusplus >= 201402L + "14" +#elif __cplusplus >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake new file mode 100644 index 00000000000..df1d98ae413 --- /dev/null +++ b/Modules/CMakeHIPInformation.cmake @@ -0,0 +1,132 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +if(UNIX) + set(CMAKE_HIP_OUTPUT_EXTENSION .o) +else() + set(CMAKE_HIP_OUTPUT_EXTENSION .obj) +endif() +set(CMAKE_INCLUDE_FLAG_HIP "-I") + +# Load compiler-specific information. +if(CMAKE_HIP_COMPILER_ID) + include(Compiler/${CMAKE_HIP_COMPILER_ID}-HIP OPTIONAL) +endif() + +# load the system- and compiler specific files +if(CMAKE_HIP_COMPILER_ID) + # load a hardware specific file, mostly useful for embedded compilers + if(CMAKE_SYSTEM_PROCESSOR) + include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_HIP_COMPILER_ID}-HIP-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL) + endif() + include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_HIP_COMPILER_ID}-HIP OPTIONAL) +endif() + + +if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG) + set(CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP) + set(CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP}) +endif() + +if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_HIP_FLAG) + set(CMAKE_SHARED_LIBRARY_RPATH_LINK_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG}) +endif() + +if(NOT DEFINED CMAKE_EXE_EXPORTS_HIP_FLAG) + set(CMAKE_EXE_EXPORTS_HIP_FLAG ${CMAKE_EXE_EXPORTS_C_FLAG}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_HIP_FLAG) + set(CMAKE_SHARED_LIBRARY_SONAME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_C_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG) + set(CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG_SEP) + set(CMAKE_EXECUTABLE_RUNTIME_HIP_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_HIP_FLAG_SEP}) +endif() + +if(NOT CMAKE_EXECUTABLE_RPATH_LINK_HIP_FLAG) + set(CMAKE_EXECUTABLE_RPATH_LINK_HIP_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_HIP_FLAG}) +endif() + +if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_HIP_WITH_RUNTIME_PATH) + set(CMAKE_SHARED_LIBRARY_LINK_HIP_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_C_WITH_RUNTIME_PATH}) +endif() + + +# for most systems a module is the same as a shared library +# so unless the variable CMAKE_MODULE_EXISTS is set just +# copy the values from the LIBRARY variables +if(NOT CMAKE_MODULE_EXISTS) + set(CMAKE_SHARED_MODULE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_HIP_FLAGS}) + set(CMAKE_SHARED_MODULE_CREATE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS}) +endif() + +# add the flags to the cache based +# on the initial values computed in the platform/*.cmake files +# use _INIT variables so that this only happens the first time +# and you can set these flags in the cmake cache +set(CMAKE_HIP_FLAGS_INIT "$ENV{HIPFLAGS} ${CMAKE_HIP_FLAGS_INIT}") + +cmake_initialize_per_config_variable(CMAKE_HIP_FLAGS "Flags used by the HIP compiler") + +if(CMAKE_HIP_STANDARD_LIBRARIES_INIT) + set(CMAKE_HIP_STANDARD_LIBRARIES "${CMAKE_HIP_STANDARD_LIBRARIES_INIT}" + CACHE STRING "Libraries linked by default with all HIP applications.") + mark_as_advanced(CMAKE_HIP_STANDARD_LIBRARIES) +endif() + +if(NOT CMAKE_HIP_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_HIP_COMPILER_LAUNCHER}) + set(CMAKE_HIP_COMPILER_LAUNCHER "$ENV{CMAKE_HIP_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for HIP.") +endif() + +include(CMakeCommonLanguageInclude) + +# now define the following rules: +# CMAKE_HIP_CREATE_SHARED_LIBRARY +# CMAKE_HIP_CREATE_SHARED_MODULE +# CMAKE_HIP_COMPILE_OBJECT +# CMAKE_HIP_LINK_EXECUTABLE + +# create a shared library +if(NOT CMAKE_HIP_CREATE_SHARED_LIBRARY) + set(CMAKE_HIP_CREATE_SHARED_LIBRARY + " -o ") +endif() + +# create a shared module copy the shared library rule by default +if(NOT CMAKE_HIP_CREATE_SHARED_MODULE) + set(CMAKE_HIP_CREATE_SHARED_MODULE ${CMAKE_HIP_CREATE_SHARED_LIBRARY}) +endif() + +# Create a static archive incrementally for large object file counts. +if(NOT DEFINED CMAKE_HIP_ARCHIVE_CREATE) + set(CMAKE_HIP_ARCHIVE_CREATE " qc ") +endif() +if(NOT DEFINED CMAKE_HIP_ARCHIVE_APPEND) + set(CMAKE_HIP_ARCHIVE_APPEND " q ") +endif() +if(NOT DEFINED CMAKE_HIP_ARCHIVE_FINISH) + set(CMAKE_HIP_ARCHIVE_FINISH " ") +endif() + +# compile a HIP file into an object file +if(NOT CMAKE_HIP_COMPILE_OBJECT) + set(CMAKE_HIP_COMPILE_OBJECT + " -o ${_CMAKE_COMPILE_AS_HIP_FLAG} -c ") +endif() + +# compile a cu file into an executable +if(NOT CMAKE_HIP_LINK_EXECUTABLE) + set(CMAKE_HIP_LINK_EXECUTABLE + " -o ") +endif() + +set(CMAKE_HIP_INFORMATION_LOADED 1) diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake new file mode 100644 index 00000000000..da70f8d2714 --- /dev/null +++ b/Modules/CMakeTestHIPCompiler.cmake @@ -0,0 +1,98 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +if(CMAKE_HIP_COMPILER_FORCED) + # The compiler configuration was forced by the user. + # Assume the user has configured all compiler information. + set(CMAKE_HIP_COMPILER_WORKS TRUE) + return() +endif() + +set(__CMAKE_HIP_FLAGS "${CMAKE_HIP_FLAGS}") +string(APPEND CMAKE_HIP_FLAGS "--cuda-host-only") + +include(CMakeTestCompilerCommon) + +# work around enforced code signing and / or missing executable target type +set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE}) +if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE) + set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE}) +endif() + +# Remove any cached result from an older CMake version. +# We now store this in CMakeHIPCompiler.cmake. +unset(CMAKE_HIP_COMPILER_WORKS CACHE) + +# Try to identify the ABI and configure it into CMakeHIPCompiler.cmake +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) +CMAKE_DETERMINE_COMPILER_ABI(HIP ${CMAKE_ROOT}/Modules/CMakeHIPCompilerABI.hip) +if(CMAKE_HIP_ABI_COMPILED) + # The compiler worked so skip dedicated test below. + set(CMAKE_HIP_COMPILER_WORKS TRUE) + message(STATUS "Check for working HIP compiler: ${CMAKE_HIP_COMPILER} - skipped") +endif() + +# This file is used by EnableLanguage in cmGlobalGenerator to +# determine that the selected C++ compiler can actually compile +# and link the most basic of programs. If not, a fatal error +# is set and cmake stops processing commands and will not generate +# any makefiles or projects. +if(NOT CMAKE_HIP_COMPILER_WORKS) + PrintTestCompilerStatus("HIP") + __TestCompiler_setTryCompileTargetType() + file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip + "#ifndef __HIP__\n" + "# error \"The CMAKE_HIP_COMPILER is set to a C/CXX compiler\"\n" + "#endif\n" + "int main(){return 0;}\n") + try_compile(CMAKE_HIP_COMPILER_WORKS ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip + OUTPUT_VARIABLE __CMAKE_HIP_COMPILER_OUTPUT) + # 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") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the HIP compiler works failed with " + "the following output:\n${__CMAKE_HIP_COMPILER_OUTPUT}\n\n") + string(REPLACE "\n" "\n " _output "${__CMAKE_HIP_COMPILER_OUTPUT}") + message(FATAL_ERROR "The HIP compiler\n \"${CMAKE_HIP_COMPILER}\"\n" + "is not able to compile a simple test program.\nIt fails " + "with the following output:\n ${_output}\n\n" + "CMake will not be able to correctly generate this project.") + endif() + PrintTestCompilerResult(CHECK_PASS "works") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the HIP compiler works passed with " + "the following output:\n${__CMAKE_HIP_COMPILER_OUTPUT}\n\n") +endif() + +set(CMAKE_HIP_FLAGS "${__CMAKE_HIP_FLAGS}") +unset(__CMAKE_HIP_FLAGS) + + +# Try to identify the compiler features +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake) +CMAKE_DETERMINE_COMPILE_FEATURES(HIP) + +# Re-configure to save learned information. +configure_file( + ${CMAKE_ROOT}/Modules/CMakeHIPCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPCompiler.cmake + @ONLY + ) +include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPCompiler.cmake) + +if(CMAKE_HIP_SIZEOF_DATA_PTR) + foreach(f ${CMAKE_HIP_ABI_FILES}) + include(${f}) + endforeach() + unset(CMAKE_HIP_ABI_FILES) +endif() + +set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE}) +unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE) +unset(__CMAKE_HIP_COMPILER_OUTPUT) diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index 29e673004c8..c86af98f8db 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -170,3 +170,19 @@ macro(cmake_record_cuda_compile_features) unset(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT) endif() endmacro() + +macro(cmake_record_hip_compile_features) + set(_result 0) + if(_result EQUAL 0 AND DEFINED CMAKE_HIP23_STANDARD_COMPILE_OPTION) + _has_compiler_features_hip(23) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_HIP20_STANDARD_COMPILE_OPTION) + _has_compiler_features_hip(20) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_HIP17_STANDARD_COMPILE_OPTION) + _has_compiler_features_hip(17) + endif() + _has_compiler_features_hip(14) + _has_compiler_features_hip(11) + _has_compiler_features_hip(98) +endmacro() diff --git a/Modules/Compiler/Clang-HIP.cmake b/Modules/Compiler/Clang-HIP.cmake new file mode 100644 index 00000000000..6ac39def09a --- /dev/null +++ b/Modules/Compiler/Clang-HIP.cmake @@ -0,0 +1,16 @@ +include(Compiler/Clang) +__compiler_clang(HIP) +__compiler_clang_cxx_standards(HIP) + +set(_CMAKE_COMPILE_AS_HIP_FLAG "-x hip") +set(_CMAKE_HIP_RDC_FLAG "-fgpu-rdc") + +if(NOT "x${CMAKE_HIP_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") + + string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -O") +endif() + +set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") +set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "") +set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "") diff --git a/Modules/Compiler/ROCMClang-HIP.cmake b/Modules/Compiler/ROCMClang-HIP.cmake new file mode 100644 index 00000000000..9e792b50592 --- /dev/null +++ b/Modules/Compiler/ROCMClang-HIP.cmake @@ -0,0 +1,45 @@ +include(Compiler/ROCMClang) +__compiler_rocmclang(HIP) + +set(_CMAKE_COMPILE_AS_HIP_FLAG "-x hip") +set(_CMAKE_HIP_RDC_FLAG "-fgpu-rdc") + +if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC") + set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") + string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -O") +endif() + +if(CMAKE_HIP_SIMULATE_ID STREQUAL "GNU") + set(CMAKE_HIP_LINKER_WRAPPER_FLAG "-Wl,") + set(CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP ",") +elseif(CMAKE_HIP_SIMULATE_ID STREQUAL "Clang") + set(CMAKE_HIP_LINKER_WRAPPER_FLAG "-Xlinker" " ") + set(CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP) +endif() + +if(NOT CMAKE_HIP_COMPILER_VERSION VERSION_LESS 1.0) + set(CMAKE_HIP98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_HIP98_EXTENSION_COMPILE_OPTION "-std=gnu++98") + set(CMAKE_HIP98_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_HIP11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_HIP11_EXTENSION_COMPILE_OPTION "-std=gnu++11") + set(CMAKE_HIP11_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_HIP14_STANDARD_COMPILE_OPTION "-std=c++14") + set(CMAKE_HIP14_EXTENSION_COMPILE_OPTION "-std=gnu++14") + set(CMAKE_HIP14_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_HIP17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_HIP17_EXTENSION_COMPILE_OPTION "-std=gnu++17") + set(CMAKE_HIP17_STANDARD__HAS_FULL_SUPPORT ON) + + set(CMAKE_HIP20_STANDARD_COMPILE_OPTION "-std=c++20") + set(CMAKE_HIP20_EXTENSION_COMPILE_OPTION "-std=gnu++20") +endif() + +set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") +set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "") +set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "") + +__compiler_check_default_language_standard(HIP 3.5 11) diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake index 72d96b33fc9..b6f3c091dc6 100644 --- a/Modules/Internal/FeatureTesting.cmake +++ b/Modules/Internal/FeatureTesting.cmake @@ -99,6 +99,16 @@ macro(_record_compiler_features_cuda std) unset(lang_level_has_features) endmacro() +macro(_record_compiler_features_hip std) + list(APPEND CMAKE_HIP${std}_COMPILE_FEATURES hip_std_${std}) + + get_property(lang_level_has_features GLOBAL PROPERTY CMAKE_HIP${std}_KNOWN_FEATURES) + if(lang_level_has_features) + _record_compiler_features(HIP "${CMAKE_HIP${std}_STANDARD_COMPILE_OPTION}" CMAKE_HIP${std}_COMPILE_FEATURES) + endif() + unset(lang_level_has_features) +endmacro() + macro(_has_compiler_features lang level compile_flags feature_list) # presume all known features are supported get_property(known_features GLOBAL PROPERTY CMAKE_${lang}${level}_KNOWN_FEATURES) @@ -117,3 +127,7 @@ macro(_has_compiler_features_cuda std) list(APPEND CMAKE_CUDA${std}_COMPILE_FEATURES cuda_std_${std}) _has_compiler_features(CUDA ${std} "${CMAKE_CUDA${std}_STANDARD_COMPILE_OPTION}" CMAKE_CUDA${std}_COMPILE_FEATURES) endmacro() +macro(_has_compiler_features_hip std) + list(APPEND CMAKE_HIP${std}_COMPILE_FEATURES hip_std_${std}) + _has_compiler_features(HIP ${std} "${CMAKE_HIP${std}_STANDARD_COMPILE_OPTION}" CMAKE_HIP${std}_COMPILE_FEATURES) +endmacro() diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 2647998ce12..d15da0c968f 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -585,10 +585,10 @@ void cmComputeLinkInformation::AddImplicitLinkInfo() this->Target->GetLinkClosure(this->Config); for (std::string const& li : lc->Languages) { - if (li == "CUDA") { + if (li == "CUDA" || li == "HIP") { // These need to go before the other implicit link information // as they could require symbols from those other library - // Currently restricted to CUDA as it is the only language + // Currently restricted as CUDA and HIP are the only languages // we have documented runtime behavior controls for this->AddRuntimeLinkLibrary(li); } diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 5399fd0f415..8ecf2648fc6 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -189,6 +189,8 @@ SETUP_LANGUAGE(cuda_properties, CUDA); // NOLINTNEXTLINE(bugprone-suspicious-missing-comma) SETUP_LANGUAGE(fortran_properties, Fortran); // NOLINTNEXTLINE(bugprone-suspicious-missing-comma) +SETUP_LANGUAGE(hip_properties, HIP); +// NOLINTNEXTLINE(bugprone-suspicious-missing-comma) SETUP_LANGUAGE(objc_properties, OBJC); // NOLINTNEXTLINE(bugprone-suspicious-missing-comma) SETUP_LANGUAGE(objcxx_properties, OBJCXX); @@ -201,6 +203,8 @@ SETUP_LANGUAGE(swift_properties, Swift); std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES"; std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY"; std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS"; +std::string const kCMAKE_HIP_ARCHITECTURES = "CMAKE_HIP_ARCHITECTURES"; +std::string const kCMAKE_HIP_RUNTIME_LIBRARY = "CMAKE_HIP_RUNTIME_LIBRARY"; std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS"; std::string const kCMAKE_ISPC_HEADER_SUFFIX = "CMAKE_ISPC_HEADER_SUFFIX"; std::string const kCMAKE_LINK_SEARCH_END_STATIC = @@ -274,6 +278,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, LanguageStandardState cState("C"); LanguageStandardState cudaState("CUDA"); LanguageStandardState cxxState("CXX"); + LanguageStandardState hipState("HIP"); LanguageStandardState objcState("OBJC"); LanguageStandardState objcxxState("OBJCXX"); std::vector targets; @@ -323,6 +328,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, } else if (cState.UpdateIfMatches(argv, i) || cxxState.UpdateIfMatches(argv, i) || cudaState.UpdateIfMatches(argv, i) || + hipState.UpdateIfMatches(argv, i) || objcState.UpdateIfMatches(argv, i) || objcxxState.UpdateIfMatches(argv, i)) { continue; @@ -428,6 +434,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, if (!cudaState.Validate(this->Makefile)) { return -1; } + if (!hipState.Validate(this->Makefile)) { + return -1; + } if (!cxxState.Validate(this->Makefile)) { return -1; } @@ -715,6 +724,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, vars.insert( &fortran_properties[lang_property_start], &fortran_properties[lang_property_start + lang_property_size]); + vars.insert(&hip_properties[lang_property_start], + &hip_properties[lang_property_start + lang_property_size]); vars.insert(&objc_properties[lang_property_start], &objc_properties[lang_property_start + lang_property_size]); vars.insert( @@ -727,6 +738,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, vars.insert(kCMAKE_CUDA_ARCHITECTURES); vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); vars.insert(kCMAKE_ENABLE_EXPORTS); + vars.insert(kCMAKE_HIP_ARCHITECTURES); + vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY); vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS); vars.insert(kCMAKE_ISPC_HEADER_SUFFIX); vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); @@ -761,6 +774,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, vars.insert( &fortran_properties[pie_property_start], &fortran_properties[pie_property_start + pie_property_size]); + vars.insert(&hip_properties[pie_property_start], + &hip_properties[pie_property_start + pie_property_size]); vars.insert(&objc_properties[pie_property_start], &objc_properties[pie_property_start + pie_property_size]); vars.insert( @@ -835,6 +850,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, cState.Enabled(testLangs.find("C") != testLangs.end()); cxxState.Enabled(testLangs.find("CXX") != testLangs.end()); cudaState.Enabled(testLangs.find("CUDA") != testLangs.end()); + hipState.Enabled(testLangs.find("HIP") != testLangs.end()); objcState.Enabled(testLangs.find("OBJC") != testLangs.end()); objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end()); @@ -842,7 +858,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, bool honorStandard = true; if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() && - objcxxState.DidNone() && cudaState.DidNone()) { + objcxxState.DidNone() && cudaState.DidNone() && hipState.DidNone()) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) { case cmPolicies::WARN: warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( @@ -872,6 +888,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, warnCMP0067, warnCMP0067Variables); cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067, warnCMP0067Variables); + hipState.LoadUnsetPropertyValues(this->Makefile, honorStandard, + warnCMP0067, warnCMP0067Variables); objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067, warnCMP0067Variables); objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard, @@ -894,6 +912,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, cState.WriteProperties(fout, targetName); cxxState.WriteProperties(fout, targetName); cudaState.WriteProperties(fout, targetName); + hipState.WriteProperties(fout, targetName); objcState.WriteProperties(fout, targetName); objcxxState.WriteProperties(fout, targetName); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index f217201749a..df1426104bb 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -366,10 +366,11 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( continue; } - // check whether it is a C/C++/CUDA implementation file + // check whether it is a C/C++/CUDA/HIP implementation file bool isCFile = false; std::string lang = s->GetOrDetermineLanguage(); - if (lang == "C" || lang == "CXX" || lang == "CUDA") { + if (lang == "C" || lang == "CXX" || lang == "CUDA" || + lang == "HIP") { std::string const& srcext = s->GetExtension(); isCFile = cm->IsACLikeSourceExtension(srcext); } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 8030b6466af..c608bf940d0 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -718,7 +718,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"), cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"), objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran"), - ispcCompilerIdNode("ISPC"); + hipCompilerIdNode("HIP"), ispcCompilerIdNode("ISPC"); struct CompilerVersionNode : public cmGeneratorExpressionNode { @@ -783,7 +783,8 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode static const CompilerVersionNode cCompilerVersionNode("C"), cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"), objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"), - fortranCompilerVersionNode("Fortran"), ispcCompilerVersionNode("ISPC"); + fortranCompilerVersionNode("Fortran"), ispcCompilerVersionNode("ISPC"), + hipCompilerVersionNode("HIP"); struct PlatformIdNode : public cmGeneratorExpressionNode { @@ -2597,6 +2598,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode }, { "CUDA_COMPILER_ID", &cudaCompilerIdNode }, { "Fortran_COMPILER_ID", &fortranCompilerIdNode }, + { "HIP_COMPILER_ID", &hipCompilerIdNode }, { "VERSION_GREATER", &versionGreaterNode }, { "VERSION_GREATER_EQUAL", &versionGreaterEqNode }, { "VERSION_LESS", &versionLessNode }, @@ -2608,6 +2610,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "OBJC_COMPILER_VERSION", &objcCompilerVersionNode }, { "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode }, { "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode }, + { "HIP_COMPILER_VERSION", &hipCompilerVersionNode }, { "PLATFORM_ID", &platformIdNode }, { "COMPILE_FEATURES", &compileFeaturesNode }, { "CONFIGURATION", &configurationNode }, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6209f3e54ac..812535b099a 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -980,7 +980,7 @@ cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( // Check if we should use the value set by another language. if (lang == "OBJC") { propertyValue = this->GetPropertyWithPairedLanguageSupport("C", suffix); - } else if (lang == "OBJCXX" || lang == "CUDA") { + } else if (lang == "OBJCXX" || lang == "CUDA" || lang == "HIP") { propertyValue = this->GetPropertyWithPairedLanguageSupport("CXX", suffix); } @@ -1121,7 +1121,7 @@ void cmGeneratorTarget::AppendLanguageSideEffects( std::map>& sideEffects) const { static const std::set LANGS_WITH_NO_SIDE_EFFECTS = { - "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s, + "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s, "HIP"_s }; for (auto const& lang : this->GetAllConfigCompileLanguages()) { @@ -3351,6 +3351,23 @@ void cmGeneratorTarget::AddISPCTargetFlags(std::string& flags) const } } +void cmGeneratorTarget::AddHIPArchitectureFlags(std::string& flags) const +{ + const std::string& property = this->GetSafeProperty("HIP_ARCHITECTURES"); + + // If HIP_ARCHITECTURES is false we don't add any architectures. + if (cmIsOff(property)) { + return; + } + + std::vector options; + cmExpandList(property, options); + + for (std::string& option : options) { + flags += " --offload-arch=" + option; + } +} + void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const { std::string const& compiler = @@ -4742,7 +4759,8 @@ bool cmGeneratorTarget::ComputeCompileFeatures( } // Custom updates for the CUDA standard. - if (generatorTargetLanguageStandard && language.first == "CUDA") { + if (generatorTargetLanguageStandard != nullptr && + (language.first == "CUDA")) { if (generatorTargetLanguageStandard->Value == "98") { this->LanguageStandardMap[key].Value = "03"; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index be36f3f206e..ab9ccfd58d8 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -459,6 +459,8 @@ class cmGeneratorTarget void AddCUDAArchitectureFlags(std::string& flags) const; void AddCUDAToolkitFlags(std::string& flags) const; + void AddHIPArchitectureFlags(std::string& flags) const; + void AddISPCTargetFlags(std::string& flags) const; std::string GetFeatureSpecificLinkRuleVariable( diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 6a49b84a797..3b282de98c7 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -780,9 +780,9 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures() this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); using LanguagePair = std::pair; - std::vector pairedLanguages{ { "OBJC", "C" }, - { "OBJCXX", "CXX" }, - { "CUDA", "CXX" } }; + std::vector pairedLanguages{ + { "OBJC", "C" }, { "OBJCXX", "CXX" }, { "CUDA", "CXX" }, { "HIP", "CXX" } + }; std::set inferredEnabledLanguages; for (auto const& lang : pairedLanguages) { if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) { @@ -1404,8 +1404,8 @@ void cmLocalGenerator::GetDeviceLinkFlags( linkLineComputer->GetLinkerLanguage(target, config); if (pcli) { - // Compute the required cuda device link libraries when - // resolving cuda device symbols + // Compute the required device link libraries when + // resolving gpu lang device symbols this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); } @@ -1968,6 +1968,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, compilerSimulateId = this->Makefile->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"); } + } else if (lang == "HIP") { + target->AddHIPArchitectureFlags(flags); } // Add VFS Overlay for Clang compilers diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 3a65a80c9e6..0667c55a395 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -289,9 +289,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() for (LocalObjectEntry const& entry : localObjectFile.second) { if (entry.Language == "C" || entry.Language == "CXX" || entry.Language == "CUDA" || entry.Language == "Fortran" || - entry.Language == "ISPC") { - // Right now, C, C++, Fortran and CUDA have both a preprocessor and the - // ability to generate assembly code + entry.Language == "HIP" || entry.Language == "ISPC") { + // Right now, C, C++, CUDA, Fortran, HIP and ISPC have both a + // preprocessor and the ability to generate assembly code lang_has_preprocessor = true; lang_has_assembly = true; break; @@ -1550,7 +1550,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( std::unique_ptr scanner; if (lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM" || lang == "OBJC" || lang == "OBJCXX" || lang == "CUDA" || - lang == "ISPC") { + lang == "HIP" || lang == "ISPC") { // TODO: Handle RC (resource files) dependencies correctly. scanner = cm::make_unique(this, targetDir, lang, &validDeps); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index e87f81bd1a2..6d8376c6788 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -945,7 +945,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string compilerLauncher; if (!compileCommands.empty() && (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || - lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { + lang == "HIP" || lang == "ISPC" || lang == "OBJC" || + lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (cmNonempty(clauncher)) { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 4feb0bb2288..60802700f3f 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -833,7 +833,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, std::string compilerLauncher; if (!compileCmds.empty() && (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || - lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { + lang == "HIP" || lang == "ISPC" || lang == "OBJC" || + lang == "OBJCXX")) { std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER"); cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (cmNonempty(clauncher)) { diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index b198a0019fb..73d0feddf6c 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -36,6 +36,9 @@ const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE( const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE( FEATURE_STRING) }; + +const char* const HIP_FEATURES[] = { nullptr FOR_EACH_HIP_FEATURE( + FEATURE_STRING) }; #undef FEATURE_STRING struct StandardNeeded @@ -306,8 +309,7 @@ struct StanardLevelComputer }; std::unordered_map StandardComputerMapping = - { - { "C", + { { "C", StanardLevelComputer{ "C", std::vector{ 90, 99, 11, 17, 23 }, std::vector{ "90", "99", "11", "17", "23" } } }, @@ -326,7 +328,10 @@ std::unordered_map StandardComputerMapping = StanardLevelComputer{ "OBJCXX", std::vector{ 98, 11, 14, 17, 20, 23 }, std::vector{ "98", "11", "14", "17", "20", "23" } } }, - }; + { "HIP", + StanardLevelComputer{ + "HIP", std::vector{ 98, 11, 14, 17, 20, 23 }, + std::vector{ "98", "11", "14", "17", "20", "23" } } } }; } std::string cmStandardLevelResolver::GetCompileOptionDef( @@ -434,6 +439,13 @@ bool cmStandardLevelResolver::CompileFeatureKnown( lang = "CUDA"; return true; } + bool isHIPFeature = + std::find_if(cm::cbegin(HIP_FEATURES) + 1, cm::cend(HIP_FEATURES), + cmStrCmp(feature)) != cm::cend(HIP_FEATURES); + if (isHIPFeature) { + lang = "HIP"; + return true; + } std::ostringstream e; if (error) { e << "specified"; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 6f2e44779ee..76227005157 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -288,6 +288,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, SETUP_COMMON_LANGUAGE_PROPERTIES(CXX); SETUP_COMMON_LANGUAGE_PROPERTIES(OBJCXX); SETUP_COMMON_LANGUAGE_PROPERTIES(CUDA); + SETUP_COMMON_LANGUAGE_PROPERTIES(HIP); initProp("ANDROID_API"); initProp("ANDROID_API_MIN"); @@ -365,6 +366,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); initProp("CUDA_RUNTIME_LIBRARY"); initProp("CUDA_ARCHITECTURES"); + initProp("HIP_RUNTIME_LIBRARY"); + initProp("HIP_ARCHITECTURES"); initProp("VISIBILITY_INLINES_HIDDEN"); initProp("JOB_POOL_COMPILE"); initProp("JOB_POOL_LINK"); @@ -1168,6 +1171,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) MAKE_STATIC_PROP(C_STANDARD); MAKE_STATIC_PROP(CXX_STANDARD); MAKE_STATIC_PROP(CUDA_STANDARD); + MAKE_STATIC_PROP(HIP_STANDARD); MAKE_STATIC_PROP(OBJC_STANDARD); MAKE_STATIC_PROP(OBJCXX_STANDARD); MAKE_STATIC_PROP(COMPILE_DEFINITIONS); @@ -1354,8 +1358,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->SetProperty("COMPILE_PDB_NAME", cmToCStr(tmp)); this->AddUtility(reusedFrom, false, this->impl->Makefile); } else if (prop == propC_STANDARD || prop == propCXX_STANDARD || - prop == propCUDA_STANDARD || prop == propOBJC_STANDARD || - prop == propOBJCXX_STANDARD) { + prop == propCUDA_STANDARD || prop == propHIP_STANDARD || + prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) { if (value) { this->impl->LanguageStandardProperties[prop] = BTs(value, this->impl->Makefile->GetBacktrace()); @@ -1461,8 +1465,8 @@ void cmTarget::AppendProperty(const std::string& prop, this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); } else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" || - prop == "CUDA_STANDARD" || prop == "OBJC_STANDARD" || - prop == "OBJCXX_STANDARD") { + prop == "CUDA_STANDARD" || prop == "HIP_STANDARD" || + prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") { this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be appended."); } else { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 9a866ab89bf..eb4c0b62cf2 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -218,6 +218,7 @@ cmake::cmake(Role role, cmState::Mode mode) setupExts(this->CudaFileExtensions, { "cu" }); setupExts(this->FortranFileExtensions, { "f", "F", "for", "f77", "f90", "f95", "f03" }); + setupExts(this->HipFileExtensions, { "hip" }); setupExts(this->ISPCFileExtensions, { "ispc" }); } } @@ -2462,6 +2463,8 @@ std::vector cmake::GetAllExtensions() const // cuda extensions are also in SourceFileExtensions so we ignore it here allExt.insert(allExt.end(), this->FortranFileExtensions.ordered.begin(), this->FortranFileExtensions.ordered.end()); + allExt.insert(allExt.end(), this->HipFileExtensions.ordered.begin(), + this->HipFileExtensions.ordered.end()); allExt.insert(allExt.end(), this->ISPCFileExtensions.ordered.begin(), this->ISPCFileExtensions.ordered.end()); return allExt; diff --git a/Source/cmake.h b/Source/cmake.h index e845662911d..5a2a88fac7f 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -297,7 +297,7 @@ class cmake return this->CLikeSourceFileExtensions.Test(ext) || this->CudaFileExtensions.Test(ext) || this->FortranFileExtensions.Test(ext) || - this->ISPCFileExtensions.Test(ext); + this->HipFileExtensions.Test(ext) || this->ISPCFileExtensions.Test(ext); } bool IsACLikeSourceExtension(cm::string_view ext) const @@ -662,6 +662,7 @@ class cmake FileExtensions CudaFileExtensions; FileExtensions ISPCFileExtensions; FileExtensions FortranFileExtensions; + FileExtensions HipFileExtensions; bool ClearBuildSystem = false; bool DebugTryCompile = false; bool RegenerateDuringBuild = false; @@ -838,3 +839,11 @@ class cmake F(cuda_std_17) \ F(cuda_std_20) \ F(cuda_std_23) + +#define FOR_EACH_HIP_FEATURE(F) \ + F(hip_std_98) \ + F(hip_std_11) \ + F(hip_std_14) \ + F(hip_std_17) \ + F(hip_std_20) \ + F(hip_std_23) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 38b43014445..346c2c5e189 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1479,6 +1479,10 @@ if(BUILD_TESTING) add_subdirectory(CudaOnly) endif() + if(CMake_TEST_HIP) + add_subdirectory(HIP) + endif() + if(CMake_TEST_ISPC) add_subdirectory(ISPC) endif() diff --git a/Tests/HIP/ArchitectureOff/CMakeLists.txt b/Tests/HIP/ArchitectureOff/CMakeLists.txt new file mode 100644 index 00000000000..bccb3b4f889 --- /dev/null +++ b/Tests/HIP/ArchitectureOff/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.18) +project(HIPArchitecture HIP) + +# Make sure CMake doesn't pass architectures if HIP_ARCHITECTURES is OFF. +string(APPEND CMAKE_HIP_FLAGS " --offload-arch=gfx908") + +add_executable(HIPOnlyArchitectureOff main.hip) +set_property(TARGET HIPOnlyArchitectureOff PROPERTY HIP_ARCHITECTURES OFF) diff --git a/Tests/HIP/ArchitectureOff/main.hip b/Tests/HIP/ArchitectureOff/main.hip new file mode 100644 index 00000000000..9256318cc25 --- /dev/null +++ b/Tests/HIP/ArchitectureOff/main.hip @@ -0,0 +1,9 @@ +#ifdef __HIP_DEVICE_COMPILE__ +# ifndef __gfx908__ +# error "Passed architecture gfx908, but got something else." +# endif +#endif + +int main() +{ +} diff --git a/Tests/HIP/CMakeLists.txt b/Tests/HIP/CMakeLists.txt new file mode 100644 index 00000000000..b3966c9ebf6 --- /dev/null +++ b/Tests/HIP/CMakeLists.txt @@ -0,0 +1,12 @@ +macro (add_hip_test_macro name) + add_test_macro("${name}" ${ARGN}) + set_property(TEST "${name}" APPEND + PROPERTY LABELS "HIP") +endmacro () + +add_hip_test_macro(HIP.ArchitectureOff HIPOnlyArchitectureOff) +add_hip_test_macro(HIP.CompileFlags HIPOnlyCompileFlags) +add_hip_test_macro(HIP.EnableStandard HIPEnableStandard) +add_hip_test_macro(HIP.MathFunctions HIPOnlyMathFunctions) +add_hip_test_macro(HIP.TryCompile HIPOnlyTryCompile) +add_hip_test_macro(HIP.WithDefs HIPOnlyWithDefs) diff --git a/Tests/HIP/CompileFlags/CMakeLists.txt b/Tests/HIP/CompileFlags/CMakeLists.txt new file mode 100644 index 00000000000..c808313870a --- /dev/null +++ b/Tests/HIP/CompileFlags/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.18) +project(CompileFlags HIP) + +add_executable(HIPOnlyCompileFlags main.hip) + +set_property(TARGET HIPOnlyCompileFlags PROPERTY HIP_ARCHITECTURES gfx803) + +target_compile_options(HIPOnlyCompileFlags PRIVATE -DALWAYS_DEFINE) diff --git a/Tests/HIP/CompileFlags/main.hip b/Tests/HIP/CompileFlags/main.hip new file mode 100644 index 00000000000..3259f1d3134 --- /dev/null +++ b/Tests/HIP/CompileFlags/main.hip @@ -0,0 +1,13 @@ +#ifdef __HIP_DEVICE_COMPILE__ +# ifndef __gfx803__ +# error "Passed architecture gfx803, but got something else." +# endif +#endif + +#ifndef ALWAYS_DEFINE +# error "ALWAYS_DEFINE not defined!" +#endif + +int main() +{ +} diff --git a/Tests/HIP/EnableStandard/CMakeLists.txt b/Tests/HIP/EnableStandard/CMakeLists.txt new file mode 100644 index 00000000000..6701724678a --- /dev/null +++ b/Tests/HIP/EnableStandard/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.18) +project (EnableStandard HIP) + +set(CMAKE_CXX_COMPILER ${CMAKE_HIP_COMPILER}) +enable_language(CXX) + +#Goal for this example: +#build hip sources that require C++11 to be enabled. + +add_library(HIPStatic11 STATIC static.cxx) +set_source_files_properties(static.cxx PROPERTIES LANGUAGE HIP) + +add_library(HIPDynamic11 SHARED shared.hip) + +add_executable(HIPEnableStandard main.hip) +target_link_libraries(HIPEnableStandard PRIVATE HIPStatic11 HIPDynamic11) + +target_compile_features(HIPDynamic11 PRIVATE cxx_std_11) +set_target_properties(HIPStatic11 PROPERTIES HIP_STANDARD 11) +set_target_properties(HIPStatic11 PROPERTIES HIP_STANDARD_REQUIRED TRUE) diff --git a/Tests/HIP/EnableStandard/main.hip b/Tests/HIP/EnableStandard/main.hip new file mode 100644 index 00000000000..7dc32e80656 --- /dev/null +++ b/Tests/HIP/EnableStandard/main.hip @@ -0,0 +1,23 @@ + +#include + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +#else +# define IMPORT +#endif + +int static_hip11_func(int); +IMPORT int shared_hip11_func(int); + +void test_functions() +{ + static_hip11_func(int(42)); + shared_hip11_func(int(42)); +} + +int main(int argc, char** argv) +{ + test_functions(); + return 0; +} diff --git a/Tests/HIP/EnableStandard/shared.hip b/Tests/HIP/EnableStandard/shared.hip new file mode 100644 index 00000000000..20422586331 --- /dev/null +++ b/Tests/HIP/EnableStandard/shared.hip @@ -0,0 +1,15 @@ + +#include + +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +using tt = std::true_type; +using ft = std::false_type; +EXPORT int __host__ shared_hip11_func(int x) +{ + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/EnableStandard/static.cxx b/Tests/HIP/EnableStandard/static.cxx new file mode 100644 index 00000000000..29558945e3a --- /dev/null +++ b/Tests/HIP/EnableStandard/static.cxx @@ -0,0 +1,9 @@ + +#include + +using tt = std::true_type; +using ft = std::false_type; +int __host__ static_hip11_func(int x) +{ + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/MathFunctions/CMakeLists.txt b/Tests/HIP/MathFunctions/CMakeLists.txt new file mode 100644 index 00000000000..81e3ddb26f2 --- /dev/null +++ b/Tests/HIP/MathFunctions/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.18) +project(MathFunctions HIP) + +# This test covers these major HIP language/runtime requirements: +# +# 1. This makes sure CMake properly specifies the internal clang header dirs +# that hold headers needed for overloads of device side functions +# +# 2. This makes sure that all HIP include directories are properly marked as +# system includes so we don't get the following warnings: +# replacement function 'operator delete' cannot be declared 'inline'# +# +# 3. This makes sure CMake properly links to all the built-in libraries +# that hip needs that inject support for __half support +# +add_executable(HIPOnlyMathFunctions main.hip) +target_compile_options(HIPOnlyMathFunctions PRIVATE -Werror) +target_compile_features(HIPOnlyMathFunctions PRIVATE hip_std_14) diff --git a/Tests/HIP/MathFunctions/main.hip b/Tests/HIP/MathFunctions/main.hip new file mode 100644 index 00000000000..8a6e77f5d36 --- /dev/null +++ b/Tests/HIP/MathFunctions/main.hip @@ -0,0 +1,40 @@ + +#include +#include +#include +#include + +#include +#include + +namespace { +template +__global__ void global_entry_point(F f, T *out) { + *out = f(); +} + +template +bool verify(F f, T expected) +{ + std::unique_ptr cpu_T(new T); + T* gpu_T = nullptr; + hipMalloc((void**)&gpu_T, sizeof(T)); + hipLaunchKernelGGL(global_entry_point, 1, 1, 0, 0, f, gpu_T); + hipMemcpy(cpu_T.get(), gpu_T, sizeof(T), hipMemcpyDeviceToHost); + hipFree(gpu_T); + return (*cpu_T == expected); +} +} + +int main(int argc, char** argv) +{ + bool valid = verify([]__device__(){ return std::round(1.4f); }, 1.0f); + valid &= verify([]__device__(){ return max<_Float16>(1.0f, 2.0f); }, 2.0f); + valid &= verify([]__device__(){ return min<_Float16>(1.0f, 2.0f); }, 1.0f); + + if (valid) { + return 0; + } else { + return 1; + } +} diff --git a/Tests/HIP/TryCompile/CMakeLists.txt b/Tests/HIP/TryCompile/CMakeLists.txt new file mode 100644 index 00000000000..f3bb3bf99d5 --- /dev/null +++ b/Tests/HIP/TryCompile/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.18) +project (TryCompile HIP) + +#Goal for this example: +# Verify try_compile with HIP language works +set(CMAKE_HIP_STANDARD 14) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +try_compile(result "${CMAKE_CURRENT_BINARY_DIR}" + SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/device_function.hip" + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/device_function.o") + +add_executable(HIPOnlyTryCompile main.hip) +target_link_libraries(HIPOnlyTryCompile "${CMAKE_CURRENT_BINARY_DIR}/device_function.o") diff --git a/Tests/HIP/TryCompile/device_function.hip b/Tests/HIP/TryCompile/device_function.hip new file mode 100644 index 00000000000..7c1205e6d78 --- /dev/null +++ b/Tests/HIP/TryCompile/device_function.hip @@ -0,0 +1,17 @@ +#include +#include + +static __global__ void fake_hip_kernel() +{ +} + +int __host__ try_compile_hip_func(int x) +{ + + fake_hip_kernel<<<1, 1>>>(); + bool valid = (hipSuccess == hipGetLastError()); + if (!valid) { + throw std::system_error(ENODEV, std::generic_category(), "no hip device"); + } + return x * x; +} diff --git a/Tests/HIP/TryCompile/main.hip b/Tests/HIP/TryCompile/main.hip new file mode 100644 index 00000000000..091dca3bca0 --- /dev/null +++ b/Tests/HIP/TryCompile/main.hip @@ -0,0 +1,8 @@ +int __host__ try_compile_hip_func(int x); + +int main(int argc, char** argv) +{ + try_compile_hip_func(int(42)); + + return 0; +} diff --git a/Tests/HIP/WithDefs/CMakeLists.txt b/Tests/HIP/WithDefs/CMakeLists.txt new file mode 100644 index 00000000000..3d4461b6b51 --- /dev/null +++ b/Tests/HIP/WithDefs/CMakeLists.txt @@ -0,0 +1,36 @@ + +cmake_minimum_required(VERSION 3.18) +project (WithDefs HIP) + +set(CMAKE_HIP_ARCHITECTURES OFF) +set(release_compile_defs DEFREL) + +#Goal for this example: +#build a executable that needs to be passed a complex define through add_definitions +#this verifies we can pass C++ style attributes to hipcc +add_definitions("-DPACKED_DEFINE=[[gnu::packed]]") + +add_executable(HIPOnlyWithDefs main.hip.cpp) +set_source_files_properties(main.hip.cpp PROPERTIES LANGUAGE HIP) + +target_compile_features(HIPOnlyWithDefs PRIVATE hip_std_17) + +target_compile_options(HIPOnlyWithDefs + PRIVATE + -DFLAG_COMPILE_LANG_$ + $<$:-DFLAG_LANG_IS_HIP=$> # Host-only defines are possible only on NVCC. + ) + +target_compile_definitions(HIPOnlyWithDefs + PRIVATE + $<$:$> + -DDEF_COMPILE_LANG_$ + -DDEF_LANG_IS_HIP=$ + -DDEF_HIP_COMPILER=$ + -DDEF_HIP_COMPILER_VERSION=$ + ) + +target_include_directories(HIPOnlyWithDefs + PRIVATE + $<$:${CMAKE_CURRENT_SOURCE_DIR}/inc_hip> +) diff --git a/Tests/HIP/WithDefs/inc_hip/inc_hip.h b/Tests/HIP/WithDefs/inc_hip/inc_hip.h new file mode 100644 index 00000000000..fe2698a0297 --- /dev/null +++ b/Tests/HIP/WithDefs/inc_hip/inc_hip.h @@ -0,0 +1 @@ +#define INC_HIP diff --git a/Tests/HIP/WithDefs/main.hip.cpp b/Tests/HIP/WithDefs/main.hip.cpp new file mode 100644 index 00000000000..a8f2d185b1b --- /dev/null +++ b/Tests/HIP/WithDefs/main.hip.cpp @@ -0,0 +1,89 @@ +#include + +#include +#include +#ifndef INC_HIP +# error "INC_HIP not defined!" +#endif + +#ifndef PACKED_DEFINE +# error "PACKED_DEFINE not defined!" +#endif + +#ifndef FLAG_COMPILE_LANG_HIP +# error "FLAG_COMPILE_LANG_HIP not defined!" +#endif + +#ifndef FLAG_LANG_IS_HIP +# error "FLAG_LANG_IS_HIP not defined!" +#endif + +#if !FLAG_LANG_IS_HIP +# error "Expected FLAG_LANG_IS_HIP" +#endif + +#ifndef DEF_COMPILE_LANG_HIP +# error "DEF_COMPILE_LANG_HIP not defined!" +#endif + +#ifndef DEF_LANG_IS_HIP +# error "DEF_LANG_IS_HIP not defined!" +#endif + +#if !DEF_LANG_IS_HIP +# error "Expected DEF_LANG_IS_HIP" +#endif + +#ifndef DEF_HIP_COMPILER +# error "DEF_HIP_COMPILER not defined!" +#endif + +#ifndef DEF_HIP_COMPILER_VERSION +# error "DEF_HIP_COMPILER_VERSION not defined!" +#endif + +static __global__ void DetermineIfValidHIPDevice() +{ +} + +#ifdef _MSC_VER +# pragma pack(push, 1) +# undef PACKED_DEFINE +# define PACKED_DEFINE +#endif +struct PACKED_DEFINE result_type +{ + bool valid; + int value; +#if defined(NDEBUG) && !defined(DEFREL) +# error missing DEFREL flag +#endif +}; +#ifdef _MSC_VER +# pragma pack(pop) +#endif + +result_type can_launch_kernel() +{ + result_type r; + DetermineIfValidHIPDevice<<<1, 1>>>(); + r.valid = (hipSuccess == hipGetLastError()); + if (r.valid) { + r.value = 1; + } else { + r.value = -1; + } + return r; +} + +int main(int argc, char** argv) +{ + hipError_t err; + int nDevices = 0; + err = hipGetDeviceCount(&nDevices); + if (err != hipSuccess) { + std::cerr << hipGetErrorString(err) << std::endl; + return 1; + } + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index d02d7a2fd57..16487f3831f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -724,6 +724,9 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") if(DEFINED CMake_TEST_CUDA) list(APPEND CompilerLauncher_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) endif() + if(DEFINED CMake_TEST_HIP) + list(APPEND CompilerLauncher_ARGS -DCMake_TEST_HIP=${CMake_TEST_HIP}) + endif() if(DEFINED CMake_TEST_ISPC) list(APPEND CompilerLauncher_ARGS -DCMake_TEST_ISPC=${CMake_TEST_ISPC}) endif() @@ -736,7 +739,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") endif() add_RunCMake_test(CompilerLauncher) set_property(TEST RunCMake.CompilerLauncher APPEND - PROPERTY LABELS "CUDA;ISPC") + PROPERTY LABELS "CUDA;HIP;ISPC") add_RunCMake_test(ctest_labels_for_subprojects) add_RunCMake_test(CompilerArgs) add_RunCMake_test(LinkerLauncher) diff --git a/Tests/RunCMake/CompilerLauncher/HIP-common.cmake b/Tests/RunCMake/CompilerLauncher/HIP-common.cmake new file mode 100644 index 00000000000..53ece7814e3 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-common.cmake @@ -0,0 +1,5 @@ +enable_language(HIP) +enable_language(CXX) +set(CMAKE_VERBOSE_MAKEFILE TRUE) + +add_executable(main main.hip) diff --git a/Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/HIP-env.cmake b/Tests/RunCMake/CompilerLauncher/HIP-env.cmake new file mode 100644 index 00000000000..1bf56cee95f --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-env.cmake @@ -0,0 +1 @@ +include(HIP-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt new file mode 100644 index 00000000000..3313e31f633 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake new file mode 100644 index 00000000000..37985a52a38 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(HIP-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/HIP-launch.cmake b/Tests/RunCMake/CompilerLauncher/HIP-launch.cmake new file mode 100644 index 00000000000..78fd16ba0f7 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP-launch.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(HIP.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/HIP.cmake b/Tests/RunCMake/CompilerLauncher/HIP.cmake new file mode 100644 index 00000000000..9d2577a6910 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/HIP.cmake @@ -0,0 +1,2 @@ +set(CMAKE_HIP_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") +include(HIP-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake index 787282a8189..84d047982c2 100644 --- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -29,6 +29,9 @@ endif() if(CMake_TEST_Fortran) list(APPEND langs Fortran) endif() +if(CMake_TEST_HIP) + list(APPEND langs HIP) +endif() if(CMake_TEST_ISPC) list(APPEND langs ISPC) endif() diff --git a/Tests/RunCMake/CompilerLauncher/main.hip b/Tests/RunCMake/CompilerLauncher/main.hip new file mode 100644 index 00000000000..f8b643afbf2 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/main.hip @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} From 947dbed0aa502c70a9e165757450bd8409036980 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 2 Sep 2020 14:53:41 -0400 Subject: [PATCH 0619/1519] HIP: Automatically inject the `hip::device` runtime target Any target that might need to link to hip code needs the `hip::device` target --- Modules/CMakeHIPCompiler.cmake.in | 5 +- Modules/CMakeHIPInformation.cmake | 7 + Modules/CMakeHIPRuntime.cmake.in | 99 +++++++++++++ Modules/CMakeTestHIPCompiler.cmake | 21 +++ Modules/Compiler/Clang-HIP.cmake | 4 + Modules/Compiler/ROCMClang-HIP.cmake | 4 + Source/cmComputeLinkDepends.cxx | 14 ++ Source/cmGeneratorTarget.cxx | 196 +++++++++++++++++++++---- Source/cmGeneratorTarget.h | 6 + Source/cmLinkItem.h | 5 + Tests/HIP/CMakeLists.txt | 3 + Tests/HIP/InferHipLang1/CMakeLists.txt | 12 ++ Tests/HIP/InferHipLang1/interface.hip | 19 +++ Tests/HIP/InferHipLang1/main.cxx | 19 +++ Tests/HIP/InferHipLang2/CMakeLists.txt | 12 ++ Tests/HIP/InferHipLang2/interface.hip | 19 +++ Tests/HIP/InferHipLang2/main.cxx | 19 +++ Tests/HIP/MixedLanguage/CMakeLists.txt | 19 +++ Tests/HIP/MixedLanguage/main.cxx | 40 +++++ Tests/HIP/MixedLanguage/shared.c | 12 ++ Tests/HIP/MixedLanguage/shared.cxx | 21 +++ Tests/HIP/MixedLanguage/shared.hip | 26 ++++ Tests/HIP/MixedLanguage/static.c | 6 + Tests/HIP/MixedLanguage/static.cxx | 7 + Tests/HIP/MixedLanguage/static.hip | 21 +++ 25 files changed, 587 insertions(+), 29 deletions(-) create mode 100644 Modules/CMakeHIPRuntime.cmake.in create mode 100644 Tests/HIP/InferHipLang1/CMakeLists.txt create mode 100644 Tests/HIP/InferHipLang1/interface.hip create mode 100644 Tests/HIP/InferHipLang1/main.cxx create mode 100644 Tests/HIP/InferHipLang2/CMakeLists.txt create mode 100644 Tests/HIP/InferHipLang2/interface.hip create mode 100644 Tests/HIP/InferHipLang2/main.cxx create mode 100644 Tests/HIP/MixedLanguage/CMakeLists.txt create mode 100644 Tests/HIP/MixedLanguage/main.cxx create mode 100644 Tests/HIP/MixedLanguage/shared.c create mode 100644 Tests/HIP/MixedLanguage/shared.cxx create mode 100644 Tests/HIP/MixedLanguage/shared.hip create mode 100644 Tests/HIP/MixedLanguage/static.c create mode 100644 Tests/HIP/MixedLanguage/static.cxx create mode 100644 Tests/HIP/MixedLanguage/static.hip diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in index eeb51b281a4..9a30a45b3af 100644 --- a/Modules/CMakeHIPCompiler.cmake.in +++ b/Modules/CMakeHIPCompiler.cmake.in @@ -22,7 +22,7 @@ set(CMAKE_HIP_COMPILER_ENV_VAR "HIPCXX") set(CMAKE_HIP_COMPILER_LOADED 1) set(CMAKE_HIP_COMPILER_ID_RUN 1) set(CMAKE_HIP_SOURCE_FILE_EXTENSIONS hip) -set(CMAKE_HIP_LINKER_PREFERENCE 15) +set(CMAKE_HIP_LINKER_PREFERENCE 90) set(CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES 1) set(CMAKE_HIP_SIZEOF_DATA_PTR "@CMAKE_HIP_SIZEOF_DATA_PTR@") @@ -48,8 +48,7 @@ set(CMAKE_HIP_IMPLICIT_LINK_LIBRARIES "@CMAKE_HIP_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES "@CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES@") set(CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") -set(CMAKE_HIP_COMPILER_DEVICE_LIBRARY_ROOT_DIR "@CMAKE_HIP_COMPILER_DEVICE_LIBRARY_ROOT_DIR@") -@_SET_CMAKE_HIP_DEVICE_LIBRARY_INCLUSION@ +set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") set(CMAKE_AR "@CMAKE_AR@") set(CMAKE_HIP_COMPILER_AR "@CMAKE_HIP_COMPILER_AR@") diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake index df1d98ae413..ec37e1c91ae 100644 --- a/Modules/CMakeHIPInformation.cmake +++ b/Modules/CMakeHIPInformation.cmake @@ -130,3 +130,10 @@ if(NOT CMAKE_HIP_LINK_EXECUTABLE) endif() set(CMAKE_HIP_INFORMATION_LOADED 1) + +# Load the file and find the relevant HIP runtime. +# This file will only exist after all compiler detection has finished +include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake OPTIONAL) +if(COMMAND _CMAKE_FIND_HIP_RUNTIME) + _CMAKE_FIND_HIP_RUNTIME() +endif() diff --git a/Modules/CMakeHIPRuntime.cmake.in b/Modules/CMakeHIPRuntime.cmake.in new file mode 100644 index 00000000000..ade26bb9b17 --- /dev/null +++ b/Modules/CMakeHIPRuntime.cmake.in @@ -0,0 +1,99 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +function(_CMAKE_FIND_HIP_RUNTIME ) + # Determined when hipcc is the HIP compiler + set(_CMAKE_HIP_COMPILER_ROCM_ROOT "@_CMAKE_HIP_COMPILER_ROCM_ROOT@") + + # Forward facing value that can be provided by the user + set(CMAKE_HIP_COMPILER_TOOLKIT_ROOT @CMAKE_HIP_COMPILER_TOOLKIT_ROOT@) + + if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) + set(message_on_found TRUE) + endif() + + set(explicit_search_only FALSE) + set(rocm_root_dirs ) + if(DEFINED CMAKE_HIP_COMPILER_TOOLKIT_ROOT) + set(rocm_root_dirs "${CMAKE_HIP_COMPILER_TOOLKIT_ROOT}") + set(explicit_search_only TRUE) + set(error_message_location "the variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"${CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]") + elseif(DEFINED ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}) + set(rocm_root_dirs "$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}") + set(explicit_search_only TRUE) + set(error_message_location "CMAKE_HIP_COMPILER_TOOLKIT_ROOT") + set(error_message_location "the environment variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]") + elseif(DEFINED _CMAKE_HIP_COMPILER_ROCM_ROOT) + set(rocm_root_dirs "${_CMAKE_HIP_COMPILER_ROCM_ROOT}") + set(explicit_search_only TRUE) + set(error_message_location "the associated hipconfig --rocmpath [\"${_CMAKE_HIP_COMPILER_ROCM_ROOT}\"]") + endif() + + # Guess on where rocm is installed + if(NOT rocm_root_dirs AND (UNIX AND NOT APPLE)) + set(platform_base "/opt/rocm-") + + # Finad all default rocm installations + file(GLOB possible_paths "${platform_base}*") + + set(versions) + foreach(p ${possible_paths}) + # Extract version number from end of string + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+$" p_version ${p}) + if(IS_DIRECTORY ${p} AND p_version) + list(APPEND versions ${p_version}) + endif() + endforeach() + + # Sort numerically in descending order, so we try the newest versions first. + list(SORT versions COMPARE NATURAL ORDER DESCENDING) + + # With a descending list of versions, populate possible paths to search. + set(rocm_root_dirs "/opt/rocm") + foreach(v IN LISTS versions) + list(APPEND rocm_root_dirs "${platform_base}${v}") + endforeach() + endif() + + set(search_rel_path "/lib/cmake/hip-lang/") + list(TRANSFORM rocm_root_dirs APPEND "${search_rel_path}") + + find_package(hip-lang + CONFIG + PATHS ${rocm_root_dirs} + QUIET + NO_DEFAULT_PATH + ) + if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET AND NOT explicit_search_only) + find_package(hip-lang CONFIG QUIET) + endif() + + if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) + set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC + ${CMAKE_HIP_RUNTIME_LIBRARIES_STATIC} + ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET} PARENT_SCOPE) + set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED + ${CMAKE_HIP_RUNTIME_LIBRARIES_SHARED} + ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET} PARENT_SCOPE) + endif() + + if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET AND message_on_found) + message(STATUS "Found HIP runtime: ${hip-lang_DIR}") + elseif(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) + if(explicit_search_only) + set(error_message "Failed to find the HIP runtime, Could not find hip-lang-config.cmake at the following location(s):\n") + foreach(p IN LISTS rocm_root_dirs) + string(APPEND error_message "\t${p}\n") + endforeach() + string(APPEND "which are computed from the location specified by ${error_message_location}. \ + Please specify CMAKE_HIP_COMPILER_TOOLKIT_ROOT to the location of") + message(FATAL_ERROR "${error_message}") + else() + message(FATAL_ERROR + "Failed to find the HIP runtime, Could not find hip-lang-config.cmake.\ + Try setting CMAKE_HIP_COMPILER_TOOLKIT_ROOT") + endif() + endif() + +endfunction() diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake index da70f8d2714..d9fcc9d8fea 100644 --- a/Modules/CMakeTestHIPCompiler.cmake +++ b/Modules/CMakeTestHIPCompiler.cmake @@ -78,6 +78,20 @@ unset(__CMAKE_HIP_FLAGS) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake) CMAKE_DETERMINE_COMPILE_FEATURES(HIP) + +# Setup the following: +# Configure the new template file CMakeHipRuntime.cmake to +# - ${CMAKE_PLATFORM_INFO_DIR}/ +# This file will do the actual find_package query. We than have +# CMakeHIPInformation.cmake include `CMakeHipRuntime` +# So it is included once system information has been finished +# +configure_file( + ${CMAKE_ROOT}/Modules/CMakeHIPRuntime.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake + @ONLY +) + # Re-configure to save learned information. configure_file( ${CMAKE_ROOT}/Modules/CMakeHIPCompiler.cmake.in @@ -96,3 +110,10 @@ endif() set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE}) unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE) unset(__CMAKE_HIP_COMPILER_OUTPUT) + +# Load the file and find the relevant HIP runtime. +# This file will only exist after all compiler detection has finished +include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake) +if(COMMAND _CMAKE_FIND_HIP_RUNTIME) + _CMAKE_FIND_HIP_RUNTIME() +endif() diff --git a/Modules/Compiler/Clang-HIP.cmake b/Modules/Compiler/Clang-HIP.cmake index 6ac39def09a..1030a43cdae 100644 --- a/Modules/Compiler/Clang-HIP.cmake +++ b/Modules/Compiler/Clang-HIP.cmake @@ -14,3 +14,7 @@ endif() set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "") set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "") + +# Populated by CMakeHIPRuntime.cmake +set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC "") +set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED "") diff --git a/Modules/Compiler/ROCMClang-HIP.cmake b/Modules/Compiler/ROCMClang-HIP.cmake index 9e792b50592..7af769987fd 100644 --- a/Modules/Compiler/ROCMClang-HIP.cmake +++ b/Modules/Compiler/ROCMClang-HIP.cmake @@ -42,4 +42,8 @@ set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "") set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "") +# Populated by CMakeHIPRuntime.cmake +set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC "") +set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED "") + __compiler_check_default_language_standard(HIP 3.5 11) diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 4a6518fde4a..0b27e34c2b7 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -371,6 +372,12 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) // This target provides its own link interface information. this->AddLinkEntries(depender_index, iface->Libraries); this->AddLinkObjects(iface->Objects); + for (auto const& language : iface->Languages) { + auto runtimeEntries = iface->LanguageRuntimeLibraries.find(language); + if (runtimeEntries != iface->LanguageRuntimeLibraries.end()) { + this->AddLinkEntries(depender_index, runtimeEntries->second); + } + } if (isIface) { return; @@ -516,6 +523,13 @@ void cmComputeLinkDepends::AddDirectLinkEntries() this->Target->GetLinkImplementation(this->Config); this->AddLinkEntries(-1, impl->Libraries); this->AddLinkObjects(impl->Objects); + + for (auto const& language : impl->Languages) { + auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language); + if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) { + this->AddLinkEntries(-1, runtimeEntries->second); + } + } for (cmLinkItem const& wi : impl->WrongConfigLibraries) { this->CheckWrongConfigItem(wi); } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 812535b099a..cb10117704a 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1235,6 +1235,20 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( &dagChecker, result, excludeImported, language); } + cmLinkImplementation const* impl = this->GetLinkImplementation(config); + if (impl != nullptr) { + auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language); + if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) { + for (auto const& lib : runtimeEntries->second) { + if (lib.Target) { + handleSystemIncludesDep(this->LocalGenerator, lib.Target, config, + this, &dagChecker, result, excludeImported, + language); + } + } + } + } + std::for_each(result.begin(), result.end(), cmSystemTools::ConvertToUnixSlashes); std::sort(result.begin(), result.end()); @@ -1474,31 +1488,80 @@ void AddLangSpecificImplicitIncludeDirectories( } } +void addInterfaceEntry(cmGeneratorTarget const* headTarget, + std::string const& config, std::string const& prop, + std::string const& lang, + cmGeneratorExpressionDAGChecker* dagChecker, + EvaluatedTargetPropertyEntries& entries, + bool usage_requirements_only, + std::vector const& libraries) +{ + for (cmLinkImplItem const& lib : libraries) { + if (lib.Target) { + EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); + // Pretend $ appeared in our + // caller's property and hand-evaluate it as if it were compiled. + // Create a context as cmCompiledGeneratorExpression::Evaluate does. + cmGeneratorExpressionContext context( + headTarget->GetLocalGenerator(), config, false, headTarget, headTarget, + true, lib.Backtrace, lang); + cmExpandList(lib.Target->EvaluateInterfaceProperty( + prop, &context, dagChecker, usage_requirements_only), + ee.Values); + ee.ContextDependent = context.HadContextSensitiveCondition; + entries.Entries.emplace_back(std::move(ee)); + } + } +} + +// IncludeRuntimeInterface is used to break the cycle in computing +// the necessary transitive dependencies of targets that can occur +// now that we have implicit language runtime targets. +// +// To determine the set of languages that a target has we need to iterate +// all the sources which includes transitive INTERFACE sources. +// Therefore we can't determine what language runtimes are needed +// for a target until after all sources are computed. +// +// Therefore while computing the applicable INTERFACE_SOURCES we +// must ignore anything in LanguageRuntimeLibraries or we would +// create a cycle ( INTERFACE_SOURCES requires LanguageRuntimeLibraries, +// LanguageRuntimeLibraries requires INTERFACE_SOURCES). +// +enum class IncludeRuntimeInterface +{ + Yes, + No +}; void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, EvaluatedTargetPropertyEntries& entries, + IncludeRuntimeInterface searchRuntime, bool usage_requirements_only = true) { - if (cmLinkImplementationLibraries const* impl = - headTarget->GetLinkImplementationLibraries(config)) { - entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition; - for (cmLinkImplItem const& lib : impl->Libraries) { - if (lib.Target) { - EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); - // Pretend $ appeared in our - // caller's property and hand-evaluate it as if it were compiled. - // Create a context as cmCompiledGeneratorExpression::Evaluate does. - cmGeneratorExpressionContext context( - headTarget->GetLocalGenerator(), config, false, headTarget, - headTarget, true, lib.Backtrace, lang); - cmExpandList(lib.Target->EvaluateInterfaceProperty( - prop, &context, dagChecker, usage_requirements_only), - ee.Values); - ee.ContextDependent = context.HadContextSensitiveCondition; - entries.Entries.emplace_back(std::move(ee)); + if (searchRuntime == IncludeRuntimeInterface::Yes) { + if (cmLinkImplementation const* impl = + headTarget->GetLinkImplementation(config)) { + entries.HadContextSensitiveCondition = + impl->HadContextSensitiveCondition; + + auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang); + if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) { + addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries, + usage_requirements_only, runtimeLibIt->second); } + addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries, + usage_requirements_only, impl->Libraries); + } + } else { + if (cmLinkImplementationLibraries const* impl = + headTarget->GetLinkImplementationLibraries(config)) { + entries.HadContextSensitiveCondition = + impl->HadContextSensitiveCondition; + addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries, + usage_requirements_only, impl->Libraries); } } } @@ -1656,7 +1719,8 @@ std::vector> cmGeneratorTarget::GetSourceFilePaths( // Collect INTERFACE_SOURCES of all direct link-dependencies. EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries; AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(), - &dagChecker, linkInterfaceSourcesEntries); + &dagChecker, linkInterfaceSourcesEntries, + IncludeRuntimeInterface::No, true); std::vector::size_type numFilesBefore = files.size(); bool contextDependentInterfaceSources = processSources( this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources); @@ -3587,7 +3651,7 @@ std::vector> cmGeneratorTarget::GetIncludeDirectories( } AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, - &dagChecker, entries); + &dagChecker, entries, IncludeRuntimeInterface::Yes); if (this->Makefile->IsOn("APPLE")) { if (cmLinkImplementationLibraries const* impl = @@ -3812,7 +3876,7 @@ std::vector> cmGeneratorTarget::GetCompileOptions( this, config, language, &dagChecker, this->CompileOptionsEntries); AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language, - &dagChecker, entries); + &dagChecker, entries, IncludeRuntimeInterface::Yes); processOptions(this, entries, result, uniqueOptions, debugOptions, "compile options", OptionsParse::Shell); @@ -3854,7 +3918,8 @@ std::vector> cmGeneratorTarget::GetCompileFeatures( this, config, std::string(), &dagChecker, this->CompileFeaturesEntries); AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES", - std::string(), &dagChecker, entries); + std::string(), &dagChecker, entries, + IncludeRuntimeInterface::Yes); processOptions(this, entries, result, uniqueFeatures, debugFeatures, "compile features", OptionsParse::None); @@ -3898,7 +3963,7 @@ std::vector> cmGeneratorTarget::GetCompileDefinitions( this, config, language, &dagChecker, this->CompileDefinitionsEntries); AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language, - &dagChecker, entries); + &dagChecker, entries, IncludeRuntimeInterface::Yes); if (!config.empty()) { std::string configPropName = @@ -3956,7 +4021,7 @@ std::vector> cmGeneratorTarget::GetPrecompileHeaders( this, config, language, &dagChecker, this->PrecompileHeadersEntries); AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language, - &dagChecker, entries); + &dagChecker, entries, IncludeRuntimeInterface::Yes); std::vector> list; processOptions(this, entries, list, uniqueOptions, debugDefines, @@ -4341,7 +4406,7 @@ std::vector> cmGeneratorTarget::GetLinkOptions( this, config, language, &dagChecker, this->LinkOptionsEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, - &dagChecker, entries, + &dagChecker, entries, IncludeRuntimeInterface::Yes, this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processOptions(this, entries, result, uniqueOptions, debugOptions, @@ -4600,7 +4665,7 @@ std::vector> cmGeneratorTarget::GetLinkDirectories( this, config, language, &dagChecker, this->LinkDirectoriesEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language, - &dagChecker, entries, + &dagChecker, entries, IncludeRuntimeInterface::Yes, this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processLinkDirectories(this, entries, result, uniqueDirectories, @@ -4639,7 +4704,7 @@ std::vector> cmGeneratorTarget::GetLinkDepends( } } AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language, - &dagChecker, entries, + &dagChecker, entries, IncludeRuntimeInterface::Yes, this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processOptions(this, entries, result, uniqueOptions, false, "link depends", @@ -6382,6 +6447,7 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface( iface.AllDone = true; if (iface.Exists) { this->ComputeLinkInterface(config, iface, head, secondPass); + this->ComputeLinkInterfaceRuntimeLibraries(config, iface); } } @@ -6905,6 +6971,83 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( } } +namespace { + +template +ReturnType constructItem(cmGeneratorTarget* target, + cmListFileBacktrace const& bt); + +template <> +inline cmLinkImplItem constructItem(cmGeneratorTarget* target, + cmListFileBacktrace const& bt) +{ + return cmLinkImplItem(cmLinkItem(target, false, bt), false); +} + +template <> +inline cmLinkItem constructItem(cmGeneratorTarget* target, + cmListFileBacktrace const& bt) +{ + return cmLinkItem(target, false, bt); +} + +template +std::vector computeImplicitLanguageTargets( + std::string const& lang, std::string const& config, + cmGeneratorTarget const* currentTarget) +{ + cmListFileBacktrace bt; + std::vector result; + cmLocalGenerator* lg = currentTarget->GetLocalGenerator(); + + std::string const& runtimeLibrary = + currentTarget->GetRuntimeLinkLibrary(lang, config); + if (cmProp runtimeLinkOptions = currentTarget->Makefile->GetDefinition( + "CMAKE_" + lang + "_RUNTIME_LIBRARIES_" + runtimeLibrary)) { + std::vector libsVec = cmExpandedList(*runtimeLinkOptions); + result.reserve(libsVec.size()); + + for (std::string const& i : libsVec) { + cmGeneratorTarget::TargetOrString resolved = + currentTarget->ResolveTargetReference(i, lg); + if (resolved.Target) { + result.emplace_back(constructItem(resolved.Target, bt)); + } + } + } + + return result; +} +} + +void cmGeneratorTarget::ComputeLinkInterfaceRuntimeLibraries( + const std::string& config, cmOptionalLinkInterface& iface) const +{ + for (std::string const& lang : iface.Languages) { + if ((lang == "CUDA" || lang == "HIP") && + iface.LanguageRuntimeLibraries.find(lang) == + iface.LanguageRuntimeLibraries.end()) { + auto implicitTargets = + computeImplicitLanguageTargets(lang, config, this); + iface.LanguageRuntimeLibraries[lang] = std::move(implicitTargets); + } + } +} + +void cmGeneratorTarget::ComputeLinkImplementationRuntimeLibraries( + const std::string& config, cmOptionalLinkImplementation& impl) const +{ + for (std::string const& lang : impl.Languages) { + if ((lang == "CUDA" || lang == "HIP") && + impl.LanguageRuntimeLibraries.find(lang) == + impl.LanguageRuntimeLibraries.end()) { + auto implicitTargets = + computeImplicitLanguageTargets(lang, config, this); + impl.LanguageRuntimeLibraries[lang] = std::move(implicitTargets); + } + } +} + const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( const std::string& config, cmGeneratorTarget const* headTarget, bool usage_requirements_only, bool secondPass) const @@ -7169,6 +7312,7 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation( if (!impl.LanguagesDone) { impl.LanguagesDone = true; this->ComputeLinkImplementationLanguages(config, impl); + this->ComputeLinkImplementationRuntimeLibraries(config, impl); } return &impl; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index ab9ccfd58d8..ed66fb1a819 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1111,6 +1111,12 @@ class cmGeneratorTarget cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang, const char* suffix) const; + void ComputeLinkImplementationRuntimeLibraries( + const std::string& config, cmOptionalLinkImplementation& impl) const; + + void ComputeLinkInterfaceRuntimeLibraries( + const std::string& config, cmOptionalLinkInterface& iface) const; + public: const std::vector& GetLinkImplementationClosure( const std::string& config) const; diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index db44938a377..0863edd558e 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -80,6 +81,8 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries { // Languages whose runtime libraries must be linked. std::vector Languages; + std::unordered_map> + LanguageRuntimeLibraries; // Shared library dependencies needed for linking on some platforms. std::vector SharedDeps; @@ -115,6 +118,8 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries { // Languages whose runtime libraries must be linked. std::vector Languages; + std::unordered_map> + LanguageRuntimeLibraries; // Whether the list depends on a link language genex. bool HadLinkLanguageSensitiveCondition = false; diff --git a/Tests/HIP/CMakeLists.txt b/Tests/HIP/CMakeLists.txt index b3966c9ebf6..9499be8f6ca 100644 --- a/Tests/HIP/CMakeLists.txt +++ b/Tests/HIP/CMakeLists.txt @@ -7,6 +7,9 @@ endmacro () add_hip_test_macro(HIP.ArchitectureOff HIPOnlyArchitectureOff) add_hip_test_macro(HIP.CompileFlags HIPOnlyCompileFlags) add_hip_test_macro(HIP.EnableStandard HIPEnableStandard) +add_hip_test_macro(HIP.InferHipLang1 HIPInferHipLang1) +add_hip_test_macro(HIP.InferHipLang2 HIPInferHipLang2) add_hip_test_macro(HIP.MathFunctions HIPOnlyMathFunctions) +add_hip_test_macro(HIP.MixedLanguage HIPMixedLanguage) add_hip_test_macro(HIP.TryCompile HIPOnlyTryCompile) add_hip_test_macro(HIP.WithDefs HIPOnlyWithDefs) diff --git a/Tests/HIP/InferHipLang1/CMakeLists.txt b/Tests/HIP/InferHipLang1/CMakeLists.txt new file mode 100644 index 00000000000..63d77fdaa48 --- /dev/null +++ b/Tests/HIP/InferHipLang1/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.18) +project(InferHipLang C CXX HIP) + +#Goal for this example: +#make sure that we understand that HIP is the correct link language +add_library(InterfaceWithHIP INTERFACE) +target_sources(InterfaceWithHIP INTERFACE interface.hip main.cxx) +target_compile_features(InterfaceWithHIP INTERFACE hip_std_14) +target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11) + +add_executable(HIPInferHipLang1 ) +target_link_libraries(HIPInferHipLang1 PRIVATE InterfaceWithHIP) diff --git a/Tests/HIP/InferHipLang1/interface.hip b/Tests/HIP/InferHipLang1/interface.hip new file mode 100644 index 00000000000..6ac8641cca7 --- /dev/null +++ b/Tests/HIP/InferHipLang1/interface.hip @@ -0,0 +1,19 @@ +#include +#include +#include + +static __global__ void fake_hip_kernel() +{ +} + + +int __host__ interface_hip_func(int x) +{ + + fake_hip_kernel<<<1, 1>>>(); + bool valid = (hipSuccess == hipGetLastError()); + if (!valid) { + throw std::system_error(ENODEV, std::generic_category(), "no hip device"); + } + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/InferHipLang1/main.cxx b/Tests/HIP/InferHipLang1/main.cxx new file mode 100644 index 00000000000..987b6c65161 --- /dev/null +++ b/Tests/HIP/InferHipLang1/main.cxx @@ -0,0 +1,19 @@ + +#include + +#ifdef __HIP_PLATFORM_HCC__ +# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!" +#endif + +#ifdef __HIP_ROCclr__ +# error "__HIP_ROCclr__ propagated to C++ compilation!" +#endif + +int interface_hip_func(int); + +int main(int argc, char** argv) +{ + interface_hip_func(int(42)); + + return 0; +} diff --git a/Tests/HIP/InferHipLang2/CMakeLists.txt b/Tests/HIP/InferHipLang2/CMakeLists.txt new file mode 100644 index 00000000000..0e69de38fe8 --- /dev/null +++ b/Tests/HIP/InferHipLang2/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.18) +project(InferHipLang C CXX HIP) + +#Goal for this example: +#make sure that we understand that HIP is the correct link language +add_library(InterfaceWithHIP OBJECT) +target_sources(InterfaceWithHIP PRIVATE interface.hip main.cxx) +target_compile_features(InterfaceWithHIP INTERFACE hip_std_14) +target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11) + +add_executable(HIPInferHipLang2 ) +target_link_libraries(HIPInferHipLang2 PRIVATE InterfaceWithHIP) diff --git a/Tests/HIP/InferHipLang2/interface.hip b/Tests/HIP/InferHipLang2/interface.hip new file mode 100644 index 00000000000..6ac8641cca7 --- /dev/null +++ b/Tests/HIP/InferHipLang2/interface.hip @@ -0,0 +1,19 @@ +#include +#include +#include + +static __global__ void fake_hip_kernel() +{ +} + + +int __host__ interface_hip_func(int x) +{ + + fake_hip_kernel<<<1, 1>>>(); + bool valid = (hipSuccess == hipGetLastError()); + if (!valid) { + throw std::system_error(ENODEV, std::generic_category(), "no hip device"); + } + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/InferHipLang2/main.cxx b/Tests/HIP/InferHipLang2/main.cxx new file mode 100644 index 00000000000..987b6c65161 --- /dev/null +++ b/Tests/HIP/InferHipLang2/main.cxx @@ -0,0 +1,19 @@ + +#include + +#ifdef __HIP_PLATFORM_HCC__ +# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!" +#endif + +#ifdef __HIP_ROCclr__ +# error "__HIP_ROCclr__ propagated to C++ compilation!" +#endif + +int interface_hip_func(int); + +int main(int argc, char** argv) +{ + interface_hip_func(int(42)); + + return 0; +} diff --git a/Tests/HIP/MixedLanguage/CMakeLists.txt b/Tests/HIP/MixedLanguage/CMakeLists.txt new file mode 100644 index 00000000000..4f6dd3b0fb8 --- /dev/null +++ b/Tests/HIP/MixedLanguage/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.18) +project (MixedLanguage C CXX HIP) + +set(CMAKE_HIP_STANDARD 14) +set(CMAKE_CXX_STANDARD 14) + +#Goal for this example: +#make sure that we can build multiple languages into targets +#and have the link language always be HIP +add_library(MixedSharedLib SHARED shared.c) +add_library(MixedObjectLib OBJECT shared.cxx shared.hip) +set_target_properties(MixedObjectLib PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_link_libraries(MixedSharedLib PRIVATE MixedObjectLib) + +add_library(MixedStaticLib STATIC static.c static.cxx static.hip) +set_target_properties(MixedStaticLib PROPERTIES POSITION_INDEPENDENT_CODE ON) + +add_executable(HIPMixedLanguage main.cxx) +target_link_libraries(HIPMixedLanguage PRIVATE MixedStaticLib MixedSharedLib) diff --git a/Tests/HIP/MixedLanguage/main.cxx b/Tests/HIP/MixedLanguage/main.cxx new file mode 100644 index 00000000000..003d18ac4c5 --- /dev/null +++ b/Tests/HIP/MixedLanguage/main.cxx @@ -0,0 +1,40 @@ + +#include + +#ifdef __HIP_PLATFORM_HCC__ +# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!" +#endif + +#ifdef __HIP_ROCclr__ +# error "__HIP_ROCclr__ propagated to C++ compilation!" +#endif + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +#else +# define IMPORT +#endif + +extern "C" { +IMPORT int shared_c_func(int); +int static_c_func(int); +} + +IMPORT int shared_cxx_func(int); +IMPORT int shared_hip_func(int); + +int static_cxx_func(int); +int static_hip_func(int); + +int main(int argc, char** argv) +{ + static_c_func(int(42)); + static_cxx_func(int(42)); + static_hip_func(int(42)); + + shared_c_func(int(42)); + shared_cxx_func(int(42)); + shared_hip_func(int(42)); + + return 0; +} diff --git a/Tests/HIP/MixedLanguage/shared.c b/Tests/HIP/MixedLanguage/shared.c new file mode 100644 index 00000000000..347fba9255e --- /dev/null +++ b/Tests/HIP/MixedLanguage/shared.c @@ -0,0 +1,12 @@ + + +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +EXPORT int shared_c_func(int x) +{ + return -x; +} diff --git a/Tests/HIP/MixedLanguage/shared.cxx b/Tests/HIP/MixedLanguage/shared.cxx new file mode 100644 index 00000000000..8e6c1d35f85 --- /dev/null +++ b/Tests/HIP/MixedLanguage/shared.cxx @@ -0,0 +1,21 @@ + +#include + +#ifdef __HIP_PLATFORM_HCC__ +# error "__HIP_PLATFORM_HCC__ propagated to C++ compilation!" +#endif + +#ifdef __HIP_ROCclr__ +# error "__HIP_ROCclr__ propagated to C++ compilation!" +#endif + +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +EXPORT int shared_cxx_func(int x) +{ + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/MixedLanguage/shared.hip b/Tests/HIP/MixedLanguage/shared.hip new file mode 100644 index 00000000000..e6fea9fe21d --- /dev/null +++ b/Tests/HIP/MixedLanguage/shared.hip @@ -0,0 +1,26 @@ +#include +#include +#include + +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + + +static __global__ void fake_hip_kernel() +{ +} + + +int __host__ shared_hip_func(int x) +{ + + fake_hip_kernel<<<1, 1>>>(); + bool valid = (hipSuccess == hipGetLastError()); + if (!valid) { + throw std::system_error(ENODEV, std::generic_category(), "no hip device"); + } + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/MixedLanguage/static.c b/Tests/HIP/MixedLanguage/static.c new file mode 100644 index 00000000000..06c33b4cc7b --- /dev/null +++ b/Tests/HIP/MixedLanguage/static.c @@ -0,0 +1,6 @@ + + +int static_c_func(int x) +{ + return -x; +} diff --git a/Tests/HIP/MixedLanguage/static.cxx b/Tests/HIP/MixedLanguage/static.cxx new file mode 100644 index 00000000000..2c14fb10180 --- /dev/null +++ b/Tests/HIP/MixedLanguage/static.cxx @@ -0,0 +1,7 @@ + +#include + +int static_cxx_func(int x) +{ + return x * x + std::integral_constant::value; +} diff --git a/Tests/HIP/MixedLanguage/static.hip b/Tests/HIP/MixedLanguage/static.hip new file mode 100644 index 00000000000..359b9facdac --- /dev/null +++ b/Tests/HIP/MixedLanguage/static.hip @@ -0,0 +1,21 @@ + +#include +#include +#include + + +static __global__ void fake_hip_kernel() +{ +} + + +int __host__ static_hip_func(int x) +{ + + fake_hip_kernel<<<1, 1>>>(); + bool valid = (hipSuccess == hipGetLastError()); + if (!valid) { + throw std::system_error(ENODEV, std::generic_category(), "no hip device"); + } + return x * x + std::integral_constant::value; +} From 2e86e50c2fb2897dc1a0612676c5bd26eb7924a9 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Sun, 25 Oct 2020 14:34:18 -0400 Subject: [PATCH 0620/1519] HIP: Add HIP to all the Check* modules --- Modules/CheckLinkerFlag.cmake | 2 ++ Modules/Internal/CheckCompilerFlag.cmake | 3 +++ Modules/Internal/CheckSourceCompiles.cmake | 3 +++ Modules/Internal/CheckSourceRuns.cmake | 3 +++ Tests/RunCMake/CMakeLists.txt | 18 ++++++++++--- .../CheckHIPCompilerFlag.cmake | 13 +++++++++ .../CheckCompilerFlag/RunCMakeTest.cmake | 4 +++ .../CheckLinkerFlag/CheckHIPLinkerFlag.cmake | 3 +++ .../CheckLinkerFlag/RunCMakeTest.cmake | 4 +++ .../CheckHIPSourceCompiles.cmake | 27 +++++++++++++++++++ .../CheckSourceCompiles/RunCMakeTest.cmake | 4 +++ .../CheckSourceRuns/CheckHIPSourceRuns.cmake | 21 +++++++++++++++ .../CheckSourceRuns/RunCMakeTest.cmake | 4 +++ 13 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake create mode 100644 Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake create mode 100644 Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake create mode 100644 Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake diff --git a/Modules/CheckLinkerFlag.cmake b/Modules/CheckLinkerFlag.cmake index 3c7a8286e12..28ac2e32e2e 100644 --- a/Modules/CheckLinkerFlag.cmake +++ b/Modules/CheckLinkerFlag.cmake @@ -65,6 +65,8 @@ function(CHECK_LINKER_FLAG _lang _flag _var) set (_source " program test\n stop\n end program") elseif (_lang MATCHES "CUDA") set (_source "__host__ int main() { return 0; }") + elseif (_lang MATCHES "HIP") + set (_source "__host__ int main() { return 0; }") elseif (_lang MATCHES "^(OBJC|OBJCXX)$") set (_source "#ifndef __OBJC__\n# error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }") else() diff --git a/Modules/Internal/CheckCompilerFlag.cmake b/Modules/Internal/CheckCompilerFlag.cmake index 6b2a11e5664..9eb1bf0f81b 100644 --- a/Modules/Internal/CheckCompilerFlag.cmake +++ b/Modules/Internal/CheckCompilerFlag.cmake @@ -24,6 +24,9 @@ function(CMAKE_CHECK_COMPILER_FLAG _lang _flag _var) elseif(_lang STREQUAL "Fortran") set(_lang_src " program test\n stop\n end program") set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for Fortran") + elseif(_lang STREQUAL "HIP") + set(_lang_src "__host__ int main() { return 0; }") + set(_lang_fail_regex FAIL_REGEX "argument unused during compilation: .*") # Clang elseif(_lang STREQUAL "OBJC") set(_lang_src [=[ #ifndef __OBJC__ diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake index 3b2152ae541..8c3a41863f2 100644 --- a/Modules/Internal/CheckSourceCompiles.cmake +++ b/Modules/Internal/CheckSourceCompiles.cmake @@ -22,6 +22,9 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) elseif(_lang STREQUAL "Fortran") set(_lang_textual "Fortran") set(_lang_ext "F90") + elseif(_lang STREQUAL "HIP") + set(_lang_textual "HIP") + set(_lang_ext "hip") elseif(_lang STREQUAL "ISPC") set(_lang_textual "ISPC") set(_lang_ext "ispc") diff --git a/Modules/Internal/CheckSourceRuns.cmake b/Modules/Internal/CheckSourceRuns.cmake index 676f3d01600..75e98960f3d 100644 --- a/Modules/Internal/CheckSourceRuns.cmake +++ b/Modules/Internal/CheckSourceRuns.cmake @@ -22,6 +22,9 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) elseif(_lang STREQUAL "Fortran") set(_lang_textual "Fortran") set(_lang_ext "F90") + elseif(_lang STREQUAL "HIP") + set(_lang_textual "HIP") + set(_lang_ext "hip") elseif(_lang STREQUAL "OBJC") set(_lang_textual "Objective-C") set(_lang_ext "m") diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 16487f3831f..dcf1e724753 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -452,6 +452,7 @@ function(add_RunCMake_test_try_compile) CMAKE_CXX_STANDARD_DEFAULT CMake_TEST_CUDA CMake_TEST_ISPC + CMake_TEST_HIP CMake_TEST_FILESYSTEM_1S CMAKE_OBJC_STANDARD_DEFAULT CMAKE_OBJCXX_STANDARD_DEFAULT @@ -600,12 +601,15 @@ add_RunCMake_test(target_include_directories) add_RunCMake_test(target_sources) add_RunCMake_test(CheckCompilerFlag -DCMake_TEST_CUDA=${CMake_TEST_CUDA} -DCMake_TEST_ISPC=${CMake_TEST_ISPC} - -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}) + -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID} + -DCMake_TEST_HIP=${CMake_TEST_HIP}) add_RunCMake_test(CheckSourceCompiles -DCMake_TEST_CUDA=${CMake_TEST_CUDA} -DCMake_TEST_ISPC=${CMake_TEST_ISPC} - -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}) + -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID} + -DCMake_TEST_HIP=${CMake_TEST_HIP}) add_RunCMake_test(CheckSourceRuns -DCMake_TEST_CUDA=${CMake_TEST_CUDA} - -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}) + -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID} + -DCMake_TEST_HIP=${CMake_TEST_HIP}) set_property(TEST RunCMake.CheckCompilerFlag RunCMake.CheckSourceCompiles RunCMake.CheckSourceRuns @@ -613,14 +617,20 @@ set_property(TEST RunCMake.CheckCompilerFlag set_property(TEST RunCMake.CheckSourceCompiles RunCMake.CheckCompilerFlag APPEND PROPERTY LABELS "ISPC") +set_property(TEST RunCMake.CheckCompilerFlag + RunCMake.CheckSourceCompiles + RunCMake.CheckSourceRuns + APPEND PROPERTY LABELS "HIP") add_RunCMake_test(CheckModules) add_RunCMake_test(CheckIPOSupported) if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)" AND (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU" OR CMAKE_Fortran_COMPILER_ID MATCHES "GNU")) add_RunCMake_test(CheckLinkerFlag -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID} - -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) + -DCMake_TEST_CUDA=${CMake_TEST_CUDA} + -DCMake_TEST_HIP=${CMake_TEST_HIP}) set_property(TEST RunCMake.CheckLinkerFlag APPEND PROPERTY LABELS "CUDA") + set_property(TEST RunCMake.CheckLinkerFlag APPEND PROPERTY LABELS "HIP") endif() diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake new file mode 100644 index 00000000000..339ce1865b9 --- /dev/null +++ b/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake @@ -0,0 +1,13 @@ + +enable_language (HIP) +include(CheckCompilerFlag) + +check_compiler_flag(HIP "-_this_is_not_a_flag_" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid HIP compile flag didn't fail.") +endif() + +check_compiler_flag(HIP "-DFOO" SHOULD_WORK) +if(NOT SHOULD_WORK) + message(SEND_ERROR "${CMAKE_HIP_COMPILER_ID} compiler flag '-DFOO' check failed") +endif() diff --git a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake index 7a4e2cebb60..7ef1860c6a8 100644 --- a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake @@ -22,3 +22,7 @@ endif() if(CMake_TEST_ISPC) run_cmake(CheckISPCCompilerFlag) endif() + +if(CMake_TEST_HIP) + run_cmake(CheckHIPCompilerFlag) +endif() diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake new file mode 100644 index 00000000000..3bf3b3051e9 --- /dev/null +++ b/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake @@ -0,0 +1,3 @@ + +set (CHECK_LANGUAGE HIP) +include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake") diff --git a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake index 6ec914806ca..5e5bff6c90e 100644 --- a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake @@ -16,3 +16,7 @@ endif() if (CMake_TEST_CUDA) run_cmake(CheckCUDALinkerFlag) endif() + +if (CMake_TEST_HIP) + run_cmake(CheckHIPLinkerFlag) +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake new file mode 100644 index 00000000000..911a0d7b9ba --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake @@ -0,0 +1,27 @@ + +enable_language (HIP) +include(CheckSourceCompiles) + +check_source_compiles(HIP "I don't build" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid HIP source didn't fail.") +endif() + +check_source_compiles(HIP [=[ + #include + __device__ int d_func() { } + int main() { + return 0; + } +]=] + SHOULD_BUILD) +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid HIP source.") +endif() + +check_source_compiles(HIP "void l(char const (&x)[2]){}; int main() { l(\"\\n\"); return 0;}" + SHOULD_BUILD_COMPLEX) + +if(NOT SHOULD_BUILD_COMPLEX) + message(SEND_ERROR "Test fail for valid HIP complex source.") +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake index 6e9088f8243..530f133da01 100644 --- a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake @@ -23,3 +23,7 @@ endif() if(CMake_TEST_ISPC) run_cmake(CheckISPCSourceCompiles) endif() + +if(CMake_TEST_HIP) + run_cmake(CheckHIPSourceCompiles) +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake new file mode 100644 index 00000000000..d9fb8c22a6b --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake @@ -0,0 +1,21 @@ + +enable_language (HIP) +include(CheckSourceRuns) + +check_source_runs(HIP "int main() {return 2;}" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "HIP check_source_runs succeeded, but should have failed.") +endif() + +check_source_runs(HIP +[=[ + #include + __device__ __host__ void fake_function(); + __host__ int main() { + return 0; + } +]=] + SHOULD_RUN) +if(NOT SHOULD_RUN) + message(SEND_ERROR "HIP check_source_runs failed for valid HIP executable.") +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake index c99ac8be296..47841033705 100644 --- a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake @@ -19,3 +19,7 @@ endif() if (CMake_TEST_CUDA) run_cmake(CheckCUDASourceRuns) endif() + +if (CMake_TEST_HIP) + run_cmake(CheckHIPSourceRuns) +endif() From 20d086f1a2c320da59830682a19e006ec19dca94 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 26 Oct 2020 21:10:18 +0000 Subject: [PATCH 0621/1519] HIP: All HIP tests now run on CMake's current AMD hardware --- Tests/HIP/InferHipLang1/CMakeLists.txt | 1 + Tests/HIP/InferHipLang2/CMakeLists.txt | 1 + Tests/HIP/MathFunctions/CMakeLists.txt | 1 + Tests/HIP/MixedLanguage/CMakeLists.txt | 1 + Tests/HIP/TryCompile/CMakeLists.txt | 1 + Tests/HIP/WithDefs/CMakeLists.txt | 1 + 6 files changed, 6 insertions(+) diff --git a/Tests/HIP/InferHipLang1/CMakeLists.txt b/Tests/HIP/InferHipLang1/CMakeLists.txt index 63d77fdaa48..f3c54216c12 100644 --- a/Tests/HIP/InferHipLang1/CMakeLists.txt +++ b/Tests/HIP/InferHipLang1/CMakeLists.txt @@ -10,3 +10,4 @@ target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11) add_executable(HIPInferHipLang1 ) target_link_libraries(HIPInferHipLang1 PRIVATE InterfaceWithHIP) +set_property(TARGET HIPInferHipLang1 PROPERTY HIP_ARCHITECTURES gfx900) diff --git a/Tests/HIP/InferHipLang2/CMakeLists.txt b/Tests/HIP/InferHipLang2/CMakeLists.txt index 0e69de38fe8..a8a55b7b0a6 100644 --- a/Tests/HIP/InferHipLang2/CMakeLists.txt +++ b/Tests/HIP/InferHipLang2/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(InterfaceWithHIP OBJECT) target_sources(InterfaceWithHIP PRIVATE interface.hip main.cxx) target_compile_features(InterfaceWithHIP INTERFACE hip_std_14) target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11) +set_property(TARGET InterfaceWithHIP PROPERTY HIP_ARCHITECTURES gfx900) add_executable(HIPInferHipLang2 ) target_link_libraries(HIPInferHipLang2 PRIVATE InterfaceWithHIP) diff --git a/Tests/HIP/MathFunctions/CMakeLists.txt b/Tests/HIP/MathFunctions/CMakeLists.txt index 81e3ddb26f2..69d63dd0a1f 100644 --- a/Tests/HIP/MathFunctions/CMakeLists.txt +++ b/Tests/HIP/MathFunctions/CMakeLists.txt @@ -13,6 +13,7 @@ project(MathFunctions HIP) # 3. This makes sure CMake properly links to all the built-in libraries # that hip needs that inject support for __half support # +set(CMAKE_HIP_ARCHITECTURES "gfx900") add_executable(HIPOnlyMathFunctions main.hip) target_compile_options(HIPOnlyMathFunctions PRIVATE -Werror) target_compile_features(HIPOnlyMathFunctions PRIVATE hip_std_14) diff --git a/Tests/HIP/MixedLanguage/CMakeLists.txt b/Tests/HIP/MixedLanguage/CMakeLists.txt index 4f6dd3b0fb8..ce2ff899353 100644 --- a/Tests/HIP/MixedLanguage/CMakeLists.txt +++ b/Tests/HIP/MixedLanguage/CMakeLists.txt @@ -3,6 +3,7 @@ project (MixedLanguage C CXX HIP) set(CMAKE_HIP_STANDARD 14) set(CMAKE_CXX_STANDARD 14) +set(CMAKE_HIP_ARCHITECTURES "gfx900") #Goal for this example: #make sure that we can build multiple languages into targets diff --git a/Tests/HIP/TryCompile/CMakeLists.txt b/Tests/HIP/TryCompile/CMakeLists.txt index f3bb3bf99d5..92a834c61b3 100644 --- a/Tests/HIP/TryCompile/CMakeLists.txt +++ b/Tests/HIP/TryCompile/CMakeLists.txt @@ -4,6 +4,7 @@ project (TryCompile HIP) #Goal for this example: # Verify try_compile with HIP language works set(CMAKE_HIP_STANDARD 14) +set(CMAKE_HIP_ARCHITECTURES gfx803 gfx900) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) try_compile(result "${CMAKE_CURRENT_BINARY_DIR}" diff --git a/Tests/HIP/WithDefs/CMakeLists.txt b/Tests/HIP/WithDefs/CMakeLists.txt index 3d4461b6b51..e2db1820a74 100644 --- a/Tests/HIP/WithDefs/CMakeLists.txt +++ b/Tests/HIP/WithDefs/CMakeLists.txt @@ -17,6 +17,7 @@ target_compile_features(HIPOnlyWithDefs PRIVATE hip_std_17) target_compile_options(HIPOnlyWithDefs PRIVATE + --offload-arch=gfx900 -DFLAG_COMPILE_LANG_$ $<$:-DFLAG_LANG_IS_HIP=$> # Host-only defines are possible only on NVCC. ) From 8514ee9b315b4ad02eed0e3cf11d8579f307fac0 Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Thu, 27 May 2021 18:03:51 +0000 Subject: [PATCH 0622/1519] HIP: analyze output of `hipcc` to determine default GPU architecture --- Help/prop_tgt/HIP_ARCHITECTURES.rst | 5 +++-- Help/variable/CMAKE_HIP_ARCHITECTURES.rst | 2 +- Modules/CMakeDetermineHIPCompiler.cmake | 7 ++++++- Source/cmGeneratorTarget.cxx | 6 ++++++ Tests/HIP/InferHipLang1/CMakeLists.txt | 1 - Tests/HIP/InferHipLang2/CMakeLists.txt | 1 - Tests/HIP/MathFunctions/CMakeLists.txt | 1 - Tests/HIP/MixedLanguage/CMakeLists.txt | 1 - 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Help/prop_tgt/HIP_ARCHITECTURES.rst b/Help/prop_tgt/HIP_ARCHITECTURES.rst index 052f472d363..06f956b18e6 100644 --- a/Help/prop_tgt/HIP_ARCHITECTURES.rst +++ b/Help/prop_tgt/HIP_ARCHITECTURES.rst @@ -5,8 +5,9 @@ HIP_ARCHITECTURES List of AMD GPU architectures to generate device code for. -An empty or false value (e.g. ``OFF``) defers architecture generation to compiler -defaults. +A non-empty false value (e.g. ``OFF``) disables adding architectures. +This is intended to support packagers and rare cases where full control +over the passed flags is required. This property is initialized by the value of the :variable:`CMAKE_HIP_ARCHITECTURES` variable if it is set when a target is created. diff --git a/Help/variable/CMAKE_HIP_ARCHITECTURES.rst b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst index 333f0213cbf..0cf020136c6 100644 --- a/Help/variable/CMAKE_HIP_ARCHITECTURES.rst +++ b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst @@ -5,7 +5,7 @@ CMAKE_HIP_ARCHITECTURES Default value for :prop_tgt:`HIP_ARCHITECTURES` property of targets. -This is initialized to ``OFF``. +This is initialized to the default architecture chosen by the compiler. This variable is used to initialize the :prop_tgt:`HIP_ARCHITECTURES` property on all targets. See the target property for additional information. diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake index 87885c0c3cd..ed0110ae2ca 100644 --- a/Modules/CMakeDetermineHIPCompiler.cmake +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -85,7 +85,12 @@ if(MSVC_HIP_ARCHITECTURE_ID) endif() if(NOT DEFINED CMAKE_HIP_ARCHITECTURES) - set(CMAKE_HIP_ARCHITECTURES "OFF" CACHE STRING "HIP architectures") + # Analyze output from hipcc to get the current GPU architecture. + if(CMAKE_HIP_COMPILER_PRODUCED_OUTPUT MATCHES " -target-cpu ([a-z0-9]+) ") + set(CMAKE_HIP_ARCHITECTURES "${CMAKE_MATCH_1}" CACHE STRING "HIP architectures") + else() + message(FATAL_ERROR "Failed to find a working HIP architecture.") + endif() endif() # configure variables set in this file for fast reload later on diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index cb10117704a..f268c6c3e6f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3419,6 +3419,12 @@ void cmGeneratorTarget::AddHIPArchitectureFlags(std::string& flags) const { const std::string& property = this->GetSafeProperty("HIP_ARCHITECTURES"); + if (property.empty()) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "HIP_ARCHITECTURES is empty for target \"" + + this->GetName() + "\"."); + } + // If HIP_ARCHITECTURES is false we don't add any architectures. if (cmIsOff(property)) { return; diff --git a/Tests/HIP/InferHipLang1/CMakeLists.txt b/Tests/HIP/InferHipLang1/CMakeLists.txt index f3c54216c12..63d77fdaa48 100644 --- a/Tests/HIP/InferHipLang1/CMakeLists.txt +++ b/Tests/HIP/InferHipLang1/CMakeLists.txt @@ -10,4 +10,3 @@ target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11) add_executable(HIPInferHipLang1 ) target_link_libraries(HIPInferHipLang1 PRIVATE InterfaceWithHIP) -set_property(TARGET HIPInferHipLang1 PROPERTY HIP_ARCHITECTURES gfx900) diff --git a/Tests/HIP/InferHipLang2/CMakeLists.txt b/Tests/HIP/InferHipLang2/CMakeLists.txt index a8a55b7b0a6..0e69de38fe8 100644 --- a/Tests/HIP/InferHipLang2/CMakeLists.txt +++ b/Tests/HIP/InferHipLang2/CMakeLists.txt @@ -7,7 +7,6 @@ add_library(InterfaceWithHIP OBJECT) target_sources(InterfaceWithHIP PRIVATE interface.hip main.cxx) target_compile_features(InterfaceWithHIP INTERFACE hip_std_14) target_compile_features(InterfaceWithHIP INTERFACE cxx_std_11) -set_property(TARGET InterfaceWithHIP PROPERTY HIP_ARCHITECTURES gfx900) add_executable(HIPInferHipLang2 ) target_link_libraries(HIPInferHipLang2 PRIVATE InterfaceWithHIP) diff --git a/Tests/HIP/MathFunctions/CMakeLists.txt b/Tests/HIP/MathFunctions/CMakeLists.txt index 69d63dd0a1f..81e3ddb26f2 100644 --- a/Tests/HIP/MathFunctions/CMakeLists.txt +++ b/Tests/HIP/MathFunctions/CMakeLists.txt @@ -13,7 +13,6 @@ project(MathFunctions HIP) # 3. This makes sure CMake properly links to all the built-in libraries # that hip needs that inject support for __half support # -set(CMAKE_HIP_ARCHITECTURES "gfx900") add_executable(HIPOnlyMathFunctions main.hip) target_compile_options(HIPOnlyMathFunctions PRIVATE -Werror) target_compile_features(HIPOnlyMathFunctions PRIVATE hip_std_14) diff --git a/Tests/HIP/MixedLanguage/CMakeLists.txt b/Tests/HIP/MixedLanguage/CMakeLists.txt index ce2ff899353..4f6dd3b0fb8 100644 --- a/Tests/HIP/MixedLanguage/CMakeLists.txt +++ b/Tests/HIP/MixedLanguage/CMakeLists.txt @@ -3,7 +3,6 @@ project (MixedLanguage C CXX HIP) set(CMAKE_HIP_STANDARD 14) set(CMAKE_CXX_STANDARD 14) -set(CMAKE_HIP_ARCHITECTURES "gfx900") #Goal for this example: #make sure that we can build multiple languages into targets From 100d3cb392679f2531ede8e3f3e944b13124cfda Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Mon, 7 Jun 2021 15:35:12 -0400 Subject: [PATCH 0623/1519] file(GET_RUNTIME_DEPENDENCIES): Use cmSystemTools::GetLineFromStream() Fixes: #22278 --- .../cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx index 1effda053c1..f14de5596b4 100644 --- a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx +++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx @@ -8,6 +8,7 @@ #include #include "cmRuntimeDependencyArchive.h" +#include "cmSystemTools.h" #include "cmUVProcessChain.h" cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool:: @@ -42,8 +43,8 @@ bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo( std::string line; static const cmsys::RegularExpression regex( - "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])\r$"); - while (std::getline(*process.OutputStream(), line)) { + "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])$"); + while (cmSystemTools::GetLineFromStream(*process.OutputStream(), line)) { cmsys::RegularExpressionMatch match; if (regex.find(line.c_str(), match)) { needed.push_back(match.match(1)); From 4c940e50bf0233accd68aa2f202d36dd956da18e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 8 Jun 2021 00:01:10 -0400 Subject: [PATCH 0624/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3fd94d6c638..7915a9cce43 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210607) +set(CMake_VERSION_PATCH 20210608) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 93e396b402d8736bd3c7a0a9b61113ceff819144 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 07:09:31 -0400 Subject: [PATCH 0625/1519] presets: Fix buildPreset "jobs" field test case Avoid passing parallel build options to Make tools that do not support them. --- Tests/RunCMake/CMakeLists.txt | 16 +++++++++++++--- Tests/RunCMake/CMakePresetsBuild/Good.json.in | 2 +- .../CMakePresetsBuild/RunCMakeTest.cmake | 8 ++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 78e0b6aee04..c81796cfa11 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -809,9 +809,19 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}) add_RunCMake_test("UnityBuild") -add_RunCMake_test(CMakePresets -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}) -add_RunCMake_test(CMakePresetsBuild -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}) -add_RunCMake_test(CMakePresetsTest -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA}) +add_RunCMake_test(CMakePresets + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} + ) +add_RunCMake_test(CMakePresetsBuild + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} + -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + ) +add_RunCMake_test(CMakePresetsTest + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} + ) if(${CMAKE_GENERATOR} MATCHES "Make|Ninja") add_RunCMake_test(TransformDepfile) diff --git a/Tests/RunCMake/CMakePresetsBuild/Good.json.in b/Tests/RunCMake/CMakePresetsBuild/Good.json.in index fd43c4e6037..8acd6f474ab 100644 --- a/Tests/RunCMake/CMakePresetsBuild/Good.json.in +++ b/Tests/RunCMake/CMakePresetsBuild/Good.json.in @@ -30,7 +30,7 @@ "description": "", "inheritConfigureEnvironment": true, "environment": {}, - "jobs": 0, + @Good_json_jobs@ "targets": [], "configuration": "", "verbose": true, diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake index 2559b12a791..f6ca6c5351a 100644 --- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake @@ -62,6 +62,14 @@ endfunction() set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) +if(RunCMake_GENERATOR MATCHES "NMake|Borland|Watcom") + set(Good_json_jobs [[]]) +elseif(RunCMake_GENERATOR MATCHES "Make" AND CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set(Good_json_jobs [["jobs": 1,]]) +else() + set(Good_json_jobs [["jobs": 0,]]) +endif() + run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject") run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset") From 5d67632813d8f086fb6d2ec26d5bad495aa0d876 Mon Sep 17 00:00:00 2001 From: Sam Freed Date: Thu, 3 Jun 2021 15:32:55 -0700 Subject: [PATCH 0626/1519] presets: Fix buildPreset "jobs" Fixes: #22273 --- Source/cmake.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 4d03821161c..db8600fc730 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3164,7 +3164,9 @@ int cmake::Build(int jobs, std::string dir, std::vector targets, this->UnprocessedPresetEnvironment = expandedPreset->Environment; this->ProcessPresetEnvironment(); - if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL && expandedPreset->Jobs) { + if ((jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL || + jobs == cmake::NO_BUILD_PARALLEL_LEVEL) && + expandedPreset->Jobs) { jobs = *expandedPreset->Jobs; } From 534c40e6d8801853c19435a8c2d732ca2b01b606 Mon Sep 17 00:00:00 2001 From: Sam Freed Date: Thu, 3 Jun 2021 15:33:58 -0700 Subject: [PATCH 0627/1519] presets: Fix buildPreset "targets" not allowing a single string Fixes: #22272 --- Source/cmCMakePresetsFile.cxx | 17 ++++++++++------- Tests/RunCMake/CMakePresetsBuild/Good.json.in | 5 +++++ .../CMakePresetsBuild/RunCMakeTest.cmake | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index dda366146e0..16c2ed3d5b9 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -184,8 +184,8 @@ auto const PresetVectorStringHelper = ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetStringHelper); -ReadFileResult PresetInheritsHelper(std::vector& out, - const Json::Value* value) +ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector& out, + const Json::Value* value) { out.clear(); if (!value) { @@ -312,8 +312,8 @@ auto const ConfigurePresetHelper = cmJSONObjectHelper( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper) - .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper, - false) + .Bind("inherits"_s, &ConfigurePreset::Inherits, + PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false) .Bind("vendor"_s, nullptr, VendorHelper(ReadFileResult::INVALID_PRESET), false) @@ -340,7 +340,8 @@ auto const BuildPresetHelper = cmJSONObjectHelper( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &BuildPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, false) + .Bind("inherits"_s, &BuildPreset::Inherits, + PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false) .Bind("vendor"_s, nullptr, VendorHelper(ReadFileResult::INVALID_PRESET), false) @@ -356,7 +357,8 @@ auto const BuildPresetHelper = &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper, false) .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false) - .Bind("targets"_s, &BuildPreset::Targets, PresetVectorStringHelper, false) + .Bind("targets"_s, &BuildPreset::Targets, + PresetVectorOneOrMoreStringHelper, false) .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper, false) .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper, @@ -657,7 +659,8 @@ auto const TestPresetHelper = cmJSONObjectHelper( ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) .Bind("name"_s, &TestPreset::Name, PresetStringHelper) - .Bind("inherits"_s, &TestPreset::Inherits, PresetInheritsHelper, false) + .Bind("inherits"_s, &TestPreset::Inherits, + PresetVectorOneOrMoreStringHelper, false) .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false) .Bind("vendor"_s, nullptr, VendorHelper(ReadFileResult::INVALID_PRESET), false) diff --git a/Tests/RunCMake/CMakePresetsBuild/Good.json.in b/Tests/RunCMake/CMakePresetsBuild/Good.json.in index 8acd6f474ab..c7f318ceda3 100644 --- a/Tests/RunCMake/CMakePresetsBuild/Good.json.in +++ b/Tests/RunCMake/CMakePresetsBuild/Good.json.in @@ -73,6 +73,11 @@ "vendor": { "example.com": "value" } + }, + { + "name": "singleTarget", + "inherits": "build-default", + "targets": "good" } ] } diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake index f6ca6c5351a..a05ad9ffd71 100644 --- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake @@ -70,7 +70,7 @@ else() set(Good_json_jobs [["jobs": 0,]]) endif() -run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject") +run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject;singleTarget") run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset") set(CMakePresetsBuild_BUILD_ONLY 1) From 6d4c51c29edfa663fce8f858e4ef0a5abf4f2e85 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 08:48:09 -0400 Subject: [PATCH 0628/1519] IRSL: Add Intel oneAPI redist location on Windows Fixes: #22283 --- Modules/InstallRequiredSystemLibraries.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index 2d08e084579..fa7b125f904 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -80,7 +80,9 @@ foreach(LANG IN ITEMS C CXX Fortran) set(_Intel_archdir ia32) endif() set(_Intel_compiler_ver ${CMAKE_${LANG}_COMPILER_VERSION}) - if(WIN32) + if(WIN32 AND EXISTS "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler") + get_filename_component(_Intel_redistdir "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler" ABSOLUTE) + elseif(WIN32) get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" ABSOLUTE) elseif(APPLE) get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib" ABSOLUTE) From fda060f030f57c52028d38985edc95a74d0243a5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 7 Jun 2021 19:48:42 -0400 Subject: [PATCH 0629/1519] LexerParser: Do not leak Fortran parser tokens discarded due to errors --- Source/LexerParser/cmFortranParser.cxx | 134 ++++++++++++++----------- Source/LexerParser/cmFortranParser.y | 2 + 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 0ea3d971e6a..3f3dddeb4e7 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -599,13 +599,13 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 99, 99, 99, 102, 106, 111, 120, 126, 133, - 138, 142, 147, 155, 160, 165, 170, 175, 180, 185, - 190, 195, 199, 203, 207, 211, 212, 217, 217, 217, - 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, - 223, 223, 224, 224, 225, 225, 226, 226, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245 + 0, 101, 101, 101, 104, 108, 113, 122, 128, 135, + 140, 144, 149, 157, 162, 167, 172, 177, 182, 187, + 192, 197, 201, 205, 209, 213, 214, 219, 219, 219, + 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, + 225, 225, 226, 226, 227, 227, 228, 228, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247 }; #endif @@ -1364,7 +1364,29 @@ yydestruct (const char *yymsg, YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); + switch (yykind) + { + case YYSYMBOL_STRING: /* STRING */ +#line 95 "cmFortranParser.y" + { free(((*yyvaluep).string)); } +#line 1373 "cmFortranParser.cxx" + break; + + case YYSYMBOL_WORD: /* WORD */ +#line 95 "cmFortranParser.y" + { free(((*yyvaluep).string)); } +#line 1379 "cmFortranParser.cxx" + break; + + case YYSYMBOL_CPP_INCLUDE_ANGLE: /* CPP_INCLUDE_ANGLE */ +#line 95 "cmFortranParser.y" + { free(((*yyvaluep).string)); } +#line 1385 "cmFortranParser.cxx" + break; + + default: + break; + } YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1634,26 +1656,26 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); switch (yyn) { case 4: /* stmt: INTERFACE EOSTMT */ -#line 102 "cmFortranParser.y" +#line 104 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1643 "cmFortranParser.cxx" +#line 1665 "cmFortranParser.cxx" break; case 5: /* stmt: USE WORD other EOSTMT */ -#line 106 "cmFortranParser.y" +#line 108 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1653 "cmFortranParser.cxx" +#line 1675 "cmFortranParser.cxx" break; case 6: /* stmt: MODULE WORD other EOSTMT */ -#line 111 "cmFortranParser.y" +#line 113 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1663,22 +1685,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); } free((yyvsp[-2].string)); } -#line 1667 "cmFortranParser.cxx" +#line 1689 "cmFortranParser.cxx" break; case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */ -#line 120 "cmFortranParser.y" +#line 122 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1678 "cmFortranParser.cxx" +#line 1700 "cmFortranParser.cxx" break; case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */ -#line 126 "cmFortranParser.y" +#line 128 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); @@ -1686,40 +1708,40 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1690 "cmFortranParser.cxx" +#line 1712 "cmFortranParser.cxx" break; case 9: /* stmt: INTERFACE WORD other EOSTMT */ -#line 133 "cmFortranParser.y" +#line 135 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1700 "cmFortranParser.cxx" +#line 1722 "cmFortranParser.cxx" break; case 10: /* stmt: END INTERFACE other EOSTMT */ -#line 138 "cmFortranParser.y" +#line 140 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1709 "cmFortranParser.cxx" +#line 1731 "cmFortranParser.cxx" break; case 11: /* stmt: USE DCOLON WORD other EOSTMT */ -#line 142 "cmFortranParser.y" +#line 144 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1719 "cmFortranParser.cxx" +#line 1741 "cmFortranParser.cxx" break; case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */ -#line 147 "cmFortranParser.y" +#line 149 "cmFortranParser.y" { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1728,139 +1750,139 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1732 "cmFortranParser.cxx" +#line 1754 "cmFortranParser.cxx" break; case 13: /* stmt: INCLUDE STRING other EOSTMT */ -#line 155 "cmFortranParser.y" +#line 157 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1742 "cmFortranParser.cxx" +#line 1764 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ -#line 160 "cmFortranParser.y" +#line 162 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1752 "cmFortranParser.cxx" +#line 1774 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ -#line 165 "cmFortranParser.y" +#line 167 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1762 "cmFortranParser.cxx" +#line 1784 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ -#line 170 "cmFortranParser.y" +#line 172 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1772 "cmFortranParser.cxx" +#line 1794 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ -#line 175 "cmFortranParser.y" +#line 177 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1782 "cmFortranParser.cxx" +#line 1804 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ -#line 180 "cmFortranParser.y" +#line 182 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1792 "cmFortranParser.cxx" +#line 1814 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ -#line 185 "cmFortranParser.y" +#line 187 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1802 "cmFortranParser.cxx" +#line 1824 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ -#line 190 "cmFortranParser.y" +#line 192 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1812 "cmFortranParser.cxx" +#line 1834 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ -#line 195 "cmFortranParser.y" +#line 197 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1821 "cmFortranParser.cxx" +#line 1843 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ -#line 199 "cmFortranParser.y" +#line 201 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1830 "cmFortranParser.cxx" +#line 1852 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ -#line 203 "cmFortranParser.y" +#line 205 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1839 "cmFortranParser.cxx" +#line 1861 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ -#line 207 "cmFortranParser.y" +#line 209 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1848 "cmFortranParser.cxx" +#line 1870 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ -#line 229 "cmFortranParser.y" +#line 231 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1854 "cmFortranParser.cxx" +#line 1876 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ -#line 236 "cmFortranParser.y" +#line 238 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1860 "cmFortranParser.cxx" +#line 1882 "cmFortranParser.cxx" break; -#line 1864 "cmFortranParser.cxx" +#line 1886 "cmFortranParser.cxx" default: break; } @@ -2085,6 +2107,6 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); return yyresult; } -#line 248 "cmFortranParser.y" +#line 250 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index e461160c6d2..a3e1c24b12b 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -92,6 +92,8 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) %token SUBMODULE %token USE +%destructor { free($$); } WORD STRING CPP_INCLUDE_ANGLE + /*-------------------------------------------------------------------------*/ /* grammar */ %% From 19d831b03d2c3921c19f07a94fce4f7b678f0afa Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 7 Jun 2021 15:09:05 -0400 Subject: [PATCH 0630/1519] ci: add compiler-rt to Fedora base image This is needed for `clang -fsanitize=` flags. --- .gitlab/ci/docker/fedora34/install_deps.sh | 1 + .gitlab/os-linux.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 7d099feccec..146d51fd4a2 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -12,6 +12,7 @@ dnf install --setopt=install_weak_deps=False -y \ # Install development tools. dnf install --setopt=install_weak_deps=False -y \ clang-tools-extra \ + compiler-rt \ gcc-c++ \ git-core \ make diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 015df4f12d6..17f51cf3086 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -69,7 +69,7 @@ ### Fedora .fedora34: - image: "kitware/cmake:ci-fedora34-x86_64-2021-06-03" + image: "kitware/cmake:ci-fedora34-x86_64-2021-06-07" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" From cbcb92d1cb4230426761fb7d08f9135546c98881 Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Fri, 4 Jun 2021 11:22:34 -0400 Subject: [PATCH 0631/1519] ctest: add support for attaching files to tests at run time Allow tests to specify files to upload at runtime. Previously this was only possible to specify at configure time with the ATTACHED_FILES test properties. This commit also fixes a bug in how our test data tarballs were generated by CTest. Previously, if you tried to attach a file outside of the binary directory, CTest would generate a tar file with a relative path, and tar would not allow you to extract it. We resolve this problem by creating tar files with a flat directory structure instead. Fixes: #22284 --- Help/command/ctest_test.rst | 13 ++- Help/release/dev/ctest-measurements-docs.rst | 5 + Help/release/dev/ctest-runtime-files.rst | 8 ++ Source/CTest/cmCTestTestHandler.cxx | 106 +++++++++++------- Source/CTest/cmCTestTestHandler.h | 2 + Source/cmCTest.cxx | 40 +++++-- Source/cmCTest.h | 3 + Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 4 + .../ctest_test/TestMeasurements-check.cmake | 5 + 9 files changed, 137 insertions(+), 49 deletions(-) create mode 100644 Help/release/dev/ctest-measurements-docs.rst create mode 100644 Help/release/dev/ctest-runtime-files.rst diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index c61d01e5d16..65555a63212 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -248,5 +248,14 @@ separate from the interactive comparison UI. Attached Files """""""""""""" -To associate other types of files with a test, use the -:prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. +The following example demonstrates how to upload non-image files to CDash. + +.. code-block:: c++ + + std::cout << + "" << + "/dir/to/data.csv" << std::endl; + +If the name of the file to upload is known at configure time, you can use the +:prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test +properties instead. diff --git a/Help/release/dev/ctest-measurements-docs.rst b/Help/release/dev/ctest-measurements-docs.rst new file mode 100644 index 00000000000..e47582e5222 --- /dev/null +++ b/Help/release/dev/ctest-measurements-docs.rst @@ -0,0 +1,5 @@ +ctest-measurements-docs +----------------------- + +* :manual:`ctest(1)` gained documentation for its ability to capture + :ref:`Additional Test Measurements`. diff --git a/Help/release/dev/ctest-runtime-files.rst b/Help/release/dev/ctest-runtime-files.rst new file mode 100644 index 00000000000..f13baa4fff8 --- /dev/null +++ b/Help/release/dev/ctest-runtime-files.rst @@ -0,0 +1,8 @@ +ctest-runtime-files +------------------- + +* :manual:`ctest(1)` learned to recognize files attached to a test at run time. + Previously it was only possible to attach files to tests at configure time + by using the :prop_test:`ATTACHED_FILES` or + :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. + See :ref:`Additional Test Measurements` for more information. diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 1596d4ac32b..fd38f397030 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1550,19 +1550,29 @@ void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml, result.Properties->AttachOnFail.end()); } for (std::string const& file : result.Properties->AttachedFiles) { - const std::string& base64 = this->CTest->Base64GzipEncodeFile(file); - std::string const fname = cmSystemTools::GetFilenameName(file); - xml.StartElement("NamedMeasurement"); - xml.Attribute("name", "Attached File"); - xml.Attribute("encoding", "base64"); - xml.Attribute("compression", "tar/gzip"); - xml.Attribute("filename", fname); - xml.Attribute("type", "file"); - xml.Element("Value", base64); - xml.EndElement(); // NamedMeasurement + this->AttachFile(xml, file, ""); } } +void cmCTestTestHandler::AttachFile(cmXMLWriter& xml, std::string const& file, + std::string const& name) +{ + const std::string& base64 = this->CTest->Base64GzipEncodeFile(file); + std::string const fname = cmSystemTools::GetFilenameName(file); + xml.StartElement("NamedMeasurement"); + std::string measurement_name = name; + if (measurement_name.empty()) { + measurement_name = "Attached File"; + } + xml.Attribute("name", measurement_name); + xml.Attribute("encoding", "base64"); + xml.Attribute("compression", "tar/gzip"); + xml.Attribute("filename", fname); + xml.Attribute("type", "file"); + xml.Element("Value", base64); + xml.EndElement(); // NamedMeasurement +} + int cmCTestTestHandler::ExecuteCommands(std::vector& vec) { for (std::string const& it : vec) { @@ -2041,11 +2051,11 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, cmCTest::CleanString(measurementfile.match(5)); if (cmSystemTools::FileExists(filename)) { long len = cmSystemTools::FileLength(filename); + std::string k1 = measurementfile.match(1); + std::string v1 = measurementfile.match(2); + std::string k2 = measurementfile.match(3); + std::string v2 = measurementfile.match(4); if (len == 0) { - std::string k1 = measurementfile.match(1); - std::string v1 = measurementfile.match(2); - std::string k2 = measurementfile.match(3); - std::string v2 = measurementfile.match(4); if (cmSystemTools::LowerCase(k1) == "type") { v1 = "text/string"; } @@ -2060,35 +2070,53 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, xml.Element("Value", "Image " + filename + " is empty"); xml.EndElement(); } else { - cmsys::ifstream ifs(filename.c_str(), - std::ios::in + std::string type; + std::string name; + if (cmSystemTools::LowerCase(k1) == "type") { + type = v1; + } else if (cmSystemTools::LowerCase(k2) == "type") { + type = v2; + } + if (cmSystemTools::LowerCase(k1) == "name") { + name = v1; + } else if (cmSystemTools::LowerCase(k2) == "name") { + name = v2; + } + if (type == "file") { + // Treat this measurement like an "ATTACHED_FILE" when the type + // is explicitly "file" (not an image). + this->AttachFile(xml, filename, name); + } else { + cmsys::ifstream ifs(filename.c_str(), + std::ios::in #ifdef _WIN32 - | std::ios::binary + | std::ios::binary #endif - ); - auto file_buffer = cm::make_unique(len + 1); - ifs.read(reinterpret_cast(file_buffer.get()), len); - auto encoded_buffer = cm::make_unique( - static_cast(static_cast(len) * 1.5 + 5.0)); - - size_t rlen = cmsysBase64_Encode(file_buffer.get(), len, - encoded_buffer.get(), 1); - - xml.StartElement("NamedMeasurement"); - xml.Attribute(measurementfile.match(1).c_str(), - measurementfile.match(2)); - xml.Attribute(measurementfile.match(3).c_str(), - measurementfile.match(4)); - xml.Attribute("encoding", "base64"); - std::ostringstream ostr; - for (size_t cc = 0; cc < rlen; cc++) { - ostr << encoded_buffer[cc]; - if (cc % 60 == 0 && cc) { - ostr << std::endl; + ); + auto file_buffer = cm::make_unique(len + 1); + ifs.read(reinterpret_cast(file_buffer.get()), len); + auto encoded_buffer = cm::make_unique( + static_cast(static_cast(len) * 1.5 + 5.0)); + + size_t rlen = cmsysBase64_Encode(file_buffer.get(), len, + encoded_buffer.get(), 1); + + xml.StartElement("NamedMeasurement"); + xml.Attribute(measurementfile.match(1).c_str(), + measurementfile.match(2)); + xml.Attribute(measurementfile.match(3).c_str(), + measurementfile.match(4)); + xml.Attribute("encoding", "base64"); + std::ostringstream ostr; + for (size_t cc = 0; cc < rlen; cc++) { + ostr << encoded_buffer[cc]; + if (cc % 60 == 0 && cc) { + ostr << std::endl; + } } + xml.Element("Value", ostr.str()); + xml.EndElement(); // NamedMeasurement } - xml.Element("Value", ostr.str()); - xml.EndElement(); // NamedMeasurement } } else { int idx = 4; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 68416246f8a..9f5b3da26ca 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -237,6 +237,8 @@ class cmCTestTestHandler : public cmCTestGenericHandler cmCTestTestResult const& result); // Write attached test files into the xml void AttachFiles(cmXMLWriter& xml, cmCTestTestResult& result); + void AttachFile(cmXMLWriter& xml, std::string const& file, + std::string const& name); //! Clean test output to specified length void CleanTestOutput(std::string& output, size_t length); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 7534e37f80f..7c469c84a4d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1612,8 +1612,33 @@ int cmCTest::GenerateDoneFile() return 0; } +bool cmCTest::TryToChangeDirectory(std::string const& dir) +{ + cmCTestLog(this, OUTPUT, + "Internal ctest changing into directory: " << dir << std::endl); + cmsys::Status status = cmSystemTools::ChangeDirectory(dir); + if (!status) { + auto msg = "Failed to change working directory to \"" + dir + + "\" : " + status.GetString() + "\n"; + cmCTestLog(this, ERROR_MESSAGE, msg); + return false; + } + return true; +} + std::string cmCTest::Base64GzipEncodeFile(std::string const& file) { + const std::string currDir = cmSystemTools::GetCurrentWorkingDirectory(); + std::string parentDir = cmSystemTools::GetParentDirectory(file); + + // Temporarily change to the file's directory so the tar gets created + // with a flat directory structure. + if (currDir != parentDir) { + if (!this->TryToChangeDirectory(parentDir)) { + return ""; + } + } + std::string tarFile = file + "_temp.tar.gz"; std::vector files; files.push_back(file); @@ -1628,6 +1653,12 @@ std::string cmCTest::Base64GzipEncodeFile(std::string const& file) } std::string base64 = this->Base64EncodeFile(tarFile); cmSystemTools::RemoveFile(tarFile); + + // Change back to the directory we started in. + if (currDir != parentDir) { + cmSystemTools::ChangeDirectory(currDir); + } + return base64; } @@ -2853,14 +2884,7 @@ int cmCTest::ExecuteTests() } if (currDir != workDir) { - cmCTestLog(this, OUTPUT, - "Internal ctest changing into directory: " << workDir - << std::endl); - cmsys::Status status = cmSystemTools::ChangeDirectory(workDir); - if (!status) { - auto msg = "Failed to change working directory to \"" + workDir + - "\" : " + status.GetString() + "\n"; - cmCTestLog(this, ERROR_MESSAGE, msg); + if (!this->TryToChangeDirectory(workDir)) { return 1; } } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 392eb1c4104..551c116ada9 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -536,6 +536,9 @@ class cmCTest int RunCMakeAndTest(std::string* output); int ExecuteTests(); + /** return true iff change directory was successful */ + bool TryToChangeDirectory(std::string const& dir); + struct Private; std::unique_ptr Impl; }; diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index b559e899f13..76a63f01145 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -161,6 +161,10 @@ add_test( NAME img_measurement COMMAND ${CMAKE_COMMAND} -E echo ]] ${IMAGE_DIR}/cmake-logo-16.png [[) +add_test( + NAME file_measurement + COMMAND ${CMAKE_COMMAND} -E + echo ]] ${IMAGE_DIR}/cmake-logo-16.png [[) ]]) run_ctest(TestMeasurements) endfunction() diff --git a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake index 9ff9447009a..0095db0dec9 100644 --- a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake +++ b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake @@ -15,3 +15,8 @@ if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage" type="image/pn string(APPEND RunCMake_TEST_FAILED "Could not find expected tag for type='image/png' in Test.xml") endif() +# Check file measurement. +if(NOT _test_contents MATCHES [[NamedMeasurement name="my_test_input_data" encoding="base64" compression="tar/gzip" filename="cmake-logo-16.png" type="file"]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected tag for type='file' in Test.xml") +endif() From 20bc209a0c61ec59912b0c2b082ed43a080905bc Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 7 Jun 2021 14:30:08 -0400 Subject: [PATCH 0632/1519] gitlab-ci: add clang asan job --- .gitlab-ci.yml | 25 +++++++++++ .gitlab/ci/configure_fedora34_asan.cmake | 4 ++ .gitlab/ci/ctest_exclusions.cmake | 7 +++ .gitlab/ci/ctest_memcheck.cmake | 45 +++++++++++++++++++ .../ci/ctest_memcheck_fedora34_asan.lsan.supp | 1 + .gitlab/ci/env_fedora34_asan.sh | 2 + .gitlab/os-linux.yml | 30 +++++++++++++ 7 files changed, 114 insertions(+) create mode 100644 .gitlab/ci/configure_fedora34_asan.cmake create mode 100644 .gitlab/ci/ctest_memcheck.cmake create mode 100644 .gitlab/ci/ctest_memcheck_fedora34_asan.lsan.supp create mode 100644 .gitlab/ci/env_fedora34_asan.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 236eac9901d..754b2a11bbc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -498,6 +498,31 @@ upload:linux-aarch64-package: variables: RSYNC_DESTINATION: dev +## Sanitizer builds + +build:fedora34-asan: + extends: + - .fedora34_asan + - .cmake_build_linux + - .cmake_build_artifacts + - .linux_builder_tags_qt + - .run_manually + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + +test:fedora34-asan: + extends: + - .fedora34_asan + - .cmake_memcheck_linux + - .linux_builder_tags_qt + - .run_automatically + dependencies: + - build:fedora34-asan + needs: + - build:fedora34-asan + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + # macOS builds build:macos-x86_64-ninja: diff --git a/.gitlab/ci/configure_fedora34_asan.cmake b/.gitlab/ci/configure_fedora34_asan.cmake new file mode 100644 index 00000000000..c22cdb7bd1b --- /dev/null +++ b/.gitlab/ci/configure_fedora34_asan.cmake @@ -0,0 +1,4 @@ +set(CMAKE_C_FLAGS "-fsanitize=address" CACHE STRING "") +set(CMAKE_CXX_FLAGS "-fsanitize=address" CACHE STRING "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora34_common.cmake") diff --git a/.gitlab/ci/ctest_exclusions.cmake b/.gitlab/ci/ctest_exclusions.cmake index b885a6a5e78..3460d48cbd9 100644 --- a/.gitlab/ci/ctest_exclusions.cmake +++ b/.gitlab/ci/ctest_exclusions.cmake @@ -13,6 +13,13 @@ if (CTEST_CMAKE_GENERATOR MATCHES "Visual Studio") "^ExternalProjectUpdateSetup$") endif () +if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "_asan") + list(APPEND test_exclusions + CTestTest2 # crashes on purpose + BootstrapTest # no need to cover this for asan + ) +endif() + string(REPLACE ";" "|" test_exclusions "${test_exclusions}") if (test_exclusions) set(test_exclusions "(${test_exclusions})") diff --git a/.gitlab/ci/ctest_memcheck.cmake b/.gitlab/ci/ctest_memcheck.cmake new file mode 100644 index 00000000000..dac907c1577 --- /dev/null +++ b/.gitlab/ci/ctest_memcheck.cmake @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.8) + +include("${CMAKE_CURRENT_LIST_DIR}/gitlab_ci.cmake") + +# Read the files from the build directory. +ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}") + +# Pick up from where the configure left off. +ctest_start(APPEND) + +include(ProcessorCount) +ProcessorCount(nproc) +if (NOT "$ENV{CTEST_MAX_PARALLELISM}" STREQUAL "") + if (nproc GREATER "$ENV{CTEST_MAX_PARALLELISM}") + set(nproc "$ENV{CTEST_MAX_PARALLELISM}") + endif () +endif () + +set(CTEST_MEMORYCHECK_TYPE "$ENV{CTEST_MEMORYCHECK_TYPE}") +set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "$ENV{CTEST_MEMORYCHECK_SANITIZER_OPTIONS}") + +set(lsan_suppressions "${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_$ENV{CMAKE_CONFIGURATION}.lsan.supp") +if (EXISTS "${lsan_suppressions}") + set(ENV{LSAN_OPTIONS} "suppressions='${lsan_suppressions}'") +endif () + +include("${CMAKE_CURRENT_LIST_DIR}/ctest_exclusions.cmake") +ctest_memcheck( + PARALLEL_LEVEL "${nproc}" + TEST_LOAD "${nproc}" + RETURN_VALUE test_result + EXCLUDE "${test_exclusions}" + DEFECT_COUNT defects) +ctest_submit(PARTS Test) +ctest_submit(PARTS Memcheck) + +if (test_result) + message(FATAL_ERROR + "Failed to test") +endif () + +if (defects) + message(FATAL_ERROR + "Found ${defects} memcheck defects") +endif () diff --git a/.gitlab/ci/ctest_memcheck_fedora34_asan.lsan.supp b/.gitlab/ci/ctest_memcheck_fedora34_asan.lsan.supp new file mode 100644 index 00000000000..8ec1a0358b2 --- /dev/null +++ b/.gitlab/ci/ctest_memcheck_fedora34_asan.lsan.supp @@ -0,0 +1 @@ +# Add 'leak:' lines here to suppress known leaks. diff --git a/.gitlab/ci/env_fedora34_asan.sh b/.gitlab/ci/env_fedora34_asan.sh new file mode 100644 index 00000000000..e9764862eb2 --- /dev/null +++ b/.gitlab/ci/env_fedora34_asan.sh @@ -0,0 +1,2 @@ +export CC=/usr/bin/clang +export CXX=/usr/bin/clang++ diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 17f51cf3086..997beab17f3 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -158,6 +158,27 @@ CMAKE_CONFIGURATION: debian10_makefiles_clang CMAKE_GENERATOR: "Unix Makefiles" +### Sanitizers + +.fedora_memcheck: + variables: + CMAKE_BUILD_TYPE: RelWithDebInfo + +.fedora_asan_addon: + extends: .fedora_memcheck + + variables: + CTEST_MEMORYCHECK_TYPE: AddressSanitizer + CTEST_MEMORYCHECK_SANITIZER_OPTIONS: "" + +.fedora34_asan: + extends: + - .fedora34 + - .fedora_asan_addon + + variables: + CMAKE_CONFIGURATION: fedora34_asan + ### Intel Compiler .intelcompiler: @@ -306,6 +327,15 @@ interruptible: true +.cmake_memcheck_linux: + stage: test + + script: + - *before_script_linux + - "$LAUNCHER ctest --output-on-failure -V -S .gitlab/ci/ctest_memcheck.cmake" + + interruptible: true + .cmake_build_linux_release: stage: build From b00512e6929c046ff472563cf1d0407149c51bb7 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 8 Jun 2021 10:46:16 -0400 Subject: [PATCH 0633/1519] Help: presets: add note for ExternalProject users with env vars Although this behavior is implied in the existing help text, I think this use case is common and could be puzzling to those who do not thoroughly read the existing help text. I think that warrants a "Note:" on this page. --- Help/manual/cmake-presets.7.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index 0bcd6910adb..db26b5a40fc 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -401,6 +401,19 @@ that may contain the following fields: 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 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 ``CC`` and ``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 From 143f7fe61a22acef474cf1295b996b04775cbc97 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 12:25:07 -0400 Subject: [PATCH 0634/1519] Tests: Remove unused RunCMake.TransformDepfile files Remove files missed by commit f0e9d74a2d (cmake_transform_depfile: Remove unused incomplete vstlog support, 2021-06-02). --- .../RunCMake/TransformDepfile/deps-unix.tlog.txt | 6 ------ .../TransformDepfile/deps-windows.tlog.txt | 6 ------ Tests/RunCMake/TransformDepfile/empty.tlog.txt | 0 .../TransformDepfile/invalid-tlog-result.txt | 1 - Tests/RunCMake/TransformDepfile/noexist.tlog.txt | 0 Tests/RunCMake/TransformDepfile/vstlog.cmake | 16 ---------------- 6 files changed, 29 deletions(-) delete mode 100644 Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt delete mode 100644 Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt delete mode 100644 Tests/RunCMake/TransformDepfile/empty.tlog.txt delete mode 100644 Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt delete mode 100644 Tests/RunCMake/TransformDepfile/noexist.tlog.txt delete mode 100644 Tests/RunCMake/TransformDepfile/vstlog.cmake diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt deleted file mode 100644 index 70bac5da262..00000000000 --- a/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt +++ /dev/null @@ -1,6 +0,0 @@ -^subdir/out1|/home/build/out2 -subdir/in1 -/home/build/in2 -^subdir/out3|/home/build/out4 -subdir/in3 -/home/build/in4 diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt deleted file mode 100644 index 09f9e9711a1..00000000000 --- a/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt +++ /dev/null @@ -1,6 +0,0 @@ -^subdir\out1|C:\build\out2 -subdir\in1 -C:\build\in2 -^subdir\out3|C:\build\out4 -subdir\in3 -C:\build\in4 diff --git a/Tests/RunCMake/TransformDepfile/empty.tlog.txt b/Tests/RunCMake/TransformDepfile/empty.tlog.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt deleted file mode 100644 index 0cfbf08886f..00000000000 --- a/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/Tests/RunCMake/TransformDepfile/noexist.tlog.txt b/Tests/RunCMake/TransformDepfile/noexist.tlog.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/Tests/RunCMake/TransformDepfile/vstlog.cmake b/Tests/RunCMake/TransformDepfile/vstlog.cmake deleted file mode 100644 index afa78d05ccb..00000000000 --- a/Tests/RunCMake/TransformDepfile/vstlog.cmake +++ /dev/null @@ -1,16 +0,0 @@ -if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.tlog.txt") - file(READ "${RunCMake_SOURCE_DIR}/${name}.tlog.txt" expected_contents) - - if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog") - file(READ "${RunCMake_TEST_BINARY_DIR}/out.tlog" actual_contents) - if(NOT actual_contents STREQUAL expected_contents) - string(REPLACE "\n" "\n " p_expected_contents "${expected_contents}") - string(REPLACE "\n" "\n " p_actual_contents "${actual_contents}") - string(APPEND RunCMake_TEST_FAILED "Expected contents of ${RunCMake_TEST_BINARY_DIR}/out.tlog:\n ${p_expected_contents}\nActual contents:\n ${p_actual_contents}") - endif() - else() - string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should exist\n") - endif() -elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog") - string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should not exist\n") -endif() From a9f992434d3a75f262d261d6a8a5a111a757d5bd Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Tue, 8 Jun 2021 21:58:42 +0200 Subject: [PATCH 0635/1519] VS: Remove the /MERGE flag from FlagTables Fixes #22229 --- Templates/MSBuild/FlagTables/v10_Link.json | 9 --------- Templates/MSBuild/FlagTables/v11_Link.json | 9 --------- Templates/MSBuild/FlagTables/v12_Link.json | 9 --------- Templates/MSBuild/FlagTables/v140_Link.json | 9 --------- Templates/MSBuild/FlagTables/v141_Link.json | 9 --------- Templates/MSBuild/FlagTables/v142_Link.json | 9 --------- 6 files changed, 54 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v10_Link.json b/Templates/MSBuild/FlagTables/v10_Link.json index ac5b8b16cc7..494774bc20d 100644 --- a/Templates/MSBuild/FlagTables/v10_Link.json +++ b/Templates/MSBuild/FlagTables/v10_Link.json @@ -1089,15 +1089,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", diff --git a/Templates/MSBuild/FlagTables/v11_Link.json b/Templates/MSBuild/FlagTables/v11_Link.json index 5d5c13f2192..0db5d9e0598 100644 --- a/Templates/MSBuild/FlagTables/v11_Link.json +++ b/Templates/MSBuild/FlagTables/v11_Link.json @@ -1224,15 +1224,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", diff --git a/Templates/MSBuild/FlagTables/v12_Link.json b/Templates/MSBuild/FlagTables/v12_Link.json index 5d5c13f2192..0db5d9e0598 100644 --- a/Templates/MSBuild/FlagTables/v12_Link.json +++ b/Templates/MSBuild/FlagTables/v12_Link.json @@ -1224,15 +1224,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", diff --git a/Templates/MSBuild/FlagTables/v140_Link.json b/Templates/MSBuild/FlagTables/v140_Link.json index 3fb072c5064..7e293b140bd 100644 --- a/Templates/MSBuild/FlagTables/v140_Link.json +++ b/Templates/MSBuild/FlagTables/v140_Link.json @@ -1268,15 +1268,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", diff --git a/Templates/MSBuild/FlagTables/v141_Link.json b/Templates/MSBuild/FlagTables/v141_Link.json index 66ee76fcb4d..e311240b63d 100644 --- a/Templates/MSBuild/FlagTables/v141_Link.json +++ b/Templates/MSBuild/FlagTables/v141_Link.json @@ -1275,15 +1275,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", diff --git a/Templates/MSBuild/FlagTables/v142_Link.json b/Templates/MSBuild/FlagTables/v142_Link.json index 110dcc2b146..d5fc2e4d7d1 100644 --- a/Templates/MSBuild/FlagTables/v142_Link.json +++ b/Templates/MSBuild/FlagTables/v142_Link.json @@ -1282,15 +1282,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", From b6faa5e2df22fecac877dc866294e8b5a36ab03a Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 9 Jun 2021 00:01:13 -0400 Subject: [PATCH 0636/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7915a9cce43..bfa84e41fff 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210608) +set(CMake_VERSION_PATCH 20210609) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d4056f24a17ab7d35a0539583cadfe08699d14e7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jun 2021 08:15:30 -0400 Subject: [PATCH 0637/1519] Tests: Improve RunCMake.CPack*.SOURCE_PACKAGE test error formatting Format message content for `message(FATAL_ERROR)`. Apply the change from commit c54c284de7 (Tests: Improve RunCMake.CPack* test error formatting, 2021-04-22) to the `SOURCE_PACKAGE` script too. Also fix a typo from commit f5d79dec53 (Tests: Cleanup CPack message when files are expected and none are found, 2021-01-15, v3.20.0-rc1~89^2~22). --- Tests/RunCMake/CPack/VerifyResult.cmake | 2 +- .../tests/SOURCE_PACKAGE/VerifyResult.cmake | 37 ++++++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake index 294b9e8427f..76c1bea7c17 100644 --- a/Tests/RunCMake/CPack/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/VerifyResult.cmake @@ -87,7 +87,7 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0) "which does not match:${msg_expected}\n" "${output_error_message}") endif() - elseif(foundFilescount_ EQUAL 0) + elseif(foundFilesCount_ EQUAL 0) message(FATAL_ERROR "Found no files for file ${file_no_}!\n" "Globbing expression:\n '${EXPECTED_FILE_${file_no_}}'\n" diff --git a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake index 73d7481f152..42e8384a8cd 100644 --- a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake @@ -18,14 +18,20 @@ execute_process(COMMAND ${RPMBUILD_EXECUTABLE} --define "_topdir ${CMAKE_CURRENT OUTPUT_QUIET ) -set(output_error_message_ - "\n${RPMBUILD_EXECUTABLE} error: '${error_}';\nresult: '${result_}';\n${output_error_message}") +string(REPLACE "\n" "\n rpmbuild-err> " rpmbuild_err "\n${error_}") +string(REPLACE "\n" "\n rpmbuild-res> " rpmbuild_res "\n${result_}") +string(CONCAT output_error_message_ + "${RPMBUILD_EXECUTABLE} error:${rpmbuild_err}\n" + "${RPMBUILD_EXECUTABLE} result:${rpmbuild_res}\n" + "${output_error_message}" + ) # expected file content are test_prog and optional build-id links that are # generated by rpmbuild (introduced in rpm 4.13.0.1) set(EXPECTED_FILE_CONTENT_ "^/foo${whitespaces_}/foo/test_prog(${whitespaces_}.*\.build-id.*)*$") +set(EXPECTED_FILE_ "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS/*.rpm") -file(GLOB_RECURSE FOUND_FILE_ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS" "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS/*.rpm") +file(GLOB_RECURSE FOUND_FILE_ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS" "${EXPECTED_FILE_}") list(APPEND foundFiles_ "${FOUND_FILE_}") list(LENGTH FOUND_FILE_ foundFilesCount_) @@ -37,17 +43,27 @@ if(foundFilesCount_ EQUAL 1) expected_content_list "${PACKAGE_CONTENT}") if(NOT expected_content_list) + string(REPLACE "\n" "\n actual> " msg_actual "\n${PACKAGE_CONTENT}") + string(REPLACE "\n" "\n expect> " msg_expected "\n${EXPECTED_FILE_CONTENT_}") + string(REPLACE "\r" "\\r" msg_expected "${msg_expected}") + string(REPLACE "\t" "\\t" msg_expected "${msg_expected}") message(FATAL_ERROR "Unexpected file content!\n" - " Content: '${PACKAGE_CONTENT}'\n\n" - " Expected: '${EXPECTED_FILE_CONTENT_}'" + "The content was:${msg_actual}\n" + "which does not match:${msg_expected}\n" "${output_error_message_}") endif() +elseif(foundFilesCount_ EQUAL 0) + message(FATAL_ERROR + "Found no files!\n" + "Globbing expression:\n '${EXPECTED_FILE_}'\n" + "${output_error_message_}") else() message(FATAL_ERROR - "Found more than one file!" - " Found files count '${foundFilesCount_}'." - " Files: '${FOUND_FILE_}'" + "Found more than one file!\n" + "Found files count '${foundFilesCount_}'.\n" + "Files:\n '${FOUND_FILE_}'\n" + "Globbing expression:\n '${EXPECTED_FILE_}'\n" "${output_error_message_}") endif() @@ -62,6 +78,7 @@ list(LENGTH allFoundFiles_ allFoundFilesCount_) if(NOT foundFilesCount_ EQUAL allFoundFilesCount_) message(FATAL_ERROR - "Found more files than expected! Found files: '${allFoundFiles_}'" - "${output_error_message_}") + "Found more files than expected!\n" + "Found files:\n '${allFoundFiles_}'\n" + "${output_error_message_}") endif() From 46686f077b68cfb50b9cf65178a7861e89e098c1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jun 2021 08:23:06 -0400 Subject: [PATCH 0638/1519] Help: Document special "CTEST_FULL_OUTPUT" test output string --- Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst | 3 +++ Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst b/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst index 5aeae88a4ec..9f145c1a2a4 100644 --- a/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst +++ b/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst @@ -5,4 +5,7 @@ When saving a failing test's output, this is the maximum size, in bytes, that will be collected by the :command:`ctest_test` command. Defaults to 307200 (300 KiB). +If a test's output contains the literal string "CTEST_FULL_OUTPUT", +the output will not be truncated and may exceed the maximum size. + .. include:: CTEST_CUSTOM_XXX.txt diff --git a/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst b/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst index 1fbb8c53f47..71ecf52bfb9 100644 --- a/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst +++ b/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst @@ -5,4 +5,7 @@ When saving a passing test's output, this is the maximum size, in bytes, that will be collected by the :command:`ctest_test` command. Defaults to 1024 (1 KiB). +If a test's output contains the literal string "CTEST_FULL_OUTPUT", +the output will not be truncated and may exceed the maximum size. + .. include:: CTEST_CUSTOM_XXX.txt From 02f1271bdf810107ad5d3c0cffb74b472d706054 Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Tue, 8 Jun 2021 14:48:57 -0400 Subject: [PATCH 0639/1519] ctest: allow test output to override the 'details' field Parse test output for .... If found, use this value to override the default 'Details' string reported to CDash. --- Help/command/ctest_test.rst | 11 +++++++++++ Source/CTest/cmCTestRunTest.cxx | 16 ++++++++++++++++ Source/CTest/cmCTestTestHandler.cxx | 10 +++++++++- Source/CTest/cmCTestTestHandler.h | 2 ++ Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 12 ++++++++++++ .../ctest_test/TestCompletionStatus-check.cmake | 16 ++++++++++++++++ 6 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 65555a63212..2153c90de35 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -259,3 +259,14 @@ The following example demonstrates how to upload non-image files to CDash. If the name of the file to upload is known at configure time, you can use the :prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test properties instead. + +Custom Details +"""""""""""""" + +The following example demonstrates how to specify a custom value for the +``Test Details`` field displayed on CDash. + +.. code-block:: c++ + + std::cout << + "My Custom Details Value" << std::endl; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 5a6c77539fd..a8921134b35 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -40,6 +40,22 @@ void cmCTestRunTest::CheckOutput(std::string const& line) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex() << ": " << line << std::endl); + + // Check for special CTest XML tags in this line of output. + // If any are found, this line is excluded from ProcessOutput. + if (!line.empty() && line.find("TestHandler->CustomCompletionStatusRegex.find(line)) { + this->TestResult.CustomCompletionStatus = + this->TestHandler->CustomCompletionStatusRegex.match(1); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() << ": " + << "Test Details changed to '" + << this->TestResult.CustomCompletionStatus + << "'" << std::endl); + return; + } + } + this->ProcessOutput += line; this->ProcessOutput += "\n"; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index fd38f397030..730ec0f04dd 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -308,6 +308,10 @@ cmCTestTestHandler::cmCTestTestHandler() // regex to detect each individual ... this->DartStuff1.compile( "()"); + + // regex to detect ... + this->CustomCompletionStatusRegex.compile( + "(.*)"); } void cmCTestTestHandler::Initialize() @@ -1460,7 +1464,11 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.StartElement("NamedMeasurement"); xml.Attribute("type", "text/string"); xml.Attribute("name", "Completion Status"); - xml.Element("Value", result.CompletionStatus); + if (result.CustomCompletionStatus.empty()) { + xml.Element("Value", result.CompletionStatus); + } else { + xml.Element("Value", result.CustomCompletionStatus); + } xml.EndElement(); // NamedMeasurement xml.StartElement("NamedMeasurement"); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 9f5b3da26ca..bd51738b8fc 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -175,6 +175,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler std::string ExceptionStatus; bool CompressOutput; std::string CompletionStatus; + std::string CustomCompletionStatus; std::string Output; std::string DartString; int TestCount; @@ -358,6 +359,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler ListOfTests TestList; size_t TotalNumberOfTests; cmsys::RegularExpression DartStuff; + cmsys::RegularExpression CustomCompletionStatusRegex; std::ostream* LogFile; diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index 76a63f01145..f07a12b7739 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -169,3 +169,15 @@ add_test( run_ctest(TestMeasurements) endfunction() run_measurements() + +# Verify that test output can override the Completion Status. +function(run_completion_status) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test( + NAME custom_details + COMMAND ${CMAKE_COMMAND} -E + echo test output\nCustomDetails\nmore output) + ]]) + run_ctest(TestCompletionStatus) +endfunction() +run_completion_status() diff --git a/Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake b/Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake new file mode 100644 index 00000000000..10de2edf0d9 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestCompletionStatus-check.cmake @@ -0,0 +1,16 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/TAG" _tag) +string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}") +file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents) + +# Check custom completion status. +if(NOT _test_contents MATCHES [[CustomDetails]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected CustomDetails in Test.xml") +endif() +# Check test output. +if(NOT _test_contents MATCHES "test output") + string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'test output' in Test.xml") +endif() +if(NOT _test_contents MATCHES "more output") + string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'more output' in Test.xml") +endif() From a6de8ec51b5afdef747e0dfd8f5d67e2b92429c0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 16:25:50 -0400 Subject: [PATCH 0640/1519] cmTransformDepfile: Make directory for transformed depfile automatically --- Source/cmLocalNinjaGenerator.cxx | 2 -- Source/cmTransformDepfile.cxx | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 81425991c43..7f7b1e7d734 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -698,8 +698,6 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: - cmSystemTools::MakeDirectory( - cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d")); depfile = ccg.GetInternalDepfile(); break; } diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 0df9550b823..039b19de3ad 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -93,6 +93,7 @@ bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, content = *std::move(result); } + cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(outfile)); cmsys::ofstream fout(outfile.c_str()); if (!fout) { return false; From 7291f312545d4a22339a4f9763ea61e16507c8a3 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 17:58:33 -0400 Subject: [PATCH 0641/1519] cmTransformDepfile: Add support for MSBuild AdditionalInputs format --- Source/cmCustomCommandGenerator.cxx | 6 ++++++ Source/cmTransformDepfile.cxx | 31 +++++++++++++++++++++++++++++ Source/cmTransformDepfile.h | 3 ++- Source/cmcmd.cxx | 2 ++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 10a6491f932..5a2683bb8b1 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -230,6 +230,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( case cmDepfileFormat::MakeDepfile: argv.emplace_back("makedepfile"); break; + case cmDepfileFormat::MSBuildAdditionalInputs: + argv.emplace_back("MSBuildAdditionalInputs"); + break; } argv.push_back(this->LG->GetSourceDirectory()); argv.push_back(this->LG->GetCurrentSourceDirectory()); @@ -437,6 +440,9 @@ std::string cmCustomCommandGenerator::GetInternalDepfileName( case cmDepfileFormat::MakeDepfile: extension = ".d"; break; + case cmDepfileFormat::MSBuildAdditionalInputs: + extension = ".AdditionalInputs"; + break; } return cmStrCat(this->LG->GetBinaryDirectory(), "/CMakeFiles/d/", hash.HashString(depfile), extension); diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 039b19de3ad..4032596b852 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -2,7 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTransformDepfile.h" +#include #include +#include #include #include #include @@ -78,6 +80,32 @@ void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout, } } } + +void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout, + cmLocalGenerator const& lg, + cmGccDepfileContent const& content) +{ + if (content.empty()) { + return; + } + + // Write a UTF-8 BOM so MSBuild knows the encoding when reading the file. + static const char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) }; + fout.write(utf8bom, sizeof(utf8bom)); + + // Write the format expected by MSBuild CustomBuild AdditionalInputs. + const char* sep = ""; + for (std::string path : content.front().paths) { + if (!cmSystemTools::FileIsFullPath(path)) { + path = + cmSystemTools::CollapseFullPath(path, lg.GetCurrentBinaryDirectory()); + } + std::replace(path.begin(), path.end(), '/', '\\'); + fout << sep << path; + sep = ";"; + } + fout << "\n"; +} } bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, @@ -103,6 +131,9 @@ bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg, case cmDepfileFormat::MakeDepfile: WriteDepfile(format, fout, lg, content); break; + case cmDepfileFormat::MSBuildAdditionalInputs: + WriteMSBuildAdditionalInputs(fout, lg, content); + break; } return true; } diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h index ce7cd66fe2f..379e8bc8821 100644 --- a/Source/cmTransformDepfile.h +++ b/Source/cmTransformDepfile.h @@ -7,7 +7,8 @@ enum class cmDepfileFormat { GccDepfile, - MakeDepfile + MakeDepfile, + MSBuildAdditionalInputs, }; class cmLocalGenerator; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 84ac1891f5f..1f4c0b8052a 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1531,6 +1531,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, format = cmDepfileFormat::GccDepfile; } else if (args[3] == "makedepfile") { format = cmDepfileFormat::MakeDepfile; + } else if (args[3] == "MSBuildAdditionalInputs") { + format = cmDepfileFormat::MSBuildAdditionalInputs; } else { return 1; } From 794ad78abb8da517e59e25ea38f5c1edced1cf46 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 12:43:47 -0400 Subject: [PATCH 0642/1519] Help: Generalize release note filename for add_custom_command DEPFILE Rename the note added by commit d67cc4882d (Xcode: Add support of DEPFILE for add_custom_command, 2021-04-15) to be more general. --- Help/release/dev/Xcode-add_custom_command-DEPFILE.rst | 5 ----- Help/release/dev/add_custom_command-DEPFILE.rst | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 Help/release/dev/Xcode-add_custom_command-DEPFILE.rst create mode 100644 Help/release/dev/add_custom_command-DEPFILE.rst diff --git a/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst b/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst deleted file mode 100644 index 4c4d48c7690..00000000000 --- a/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst +++ /dev/null @@ -1,5 +0,0 @@ -Xcode-add_custom_command-DEPFILE --------------------------------- - -* The :command:`add_custom_command` command gained ``DEPFILE`` support on - :generator:`Xcode` generator. diff --git a/Help/release/dev/add_custom_command-DEPFILE.rst b/Help/release/dev/add_custom_command-DEPFILE.rst new file mode 100644 index 00000000000..6361a66446b --- /dev/null +++ b/Help/release/dev/add_custom_command-DEPFILE.rst @@ -0,0 +1,5 @@ +add_custom_command-DEPFILE +-------------------------- + +* The :command:`add_custom_command` command gained ``DEPFILE`` support on + the :generator:`Xcode` generator. From 526e2ef71c5b797818bbf232e21d0152a3938197 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 8 Jun 2021 12:45:20 -0400 Subject: [PATCH 0643/1519] VS: Add support for add_custom_command DEPFILE Transform the depfile into MSBuild `AdditionalInputs` content. Add MSBuild Targets to update `AdditionalInputs` and the `.tlog` files for future builds without actually modifying the `.vcxproj` file. Fixes: #20286 --- Help/command/add_custom_command.rst | 8 ++-- .../dev/add_custom_command-DEPFILE.rst | 3 +- Source/cmGlobalVisualStudio11Generator.h | 7 +++ Source/cmVisualStudio10TargetGenerator.cxx | 32 +++++++++++-- Source/cmVisualStudio10TargetGenerator.h | 8 +++- Templates/MSBuild/CustomBuildDepFile.targets | 48 +++++++++++++++++++ .../RunCMake/BuildDepends/RunCMakeTest.cmake | 3 +- 7 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 Templates/MSBuild/CustomBuildDepFile.targets diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index a053e59f792..d881a66b5c0 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -282,17 +282,19 @@ The options are: :generator:`Xcode` or :ref:`Makefile ` is an error. .. versionadded:: 3.20 - Added the support of :ref:`Makefile Generators`. + Added support for :ref:`Makefile Generators`. .. versionadded:: 3.21 - Added the support of :generator:`Xcode` generator and + Added support for :ref:`Visual Studio Generators` with VS 2012 and above, + for the :generator:`Xcode` generator, and for :manual:`generator expressions `. If the ``DEPFILE`` argument is relative, it should be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR` (see policy :policy:`CMP0116`. This policy is always ``NEW`` for - :ref:`Makefile ` and :generator:`Xcode` generators). + :ref:`Makefile Generators`, :ref:`Visual Studio Generators`, + and the :generator:`Xcode` generator). .. note:: diff --git a/Help/release/dev/add_custom_command-DEPFILE.rst b/Help/release/dev/add_custom_command-DEPFILE.rst index 6361a66446b..893c374e700 100644 --- a/Help/release/dev/add_custom_command-DEPFILE.rst +++ b/Help/release/dev/add_custom_command-DEPFILE.rst @@ -2,4 +2,5 @@ add_custom_command-DEPFILE -------------------------- * The :command:`add_custom_command` command gained ``DEPFILE`` support on - the :generator:`Xcode` generator. + the :generator:`Xcode` generator, and on :ref:`Visual Studio Generators` + for VS 2012 and above. diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 6e409cfa9e0..b11905ec146 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -24,6 +24,13 @@ class cmGlobalVisualStudio11Generator : public cmGlobalVisualStudio10Generator bool MatchesGeneratorName(const std::string& name) const override; + bool SupportsCustomCommandDepfile() const override { return true; } + + cm::optional DepfileFormat() const override + { + return cmDepfileFormat::MSBuildAdditionalInputs; + } + protected: cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name, std::string const& platformInGeneratorName); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 98d56df32a5..b79c6fda14e 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -768,6 +768,11 @@ void cmVisualStudio10TargetGenerator::Generate() Elem(e1, "Import").Attribute("Project", nasmTargets); } } + if (this->ProjectType == vcxproj && this->HaveCustomCommandDepfile) { + std::string depfileTargets = + GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets"); + Elem(e0, "Import").Attribute("Project", depfileTargets); + } if (this->ProjectType == csproj) { for (std::string const& c : this->Configurations) { Elem e1(e0, "PropertyGroup"); @@ -1460,7 +1465,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( e2.SetHasElements(); } for (std::string const& c : this->Configurations) { - cmCustomCommandGenerator ccg(command, c, lg); + cmCustomCommandGenerator ccg(command, c, lg, true); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); std::string script = lg->ConstructScript(ccg); @@ -1524,10 +1529,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( std::string name = "CustomCommand_" + c + "_" + cmSystemTools::ComputeStringMD5(sourcePath); this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(), - outputs.str(), comment); + outputs.str(), comment, ccg); } else { this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(), - outputs.str(), comment, symbolic); + outputs.str(), comment, ccg, symbolic); } } } @@ -1535,7 +1540,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp( Elem& e2, std::string const& config, std::string const& script, std::string const& additional_inputs, std::string const& outputs, - std::string const& comment, bool symbolic) + std::string const& comment, cmCustomCommandGenerator const& ccg, + bool symbolic) { const std::string cond = this->CalcCondition(config); e2.WritePlatformConfigTag("Message", cond, comment); @@ -1554,13 +1560,29 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp( // outputs is marked SYMBOLIC and not expected to be created. e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false"); } + + std::string depfile = ccg.GetFullDepfile(); + if (!depfile.empty()) { + this->HaveCustomCommandDepfile = true; + std::string internal_depfile = ccg.GetInternalDepfile(); + ConvertToWindowsSlash(internal_depfile); + e2.WritePlatformConfigTag("DepFileAdditionalInputsFile", cond, + internal_depfile); + } } void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp( Elem& e0, std::string const& config, std::string const& name, std::string const& script, std::string const& inputs, - std::string const& outputs, std::string const& comment) + std::string const& outputs, std::string const& comment, + cmCustomCommandGenerator const& ccg) { + if (!ccg.GetFullDepfile().empty()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("CSharp target \"", this->GeneratorTarget->GetName(), + "\" does not support add_custom_command DEPFILE.")); + } this->CSharpCustomCommandNames.insert(name); Elem e1(e0, "Target"); e1.Attribute("Condition", this->CalcCondition(config)); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 35dbba81218..55c5444f1a8 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -16,6 +16,7 @@ class cmComputeLinkInformation; class cmCustomCommand; +class cmCustomCommandGenerator; class cmGeneratedFileStream; class cmGlobalVisualStudio10Generator; class cmLocalVisualStudio10Generator; @@ -143,13 +144,15 @@ class cmVisualStudio10TargetGenerator std::string const& script, std::string const& additional_inputs, std::string const& outputs, - std::string const& comment, bool symbolic); + std::string const& comment, + cmCustomCommandGenerator const& ccg, bool symbolic); void WriteCustomRuleCSharp(Elem& e0, std::string const& config, std::string const& commandName, std::string const& script, std::string const& inputs, std::string const& outputs, - std::string const& comment); + std::string const& comment, + cmCustomCommandGenerator const& ccg); void WriteCustomCommands(Elem& e0); void WriteCustomCommand(Elem& e0, cmSourceFile const* sf); void WriteGroups(); @@ -216,6 +219,7 @@ class cmVisualStudio10TargetGenerator bool Managed; bool NsightTegra; bool Android; + bool HaveCustomCommandDepfile = false; unsigned int NsightTegraVersion[4]; bool TargetCompileAsWinRT; std::set IPOEnabledConfigurations; diff --git a/Templates/MSBuild/CustomBuildDepFile.targets b/Templates/MSBuild/CustomBuildDepFile.targets new file mode 100644 index 00000000000..2387ab5392b --- /dev/null +++ b/Templates/MSBuild/CustomBuildDepFile.targets @@ -0,0 +1,48 @@ + + + + + + + + %(CustomBuild.AdditionalInputs) + + + + $([System.IO.File]::ReadAllText('%(CustomBuild.DepFileAdditionalInputsFile)').TrimEnd()) + + + + %(CustomBuild.DepFileAdditionalInputs) + %(CustomBuild.AdditionalInputs);%(CustomBuild.DepFileAdditionalInputs) + + + + + + + + + + + $([System.IO.File]::ReadAllText('%(CustomBuild.DepFileAdditionalInputsFile)').TrimEnd()) + + + + ^%(CustomBuild.Identity) + + + %(ReadTLog)$([System.String]::Copy('%(CustomBuild.CMakeAdditionalInputs)').Trim(';').Replace(';', ' ')) + + + %(ReadTLog)$([System.String]::Copy('%(CustomBuild.DepFileAdditionalInputs)').Trim(';').Replace(';', ' ')) + + + + + @(CustomBuild->'%(ReadTLog)','') + + + + + diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 0a8058049bd..f8c20c2ea1e 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -172,7 +172,8 @@ if (RunCMake_GENERATOR MATCHES "Makefiles") run_cmake(CustomCommandDependencies-BadArgs) endif() -if(RunCMake_GENERATOR MATCHES "Make|Ninja|Xcode") +if(RunCMake_GENERATOR MATCHES "Make|Ninja|Visual Studio|Xcode" AND + NOT RunCMake_GENERATOR MATCHES "Visual Studio (9|10)( |$)") unset(run_BuildDepends_skip_step_3) run_BuildDepends(CustomCommandDepfile) set(run_BuildDepends_skip_step_3 1) From 82c867ad85785cdf6efed98f8fdef27419375f29 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 8 Jun 2021 11:27:39 -0400 Subject: [PATCH 0644/1519] cmScanDepFormat: P1689R4: Flatten future-compile members into parent --- Help/dev/experimental.rst | 1 + Source/cmScanDepFormat.cxx | 102 +++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 54 deletions(-) diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 3db81779be4..52feec3fae8 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -43,6 +43,7 @@ by the `P1689r3`_ paper, with the following updates: * Omit the ``outputs``, ``inputs``, and ``depends`` fields from each entry in the ``rules`` array. They are unused. +* Flatten ``future-compile`` members directly into each rule. Compiler writers may try out their scanning functionality using the `cxx-modules-sandbox`_ test project, modified to set variables diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index e66f96dfc61..8e09a785591 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -117,65 +117,61 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, return false; } - if (rule.isMember("future-compile")) { - Json::Value const& future_compile = rule["future-compile"]; - - if (future_compile.isMember("outputs")) { - Json::Value const& outputs = future_compile["outputs"]; - if (outputs.isArray()) { - if (outputs.empty()) { - cmSystemTools::Error( - cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, - ": expected at least one 1 output")); - return false; - } - - PARSE_FILENAME(outputs[0], info->PrimaryOutput); + if (rule.isMember("outputs")) { + Json::Value const& outputs = rule["outputs"]; + if (outputs.isArray()) { + if (outputs.empty()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": expected at least one 1 output")); + return false; } + + PARSE_FILENAME(outputs[0], info->PrimaryOutput); } + } - if (future_compile.isMember("provides")) { - Json::Value const& provides = future_compile["provides"]; - if (provides.isArray()) { - for (auto const& provide : provides) { - cmSourceReqInfo provide_info; - - Json::Value const& logical_name = provide["logical-name"]; - PARSE_BLOB(logical_name, provide_info.LogicalName); - - if (provide.isMember("compiled-module-path")) { - Json::Value const& compiled_module_path = - provide["compiled-module-path"]; - PARSE_FILENAME(compiled_module_path, - provide_info.CompiledModulePath); - } else { - provide_info.CompiledModulePath = - cmStrCat(provide_info.LogicalName, ".mod"); - } - - info->Provides.push_back(provide_info); + if (rule.isMember("provides")) { + Json::Value const& provides = rule["provides"]; + if (provides.isArray()) { + for (auto const& provide : provides) { + cmSourceReqInfo provide_info; + + Json::Value const& logical_name = provide["logical-name"]; + PARSE_BLOB(logical_name, provide_info.LogicalName); + + if (provide.isMember("compiled-module-path")) { + Json::Value const& compiled_module_path = + provide["compiled-module-path"]; + PARSE_FILENAME(compiled_module_path, + provide_info.CompiledModulePath); + } else { + provide_info.CompiledModulePath = + cmStrCat(provide_info.LogicalName, ".mod"); } + + info->Provides.push_back(provide_info); } } + } - if (future_compile.isMember("requires")) { - Json::Value const& reqs = future_compile["requires"]; - if (reqs.isArray()) { - for (auto const& require : reqs) { - cmSourceReqInfo require_info; - - Json::Value const& logical_name = require["logical-name"]; - PARSE_BLOB(logical_name, require_info.LogicalName); + if (rule.isMember("requires")) { + Json::Value const& reqs = rule["requires"]; + if (reqs.isArray()) { + for (auto const& require : reqs) { + cmSourceReqInfo require_info; - if (require.isMember("compiled-module-path")) { - Json::Value const& compiled_module_path = - require["compiled-module-path"]; - PARSE_FILENAME(compiled_module_path, - require_info.CompiledModulePath); - } + Json::Value const& logical_name = require["logical-name"]; + PARSE_BLOB(logical_name, require_info.LogicalName); - info->Requires.push_back(require_info); + if (require.isMember("compiled-module-path")) { + Json::Value const& compiled_module_path = + require["compiled-module-path"]; + PARSE_FILENAME(compiled_module_path, + require_info.CompiledModulePath); } + + info->Requires.push_back(require_info); } } } @@ -196,12 +192,10 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, Json::Value rule(Json::objectValue); - Json::Value& future_compile = rule["future-compile"] = Json::objectValue; - - Json::Value& outputs = future_compile["outputs"] = Json::arrayValue; + Json::Value& outputs = rule["outputs"] = Json::arrayValue; outputs.append(info.PrimaryOutput); - Json::Value& provides = future_compile["provides"] = Json::arrayValue; + Json::Value& provides = rule["provides"] = Json::arrayValue; for (auto const& provide : info.Provides) { Json::Value provide_obj(Json::objectValue); auto const encoded = EncodeFilename(provide.LogicalName); @@ -218,7 +212,7 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, provides.append(provide_obj); } - Json::Value& reqs = future_compile["requires"] = Json::arrayValue; + Json::Value& reqs = rule["requires"] = Json::arrayValue; for (auto const& require : info.Requires) { Json::Value require_obj(Json::objectValue); auto const encoded = EncodeFilename(require.LogicalName); From b0a8fa959cbf8936a7e1aa558cf0c08bfa9e0a39 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 8 Jun 2021 11:27:39 -0400 Subject: [PATCH 0645/1519] cmScanDepFormat: P1689R4: Diagnose invalid provides/requires json type --- Source/cmScanDepFormat.cxx | 70 ++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index 8e09a785591..68ed3b2ff59 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -133,46 +133,56 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, if (rule.isMember("provides")) { Json::Value const& provides = rule["provides"]; - if (provides.isArray()) { - for (auto const& provide : provides) { - cmSourceReqInfo provide_info; - - Json::Value const& logical_name = provide["logical-name"]; - PARSE_BLOB(logical_name, provide_info.LogicalName); - - if (provide.isMember("compiled-module-path")) { - Json::Value const& compiled_module_path = - provide["compiled-module-path"]; - PARSE_FILENAME(compiled_module_path, - provide_info.CompiledModulePath); - } else { - provide_info.CompiledModulePath = - cmStrCat(provide_info.LogicalName, ".mod"); - } - - info->Provides.push_back(provide_info); + if (!provides.isArray()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": provides is not an array")); + return false; + } + + for (auto const& provide : provides) { + cmSourceReqInfo provide_info; + + Json::Value const& logical_name = provide["logical-name"]; + PARSE_BLOB(logical_name, provide_info.LogicalName); + + if (provide.isMember("compiled-module-path")) { + Json::Value const& compiled_module_path = + provide["compiled-module-path"]; + PARSE_FILENAME(compiled_module_path, + provide_info.CompiledModulePath); + } else { + provide_info.CompiledModulePath = + cmStrCat(provide_info.LogicalName, ".mod"); } + + info->Provides.push_back(provide_info); } } if (rule.isMember("requires")) { Json::Value const& reqs = rule["requires"]; - if (reqs.isArray()) { - for (auto const& require : reqs) { - cmSourceReqInfo require_info; + if (!reqs.isArray()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": requires is not an array")); + return false; + } - Json::Value const& logical_name = require["logical-name"]; - PARSE_BLOB(logical_name, require_info.LogicalName); + for (auto const& require : reqs) { + cmSourceReqInfo require_info; - if (require.isMember("compiled-module-path")) { - Json::Value const& compiled_module_path = - require["compiled-module-path"]; - PARSE_FILENAME(compiled_module_path, - require_info.CompiledModulePath); - } + Json::Value const& logical_name = require["logical-name"]; + PARSE_BLOB(logical_name, require_info.LogicalName); - info->Requires.push_back(require_info); + if (require.isMember("compiled-module-path")) { + Json::Value const& compiled_module_path = + require["compiled-module-path"]; + PARSE_FILENAME(compiled_module_path, + require_info.CompiledModulePath); } + + info->Requires.push_back(require_info); } } } From aab9a5fc3e60db247c922f14420b088d9a983ff2 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 8 Jun 2021 11:27:39 -0400 Subject: [PATCH 0646/1519] cmScanDepFormat: P1689R4: Factor out primary-output field --- Help/dev/experimental.rst | 1 + Source/cmScanDepFormat.cxx | 25 ++++++++++++++++--------- Source/cmScanDepFormat.h | 1 + 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 52feec3fae8..517ffe4b1da 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -44,6 +44,7 @@ by the `P1689r3`_ paper, with the following updates: * Omit the ``outputs``, ``inputs``, and ``depends`` fields from each entry in the ``rules`` array. They are unused. * Flatten ``future-compile`` members directly into each rule. +* Factor a ``primary-output`` field out of the now-flattened ``outputs``. Compiler writers may try out their scanning functionality using the `cxx-modules-sandbox`_ test project, modified to set variables diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index 68ed3b2ff59..d75a75090d8 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -117,17 +117,20 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, return false; } + if (rule.isMember("primary-output")) { + Json::Value const& primary_output = rule["primary-output"]; + PARSE_FILENAME(primary_output, info->PrimaryOutput); + } + if (rule.isMember("outputs")) { Json::Value const& outputs = rule["outputs"]; if (outputs.isArray()) { - if (outputs.empty()) { - cmSystemTools::Error( - cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, - ": expected at least one 1 output")); - return false; - } + for (auto const& output : outputs) { + std::string extra_output; + PARSE_FILENAME(output, extra_output); - PARSE_FILENAME(outputs[0], info->PrimaryOutput); + info->ExtraOutputs.emplace_back(extra_output); + } } } @@ -202,8 +205,12 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, Json::Value rule(Json::objectValue); - Json::Value& outputs = rule["outputs"] = Json::arrayValue; - outputs.append(info.PrimaryOutput); + rule["primary-output"] = EncodeFilename(info.PrimaryOutput); + + Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue; + for (auto const& output : info.ExtraOutputs) { + rule_outputs.append(EncodeFilename(output)); + } Json::Value& provides = rule["provides"] = Json::arrayValue; for (auto const& provide : info.Provides) { diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h index 51ceec1f61b..cb8921de016 100644 --- a/Source/cmScanDepFormat.h +++ b/Source/cmScanDepFormat.h @@ -14,6 +14,7 @@ struct cmSourceReqInfo struct cmScanDepInfo { std::string PrimaryOutput; + std::vector ExtraOutputs; // Set of provided and required modules. std::vector Provides; From 3e5b609547750f0498b6ca924fb70379457653da Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 8 Jun 2021 11:27:39 -0400 Subject: [PATCH 0647/1519] cmScanDepFormat: P1689R4: Make work-directory optional --- Help/dev/experimental.rst | 1 + Source/cmScanDepFormat.cxx | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 517ffe4b1da..9cf33ebfaea 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -45,6 +45,7 @@ by the `P1689r3`_ paper, with the following updates: each entry in the ``rules`` array. They are unused. * Flatten ``future-compile`` members directly into each rule. * Factor a ``primary-output`` field out of the now-flattened ``outputs``. +* The ``work-directory`` field is optional. Compiler writers may try out their scanning functionality using the `cxx-modules-sandbox`_ test project, modified to set variables diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index d75a75090d8..a40a552a465 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -5,6 +5,9 @@ #include #include +#include + +#include #include #include @@ -69,8 +72,9 @@ static Json::Value EncodeFilename(std::string const& path) return false; \ } \ \ - if (!work_directory.empty() && !cmSystemTools::FileIsFullPath(res)) { \ - res = cmStrCat(work_directory, '/', res); \ + if (work_directory && !work_directory->empty() && \ + !cmSystemTools::FileIsFullPath(res)) { \ + res = cmStrCat(*work_directory, '/', res); \ } \ } while (0) @@ -106,10 +110,12 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, } for (auto const& rule : rules) { - std::string work_directory; + cm::optional work_directory; Json::Value const& workdir = rule["work-directory"]; if (workdir.isString()) { - PARSE_BLOB(workdir, work_directory); + std::string wd; + PARSE_BLOB(workdir, wd); + work_directory = std::move(wd); } else if (!workdir.isNull()) { cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, From cf8710da7471c69627d87a5f4bdbd30457caa40d Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 9 Jun 2021 14:33:21 -0400 Subject: [PATCH 0648/1519] Help: Document ctest(1) --interactive-debug-mode limitation Fixes: #22287 Issue: #20115 --- Help/manual/ctest.1.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 72ef2597ad1..ab819f94ef2 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -322,11 +322,13 @@ Options Set the interactive mode to ``0`` or ``1``. This option causes CTest to run tests in either an interactive mode - or a non-interactive mode. On Windows this means that in - non-interactive mode, all system debug pop up windows are blocked. - In dashboard mode (``Experimental``, ``Nightly``, ``Continuous``), the default - is non-interactive. When just running tests not for a dashboard the - default is to allow popups and interactive debugging. + or a non-interactive mode. In dashboard mode (``Experimental``, ``Nightly``, + ``Continuous``), the default is non-interactive. In non-interactive mode, + the environment variable :envvar:`DASHBOARD_TEST_FROM_CTEST` is set. + + Prior to CMake 3.11, interactive mode on Windows allowed system debug + popup windows to appear. Now, due to CTest's use of ``libuv`` to launch + test processes, all system debug popup windows are always blocked. ``--no-label-summary`` Disable timing summary information for labels. From 2086b938a7b60ce07a28840240de82687b769575 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 10 Jun 2021 00:01:12 -0400 Subject: [PATCH 0649/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bfa84e41fff..8018e406edb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210609) +set(CMake_VERSION_PATCH 20210610) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ccc0466fc56dc90de043f0d55781bf9b0ff1365a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 8 Jun 2021 11:27:39 -0400 Subject: [PATCH 0650/1519] cmScanDepFormat: P1689R4: Implement source-path related fields --- Source/cmScanDepFormat.cxx | 107 +++++++++++++++++++++++++++++++++++-- Source/cmScanDepFormat.h | 10 ++++ 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index a40a552a465..66202212c89 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -3,11 +3,14 @@ #include "cmScanDepFormat.h" +#include #include #include #include #include +#include +#include #include #include @@ -165,6 +168,30 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmStrCat(provide_info.LogicalName, ".mod"); } + if (provide.isMember("unique-on-source-path")) { + Json::Value const& unique_on_source_path = + provide["unique-on-source-path"]; + if (!unique_on_source_path.isBool()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": unique-on-source-path is not a boolean")); + return false; + } + provide_info.UseSourcePath = unique_on_source_path.asBool(); + } else { + provide_info.UseSourcePath = false; + } + + if (provide.isMember("source-path")) { + Json::Value const& source_path = provide["source-path"]; + PARSE_FILENAME(source_path, provide_info.SourcePath); + } else if (provide_info.UseSourcePath) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": source-path is missing")); + return false; + } + info->Provides.push_back(provide_info); } } @@ -191,6 +218,56 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, require_info.CompiledModulePath); } + if (require.isMember("unique-on-source-path")) { + Json::Value const& unique_on_source_path = + require["unique-on-source-path"]; + if (!unique_on_source_path.isBool()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": unique-on-source-path is not a boolean")); + return false; + } + require_info.UseSourcePath = unique_on_source_path.asBool(); + } else { + require_info.UseSourcePath = false; + } + + if (require.isMember("source-path")) { + Json::Value const& source_path = require["source-path"]; + PARSE_FILENAME(source_path, require_info.SourcePath); + } else if (require_info.UseSourcePath) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": source-path is missing")); + return false; + } + + if (require.isMember("lookup-method")) { + Json::Value const& lookup_method = require["lookup-method"]; + if (!lookup_method.isString()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": lookup-method is not a string")); + return false; + } + + std::string lookup_method_str = lookup_method.asString(); + if (lookup_method_str == "by-name"_s) { + require_info.Method = LookupMethod::ByName; + } else if (lookup_method_str == "include-angle"_s) { + require_info.Method = LookupMethod::IncludeAngle; + } else if (lookup_method_str == "include-quote"_s) { + require_info.Method = LookupMethod::IncludeQuote; + } else { + cmSystemTools::Error(cmStrCat( + "-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": lookup-method is not a valid: ", lookup_method_str)); + return false; + } + } else if (require_info.UseSourcePath) { + require_info.Method = LookupMethod::ByName; + } + info->Requires.push_back(require_info); } } @@ -230,7 +307,12 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, EncodeFilename(provide.CompiledModulePath); } - // TODO: Source file tracking. See below. + if (provide.UseSourcePath) { + provide_obj["unique-on-source-path"] = true; + provide_obj["source-path"] = EncodeFilename(provide.SourcePath); + } else if (!provide.SourcePath.empty()) { + provide_obj["source-path"] = EncodeFilename(provide.SourcePath); + } provides.append(provide_obj); } @@ -247,8 +329,27 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, EncodeFilename(require.CompiledModulePath); } - // TODO: Source filename inclusion. Requires collating with the provides - // filenames (as a sanity check if available on both sides). + if (require.UseSourcePath) { + require_obj["unique-on-source-path"] = true; + require_obj["source-path"] = EncodeFilename(require.SourcePath); + } else if (!require.SourcePath.empty()) { + require_obj["source-path"] = EncodeFilename(require.SourcePath); + } + + const char* lookup_method = nullptr; + switch (require.Method) { + case LookupMethod::ByName: + lookup_method = "by-name"; + break; + case LookupMethod::IncludeAngle: + lookup_method = "include-angle"; + break; + case LookupMethod::IncludeQuote: + lookup_method = "include-quote"; + break; + } + assert(lookup_method); + require_obj["lookup-method"] = lookup_method; reqs.append(require_obj); } diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h index cb8921de016..dae28d950bc 100644 --- a/Source/cmScanDepFormat.h +++ b/Source/cmScanDepFormat.h @@ -5,10 +5,20 @@ #include #include +enum class LookupMethod +{ + ByName, + IncludeAngle, + IncludeQuote, +}; + struct cmSourceReqInfo { std::string LogicalName; + std::string SourcePath; std::string CompiledModulePath; + bool UseSourcePath = false; + LookupMethod Method = LookupMethod::ByName; }; struct cmScanDepInfo From 45935ac973a280ea9602ba17aa448d94a66a056d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 10:51:49 -0400 Subject: [PATCH 0651/1519] Tests: Improve CPackComponentsForAll test error formatting Format message content for `message(FATAL_ERROR)`. --- .../RunCPackVerifyResult.cmake | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake index 31e843a8275..3e1c13d06f3 100644 --- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake @@ -115,8 +115,17 @@ execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${config_verbose} -G ${CPackGen} ERROR_VARIABLE CPack_error WORKING_DIRECTORY ${CPackComponentsForAll_BINARY_DIR}) +string(REPLACE "\n" "\n cpack-out> " cpack_out "\n${CPack_output}") +string(REPLACE "\n" "\n cpack-err> " cpack_err "\n${CPack_error}") +string(REPLACE "\n" "\n cpack-res> " cpack_res "\n${CPack_result}") +string(CONCAT output_error_message + "CPack output:${cpack_out}\n" + "CPack error:${cpack_err}\n" + "CPack result:${cpack_res}\n" + ) + if(CPack_result) - message(FATAL_ERROR "error: CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}") + message(FATAL_ERROR "error: CPack execution went wrong!,\n${output_error_message}") else () message(STATUS "CPack_output=${CPack_output}") endif() @@ -132,13 +141,13 @@ if(expected_file_mask) message(STATUS "expected_file_mask='${expected_file_mask}'") if(NOT expected_file) - message(FATAL_ERROR "error: expected_file does not exist: CPackComponentsForAll test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error}") + message(FATAL_ERROR "error: expected_file does not exist: CPackComponentsForAll test fails.\n${output_error_message}") endif() list(LENGTH expected_file actual_count) message(STATUS "actual_count='${actual_count}'") if(NOT actual_count EQUAL expected_count) - message(FATAL_ERROR "error: expected_count=${expected_count} does not match actual_count=${actual_count}: CPackComponents test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error})") + message(FATAL_ERROR "error: expected_count=${expected_count} does not match actual_count=${actual_count}: CPackComponents test fails.\n${output_error_message}") endif() if(expect_dmg_sla) From 624110b90daf2876058ce9bb1207d69612bd9ab9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 08:56:59 -0400 Subject: [PATCH 0652/1519] FindBLAS: Revert "Do not statically link against iomp5 ... Intel MKL" Since commit 20ab504591 (FindBLAS: Do not statically link against iomp5 in the case of Intel MKL, 2021-04-11), we no longer find MKL's BLAS when using the GNU compiler because FindOpenMP chooses libgomp instead of libiomp5, and mkl_intel_thread depends on the latter. Revert the change for now. A new approach will be needed to solve the original problem. Issue: #21811 --- Modules/FindBLAS.cmake | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 0f8360a9ddc..826a9c21d00 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -337,21 +337,12 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") if(CMAKE_Fortran_COMPILER_LOADED AND CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) set(BLAS_mkl_INTFACE "gf") set(BLAS_mkl_THREADING "gnu") + set(BLAS_mkl_OMP "gomp") else() set(BLAS_mkl_INTFACE "intel") set(BLAS_mkl_THREADING "intel") + set(BLAS_mkl_OMP "iomp5") endif() - - foreach(lang IN ITEMS C CXX Fortran) - if(CMAKE_${lang}_COMPILER_LOADED) - find_package(OpenMP COMPONENTS ${lang}) - if(${OpenMP_${lang}_FOUND}) - set(BLAS_mkl_OMP ${OpenMP_${lang}_LIBRARIES}) - break() - endif() - endif() - endforeach() - set(BLAS_mkl_LM "-lm") set(BLAS_mkl_LDL "-ldl") endif() @@ -416,7 +407,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") + "${BLAS_mkl_START_GROUP} mkl_blas95 mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All") # old version @@ -425,7 +416,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") + "${BLAS_mkl_START_GROUP} mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All") list(APPEND BLAS_SEARCH_LIBS @@ -481,7 +472,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") + "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All") # old version @@ -490,7 +481,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") # mkl >= 10.3 list(APPEND BLAS_SEARCH_LIBS - "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP}") + "${BLAS_mkl_START_GROUP} mkl_${BLAS_mkl_INTFACE}_${BLAS_mkl_ILP_MODE} mkl_${BLAS_mkl_THREADING}_thread mkl_core ${BLAS_mkl_END_GROUP} ${BLAS_mkl_OMP}") endif() if(BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All") list(APPEND BLAS_SEARCH_LIBS @@ -553,7 +544,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") ${BLAS_mkl_SEARCH_SYMBOL} "" "${SEARCH_LIBS}" - "${BLAS_mkl_OMP};${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}" + "${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}" "${BLAS_mkl_MKLROOT}" "${BLAS_mkl_LIB_PATH_SUFFIXES}" ) From daa0a1f877c410f5ee59e9860d9cba86e1475152 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 13:00:45 -0400 Subject: [PATCH 0653/1519] Find{BLAS,LAPACK}: Add tests covering Intel MKL with GNU compiler --- .../ci/configure_intelcompiler_common.cmake | 8 ++--- Tests/FindBLAS/CMakeLists.txt | 30 ++++++++++++++----- Tests/FindLAPACK/CMakeLists.txt | 30 ++++++++++++++----- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake index 79f657be92b..df3a69615d1 100644 --- a/.gitlab/ci/configure_intelcompiler_common.cmake +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -1,6 +1,6 @@ -set(CMake_TEST_FindBLAS "Intel10_64lp" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC "Intel10_64lp" CACHE STRING "") -set(CMake_TEST_FindLAPACK "Intel10_64lp" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindBLAS "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindLAPACK "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt index 63ef1dde3b7..31c701e4b3a 100644 --- a/Tests/FindBLAS/CMakeLists.txt +++ b/Tests/FindBLAS/CMakeLists.txt @@ -1,25 +1,39 @@ -foreach(vendor IN LISTS CMake_TEST_FindBLAS) - add_test(NAME FindBLAS.Test_${vendor} COMMAND +foreach(variant IN LISTS CMake_TEST_FindBLAS) + if(variant MATCHES "^([^.]+)\\.(.*)$") + set(vendor "${CMAKE_MATCH_1}") + set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") + else() + set(vendor "${variant}") + set(alt_compiler "") + endif() + add_test(NAME FindBLAS.Test_${variant} COMMAND ${CMAKE_CTEST_COMMAND} -C $ --build-and-test "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" - "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${vendor}" + "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}" ${build_generator_args} --build-project TestFindBLAS - --build-options ${build_options} -DBLA_VENDOR=${vendor} + --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) endforeach() -foreach(vendor IN LISTS CMake_TEST_FindBLAS_STATIC) - add_test(NAME FindBLAS.Test_${vendor}_Static COMMAND +foreach(variant IN LISTS CMake_TEST_FindBLAS_STATIC) + if(variant MATCHES "^([^.]+)\\.(.*)$") + set(vendor "${CMAKE_MATCH_1}") + set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") + else() + set(vendor "${variant}") + set(alt_compiler "") + endif() + add_test(NAME FindBLAS.Test_${variant}_Static COMMAND ${CMAKE_CTEST_COMMAND} -C $ --build-and-test "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" - "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${vendor}_Static" + "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}_Static" ${build_generator_args} --build-project TestFindBLAS - --build-options ${build_options} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON + --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) endforeach() diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt index eab5bb44d6a..26cfa87629d 100644 --- a/Tests/FindLAPACK/CMakeLists.txt +++ b/Tests/FindLAPACK/CMakeLists.txt @@ -1,25 +1,39 @@ -foreach(vendor IN LISTS CMake_TEST_FindLAPACK) - add_test(NAME FindLAPACK.Test_${vendor} COMMAND +foreach(variant IN LISTS CMake_TEST_FindLAPACK) + if(variant MATCHES "^([^.]+)\\.(.*)$") + set(vendor "${CMAKE_MATCH_1}") + set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") + else() + set(vendor "${variant}") + set(alt_compiler "") + endif() + add_test(NAME FindLAPACK.Test_${variant} COMMAND ${CMAKE_CTEST_COMMAND} -C $ --build-and-test "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" - "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${vendor}" + "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}" ${build_generator_args} --build-project TestFindLAPACK - --build-options ${build_options} -DBLA_VENDOR=${vendor} + --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) endforeach() -foreach(vendor IN LISTS CMake_TEST_FindLAPACK_STATIC) - add_test(NAME FindLAPACK.Test_${vendor}_Static COMMAND +foreach(variant IN LISTS CMake_TEST_FindLAPACK_STATIC) + if(variant MATCHES "^([^.]+)\\.(.*)$") + set(vendor "${CMAKE_MATCH_1}") + set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") + else() + set(vendor "${variant}") + set(alt_compiler "") + endif() + add_test(NAME FindLAPACK.Test_${variant}_Static COMMAND ${CMAKE_CTEST_COMMAND} -C $ --build-and-test "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" - "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${vendor}_Static" + "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}_Static" ${build_generator_args} --build-project TestFindLAPACK - --build-options ${build_options} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON + --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) endforeach() From 5130ff6878547aa3096340d3a7f44485a211ea35 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 13:55:37 -0400 Subject: [PATCH 0654/1519] Tests: Fix CPackComponentsForAll-RPM-IgnoreGroup test on Fedora 34 Update the cross-arch case from commit f174b919d6 (Tests: CpackRPM test component architecture, 2015-02-19, v3.3.0-rc1~415^2~1) to use `armv7hl`, which is supported by current RPM versions. Fixes: #19983 --- .../CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in | 2 +- Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in index a6f6ea9e8dd..1105cb83f1b 100644 --- a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in +++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in @@ -20,7 +20,7 @@ if(CPACK_GENERATOR MATCHES "RPM") set(CPACK_RPM_HEADERS_PACKAGE_ARCHITECTURE "noarch") # test cross-built rpm - set(CPACK_RPM_APPLICATIONS_PACKAGE_ARCHITECTURE "armv7hf") + set(CPACK_RPM_APPLICATIONS_PACKAGE_ARCHITECTURE "armv7hl") # test package summary override - headers rpm is generated in the middle set(CPACK_RPM_PACKAGE_SUMMARY "default summary") diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake index 31e843a8275..010b0559b7f 100644 --- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake @@ -261,7 +261,7 @@ if(CPackGen MATCHES "RPM") set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*") set(check_file_match_expected_description ".*${CPACK_COMPONENT_APPLICATIONS_DESCRIPTION}.*") set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") - set(check_file_match_expected_architecture "armv7hf") + set(check_file_match_expected_architecture "armv7hl") set(spec_regex "*applications*") set(check_content_list "^/usr/foo/bar /usr/foo/bar/bin From 60380bd77c93758774eb372c81c79fdf6557cffa Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 14:31:35 -0400 Subject: [PATCH 0655/1519] Tests: Fix RunCMake.CPack_RPM.DEBUGINFO test case Since commit c826745f5a (CPack/DEB: Do not crash when asked for debug symbols when there are none, 2020-10-29, v3.20.0-rc1~461^2) the test fails because CPackRPM warns about no sources in which to find debug symbols. Add expected output for this case. --- .../tests/DEBUGINFO/RPM-COMPONENT-stderr.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt b/Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt new file mode 100644 index 00000000000..8f798bbfd9a --- /dev/null +++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/RPM-COMPONENT-stderr.txt @@ -0,0 +1,17 @@ +^CMake Warning \(dev\) at [^ +]*/Modules/Internal/CPack/CPackRPM.cmake:[0-9]+ \(message\): + CPackRPM:Warning: debuginfo package was requested but will not be generated + as no source files were found! Component: 'appheaders'. +Call Stack \(most recent call first\): + [^ +]*/Modules/Internal/CPack/CPackRPM.cmake:[0-9]+ \(cpack_rpm_generate_package\) +This warning is for project developers. Use -Wno-dev to suppress it. ++ +CPackRPM: Will use GENERATED spec file: [^ +]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-appheaders.spec +CPackRPM: Will use GENERATED spec file: [^ +]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-applications.spec +CPackRPM: Will use GENERATED spec file: [^ +]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-headers.spec +CPackRPM: Will use GENERATED spec file: [^ +]*/Tests/RunCMake/RPM.DEBUGINFO/CPack/DEBUGINFO-build/_CPack_Packages/Linux/RPM/SPECS/Debuginfo-libs.spec$ From 1186ed64d0b11c6ad34010bec0cc028780a7181e Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 09:31:48 -0400 Subject: [PATCH 0656/1519] ci: add rpm-build to Fedora base image This is needed to test the CPack RPM generator. --- .gitlab/ci/docker/fedora34/install_deps.sh | 4 ++++ .gitlab/os-linux.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 146d51fd4a2..19923730c96 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -36,6 +36,10 @@ dnf install --setopt=install_weak_deps=False -y \ jq \ which +# Packages needed to test CPack. +dnf install --setopt=install_weak_deps=False -y \ + rpm-build + # Packages needed to test find modules. dnf install --setopt=install_weak_deps=False -y \ alsa-lib-devel \ diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 997beab17f3..6b490be05b3 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -69,7 +69,7 @@ ### Fedora .fedora34: - image: "kitware/cmake:ci-fedora34-x86_64-2021-06-07" + image: "kitware/cmake:ci-fedora34-x86_64-2021-06-10" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" From 369725faa5e410ca5fdc51c84e4f11af73b13ade Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 10:02:06 -0400 Subject: [PATCH 0657/1519] gitlab-ci: add job to run CPack RPM tests Run tests on Fedora in a path without spaces so the RPM tests activate. --- .gitlab-ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 754b2a11bbc..3765abcc301 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -194,6 +194,18 @@ test:fedora34-makefiles: - .run_dependent - .needs_centos6_x86_64 +test:fedora34-makefiles-nospace: + extends: + - .fedora34_makefiles + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_dependent + - .needs_centos6_x86_64 + variables: + GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake-ci" + CMAKE_CI_BUILD_NAME: fedora34_makefiles_nospace + CMAKE_CI_JOB_NIGHTLY: "true" + test:cuda10.2-nvidia: extends: - .cuda10.2_nvidia From ea6d338ea10cd9a567e727cbf3d365966cb6f43c Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 15:38:57 -0400 Subject: [PATCH 0658/1519] cmState: Record imported target names in each directory Model the change after commit 089868a244 (cmState: Record buildsystem target names in each directory, 2016-09-16, v3.7.0-rc1~79^2~3). --- Source/cmMakefile.cxx | 1 + Source/cmState.cxx | 1 + Source/cmStateDirectory.cxx | 5 +++++ Source/cmStateDirectory.h | 1 + Source/cmStatePrivate.h | 1 + 5 files changed, 9 insertions(+) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 908b3f0d25a..d2d34f9fb74 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4134,6 +4134,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, // Add to the set of available imported targets. this->ImportedTargets[name] = target.get(); this->GetGlobalGenerator()->IndexTarget(target.get()); + this->GetStateSnapshot().GetDirectory().AddImportedTargetName(name); // Transfer ownership to this cmMakefile object. this->ImportedTargetsOwned.push_back(std::move(target)); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index d97762bb6c4..0b8a64b90ed 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -286,6 +286,7 @@ cmStateSnapshot cmState::Reset() it->LinkDirectoriesBacktraces.clear(); it->DirectoryEnd = pos; it->NormalTargetNames.clear(); + it->ImportedTargetNames.clear(); it->Properties.Clear(); it->Children.clear(); } diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 9ae2861574f..76201cd8f8c 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -546,3 +546,8 @@ void cmStateDirectory::AddNormalTargetName(std::string const& name) { this->DirectoryState->NormalTargetNames.push_back(name); } + +void cmStateDirectory::AddImportedTargetName(std::string const& name) +{ + this->DirectoryState->ImportedTargetNames.emplace_back(name); +} diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index ce00dbb3c39..b8abccb81e8 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -81,6 +81,7 @@ class cmStateDirectory std::vector GetPropertyKeys() const; void AddNormalTargetName(std::string const& name); + void AddImportedTargetName(std::string const& name); private: cmLinkedTree::iterator diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index a437ce2efc1..6f475f2eea1 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -83,6 +83,7 @@ struct cmStateDetail::BuildsystemDirectoryStateType std::vector LinkDirectoriesBacktraces; std::vector NormalTargetNames; + std::vector ImportedTargetNames; std::string ProjectName; From e13704ce72a49684a835ab7ee3db9c2a928b5db5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 10 Jun 2021 15:41:39 -0400 Subject: [PATCH 0659/1519] Add directory property to list imported targets Model the change after commit cbca65826c (Add directory property to list buildsystem targets, 2016-09-19, v3.7.0-rc1~79^2~1). Fixes: #22291 --- Help/manual/cmake-properties.7.rst | 1 + Help/prop_dir/BUILDSYSTEM_TARGETS.rst | 2 ++ Help/prop_dir/IMPORTED_TARGETS.rst | 14 ++++++++++++++ Help/release/dev/dir-IMPORTED_TARGETS.rst | 6 ++++++ Source/cmStateDirectory.cxx | 6 ++++++ .../get_property/directory_properties-stderr.txt | 4 ++++ .../get_property/directory_properties.cmake | 5 +++++ .../directory_properties/CMakeLists.txt | 3 +++ 8 files changed, 41 insertions(+) create mode 100644 Help/prop_dir/IMPORTED_TARGETS.rst create mode 100644 Help/release/dev/dir-IMPORTED_TARGETS.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 2db1ec29ed7..5f18a824755 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -74,6 +74,7 @@ Properties on Directories /prop_dir/DEFINITIONS /prop_dir/EXCLUDE_FROM_ALL /prop_dir/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM + /prop_dir/IMPORTED_TARGETS /prop_dir/INCLUDE_DIRECTORIES /prop_dir/INCLUDE_REGULAR_EXPRESSION /prop_dir/INTERPROCEDURAL_OPTIMIZATION diff --git a/Help/prop_dir/BUILDSYSTEM_TARGETS.rst b/Help/prop_dir/BUILDSYSTEM_TARGETS.rst index 5c5893dfc71..c998488b4af 100644 --- a/Help/prop_dir/BUILDSYSTEM_TARGETS.rst +++ b/Help/prop_dir/BUILDSYSTEM_TARGETS.rst @@ -11,3 +11,5 @@ and :command:`add_custom_target` commands. The list does not include any :ref:`Interface Libraries`. Each entry in the list is the logical name of a target, suitable to pass to the :command:`get_property` command ``TARGET`` option. + +See also the :prop_dir:`IMPORTED_TARGETS` directory property. diff --git a/Help/prop_dir/IMPORTED_TARGETS.rst b/Help/prop_dir/IMPORTED_TARGETS.rst new file mode 100644 index 00000000000..fea8a93d49c --- /dev/null +++ b/Help/prop_dir/IMPORTED_TARGETS.rst @@ -0,0 +1,14 @@ +IMPORTED_TARGETS +---------------- + +.. versionadded:: 3.21 + +This read-only directory property contains a +:ref:`semicolon-separated list ` of +:ref:`Imported Targets` added in the directory by calls to the +:command:`add_library` and :command:`add_executable` commands. +Each entry in the list is the logical name of a target, suitable +to pass to the :command:`get_property` command ``TARGET`` option +when called in the same directory. + +See also the :prop_dir:`BUILDSYSTEM_TARGETS` directory property. diff --git a/Help/release/dev/dir-IMPORTED_TARGETS.rst b/Help/release/dev/dir-IMPORTED_TARGETS.rst new file mode 100644 index 00000000000..a2797ec6b38 --- /dev/null +++ b/Help/release/dev/dir-IMPORTED_TARGETS.rst @@ -0,0 +1,6 @@ +dir-IMPORTED_TARGETS +-------------------- + +* The :prop_dir:`IMPORTED_TARGETS` directory property was added to + get a list of :ref:`Imported Targets` created in the current + directory. diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 76201cd8f8c..c898dd47517 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -8,7 +8,9 @@ #include #include +#include #include +#include #include "cmAlgorithms.h" #include "cmProperty.h" @@ -475,6 +477,10 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const output = cmJoin(this->DirectoryState->NormalTargetNames, ";"); return &output; } + if (prop == "IMPORTED_TARGETS"_s) { + output = cmJoin(this->DirectoryState->ImportedTargetNames, ";"); + return &output; + } if (prop == "LISTFILE_STACK") { std::vector listFiles; diff --git a/Tests/RunCMake/get_property/directory_properties-stderr.txt b/Tests/RunCMake/get_property/directory_properties-stderr.txt index 89f5618ee31..be06f0ede21 100644 --- a/Tests/RunCMake/get_property/directory_properties-stderr.txt +++ b/Tests/RunCMake/get_property/directory_properties-stderr.txt @@ -12,6 +12,10 @@ get_directory_property: -->CustomTop;InterfaceTop<-- get_property: -->CustomTop;InterfaceTop<-- get_directory_property: -->CustomSub;InterfaceSub<-- get_property: -->CustomSub;InterfaceSub<-- +get_directory_property: -->Imported1Top;Imported2Top<-- +get_property: -->Imported1Top;Imported2Top<-- +get_directory_property: -->Imported1Sub;Imported2Sub<-- +get_property: -->Imported1Sub;Imported2Sub<-- get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build<-- get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build<-- get_directory_property: -->[^<;]*/RunCMake/get_property<-- diff --git a/Tests/RunCMake/get_property/directory_properties.cmake b/Tests/RunCMake/get_property/directory_properties.cmake index 9b978fd5038..4dce52440ef 100644 --- a/Tests/RunCMake/get_property/directory_properties.cmake +++ b/Tests/RunCMake/get_property/directory_properties.cmake @@ -18,11 +18,16 @@ add_custom_target(CustomTop) add_library(InterfaceTop INTERFACE) add_library(my::InterfaceTop ALIAS InterfaceTop) +add_library(Imported1Top INTERFACE IMPORTED) +add_library(Imported2Top INTERFACE IMPORTED) + add_subdirectory(directory_properties) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SUBDIRECTORIES) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" SUBDIRECTORIES) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" BUILDSYSTEM_TARGETS) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" BUILDSYSTEM_TARGETS) +check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" IMPORTED_TARGETS) +check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" IMPORTED_TARGETS) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" BINARY_DIR) check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SOURCE_DIR) diff --git a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt index 95106adca37..9fab7996752 100644 --- a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt +++ b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt @@ -5,5 +5,8 @@ add_custom_target(CustomSub) add_library(InterfaceSub INTERFACE) add_library(my::InterfaceSub ALIAS InterfaceSub) +add_library(Imported1Sub INTERFACE IMPORTED) +add_library(Imported2Sub INTERFACE IMPORTED) + add_test(Sub/test1 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test1") add_test(Sub/test2 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test2") From 8dcdd4351fd6236f05fbb613cd805fb41d2a1865 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 10 Jun 2021 16:09:04 +0200 Subject: [PATCH 0660/1519] Tests: recognize Xcode 13 linker warning The linker shipped with Xcode 13 changed the architecture mismatch linker warning into: ``` ld: warning: ignoring file libfoo.a, building for macOS-x86_64 but attempting to link with file built for macOS-i386 ``` --- Tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 57d75e180b1..2f9b7ff90d5 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -538,7 +538,7 @@ if(BUILD_TESTING) if(CTEST_TEST_OSX_ARCH) ADD_TEST_MACRO(Architecture Architecture) set_tests_properties(Architecture PROPERTIES - PASS_REGULAR_EXPRESSION "(file is not of required architecture|does not match cputype|not the architecture being linked)") + PASS_REGULAR_EXPRESSION "(file is not of required architecture|does not match cputype|not the architecture being linked|but attempting to link with file built for)") endif() list(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX}) From a7bbbbf73b7c5bb4c17ca04c31894884e55d066c Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 10 Jun 2021 22:50:06 +0200 Subject: [PATCH 0661/1519] Tests: ignore Xcode DVTPlugInManager output --- Tests/RunCMake/RunCMake.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index b4a57b209ba..3363a579e0a 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -155,6 +155,7 @@ function(run_cmake test) "|contact PGI Sales at" "|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:" + "|[^\n]*xcodebuild[^\n]*DVTPlugInManager" "|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type" "|[^\n]*objc[^\n]*: Class AMSupportURL[^\n]* One of the two will be used. Which one is undefined." "|[^\n]*is a member of multiple groups" From 42ca81ce423a16aa22cbbe314f39abb65de79961 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 11 Jun 2021 00:01:10 -0400 Subject: [PATCH 0662/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8018e406edb..8a958701b12 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210610) +set(CMake_VERSION_PATCH 20210611) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 130fa72bb336bf0a30aef297b1441594c147398e Mon Sep 17 00:00:00 2001 From: Peter Knowles Date: Wed, 9 Jun 2021 08:45:56 +0100 Subject: [PATCH 0663/1519] Find{BLAS,LAPACK}: Update for Intel oneAPI structure under MKLROOT Add search paths for the Intel oneAPI MKL directory structure so that we do not rely on paths in `LD_LIBRARY_PATH`. --- Modules/FindBLAS.cmake | 4 +++- Modules/FindLAPACK.cmake | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 826a9c21d00..dc35f0124a2 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -533,7 +533,9 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") "compiler/lib/${BLAS_mkl_ARCH_NAME}" "mkl/lib" "mkl/lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}" "mkl/lib/${BLAS_mkl_ARCH_NAME}" - "lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}") + "lib" "lib/${BLAS_mkl_ARCH_NAME}_${BLAS_mkl_OS_NAME}" + "lib/${BLAS_mkl_ARCH_NAME}" + ) foreach(IT ${BLAS_SEARCH_LIBS}) string(REPLACE " " ";" SEARCH_LIBS ${IT}) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index fa2300d6b0d..bb490399b8c 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -387,7 +387,9 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) "compiler/lib/${LAPACK_mkl_ARCH_NAME}" "mkl/lib" "mkl/lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}" "mkl/lib/${LAPACK_mkl_ARCH_NAME}" - "lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}") + "lib" "lib/${LAPACK_mkl_ARCH_NAME}_${LAPACK_mkl_OS_NAME}" + "lib/${LAPACK_mkl_ARCH_NAME}" + ) # First try empty lapack libs if(NOT ${_LIBRARIES}) From 6f305cd5fd9e027bd06d321d1c80759004855cc9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 07:06:29 -0400 Subject: [PATCH 0664/1519] Find{BLAS,LAPACK}: Factor out vendor documentation Move the list of vendors to a dedicated section shared by both modules. Format it as a definition list. --- Modules/FindBLAS.cmake | 160 ++++++++++++++++++++++++--------------- Modules/FindLAPACK.cmake | 54 +------------ 2 files changed, 100 insertions(+), 114 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 826a9c21d00..74d8bf0a84e 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -23,68 +23,8 @@ The following variables may be set to influence this module's behavior: if ``ON`` use static linkage ``BLA_VENDOR`` - If set, checks only the specified vendor, if not set checks all the - possibilities. List of vendors valid in this module: - - * ``Goto`` - * ``FlexiBLAS`` - * ``OpenBLAS`` - * ``FLAME`` - * ``ATLAS PhiPACK`` - * ``CXML`` - * ``DXML`` - * ``SunPerf`` - * ``SCSL`` - * ``SGIMATH`` - * ``IBMESSL`` - * ``Intel10_32`` (intel mkl v10 32 bit, threaded code) - * ``Intel10_64lp`` (intel mkl v10+ 64 bit, threaded code, lp64 model) - * ``Intel10_64lp_seq`` (intel mkl v10+ 64 bit, sequential code, lp64 model) - * ``Intel10_64ilp`` (intel mkl v10+ 64 bit, threaded code, ilp64 model) - * ``Intel10_64ilp_seq`` (intel mkl v10+ 64 bit, sequential code, ilp64 model) - * ``Intel10_64_dyn`` (intel mkl v10+ 64 bit, single dynamic library) - * ``Intel`` (obsolete versions of mkl 32 and 64 bit) - * ``ACML`` - * ``ACML_MP`` - * ``ACML_GPU`` - * ``Apple`` - * ``NAS`` - * ``Arm`` - * ``Arm_mp`` - * ``Arm_ilp64`` - * ``Arm_ilp64_mp`` - * ``EML`` - * ``EML_mt`` - * ``Fujitsu_SSL2`` (Fujitsu serial blas / lapack) - * ``Fujitsu_SSL2BLAMP`` (Fujitsu parallel blas / lapack) - * ``NVHPC`` - * ``Generic`` - - .. versionadded:: 3.6 - ``OpenBLAS`` support. - - .. versionadded:: 3.11 - ``FLAME`` support. - - .. versionadded:: 3.13 - Added ILP64 MKL variants (``Intel10_64ilp``, ``Intel10_64ilp_seq``). - - .. versionadded:: 3.17 - Added single dynamic library MKL variant (``Intel10_64_dyn``). - - .. versionadded:: 3.18 - Arm Performance Libraries support (``Arm``, ``Arm_mp``, ``Arm_ilp64``, - ``Arm_ilp64_mp``). - - .. versionadded:: 3.19 - ``FlexiBLAS`` support. - - .. versionadded:: 3.20 - Elbrus Math Library support (``EML``, ``EML_mt``). - Fujitsu SSL2 Library support (``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``) - - .. versionadded:: 3.21 - NVHPC support + Set to one of the :ref:`BLAS/LAPACK Vendors` to search for BLAS only + from the specified vendor. If not set, all vendors are considered. ``BLA_F95`` if ``ON`` tries to find the BLAS95 interfaces @@ -136,6 +76,102 @@ This module defines the following variables: set(BLA_VENDOR Intel10_64lp) find_package(BLAS) +.. _`BLAS/LAPACK Vendors`: + +BLAS/LAPACK Vendors +^^^^^^^^^^^^^^^^^^^ + +``Generic`` + Generic reference implementation + +``ACML``, ``ACML_MP``, ``ACML_GPU`` + AMD Core Math Library + +``Apple``, ``NAS`` + Apple BLAS (Accelerate), and Apple NAS (vecLib) + +``Arm``, ``Arm_mp``, ``Arm_ilp64``, ``Arm_ilp64_mp`` + .. versionadded:: 3.18 + + Arm Performance Libraries + +``ATLAS`` + Automatically Tuned Linear Algebra Software + +``CXML``, ``DXML`` + Compaq/Digital Extended Math Library + +``EML``, ``EML_mt`` + .. versionadded:: 3.20 + + Elbrus Math Library + +``FLAME`` + .. versionadded:: 3.11 + + BLIS Framework + +``FlexiBLAS`` + .. versionadded:: 3.19 + +``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP`` + .. versionadded:: 3.20 + + Fujitsu SSL2 serial and parallel blas/lapack + +``Goto`` + GotoBLAS + +``IBMESSL`` + IBM Engineering and Scientific Subroutine Library + +``Intel`` + Intel MKL 32 bit and 64 bit obsolete versions + +``Intel10_32`` + Intel MKL v10 32 bit, threaded code + +``Intel10_64lp`` + Intel MKL v10+ 64 bit, threaded code, lp64 model + +``Intel10_64lp_seq`` + Intel MKL v10+ 64 bit, sequential code, lp64 model + +``Intel10_64ilp`` + .. versionadded:: 3.13 + + Intel MKL v10+ 64 bit, threaded code, ilp64 model + +``Intel10_64ilp_seq`` + .. versionadded:: 3.13 + + Intel MKL v10+ 64 bit, sequential code, ilp64 model + +``Intel10_64_dyn`` + .. versionadded:: 3.17 + + Intel MKL v10+ 64 bit, single dynamic library + +``NVHPC`` + .. versionadded:: 3.21 + + NVIDIA HPC SDK + +``OpenBLAS`` + .. versionadded:: 3.6 + +``PhiPACK`` + Portable High Performance ANSI C (PHiPAC) + +``SCSL`` + Scientific Computing Software Library + +``SGIMATH`` + SGI Scientific Mathematical Library + +``SunPerf`` + Sun Performance Library + Hints ^^^^^ diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index fa2300d6b0d..593b5e83800 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -23,58 +23,8 @@ The following variables may be set to influence this module's behavior: if ``ON`` use static linkage ``BLA_VENDOR`` - If set, checks only the specified vendor, if not set checks all the - possibilities. List of vendors valid in this module: - - * ``FlexiBLAS`` - * ``OpenBLAS`` - * ``FLAME`` - * ``Intel10_32`` (intel mkl v10 32 bit, threaded code) - * ``Intel10_64lp`` (intel mkl v10+ 64 bit, threaded code, lp64 model) - * ``Intel10_64lp_seq`` (intel mkl v10+ 64 bit, sequential code, lp64 model) - * ``Intel10_64ilp`` (intel mkl v10+ 64 bit, threaded code, ilp64 model) - * ``Intel10_64ilp_seq`` (intel mkl v10+ 64 bit, sequential code, ilp64 model) - * ``Intel10_64_dyn`` (intel mkl v10+ 64 bit, single dynamic library) - * ``Intel`` (obsolete versions of mkl 32 and 64 bit) - * ``ACML`` - * ``Apple`` - * ``NAS`` - * ``Arm`` - * ``Arm_mp`` - * ``Arm_ilp64`` - * ``Arm_ilp64_mp`` - * ``EML`` - * ``EML_mt`` - * ``Fujitsu_SSL2`` (Fujitsu serial blas / lapack) - * ``Fujitsu_SSL2BLAMP`` (Fujitsu parallel blas / lapack) - * ``NVHPC`` - * ``Generic`` - - .. versionadded:: 3.6 - ``OpenBLAS`` support. - - .. versionadded:: 3.11 - ``FLAME`` support. - - .. versionadded:: 3.13 - Added ILP64 MKL variants (``Intel10_64ilp``, ``Intel10_64ilp_seq``). - - .. versionadded:: 3.17 - Added single dynamic library MKL variant (``Intel10_64_dyn``). - - .. versionadded:: 3.18 - Arm Performance Libraries support (``Arm``, ``Arm_mp``, ``Arm_ilp64``, - ``Arm_ilp64_mp``). - - .. versionadded:: 3.19 - ``FlexiBLAS`` support. - - .. versionadded:: 3.20 - Elbrus Math Library support (``EML``, ``EML_mt``). - Fujitsu SSL2 Library support (``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``) - - .. versionadded:: 3.21 - NVHPC support + Set to one of the :ref:`BLAS/LAPACK Vendors` to search for BLAS only + from the specified vendor. If not set, all vendors are considered. ``BLA_F95`` if ``ON`` tries to find the BLAS95/LAPACK95 interfaces From 3beac78a133a6bc23a77530490cffe978d9f1311 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 07:58:15 -0400 Subject: [PATCH 0665/1519] Find{BLAS,LAPACK}: Revise imported targets documentation layout --- Modules/FindBLAS.cmake | 7 +++---- Modules/FindLAPACK.cmake | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 74d8bf0a84e..f0778140a9f 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -38,13 +38,12 @@ The following variables may be set to influence this module's behavior: Imported targets ^^^^^^^^^^^^^^^^ -.. versionadded:: 3.18 - -This module defines the following :prop_tgt:`IMPORTED` target: +This module defines the following :prop_tgt:`IMPORTED` targets: ``BLAS::BLAS`` - The libraries to use for BLAS, if found. + .. versionadded:: 3.18 + The libraries to use for BLAS, if found. Result Variables ^^^^^^^^^^^^^^^^ diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 593b5e83800..3eeb4b2998a 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -38,11 +38,11 @@ The following variables may be set to influence this module's behavior: Imported targets ^^^^^^^^^^^^^^^^ -.. versionadded:: 3.18 - -This module defines the following :prop_tgt:`IMPORTED` target: +This module defines the following :prop_tgt:`IMPORTED` targets: ``LAPACK::LAPACK`` + .. versionadded:: 3.18 + The libraries to use for LAPACK, if found. Result Variables From 43b581367d71ce45bb36ef0fc3bf77bfbea98af2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 08:00:22 -0400 Subject: [PATCH 0666/1519] Find{BLAS,LAPACK}: Move implementation note from docs to comments --- Modules/FindBLAS.cmake | 7 +++---- Modules/FindLAPACK.cmake | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index f0778140a9f..ae4f779fe32 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -10,10 +10,6 @@ Find Basic Linear Algebra Subprograms (BLAS) library This module finds an installed Fortran library that implements the BLAS linear-algebra interface (see http://www.netlib.org/blas/). -The approach follows that taken for the ``autoconf`` macro file, -``acx_blas.m4`` (distributed at -http://ac-archive.sourceforge.net/ac-archive/acx_blas.html). - Input Variables ^^^^^^^^^^^^^^^ @@ -184,6 +180,9 @@ Hints #]=======================================================================] +# The approach follows that of the ``autoconf`` macro file, ``acx_blas.m4`` +# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_blas.html). + # Check the language being used if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED)) if(BLAS_FIND_REQUIRED) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 3eeb4b2998a..7026f1112ad 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -10,10 +10,6 @@ Find Linear Algebra PACKage (LAPACK) library This module finds an installed Fortran library that implements the LAPACK linear-algebra interface (see http://www.netlib.org/lapack/). -The approach follows that taken for the ``autoconf`` macro file, -``acx_lapack.m4`` (distributed at -http://ac-archive.sourceforge.net/ac-archive/acx_lapack.html). - Input Variables ^^^^^^^^^^^^^^^ @@ -76,6 +72,9 @@ This module defines the following variables: find_package(LAPACK) #]=======================================================================] +# The approach follows that of the ``autoconf`` macro file, ``acx_lapack.m4`` +# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_lapack.html). + if(CMAKE_Fortran_COMPILER_LOADED) include(${CMAKE_CURRENT_LIST_DIR}/CheckFortranFunctionExists.cmake) else() From 6a7c055f96c02587d36c57a33f5e37cb95c53fac Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 08:02:59 -0400 Subject: [PATCH 0667/1519] Find{BLAS,LAPACK}: Revise formatting of intro docs --- Modules/FindBLAS.cmake | 4 +++- Modules/FindLAPACK.cmake | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index ae4f779fe32..00ce9467928 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -8,7 +8,9 @@ FindBLAS Find Basic Linear Algebra Subprograms (BLAS) library This module finds an installed Fortran library that implements the -BLAS linear-algebra interface (see http://www.netlib.org/blas/). +`BLAS linear-algebra interface`_. + +.. _`BLAS linear-algebra interface`: http://www.netlib.org/blas/ Input Variables ^^^^^^^^^^^^^^^ diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 7026f1112ad..2d396d1d74c 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -8,7 +8,9 @@ FindLAPACK Find Linear Algebra PACKage (LAPACK) library This module finds an installed Fortran library that implements the -LAPACK linear-algebra interface (see http://www.netlib.org/lapack/). +`LAPACK linear-algebra interface`_. + +.. _`LAPACK linear-algebra interface`: http://www.netlib.org/lapack/ Input Variables ^^^^^^^^^^^^^^^ From 8585a12bd94241a6527cee22e840c430a45fead3 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 08:40:37 -0400 Subject: [PATCH 0668/1519] Find{BLAS,LAPACK}: Move enabled language requirement to top of documentation --- Modules/FindBLAS.cmake | 3 ++- Modules/FindLAPACK.cmake | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 00ce9467928..ed816faa679 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -10,6 +10,8 @@ Find Basic Linear Algebra Subprograms (BLAS) library This module finds an installed Fortran library that implements the `BLAS linear-algebra interface`_. +At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled. + .. _`BLAS linear-algebra interface`: http://www.netlib.org/blas/ Input Variables @@ -63,7 +65,6 @@ This module defines the following variables: .. note:: - C, CXX or Fortran must be enabled to detect a BLAS library. C or CXX must be enabled to use Intel Math Kernel Library (MKL). For example, to use Intel MKL libraries and/or Intel compiler: diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 2d396d1d74c..740dc28feb4 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -10,6 +10,8 @@ Find Linear Algebra PACKage (LAPACK) library This module finds an installed Fortran library that implements the `LAPACK linear-algebra interface`_. +At least one of the ``C``, ``CXX``, or ``Fortran`` languages must be enabled. + .. _`LAPACK linear-algebra interface`: http://www.netlib.org/lapack/ Input Variables @@ -63,7 +65,6 @@ This module defines the following variables: .. note:: - C, CXX or Fortran must be enabled to detect a BLAS/LAPACK library. C or CXX must be enabled to use Intel Math Kernel Library (MKL). For example, to use Intel MKL libraries and/or Intel compiler: From 5bf16514525eabc179b826d3caa5114afb51d9ad Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 08:41:25 -0400 Subject: [PATCH 0669/1519] Find{BLAS,LAPACK}: Revise and extend Intel MKL usage documentation Fixes: #22295 --- Modules/FindBLAS.cmake | 77 ++++++++++++++++++++++++++++++---------- Modules/FindLAPACK.cmake | 19 ++++++---- 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index ed816faa679..7c36f128a66 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -63,17 +63,6 @@ This module defines the following variables: ``BLAS95_FOUND`` library implementing the BLAS95 interface is found -.. note:: - - C or CXX must be enabled to use Intel Math Kernel Library (MKL). - - For example, to use Intel MKL libraries and/or Intel compiler: - - .. code-block:: cmake - - set(BLA_VENDOR Intel10_64lp) - find_package(BLAS) - .. _`BLAS/LAPACK Vendors`: BLAS/LAPACK Vendors @@ -170,16 +159,66 @@ BLAS/LAPACK Vendors ``SunPerf`` Sun Performance Library -Hints -^^^^^ +.. _`Intel MKL`: + +Intel MKL +^^^^^^^^^ + +To use the Intel MKL implementation of BLAS, a project must enable at least +one of the ``C`` or ``CXX`` languages. Set ``BLA_VENDOR`` to an Intel MKL +variant either on the command-line as ``-DBLA_VENDOR=Intel10_64lp`` or in +project code: + +.. code-block:: cmake + + set(BLA_VENDOR Intel10_64lp) + find_package(BLAS) + +In order to build a project using Intel MKL, and end user must first +establish an Intel MKL environment: + +Intel oneAPI + Source the full Intel environment script: + + .. code-block:: shell + + . /opt/intel/oneapi/setvars.sh + + Or, source the MKL component environment script: + + .. code-block:: shell + + . /opt/intel/oneapi/mkl/latest/env/vars.sh + +Intel Classic + Source the full Intel environment script: + + .. code-block:: shell + + . /opt/intel/bin/compilervars.sh intel64 + + Or, source the MKL component environment script: + + .. code-block:: shell + + . /opt/intel/mkl/bin/mklvars.sh intel64 + +The above environment scripts set the ``MKLROOT`` environment variable +to the top of the MKL installation. They also add the location of the +runtime libraries to the dynamic library loader environment variable for +your platform (e.g. ``LD_LIBRARY_PATH``). This is necessary for programs +linked against MKL to run. + +.. note:: + + As of Intel oneAPI 2021.2, loading only the MKL component does not + make all of its dependencies available. In particular, the ``iomp5`` + library must be available separately, or provided by also loading + the compiler component environment: -``MKLROOT`` - .. versionadded:: 3.15 + .. code-block:: shell - Set this environment variable to a directory that contains an MKL - installation, or add the directory to the dynamic library loader environment - variable for your platform (``LIB``, ``DYLD_LIBRARY_PATH`` or - ``LD_LIBRARY_PATH``). + . /opt/intel/oneapi/compiler/latest/env/vars.sh #]=======================================================================] diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 740dc28feb4..725a70cefc7 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -63,16 +63,23 @@ This module defines the following variables: ``LAPACK95_FOUND`` library implementing the LAPACK95 interface is found -.. note:: +Intel MKL +^^^^^^^^^ - C or CXX must be enabled to use Intel Math Kernel Library (MKL). +To use the Intel MKL implementation of LAPACK, a project must enable at least +one of the ``C`` or ``CXX`` languages. Set ``BLA_VENDOR`` to an Intel MKL +variant either on the command-line as ``-DBLA_VENDOR=Intel10_64lp`` or in +project code: - For example, to use Intel MKL libraries and/or Intel compiler: +.. code-block:: cmake - .. code-block:: cmake + set(BLA_VENDOR Intel10_64lp) + find_package(LAPACK) + +In order to build a project using Intel MKL, and end user must first +establish an Intel MKL environment. See the :module:`FindBLAS` module +section on :ref:`Intel MKL` for details. - set(BLA_VENDOR Intel10_64lp) - find_package(LAPACK) #]=======================================================================] # The approach follows that of the ``autoconf`` macro file, ``acx_lapack.m4`` From e8dc95ae1ec0f0ded781b7b36f3117e499502273 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Fri, 11 Jun 2021 13:40:57 +0200 Subject: [PATCH 0670/1519] ObjectiveC: Add C17 and C23 support Issue: #22297 --- Help/release/dev/objc-std-17-23.rst | 4 ++++ Modules/CMakeOBJCCompiler.cmake.in | 2 ++ Modules/CMakeOBJCCompilerId.m.in | 4 ++++ Modules/Compiler/AppleClang-OBJC.cmake | 16 +++++++++++++++- Modules/Compiler/Clang-OBJC.cmake | 12 ++++++++++++ Source/cmStandardLevelResolver.cxx | 5 +++-- 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 Help/release/dev/objc-std-17-23.rst diff --git a/Help/release/dev/objc-std-17-23.rst b/Help/release/dev/objc-std-17-23.rst new file mode 100644 index 00000000000..5aba3951e8a --- /dev/null +++ b/Help/release/dev/objc-std-17-23.rst @@ -0,0 +1,4 @@ +objc-std-17-23 +-------------- + +* :prop_tgt:`OBJC_STANDARD` gained support for C17 and C23. diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in index 608adce0fd8..ab67bf3961c 100644 --- a/Modules/CMakeOBJCCompiler.cmake.in +++ b/Modules/CMakeOBJCCompiler.cmake.in @@ -9,6 +9,8 @@ set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@") set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@") set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@") set(CMAKE_OBJC11_COMPILE_FEATURES "@CMAKE_OBJC11_COMPILE_FEATURES@") +set(CMAKE_OBJC17_COMPILE_FEATURES "@CMAKE_OBJC17_COMPILE_FEATURES@") +set(CMAKE_OBJC23_COMPILE_FEATURES "@CMAKE_OBJC23_COMPILE_FEATURES@") set(CMAKE_OBJC_PLATFORM_ID "@CMAKE_OBJC_PLATFORM_ID@") set(CMAKE_OBJC_SIMULATE_ID "@CMAKE_OBJC_SIMULATE_ID@") diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in index 2b8aa3020e6..418fd4852ff 100644 --- a/Modules/CMakeOBJCCompilerId.m.in +++ b/Modules/CMakeOBJCCompilerId.m.in @@ -27,6 +27,10 @@ char const* qnxnto = "INFO" ":" "qnxnto[]"; # else # define C_DIALECT # endif +#elif __STDC_VERSION__ > 201710L +# define C_DIALECT "23" +#elif __STDC_VERSION__ >= 201710L +# define C_DIALECT "17" #elif __STDC_VERSION__ >= 201000L # define C_DIALECT "11" #elif __STDC_VERSION__ >= 199901L diff --git a/Modules/Compiler/AppleClang-OBJC.cmake b/Modules/Compiler/AppleClang-OBJC.cmake index d4eab4f63a2..f40c3961556 100644 --- a/Modules/Compiler/AppleClang-OBJC.cmake +++ b/Modules/Compiler/AppleClang-OBJC.cmake @@ -23,4 +23,18 @@ if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON) endif() -__compiler_check_default_language_standard(OBJC 4.0 99) +# AppleClang 10.0 was the oldest compiler available to test C17 support +if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 10.0) + set(CMAKE_OBJC17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_OBJC17_EXTENSION_COMPILE_OPTION "-std=gnu17") + set(CMAKE_OBJC17_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 11.0) + set(CMAKE_OBJC23_STANDARD_COMPILE_OPTION "-std=c2x") + set(CMAKE_OBJC23_EXTENSION_COMPILE_OPTION "-std=gnu2x") + set(CMAKE_OBJC23_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +# AppleClang 10.0 was the oldest compiler available to test default C11 support +__compiler_check_default_language_standard(OBJC 4.0 99 10.0 11) diff --git a/Modules/Compiler/Clang-OBJC.cmake b/Modules/Compiler/Clang-OBJC.cmake index 19179e36e54..7a83b77fc90 100644 --- a/Modules/Compiler/Clang-OBJC.cmake +++ b/Modules/Compiler/Clang-OBJC.cmake @@ -24,4 +24,16 @@ if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON) endif() +if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 6.0) + set(CMAKE_OBJC17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_OBJC17_EXTENSION_COMPILE_OPTION "-std=gnu17") + set(CMAKE_OBJC17_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 9.0) + set(CMAKE_OBJC23_STANDARD_COMPILE_OPTION "-std=c2x") + set(CMAKE_OBJC23_EXTENSION_COMPILE_OPTION "-std=gnu2x") + set(CMAKE_OBJC23_STANDARD__HAS_FULL_SUPPORT ON) +endif() + __compiler_check_default_language_standard(OBJC 3.4 99 3.6 11) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 73d0feddf6c..37ed4c130ac 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -322,8 +322,9 @@ std::unordered_map StandardComputerMapping = "CUDA", std::vector{ 03, 11, 14, 17, 20, 23 }, std::vector{ "03", "11", "14", "17", "20", "23" } } }, { "OBJC", - StanardLevelComputer{ "OBJC", std::vector{ 90, 99, 11 }, - std::vector{ "90", "99", "11" } } }, + StanardLevelComputer{ + "OBJC", std::vector{ 90, 99, 11, 17, 23 }, + std::vector{ "90", "99", "11", "17", "23" } } }, { "OBJCXX", StanardLevelComputer{ "OBJCXX", std::vector{ 98, 11, 14, 17, 20, 23 }, From 68bbec66e094e21bdace9607768895b0d381cc2c Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 11 Jun 2021 10:52:06 -0400 Subject: [PATCH 0671/1519] fileapi: Fix codemodel-v2 link command fragment relative paths Use the same `cmLinkLineComputer` subclass as the generator does. This affects the base directory from which relative paths are computed. Fixes: #22301 --- Source/cmFileAPICodemodel.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 90611092bad..c96eecda1f4 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -27,7 +27,7 @@ #include "cmInstallGenerator.h" #include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" -#include "cmLinkLineComputer.h" +#include "cmLinkLineComputer.h" // IWYU pragma: keep #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -1444,9 +1444,10 @@ Json::Value Target::DumpLinkCommandFragments() std::vector> linkPath; std::vector> linkLibs; cmLocalGenerator* lg = this->GT->GetLocalGenerator(); - cmLinkLineComputer linkLineComputer(lg, - lg->GetStateSnapshot().GetDirectory()); - lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs, + cmGlobalGenerator* gg = this->GT->GetGlobalGenerator(); + std::unique_ptr linkLineComputer = + gg->CreateLinkLineComputer(lg, lg->GetStateSnapshot().GetDirectory()); + lg->GetTargetFlags(linkLineComputer.get(), this->Config, linkLibs, linkLanguageFlags, linkFlags, frameworkPath, linkPath, this->GT); linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags); From 8a4f3fd8611b9ea3b18d4f74c42d071f10d306a7 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 12 Jun 2021 00:01:11 -0400 Subject: [PATCH 0672/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8a958701b12..6077ec65a65 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210611) +set(CMake_VERSION_PATCH 20210612) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e49cbf1d440b8c54fa5acd806f91475092708bc3 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sat, 12 Jun 2021 11:18:37 +0200 Subject: [PATCH 0673/1519] Help: cmake_path: fix erroneous example for IS_PREFIX --- Help/command/cmake_path.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst index a8999f35b12..e7a01ab6091 100644 --- a/Help/command/cmake_path.rst +++ b/Help/command/cmake_path.rst @@ -459,9 +459,10 @@ are :ref:`normalized ` before the check. .. code-block:: cmake - set(path "/a/b/c/d") - cmake_path(IS_PREFIX path "/a/b" result) # result = true - cmake_path(IS_PREFIX path "/x/y/z" result) # result = false + set(path "/a/b/c") + cmake_path(IS_PREFIX path "/a/b/c/d" result) # result = true + cmake_path(IS_PREFIX path "/a/b" result) # result = false + cmake_path(IS_PREFIX path "/x/y/z" result) # result = false set(path "/a/b") cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result) # result = true From 4665d1e69ad07b9c147db5b6e140235ea2f5ab9d Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sat, 12 Jun 2021 11:23:47 +0200 Subject: [PATCH 0674/1519] Help: cmake_path: fix erroneous example for IS_PREFIX Fixes: #22302 --- Help/command/cmake_path.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst index 193180d1728..565a37b6a85 100644 --- a/Help/command/cmake_path.rst +++ b/Help/command/cmake_path.rst @@ -459,9 +459,10 @@ are :ref:`normalized ` before the check. .. code-block:: cmake - set(path "/a/b/c/d") - cmake_path(IS_PREFIX path "/a/b" result) # result = true - cmake_path(IS_PREFIX path "/x/y/z" result) # result = false + set(path "/a/b/c") + cmake_path(IS_PREFIX path "/a/b/c/d" result) # result = true + cmake_path(IS_PREFIX path "/a/b" result) # result = false + cmake_path(IS_PREFIX path "/x/y/z" result) # result = false set(path "/a/b") cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result) # result = true From d0ddef58128799dcb2a139365c1eecbb6c046aab Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 13 Jun 2021 00:01:06 -0400 Subject: [PATCH 0675/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6077ec65a65..4f77c4d3605 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210612) +set(CMake_VERSION_PATCH 20210613) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6230be49753a7a8bcf833f5aa896e3b5ed5c13ae Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 14 Jun 2021 00:01:14 -0400 Subject: [PATCH 0676/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4f77c4d3605..c5366391a4a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210613) +set(CMake_VERSION_PATCH 20210614) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b61fe6a831c72050c3a4f830445f98696b0cedf7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 11:05:49 -0400 Subject: [PATCH 0677/1519] CMake 3.20.4 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e0d72f22888..47107996224 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 3) +set(CMake_VERSION_PATCH 4) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 046aee0441b9d21da322d2836a96f7dbbd818e09 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 12:14:28 -0400 Subject: [PATCH 0678/1519] Help: Consolidate 3.21 release notes Run the `Utilities/Release/consolidate-relnotes.bash` script to move notes from `Help/release/dev/*` into `Help/release/3.21.rst`. --- Help/release/3.21.rst | 235 ++++++++++++++++++ Help/release/dev/ARMClang-cpu-arch-flags.rst | 7 - .../dev/FindDevIL-imported-targets.rst | 4 - Help/release/dev/FindIconv-version.rst | 4 - Help/release/dev/FindIntl-version.rst | 4 - Help/release/dev/FindMsys.rst | 6 - ...n-add-Headers-glslangValidator-targets.rst | 5 - .../dev/UseJava-RESOURCES-NAMESPACE.rst | 5 - Help/release/dev/UseSWIG-csharp.rst | 5 - Help/release/dev/UseSWIG-dependencies.rst | 6 - .../dev/add_custom_command-DEPFILE-genex.rst | 5 - .../dev/add_custom_command-DEPFILE.rst | 6 - .../dev/add_custom_command-TARGET-genex.rst | 5 - Help/release/dev/c-std.rst | 6 - .../dev/capabilties-generator-platforms.rst | 6 - .../dev/cmake-install-prefix-command.rst | 8 - Help/release/dev/cmake-presets-condition.rst | 4 - .../dev/cmake-presets-host-system-name.rst | 5 - ...esets-optional-generator-and-binarydir.rst | 5 - .../release/dev/cmake-system-name-version.rst | 10 - Help/release/dev/cmake-toolchain-command.rst | 5 - Help/release/dev/compile-options-order.rst | 7 - Help/release/dev/cpack-dmg-filesystem.rst | 5 - Help/release/dev/cpack-install-opts.rst | 6 - .../dev/cpack-nsis-executable-name.rst | 6 - Help/release/dev/ctest-measurements-docs.rst | 5 - Help/release/dev/ctest-output-junit.rst | 5 - Help/release/dev/ctest-runtime-files.rst | 8 - Help/release/dev/cxx-module-extensions.rst | 4 - Help/release/dev/dir-IMPORTED_TARGETS.rst | 6 - Help/release/dev/env-toolchain-file.rst | 5 - Help/release/dev/file-COPY_FILE.rst | 4 - .../dev/file-REAL_PATH-EXPAND_TILDE.rst | 5 - Help/release/dev/file-RENAME.rst | 6 - .../dev/fileapi-codemodel-directory.rst | 10 - Help/release/dev/find_item-NO_CACHE.rst | 6 - .../dev/find_item-consistent-behavior.rst | 6 - Help/release/dev/foreach-variable-scope.rst | 5 - Help/release/dev/fujitsu-compiler-support.rst | 11 - .../generate-cmake-build-command-parallel.rst | 6 - .../get-runtime-dependencies-file-filter.rst | 5 - Help/release/dev/hip.rst | 5 - .../dev/ifw-default-version-operator.rst | 7 - .../install-imported-runtime-artifacts.rst | 5 - .../dev/install-runtime-dependencies.rst | 9 - .../dev/install-script-all-components.rst | 7 - Help/release/dev/link-objects-first.rst | 8 - Help/release/dev/linker-launcher.rst | 7 - Help/release/dev/list-index-arg-parsing.rst | 7 - Help/release/dev/lzma-threads.rst | 7 - Help/release/dev/message-color.rst | 4 - Help/release/dev/msys.rst | 4 - Help/release/dev/ninja-absolute-paths.rst | 6 - Help/release/dev/nmake-utf8.rst | 5 - Help/release/dev/objc-std-17-23.rst | 4 - Help/release/dev/project-is-top-level.rst | 6 - Help/release/dev/runtime-dll-deps.rst | 4 - Help/release/dev/set-cache-variable.rst | 5 - Help/release/dev/xcode_app_extensions.rst | 11 - Help/release/index.rst | 1 + 60 files changed, 236 insertions(+), 343 deletions(-) create mode 100644 Help/release/3.21.rst delete mode 100644 Help/release/dev/ARMClang-cpu-arch-flags.rst delete mode 100644 Help/release/dev/FindDevIL-imported-targets.rst delete mode 100644 Help/release/dev/FindIconv-version.rst delete mode 100644 Help/release/dev/FindIntl-version.rst delete mode 100644 Help/release/dev/FindMsys.rst delete mode 100644 Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst delete mode 100644 Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst delete mode 100644 Help/release/dev/UseSWIG-csharp.rst delete mode 100644 Help/release/dev/UseSWIG-dependencies.rst delete mode 100644 Help/release/dev/add_custom_command-DEPFILE-genex.rst delete mode 100644 Help/release/dev/add_custom_command-DEPFILE.rst delete mode 100644 Help/release/dev/add_custom_command-TARGET-genex.rst delete mode 100644 Help/release/dev/c-std.rst delete mode 100644 Help/release/dev/capabilties-generator-platforms.rst delete mode 100644 Help/release/dev/cmake-install-prefix-command.rst delete mode 100644 Help/release/dev/cmake-presets-condition.rst delete mode 100644 Help/release/dev/cmake-presets-host-system-name.rst delete mode 100644 Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst delete mode 100644 Help/release/dev/cmake-system-name-version.rst delete mode 100644 Help/release/dev/cmake-toolchain-command.rst delete mode 100644 Help/release/dev/compile-options-order.rst delete mode 100644 Help/release/dev/cpack-dmg-filesystem.rst delete mode 100644 Help/release/dev/cpack-install-opts.rst delete mode 100644 Help/release/dev/cpack-nsis-executable-name.rst delete mode 100644 Help/release/dev/ctest-measurements-docs.rst delete mode 100644 Help/release/dev/ctest-output-junit.rst delete mode 100644 Help/release/dev/ctest-runtime-files.rst delete mode 100644 Help/release/dev/cxx-module-extensions.rst delete mode 100644 Help/release/dev/dir-IMPORTED_TARGETS.rst delete mode 100644 Help/release/dev/env-toolchain-file.rst delete mode 100644 Help/release/dev/file-COPY_FILE.rst delete mode 100644 Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst delete mode 100644 Help/release/dev/file-RENAME.rst delete mode 100644 Help/release/dev/fileapi-codemodel-directory.rst delete mode 100644 Help/release/dev/find_item-NO_CACHE.rst delete mode 100644 Help/release/dev/find_item-consistent-behavior.rst delete mode 100644 Help/release/dev/foreach-variable-scope.rst delete mode 100644 Help/release/dev/fujitsu-compiler-support.rst delete mode 100644 Help/release/dev/generate-cmake-build-command-parallel.rst delete mode 100644 Help/release/dev/get-runtime-dependencies-file-filter.rst delete mode 100644 Help/release/dev/hip.rst delete mode 100644 Help/release/dev/ifw-default-version-operator.rst delete mode 100644 Help/release/dev/install-imported-runtime-artifacts.rst delete mode 100644 Help/release/dev/install-runtime-dependencies.rst delete mode 100644 Help/release/dev/install-script-all-components.rst delete mode 100644 Help/release/dev/link-objects-first.rst delete mode 100644 Help/release/dev/linker-launcher.rst delete mode 100644 Help/release/dev/list-index-arg-parsing.rst delete mode 100644 Help/release/dev/lzma-threads.rst delete mode 100644 Help/release/dev/message-color.rst delete mode 100644 Help/release/dev/msys.rst delete mode 100644 Help/release/dev/ninja-absolute-paths.rst delete mode 100644 Help/release/dev/nmake-utf8.rst delete mode 100644 Help/release/dev/objc-std-17-23.rst delete mode 100644 Help/release/dev/project-is-top-level.rst delete mode 100644 Help/release/dev/runtime-dll-deps.rst delete mode 100644 Help/release/dev/set-cache-variable.rst delete mode 100644 Help/release/dev/xcode_app_extensions.rst diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst new file mode 100644 index 00000000000..609ffb504fd --- /dev/null +++ b/Help/release/3.21.rst @@ -0,0 +1,235 @@ +CMake 3.21 Release Notes +************************ + +.. only:: html + + .. contents:: + +Changes made since CMake 3.20 include the following. + +* The :command:`add_custom_command` command ``DEPFILE`` option learned to + support :manual:`generator expressions `. + +* The :command:`add_custom_command` command gained ``DEPFILE`` support on + the :generator:`Xcode` generator, and on :ref:`Visual Studio Generators` + for VS 2012 and above. + +* The :ref:`add_custom_command(TARGET) ` command + gained support for resolving target-dependent generator expressions. + +* ``ARMClang`` cpu/arch compile and link flags are no longer added + automatically based on the :variable:`CMAKE_SYSTEM_PROCESSOR` + variable or the undocumented ``CMAKE_SYSTEM_ARCH`` variable. + They must be specified explicitly. See policy :policy:`CMP0123`. + +* The :manual:`cmake(1)` ``-E capabilities`` output now contains for each + generator a ``supportedPlatforms`` field listing platform known to + be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. + +* The :manual:`cmake(1)` command gained the ``--install-prefix `` + command line option to specify the location of the install prefix. + +* :manual:`cmake-presets(7)` configure preset gained support for specifying + the install prefix. + +* :manual:`cmake-presets(7)` now support conditional enabling of presets. + +* :manual:`cmake-presets(7)` gained support for a new ``${hostSystemName}`` + macro. + +* :manual:`cmake-presets(7)` now support omitting the ``generator`` and + ``binaryDir`` fields. + +* :variable:`CMAKE_HOST_SYSTEM_NAME`'s undocumented version-stripping behavior + has been moved earlier, before :command:`project` or + :command:`enable_language` is called. +* :variable:`CMAKE_SYSTEM_NAME`'s undocumented version-stripping behavior has + been removed entirely. If it is set by a ``-D`` flag or by a + :manual:`toolchain file `, it is left unaltered, even if + it still contains a version number. + +* The :manual:`cmake(1)` command gained the ``--toolchain `` + command line option to specify a toolchain file. + +* The :ref:`Visual Studio Generators` for VS 2010 and above now place + per-source preprocessor definitions after target-wide preprocssor + definitions. This makes VS consistent with the :ref:`Ninja Generators` + and the :ref:`Makefile Generators`. + +* The :cpack_gen:`CPack DragNDrop Generator` gained option + :variable:`CPACK_DMG_FILESYSTEM` to control the ``.dmg`` filesystem. + +* The new :variable:`CPACK_CUSTOM_INSTALL_VARIABLES` + can be used to set variables in CPack ``cmake_install.cmake`` + invocations. + +* The :cpack_gen:`CPack NSIS Generator` gained a new variable + :variable:`CPACK_NSIS_EXECUTABLE` to specify the makensis + executable to use instead of the default one. + +* :prop_tgt:`C_STANDARD` and the + :manual:`Compile Features ` functionality gained + support for C17 and C23. + +* :manual:`ctest(1)` gained documentation for its ability to capture + :ref:`Additional Test Measurements`. + +* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results + to a JUnit XML file. + +* :manual:`ctest(1)` learned to recognize files attached to a test at run time. + Previously it was only possible to attach files to tests at configure time + by using the :prop_test:`ATTACHED_FILES` or + :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. + See :ref:`Additional Test Measurements` for more information. + +* Source file extensions ``.ixx`` and ``.cppm`` are now treated as C++. + +* The :prop_dir:`IMPORTED_TARGETS` directory property was added to + get a list of :ref:`Imported Targets` created in the current + directory. + +* The :envvar:`CMAKE_TOOLCHAIN_FILE` environment variable was added to + provide a default value for the :variable:`CMAKE_TOOLCHAIN_FILE` variable. + +* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has + component been updated to 2.3. + +* The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a + new "directory" object containing directory-level information. + This includes a list of installers generated by the :command:`install` + command. + +* The :command:`file(COPY_FILE)` command was added to copy a file to another. + +* The :command:`file(REAL_PATH)` command gained the option ``EXPAND_TILDE`` to + replace any leading tilde with the path to the user's home directory. + +* The :command:`file(RENAME)` command learned to optionally capture + failure in a result variable. It also gained a ``NO_REPLACE`` + option to fail if the destination exists. + +* The :module:`FindDevIL` module now provides imported targets. + +* The :module:`FindIconv` module now has version support. + +* The :module:`FindIntl` module now has version support. + +* The :command:`find_file`, :command:`find_path`, :command:`find_program`, + and :command:`find_library` commands handle cache variables in the same way + regardless how they are defined. See policy :policy:`CMP0125` for details. + +* The :command:`find_file`, :command:`find_path`, :command:`find_program`, + and :command:`find_library` commands gained the option ``NO_CACHE`` to store + find result in normal variable. + +* The :module:`FindMsys` module was added to find MSYS installations. + Like :module:`FindCygwin`, it is used automatically by some other + find modules to locate UNIX-style tools on Windows. + +* The :module:`FindVulkan` module gained imported targets + ``Vulkan::Headers`` and ``Vulkan::glslangValidator``. + +* The :command:`foreach` command restrict loop variables to the loop scope. + See policy :policy:`CMP0124` for details. + +* Addition of the ``Fujitsu`` compiler ID operating in traditional ``Trad`` + mode and ``FujitsuClang`` operating in ``Clang`` mode. +* The :module:`FindOpenMP` module learned to support ``Fujitsu`` and + ``FujitsuClang``. +* The :module:`FindMPI` module learned to support ``Fujitsu`` and + ``FujitsuClang`` in both host and cross compiling modes. +* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support + the serial ``Fujitsu SSL2`` and parallel ``Fujitsu SSL2BLAMP`` libraries. + +* The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option. + +* The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option. + +* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command gained new + ``POST_INCLUDE_FILES`` and ``POST_EXCLUDE_FILES`` arguments. + +* CMake learned to support ``HIP`` as a first-class language that can be + enabled via the :command:`project` and :command:`enable_language` commands. + +* Names given as ``DEPENDS`` or ``DEPENDENCIES`` arguments to + :command:`cpack_ifw_configure_component` or + :command:`cpack_ifw_configure_component_group` may now contain hyphens. + This requires QtIFW 3.1 or later. + +* The :command:`install` command gained a new ``IMPORTED_RUNTIME_ARTIFACTS`` + mode, which can be used to install the runtime artifacts of imported targets. + +* The :command:`install(TARGETS)` command gained new ``RUNTIME_DEPENDENCIES`` + and ``RUNTIME_DEPENDENCY_SET`` arguments, which can be used to install + runtime dependencies using :command:`file(GET_RUNTIME_DEPENDENCIES)`. +* The :command:`install` command gained a new ``RUNTIME_DEPENDENCY_SET`` mode, + which can be used to install runtime dependencies using + :command:`file(GET_RUNTIME_DEPENDENCIES)`. + +* The :command:`install(SCRIPT|CODE)` command + supports a new option ``ALL_COMPONENTS`` which allows + the corresponding code to run for every component of + a per component installation. + +* The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to + add linker launcher tools along with the linker for ``C``, ``CXX``, ``OBJC``, and + ``OBJCXX`` languages. See the :variable:`CMAKE__LINKER_LAUNCHER` variable + and :prop_tgt:`_LINKER_LAUNCHER` target property for details. + +* :command:`target_link_libraries` calls referencing object libraries + via the :genex:`TARGET_OBJECTS` generator expression now place the + object files before all libraries on the link line, regardless of + their specified order. See documentation on + :ref:`Linking Object Libraries via \$\` for details. + +* The :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and + ``REMOVE_AT`` subcommands now error with invalid (i.e., non-integer) values + are given as any of their index arguments based on the setting of policy + :policy:`CMP0121`. + +* The precompiled binaries provided on + `cmake.org `_ now support + ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and + :variable:`CPACK_ARCHIVE_THREADS` variables. + +* Messages printed to a terminal now may be colored by message type. + +* CMake now supports the MSYS runtime environment, much like CYGWIN. + +* The :ref:`Ninja Generators` now pass source files and include directories + to the compiler using absolute paths. This makes diagnostic messages and + debug symbols more consistent, and matches the :ref:`Makefile Generators`. + +* The :generator:`NMake Makefiles` generator now encodes the generated + makefiles as UTF-8 with a BOM when using ``nmake`` from VS 9 or above. + +* :prop_tgt:`OBJC_STANDARD` gained support for C17 and C23. + +* :command:`project` now sets variables :variable:`PROJECT_IS_TOP_LEVEL` and + :variable:`_IS_TOP_LEVEL` to indicate whether it was called + in a top level ``CMakeLists.txt`` file. + +* A new :genex:`TARGET_RUNTIME_DLLS` generator expression was added. + +* The :command:`set(CACHE)` command no longer removes a normal variable of the + same name, if any. See policy :policy:`CMP0126`. + +* The :module:`UseJava` module command ``add_jar`` gained option RESOURCES + allow explicit naming of resources with non-optional namespace. + +* The :module:`UseSWIG` module use now standard library name conventions for + ``CSharp`` language. See policy :policy:`CMP0122`. + +* :module:`UseSWIG` module gained the capability, for + :generator:`Xcode` generator, to use `swig` tool to generate implicit + dependencies. + +* The :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS >` target property + was added to tell the :generator:`Xcode` generator to embed app extensions + such as iMessage sticker packs. + Aspects of the embedding can be customized with the + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_PATH >`, + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_CODE_SIGN_ON_COPY _CODE_SIGN_ON_COPY>` and + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY _REMOVE_HEADERS_ON_COPY>` + properties. diff --git a/Help/release/dev/ARMClang-cpu-arch-flags.rst b/Help/release/dev/ARMClang-cpu-arch-flags.rst deleted file mode 100644 index 5e885fe4ff0..00000000000 --- a/Help/release/dev/ARMClang-cpu-arch-flags.rst +++ /dev/null @@ -1,7 +0,0 @@ -ARMClang-cpu-arch-flags ------------------------ - -* ``ARMClang`` cpu/arch compile and link flags are no longer added - automatically based on the :variable:`CMAKE_SYSTEM_PROCESSOR` - variable or the undocumented ``CMAKE_SYSTEM_ARCH`` variable. - They must be specified explicitly. See policy :policy:`CMP0123`. diff --git a/Help/release/dev/FindDevIL-imported-targets.rst b/Help/release/dev/FindDevIL-imported-targets.rst deleted file mode 100644 index aa0929ea0fa..00000000000 --- a/Help/release/dev/FindDevIL-imported-targets.rst +++ /dev/null @@ -1,4 +0,0 @@ -FindDevIL ---------- - -* The :module:`FindDevIL` module now provides imported targets. diff --git a/Help/release/dev/FindIconv-version.rst b/Help/release/dev/FindIconv-version.rst deleted file mode 100644 index 3546d865111..00000000000 --- a/Help/release/dev/FindIconv-version.rst +++ /dev/null @@ -1,4 +0,0 @@ -FindIconv-version ------------------ - -* The :module:`FindIconv` module now has version support. diff --git a/Help/release/dev/FindIntl-version.rst b/Help/release/dev/FindIntl-version.rst deleted file mode 100644 index 5365cf1d9d7..00000000000 --- a/Help/release/dev/FindIntl-version.rst +++ /dev/null @@ -1,4 +0,0 @@ -FindIntl-version ----------------- - -* The :module:`FindIntl` module now has version support. diff --git a/Help/release/dev/FindMsys.rst b/Help/release/dev/FindMsys.rst deleted file mode 100644 index d237c4eaea5..00000000000 --- a/Help/release/dev/FindMsys.rst +++ /dev/null @@ -1,6 +0,0 @@ -FindMsys --------- - -* The :module:`FindMsys` module was added to find MSYS installations. - Like :module:`FindCygwin`, it is used automatically by some other - find modules to locate UNIX-style tools on Windows. diff --git a/Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst b/Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst deleted file mode 100644 index 4f224cc58f0..00000000000 --- a/Help/release/dev/FindVulkan-add-Headers-glslangValidator-targets.rst +++ /dev/null @@ -1,5 +0,0 @@ -FindVulkan-add-Headers-glslangValidator-targets ------------------------------------------------ - -* The :module:`FindVulkan` module gained imported targets - ``Vulkan::Headers`` and ``Vulkan::glslangValidator``. diff --git a/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst b/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst deleted file mode 100644 index caa07e7d8cb..00000000000 --- a/Help/release/dev/UseJava-RESOURCES-NAMESPACE.rst +++ /dev/null @@ -1,5 +0,0 @@ -UseJava-RESOURCES-NAMESPACE ---------------------------- - -* The :module:`UseJava` module command ``add_jar`` gained option RESOURCES - allow explicit naming of resources with non-optional namespace. diff --git a/Help/release/dev/UseSWIG-csharp.rst b/Help/release/dev/UseSWIG-csharp.rst deleted file mode 100644 index dbbeaf16ac5..00000000000 --- a/Help/release/dev/UseSWIG-csharp.rst +++ /dev/null @@ -1,5 +0,0 @@ -UseSWIG-csharp --------------- - -* The :module:`UseSWIG` module use now standard library name conventions for - ``CSharp`` language. See policy :policy:`CMP0122`. diff --git a/Help/release/dev/UseSWIG-dependencies.rst b/Help/release/dev/UseSWIG-dependencies.rst deleted file mode 100644 index b5a38c3eeb0..00000000000 --- a/Help/release/dev/UseSWIG-dependencies.rst +++ /dev/null @@ -1,6 +0,0 @@ -UseSWIG-dependencies --------------------- - -* :module:`UseSWIG` module gained the capability, for - :generator:`Xcode` generator, to use `swig` tool to generate implicit - dependencies. diff --git a/Help/release/dev/add_custom_command-DEPFILE-genex.rst b/Help/release/dev/add_custom_command-DEPFILE-genex.rst deleted file mode 100644 index 52e5e9fabff..00000000000 --- a/Help/release/dev/add_custom_command-DEPFILE-genex.rst +++ /dev/null @@ -1,5 +0,0 @@ -add_custom_command-DEPFILE-genex --------------------------------- - -* The :command:`add_custom_command` command ``DEPFILE`` option learned to - support :manual:`generator expressions `. diff --git a/Help/release/dev/add_custom_command-DEPFILE.rst b/Help/release/dev/add_custom_command-DEPFILE.rst deleted file mode 100644 index 893c374e700..00000000000 --- a/Help/release/dev/add_custom_command-DEPFILE.rst +++ /dev/null @@ -1,6 +0,0 @@ -add_custom_command-DEPFILE --------------------------- - -* The :command:`add_custom_command` command gained ``DEPFILE`` support on - the :generator:`Xcode` generator, and on :ref:`Visual Studio Generators` - for VS 2012 and above. diff --git a/Help/release/dev/add_custom_command-TARGET-genex.rst b/Help/release/dev/add_custom_command-TARGET-genex.rst deleted file mode 100644 index 86f8b36be56..00000000000 --- a/Help/release/dev/add_custom_command-TARGET-genex.rst +++ /dev/null @@ -1,5 +0,0 @@ -add_custom_command-TARGET-genex -------------------------------- - -* The :ref:`add_custom_command(TARGET) ` command - gained support for resolving target-dependent generator expressions. diff --git a/Help/release/dev/c-std.rst b/Help/release/dev/c-std.rst deleted file mode 100644 index 44daa85cd4a..00000000000 --- a/Help/release/dev/c-std.rst +++ /dev/null @@ -1,6 +0,0 @@ -c-std ------ - -* :prop_tgt:`C_STANDARD` and the - :manual:`Compile Features ` functionality gained - support for C17 and C23. diff --git a/Help/release/dev/capabilties-generator-platforms.rst b/Help/release/dev/capabilties-generator-platforms.rst deleted file mode 100644 index 5de2b67ab2e..00000000000 --- a/Help/release/dev/capabilties-generator-platforms.rst +++ /dev/null @@ -1,6 +0,0 @@ -capabilties-generator-platforms -------------------------------- - -* The :manual:`cmake(1)` ``-E capabilities`` output now contains for each - generator a ``supportedPlatforms`` field listing platform known to - be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. diff --git a/Help/release/dev/cmake-install-prefix-command.rst b/Help/release/dev/cmake-install-prefix-command.rst deleted file mode 100644 index 2de5d918549..00000000000 --- a/Help/release/dev/cmake-install-prefix-command.rst +++ /dev/null @@ -1,8 +0,0 @@ -cmake-install-prefix-command ----------------------------- - -* The :manual:`cmake(1)` command gained the ``--install-prefix `` - command line option to specify the location of the install prefix. - -* :manual:`cmake-presets(7)` configure preset gained support for specifying - the install prefix. diff --git a/Help/release/dev/cmake-presets-condition.rst b/Help/release/dev/cmake-presets-condition.rst deleted file mode 100644 index aa01bc19a9d..00000000000 --- a/Help/release/dev/cmake-presets-condition.rst +++ /dev/null @@ -1,4 +0,0 @@ -cmake-presets-condition ------------------------ - -* :manual:`cmake-presets(7)` now support conditional enabling of presets. diff --git a/Help/release/dev/cmake-presets-host-system-name.rst b/Help/release/dev/cmake-presets-host-system-name.rst deleted file mode 100644 index 803693965a1..00000000000 --- a/Help/release/dev/cmake-presets-host-system-name.rst +++ /dev/null @@ -1,5 +0,0 @@ -cmake-presets-host-system-name ------------------------------- - -* :manual:`cmake-presets(7)` gained support for a new ``${hostSystemName}`` - macro. diff --git a/Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst b/Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst deleted file mode 100644 index 79734896b9c..00000000000 --- a/Help/release/dev/cmake-presets-optional-generator-and-binarydir.rst +++ /dev/null @@ -1,5 +0,0 @@ -cmake-presets-optional-generator-and-binarydir ----------------------------------------------- - -* :manual:`cmake-presets(7)` now support omitting the ``generator`` and - ``binaryDir`` fields. diff --git a/Help/release/dev/cmake-system-name-version.rst b/Help/release/dev/cmake-system-name-version.rst deleted file mode 100644 index 9cfe4013286..00000000000 --- a/Help/release/dev/cmake-system-name-version.rst +++ /dev/null @@ -1,10 +0,0 @@ -cmake-system-name-version -------------------------- - -* :variable:`CMAKE_HOST_SYSTEM_NAME`'s undocumented version-stripping behavior - has been moved earlier, before :command:`project` or - :command:`enable_language` is called. -* :variable:`CMAKE_SYSTEM_NAME`'s undocumented version-stripping behavior has - been removed entirely. If it is set by a ``-D`` flag or by a - :manual:`toolchain file `, it is left unaltered, even if - it still contains a version number. diff --git a/Help/release/dev/cmake-toolchain-command.rst b/Help/release/dev/cmake-toolchain-command.rst deleted file mode 100644 index 111ca49a5f3..00000000000 --- a/Help/release/dev/cmake-toolchain-command.rst +++ /dev/null @@ -1,5 +0,0 @@ -cmake-toolchain-command ----------------------------- - -* The :manual:`cmake(1)` command gained the ``--toolchain `` - command line option to specify a toolchain file. diff --git a/Help/release/dev/compile-options-order.rst b/Help/release/dev/compile-options-order.rst deleted file mode 100644 index 2e182cdf06e..00000000000 --- a/Help/release/dev/compile-options-order.rst +++ /dev/null @@ -1,7 +0,0 @@ -compile-options-order ---------------------- - -* The :ref:`Visual Studio Generators` for VS 2010 and above now place - per-source preprocessor definitions after target-wide preprocssor - definitions. This makes VS consistent with the :ref:`Ninja Generators` - and the :ref:`Makefile Generators`. diff --git a/Help/release/dev/cpack-dmg-filesystem.rst b/Help/release/dev/cpack-dmg-filesystem.rst deleted file mode 100644 index e2a4742a258..00000000000 --- a/Help/release/dev/cpack-dmg-filesystem.rst +++ /dev/null @@ -1,5 +0,0 @@ -cpack-dmg-filesystem --------------------- - -* The :cpack_gen:`CPack DragNDrop Generator` gained option - :variable:`CPACK_DMG_FILESYSTEM` to control the ``.dmg`` filesystem. diff --git a/Help/release/dev/cpack-install-opts.rst b/Help/release/dev/cpack-install-opts.rst deleted file mode 100644 index 970f9a9bf04..00000000000 --- a/Help/release/dev/cpack-install-opts.rst +++ /dev/null @@ -1,6 +0,0 @@ -cpack-install-opts ------------------- - -* The new :variable:`CPACK_CUSTOM_INSTALL_VARIABLES` - can be used to set variables in CPack ``cmake_install.cmake`` - invocations. diff --git a/Help/release/dev/cpack-nsis-executable-name.rst b/Help/release/dev/cpack-nsis-executable-name.rst deleted file mode 100644 index a3818db192f..00000000000 --- a/Help/release/dev/cpack-nsis-executable-name.rst +++ /dev/null @@ -1,6 +0,0 @@ -cpack-nsis-executable-name --------------------------- - -* The :cpack_gen:`CPack NSIS Generator` gained a new variable - :variable:`CPACK_NSIS_EXECUTABLE` to specify the makensis - executable to use instead of the default one. diff --git a/Help/release/dev/ctest-measurements-docs.rst b/Help/release/dev/ctest-measurements-docs.rst deleted file mode 100644 index e47582e5222..00000000000 --- a/Help/release/dev/ctest-measurements-docs.rst +++ /dev/null @@ -1,5 +0,0 @@ -ctest-measurements-docs ------------------------ - -* :manual:`ctest(1)` gained documentation for its ability to capture - :ref:`Additional Test Measurements`. diff --git a/Help/release/dev/ctest-output-junit.rst b/Help/release/dev/ctest-output-junit.rst deleted file mode 100644 index 66df19d6e47..00000000000 --- a/Help/release/dev/ctest-output-junit.rst +++ /dev/null @@ -1,5 +0,0 @@ -ctest-output-junit ------------------- - -* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results - to a JUnit XML file. diff --git a/Help/release/dev/ctest-runtime-files.rst b/Help/release/dev/ctest-runtime-files.rst deleted file mode 100644 index f13baa4fff8..00000000000 --- a/Help/release/dev/ctest-runtime-files.rst +++ /dev/null @@ -1,8 +0,0 @@ -ctest-runtime-files -------------------- - -* :manual:`ctest(1)` learned to recognize files attached to a test at run time. - Previously it was only possible to attach files to tests at configure time - by using the :prop_test:`ATTACHED_FILES` or - :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. - See :ref:`Additional Test Measurements` for more information. diff --git a/Help/release/dev/cxx-module-extensions.rst b/Help/release/dev/cxx-module-extensions.rst deleted file mode 100644 index b9d0a8a1544..00000000000 --- a/Help/release/dev/cxx-module-extensions.rst +++ /dev/null @@ -1,4 +0,0 @@ -cxx-module-extensions ---------------------- - -* Source file extensions ``.ixx`` and ``.cppm`` are now treated as C++. diff --git a/Help/release/dev/dir-IMPORTED_TARGETS.rst b/Help/release/dev/dir-IMPORTED_TARGETS.rst deleted file mode 100644 index a2797ec6b38..00000000000 --- a/Help/release/dev/dir-IMPORTED_TARGETS.rst +++ /dev/null @@ -1,6 +0,0 @@ -dir-IMPORTED_TARGETS --------------------- - -* The :prop_dir:`IMPORTED_TARGETS` directory property was added to - get a list of :ref:`Imported Targets` created in the current - directory. diff --git a/Help/release/dev/env-toolchain-file.rst b/Help/release/dev/env-toolchain-file.rst deleted file mode 100644 index 0bcd493a2b0..00000000000 --- a/Help/release/dev/env-toolchain-file.rst +++ /dev/null @@ -1,5 +0,0 @@ -env-toolchain-file ------------------- - -* The :envvar:`CMAKE_TOOLCHAIN_FILE` environment variable was added to - provide a default value for the :variable:`CMAKE_TOOLCHAIN_FILE` variable. diff --git a/Help/release/dev/file-COPY_FILE.rst b/Help/release/dev/file-COPY_FILE.rst deleted file mode 100644 index 2f0cdf009c4..00000000000 --- a/Help/release/dev/file-COPY_FILE.rst +++ /dev/null @@ -1,4 +0,0 @@ -file-COPY_ONLY --------------- - -* The :command:`file(COPY_FILE)` command was added to copy a file to another. diff --git a/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst b/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst deleted file mode 100644 index cdf1efa3cba..00000000000 --- a/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst +++ /dev/null @@ -1,5 +0,0 @@ -file-REAL_PATH-EXPAND_TILDE ---------------------------- - -* The :command:`file(REAL_PATH)` command gained the option ``EXPAND_TILDE`` to - replace any leading tilde with the path to the user's home directory. diff --git a/Help/release/dev/file-RENAME.rst b/Help/release/dev/file-RENAME.rst deleted file mode 100644 index 6c1314d24f2..00000000000 --- a/Help/release/dev/file-RENAME.rst +++ /dev/null @@ -1,6 +0,0 @@ -file-RENAME ------------ - -* The :command:`file(RENAME)` command learned to optionally capture - failure in a result variable. It also gained a ``NO_REPLACE`` - option to fail if the destination exists. diff --git a/Help/release/dev/fileapi-codemodel-directory.rst b/Help/release/dev/fileapi-codemodel-directory.rst deleted file mode 100644 index f6515fd17c3..00000000000 --- a/Help/release/dev/fileapi-codemodel-directory.rst +++ /dev/null @@ -1,10 +0,0 @@ -fileapi-codemodel-directory ---------------------------- - -* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has - component been updated to 2.3. - -* The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a - new "directory" object containing directory-level information. - This includes a list of installers generated by the :command:`install` - command. diff --git a/Help/release/dev/find_item-NO_CACHE.rst b/Help/release/dev/find_item-NO_CACHE.rst deleted file mode 100644 index be5258c1a04..00000000000 --- a/Help/release/dev/find_item-NO_CACHE.rst +++ /dev/null @@ -1,6 +0,0 @@ -find_item-NO_CACHE ------------------- - -* The :command:`find_file`, :command:`find_path`, :command:`find_program`, - and :command:`find_library` commands gained the option ``NO_CACHE`` to store - find result in normal variable. diff --git a/Help/release/dev/find_item-consistent-behavior.rst b/Help/release/dev/find_item-consistent-behavior.rst deleted file mode 100644 index 43905e72978..00000000000 --- a/Help/release/dev/find_item-consistent-behavior.rst +++ /dev/null @@ -1,6 +0,0 @@ -find_item-consistent-behavior ------------------------------ - -* The :command:`find_file`, :command:`find_path`, :command:`find_program`, - and :command:`find_library` commands handle cache variables in the same way - regardless how they are defined. See policy :policy:`CMP0125` for details. diff --git a/Help/release/dev/foreach-variable-scope.rst b/Help/release/dev/foreach-variable-scope.rst deleted file mode 100644 index 29a57bbc5fb..00000000000 --- a/Help/release/dev/foreach-variable-scope.rst +++ /dev/null @@ -1,5 +0,0 @@ -foreach-variable-scope ----------------------- - -* The :command:`foreach` command restrict loop variables to the loop scope. - See policy :policy:`CMP0124` for details. diff --git a/Help/release/dev/fujitsu-compiler-support.rst b/Help/release/dev/fujitsu-compiler-support.rst deleted file mode 100644 index c6f8cfbbcec..00000000000 --- a/Help/release/dev/fujitsu-compiler-support.rst +++ /dev/null @@ -1,11 +0,0 @@ -fujitsu-compiler-support ------------------------- - -* Addition of the ``Fujitsu`` compiler ID operating in traditional ``Trad`` - mode and ``FujitsuClang`` operating in ``Clang`` mode. -* The :module:`FindOpenMP` module learned to support ``Fujitsu`` and - ``FujitsuClang``. -* The :module:`FindMPI` module learned to support ``Fujitsu`` and - ``FujitsuClang`` in both host and cross compiling modes. -* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support - the serial ``Fujitsu SSL2`` and parallel ``Fujitsu SSL2BLAMP`` libraries. diff --git a/Help/release/dev/generate-cmake-build-command-parallel.rst b/Help/release/dev/generate-cmake-build-command-parallel.rst deleted file mode 100644 index 1b8dd40acbb..00000000000 --- a/Help/release/dev/generate-cmake-build-command-parallel.rst +++ /dev/null @@ -1,6 +0,0 @@ -generate-cmake-build-command-parallel -------------------------------------- - -* The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option. - -* The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option. diff --git a/Help/release/dev/get-runtime-dependencies-file-filter.rst b/Help/release/dev/get-runtime-dependencies-file-filter.rst deleted file mode 100644 index 3fc17ac7929..00000000000 --- a/Help/release/dev/get-runtime-dependencies-file-filter.rst +++ /dev/null @@ -1,5 +0,0 @@ -get-runtime-dependencies-file-filter ------------------------------------- - -* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command gained new - ``POST_INCLUDE_FILES`` and ``POST_EXCLUDE_FILES`` arguments. diff --git a/Help/release/dev/hip.rst b/Help/release/dev/hip.rst deleted file mode 100644 index abf9a359e4d..00000000000 --- a/Help/release/dev/hip.rst +++ /dev/null @@ -1,5 +0,0 @@ -hip ---- - -* CMake learned to support ``HIP`` as a first-class language that can be - enabled via the :command:`project` and :command:`enable_language` commands. diff --git a/Help/release/dev/ifw-default-version-operator.rst b/Help/release/dev/ifw-default-version-operator.rst deleted file mode 100644 index 4aeace26870..00000000000 --- a/Help/release/dev/ifw-default-version-operator.rst +++ /dev/null @@ -1,7 +0,0 @@ -ifw-default-version-operator ----------------------------- - -* Names given as ``DEPENDS`` or ``DEPENDENCIES`` arguments to - :command:`cpack_ifw_configure_component` or - :command:`cpack_ifw_configure_component_group` may now contain hyphens. - This requires QtIFW 3.1 or later. diff --git a/Help/release/dev/install-imported-runtime-artifacts.rst b/Help/release/dev/install-imported-runtime-artifacts.rst deleted file mode 100644 index e2821c15c12..00000000000 --- a/Help/release/dev/install-imported-runtime-artifacts.rst +++ /dev/null @@ -1,5 +0,0 @@ -install-imported-runtime-artifacts ----------------------------------- - -* The :command:`install` command gained a new ``IMPORTED_RUNTIME_ARTIFACTS`` - mode, which can be used to install the runtime artifacts of imported targets. diff --git a/Help/release/dev/install-runtime-dependencies.rst b/Help/release/dev/install-runtime-dependencies.rst deleted file mode 100644 index 58c92e6a533..00000000000 --- a/Help/release/dev/install-runtime-dependencies.rst +++ /dev/null @@ -1,9 +0,0 @@ -install-runtime-dependencies ----------------------------- - -* The :command:`install(TARGETS)` command gained new ``RUNTIME_DEPENDENCIES`` - and ``RUNTIME_DEPENDENCY_SET`` arguments, which can be used to install - runtime dependencies using :command:`file(GET_RUNTIME_DEPENDENCIES)`. -* The :command:`install` command gained a new ``RUNTIME_DEPENDENCY_SET`` mode, - which can be used to install runtime dependencies using - :command:`file(GET_RUNTIME_DEPENDENCIES)`. diff --git a/Help/release/dev/install-script-all-components.rst b/Help/release/dev/install-script-all-components.rst deleted file mode 100644 index e421d3df781..00000000000 --- a/Help/release/dev/install-script-all-components.rst +++ /dev/null @@ -1,7 +0,0 @@ -install-script-all-components ------------------------------ - -* The :command:`install(SCRIPT|CODE)` command - supports a new option ``ALL_COMPONENTS`` which allows - the corresponding code to run for every component of - a per component installation. diff --git a/Help/release/dev/link-objects-first.rst b/Help/release/dev/link-objects-first.rst deleted file mode 100644 index 0c622e7ae19..00000000000 --- a/Help/release/dev/link-objects-first.rst +++ /dev/null @@ -1,8 +0,0 @@ -link-objects-first ------------------- - -* :command:`target_link_libraries` calls referencing object libraries - via the :genex:`TARGET_OBJECTS` generator expression now place the - object files before all libraries on the link line, regardless of - their specified order. See documentation on - :ref:`Linking Object Libraries via \$\` for details. diff --git a/Help/release/dev/linker-launcher.rst b/Help/release/dev/linker-launcher.rst deleted file mode 100644 index 6563347b11e..00000000000 --- a/Help/release/dev/linker-launcher.rst +++ /dev/null @@ -1,7 +0,0 @@ -linker-launcher ---------------- - -* The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to - add linker launcher tools along with the linker for ``C``, ``CXX``, ``OBJC``, and - ``OBJCXX`` languages. See the :variable:`CMAKE__LINKER_LAUNCHER` variable - and :prop_tgt:`_LINKER_LAUNCHER` target property for details. diff --git a/Help/release/dev/list-index-arg-parsing.rst b/Help/release/dev/list-index-arg-parsing.rst deleted file mode 100644 index 2ea525bc463..00000000000 --- a/Help/release/dev/list-index-arg-parsing.rst +++ /dev/null @@ -1,7 +0,0 @@ -list-index-arg-parsing ----------------------- - -* The :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and - ``REMOVE_AT`` subcommands now error with invalid (i.e., non-integer) values - are given as any of their index arguments based on the setting of policy - :policy:`CMP0121`. diff --git a/Help/release/dev/lzma-threads.rst b/Help/release/dev/lzma-threads.rst deleted file mode 100644 index a481cfa684c..00000000000 --- a/Help/release/dev/lzma-threads.rst +++ /dev/null @@ -1,7 +0,0 @@ -lzma-threads ------------- - -* The precompiled binaries provided on - `cmake.org `_ now support - ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and - :variable:`CPACK_ARCHIVE_THREADS` variables. diff --git a/Help/release/dev/message-color.rst b/Help/release/dev/message-color.rst deleted file mode 100644 index 4acf15e9ff7..00000000000 --- a/Help/release/dev/message-color.rst +++ /dev/null @@ -1,4 +0,0 @@ -message-color -------------- - -* Messages printed to a terminal now may be colored by message type. diff --git a/Help/release/dev/msys.rst b/Help/release/dev/msys.rst deleted file mode 100644 index ece5de74fc3..00000000000 --- a/Help/release/dev/msys.rst +++ /dev/null @@ -1,4 +0,0 @@ -msys ----- - -* CMake now supports the MSYS runtime environment, much like CYGWIN. diff --git a/Help/release/dev/ninja-absolute-paths.rst b/Help/release/dev/ninja-absolute-paths.rst deleted file mode 100644 index 2dfc1b76fe1..00000000000 --- a/Help/release/dev/ninja-absolute-paths.rst +++ /dev/null @@ -1,6 +0,0 @@ -ninja-absolute-paths --------------------- - -* The :ref:`Ninja Generators` now pass source files and include directories - to the compiler using absolute paths. This makes diagnostic messages and - debug symbols more consistent, and matches the :ref:`Makefile Generators`. diff --git a/Help/release/dev/nmake-utf8.rst b/Help/release/dev/nmake-utf8.rst deleted file mode 100644 index ebbb45b0189..00000000000 --- a/Help/release/dev/nmake-utf8.rst +++ /dev/null @@ -1,5 +0,0 @@ -nmake-utf8 ----------- - -* The :generator:`NMake Makefiles` generator now encodes the generated - makefiles as UTF-8 with a BOM when using ``nmake`` from VS 9 or above. diff --git a/Help/release/dev/objc-std-17-23.rst b/Help/release/dev/objc-std-17-23.rst deleted file mode 100644 index 5aba3951e8a..00000000000 --- a/Help/release/dev/objc-std-17-23.rst +++ /dev/null @@ -1,4 +0,0 @@ -objc-std-17-23 --------------- - -* :prop_tgt:`OBJC_STANDARD` gained support for C17 and C23. diff --git a/Help/release/dev/project-is-top-level.rst b/Help/release/dev/project-is-top-level.rst deleted file mode 100644 index 568afe02c36..00000000000 --- a/Help/release/dev/project-is-top-level.rst +++ /dev/null @@ -1,6 +0,0 @@ -project-is-top-level --------------------- - -* :command:`project` now sets variables :variable:`PROJECT_IS_TOP_LEVEL` and - :variable:`_IS_TOP_LEVEL` to indicate whether it was called - in a top level ``CMakeLists.txt`` file. diff --git a/Help/release/dev/runtime-dll-deps.rst b/Help/release/dev/runtime-dll-deps.rst deleted file mode 100644 index 831410f3bcc..00000000000 --- a/Help/release/dev/runtime-dll-deps.rst +++ /dev/null @@ -1,4 +0,0 @@ -runtime-dll-deps ----------------- - -* A new :genex:`TARGET_RUNTIME_DLLS` generator expression was added. diff --git a/Help/release/dev/set-cache-variable.rst b/Help/release/dev/set-cache-variable.rst deleted file mode 100644 index a96242c7cff..00000000000 --- a/Help/release/dev/set-cache-variable.rst +++ /dev/null @@ -1,5 +0,0 @@ -set-cache-variable ------------------- - -* The :command:`set(CACHE)` command no longer removes a normal variable of the - same name, if any. See policy :policy:`CMP0126`. diff --git a/Help/release/dev/xcode_app_extensions.rst b/Help/release/dev/xcode_app_extensions.rst deleted file mode 100644 index 7be7d82ecef..00000000000 --- a/Help/release/dev/xcode_app_extensions.rst +++ /dev/null @@ -1,11 +0,0 @@ -xcode_app_extensions --------------------- - -* The :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS >` target property - was added to tell the :generator:`Xcode` generator to embed app extensions - such as iMessage sticker packs. - Aspects of the embedding can be customized with the - :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_PATH >`, - :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_CODE_SIGN_ON_COPY _CODE_SIGN_ON_COPY>` and - :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY _REMOVE_HEADERS_ON_COPY>` - properties. diff --git a/Help/release/index.rst b/Help/release/index.rst index 5dfca051be6..59388784510 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -15,6 +15,7 @@ Releases .. toctree:: :maxdepth: 1 + 3.21 <3.21> 3.20 <3.20> 3.19 <3.19> 3.18 <3.18> From 0665d9092e5099c581e47f3be5360d711d176c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Sun, 13 Jun 2021 23:50:47 +0200 Subject: [PATCH 0679/1519] CMakeDependentOption: Allow parentheses in the depends string `if()` takes the condition as a list of arguments. Parentheses need to be separated as well. Fixes: #22303 --- Modules/CMakeDependentOption.cmake | 5 ++++- Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt | 1 + Tests/RunCMake/CMakeDependentOption/Parentheses.cmake | 7 +++++++ Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake | 3 +++ Tests/RunCMake/CMakeLists.txt | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt create mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses.cmake create mode 100644 Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index 96855d28f1c..0a291f24fb4 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -42,7 +42,10 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force) if(${option}_ISSET MATCHES "^${option}_ISSET$") set(${option}_AVAILABLE 1) foreach(d ${depends}) - string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") + string(REPLACE "(" " ( " _CMAKE_CDO_DEP "${d}") + string(REPLACE ")" " ) " _CMAKE_CDO_DEP "${_CMAKE_CDO_DEP}") + string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${_CMAKE_CDO_DEP}") + unset(_CMAKE_CDO_DEP) if(${CMAKE_DEPENDENT_OPTION_DEP}) else() set(${option}_AVAILABLE 0) diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt new file mode 100644 index 00000000000..15b56a10d4b --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake new file mode 100644 index 00000000000..c2951f1dcbf --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake @@ -0,0 +1,7 @@ +include(CMakeDependentOption) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake new file mode 100644 index 00000000000..bbdd3e58869 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake_script(Parentheses) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 4e285497974..dafb174000c 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -233,6 +233,7 @@ add_RunCMake_test(BuildDepends if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") add_RunCMake_test(Byproducts) endif() +add_RunCMake_test(CMakeDependentOption) add_RunCMake_test(CMakeRoleGlobalProperty) add_RunCMake_test(CMakeRelease -DCMake_TEST_JQ=${CMake_TEST_JQ}) if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") From d94b23885a6646571904c9f41599ffde487d6314 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 15:06:34 -0400 Subject: [PATCH 0680/1519] cmNinjaTargetGenerator: Simplify scan rule response file selection Since commit 33a8e0bb09 (cmNinjaTargetGenerator: Simplify scan rule depfile selection, 2020-11-06, v3.20.0-rc1~516^2~1), the `$out` of the scan rule always matches our `.rsp` file selection, so use `$out.rsp`. --- Source/cmNinjaTargetGenerator.cxx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 60802700f3f..65434850570 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1118,11 +1118,7 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName, { cmNinjaBuild scanBuild(ruleName); - if (!ppFileName.empty()) { - scanBuild.RspFile = cmStrCat(ppFileName, ".rsp"); - } else { - scanBuild.RspFile = "$out.rsp"; - } + scanBuild.RspFile = "$out.rsp"; if (compilePP) { // Move compilation dependencies to the scan/preprocessing build statement. From 1dd9c4ab6fa9ced2276433dbce081d9cff838d1e Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 15:11:20 -0400 Subject: [PATCH 0681/1519] cmNinjaTargetGenerator: Clarify GetScanBuildStatement condition Use the `compilePP` variable directly rather than relying on callers to make `compilePP == !ppFileName.empty()`. --- Source/cmNinjaTargetGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 65434850570..c8dc30438ed 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1162,7 +1162,7 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName, scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; // Outputs of the scan/preprocessor build statement. - if (!ppFileName.empty()) { + if (compilePP) { scanBuild.Outputs.push_back(ppFileName); scanBuild.ImplicitOuts.push_back(ddiFile); } else { From 312ced6547e789447f518ea996215ddd1741c80a Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 15:15:39 -0400 Subject: [PATCH 0682/1519] cmNinjaTargetGenerator: Fix scan rule PREPROCESSED_SOURCE placeholder When running the module dependencies scan tool for for a language that does not compile the preprocessed output, we do not actually put the preprocessed output in the build graph. However, the value of `CMAKE_EXPERIMENTAL__SCANDEP_SOURCE` may reference the placeholder for the preprocessed source. Populate the placeholder to keep the file out of the way. In particular, do not clobber the `.ddi` file. --- Source/cmNinjaTargetGenerator.cxx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index c8dc30438ed..609848b433b 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -536,7 +536,7 @@ std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi, // Helper function to create dependency scanning rule that may or may // not perform explicit preprocessing too. cmNinjaRule GetScanRule( - const std::string& ruleName, + std::string const& ruleName, std::string const& ppFileName, cmRulePlaceholderExpander::RuleVariables const& vars, const std::string& responseFlag, const std::string& flags, cmRulePlaceholderExpander* const rulePlaceholderExpander, @@ -553,7 +553,7 @@ cmNinjaRule GetScanRule( scanVars.CMTargetType = vars.CMTargetType; scanVars.Language = vars.Language; scanVars.Object = "$OBJ_FILE"; - scanVars.PreprocessedSource = "$out"; + scanVars.PreprocessedSource = ppFileName.c_str(); scanVars.DynDepFile = "$DYNDEP_INTERMEDIATE_FILE"; scanVars.DependencyFile = rule.DepFile.c_str(); scanVars.DependencyTarget = "$out"; @@ -653,8 +653,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, { std::vector scanCommands; std::string scanRuleName; + std::string ppFileName; if (compilationPreprocesses) { scanRuleName = this->LanguageScanRule(lang, config); + ppFileName = "$PREPROCESSED_OUTPUT_FILE"; std::string const& scanCommand = mf->GetRequiredDefinition( cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_SOURCE")); cmExpandList(scanCommand, scanCommands); @@ -663,6 +665,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, } } else { scanRuleName = this->LanguagePreprocessAndScanRule(lang, config); + ppFileName = "$out"; std::string const& ppCommmand = mf->GetRequiredDefinition( cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE")); cmExpandList(ppCommmand, scanCommands); @@ -673,9 +676,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, "$DYNDEP_INTERMEDIATE_FILE")); } - auto scanRule = GetScanRule( - scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(), - this->GetLocalGenerator(), std::move(scanCommands), config); + auto scanRule = + GetScanRule(scanRuleName, ppFileName, vars, responseFlag, flags, + rulePlaceholderExpander.get(), this->GetLocalGenerator(), + std::move(scanCommands), config); scanRule.Comment = cmStrCat("Rule for generating ", lang, " dependencies."); @@ -704,7 +708,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, GetScanCommand(cmakeCmd, tdi, lang, "$in", "$out")); auto scanRule = GetScanRule( - scanRuleName, vars, "", flags, rulePlaceholderExpander.get(), + scanRuleName, "", vars, "", flags, rulePlaceholderExpander.get(), this->GetLocalGenerator(), std::move(scanCommands), config); // Write the rule for generating dependencies for the given language. @@ -1167,6 +1171,7 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName, scanBuild.ImplicitOuts.push_back(ddiFile); } else { scanBuild.Outputs.push_back(ddiFile); + scanBuild.Variables["PREPROCESSED_OUTPUT_FILE"] = ppFileName; } // Scanning always uses a depfile for preprocessor dependencies. @@ -1362,6 +1367,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->GetPreprocessedFilePath(source, config)); } else { scanRuleName = this->LanguageScanRule(language, config); + ppFileName = cmStrCat(objectFileName, ".ddi.i"); } cmNinjaBuild ppBuild = GetScanBuildStatement( From b302dd776cfd5ad22aff343c3c90a4949e6bbd13 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 15 Jun 2021 00:01:25 -0400 Subject: [PATCH 0683/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c5366391a4a..6be75118012 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210614) +set(CMake_VERSION_PATCH 20210615) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2b9890e9b940db59b4d1633fa5b8067f615ed0f4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 15:32:31 -0400 Subject: [PATCH 0684/1519] cmScanDepFormat: Avoid writing lookup-method with default value --- Source/cmScanDepFormat.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index 66202212c89..ae0e649de84 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -3,7 +3,6 @@ #include "cmScanDepFormat.h" -#include #include #include #include @@ -339,7 +338,7 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, const char* lookup_method = nullptr; switch (require.Method) { case LookupMethod::ByName: - lookup_method = "by-name"; + // No explicit value needed for the default. break; case LookupMethod::IncludeAngle: lookup_method = "include-angle"; @@ -348,8 +347,9 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, lookup_method = "include-quote"; break; } - assert(lookup_method); - require_obj["lookup-method"] = lookup_method; + if (lookup_method) { + require_obj["lookup-method"] = lookup_method; + } reqs.append(require_obj); } From 10b2e5346984d95c15d0cc38ddf5c5fad11a6a65 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 16:14:35 -0400 Subject: [PATCH 0685/1519] cmScanDepFormat: Remove Fortran-specific compiled-module-path logic Read and write the `compiled-module-path` field only when explicitly known. Move the assumption that the `compiled-module-path` can be derived from the logical module name from the scandep parser to the `cmake_ninja_dyndep` helper. --- Source/cmGlobalNinjaGenerator.cxx | 16 ++++++++++++---- Source/cmScanDepFormat.cxx | 11 ++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index cbe1bc85014..5108a6faa00 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2448,7 +2448,6 @@ cm::optional cmcmd_cmake_ninja_depends_fortran( for (std::string const& provide : finfo.Provides) { cmSourceReqInfo src_info; src_info.LogicalName = provide; - src_info.CompiledModulePath = provide; info->ScanDep.Provides.emplace_back(src_info); } for (std::string const& require : finfo.Requires) { @@ -2458,7 +2457,6 @@ cm::optional cmcmd_cmake_ninja_depends_fortran( } cmSourceReqInfo src_info; src_info.LogicalName = require; - src_info.CompiledModulePath = require; info->ScanDep.Requires.emplace_back(src_info); } for (std::string const& include : finfo.Includes) { @@ -2529,8 +2527,18 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( Json::Value tm = Json::objectValue; for (cmScanDepInfo const& object : objects) { for (auto const& p : object.Provides) { - std::string const mod = cmStrCat( - module_dir, cmSystemTools::GetFilenameName(p.CompiledModulePath)); + std::string mod; + if (!p.CompiledModulePath.empty()) { + // The scanner provided the path to the module file. + mod = p.CompiledModulePath; + if (!cmSystemTools::FileIsFullPath(mod)) { + // Treat relative to work directory (top of build tree). + mod = cmSystemTools::CollapseFullPath(mod, dir_top_bld); + } + } else { + // Assume the module file path matches the logical module name. + mod = cmStrCat(module_dir, p.LogicalName); + } mod_files[p.LogicalName] = mod; tm[p.LogicalName] = mod; } diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index ae0e649de84..6fcbce5f18d 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -162,9 +162,6 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, provide["compiled-module-path"]; PARSE_FILENAME(compiled_module_path, provide_info.CompiledModulePath); - } else { - provide_info.CompiledModulePath = - cmStrCat(provide_info.LogicalName, ".mod"); } if (provide.isMember("unique-on-source-path")) { @@ -299,9 +296,7 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, Json::Value provide_obj(Json::objectValue); auto const encoded = EncodeFilename(provide.LogicalName); provide_obj["logical-name"] = encoded; - if (provide.CompiledModulePath.empty()) { - provide_obj["compiled-module-path"] = encoded; - } else { + if (!provide.CompiledModulePath.empty()) { provide_obj["compiled-module-path"] = EncodeFilename(provide.CompiledModulePath); } @@ -321,9 +316,7 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, Json::Value require_obj(Json::objectValue); auto const encoded = EncodeFilename(require.LogicalName); require_obj["logical-name"] = encoded; - if (require.CompiledModulePath.empty()) { - require_obj["compiled-module-path"] = encoded; - } else { + if (!require.CompiledModulePath.empty()) { require_obj["compiled-module-path"] = EncodeFilename(require.CompiledModulePath); } From a35d1212760707b195f6c462aadae8383ffcdeca Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 16:25:02 -0400 Subject: [PATCH 0686/1519] Ninja: Populate P1689R4 compiled-module-path field for Fortran When scanning Fortran dependencies, we know the file path at which a provided module file is written. Store it in the `compiled-module-path` field as specified by P1689R4. Our collator in `cmake_ninja_dyndep` no longer needs to assume that the module file path can be derived from the logical module name. In the future, the Fortran dependency scanning may be done by the compiler itself, in which case it will provide the value of `compiled-module-path`. --- Source/cmGlobalNinjaGenerator.cxx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 5108a6faa00..963118fd626 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -2400,6 +2401,8 @@ cm::optional cmcmd_cmake_ninja_depends_fortran( cm::optional info; cmFortranCompiler fc; std::vector includes; + std::string dir_top_bld; + std::string module_dir; { Json::Value tdio; Json::Value const& tdi = tdio; @@ -2414,6 +2417,11 @@ cm::optional cmcmd_cmake_ninja_depends_fortran( } } + dir_top_bld = tdi["dir-top-bld"].asString(); + if (!dir_top_bld.empty() && !cmHasLiteralSuffix(dir_top_bld, "/")) { + dir_top_bld += '/'; + } + Json::Value const& tdi_include_dirs = tdi["include-dirs"]; if (tdi_include_dirs.isArray()) { for (auto const& tdi_include_dir : tdi_include_dirs) { @@ -2421,6 +2429,12 @@ cm::optional cmcmd_cmake_ninja_depends_fortran( } } + Json::Value const& tdi_module_dir = tdi["module-dir"]; + module_dir = tdi_module_dir.asString(); + if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) { + module_dir += '/'; + } + Json::Value const& tdi_compiler_id = tdi["compiler-id"]; fc.Id = tdi_compiler_id.asString(); @@ -2448,6 +2462,13 @@ cm::optional cmcmd_cmake_ninja_depends_fortran( for (std::string const& provide : finfo.Provides) { cmSourceReqInfo src_info; src_info.LogicalName = provide; + if (!module_dir.empty()) { + std::string mod = cmStrCat(module_dir, provide); + if (!dir_top_bld.empty() && cmHasPrefix(mod, dir_top_bld)) { + mod = mod.substr(dir_top_bld.size()); + } + src_info.CompiledModulePath = std::move(mod); + } info->ScanDep.Provides.emplace_back(src_info); } for (std::string const& require : finfo.Requires) { From 9c98878451f596e1fdf7e5887dd26349fd6ea8b1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 15 Jun 2021 15:42:08 -0400 Subject: [PATCH 0687/1519] gitlab-ci: update macOS jobs to use Xcode 12.5 --- .gitlab/os-macos.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab/os-macos.yml b/.gitlab/os-macos.yml index 1ce96b30cf7..9c4a920797a 100644 --- a/.gitlab/os-macos.yml +++ b/.gitlab/os-macos.yml @@ -7,7 +7,7 @@ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci ext/$CI_CONCURRENT_ID" # TODO: Factor this out so that each job selects the Xcode version to # use so that different versions can be tested in a single pipeline. - DEVELOPER_DIR: "/Applications/Xcode-12.4.app/Contents/Developer" + DEVELOPER_DIR: "/Applications/Xcode-12.5.app/Contents/Developer" # Avoid conflicting with other projects running on the same machine. SCCACHE_SERVER_PORT: 4227 @@ -87,7 +87,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-12.4 + - xcode-12.5 - nonconcurrent .macos_x86_64_builder_tags_package: @@ -95,7 +95,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-12.4 + - xcode-12.5 - nonconcurrent - finder @@ -104,7 +104,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-12.4 + - xcode-12.5 - concurrent .macos_arm64_builder_tags: @@ -112,7 +112,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos-arm64 - shell - - xcode-12.4 + - xcode-12.5 - nonconcurrent .macos_arm64_builder_ext_tags: @@ -120,7 +120,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos-arm64 - shell - - xcode-12.4 + - xcode-12.5 - concurrent ## macOS-specific scripts From 24399a8d840151ac8fe9241209ec013a5da412f5 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 16 Jun 2021 00:01:09 -0400 Subject: [PATCH 0688/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6be75118012..ca070e9c86a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210615) +set(CMake_VERSION_PATCH 20210616) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d3274e0a6f7664d611b0a804c24add13b254e348 Mon Sep 17 00:00:00 2001 From: Steven A White Date: Wed, 16 Jun 2021 01:01:02 -0400 Subject: [PATCH 0689/1519] FindLATEX: Search user-local MiKTeX locations I've noticed the default installer for MikTex does not prompt for escalation. So, many installations I find do not have registry entries. This should cover finding it in the current defaults. --- Modules/FindLATEX.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/FindLATEX.cmake b/Modules/FindLATEX.cmake index 1e82651fe15..9d7168ee8e4 100644 --- a/Modules/FindLATEX.cmake +++ b/Modules/FindLATEX.cmake @@ -61,6 +61,10 @@ if (WIN32) # Try to find the MikTex binary path (look for its package manager). find_path(MIKTEX_BINARY_PATH mpm.exe "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MiK\\MiKTeX\\CurrentVersion\\MiKTeX;Install Root]/miktex/bin" + "$ENV{LOCALAPPDATA}/Programs/MiKTeX/miktex/bin" + "$ENV{LOCALAPPDATA}/Programs/MiKTeX/miktex/bin/x64" + "$ENV{APPDATA}/Programs/MiKTeX/miktex/bin" + "$ENV{APPDATA}/Programs/MiKTeX/miktex/bin/x64" DOC "Path to the MikTex binary directory." ) From c017098d4d06ba114085ba7de47b99fc0b71e8d0 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 16 Jun 2021 10:39:39 -0400 Subject: [PATCH 0690/1519] CMake: Allow override of unexpected non-flow-control commands Fixes: #22310 --- Source/cmCommands.cxx | 14 +++++++------- Source/cmState.cxx | 9 ++++++++- Source/cmState.h | 2 ++ Tests/RunCMake/Syntax/OverrideProject-result.txt | 1 + Tests/RunCMake/Syntax/OverrideProject-stderr.txt | 3 +++ Tests/RunCMake/Syntax/RunCMakeTest.cmake | 1 + 6 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 Tests/RunCMake/Syntax/OverrideProject-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideProject-stderr.txt diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 9e5b78351d1..a241a3a6430 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -164,36 +164,36 @@ void GetScriptingCommands(cmState* state) state->AddBuiltinCommand("string", cmStringCommand); state->AddBuiltinCommand("unset", cmUnsetCommand); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "else", "An ELSE command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command."); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "elseif", "An ELSEIF command was found outside of a proper " "IF ENDIF structure."); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "endforeach", "An ENDFOREACH command was found outside of a proper " "FOREACH ENDFOREACH structure. Or its arguments did " "not match the opening FOREACH command."); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "endfunction", "An ENDFUNCTION command was found outside of a proper " "FUNCTION ENDFUNCTION structure. Or its arguments did not " "match the opening FUNCTION command."); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "endif", "An ENDIF command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command."); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "endmacro", "An ENDMACRO command was found outside of a proper " "MACRO ENDMACRO structure. Or its arguments did not " "match the opening MACRO command."); - state->AddUnexpectedCommand( + state->AddUnexpectedFlowControlCommand( "endwhile", "An ENDWHILE command was found outside of a proper " "WHILE ENDWHILE structure. Or its arguments did not " diff --git a/Source/cmState.cxx b/Source/cmState.cxx index d97762bb6c4..929b0fba96a 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -480,7 +480,7 @@ void cmState::AddDisallowedCommand(std::string const& name, void cmState::AddUnexpectedCommand(std::string const& name, const char* error) { - this->AddFlowControlCommand( + this->AddBuiltinCommand( name, [name, error](std::vector const&, cmExecutionStatus& status) -> bool { @@ -495,6 +495,13 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error) }); } +void cmState::AddUnexpectedFlowControlCommand(std::string const& name, + const char* error) +{ + this->FlowControlCommands.insert(name); + this->AddUnexpectedCommand(name, error); +} + bool cmState::AddScriptedCommand(std::string const& name, BT command, cmMakefile& mf) { diff --git a/Source/cmState.h b/Source/cmState.h index 4e411560a17..9951b9acfee 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -166,6 +166,8 @@ class cmState void AddDisallowedCommand(std::string const& name, BuiltinCommand command, cmPolicies::PolicyID policy, const char* message); void AddUnexpectedCommand(std::string const& name, const char* error); + void AddUnexpectedFlowControlCommand(std::string const& name, + const char* error); bool AddScriptedCommand(std::string const& name, BT command, cmMakefile& mf); void RemoveBuiltinCommand(std::string const& name); diff --git a/Tests/RunCMake/Syntax/OverrideProject-result.txt b/Tests/RunCMake/Syntax/OverrideProject-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideProject-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideProject-stderr.txt b/Tests/RunCMake/Syntax/OverrideProject-stderr.txt new file mode 100644 index 00000000000..862d5c87308 --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideProject-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/Tests/RunCMake/Syntax/Override\.cmake:[0-9]+ \(message\): + This shouldn't happen$ diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake index 4d246577b20..f0c287cdb91 100644 --- a/Tests/RunCMake/Syntax/RunCMakeTest.cmake +++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake @@ -150,3 +150,4 @@ run_override(If) run_override(Macro) run_override(Return) run_override(While) +run_override(Project) From d6d4af0ec3b52170c2691478a4d43c505a846799 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 10:54:50 -0400 Subject: [PATCH 0691/1519] cmGlobalVisualStudio10Generator: Move static functions to anonymous namespace --- Source/cmGlobalVisualStudio10Generator.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index badce2eb52c..596c73120fc 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1313,8 +1313,9 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry, return value; } -static cmIDEFlagTable const* cmLoadFlagTableJson( - std::string const& flagJsonPath) +namespace { + +cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath) { cmIDEFlagTable* ret = nullptr; auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath); @@ -1349,12 +1350,13 @@ static cmIDEFlagTable const* cmLoadFlagTableJson( return ret; } -static std::string cmGetFlagTableName(std::string const& toolsetName, - std::string const& table) +std::string cmGetFlagTableName(std::string const& toolsetName, + std::string const& table) { return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" + toolsetName + "_" + table + ".json"; } +} cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( std::string const& optionsName, std::string const& toolsetName, From e59a208b69e701593ca7ba60f3a4c2215f3e44c4 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 10:53:22 -0400 Subject: [PATCH 0692/1519] cmGlobalVisualStudio10Generator: Adopt GetVSInstanceVersion method Port from `cmGlobalVisualStudioVersionedGenerator`. --- Source/cmGlobalVisualStudio10Generator.h | 7 +++++++ .../cmGlobalVisualStudioVersionedGenerator.cxx | 17 +++++++++++------ Source/cmGlobalVisualStudioVersionedGenerator.h | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 8d30ef8e855..5022a0fe5ed 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -5,6 +5,8 @@ #include #include +#include + #include "cmGlobalVisualStudio8Generator.h" #include "cmVisualStudio10ToolsetOptions.h" @@ -119,6 +121,11 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string Encoding() override; const char* GetToolsVersion() const; + virtual cm::optional GetVSInstanceVersion() const + { + return {}; + } + bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; } bool FindMakeProgram(cmMakefile* mf) override; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index c11ab1bf82c..50dc30b32cf 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -391,10 +391,15 @@ bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( return vsSetupAPIHelper.GetVSInstanceInfo(dir); } -bool cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion( - unsigned long long& vsInstanceVersion) const +cm::optional +cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion() const { - return vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion); + cm::optional result; + unsigned long long vsInstanceVersion; + if (vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion)) { + result = vsInstanceVersion; + } + return result; } bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const @@ -407,9 +412,9 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const return false; } unsigned long long const vsInstanceVersion16_7_P2 = 4503631666610212; - unsigned long long vsInstanceVersion; - return (this->GetVSInstanceVersion(vsInstanceVersion) && - vsInstanceVersion > vsInstanceVersion16_7_P2); + cm::optional vsInstanceVersion = + this->GetVSInstanceVersion(); + return (vsInstanceVersion && *vsInstanceVersion > vsInstanceVersion16_7_P2); } const char* diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index cee129e52b5..105e4954bd4 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -28,7 +28,7 @@ class cmGlobalVisualStudioVersionedGenerator bool GetVSInstance(std::string& dir) const; - bool GetVSInstanceVersion(unsigned long long& vsInstanceVersion) const; + cm::optional GetVSInstanceVersion() const override; AuxToolset FindAuxToolset(std::string& version, std::string& props) const override; From 947f0c8b811a2f5b0681590b449125e07a74ae0f Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 10:56:15 -0400 Subject: [PATCH 0693/1519] VS: Do not apply '/external:W*' flag table mapping on VS < 16.10 Since commit 9054cd05e6 (VS: Add flag table entries for '/external:W*' flags in VS 16.10, 2021-05-28, v3.20.4~10^2) we map flags to the `ExternalWarningLevel` element. VS 16.9 does not support that element, but its `cl` compiler does support the `/external:W*` flags. Filter out the flag table entry on older VS versions. Fixes: #22308 --- Source/cmGlobalVisualStudio10Generator.cxx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 596c73120fc..b911eef40b3 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1315,7 +1315,10 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry, namespace { -cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath) +unsigned long long const vsVer16_10_0 = 4503644629696790; + +cmIDEFlagTable const* cmLoadFlagTableJson( + std::string const& flagJsonPath, cm::optional vsver) { cmIDEFlagTable* ret = nullptr; auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath); @@ -1337,6 +1340,11 @@ cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath) flagEntry.comment = cmLoadFlagTableString(flag, "comment"); flagEntry.value = cmLoadFlagTableString(flag, "value"); flagEntry.special = cmLoadFlagTableSpecial(flag, "flags"); + // FIXME: Port this version check to a Json field. + if (vsver && *vsver < vsVer16_10_0 && + flagEntry.IDEName == "ExternalWarningLevel") { + continue; + } flagTable.push_back(flagEntry); } cmIDEFlagTable endFlag{ "", "", "", "", 0 }; @@ -1364,17 +1372,19 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( { cmIDEFlagTable const* ret = nullptr; + cm::optional vsver = this->GetVSInstanceVersion(); + std::string filename; if (!optionsName.empty()) { filename = cmGetFlagTableName(optionsName, table); - ret = cmLoadFlagTableJson(filename); + ret = cmLoadFlagTableJson(filename, vsver); } else { filename = cmGetFlagTableName(toolsetName, table); if (cmSystemTools::FileExists(filename)) { - ret = cmLoadFlagTableJson(filename); + ret = cmLoadFlagTableJson(filename, vsver); } else { filename = cmGetFlagTableName(defaultName, table); - ret = cmLoadFlagTableJson(filename); + ret = cmLoadFlagTableJson(filename, vsver); } } From e66a7fe07b117362120ae62826eb51c189f39c40 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 10:54:50 -0400 Subject: [PATCH 0694/1519] cmGlobalVisualStudio10Generator: Move static functions to anonymous namespace --- Source/cmGlobalVisualStudio10Generator.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 6c52ce0bc8b..1ebe40524b7 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1359,8 +1359,9 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry, return value; } -static cmIDEFlagTable const* cmLoadFlagTableJson( - std::string const& flagJsonPath) +namespace { + +cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath) { cmIDEFlagTable* ret = nullptr; auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath); @@ -1394,6 +1395,7 @@ static cmIDEFlagTable const* cmLoadFlagTableJson( } return ret; } +} cm::optional cmGlobalVisualStudio10Generator::FindFlagTable( cm::string_view toolsetName, cm::string_view table) const From aabc3ca47d51731e247300e4a6159f41e9dcb17c Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 10:53:22 -0400 Subject: [PATCH 0695/1519] cmGlobalVisualStudio10Generator: Adopt GetVSInstanceVersion method Port from `cmGlobalVisualStudioVersionedGenerator`. --- Source/cmGlobalVisualStudio10Generator.h | 5 +++++ .../cmGlobalVisualStudioVersionedGenerator.cxx | 17 +++++++++++------ Source/cmGlobalVisualStudioVersionedGenerator.h | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 25967204af5..48fe4659ab6 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -128,6 +128,11 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string Encoding() override; const char* GetToolsVersion() const; + virtual cm::optional GetVSInstanceVersion() const + { + return {}; + } + bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; } bool FindMakeProgram(cmMakefile* mf) override; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index c11ab1bf82c..50dc30b32cf 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -391,10 +391,15 @@ bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( return vsSetupAPIHelper.GetVSInstanceInfo(dir); } -bool cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion( - unsigned long long& vsInstanceVersion) const +cm::optional +cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion() const { - return vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion); + cm::optional result; + unsigned long long vsInstanceVersion; + if (vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion)) { + result = vsInstanceVersion; + } + return result; } bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const @@ -407,9 +412,9 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const return false; } unsigned long long const vsInstanceVersion16_7_P2 = 4503631666610212; - unsigned long long vsInstanceVersion; - return (this->GetVSInstanceVersion(vsInstanceVersion) && - vsInstanceVersion > vsInstanceVersion16_7_P2); + cm::optional vsInstanceVersion = + this->GetVSInstanceVersion(); + return (vsInstanceVersion && *vsInstanceVersion > vsInstanceVersion16_7_P2); } const char* diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index cee129e52b5..105e4954bd4 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -28,7 +28,7 @@ class cmGlobalVisualStudioVersionedGenerator bool GetVSInstance(std::string& dir) const; - bool GetVSInstanceVersion(unsigned long long& vsInstanceVersion) const; + cm::optional GetVSInstanceVersion() const override; AuxToolset FindAuxToolset(std::string& version, std::string& props) const override; From e4ca525d845e2b154ec7bc809071539618e2f7a2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 10:56:15 -0400 Subject: [PATCH 0696/1519] VS: Do not apply '/external:W*' flag table mapping on VS < 16.10 Since commit 9054cd05e6 (VS: Add flag table entries for '/external:W*' flags in VS 16.10, 2021-05-28, v3.20.4~10^2) we map flags to the `ExternalWarningLevel` element. VS 16.9 does not support that element, but its `cl` compiler does support the `/external:W*` flags. Filter out the flag table entry on older VS versions. Fixes: #22308 --- Source/cmGlobalVisualStudio10Generator.cxx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 1ebe40524b7..fa51092e3aa 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1361,7 +1361,10 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry, namespace { -cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath) +unsigned long long const vsVer16_10_0 = 4503644629696790; + +cmIDEFlagTable const* cmLoadFlagTableJson( + std::string const& flagJsonPath, cm::optional vsver) { cmIDEFlagTable* ret = nullptr; auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath); @@ -1383,6 +1386,11 @@ cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath) flagEntry.comment = cmLoadFlagTableString(flag, "comment"); flagEntry.value = cmLoadFlagTableString(flag, "value"); flagEntry.special = cmLoadFlagTableSpecial(flag, "flags"); + // FIXME: Port this version check to a Json field. + if (vsver && *vsver < vsVer16_10_0 && + flagEntry.IDEName == "ExternalWarningLevel") { + continue; + } flagTable.push_back(flagEntry); } cmIDEFlagTable endFlag{ "", "", "", "", 0 }; @@ -1458,7 +1466,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( } } - if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename)) { + cm::optional vsver = this->GetVSInstanceVersion(); + if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename, vsver)) { return ret; } From 9548b059c0ad6b35cd019b2ff00c0b23f702b840 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 14:18:09 -0400 Subject: [PATCH 0697/1519] ci: add clang-11 to cuda10.2 base image --- .gitlab/ci/docker/cuda10.2/Dockerfile | 4 ++ .gitlab/ci/docker/cuda10.2/install_deps.sh | 1 + .../ci/docker/cuda10.2/llvm-snapshot.gpg.key | 52 +++++++++++++++++++ .gitlab/ci/docker/cuda10.2/llvm.list | 2 + .gitlab/os-linux.yml | 2 +- 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 .gitlab/ci/docker/cuda10.2/llvm-snapshot.gpg.key create mode 100644 .gitlab/ci/docker/cuda10.2/llvm.list diff --git a/.gitlab/ci/docker/cuda10.2/Dockerfile b/.gitlab/ci/docker/cuda10.2/Dockerfile index e0ea0e73623..b6f37b51789 100644 --- a/.gitlab/ci/docker/cuda10.2/Dockerfile +++ b/.gitlab/ci/docker/cuda10.2/Dockerfile @@ -1,5 +1,9 @@ FROM nvidia/cuda:10.2-devel-ubuntu18.04 MAINTAINER Ben Boeckel +COPY llvm.list /etc/apt/sources.list.d/llvm.list +COPY llvm-snapshot.gpg.key /root/llvm-snapshot.gpg.key +RUN apt-key add /root/llvm-snapshot.gpg.key + COPY install_deps.sh /root/install_deps.sh RUN sh /root/install_deps.sh diff --git a/.gitlab/ci/docker/cuda10.2/install_deps.sh b/.gitlab/ci/docker/cuda10.2/install_deps.sh index 0d57cd386d8..6d539979d96 100755 --- a/.gitlab/ci/docker/cuda10.2/install_deps.sh +++ b/.gitlab/ci/docker/cuda10.2/install_deps.sh @@ -7,6 +7,7 @@ apt-get update # Install development tools. apt-get install -y \ g++ \ + clang-11 \ curl \ git diff --git a/.gitlab/ci/docker/cuda10.2/llvm-snapshot.gpg.key b/.gitlab/ci/docker/cuda10.2/llvm-snapshot.gpg.key new file mode 100644 index 00000000000..aa6b105aa3d --- /dev/null +++ b/.gitlab/ci/docker/cuda10.2/llvm-snapshot.gpg.key @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +mQINBFE9lCwBEADi0WUAApM/mgHJRU8lVkkw0CHsZNpqaQDNaHefD6Rw3S4LxNmM +EZaOTkhP200XZM8lVdbfUW9xSjA3oPldc1HG26NjbqqCmWpdo2fb+r7VmU2dq3NM +R18ZlKixiLDE6OUfaXWKamZsXb6ITTYmgTO6orQWYrnW6ckYHSeaAkW0wkDAryl2 +B5v8aoFnQ1rFiVEMo4NGzw4UX+MelF7rxaaregmKVTPiqCOSPJ1McC1dHFN533FY +Wh/RVLKWo6npu+owtwYFQW+zyQhKzSIMvNujFRzhIxzxR9Gn87MoLAyfgKEzrbbT +DhqqNXTxS4UMUKCQaO93TzetX/EBrRpJj+vP640yio80h4Dr5pAd7+LnKwgpTDk1 +G88bBXJAcPZnTSKu9I2c6KY4iRNbvRz4i+ZdwwZtdW4nSdl2792L7Sl7Nc44uLL/ +ZqkKDXEBF6lsX5XpABwyK89S/SbHOytXv9o4puv+65Ac5/UShspQTMSKGZgvDauU +cs8kE1U9dPOqVNCYq9Nfwinkf6RxV1k1+gwtclxQuY7UpKXP0hNAXjAiA5KS5Crq +7aaJg9q2F4bub0mNU6n7UI6vXguF2n4SEtzPRk6RP+4TiT3bZUsmr+1ktogyOJCc +Ha8G5VdL+NBIYQthOcieYCBnTeIH7D3Sp6FYQTYtVbKFzmMK+36ERreL/wARAQAB +tD1TeWx2ZXN0cmUgTGVkcnUgLSBEZWJpYW4gTExWTSBwYWNrYWdlcyA8c3lsdmVz +dHJlQGRlYmlhbi5vcmc+iQI4BBMBAgAiBQJRPZQsAhsDBgsJCAcDAgYVCAIJCgsE +FgIDAQIeAQIXgAAKCRAVz00Yr090Ibx+EADArS/hvkDF8juWMXxh17CgR0WZlHCC +9CTBWkg5a0bNN/3bb97cPQt/vIKWjQtkQpav6/5JTVCSx2riL4FHYhH0iuo4iAPR +udC7Cvg8g7bSPrKO6tenQZNvQm+tUmBHgFiMBJi92AjZ/Qn1Shg7p9ITivFxpLyX +wpmnF1OKyI2Kof2rm4BFwfSWuf8Fvh7kDMRLHv+MlnK/7j/BNpKdozXxLcwoFBmn +l0WjpAH3OFF7Pvm1LJdf1DjWKH0Dc3sc6zxtmBR/KHHg6kK4BGQNnFKujcP7TVdv +gMYv84kun14pnwjZcqOtN3UJtcx22880DOQzinoMs3Q4w4o05oIF+sSgHViFpc3W +R0v+RllnH05vKZo+LDzc83DQVrdwliV12eHxrMQ8UYg88zCbF/cHHnlzZWAJgftg +hB08v1BKPgYRUzwJ6VdVqXYcZWEaUJmQAPuAALyZESw94hSo28FAn0/gzEc5uOYx +K+xG/lFwgAGYNb3uGM5m0P6LVTfdg6vDwwOeTNIExVk3KVFXeSQef2ZMkhwA7wya +KJptkb62wBHFE+o9TUdtMCY6qONxMMdwioRE5BYNwAsS1PnRD2+jtlI0DzvKHt7B +MWd8hnoUKhMeZ9TNmo+8CpsAtXZcBho0zPGz/R8NlJhAWpdAZ1CmcPo83EW86Yq7 +BxQUKnNHcwj2ebkCDQRRPZQsARAA4jxYmbTHwmMjqSizlMJYNuGOpIidEdx9zQ5g +zOr431/VfWq4S+VhMDhs15j9lyml0y4ok215VRFwrAREDg6UPMr7ajLmBQGau0Fc +bvZJ90l4NjXp5p0NEE/qOb9UEHT7EGkEhaZ1ekkWFTWCgsy7rRXfZLxB6sk7pzLC +DshyW3zjIakWAnpQ5j5obiDy708pReAuGB94NSyb1HoW/xGsGgvvCw4r0w3xPStw +F1PhmScE6NTBIfLliea3pl8vhKPlCh54Hk7I8QGjo1ETlRP4Qll1ZxHJ8u25f/ta +RES2Aw8Hi7j0EVcZ6MT9JWTI83yUcnUlZPZS2HyeWcUj+8nUC8W4N8An+aNps9l/ +21inIl2TbGo3Yn1JQLnA1YCoGwC34g8QZTJhElEQBN0X29ayWW6OdFx8MDvllbBV +ymmKq2lK1U55mQTfDli7S3vfGz9Gp/oQwZ8bQpOeUkc5hbZszYwP4RX+68xDPfn+ +M9udl+qW9wu+LyePbW6HX90LmkhNkkY2ZzUPRPDHZANU5btaPXc2H7edX4y4maQa +xenqD0lGh9LGz/mps4HEZtCI5CY8o0uCMF3lT0XfXhuLksr7Pxv57yue8LLTItOJ +d9Hmzp9G97SRYYeqU+8lyNXtU2PdrLLq7QHkzrsloG78lCpQcalHGACJzrlUWVP/ +fN3Ht3kAEQEAAYkCHwQYAQIACQUCUT2ULAIbDAAKCRAVz00Yr090IbhWEADbr50X +OEXMIMGRLe+YMjeMX9NG4jxs0jZaWHc/WrGR+CCSUb9r6aPXeLo+45949uEfdSsB +pbaEdNWxF5Vr1CSjuO5siIlgDjmT655voXo67xVpEN4HhMrxugDJfCa6z97P0+ML +PdDxim57uNqkam9XIq9hKQaurxMAECDPmlEXI4QT3eu5qw5/knMzDMZj4Vi6hovL +wvvAeLHO/jsyfIdNmhBGU2RWCEZ9uo/MeerPHtRPfg74g+9PPfP6nyHD2Wes6yGd +oVQwtPNAQD6Cj7EaA2xdZYLJ7/jW6yiPu98FFWP74FN2dlyEA2uVziLsfBrgpS4l +tVOlrO2YzkkqUGrybzbLpj6eeHx+Cd7wcjI8CalsqtL6cG8cUEjtWQUHyTbQWAgG +5VPEgIAVhJ6RTZ26i/G+4J8neKyRs4vz+57UGwY6zI4AB1ZcWGEE3Bf+CDEDgmnP +LSwbnHefK9IljT9XU98PelSryUO/5UPw7leE0akXKB4DtekToO226px1VnGp3Bov +1GBGvpHvL2WizEwdk+nfk8LtrLzej+9FtIcq3uIrYnsac47Pf7p0otcFeTJTjSq3 +krCaoG4Hx0zGQG2ZFpHrSrZTVy6lxvIdfi0beMgY6h78p6M9eYZHQHc02DjFkQXN +bXb5c6gCHESH5PXwPU4jQEE7Ib9J6sbk7ZT2Mw== +=j+4q +-----END PGP PUBLIC KEY BLOCK----- diff --git a/.gitlab/ci/docker/cuda10.2/llvm.list b/.gitlab/ci/docker/cuda10.2/llvm.list new file mode 100644 index 00000000000..79f8265e72c --- /dev/null +++ b/.gitlab/ci/docker/cuda10.2/llvm.list @@ -0,0 +1,2 @@ +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 6b490be05b3..978543b8a8f 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -203,7 +203,7 @@ ### CUDA builds .cuda10.2: - image: "kitware/cmake:ci-cuda10.2-x86_64-2020-06-11" + image: "kitware/cmake:ci-cuda10.2-x86_64-2021-06-16" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" From f7af01efb6e3cf453f48def6e7eb8b325667578a Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 14:22:48 -0400 Subject: [PATCH 0698/1519] gitlab-ci: add job testing cuda10.2 with clang 11 --- .gitlab-ci.yml | 10 ++++++++++ .gitlab/ci/configure_cuda10.2_clang.cmake | 3 +++ .gitlab/ci/env_cuda10.2_clang.sh | 3 +++ .gitlab/os-linux.yml | 7 +++++++ 4 files changed, 23 insertions(+) create mode 100644 .gitlab/ci/configure_cuda10.2_clang.cmake create mode 100644 .gitlab/ci/env_cuda10.2_clang.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3765abcc301..d6825d1aee4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -214,6 +214,16 @@ test:cuda10.2-nvidia: - .run_dependent - .needs_centos6_x86_64 +test:cuda10.2-clang: + extends: + - .cuda10.2_clang + - .cmake_test_linux_release + - .linux_builder_tags_cuda + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + build:fedora34-ninja: extends: - .fedora34_ninja diff --git a/.gitlab/ci/configure_cuda10.2_clang.cmake b/.gitlab/ci/configure_cuda10.2_clang.cmake new file mode 100644 index 00000000000..e13ca881d6c --- /dev/null +++ b/.gitlab/ci/configure_cuda10.2_clang.cmake @@ -0,0 +1,3 @@ +set(CMake_TEST_CUDA "Clang" CACHE STRING "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/env_cuda10.2_clang.sh b/.gitlab/ci/env_cuda10.2_clang.sh new file mode 100644 index 00000000000..d3b253016e8 --- /dev/null +++ b/.gitlab/ci/env_cuda10.2_clang.sh @@ -0,0 +1,3 @@ +export CC=/usr/bin/clang-11 +export CXX=/usr/bin/clang++-11 +export CUDACXX=/usr/bin/clang++-11 diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 978543b8a8f..67e9ce54771 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -217,6 +217,13 @@ CMAKE_CONFIGURATION: cuda10.2_nvidia CTEST_NO_WARNINGS_ALLOWED: 1 +.cuda10.2_clang: + extends: .cuda10.2 + + variables: + CMAKE_CONFIGURATION: cuda10.2_clang + CTEST_NO_WARNINGS_ALLOWED: 1 + ## Tags .linux_builder_tags: From 886a97cbe7da0f969549f819ba22a8f264838272 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 14:56:06 -0400 Subject: [PATCH 0699/1519] gitlab-ci: add job to test with clang-7 and ninja on debian10 In commit 7e5e558d0f (gitlab-ci: add job to test with clang-7 on debian10, 2021-06-04) we added coverage of clang-7 with the Unix Makefiles generator. Do the same for Ninja. --- .gitlab-ci.yml | 10 ++++++++++ .gitlab/ci/configure_debian10_ninja_clang.cmake | 1 + .gitlab/ci/env_debian10_ninja_clang.sh | 2 ++ .gitlab/os-linux.yml | 6 ++++++ 4 files changed, 19 insertions(+) create mode 100644 .gitlab/ci/configure_debian10_ninja_clang.cmake create mode 100644 .gitlab/ci/env_debian10_ninja_clang.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3765abcc301..814fe2a08c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -176,6 +176,16 @@ test:debian10-aarch64-ninja: variables: CMAKE_CI_NO_MR: "true" +test:debian10-ninja-clang: + extends: + - .debian10_ninja_clang + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_manually + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + test:debian10-makefiles-clang: extends: - .debian10_makefiles_clang diff --git a/.gitlab/ci/configure_debian10_ninja_clang.cmake b/.gitlab/ci/configure_debian10_ninja_clang.cmake new file mode 100644 index 00000000000..20863a2fb08 --- /dev/null +++ b/.gitlab/ci/configure_debian10_ninja_clang.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/env_debian10_ninja_clang.sh b/.gitlab/ci/env_debian10_ninja_clang.sh new file mode 100644 index 00000000000..e0d5d6105b3 --- /dev/null +++ b/.gitlab/ci/env_debian10_ninja_clang.sh @@ -0,0 +1,2 @@ +export CC=/usr/bin/clang-7 +export CXX=/usr/bin/clang++-7 diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 6b490be05b3..c729aa95652 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -158,6 +158,12 @@ CMAKE_CONFIGURATION: debian10_makefiles_clang CMAKE_GENERATOR: "Unix Makefiles" +.debian10_ninja_clang: + extends: .debian10 + + variables: + CMAKE_CONFIGURATION: debian10_ninja_clang + ### Sanitizers .fedora_memcheck: From b642022046f8a43adc3f546921a206601e7d427f Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 09:55:10 -0400 Subject: [PATCH 0700/1519] AppleClang: Add flags for C17 and C23 Follow up commit 72f4984cdc (Clang: C23 support, 2021-02-07). --- Modules/Compiler/AppleClang-C.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Modules/Compiler/AppleClang-C.cmake b/Modules/Compiler/AppleClang-C.cmake index bd9819350a4..d711b6e654e 100644 --- a/Modules/Compiler/AppleClang-C.cmake +++ b/Modules/Compiler/AppleClang-C.cmake @@ -28,4 +28,14 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) endif() -__compiler_check_default_language_standard(C 4.0 99) +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) + set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") +endif() + +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0.3) + set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x") + set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x") +endif() + +__compiler_check_default_language_standard(C 4.0 99 9.1 11 12.0.5 17) From e80f56a7e5690db691efa1d5bb932ffd613c51a5 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 17 Jun 2021 00:03:04 -0400 Subject: [PATCH 0701/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ca070e9c86a..46e94f153ab 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210616) +set(CMake_VERSION_PATCH 20210617) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3fd65f5ca601d38c7b2ee8c99b148df31cea1acd Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 07:30:48 -0400 Subject: [PATCH 0702/1519] VS: Compare VS instance versions as strings This makes the values more readable. --- Source/cmGlobalVisualStudio10Generator.cxx | 13 +++++++------ Source/cmGlobalVisualStudio10Generator.h | 5 +---- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 14 +++++++------- Source/cmGlobalVisualStudioVersionedGenerator.h | 2 +- Source/cmVSSetupHelper.cxx | 8 +++----- Source/cmVSSetupHelper.h | 4 ++-- 6 files changed, 21 insertions(+), 25 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index fa51092e3aa..6ce82f4ea60 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1361,10 +1361,10 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry, namespace { -unsigned long long const vsVer16_10_0 = 4503644629696790; +std::string const vsVer16_10_0 = "16.10.31321.278"; -cmIDEFlagTable const* cmLoadFlagTableJson( - std::string const& flagJsonPath, cm::optional vsver) +cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath, + cm::optional vsVer) { cmIDEFlagTable* ret = nullptr; auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath); @@ -1387,7 +1387,8 @@ cmIDEFlagTable const* cmLoadFlagTableJson( flagEntry.value = cmLoadFlagTableString(flag, "value"); flagEntry.special = cmLoadFlagTableSpecial(flag, "flags"); // FIXME: Port this version check to a Json field. - if (vsver && *vsver < vsVer16_10_0 && + if (vsVer && + !cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_10_0) && flagEntry.IDEName == "ExternalWarningLevel") { continue; } @@ -1466,8 +1467,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable( } } - cm::optional vsver = this->GetVSInstanceVersion(); - if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename, vsver)) { + cm::optional vsVer = this->GetVSInstanceVersion(); + if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename, vsVer)) { return ret; } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 48fe4659ab6..646dbe28ae9 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -128,10 +128,7 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator std::string Encoding() override; const char* GetToolsVersion() const; - virtual cm::optional GetVSInstanceVersion() const - { - return {}; - } + virtual cm::optional GetVSInstanceVersion() const { return {}; } bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 50dc30b32cf..384aa66bdec 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -391,11 +391,11 @@ bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance( return vsSetupAPIHelper.GetVSInstanceInfo(dir); } -cm::optional +cm::optional cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion() const { - cm::optional result; - unsigned long long vsInstanceVersion; + cm::optional result; + std::string vsInstanceVersion; if (vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion)) { result = vsInstanceVersion; } @@ -411,10 +411,10 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS16) { return false; } - unsigned long long const vsInstanceVersion16_7_P2 = 4503631666610212; - cm::optional vsInstanceVersion = - this->GetVSInstanceVersion(); - return (vsInstanceVersion && *vsInstanceVersion > vsInstanceVersion16_7_P2); + static std::string const vsVer16_7_P2 = "16.7.30128.36"; + cm::optional vsVer = this->GetVSInstanceVersion(); + return (vsVer && + cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_7_P2)); } const char* diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 105e4954bd4..db4a0ba97a6 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -28,7 +28,7 @@ class cmGlobalVisualStudioVersionedGenerator bool GetVSInstance(std::string& dir) const; - cm::optional GetVSInstanceVersion() const override; + cm::optional GetVSInstanceVersion() const override; AuxToolset FindAuxToolset(std::string& version, std::string& props) const override; diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index 9626599a300..969a2c2c1c0 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -258,15 +258,13 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(std::string& vsInstallLocation) return isInstalled; } -bool cmVSSetupAPIHelper::GetVSInstanceVersion( - unsigned long long& vsInstanceVersion) +bool cmVSSetupAPIHelper::GetVSInstanceVersion(std::string& vsInstanceVersion) { - vsInstanceVersion = 0; + vsInstanceVersion.clear(); bool isInstalled = this->EnumerateAndChooseVSInstance(); if (isInstalled) { - vsInstanceVersion = - static_cast(chosenInstanceInfo.ullVersion); + vsInstanceVersion = cmsys::Encoding::ToNarrow(chosenInstanceInfo.Version); } return isInstalled; diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 04ea46db119..61a3ac7f8d8 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -88,7 +88,7 @@ struct VSInstanceInfo std::wstring VSInstallLocation; std::wstring Version; std::string VCToolsetVersion; - ULONGLONG ullVersion = 0; + ULONGLONG ullVersion = 0; // A.B.C.D = (A<<48)|(B<<32)|(C<<16)|D bool IsWin10SDKInstalled = false; bool IsWin81SDKInstalled = false; @@ -105,7 +105,7 @@ class cmVSSetupAPIHelper bool IsVSInstalled(); bool GetVSInstanceInfo(std::string& vsInstallLocation); - bool GetVSInstanceVersion(unsigned long long& vsInstanceVersion); + bool GetVSInstanceVersion(std::string& vsInstanceVersion); bool GetVCToolsetVersion(std::string& vsToolsetVersion); bool IsWin10SDKInstalled(); bool IsWin81SDKInstalled(); From b0f830ced6552b055bc73de470a4631aa3a14430 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 08:25:04 -0400 Subject: [PATCH 0703/1519] VS: Do not apply any '/external:*' flag table mapping on VS < 16.10 Since commit 887e9df0c7 (VS: Update v142 CL flag table for VS 16.10, 2021-06-04) we map several `/external:*` flags to their corresponding `.vcxproj` elements. These elements were added to `cl.xml` in VS 16.10, so filter them out in older VS versions. Add a field to the json flag table format to specify the minimum version of VS needed for a given mapping. Issue: #22308 --- Source/cmGlobalVisualStudio10Generator.cxx | 18 ++++++++++-------- Templates/MSBuild/FlagTables/v142_CL.json | 8 ++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 6ce82f4ea60..fc2665b42ba 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1361,8 +1361,6 @@ static unsigned int cmLoadFlagTableSpecial(Json::Value entry, namespace { -std::string const vsVer16_10_0 = "16.10.31321.278"; - cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath, cm::optional vsVer) { @@ -1380,18 +1378,22 @@ cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath, if (reader.parse(stream, flags, false) && flags.isArray()) { std::vector flagTable; for (auto const& flag : flags) { + Json::Value const& vsminJson = flag["vsmin"]; + if (vsminJson.isString()) { + std::string const& vsmin = vsminJson.asString(); + if (!vsmin.empty()) { + if (!vsVer || + cmSystemTools::VersionCompareGreater(vsmin, *vsVer)) { + continue; + } + } + } cmIDEFlagTable flagEntry; flagEntry.IDEName = cmLoadFlagTableString(flag, "name"); flagEntry.commandFlag = cmLoadFlagTableString(flag, "switch"); flagEntry.comment = cmLoadFlagTableString(flag, "comment"); flagEntry.value = cmLoadFlagTableString(flag, "value"); flagEntry.special = cmLoadFlagTableSpecial(flag, "flags"); - // FIXME: Port this version check to a Json field. - if (vsVer && - !cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_10_0) && - flagEntry.IDEName == "ExternalWarningLevel") { - continue; - } flagTable.push_back(flagEntry); } cmIDEFlagTable endFlag{ "", "", "", "", 0 }; diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 650ff6c1809..c21a3def6ab 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -572,6 +572,7 @@ "switch": "external:W0", "comment": "Turn Off All Warnings", "value": "TurnOffAllWarnings", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -579,6 +580,7 @@ "switch": "external:W1", "comment": "Level1", "value": "Level1", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -586,6 +588,7 @@ "switch": "external:W2", "comment": "Level2", "value": "Level2", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -593,6 +596,7 @@ "switch": "external:W3", "comment": "Level3", "value": "Level3", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -600,6 +604,7 @@ "switch": "external:W4", "comment": "Level4", "value": "Level4", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -1141,6 +1146,7 @@ "switch": "external:anglebrackets", "comment": "Treat Files Included with Angle Brackets as External", "value": "true", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -1148,6 +1154,7 @@ "switch": "external:templates-", "comment": "Template Diagnostics in External Headers", "value": "true", + "vsmin": "16.10.31321.278", "flags": [] }, { @@ -1277,6 +1284,7 @@ "switch": "external:env:", "comment": "External Directories Environment Variables", "value": "", + "vsmin": "16.10.31321.278", "flags": [ "UserValue", "SemicolonAppendable" From 45acb61432a9233cf39f652ea1eb638b3502a235 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Jun 2021 12:48:19 -0400 Subject: [PATCH 0704/1519] Help: Organize and revise 3.21 release notes Add section headers similar to the 3.20 release notes and move each individual bullet into an appropriate section. Revise a few bullets. --- Help/release/3.21.rst | 352 ++++++++++++++++++++++++------------------ 1 file changed, 204 insertions(+), 148 deletions(-) diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 609ffb504fd..04354dba723 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -7,100 +7,104 @@ CMake 3.21 Release Notes Changes made since CMake 3.20 include the following. -* The :command:`add_custom_command` command ``DEPFILE`` option learned to - support :manual:`generator expressions `. +New Features +============ -* The :command:`add_custom_command` command gained ``DEPFILE`` support on - the :generator:`Xcode` generator, and on :ref:`Visual Studio Generators` - for VS 2012 and above. +Presets +------- -* The :ref:`add_custom_command(TARGET) ` command - gained support for resolving target-dependent generator expressions. +* :manual:`cmake-presets(7)` gained support for specifying the install prefix + in a configure preset. -* ``ARMClang`` cpu/arch compile and link flags are no longer added - automatically based on the :variable:`CMAKE_SYSTEM_PROCESSOR` - variable or the undocumented ``CMAKE_SYSTEM_ARCH`` variable. - They must be specified explicitly. See policy :policy:`CMP0123`. - -* The :manual:`cmake(1)` ``-E capabilities`` output now contains for each - generator a ``supportedPlatforms`` field listing platform known to - be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. +* :manual:`cmake-presets(7)` gained support for conditional enabling of presets. -* The :manual:`cmake(1)` command gained the ``--install-prefix `` - command line option to specify the location of the install prefix. +* :manual:`cmake-presets(7)` gained support for a ``${hostSystemName}`` macro. -* :manual:`cmake-presets(7)` configure preset gained support for specifying - the install prefix. +* :manual:`cmake-presets(7)` gained support for omitting the ``generator`` and + ``binaryDir`` fields. -* :manual:`cmake-presets(7)` now support conditional enabling of presets. +Generators +---------- -* :manual:`cmake-presets(7)` gained support for a new ``${hostSystemName}`` - macro. +* The :ref:`Makefile Generators` and the :generator:`Ninja` generator + learned to add linker launcher tools along with the linker for ``C``, + ``CXX``, ``OBJC``, and ``OBJCXX`` languages. + See the :variable:`CMAKE__LINKER_LAUNCHER` variable + and :prop_tgt:`_LINKER_LAUNCHER` target property for details. -* :manual:`cmake-presets(7)` now support omitting the ``generator`` and - ``binaryDir`` fields. +Languages +--------- -* :variable:`CMAKE_HOST_SYSTEM_NAME`'s undocumented version-stripping behavior - has been moved earlier, before :command:`project` or - :command:`enable_language` is called. -* :variable:`CMAKE_SYSTEM_NAME`'s undocumented version-stripping behavior has - been removed entirely. If it is set by a ``-D`` flag or by a - :manual:`toolchain file `, it is left unaltered, even if - it still contains a version number. +* CMake learned to support ``HIP`` as a first-class language that can be + enabled via the :command:`project` and :command:`enable_language` commands. -* The :manual:`cmake(1)` command gained the ``--toolchain `` - command line option to specify a toolchain file. +* :prop_tgt:`C_STANDARD`, :prop_tgt:`OBJC_STANDARD`, and the + :manual:`Compile Features ` functionality gained + support for C17 and C23. -* The :ref:`Visual Studio Generators` for VS 2010 and above now place - per-source preprocessor definitions after target-wide preprocssor - definitions. This makes VS consistent with the :ref:`Ninja Generators` - and the :ref:`Makefile Generators`. +* Source file extensions ``.ixx`` and ``.cppm`` are now treated as C++. -* The :cpack_gen:`CPack DragNDrop Generator` gained option - :variable:`CPACK_DMG_FILESYSTEM` to control the ``.dmg`` filesystem. +Command-Line +------------ -* The new :variable:`CPACK_CUSTOM_INSTALL_VARIABLES` - can be used to set variables in CPack ``cmake_install.cmake`` - invocations. +* :manual:`cmake(1)` gained the ``--install-prefix `` + command-line option to specify the location of the install prefix. -* The :cpack_gen:`CPack NSIS Generator` gained a new variable - :variable:`CPACK_NSIS_EXECUTABLE` to specify the makensis - executable to use instead of the default one. +* :manual:`cmake(1)` gained the ``--toolchain `` + command-line option to specify a toolchain file. -* :prop_tgt:`C_STANDARD` and the - :manual:`Compile Features ` functionality gained - support for C17 and C23. +* :manual:`cmake(1)` ``-E capabilities`` output now contains for each + generator a ``supportedPlatforms`` field listing platforms known to + be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. -* :manual:`ctest(1)` gained documentation for its ability to capture - :ref:`Additional Test Measurements`. +* Messages printed to a terminal now may be colored by message type. -* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results - to a JUnit XML file. +Compilers +--------- -* :manual:`ctest(1)` learned to recognize files attached to a test at run time. - Previously it was only possible to attach files to tests at configure time - by using the :prop_test:`ATTACHED_FILES` or - :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. - See :ref:`Additional Test Measurements` for more information. +* The Fujitsu compiler is now supported using compiler id ``Fujitsu`` + in traditional (``Trad``) mode, and compiler id ``FujitsuClang`` + in ``Clang`` mode. -* Source file extensions ``.ixx`` and ``.cppm`` are now treated as C++. +Platforms +--------- -* The :prop_dir:`IMPORTED_TARGETS` directory property was added to - get a list of :ref:`Imported Targets` created in the current - directory. +* CMake now supports the MSYS runtime environment, much like CYGWIN. -* The :envvar:`CMAKE_TOOLCHAIN_FILE` environment variable was added to - provide a default value for the :variable:`CMAKE_TOOLCHAIN_FILE` variable. +File-Based API +-------------- -* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has - component been updated to 2.3. +* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field + has been updated to 2.3. * The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a new "directory" object containing directory-level information. This includes a list of installers generated by the :command:`install` command. -* The :command:`file(COPY_FILE)` command was added to copy a file to another. +Commands +-------- + +* The :command:`add_custom_command` command ``DEPFILE`` option: + + * may now use + :manual:`generator expressions `, + + * is now supported by :ref:`Visual Studio Generators` for VS 2012 + and above, and + + * is now supported by the :generator:`Xcode` generator. + +* The :command:`add_custom_command(TARGET)` command + (for :ref:`Build Events `) + gained support for resolving target-dependent generator expressions. + +* The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option. + +* The :command:`file(COPY_FILE)` command was added to copy a single file. + +* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command gained new + ``POST_INCLUDE_FILES`` and ``POST_EXCLUDE_FILES`` arguments. * The :command:`file(REAL_PATH)` command gained the option ``EXPAND_TILDE`` to replace any leading tilde with the path to the user's home directory. @@ -109,93 +113,165 @@ Changes made since CMake 3.20 include the following. failure in a result variable. It also gained a ``NO_REPLACE`` option to fail if the destination exists. +* The :command:`install` command gained a new ``IMPORTED_RUNTIME_ARTIFACTS`` + mode, which can be used to install the runtime artifacts of imported targets. + +* The :command:`install` command gained a new ``RUNTIME_DEPENDENCY_SET`` mode, + which can be used to install runtime dependencies using + :command:`file(GET_RUNTIME_DEPENDENCIES)`. + +* The :command:`install(TARGETS)` command gained new ``RUNTIME_DEPENDENCIES`` + and ``RUNTIME_DEPENDENCY_SET`` arguments, which can be used to install + runtime dependencies using :command:`file(GET_RUNTIME_DEPENDENCIES)`. + +* The :command:`install(SCRIPT|CODE)` command + supports a new option ``ALL_COMPONENTS`` which allows + the corresponding code to run for every component of + a per component installation. + +* The :command:`project` command now sets variables + :variable:`PROJECT_IS_TOP_LEVEL` and :variable:`_IS_TOP_LEVEL` + to indicate whether it was called in a top-level ``CMakeLists.txt`` file. + +Variables +--------- + +* The :envvar:`CMAKE_TOOLCHAIN_FILE` environment variable was added to + provide a default value for the :variable:`CMAKE_TOOLCHAIN_FILE` variable. + +Properties +---------- + +* The :prop_dir:`IMPORTED_TARGETS` directory property was added to + get a list of :ref:`Imported Targets` created in the current + directory. + +* The :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS >` target property + was added to tell the :generator:`Xcode` generator to embed app extensions + such as iMessage sticker packs. + Aspects of the embedding can be customized with the + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_PATH >`, + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_CODE_SIGN_ON_COPY _CODE_SIGN_ON_COPY>` and + :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY _REMOVE_HEADERS_ON_COPY>` + properties. + +Modules +------- + +* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support + the serial ``Fujitsu_SSL2`` and parallel ``Fujitsu_SSL2BLAMP`` libraries. + * The :module:`FindDevIL` module now provides imported targets. * The :module:`FindIconv` module now has version support. * The :module:`FindIntl` module now has version support. -* The :command:`find_file`, :command:`find_path`, :command:`find_program`, - and :command:`find_library` commands handle cache variables in the same way - regardless how they are defined. See policy :policy:`CMP0125` for details. - -* The :command:`find_file`, :command:`find_path`, :command:`find_program`, - and :command:`find_library` commands gained the option ``NO_CACHE`` to store - find result in normal variable. +* The :module:`FindMPI` module learned to support ``Fujitsu`` and + ``FujitsuClang`` in both host and cross compiling modes. * The :module:`FindMsys` module was added to find MSYS installations. Like :module:`FindCygwin`, it is used automatically by some other find modules to locate UNIX-style tools on Windows. +* The :module:`FindOpenMP` module learned to support ``Fujitsu`` and + ``FujitsuClang``. + * The :module:`FindVulkan` module gained imported targets ``Vulkan::Headers`` and ``Vulkan::glslangValidator``. -* The :command:`foreach` command restrict loop variables to the loop scope. - See policy :policy:`CMP0124` for details. +* The :module:`UseJava` module command ``add_jar`` gained a ``RESOURCES`` + option to allow explicit naming of resources with non-optional namespace. -* Addition of the ``Fujitsu`` compiler ID operating in traditional ``Trad`` - mode and ``FujitsuClang`` operating in ``Clang`` mode. -* The :module:`FindOpenMP` module learned to support ``Fujitsu`` and - ``FujitsuClang``. -* The :module:`FindMPI` module learned to support ``Fujitsu`` and - ``FujitsuClang`` in both host and cross compiling modes. -* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support - the serial ``Fujitsu SSL2`` and parallel ``Fujitsu SSL2BLAMP`` libraries. +* The :module:`UseSWIG` module use now standard library naming conventions + for the ``CSharp`` language. See policy :policy:`CMP0122`. -* The :command:`build_command` command gained a ``PARALLEL_LEVEL`` option. +* The :module:`UseSWIG` module now supports using the ``swig`` tool to + generate implicit dependencies with the :generator:`Xcode` generator. + +Generator Expressions +--------------------- + +* A new :genex:`TARGET_RUNTIME_DLLS` generator expression was added. + +CTest +----- + +* :manual:`ctest(1)` gained documentation for its ability to capture + :ref:`Additional Test Measurements`. + +* :manual:`ctest(1)` learned to recognize files attached to a test at run time. + Previously it was only possible to attach files to tests at configure time + by using the :prop_test:`ATTACHED_FILES` or + :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. + See :ref:`Additional Test Measurements` for more information. + +* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results + to a JUnit XML file. * The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option. -* The :command:`file(GET_RUNTIME_DEPENDENCIES)` command gained new - ``POST_INCLUDE_FILES`` and ``POST_EXCLUDE_FILES`` arguments. +CPack +----- -* CMake learned to support ``HIP`` as a first-class language that can be - enabled via the :command:`project` and :command:`enable_language` commands. +* The :cpack_gen:`CPack DragNDrop Generator` gained option + :variable:`CPACK_DMG_FILESYSTEM` to control the ``.dmg`` filesystem. -* Names given as ``DEPENDS`` or ``DEPENDENCIES`` arguments to - :command:`cpack_ifw_configure_component` or - :command:`cpack_ifw_configure_component_group` may now contain hyphens. - This requires QtIFW 3.1 or later. +* The :cpack_gen:`CPack IFW Generator` now supports hyphens in names + given to :command:`cpack_ifw_configure_component` or + :command:`cpack_ifw_configure_component_group` as ``DEPENDS`` or + ``DEPENDENCIES`` arguments. This requires QtIFW 3.1 or later. -* The :command:`install` command gained a new ``IMPORTED_RUNTIME_ARTIFACTS`` - mode, which can be used to install the runtime artifacts of imported targets. +* The :cpack_gen:`CPack NSIS Generator` gained a new + :variable:`CPACK_NSIS_EXECUTABLE` variable to specify the ``makensis`` + executable to use instead of the default one. -* The :command:`install(TARGETS)` command gained new ``RUNTIME_DEPENDENCIES`` - and ``RUNTIME_DEPENDENCY_SET`` arguments, which can be used to install - runtime dependencies using :command:`file(GET_RUNTIME_DEPENDENCIES)`. -* The :command:`install` command gained a new ``RUNTIME_DEPENDENCY_SET`` mode, - which can be used to install runtime dependencies using - :command:`file(GET_RUNTIME_DEPENDENCIES)`. +* The :variable:`CPACK_CUSTOM_INSTALL_VARIABLES` variable was added to set + variables in ``cmake_install.cmake`` script invocations made by CPack. -* The :command:`install(SCRIPT|CODE)` command - supports a new option ``ALL_COMPONENTS`` which allows - the corresponding code to run for every component of - a per component installation. +Deprecated and Removed Features +=============================== -* The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to - add linker launcher tools along with the linker for ``C``, ``CXX``, ``OBJC``, and - ``OBJCXX`` languages. See the :variable:`CMAKE__LINKER_LAUNCHER` variable - and :prop_tgt:`_LINKER_LAUNCHER` target property for details. +* Undocumented :variable:`CMAKE_SYSTEM_NAME` version-stripping behavior has + been removed entirely. If it is set by a ``-D`` flag or by a + :manual:`toolchain file `, it is left unaltered, + even if it still contains a version number. + Similar :variable:`CMAKE_HOST_SYSTEM_NAME` version-stripping behavior, + also undocumented, has been moved earlier, before :command:`project` or + :command:`enable_language` is called. -* :command:`target_link_libraries` calls referencing object libraries - via the :genex:`TARGET_OBJECTS` generator expression now place the - object files before all libraries on the link line, regardless of - their specified order. See documentation on - :ref:`Linking Object Libraries via \$\` for details. +* ``ARMClang`` cpu/arch compile and link flags are no longer added + automatically based on the :variable:`CMAKE_SYSTEM_PROCESSOR` + variable or the undocumented ``CMAKE_SYSTEM_ARCH`` variable. + They must be specified explicitly. See policy :policy:`CMP0123`. + +Other Changes +============= + +* The :command:`find_file`, :command:`find_path`, :command:`find_program`, + and :command:`find_library` commands handle cache variables in the same way + regardless how they are defined. See policy :policy:`CMP0125` for details. + +* The :command:`find_file`, :command:`find_path`, :command:`find_program`, + and :command:`find_library` commands gained the option ``NO_CACHE`` to store + find result in normal variable. + +* The :command:`foreach` command now isolates loop variables in the loop scope. + See policy :policy:`CMP0124` for details. * The :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and ``REMOVE_AT`` subcommands now error with invalid (i.e., non-integer) values are given as any of their index arguments based on the setting of policy :policy:`CMP0121`. -* The precompiled binaries provided on - `cmake.org `_ now support - ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and - :variable:`CPACK_ARCHIVE_THREADS` variables. +* The :command:`set(CACHE)` command no longer removes a normal variable + of the same name, if any. See policy :policy:`CMP0126`. -* Messages printed to a terminal now may be colored by message type. - -* CMake now supports the MSYS runtime environment, much like CYGWIN. +* :command:`target_link_libraries` calls referencing object libraries + via the :genex:`TARGET_OBJECTS` generator expression now place the + object files before all libraries on the link line, regardless of + their specified order. See documentation on + :ref:`Linking Object Libraries via \$\` for details. * The :ref:`Ninja Generators` now pass source files and include directories to the compiler using absolute paths. This makes diagnostic messages and @@ -204,32 +280,12 @@ Changes made since CMake 3.20 include the following. * The :generator:`NMake Makefiles` generator now encodes the generated makefiles as UTF-8 with a BOM when using ``nmake`` from VS 9 or above. -* :prop_tgt:`OBJC_STANDARD` gained support for C17 and C23. - -* :command:`project` now sets variables :variable:`PROJECT_IS_TOP_LEVEL` and - :variable:`_IS_TOP_LEVEL` to indicate whether it was called - in a top level ``CMakeLists.txt`` file. - -* A new :genex:`TARGET_RUNTIME_DLLS` generator expression was added. - -* The :command:`set(CACHE)` command no longer removes a normal variable of the - same name, if any. See policy :policy:`CMP0126`. - -* The :module:`UseJava` module command ``add_jar`` gained option RESOURCES - allow explicit naming of resources with non-optional namespace. - -* The :module:`UseSWIG` module use now standard library name conventions for - ``CSharp`` language. See policy :policy:`CMP0122`. - -* :module:`UseSWIG` module gained the capability, for - :generator:`Xcode` generator, to use `swig` tool to generate implicit - dependencies. +* The :ref:`Visual Studio Generators` for VS 2010 and above now place + per-source preprocessor definitions after target-wide preprocssor + definitions. This makes VS consistent with the :ref:`Ninja Generators` + and the :ref:`Makefile Generators`. -* The :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS >` target property - was added to tell the :generator:`Xcode` generator to embed app extensions - such as iMessage sticker packs. - Aspects of the embedding can be customized with the - :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_PATH >`, - :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_CODE_SIGN_ON_COPY _CODE_SIGN_ON_COPY>` and - :prop_tgt:`XCODE_EMBED_APP_EXTENSIONS_REMOVE_HEADERS_ON_COPY _REMOVE_HEADERS_ON_COPY>` - properties. +* The precompiled binaries provided on + `cmake.org `_ now support + ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and + :variable:`CPACK_ARCHIVE_THREADS` variables. From f119fbeec568c28ca36b52532c40e72252fe69be Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 09:48:54 -0400 Subject: [PATCH 0705/1519] Help: Update Sphinx versionadded directives for 3.21 release Run the script: Utilities/Sphinx/update_versions.py --since v3.20.0 --overwrite Manually remove directives generated in documents for long-existing features for which documentation was added. --- Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst index 534e2ada3a9..1c070b8faf6 100644 --- a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst +++ b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst @@ -1,6 +1,8 @@ CPACK_CUSTOM_INSTALL_VARIABLES ------------------------------ +.. versionadded:: 3.21 + CPack variables (set via e.g. ``cpack -D``, ``CPackConfig.cmake`` or :variable:`CPACK_PROJECT_CONFIG_FILE` scripts) are not directly visible in installation scripts. Instead, one can pass a list of ``varName=value`` From 8406d4c1d1d0371c933b6d142b1cd4522c289f83 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Jun 2021 11:58:48 -0400 Subject: [PATCH 0706/1519] Utilities/Sphinx: Index guide section documents for cross-referencing Extend the change from commit 6185265800 (Utilities/Sphinx: Index guide-level documents for cross-referencing, 2019-12-06, v3.17.0-rc1~181^2~1) to name guide documents other than the top level using their docname instead of their title. This will allow them to be cross-referenced by a stable name even if their title changes. --- Utilities/Sphinx/cmake.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 9fa56cd4b0c..9215e149863 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -260,6 +260,8 @@ def apply(self): # Insert the object link target. if objtype == 'command': targetname = title.lower() + elif objtype == 'guide' and not tail.endswith('/index'): + targetname = tail else: if objtype == 'genex': m = CMakeXRefRole._re_genex.match(title) @@ -312,6 +314,7 @@ class CMakeXRefRole(XRefRole): _re = re.compile(r'^(.+?)(\s*)(?$', re.DOTALL) _re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL) _re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL) + _re_guide = re.compile(r'^([^<>/]+)/([^<>]*)$', re.DOTALL) def __call__(self, typ, rawtext, text, *args, **keys): # Translate CMake command cross-references of the form: @@ -326,6 +329,10 @@ def __call__(self, typ, rawtext, text, *args, **keys): m = CMakeXRefRole._re_genex.match(text) if m: text = '%s <%s>' % (text, m.group(1)) + elif typ == 'cmake:guide': + m = CMakeXRefRole._re_guide.match(text) + if m: + text = '%s <%s>' % (m.group(2), text) # CMake cross-reference targets frequently contain '<' so escape # any explicit `` with '<' not preceded by whitespace. while True: @@ -369,6 +376,10 @@ def apply(self): continue objname = ref['reftarget'] + if objtype == 'guide' and CMakeXRefRole._re_guide.match(objname): + # Do not index cross-references to guide sections. + continue + targetnum = env.new_serialno('index-%s:%s' % (objtype, objname)) targetid = 'index-%s-%s:%s' % (targetnum, objtype, objname) From 13fdb263231598df2cec0fb7bc9515f1f56b5577 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 10:33:07 -0400 Subject: [PATCH 0707/1519] Tutorial: Break up intro paragraph --- Help/guide/tutorial/index.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 94753d5dc9b..7cdd844d06a 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -10,12 +10,13 @@ Introduction The CMake tutorial provides a step-by-step guide that covers common build system issues that CMake helps address. Seeing how various topics all -work together in an example project can be very helpful. The tutorial -documentation and source code for examples can be found in the -``Help/guide/tutorial`` directory of the CMake source code tree. Each step has -its own subdirectory containing code that may be used as a starting point. The -tutorial examples are progressive so that each step provides the complete -solution for the previous step. +work together in an example project can be very helpful. + +The tutorial documentation and source code for examples can be found in +the ``Help/guide/tutorial`` directory of the CMake source code tree. +Each step has its own subdirectory containing code that may be used as a +starting point. The tutorial examples are progressive so that each step +provides the complete solution for the previous step. A Basic Starting Point (Step 1) =============================== From d1c3e7e78af0b3a4a5637e2bf3af86cfa5ba6e6f Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 10 Jun 2021 23:03:40 +0200 Subject: [PATCH 0708/1519] Tutorial: Split steps into separate files Fixes: #21737 --- .../guide/tutorial/A Basic Starting Point.rst | 135 +++ .../tutorial/Adding Export Configuration.rst | 88 ++ .../tutorial/Adding Generator Expressions.rst | 69 ++ ...Adding Support for a Testing Dashboard.rst | 51 + .../tutorial/Adding System Introspection.rst | 50 + ...dding Usage Requirements for a Library.rst | 46 + ...ng a Custom Command and Generated File.rst | 75 ++ Help/guide/tutorial/Adding a Library.rst | 116 +++ .../guide/tutorial/Installing and Testing.rst | 85 ++ .../tutorial/Packaging Debug and Release.rst | 78 ++ .../guide/tutorial/Packaging an Installer.rst | 55 + .../Selecting Static or Shared Libraries.rst | 66 ++ Help/guide/tutorial/index.rst | 949 +----------------- 13 files changed, 932 insertions(+), 931 deletions(-) create mode 100644 Help/guide/tutorial/A Basic Starting Point.rst create mode 100644 Help/guide/tutorial/Adding Export Configuration.rst create mode 100644 Help/guide/tutorial/Adding Generator Expressions.rst create mode 100644 Help/guide/tutorial/Adding Support for a Testing Dashboard.rst create mode 100644 Help/guide/tutorial/Adding System Introspection.rst create mode 100644 Help/guide/tutorial/Adding Usage Requirements for a Library.rst create mode 100644 Help/guide/tutorial/Adding a Custom Command and Generated File.rst create mode 100644 Help/guide/tutorial/Adding a Library.rst create mode 100644 Help/guide/tutorial/Installing and Testing.rst create mode 100644 Help/guide/tutorial/Packaging Debug and Release.rst create mode 100644 Help/guide/tutorial/Packaging an Installer.rst create mode 100644 Help/guide/tutorial/Selecting Static or Shared Libraries.rst diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst new file mode 100644 index 00000000000..296b3c32ed1 --- /dev/null +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -0,0 +1,135 @@ +Step 1: A Basic Starting Point +============================== + +The most basic project is an executable built from source code files. +For simple projects, a three line ``CMakeLists.txt`` file is all that is +required. This will be the starting point for our tutorial. Create a +``CMakeLists.txt`` file in the ``Step1`` directory that looks like: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.10) + + # set the project name + project(Tutorial) + + # add the executable + add_executable(Tutorial tutorial.cxx) + + +Note that this example uses lower case commands in the ``CMakeLists.txt`` file. +Upper, lower, and mixed case commands are supported by CMake. The source +code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be +used to compute the square root of a number. + +Adding a Version Number and Configured Header File +-------------------------------------------------- + +The first feature we will add is to provide our executable and project with a +version number. While we could do this exclusively in the source code, using +``CMakeLists.txt`` provides more flexibility. + +First, modify the ``CMakeLists.txt`` file to use the :command:`project` command +to set the project name and version number. + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :end-before: # specify the C++ standard + +Then, configure a header file to pass the version number to the source +code: + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :start-after: # to the source code + :end-before: # add the executable + +Since the configured file will be written into the binary tree, we +must add that directory to the list of paths to search for include +files. Add the following lines to the end of the ``CMakeLists.txt`` file: + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +Using your favorite editor, create ``TutorialConfig.h.in`` in the source +directory with the following contents: + +.. literalinclude:: Step2/TutorialConfig.h.in + :language: cmake + +When CMake configures this header file the values for +``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be +replaced. + +Next modify ``tutorial.cxx`` to include the configured header file, +``TutorialConfig.h``. + +Finally, let's print out the executable name and version number by updating +``tutorial.cxx`` as follows: + +.. literalinclude:: Step2/tutorial.cxx + :language: c++ + :start-after: { + :end-before: // convert input to double + +Specify the C++ Standard +------------------------- + +Next let's add some C++11 features to our project by replacing ``atof`` with +``std::stod`` in ``tutorial.cxx``. At the same time, remove +``#include ``. + +.. literalinclude:: Step2/tutorial.cxx + :language: c++ + :start-after: // convert input to double + :end-before: // calculate square root + +We will need to explicitly state in the CMake code that it should use the +correct flags. The easiest way to enable support for a specific C++ standard +in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this +tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the +``CMakeLists.txt`` file to 11 and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to +True. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the call +to ``add_executable``. + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :end-before: # configure a header file to pass some of the CMake settings + +Build and Test +-------------- + +Run the :manual:`cmake ` executable or the +:manual:`cmake-gui ` to configure the project and then build it +with your chosen build tool. + +For example, from the command line we could navigate to the +``Help/guide/tutorial`` directory of the CMake source code tree and create a +build directory: + +.. code-block:: console + + mkdir Step1_build + +Next, navigate to the build directory and run CMake to configure the project +and generate a native build system: + +.. code-block:: console + + cd Step1_build + cmake ../Step1 + +Then call that build system to actually compile/link the project: + +.. code-block:: console + + cmake --build . + +Finally, try to use the newly built ``Tutorial`` with these commands: + +.. code-block:: console + + Tutorial 4294967296 + Tutorial 10 + Tutorial diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst new file mode 100644 index 00000000000..55cb3e29f8c --- /dev/null +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -0,0 +1,88 @@ +Step 11: Adding Export Configuration +==================================== + +During `Installing and Testing (Step 4)`_ of the tutorial we added the ability +for CMake to install the library and headers of the project. During +`Building an Installer (Step 7)`_ we added the ability to package up this +information so it could be distributed to other people. + +The next step is to add the necessary information so that other CMake projects +can use our project, be it from a build directory, a local install or when +packaged. + +The first step is to update our :command:`install(TARGETS)` commands to not +only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword +generates and installs a CMake file containing code to import all targets +listed in the install command from the installation tree. So let's go ahead and +explicitly ``EXPORT`` the MathFunctions library by updating the ``install`` +command in ``MathFunctions/CMakeLists.txt`` to look like: + +.. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install rules + +Now that we have MathFunctions being exported, we also need to explicitly +install the generated ``MathFunctionsTargets.cmake`` file. This is done by +adding the following to the bottom of the top-level ``CMakeLists.txt``: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: # install the configuration targets + :end-before: include(CMakePackageConfigHelpers) + +At this point you should try and run CMake. If everything is setup properly +you will see that CMake will generate an error that looks like: + +.. code-block:: console + + Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains + path: + + "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions" + + which is prefixed in the source directory. + +What CMake is trying to say is that during generating the export information +it will export a path that is intrinsically tied to the current machine and +will not be valid on other machines. The solution to this is to update the +MathFunctions :command:`target_include_directories` to understand that it needs +different ``INTERFACE`` locations when being used from within the build +directory and from an install / package. This means converting the +:command:`target_include_directories` call for MathFunctions to look like: + +.. literalinclude:: Step12/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # to find MathFunctions.h, while we don't. + :end-before: # should we use our own math functions + +Once this has been updated, we can re-run CMake and verify that it doesn't +warn anymore. + +At this point, we have CMake properly packaging the target information that is +required but we will still need to generate a ``MathFunctionsConfig.cmake`` so +that the CMake :command:`find_package` command can find our project. So let's go +ahead and add a new file to the top-level of the project called +``Config.cmake.in`` with the following contents: + +.. literalinclude:: Step12/Config.cmake.in + +Then, to properly configure and install that file, add the following to the +bottom of the top-level ``CMakeLists.txt``: + +.. literalinclude:: Step12/CMakeLists.txt + :language: cmake + :start-after: # install the configuration targets + :end-before: # generate the export + +At this point, we have generated a relocatable CMake Configuration for our +project that can be used after the project has been installed or packaged. If +we want our project to also be used from a build directory we only have to add +the following to the bottom of the top level ``CMakeLists.txt``: + +.. literalinclude:: Step12/CMakeLists.txt + :language: cmake + :start-after: # needs to be after the install(TARGETS ) command + +With this export call we now generate a ``Targets.cmake``, allowing the +configured ``MathFunctionsConfig.cmake`` in the build directory to be used by +other projects, without needing it to be installed. diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst new file mode 100644 index 00000000000..7a3abb135f3 --- /dev/null +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -0,0 +1,69 @@ +Step 10: Adding Generator Expressions +===================================== + +:manual:`Generator expressions ` are evaluated +during build system generation to produce information specific to each build +configuration. + +:manual:`Generator expressions ` are allowed in +the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`, +:prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others. +They may also be used when using commands to populate those properties, such as +:command:`target_link_libraries`, :command:`target_include_directories`, +:command:`target_compile_definitions` and others. + +:manual:`Generator expressions ` may be used +to enable conditional linking, conditional definitions used when compiling, +conditional include directories and more. The conditions may be based on the +build configuration, target properties, platform information or any other +queryable information. + +There are different types of +:manual:`generator expressions ` including +Logical, Informational, and Output expressions. + +Logical expressions are used to create conditional output. The basic +expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty +string, and ``<1:...>`` results in the content of "...". They can also be +nested. + +A common usage of +:manual:`generator expressions ` is to +conditionally add compiler flags, such as those for language levels or +warnings. A nice pattern is to associate this information to an ``INTERFACE`` +target allowing this information to propagate. Let's start by constructing an +``INTERFACE`` target and specifying the required C++ standard level of ``11`` +instead of using :variable:`CMAKE_CXX_STANDARD`. + +So the following code: + +.. literalinclude:: Step10/CMakeLists.txt + :language: cmake + :start-after: project(Tutorial VERSION 1.0) + :end-before: # control where the static and shared libraries are built so that on windows + +Would be replaced with: + +.. literalinclude:: Step11/CMakeLists.txt + :language: cmake + :start-after: project(Tutorial VERSION 1.0) + :end-before: # add compiler warning flags just when building this project via + + +Next we add the desired compiler warning flags that we want for our project. As +warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID`` +generator expression to control which flags to apply given a language and a set +of compiler ids as seen below: + +.. literalinclude:: Step11/CMakeLists.txt + :language: cmake + :start-after: # the BUILD_INTERFACE genex + :end-before: # control where the static and shared libraries are built so that on windows + +Looking at this we see that the warning flags are encapsulated inside a +``BUILD_INTERFACE`` condition. This is done so that consumers of our installed +project will not inherit our warning flags. + + +**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have +a :command:`target_link_libraries` call to ``tutorial_compiler_flags``. diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst new file mode 100644 index 00000000000..41b772c9db2 --- /dev/null +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -0,0 +1,51 @@ +Step 8: Adding Support for a Testing Dashboard +============================================== + +Adding support for submitting our test results to a dashboard is simple. We +already defined a number of tests for our project in `Testing Support`_. Now we +just have to run those tests and submit them to a dashboard. To include support +for dashboards we include the :module:`CTest` module in our top-level +``CMakeLists.txt``. + +Replace: + +.. code-block:: cmake + + # enable testing + enable_testing() + +With: + +.. code-block:: cmake + + # enable dashboard scripting + include(CTest) + +The :module:`CTest` module will automatically call ``enable_testing()``, so we +can remove it from our CMake files. + +We will also need to create a ``CTestConfig.cmake`` file in the top-level +directory where we can specify the name of the project and where to submit the +dashboard. + +.. literalinclude:: Step9/CTestConfig.cmake + :language: cmake + +The :manual:`ctest ` executable will read in this file when it runs. +To create a simple dashboard you can run the :manual:`cmake ` +executable or the :manual:`cmake-gui ` to configure the project, +but do not build it yet. Instead, change directory to the binary tree, and then +run: + + ctest [-VV] -D Experimental + +Remember, for multi-config generators (e.g. Visual Studio), the configuration +type must be specified:: + + ctest [-VV] -C Debug -D Experimental + +Or, from an IDE, build the ``Experimental`` target. + +The :manual:`ctest ` executable will build and test the project and +submit the results to Kitware's public dashboard: +https://my.cdash.org/index.php?project=CMakeTutorial. diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst new file mode 100644 index 00000000000..0ee360cf5f7 --- /dev/null +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -0,0 +1,50 @@ +Step 5: Adding System Introspection +=================================== + +Let us consider adding some code to our project that depends on features the +target platform may not have. For this example, we will add some code that +depends on whether or not the target platform has the ``log`` and ``exp`` +functions. Of course almost every platform has these functions but for this +tutorial assume that they are not common. + +If the platform has ``log`` and ``exp`` then we will use them to compute the +square root in the ``mysqrt`` function. We first test for the availability of +these functions using the :module:`CheckSymbolExists` module in +``MathFunctions/CMakeLists.txt``. On some platforms, we will need to link to +the m library. If ``log`` and ``exp`` are not initially found, require the m +library and try again. + +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # does this system provide the log and exp functions? + :end-before: # add compile definitions + +If available, use :command:`target_compile_definitions` to specify +``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions. + +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # add compile definitions + :end-before: # install rules + +If ``log`` and ``exp`` are available on the system, then we will use them to +compute the square root in the ``mysqrt`` function. Add the following code to +the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the +``#endif`` before returning the result!): + +.. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :language: c++ + :start-after: // if we have both log and exp then use them + :end-before: // do ten iterations + +We will also need to modify ``mysqrt.cxx`` to include ``cmath``. + +.. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :language: c++ + :end-before: #include + +Run the :manual:`cmake ` executable or the +:manual:`cmake-gui ` to configure the project and then build it +with your chosen build tool and run the Tutorial executable. + +Which function gives better results now, sqrt or mysqrt? diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst new file mode 100644 index 00000000000..a625d90480e --- /dev/null +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -0,0 +1,46 @@ +Step 3: Adding Usage Requirements for a Library +=============================================== + +Usage requirements allow for far better control over a library or executable's +link and include line while also giving more control over the transitive +property of targets inside CMake. The primary commands that leverage usage +requirements are: + + - :command:`target_compile_definitions` + - :command:`target_compile_options` + - :command:`target_include_directories` + - :command:`target_link_libraries` + +Let's refactor our code from `Adding a Library (Step 2)`_ to use the modern +CMake approach of usage requirements. We first state that anybody linking to +MathFunctions needs to include the current source directory, while +MathFunctions itself doesn't. So this can become an ``INTERFACE`` usage +requirement. + +Remember ``INTERFACE`` means things that consumers require but the producer +doesn't. Add the following lines to the end of +``MathFunctions/CMakeLists.txt``: + +.. literalinclude:: Step4/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # to find MathFunctions.h + +Now that we've specified usage requirements for MathFunctions we can safely +remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level +``CMakeLists.txt``, here: + +.. literalinclude:: Step4/CMakeLists.txt + :language: cmake + :start-after: # add the MathFunctions library + :end-before: # add the executable + +And here: + +.. literalinclude:: Step4/CMakeLists.txt + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +Once this is done, run the :manual:`cmake ` executable or the +:manual:`cmake-gui ` to configure the project and then build it +with your chosen build tool or by using ``cmake --build .`` from the build +directory. diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst new file mode 100644 index 00000000000..0e3e60cdb3a --- /dev/null +++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst @@ -0,0 +1,75 @@ +Step 6: Adding a Custom Command and Generated File +================================================== + +Suppose, for the purpose of this tutorial, we decide that we never want to use +the platform ``log`` and ``exp`` functions and instead would like to +generate a table of precomputed values to use in the ``mysqrt`` function. +In this section, we will create the table as part of the build process, +and then compile that table into our application. + +First, let's remove the check for the ``log`` and ``exp`` functions in +``MathFunctions/CMakeLists.txt``. Then remove the check for ``HAVE_LOG`` and +``HAVE_EXP`` from ``mysqrt.cxx``. At the same time, we can remove +:code:`#include `. + +In the ``MathFunctions`` subdirectory, a new source file named +``MakeTable.cxx`` has been provided to generate the table. + +After reviewing the file, we can see that the table is produced as valid C++ +code and that the output filename is passed in as an argument. + +The next step is to add the appropriate commands to the +``MathFunctions/CMakeLists.txt`` file to build the MakeTable executable and +then run it as part of the build process. A few commands are needed to +accomplish this. + +First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for +``MakeTable`` is added as any other executable would be added. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # first we add the executable that generates the table + :end-before: # add the command to generate the source code + +Then we add a custom command that specifies how to produce ``Table.h`` +by running MakeTable. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # add the command to generate the source code + :end-before: # add the main library + +Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated +file ``Table.h``. This is done by adding the generated ``Table.h`` to the list +of sources for the library MathFunctions. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # add the main library + :end-before: # state that anybody linking + +We also have to add the current binary directory to the list of include +directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # state that we depend on our bin + :end-before: # install rules + +Now let's use the generated table. First, modify ``mysqrt.cxx`` to include +``Table.h``. Next, we can rewrite the mysqrt function to use the table: + +.. literalinclude:: Step7/MathFunctions/mysqrt.cxx + :language: c++ + :start-after: // a hack square root calculation using simple operations + +Run the :manual:`cmake ` executable or the +:manual:`cmake-gui ` to configure the project and then build it +with your chosen build tool. + +When this project is built it will first build the ``MakeTable`` executable. +It will then run ``MakeTable`` to produce ``Table.h``. Finally, it will +compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the MathFunctions +library. + +Run the Tutorial executable and verify that it is using the table. diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst new file mode 100644 index 00000000000..3ff966cf5bd --- /dev/null +++ b/Help/guide/tutorial/Adding a Library.rst @@ -0,0 +1,116 @@ +Step 2: Adding a Library +======================== + +Now we will add a library to our project. This library will contain our own +implementation for computing the square root of a number. The executable can +then use this library instead of the standard square root function provided by +the compiler. + +For this tutorial we will put the library into a subdirectory +called ``MathFunctions``. This directory already contains a header file, +``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one +function called ``mysqrt`` that provides similar functionality to the +compiler's ``sqrt`` function. + +Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions`` +directory: + +.. literalinclude:: Step3/MathFunctions/CMakeLists.txt + :language: cmake + +To make use of the new library we will add an :command:`add_subdirectory` +call in the top-level ``CMakeLists.txt`` file so that the library will get +built. We add the new library to the executable, and add ``MathFunctions`` as +an include directory so that the ``mysqrt.h`` header file can be found. The +last few lines of the top-level ``CMakeLists.txt`` file should now look like: + +.. code-block:: cmake + + # add the MathFunctions library + add_subdirectory(MathFunctions) + + # add the executable + add_executable(Tutorial tutorial.cxx) + + target_link_libraries(Tutorial PUBLIC MathFunctions) + + # add the binary tree to the search path for include files + # so that we will find TutorialConfig.h + target_include_directories(Tutorial PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/MathFunctions" + ) + +Now let us make the MathFunctions library optional. While for the tutorial +there really isn't any need to do so, for larger projects this is a common +occurrence. The first step is to add an option to the top-level +``CMakeLists.txt`` file. + +.. literalinclude:: Step3/CMakeLists.txt + :language: cmake + :start-after: # should we use our own math functions + :end-before: # add the MathFunctions library + +This option will be displayed in the :manual:`cmake-gui ` and +:manual:`ccmake ` +with a default value of ON that can be changed by the user. This setting will +be stored in the cache so that the user does not need to set the value each +time they run CMake on a build directory. + +The next change is to make building and linking the MathFunctions library +conditional. To do this we change the end of the top-level ``CMakeLists.txt`` +file to look like the following: + +.. literalinclude:: Step3/CMakeLists.txt + :language: cmake + :start-after: # add the MathFunctions library + +Note the use of the variable ``EXTRA_LIBS`` to collect up any optional +libraries to later be linked into the executable. The variable +``EXTRA_INCLUDES`` is used similarly for optional header files. This is a +classic approach when dealing with many optional components, we will cover +the modern approach in the next step. + +The corresponding changes to the source code are fairly straightforward. +First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we +need it: + +.. literalinclude:: Step3/tutorial.cxx + :language: c++ + :start-after: // should we include the MathFunctions header + :end-before: int main + +Then, in the same file, make ``USE_MYMATH`` control which square root +function is used: + +.. literalinclude:: Step3/tutorial.cxx + :language: c++ + :start-after: // which square root function should we use? + :end-before: std::cout << "The square root of + +Since the source code now requires ``USE_MYMATH`` we can add it to +``TutorialConfig.h.in`` with the following line: + +.. literalinclude:: Step3/TutorialConfig.h.in + :language: c + :lines: 4 + +**Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` +after the option for ``USE_MYMATH``? What would happen if we inverted the two? + +Run the :manual:`cmake ` executable or the +:manual:`cmake-gui ` to configure the project and then build it +with your chosen build tool. Then run the built Tutorial executable. + +Now let's update the value of ``USE_MYMATH``. The easiest way is to use the +:manual:`cmake-gui ` or :manual:`ccmake ` if you're +in the terminal. Or, alternatively, if you want to change the option from the +command-line, try: + +.. code-block:: console + + cmake ../Step2 -DUSE_MYMATH=OFF + +Rebuild and run the tutorial again. + +Which function gives better results, sqrt or mysqrt? diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst new file mode 100644 index 00000000000..3f85df3e158 --- /dev/null +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -0,0 +1,85 @@ +Step 4: Installing and Testing +============================== + +Now we can start adding install rules and testing support to our project. + +Install Rules +------------- + +The install rules are fairly simple: for MathFunctions we want to install the +library and header file and for the application we want to install the +executable and configured header. + +So to the end of ``MathFunctions/CMakeLists.txt`` we add: + +.. literalinclude:: Step5/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install rules + +And to the end of the top-level ``CMakeLists.txt`` we add: + +.. literalinclude:: Step5/CMakeLists.txt + :language: cmake + :start-after: # add the install targets + :end-before: # enable testing + +That is all that is needed to create a basic local install of the tutorial. + +Now run the :manual:`cmake ` executable or the +:manual:`cmake-gui ` to configure the project and then build it +with your chosen build tool. + +Then run the install step by using the ``install`` option of the +:manual:`cmake ` command (introduced in 3.15, older versions of +CMake must use ``make install``) from the command line. For +multi-configuration tools, don't forget to use the ``--config`` argument to +specify the configuration. If using an IDE, simply build the ``INSTALL`` +target. This step will install the appropriate header files, libraries, and +executables. For example: + +.. code-block:: console + + cmake --install . + +The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the +root of where the files will be installed. If using the ``cmake --install`` +command, the installation prefix can be overridden via the ``--prefix`` +argument. For example: + +.. code-block:: console + + cmake --install . --prefix "/home/myuser/installdir" + +Navigate to the install directory and verify that the installed Tutorial runs. + +Testing Support +--------------- + +Next let's test our application. At the end of the top-level ``CMakeLists.txt`` +file we can enable testing and then add a number of basic tests to verify that +the application is working correctly. + +.. literalinclude:: Step5/CMakeLists.txt + :language: cmake + :start-after: # enable testing + +The first test simply verifies that the application runs, does not segfault or +otherwise crash, and has a zero return value. This is the basic form of a +CTest test. + +The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test +property to verify that the output of the test contains certain strings. In +this case, verifying that the usage message is printed when an incorrect number +of arguments are provided. + +Lastly, we have a function called ``do_test`` that runs the application and +verifies that the computed square root is correct for given input. For each +invocation of ``do_test``, another test is added to the project with a name, +input, and expected results based on the passed arguments. + +Rebuild the application and then cd to the binary directory and run the +:manual:`ctest ` executable: ``ctest -N`` and ``ctest -VV``. For +multi-config generators (e.g. Visual Studio), the configuration type must be +specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV`` +from the build directory (not the Debug subdirectory!). Alternatively, build +the ``RUN_TESTS`` target from the IDE. diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst new file mode 100644 index 00000000000..b73378c16f5 --- /dev/null +++ b/Help/guide/tutorial/Packaging Debug and Release.rst @@ -0,0 +1,78 @@ +Step 12: Packaging Debug and Release +==================================== + +**Note:** This example is valid for single-configuration generators and will +not work for multi-configuration generators (e.g. Visual Studio). + +By default, CMake's model is that a build directory only contains a single +configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is +possible, however, to setup CPack to bundle multiple build directories and +construct a package that contains multiple configurations of the same project. + +First, we want to ensure that the debug and release builds use different names +for the executables and libraries that will be installed. Let's use `d` as the +postfix for the debug executable and libraries. + +Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level +``CMakeLists.txt`` file: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: project(Tutorial VERSION 1.0) + :end-before: target_compile_features(tutorial_compiler_flags + +And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: # add the executable + :end-before: # add the binary tree to the search path for include files + +Let's also add version numbering to the MathFunctions library. In +``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and +:prop_tgt:`SOVERSION` properties: + +.. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # setup the version numbering + :end-before: # install rules + +From the ``Step12`` directory, create ``debug`` and ``release`` +subbdirectories. The layout will look like: + +.. code-block:: none + + - Step12 + - debug + - release + +Now we need to setup debug and release builds. We can use +:variable:`CMAKE_BUILD_TYPE` to set the configuration type: + +.. code-block:: console + + cd debug + cmake -DCMAKE_BUILD_TYPE=Debug .. + cmake --build . + cd ../release + cmake -DCMAKE_BUILD_TYPE=Release .. + cmake --build . + +Now that both the debug and release builds are complete, we can use a custom +configuration file to package both builds into a single release. In the +``Step12`` directory, create a file called ``MultiCPackConfig.cmake``. In this +file, first include the default configuration file that was created by the +:manual:`cmake ` executable. + +Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which +projects to install. In this case, we want to install both debug and release. + +.. literalinclude:: Complete/MultiCPackConfig.cmake + :language: cmake + +From the ``Step12`` directory, run :manual:`cpack ` specifying our +custom configuration file with the ``config`` option: + +.. code-block:: console + + cpack --config MultiCPackConfig.cmake diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst new file mode 100644 index 00000000000..037ae866997 --- /dev/null +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -0,0 +1,55 @@ +Step 7: Packaging an Installer +============================== + +Next suppose that we want to distribute our project to other people so that +they can use it. We want to provide both binary and source distributions on a +variety of platforms. This is a little different from the install we did +previously in `Installing and Testing (Step 4)`_ , where we were +installing the binaries that we had built from the source code. In this +example we will be building installation packages that support binary +installations and package management features. To accomplish this we will use +CPack to create platform specific installers. Specifically we need to add a +few lines to the bottom of our top-level ``CMakeLists.txt`` file. + +.. literalinclude:: Step8/CMakeLists.txt + :language: cmake + :start-after: # setup installer + +That is all there is to it. We start by including +:module:`InstallRequiredSystemLibraries`. This module will include any runtime +libraries that are needed by the project for the current platform. Next we set +some CPack variables to where we have stored the license and version +information for this project. The version information was set earlier in this +tutorial and the ``license.txt`` has been included in the top-level source +directory for this step. + +Finally we include the :module:`CPack module ` which will use these +variables and some other properties of the current system to setup an +installer. + +The next step is to build the project in the usual manner and then run the +:manual:`cpack ` executable. To build a binary distribution, from the +binary directory run: + +.. code-block:: console + + cpack + +To specify the generator, use the ``-G`` option. For multi-config builds, use +``-C`` to specify the configuration. For example: + +.. code-block:: console + + cpack -G ZIP -C Debug + +To create a source distribution you would type: + +.. code-block:: console + + cpack --config CPackSourceConfig.cmake + +Alternatively, run ``make package`` or right click the ``Package`` target and +``Build Project`` from an IDE. + +Run the installer found in the binary directory. Then run the installed +executable and verify that it works. diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst new file mode 100644 index 00000000000..c9b5e319e0d --- /dev/null +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -0,0 +1,66 @@ +Step 9: Selecting Static or Shared Libraries +============================================ + +In this section we will show how the :variable:`BUILD_SHARED_LIBS` variable can +be used to control the default behavior of :command:`add_library`, +and allow control over how libraries without an explicit type (``STATIC``, +``SHARED``, ``MODULE`` or ``OBJECT``) are built. + +To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the +top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows +users to optionally select if the value should be ON or OFF. + +Next we are going to refactor MathFunctions to become a real library that +encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling +code to do this logic. This will also mean that ``USE_MYMATH`` will not control +building MathFunctions, but instead will control the behavior of this library. + +The first step is to update the starting section of the top-level +``CMakeLists.txt`` to look like: + +.. literalinclude:: Step10/CMakeLists.txt + :language: cmake + :end-before: # add the binary tree + +Now that we have made MathFunctions always be used, we will need to update +the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to +create a SqrtLibrary that will conditionally be built and installed when +``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to +explicitly require that SqrtLibrary is built statically. + +The end result is that ``MathFunctions/CMakeLists.txt`` should look like: + +.. literalinclude:: Step10/MathFunctions/CMakeLists.txt + :language: cmake + :lines: 1-36,42- + +Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and +``detail`` namespaces: + +.. literalinclude:: Step10/MathFunctions/mysqrt.cxx + :language: c++ + +We also need to make some changes in ``tutorial.cxx``, so that it no longer +uses ``USE_MYMATH``: + +#. Always include ``MathFunctions.h`` +#. Always use ``mathfunctions::sqrt`` +#. Don't include cmath + +Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: + +.. literalinclude:: Step10/MathFunctions/MathFunctions.h + :language: c++ + +At this point, if you build everything, you may notice that linking fails +as we are combining a static library without position independent code with a +library that has position independent code. The solution to this is to +explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of +SqrtLibrary to be True no matter the build type. + +.. literalinclude:: Step10/MathFunctions/CMakeLists.txt + :language: cmake + :lines: 37-42 + +**Exercise**: We modified ``MathFunctions.h`` to use dll export defines. +Using CMake documentation can you find a helper module to simplify this? diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 7cdd844d06a..8a765fdebb0 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -1,10 +1,6 @@ CMake Tutorial ************** -.. only:: html - - .. contents:: - Introduction ============ @@ -12,936 +8,27 @@ The CMake tutorial provides a step-by-step guide that covers common build system issues that CMake helps address. Seeing how various topics all work together in an example project can be very helpful. +Steps +===== + The tutorial documentation and source code for examples can be found in the ``Help/guide/tutorial`` directory of the CMake source code tree. Each step has its own subdirectory containing code that may be used as a starting point. The tutorial examples are progressive so that each step provides the complete solution for the previous step. -A Basic Starting Point (Step 1) -=============================== - -The most basic project is an executable built from source code files. -For simple projects, a three line ``CMakeLists.txt`` file is all that is -required. This will be the starting point for our tutorial. Create a -``CMakeLists.txt`` file in the ``Step1`` directory that looks like: - -.. code-block:: cmake - - cmake_minimum_required(VERSION 3.10) - - # set the project name - project(Tutorial) - - # add the executable - add_executable(Tutorial tutorial.cxx) - - -Note that this example uses lower case commands in the ``CMakeLists.txt`` file. -Upper, lower, and mixed case commands are supported by CMake. The source -code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be -used to compute the square root of a number. - -Adding a Version Number and Configured Header File --------------------------------------------------- - -The first feature we will add is to provide our executable and project with a -version number. While we could do this exclusively in the source code, using -``CMakeLists.txt`` provides more flexibility. - -First, modify the ``CMakeLists.txt`` file to use the :command:`project` command -to set the project name and version number. - -.. literalinclude:: Step2/CMakeLists.txt - :language: cmake - :end-before: # specify the C++ standard - -Then, configure a header file to pass the version number to the source -code: - -.. literalinclude:: Step2/CMakeLists.txt - :language: cmake - :start-after: # to the source code - :end-before: # add the executable - -Since the configured file will be written into the binary tree, we -must add that directory to the list of paths to search for include -files. Add the following lines to the end of the ``CMakeLists.txt`` file: - -.. literalinclude:: Step2/CMakeLists.txt - :language: cmake - :start-after: # so that we will find TutorialConfig.h - -Using your favorite editor, create ``TutorialConfig.h.in`` in the source -directory with the following contents: - -.. literalinclude:: Step2/TutorialConfig.h.in - :language: cmake - -When CMake configures this header file the values for -``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be -replaced. - -Next modify ``tutorial.cxx`` to include the configured header file, -``TutorialConfig.h``. - -Finally, let's print out the executable name and version number by updating -``tutorial.cxx`` as follows: - -.. literalinclude:: Step2/tutorial.cxx - :language: c++ - :start-after: { - :end-before: // convert input to double - -Specify the C++ Standard -------------------------- - -Next let's add some C++11 features to our project by replacing ``atof`` with -``std::stod`` in ``tutorial.cxx``. At the same time, remove -``#include ``. - -.. literalinclude:: Step2/tutorial.cxx - :language: c++ - :start-after: // convert input to double - :end-before: // calculate square root - -We will need to explicitly state in the CMake code that it should use the -correct flags. The easiest way to enable support for a specific C++ standard -in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this -tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the -``CMakeLists.txt`` file to 11 and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to -True. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the call -to ``add_executable``. - -.. literalinclude:: Step2/CMakeLists.txt - :language: cmake - :end-before: # configure a header file to pass some of the CMake settings - -Build and Test --------------- - -Run the :manual:`cmake ` executable or the -:manual:`cmake-gui ` to configure the project and then build it -with your chosen build tool. - -For example, from the command line we could navigate to the -``Help/guide/tutorial`` directory of the CMake source code tree and create a -build directory: - -.. code-block:: console - - mkdir Step1_build - -Next, navigate to the build directory and run CMake to configure the project -and generate a native build system: - -.. code-block:: console - - cd Step1_build - cmake ../Step1 - -Then call that build system to actually compile/link the project: - -.. code-block:: console - - cmake --build . - -Finally, try to use the newly built ``Tutorial`` with these commands: - -.. code-block:: console - - Tutorial 4294967296 - Tutorial 10 - Tutorial - -Adding a Library (Step 2) -========================= - -Now we will add a library to our project. This library will contain our own -implementation for computing the square root of a number. The executable can -then use this library instead of the standard square root function provided by -the compiler. - -For this tutorial we will put the library into a subdirectory -called ``MathFunctions``. This directory already contains a header file, -``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one -function called ``mysqrt`` that provides similar functionality to the -compiler's ``sqrt`` function. - -Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions`` -directory: - -.. literalinclude:: Step3/MathFunctions/CMakeLists.txt - :language: cmake - -To make use of the new library we will add an :command:`add_subdirectory` -call in the top-level ``CMakeLists.txt`` file so that the library will get -built. We add the new library to the executable, and add ``MathFunctions`` as -an include directory so that the ``mysqrt.h`` header file can be found. The -last few lines of the top-level ``CMakeLists.txt`` file should now look like: - -.. code-block:: cmake - - # add the MathFunctions library - add_subdirectory(MathFunctions) - - # add the executable - add_executable(Tutorial tutorial.cxx) - - target_link_libraries(Tutorial PUBLIC MathFunctions) - - # add the binary tree to the search path for include files - # so that we will find TutorialConfig.h - target_include_directories(Tutorial PUBLIC - "${PROJECT_BINARY_DIR}" - "${PROJECT_SOURCE_DIR}/MathFunctions" - ) - -Now let us make the MathFunctions library optional. While for the tutorial -there really isn't any need to do so, for larger projects this is a common -occurrence. The first step is to add an option to the top-level -``CMakeLists.txt`` file. - -.. literalinclude:: Step3/CMakeLists.txt - :language: cmake - :start-after: # should we use our own math functions - :end-before: # add the MathFunctions library - -This option will be displayed in the :manual:`cmake-gui ` and -:manual:`ccmake ` -with a default value of ON that can be changed by the user. This setting will -be stored in the cache so that the user does not need to set the value each -time they run CMake on a build directory. - -The next change is to make building and linking the MathFunctions library -conditional. To do this we change the end of the top-level ``CMakeLists.txt`` -file to look like the following: - -.. literalinclude:: Step3/CMakeLists.txt - :language: cmake - :start-after: # add the MathFunctions library - -Note the use of the variable ``EXTRA_LIBS`` to collect up any optional -libraries to later be linked into the executable. The variable -``EXTRA_INCLUDES`` is used similarly for optional header files. This is a -classic approach when dealing with many optional components, we will cover -the modern approach in the next step. - -The corresponding changes to the source code are fairly straightforward. -First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we -need it: - -.. literalinclude:: Step3/tutorial.cxx - :language: c++ - :start-after: // should we include the MathFunctions header - :end-before: int main - -Then, in the same file, make ``USE_MYMATH`` control which square root -function is used: - -.. literalinclude:: Step3/tutorial.cxx - :language: c++ - :start-after: // which square root function should we use? - :end-before: std::cout << "The square root of - -Since the source code now requires ``USE_MYMATH`` we can add it to -``TutorialConfig.h.in`` with the following line: - -.. literalinclude:: Step3/TutorialConfig.h.in - :language: c - :lines: 4 - -**Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` -after the option for ``USE_MYMATH``? What would happen if we inverted the two? - -Run the :manual:`cmake ` executable or the -:manual:`cmake-gui ` to configure the project and then build it -with your chosen build tool. Then run the built Tutorial executable. - -Now let's update the value of ``USE_MYMATH``. The easiest way is to use the -:manual:`cmake-gui ` or :manual:`ccmake ` if you're -in the terminal. Or, alternatively, if you want to change the option from the -command-line, try: - -.. code-block:: console - - cmake ../Step2 -DUSE_MYMATH=OFF - -Rebuild and run the tutorial again. - -Which function gives better results, sqrt or mysqrt? - -Adding Usage Requirements for Library (Step 3) -============================================== - -Usage requirements allow for far better control over a library or executable's -link and include line while also giving more control over the transitive -property of targets inside CMake. The primary commands that leverage usage -requirements are: - - - :command:`target_compile_definitions` - - :command:`target_compile_options` - - :command:`target_include_directories` - - :command:`target_link_libraries` - -Let's refactor our code from `Adding a Library (Step 2)`_ to use the modern -CMake approach of usage requirements. We first state that anybody linking to -MathFunctions needs to include the current source directory, while -MathFunctions itself doesn't. So this can become an ``INTERFACE`` usage -requirement. - -Remember ``INTERFACE`` means things that consumers require but the producer -doesn't. Add the following lines to the end of -``MathFunctions/CMakeLists.txt``: - -.. literalinclude:: Step4/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # to find MathFunctions.h - -Now that we've specified usage requirements for MathFunctions we can safely -remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level -``CMakeLists.txt``, here: - -.. literalinclude:: Step4/CMakeLists.txt - :language: cmake - :start-after: # add the MathFunctions library - :end-before: # add the executable - -And here: - -.. literalinclude:: Step4/CMakeLists.txt - :language: cmake - :start-after: # so that we will find TutorialConfig.h - -Once this is done, run the :manual:`cmake ` executable or the -:manual:`cmake-gui ` to configure the project and then build it -with your chosen build tool or by using ``cmake --build .`` from the build -directory. - -Installing and Testing (Step 4) -=============================== - -Now we can start adding install rules and testing support to our project. - -Install Rules -------------- - -The install rules are fairly simple: for MathFunctions we want to install the -library and header file and for the application we want to install the -executable and configured header. - -So to the end of ``MathFunctions/CMakeLists.txt`` we add: - -.. literalinclude:: Step5/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # install rules - -And to the end of the top-level ``CMakeLists.txt`` we add: - -.. literalinclude:: Step5/CMakeLists.txt - :language: cmake - :start-after: # add the install targets - :end-before: # enable testing - -That is all that is needed to create a basic local install of the tutorial. - -Now run the :manual:`cmake ` executable or the -:manual:`cmake-gui ` to configure the project and then build it -with your chosen build tool. - -Then run the install step by using the ``install`` option of the -:manual:`cmake ` command (introduced in 3.15, older versions of -CMake must use ``make install``) from the command line. For -multi-configuration tools, don't forget to use the ``--config`` argument to -specify the configuration. If using an IDE, simply build the ``INSTALL`` -target. This step will install the appropriate header files, libraries, and -executables. For example: - -.. code-block:: console - - cmake --install . - -The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the -root of where the files will be installed. If using the ``cmake --install`` -command, the installation prefix can be overridden via the ``--prefix`` -argument. For example: - -.. code-block:: console - - cmake --install . --prefix "/home/myuser/installdir" - -Navigate to the install directory and verify that the installed Tutorial runs. - -Testing Support ---------------- - -Next let's test our application. At the end of the top-level ``CMakeLists.txt`` -file we can enable testing and then add a number of basic tests to verify that -the application is working correctly. - -.. literalinclude:: Step5/CMakeLists.txt - :language: cmake - :start-after: # enable testing - -The first test simply verifies that the application runs, does not segfault or -otherwise crash, and has a zero return value. This is the basic form of a -CTest test. - -The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test -property to verify that the output of the test contains certain strings. In -this case, verifying that the usage message is printed when an incorrect number -of arguments are provided. - -Lastly, we have a function called ``do_test`` that runs the application and -verifies that the computed square root is correct for given input. For each -invocation of ``do_test``, another test is added to the project with a name, -input, and expected results based on the passed arguments. - -Rebuild the application and then cd to the binary directory and run the -:manual:`ctest ` executable: ``ctest -N`` and ``ctest -VV``. For -multi-config generators (e.g. Visual Studio), the configuration type must be -specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV`` -from the build directory (not the Debug subdirectory!). Alternatively, build -the ``RUN_TESTS`` target from the IDE. - -Adding System Introspection (Step 5) -==================================== - -Let us consider adding some code to our project that depends on features the -target platform may not have. For this example, we will add some code that -depends on whether or not the target platform has the ``log`` and ``exp`` -functions. Of course almost every platform has these functions but for this -tutorial assume that they are not common. - -If the platform has ``log`` and ``exp`` then we will use them to compute the -square root in the ``mysqrt`` function. We first test for the availability of -these functions using the :module:`CheckSymbolExists` module in -``MathFunctions/CMakeLists.txt``. On some platforms, we will need to link to -the m library. If ``log`` and ``exp`` are not initially found, require the m -library and try again. - -.. literalinclude:: Step6/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # does this system provide the log and exp functions? - :end-before: # add compile definitions - -If available, use :command:`target_compile_definitions` to specify -``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions. - -.. literalinclude:: Step6/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # add compile definitions - :end-before: # install rules - -If ``log`` and ``exp`` are available on the system, then we will use them to -compute the square root in the ``mysqrt`` function. Add the following code to -the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the -``#endif`` before returning the result!): - -.. literalinclude:: Step6/MathFunctions/mysqrt.cxx - :language: c++ - :start-after: // if we have both log and exp then use them - :end-before: // do ten iterations - -We will also need to modify ``mysqrt.cxx`` to include ``cmath``. - -.. literalinclude:: Step6/MathFunctions/mysqrt.cxx - :language: c++ - :end-before: #include - -Run the :manual:`cmake ` executable or the -:manual:`cmake-gui ` to configure the project and then build it -with your chosen build tool and run the Tutorial executable. - -Which function gives better results now, sqrt or mysqrt? - -Adding a Custom Command and Generated File (Step 6) -=================================================== - -Suppose, for the purpose of this tutorial, we decide that we never want to use -the platform ``log`` and ``exp`` functions and instead would like to -generate a table of precomputed values to use in the ``mysqrt`` function. -In this section, we will create the table as part of the build process, -and then compile that table into our application. - -First, let's remove the check for the ``log`` and ``exp`` functions in -``MathFunctions/CMakeLists.txt``. Then remove the check for ``HAVE_LOG`` and -``HAVE_EXP`` from ``mysqrt.cxx``. At the same time, we can remove -:code:`#include `. - -In the ``MathFunctions`` subdirectory, a new source file named -``MakeTable.cxx`` has been provided to generate the table. - -After reviewing the file, we can see that the table is produced as valid C++ -code and that the output filename is passed in as an argument. - -The next step is to add the appropriate commands to the -``MathFunctions/CMakeLists.txt`` file to build the MakeTable executable and -then run it as part of the build process. A few commands are needed to -accomplish this. - -First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for -``MakeTable`` is added as any other executable would be added. - -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # first we add the executable that generates the table - :end-before: # add the command to generate the source code - -Then we add a custom command that specifies how to produce ``Table.h`` -by running MakeTable. - -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # add the command to generate the source code - :end-before: # add the main library - -Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated -file ``Table.h``. This is done by adding the generated ``Table.h`` to the list -of sources for the library MathFunctions. - -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # add the main library - :end-before: # state that anybody linking - -We also have to add the current binary directory to the list of include -directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. - -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # state that we depend on our bin - :end-before: # install rules - -Now let's use the generated table. First, modify ``mysqrt.cxx`` to include -``Table.h``. Next, we can rewrite the mysqrt function to use the table: - -.. literalinclude:: Step7/MathFunctions/mysqrt.cxx - :language: c++ - :start-after: // a hack square root calculation using simple operations - -Run the :manual:`cmake ` executable or the -:manual:`cmake-gui ` to configure the project and then build it -with your chosen build tool. - -When this project is built it will first build the ``MakeTable`` executable. -It will then run ``MakeTable`` to produce ``Table.h``. Finally, it will -compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the MathFunctions -library. - -Run the Tutorial executable and verify that it is using the table. - -Building an Installer (Step 7) -============================== - -Next suppose that we want to distribute our project to other people so that -they can use it. We want to provide both binary and source distributions on a -variety of platforms. This is a little different from the install we did -previously in `Installing and Testing (Step 4)`_ , where we were -installing the binaries that we had built from the source code. In this -example we will be building installation packages that support binary -installations and package management features. To accomplish this we will use -CPack to create platform specific installers. Specifically we need to add a -few lines to the bottom of our top-level ``CMakeLists.txt`` file. - -.. literalinclude:: Step8/CMakeLists.txt - :language: cmake - :start-after: # setup installer - -That is all there is to it. We start by including -:module:`InstallRequiredSystemLibraries`. This module will include any runtime -libraries that are needed by the project for the current platform. Next we set -some CPack variables to where we have stored the license and version -information for this project. The version information was set earlier in this -tutorial and the ``license.txt`` has been included in the top-level source -directory for this step. - -Finally we include the :module:`CPack module ` which will use these -variables and some other properties of the current system to setup an -installer. - -The next step is to build the project in the usual manner and then run the -:manual:`cpack ` executable. To build a binary distribution, from the -binary directory run: - -.. code-block:: console - - cpack - -To specify the generator, use the ``-G`` option. For multi-config builds, use -``-C`` to specify the configuration. For example: - -.. code-block:: console - - cpack -G ZIP -C Debug - -To create a source distribution you would type: - -.. code-block:: console - - cpack --config CPackSourceConfig.cmake - -Alternatively, run ``make package`` or right click the ``Package`` target and -``Build Project`` from an IDE. - -Run the installer found in the binary directory. Then run the installed -executable and verify that it works. - -Adding Support for a Dashboard (Step 8) -======================================= - -Adding support for submitting our test results to a dashboard is simple. We -already defined a number of tests for our project in `Testing Support`_. Now we -just have to run those tests and submit them to a dashboard. To include support -for dashboards we include the :module:`CTest` module in our top-level -``CMakeLists.txt``. - -Replace: - -.. code-block:: cmake - - # enable testing - enable_testing() - -With: - -.. code-block:: cmake - - # enable dashboard scripting - include(CTest) - -The :module:`CTest` module will automatically call ``enable_testing()``, so we -can remove it from our CMake files. - -We will also need to create a ``CTestConfig.cmake`` file in the top-level -directory where we can specify the name of the project and where to submit the -dashboard. - -.. literalinclude:: Step9/CTestConfig.cmake - :language: cmake - -The :manual:`ctest ` executable will read in this file when it runs. -To create a simple dashboard you can run the :manual:`cmake ` -executable or the :manual:`cmake-gui ` to configure the project, -but do not build it yet. Instead, change directory to the binary tree, and then -run: - - ctest [-VV] -D Experimental - -Remember, for multi-config generators (e.g. Visual Studio), the configuration -type must be specified:: - - ctest [-VV] -C Debug -D Experimental - -Or, from an IDE, build the ``Experimental`` target. - -The :manual:`ctest ` executable will build and test the project and -submit the results to Kitware's public dashboard: -https://my.cdash.org/index.php?project=CMakeTutorial. - -Mixing Static and Shared (Step 9) -================================= - -In this section we will show how the :variable:`BUILD_SHARED_LIBS` variable can -be used to control the default behavior of :command:`add_library`, -and allow control over how libraries without an explicit type (``STATIC``, -``SHARED``, ``MODULE`` or ``OBJECT``) are built. - -To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the -top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows -users to optionally select if the value should be ON or OFF. - -Next we are going to refactor MathFunctions to become a real library that -encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling -code to do this logic. This will also mean that ``USE_MYMATH`` will not control -building MathFunctions, but instead will control the behavior of this library. - -The first step is to update the starting section of the top-level -``CMakeLists.txt`` to look like: - -.. literalinclude:: Step10/CMakeLists.txt - :language: cmake - :end-before: # add the binary tree - -Now that we have made MathFunctions always be used, we will need to update -the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to -create a SqrtLibrary that will conditionally be built and installed when -``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to -explicitly require that SqrtLibrary is built statically. - -The end result is that ``MathFunctions/CMakeLists.txt`` should look like: - -.. literalinclude:: Step10/MathFunctions/CMakeLists.txt - :language: cmake - :lines: 1-36,42- - -Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and -``detail`` namespaces: - -.. literalinclude:: Step10/MathFunctions/mysqrt.cxx - :language: c++ - -We also need to make some changes in ``tutorial.cxx``, so that it no longer -uses ``USE_MYMATH``: - -#. Always include ``MathFunctions.h`` -#. Always use ``mathfunctions::sqrt`` -#. Don't include cmath - -Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: - -.. literalinclude:: Step10/MathFunctions/MathFunctions.h - :language: c++ - -At this point, if you build everything, you may notice that linking fails -as we are combining a static library without position independent code with a -library that has position independent code. The solution to this is to -explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of -SqrtLibrary to be True no matter the build type. - -.. literalinclude:: Step10/MathFunctions/CMakeLists.txt - :language: cmake - :lines: 37-42 - -**Exercise**: We modified ``MathFunctions.h`` to use dll export defines. -Using CMake documentation can you find a helper module to simplify this? - - -Adding Generator Expressions (Step 10) -====================================== - -:manual:`Generator expressions ` are evaluated -during build system generation to produce information specific to each build -configuration. - -:manual:`Generator expressions ` are allowed in -the context of many target properties, such as :prop_tgt:`LINK_LIBRARIES`, -:prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and others. -They may also be used when using commands to populate those properties, such as -:command:`target_link_libraries`, :command:`target_include_directories`, -:command:`target_compile_definitions` and others. - -:manual:`Generator expressions ` may be used -to enable conditional linking, conditional definitions used when compiling, -conditional include directories and more. The conditions may be based on the -build configuration, target properties, platform information or any other -queryable information. - -There are different types of -:manual:`generator expressions ` including -Logical, Informational, and Output expressions. - -Logical expressions are used to create conditional output. The basic -expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty -string, and ``<1:...>`` results in the content of "...". They can also be -nested. - -A common usage of -:manual:`generator expressions ` is to -conditionally add compiler flags, such as those for language levels or -warnings. A nice pattern is to associate this information to an ``INTERFACE`` -target allowing this information to propagate. Let's start by constructing an -``INTERFACE`` target and specifying the required C++ standard level of ``11`` -instead of using :variable:`CMAKE_CXX_STANDARD`. - -So the following code: - -.. literalinclude:: Step10/CMakeLists.txt - :language: cmake - :start-after: project(Tutorial VERSION 1.0) - :end-before: # control where the static and shared libraries are built so that on windows - -Would be replaced with: - -.. literalinclude:: Step11/CMakeLists.txt - :language: cmake - :start-after: project(Tutorial VERSION 1.0) - :end-before: # add compiler warning flags just when building this project via - - -Next we add the desired compiler warning flags that we want for our project. As -warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID`` -generator expression to control which flags to apply given a language and a set -of compiler ids as seen below: - -.. literalinclude:: Step11/CMakeLists.txt - :language: cmake - :start-after: # the BUILD_INTERFACE genex - :end-before: # control where the static and shared libraries are built so that on windows - -Looking at this we see that the warning flags are encapsulated inside a -``BUILD_INTERFACE`` condition. This is done so that consumers of our installed -project will not inherit our warning flags. - - -**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have -a :command:`target_link_libraries` call to ``tutorial_compiler_flags``. - - -Adding Export Configuration (Step 11) -===================================== - -During `Installing and Testing (Step 4)`_ of the tutorial we added the ability -for CMake to install the library and headers of the project. During -`Building an Installer (Step 7)`_ we added the ability to package up this -information so it could be distributed to other people. - -The next step is to add the necessary information so that other CMake projects -can use our project, be it from a build directory, a local install or when -packaged. - -The first step is to update our :command:`install(TARGETS)` commands to not -only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword -generates and installs a CMake file containing code to import all targets -listed in the install command from the installation tree. So let's go ahead and -explicitly ``EXPORT`` the MathFunctions library by updating the ``install`` -command in ``MathFunctions/CMakeLists.txt`` to look like: - -.. literalinclude:: Complete/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # install rules - -Now that we have MathFunctions being exported, we also need to explicitly -install the generated ``MathFunctionsTargets.cmake`` file. This is done by -adding the following to the bottom of the top-level ``CMakeLists.txt``: - -.. literalinclude:: Complete/CMakeLists.txt - :language: cmake - :start-after: # install the configuration targets - :end-before: include(CMakePackageConfigHelpers) - -At this point you should try and run CMake. If everything is setup properly -you will see that CMake will generate an error that looks like: - -.. code-block:: console - - Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains - path: - - "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions" - - which is prefixed in the source directory. - -What CMake is trying to say is that during generating the export information -it will export a path that is intrinsically tied to the current machine and -will not be valid on other machines. The solution to this is to update the -MathFunctions :command:`target_include_directories` to understand that it needs -different ``INTERFACE`` locations when being used from within the build -directory and from an install / package. This means converting the -:command:`target_include_directories` call for MathFunctions to look like: - -.. literalinclude:: Step12/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # to find MathFunctions.h, while we don't. - :end-before: # should we use our own math functions - -Once this has been updated, we can re-run CMake and verify that it doesn't -warn anymore. - -At this point, we have CMake properly packaging the target information that is -required but we will still need to generate a ``MathFunctionsConfig.cmake`` so -that the CMake :command:`find_package` command can find our project. So let's go -ahead and add a new file to the top-level of the project called -``Config.cmake.in`` with the following contents: - -.. literalinclude:: Step12/Config.cmake.in - -Then, to properly configure and install that file, add the following to the -bottom of the top-level ``CMakeLists.txt``: - -.. literalinclude:: Step12/CMakeLists.txt - :language: cmake - :start-after: # install the configuration targets - :end-before: # generate the export - -At this point, we have generated a relocatable CMake Configuration for our -project that can be used after the project has been installed or packaged. If -we want our project to also be used from a build directory we only have to add -the following to the bottom of the top level ``CMakeLists.txt``: - -.. literalinclude:: Step12/CMakeLists.txt - :language: cmake - :start-after: # needs to be after the install(TARGETS ) command - -With this export call we now generate a ``Targets.cmake``, allowing the -configured ``MathFunctionsConfig.cmake`` in the build directory to be used by -other projects, without needing it to be installed. - -Packaging Debug and Release (Step 12) -===================================== - -**Note:** This example is valid for single-configuration generators and will -not work for multi-configuration generators (e.g. Visual Studio). - -By default, CMake's model is that a build directory only contains a single -configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is -possible, however, to setup CPack to bundle multiple build directories and -construct a package that contains multiple configurations of the same project. - -First, we want to ensure that the debug and release builds use different names -for the executables and libraries that will be installed. Let's use `d` as the -postfix for the debug executable and libraries. - -Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level -``CMakeLists.txt`` file: - -.. literalinclude:: Complete/CMakeLists.txt - :language: cmake - :start-after: project(Tutorial VERSION 1.0) - :end-before: target_compile_features(tutorial_compiler_flags - -And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable: - -.. literalinclude:: Complete/CMakeLists.txt - :language: cmake - :start-after: # add the executable - :end-before: # add the binary tree to the search path for include files - -Let's also add version numbering to the MathFunctions library. In -``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and -:prop_tgt:`SOVERSION` properties: - -.. literalinclude:: Complete/MathFunctions/CMakeLists.txt - :language: cmake - :start-after: # setup the version numbering - :end-before: # install rules - -From the ``Step12`` directory, create ``debug`` and ``release`` -subbdirectories. The layout will look like: - -.. code-block:: none - - - Step12 - - debug - - release - -Now we need to setup debug and release builds. We can use -:variable:`CMAKE_BUILD_TYPE` to set the configuration type: - -.. code-block:: console - - cd debug - cmake -DCMAKE_BUILD_TYPE=Debug .. - cmake --build . - cd ../release - cmake -DCMAKE_BUILD_TYPE=Release .. - cmake --build . - -Now that both the debug and release builds are complete, we can use a custom -configuration file to package both builds into a single release. In the -``Step12`` directory, create a file called ``MultiCPackConfig.cmake``. In this -file, first include the default configuration file that was created by the -:manual:`cmake ` executable. - -Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which -projects to install. In this case, we want to install both debug and release. - -.. literalinclude:: Complete/MultiCPackConfig.cmake - :language: cmake - -From the ``Step12`` directory, run :manual:`cpack ` specifying our -custom configuration file with the ``config`` option: - -.. code-block:: console - - cpack --config MultiCPackConfig.cmake +.. toctree:: + :maxdepth: 2 + + A Basic Starting Point + Adding a Library + Adding Usage Requirements for a Library + Installing and Testing + Adding System Introspection + Adding a Custom Command and Generated File + Packaging an Installer + Adding Support for a Testing Dashboard + Selecting Static or Shared Libraries + Adding Generator Expressions + Adding Export Configuration + Packaging Debug and Release From 25dde20cc5df77326f369c2dbcca3edcf687e581 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 10 Jun 2021 23:16:18 +0200 Subject: [PATCH 0709/1519] Tutorial: Fix links after splitting steps --- Help/guide/tutorial/Adding Export Configuration.rst | 8 ++++---- .../Adding Support for a Testing Dashboard.rst | 8 ++++---- .../Adding Usage Requirements for a Library.rst | 10 +++++----- Help/guide/tutorial/Installing and Testing.rst | 2 ++ Help/guide/tutorial/Packaging an Installer.rst | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index 55cb3e29f8c..6c283a64a09 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -1,10 +1,10 @@ Step 11: Adding Export Configuration ==================================== -During `Installing and Testing (Step 4)`_ of the tutorial we added the ability -for CMake to install the library and headers of the project. During -`Building an Installer (Step 7)`_ we added the ability to package up this -information so it could be distributed to other people. +During :guide:`tutorial/Installing and Testing` of the tutorial we added the +ability for CMake to install the library and headers of the project. During +:guide:`tutorial/Packaging an Installer` we added the ability to package up +this information so it could be distributed to other people. The next step is to add the necessary information so that other CMake projects can use our project, be it from a build directory, a local install or when diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index 41b772c9db2..74d3f0f3650 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -2,10 +2,10 @@ Step 8: Adding Support for a Testing Dashboard ============================================== Adding support for submitting our test results to a dashboard is simple. We -already defined a number of tests for our project in `Testing Support`_. Now we -just have to run those tests and submit them to a dashboard. To include support -for dashboards we include the :module:`CTest` module in our top-level -``CMakeLists.txt``. +already defined a number of tests for our project in +:ref:`Testing Support `. Now we just have to run +those tests and submit them to a dashboard. To include support for dashboards +we include the :module:`CTest` module in our top-level ``CMakeLists.txt``. Replace: diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index a625d90480e..6146a5e3196 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -11,11 +11,11 @@ requirements are: - :command:`target_include_directories` - :command:`target_link_libraries` -Let's refactor our code from `Adding a Library (Step 2)`_ to use the modern -CMake approach of usage requirements. We first state that anybody linking to -MathFunctions needs to include the current source directory, while -MathFunctions itself doesn't. So this can become an ``INTERFACE`` usage -requirement. +Let's refactor our code from :guide:`tutorial/Adding a Library` to use the +modern CMake approach of usage requirements. We first state that anybody +linking to MathFunctions needs to include the current source directory, +while MathFunctions itself doesn't. So this can become an ``INTERFACE`` +usage requirement. Remember ``INTERFACE`` means things that consumers require but the producer doesn't. Add the following lines to the end of diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 3f85df3e158..611749b3ae6 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -52,6 +52,8 @@ argument. For example: Navigate to the install directory and verify that the installed Tutorial runs. +.. _`Tutorial Testing Support`: + Testing Support --------------- diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst index 037ae866997..cee1da44f40 100644 --- a/Help/guide/tutorial/Packaging an Installer.rst +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -4,7 +4,7 @@ Step 7: Packaging an Installer Next suppose that we want to distribute our project to other people so that they can use it. We want to provide both binary and source distributions on a variety of platforms. This is a little different from the install we did -previously in `Installing and Testing (Step 4)`_ , where we were +previously in :guide:`tutorial/Installing and Testing`, where we were installing the binaries that we had built from the source code. In this example we will be building installation packages that support binary installations and package management features. To accomplish this we will use From fe60154fe8efc7528da92f6b9a6b17a6f9d4a179 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Thu, 10 Jun 2021 23:42:39 +0200 Subject: [PATCH 0710/1519] Tutorial: Small formatting improvements - Use inline literals for all code fragments and names. - Add missing console code-blocks. - Always use c++, not c as code language. --- Help/guide/tutorial/A Basic Starting Point.rst | 8 ++++---- .../guide/tutorial/Adding Export Configuration.rst | 10 +++++----- .../tutorial/Adding Generator Expressions.rst | 7 +++---- .../Adding Support for a Testing Dashboard.rst | 6 +++++- .../guide/tutorial/Adding System Introspection.rst | 6 +++--- .../Adding Usage Requirements for a Library.rst | 6 +++--- .../Adding a Custom Command and Generated File.rst | 6 +++--- Help/guide/tutorial/Adding a Library.rst | 14 +++++++------- Help/guide/tutorial/Installing and Testing.rst | 4 ++-- .../guide/tutorial/Packaging Debug and Release.rst | 2 +- .../Selecting Static or Shared Libraries.rst | 13 +++++++------ 11 files changed, 43 insertions(+), 39 deletions(-) diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index 296b3c32ed1..e5f7b9121cd 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -56,7 +56,7 @@ Using your favorite editor, create ``TutorialConfig.h.in`` in the source directory with the following contents: .. literalinclude:: Step2/TutorialConfig.h.in - :language: cmake + :language: c++ When CMake configures this header file the values for ``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be @@ -89,9 +89,9 @@ We will need to explicitly state in the CMake code that it should use the correct flags. The easiest way to enable support for a specific C++ standard in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the -``CMakeLists.txt`` file to 11 and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to -True. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the call -to ``add_executable``. +``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` +to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the +call to ``add_executable``. .. literalinclude:: Step2/CMakeLists.txt :language: cmake diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index 6c283a64a09..b1d0f979d25 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -14,14 +14,14 @@ The first step is to update our :command:`install(TARGETS)` commands to not only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword generates and installs a CMake file containing code to import all targets listed in the install command from the installation tree. So let's go ahead and -explicitly ``EXPORT`` the MathFunctions library by updating the ``install`` +explicitly ``EXPORT`` the ``MathFunctions`` library by updating the ``install`` command in ``MathFunctions/CMakeLists.txt`` to look like: .. literalinclude:: Complete/MathFunctions/CMakeLists.txt :language: cmake :start-after: # install rules -Now that we have MathFunctions being exported, we also need to explicitly +Now that we have ``MathFunctions`` being exported, we also need to explicitly install the generated ``MathFunctionsTargets.cmake`` file. This is done by adding the following to the bottom of the top-level ``CMakeLists.txt``: @@ -45,10 +45,10 @@ you will see that CMake will generate an error that looks like: What CMake is trying to say is that during generating the export information it will export a path that is intrinsically tied to the current machine and will not be valid on other machines. The solution to this is to update the -MathFunctions :command:`target_include_directories` to understand that it needs -different ``INTERFACE`` locations when being used from within the build +``MathFunctions`` :command:`target_include_directories` to understand that it +needs different ``INTERFACE`` locations when being used from within the build directory and from an install / package. This means converting the -:command:`target_include_directories` call for MathFunctions to look like: +:command:`target_include_directories` call for ``MathFunctions`` to look like: .. literalinclude:: Step12/MathFunctions/CMakeLists.txt :language: cmake diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index 7a3abb135f3..f5a35f35c9b 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -23,9 +23,9 @@ There are different types of Logical, Informational, and Output expressions. Logical expressions are used to create conditional output. The basic -expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty -string, and ``<1:...>`` results in the content of "...". They can also be -nested. +expressions are the ``0`` and ``1`` expressions. A ``$<0:...>`` results in the +empty string, and ``<1:...>`` results in the content of ``...``. They can also +be nested. A common usage of :manual:`generator expressions ` is to @@ -64,6 +64,5 @@ Looking at this we see that the warning flags are encapsulated inside a ``BUILD_INTERFACE`` condition. This is done so that consumers of our installed project will not inherit our warning flags. - **Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have a :command:`target_link_libraries` call to ``tutorial_compiler_flags``. diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index 74d3f0f3650..775e8dd5d11 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -37,10 +37,14 @@ executable or the :manual:`cmake-gui ` to configure the project, but do not build it yet. Instead, change directory to the binary tree, and then run: +.. code-block:: console + ctest [-VV] -D Experimental Remember, for multi-config generators (e.g. Visual Studio), the configuration -type must be specified:: +type must be specified: + +.. code-block:: console ctest [-VV] -C Debug -D Experimental diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index 0ee360cf5f7..924f904f5ae 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -11,8 +11,8 @@ If the platform has ``log`` and ``exp`` then we will use them to compute the square root in the ``mysqrt`` function. We first test for the availability of these functions using the :module:`CheckSymbolExists` module in ``MathFunctions/CMakeLists.txt``. On some platforms, we will need to link to -the m library. If ``log`` and ``exp`` are not initially found, require the m -library and try again. +the ``m`` library. If ``log`` and ``exp`` are not initially found, require the +``m`` library and try again. .. literalinclude:: Step6/MathFunctions/CMakeLists.txt :language: cmake @@ -47,4 +47,4 @@ Run the :manual:`cmake ` executable or the :manual:`cmake-gui ` to configure the project and then build it with your chosen build tool and run the Tutorial executable. -Which function gives better results now, sqrt or mysqrt? +Which function gives better results now, ``sqrt`` or ``mysqrt``? diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index 6146a5e3196..ade75f0c2f1 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -13,8 +13,8 @@ requirements are: Let's refactor our code from :guide:`tutorial/Adding a Library` to use the modern CMake approach of usage requirements. We first state that anybody -linking to MathFunctions needs to include the current source directory, -while MathFunctions itself doesn't. So this can become an ``INTERFACE`` +linking to ``MathFunctions`` needs to include the current source directory, +while ``MathFunctions`` itself doesn't. So this can become an ``INTERFACE`` usage requirement. Remember ``INTERFACE`` means things that consumers require but the producer @@ -25,7 +25,7 @@ doesn't. Add the following lines to the end of :language: cmake :start-after: # to find MathFunctions.h -Now that we've specified usage requirements for MathFunctions we can safely +Now that we've specified usage requirements for ``MathFunctions`` we can safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level ``CMakeLists.txt``, here: diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst index 0e3e60cdb3a..499df994f3a 100644 --- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst +++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst @@ -57,7 +57,7 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. :end-before: # install rules Now let's use the generated table. First, modify ``mysqrt.cxx`` to include -``Table.h``. Next, we can rewrite the mysqrt function to use the table: +``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table: .. literalinclude:: Step7/MathFunctions/mysqrt.cxx :language: c++ @@ -69,7 +69,7 @@ with your chosen build tool. When this project is built it will first build the ``MakeTable`` executable. It will then run ``MakeTable`` to produce ``Table.h``. Finally, it will -compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the MathFunctions -library. +compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the +``MathFunctions`` library. Run the Tutorial executable and verify that it is using the table. diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index 3ff966cf5bd..4462aaaeb83 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -41,7 +41,7 @@ last few lines of the top-level ``CMakeLists.txt`` file should now look like: "${PROJECT_SOURCE_DIR}/MathFunctions" ) -Now let us make the MathFunctions library optional. While for the tutorial +Now let us make the ``MathFunctions`` library optional. While for the tutorial there really isn't any need to do so, for larger projects this is a common occurrence. The first step is to add an option to the top-level ``CMakeLists.txt`` file. @@ -53,11 +53,11 @@ occurrence. The first step is to add an option to the top-level This option will be displayed in the :manual:`cmake-gui ` and :manual:`ccmake ` -with a default value of ON that can be changed by the user. This setting will -be stored in the cache so that the user does not need to set the value each -time they run CMake on a build directory. +with a default value of ``ON`` that can be changed by the user. This setting +will be stored in the cache so that the user does not need to set the value +each time they run CMake on a build directory. -The next change is to make building and linking the MathFunctions library +The next change is to make building and linking the ``MathFunctions`` library conditional. To do this we change the end of the top-level ``CMakeLists.txt`` file to look like the following: @@ -92,7 +92,7 @@ Since the source code now requires ``USE_MYMATH`` we can add it to ``TutorialConfig.h.in`` with the following line: .. literalinclude:: Step3/TutorialConfig.h.in - :language: c + :language: c++ :lines: 4 **Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` @@ -113,4 +113,4 @@ command-line, try: Rebuild and run the tutorial again. -Which function gives better results, sqrt or mysqrt? +Which function gives better results, ``sqrt`` or ``mysqrt``? diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 611749b3ae6..8bab4540b10 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -6,8 +6,8 @@ Now we can start adding install rules and testing support to our project. Install Rules ------------- -The install rules are fairly simple: for MathFunctions we want to install the -library and header file and for the application we want to install the +The install rules are fairly simple: for ``MathFunctions`` we want to install +the library and header file and for the application we want to install the executable and configured header. So to the end of ``MathFunctions/CMakeLists.txt`` we add: diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst index b73378c16f5..1f9026870cf 100644 --- a/Help/guide/tutorial/Packaging Debug and Release.rst +++ b/Help/guide/tutorial/Packaging Debug and Release.rst @@ -28,7 +28,7 @@ And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable: :start-after: # add the executable :end-before: # add the binary tree to the search path for include files -Let's also add version numbering to the MathFunctions library. In +Let's also add version numbering to the ``MathFunctions`` library. In ``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and :prop_tgt:`SOVERSION` properties: diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst index c9b5e319e0d..4a7a86ae24e 100644 --- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -8,12 +8,13 @@ and allow control over how libraries without an explicit type (``STATIC``, To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows -users to optionally select if the value should be ON or OFF. +users to optionally select if the value should be ``ON`` or ``OFF``. -Next we are going to refactor MathFunctions to become a real library that +Next we are going to refactor ``MathFunctions`` to become a real library that encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling code to do this logic. This will also mean that ``USE_MYMATH`` will not control -building MathFunctions, but instead will control the behavior of this library. +building ``MathFunctions``, but instead will control the behavior of this +library. The first step is to update the starting section of the top-level ``CMakeLists.txt`` to look like: @@ -22,7 +23,7 @@ The first step is to update the starting section of the top-level :language: cmake :end-before: # add the binary tree -Now that we have made MathFunctions always be used, we will need to update +Now that we have made ``MathFunctions`` always be used, we will need to update the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to create a SqrtLibrary that will conditionally be built and installed when ``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to @@ -45,7 +46,7 @@ uses ``USE_MYMATH``: #. Always include ``MathFunctions.h`` #. Always use ``mathfunctions::sqrt`` -#. Don't include cmath +#. Don't include ``cmath`` Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: @@ -56,7 +57,7 @@ At this point, if you build everything, you may notice that linking fails as we are combining a static library without position independent code with a library that has position independent code. The solution to this is to explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of -SqrtLibrary to be True no matter the build type. +SqrtLibrary to be ``True`` no matter the build type. .. literalinclude:: Step10/MathFunctions/CMakeLists.txt :language: cmake From 9e5bbb69eaa21830e1e306e0705ba32213def064 Mon Sep 17 00:00:00 2001 From: Josef Angstenberger Date: Fri, 11 Jun 2021 00:20:58 +0200 Subject: [PATCH 0711/1519] Tutorial: Add captions for code blocks --- Help/guide/tutorial/A Basic Starting Point.rst | 8 ++++++++ Help/guide/tutorial/Adding Export Configuration.rst | 6 ++++++ Help/guide/tutorial/Adding Generator Expressions.rst | 3 +++ .../tutorial/Adding Support for a Testing Dashboard.rst | 3 +++ Help/guide/tutorial/Adding System Introspection.rst | 4 ++++ .../tutorial/Adding Usage Requirements for a Library.rst | 3 +++ .../Adding a Custom Command and Generated File.rst | 5 +++++ Help/guide/tutorial/Adding a Library.rst | 7 +++++++ Help/guide/tutorial/Installing and Testing.rst | 3 +++ Help/guide/tutorial/Packaging Debug and Release.rst | 4 ++++ Help/guide/tutorial/Packaging an Installer.rst | 1 + .../tutorial/Selecting Static or Shared Libraries.rst | 5 +++++ 12 files changed, 52 insertions(+) diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index e5f7b9121cd..20e4129376d 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -7,6 +7,7 @@ required. This will be the starting point for our tutorial. Create a ``CMakeLists.txt`` file in the ``Step1`` directory that looks like: .. code-block:: cmake + :caption: CMakeLists.txt cmake_minimum_required(VERSION 3.10) @@ -33,6 +34,7 @@ First, modify the ``CMakeLists.txt`` file to use the :command:`project` command to set the project name and version number. .. literalinclude:: Step2/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :end-before: # specify the C++ standard @@ -40,6 +42,7 @@ Then, configure a header file to pass the version number to the source code: .. literalinclude:: Step2/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # to the source code :end-before: # add the executable @@ -49,6 +52,7 @@ must add that directory to the list of paths to search for include files. Add the following lines to the end of the ``CMakeLists.txt`` file: .. literalinclude:: Step2/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # so that we will find TutorialConfig.h @@ -56,6 +60,7 @@ Using your favorite editor, create ``TutorialConfig.h.in`` in the source directory with the following contents: .. literalinclude:: Step2/TutorialConfig.h.in + :caption: TutorialConfig.h.in :language: c++ When CMake configures this header file the values for @@ -69,6 +74,7 @@ Finally, let's print out the executable name and version number by updating ``tutorial.cxx`` as follows: .. literalinclude:: Step2/tutorial.cxx + :caption: tutorial.cxx :language: c++ :start-after: { :end-before: // convert input to double @@ -81,6 +87,7 @@ Next let's add some C++11 features to our project by replacing ``atof`` with ``#include ``. .. literalinclude:: Step2/tutorial.cxx + :caption: tutorial.cxx :language: c++ :start-after: // convert input to double :end-before: // calculate square root @@ -94,6 +101,7 @@ to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the call to ``add_executable``. .. literalinclude:: Step2/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :end-before: # configure a header file to pass some of the CMake settings diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index b1d0f979d25..da0d877e9be 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -18,6 +18,7 @@ explicitly ``EXPORT`` the ``MathFunctions`` library by updating the ``install`` command in ``MathFunctions/CMakeLists.txt`` to look like: .. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # install rules @@ -26,6 +27,7 @@ install the generated ``MathFunctionsTargets.cmake`` file. This is done by adding the following to the bottom of the top-level ``CMakeLists.txt``: .. literalinclude:: Complete/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # install the configuration targets :end-before: include(CMakePackageConfigHelpers) @@ -51,6 +53,7 @@ directory and from an install / package. This means converting the :command:`target_include_directories` call for ``MathFunctions`` to look like: .. literalinclude:: Step12/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # to find MathFunctions.h, while we don't. :end-before: # should we use our own math functions @@ -65,11 +68,13 @@ ahead and add a new file to the top-level of the project called ``Config.cmake.in`` with the following contents: .. literalinclude:: Step12/Config.cmake.in + :caption: Config.cmake.in Then, to properly configure and install that file, add the following to the bottom of the top-level ``CMakeLists.txt``: .. literalinclude:: Step12/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # install the configuration targets :end-before: # generate the export @@ -80,6 +85,7 @@ we want our project to also be used from a build directory we only have to add the following to the bottom of the top level ``CMakeLists.txt``: .. literalinclude:: Step12/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # needs to be after the install(TARGETS ) command diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index f5a35f35c9b..b21fc62f1da 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -38,6 +38,7 @@ instead of using :variable:`CMAKE_CXX_STANDARD`. So the following code: .. literalinclude:: Step10/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: project(Tutorial VERSION 1.0) :end-before: # control where the static and shared libraries are built so that on windows @@ -45,6 +46,7 @@ So the following code: Would be replaced with: .. literalinclude:: Step11/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: project(Tutorial VERSION 1.0) :end-before: # add compiler warning flags just when building this project via @@ -56,6 +58,7 @@ generator expression to control which flags to apply given a language and a set of compiler ids as seen below: .. literalinclude:: Step11/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # the BUILD_INTERFACE genex :end-before: # control where the static and shared libraries are built so that on windows diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index 775e8dd5d11..9cdbb343b38 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -10,6 +10,7 @@ we include the :module:`CTest` module in our top-level ``CMakeLists.txt``. Replace: .. code-block:: cmake + :caption: CMakeLists.txt # enable testing enable_testing() @@ -17,6 +18,7 @@ Replace: With: .. code-block:: cmake + :caption: CMakeLists.txt # enable dashboard scripting include(CTest) @@ -29,6 +31,7 @@ directory where we can specify the name of the project and where to submit the dashboard. .. literalinclude:: Step9/CTestConfig.cmake + :caption: CTestConfig.cmake :language: cmake The :manual:`ctest ` executable will read in this file when it runs. diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index 924f904f5ae..c11f793fcb8 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -15,6 +15,7 @@ the ``m`` library. If ``log`` and ``exp`` are not initially found, require the ``m`` library and try again. .. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # does this system provide the log and exp functions? :end-before: # add compile definitions @@ -23,6 +24,7 @@ If available, use :command:`target_compile_definitions` to specify ``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions. .. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # add compile definitions :end-before: # install rules @@ -33,6 +35,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the ``#endif`` before returning the result!): .. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :caption: MathFunctions/mysqrt.cxx :language: c++ :start-after: // if we have both log and exp then use them :end-before: // do ten iterations @@ -40,6 +43,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the We will also need to modify ``mysqrt.cxx`` to include ``cmath``. .. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :caption: MathFunctions/mysqrt.cxx :language: c++ :end-before: #include diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index ade75f0c2f1..8ef9cc66079 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -22,6 +22,7 @@ doesn't. Add the following lines to the end of ``MathFunctions/CMakeLists.txt``: .. literalinclude:: Step4/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # to find MathFunctions.h @@ -30,6 +31,7 @@ remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level ``CMakeLists.txt``, here: .. literalinclude:: Step4/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # add the MathFunctions library :end-before: # add the executable @@ -37,6 +39,7 @@ remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level And here: .. literalinclude:: Step4/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst index 499df994f3a..c60379aaca5 100644 --- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst +++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst @@ -27,6 +27,7 @@ First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for ``MakeTable`` is added as any other executable would be added. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # first we add the executable that generates the table :end-before: # add the command to generate the source code @@ -35,6 +36,7 @@ Then we add a custom command that specifies how to produce ``Table.h`` by running MakeTable. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # add the command to generate the source code :end-before: # add the main library @@ -44,6 +46,7 @@ file ``Table.h``. This is done by adding the generated ``Table.h`` to the list of sources for the library MathFunctions. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # add the main library :end-before: # state that anybody linking @@ -52,6 +55,7 @@ We also have to add the current binary directory to the list of include directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # state that we depend on our bin :end-before: # install rules @@ -60,6 +64,7 @@ Now let's use the generated table. First, modify ``mysqrt.cxx`` to include ``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table: .. literalinclude:: Step7/MathFunctions/mysqrt.cxx + :caption: MathFunctions/mysqrt.cxx :language: c++ :start-after: // a hack square root calculation using simple operations diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index 4462aaaeb83..02f7ed13e8f 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -16,6 +16,7 @@ Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions`` directory: .. literalinclude:: Step3/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake To make use of the new library we will add an :command:`add_subdirectory` @@ -25,6 +26,7 @@ an include directory so that the ``mysqrt.h`` header file can be found. The last few lines of the top-level ``CMakeLists.txt`` file should now look like: .. code-block:: cmake + :caption: CMakeLists.txt # add the MathFunctions library add_subdirectory(MathFunctions) @@ -47,6 +49,7 @@ occurrence. The first step is to add an option to the top-level ``CMakeLists.txt`` file. .. literalinclude:: Step3/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # should we use our own math functions :end-before: # add the MathFunctions library @@ -62,6 +65,7 @@ conditional. To do this we change the end of the top-level ``CMakeLists.txt`` file to look like the following: .. literalinclude:: Step3/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # add the MathFunctions library @@ -76,6 +80,7 @@ First, in ``tutorial.cxx``, include the ``MathFunctions.h`` header if we need it: .. literalinclude:: Step3/tutorial.cxx + :caption: tutorial.cxx :language: c++ :start-after: // should we include the MathFunctions header :end-before: int main @@ -84,6 +89,7 @@ Then, in the same file, make ``USE_MYMATH`` control which square root function is used: .. literalinclude:: Step3/tutorial.cxx + :caption: tutorial.cxx :language: c++ :start-after: // which square root function should we use? :end-before: std::cout << "The square root of @@ -92,6 +98,7 @@ Since the source code now requires ``USE_MYMATH`` we can add it to ``TutorialConfig.h.in`` with the following line: .. literalinclude:: Step3/TutorialConfig.h.in + :caption: TutorialConfig.h.in :language: c++ :lines: 4 diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 8bab4540b10..53f03631a2c 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -13,12 +13,14 @@ executable and configured header. So to the end of ``MathFunctions/CMakeLists.txt`` we add: .. literalinclude:: Step5/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # install rules And to the end of the top-level ``CMakeLists.txt`` we add: .. literalinclude:: Step5/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # add the install targets :end-before: # enable testing @@ -62,6 +64,7 @@ file we can enable testing and then add a number of basic tests to verify that the application is working correctly. .. literalinclude:: Step5/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # enable testing diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst index 1f9026870cf..c2bf1b5641f 100644 --- a/Help/guide/tutorial/Packaging Debug and Release.rst +++ b/Help/guide/tutorial/Packaging Debug and Release.rst @@ -17,6 +17,7 @@ Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level ``CMakeLists.txt`` file: .. literalinclude:: Complete/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: project(Tutorial VERSION 1.0) :end-before: target_compile_features(tutorial_compiler_flags @@ -24,6 +25,7 @@ Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable: .. literalinclude:: Complete/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # add the executable :end-before: # add the binary tree to the search path for include files @@ -33,6 +35,7 @@ Let's also add version numbering to the ``MathFunctions`` library. In :prop_tgt:`SOVERSION` properties: .. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :start-after: # setup the version numbering :end-before: # install rules @@ -68,6 +71,7 @@ Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which projects to install. In this case, we want to install both debug and release. .. literalinclude:: Complete/MultiCPackConfig.cmake + :caption: MultiCPackConfig.cmake :language: cmake From the ``Step12`` directory, run :manual:`cpack ` specifying our diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst index cee1da44f40..f3a5e12d5db 100644 --- a/Help/guide/tutorial/Packaging an Installer.rst +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -12,6 +12,7 @@ CPack to create platform specific installers. Specifically we need to add a few lines to the bottom of our top-level ``CMakeLists.txt`` file. .. literalinclude:: Step8/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :start-after: # setup installer diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst index 4a7a86ae24e..85dcbf56fca 100644 --- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -20,6 +20,7 @@ The first step is to update the starting section of the top-level ``CMakeLists.txt`` to look like: .. literalinclude:: Step10/CMakeLists.txt + :caption: CMakeLists.txt :language: cmake :end-before: # add the binary tree @@ -32,6 +33,7 @@ explicitly require that SqrtLibrary is built statically. The end result is that ``MathFunctions/CMakeLists.txt`` should look like: .. literalinclude:: Step10/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :lines: 1-36,42- @@ -39,6 +41,7 @@ Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and ``detail`` namespaces: .. literalinclude:: Step10/MathFunctions/mysqrt.cxx + :caption: MathFunctions/mysqrt.cxx :language: c++ We also need to make some changes in ``tutorial.cxx``, so that it no longer @@ -51,6 +54,7 @@ uses ``USE_MYMATH``: Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: .. literalinclude:: Step10/MathFunctions/MathFunctions.h + :caption: MathFunctions/MathFunctions.h :language: c++ At this point, if you build everything, you may notice that linking fails @@ -60,6 +64,7 @@ explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of SqrtLibrary to be ``True`` no matter the build type. .. literalinclude:: Step10/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt :language: cmake :lines: 37-42 From 9c703ff7412c2f5ba3992674c3ed73e21d9d014b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 12:10:14 -0400 Subject: [PATCH 0712/1519] Tutorial: Add infrastructure to preserve old links when renaming steps --- Help/guide/tutorial/index.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 8a765fdebb0..8b20a2dfe6f 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -32,3 +32,12 @@ provides the complete solution for the previous step. Adding Generator Expressions Adding Export Configuration Packaging Debug and Release + +.. + Whenever a step above is renamed or removed, leave forwarding text in + its original document file, and list it below to preserve old links + to cmake.org/cmake/help/latest/ URLs. + +.. toctree:: + :maxdepth: 1 + :hidden: From d59b76f7b4872f85b3b31fa79ffa5bc8e9ef255d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 13:14:21 -0400 Subject: [PATCH 0713/1519] Help: Drop development topic notes to prepare release Release versions do not have the development topic section of the CMake Release Notes index page. --- Help/release/dev/0-sample-topic.rst | 7 ------- Help/release/index.rst | 2 -- 2 files changed, 9 deletions(-) delete mode 100644 Help/release/dev/0-sample-topic.rst diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst deleted file mode 100644 index e4cc01e23fe..00000000000 --- a/Help/release/dev/0-sample-topic.rst +++ /dev/null @@ -1,7 +0,0 @@ -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/index.rst b/Help/release/index.rst index 59388784510..75667e54f0e 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -7,8 +7,6 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. -.. include:: dev.txt - Releases ======== From f52b5aba20886135618909d5ab560adf9c4eb1c0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 13:15:33 -0400 Subject: [PATCH 0714/1519] gitlab-ci: Drop package pipeline upload jobs for release branch The package pipeline for release versions should not upload packages automatically to our archive of nightly development versions. --- .gitlab-ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d224088e9d0..bbed2e2003d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,7 @@ prep:doc-package: - .cmake_doc_artifacts - .run_only_for_package -upload:source-package: +.upload:source-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -70,7 +70,7 @@ build:help:master: - .cmake_org_help - .run_only_for_continuous_master -upload:help:master: +.upload:help:master: extends: - .rsync_upload_help - .run_only_for_continuous_master @@ -86,7 +86,7 @@ build:help:stage: - .cmake_org_help - .run_only_for_continuous_stage -upload:help:stage: +.upload:help:stage: extends: - .rsync_upload_help - .run_only_for_continuous_stage @@ -495,7 +495,7 @@ build:linux-x86_64-package: needs: - prep:doc-package -upload:linux-x86_64-package: +.upload:linux-x86_64-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -519,7 +519,7 @@ build:linux-aarch64-package: needs: - prep:doc-package -upload:linux-aarch64-package: +.upload:linux-aarch64-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -656,7 +656,7 @@ build:macos-package: needs: - prep:doc-package -upload:macos-package: +.upload:macos-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -679,7 +679,7 @@ build:macos10.10-package: needs: - prep:doc-package -upload:macos10.10-package: +.upload:macos10.10-package: extends: - .rsync_upload_binary - .run_only_for_package From 22fb0713a25ac4ecfbbc1e1c24f440ba83a175b8 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 13:17:06 -0400 Subject: [PATCH 0715/1519] Begin 3.21 release versioning --- Source/CMakeVersion.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 46e94f153ab..ad174a7687a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,8 +1,8 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 20210617) -#set(CMake_VERSION_RC 0) +set(CMake_VERSION_MINOR 21) +set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 11695f5985e9cbd7a5206908fe6d2ea7e77865e9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jun 2021 13:18:30 -0400 Subject: [PATCH 0716/1519] Begin post-3.21 development --- .gitlab-ci.yml | 14 +++++++------- Help/release/dev/0-sample-topic.rst | 7 +++++++ Help/release/index.rst | 2 ++ Source/CMakeVersion.cmake | 4 ++-- 4 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 Help/release/dev/0-sample-topic.rst diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bbed2e2003d..d224088e9d0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,7 @@ prep:doc-package: - .cmake_doc_artifacts - .run_only_for_package -.upload:source-package: +upload:source-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -70,7 +70,7 @@ build:help:master: - .cmake_org_help - .run_only_for_continuous_master -.upload:help:master: +upload:help:master: extends: - .rsync_upload_help - .run_only_for_continuous_master @@ -86,7 +86,7 @@ build:help:stage: - .cmake_org_help - .run_only_for_continuous_stage -.upload:help:stage: +upload:help:stage: extends: - .rsync_upload_help - .run_only_for_continuous_stage @@ -495,7 +495,7 @@ build:linux-x86_64-package: needs: - prep:doc-package -.upload:linux-x86_64-package: +upload:linux-x86_64-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -519,7 +519,7 @@ build:linux-aarch64-package: needs: - prep:doc-package -.upload:linux-aarch64-package: +upload:linux-aarch64-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -656,7 +656,7 @@ build:macos-package: needs: - prep:doc-package -.upload:macos-package: +upload:macos-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -679,7 +679,7 @@ build:macos10.10-package: needs: - prep:doc-package -.upload:macos10.10-package: +upload:macos10.10-package: extends: - .rsync_upload_binary - .run_only_for_package diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst new file mode 100644 index 00000000000..e4cc01e23fe --- /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/index.rst b/Help/release/index.rst index 75667e54f0e..59388784510 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -7,6 +7,8 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. +.. include:: dev.txt + Releases ======== diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ad174a7687a..521aa2090fc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,8 +1,8 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 0) +set(CMake_VERSION_PATCH 20210617) +#set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 701773f1da09568cc7501b97373fb1ad6b489a2b Mon Sep 17 00:00:00 2001 From: Marc Aldorasi Date: Thu, 17 Jun 2021 13:39:48 -0400 Subject: [PATCH 0717/1519] CheckCompilerFlag: Handle -Werror= for GCC 11 --- Modules/Internal/CheckCompilerFlag.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/Internal/CheckCompilerFlag.cmake b/Modules/Internal/CheckCompilerFlag.cmake index 9eb1bf0f81b..693e28b69d2 100644 --- a/Modules/Internal/CheckCompilerFlag.cmake +++ b/Modules/Internal/CheckCompilerFlag.cmake @@ -13,10 +13,12 @@ function(CMAKE_CHECK_COMPILER_FLAG _lang _flag _var) if(_lang STREQUAL "C") set(_lang_src "int main(void) { return 0; }") - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C") + set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C" + FAIL_REGEX "-Werror=.* argument .* is not valid for C") elseif(_lang STREQUAL "CXX") set(_lang_src "int main() { return 0; }") - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+") + set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" + FAIL_REGEX "-Werror=.* argument .* is not valid for C\\+\\+") elseif(_lang STREQUAL "CUDA") set(_lang_src "__host__ int main() { return 0; }") set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" # Host GNU From 9ba99a1203efea8e5c3977514b22f6204507f17b Mon Sep 17 00:00:00 2001 From: Gustavo Varo Date: Wed, 16 Jun 2021 18:05:55 -0400 Subject: [PATCH 0718/1519] VS: Add support for Utf8Enconding when using VS 16.10+ On VS 16.10 Preview 2 or above, generate `UseUtf8Encoding` instead of `StdOutEncoding=UTF-8` in `.vcxproj` files. Fixes: #22032 --- Source/cmGlobalVisualStudio10Generator.h | 2 ++ Source/cmGlobalVisualStudioVersionedGenerator.cxx | 15 +++++++++++++++ Source/cmGlobalVisualStudioVersionedGenerator.h | 2 ++ Source/cmVisualStudio10TargetGenerator.cxx | 4 +++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 646dbe28ae9..b7ae1eecfd8 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -138,6 +138,8 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator virtual bool IsStdOutEncodingSupported() const { return false; } + virtual bool IsUtf8EncodingSupported() const { return false; } + static std::string GetInstalledNsightTegraVersion(); /** Return the first two components of CMAKE_SYSTEM_VERSION. */ diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 384aa66bdec..c8213c54c74 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -417,6 +417,21 @@ bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_7_P2)); } +bool cmGlobalVisualStudioVersionedGenerator::IsUtf8EncodingSupported() const +{ + // Supported from Visual Studio 16.10 Preview 2. + if (this->Version > cmGlobalVisualStudioGenerator::VSVersion::VS16) { + return true; + } + if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS16) { + return false; + } + static std::string const vsVer16_10_P2 = "16.10.31213.239"; + cm::optional vsVer = this->GetVSInstanceVersion(); + return (vsVer && + cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_10_P2)); +} + const char* cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision() const diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index db4a0ba97a6..e6c19e4b349 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -35,6 +35,8 @@ class cmGlobalVisualStudioVersionedGenerator bool IsStdOutEncodingSupported() const override; + bool IsUtf8EncodingSupported() const override; + const char* GetAndroidApplicationTypeRevision() const override; protected: diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index b79c6fda14e..11a8b1f3e70 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -5115,7 +5115,9 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1) { - if (this->GlobalGenerator->IsStdOutEncodingSupported()) { + if (this->GlobalGenerator->IsUtf8EncodingSupported()) { + e1.Element("UseUtf8Encoding", "Always"); + } else if (this->GlobalGenerator->IsStdOutEncodingSupported()) { e1.Element("StdOutEncoding", "UTF-8"); } } From 8f63f3b04ec36b8adc8bcdef38204cb073131229 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 4 Jun 2021 14:47:52 -0400 Subject: [PATCH 0719/1519] cmVisualStudio10TargetGenerator: remove unused variable --- Source/cmVisualStudio10TargetGenerator.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index b79c6fda14e..822abb3788b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3543,8 +3543,6 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions( } Elem e2(e1, "NASM"); - std::vector includes = - this->GetIncludes(configName, "ASM_NASM"); OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2); nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM"); nasmOptions.OutputFlagMap(); From b094324948291ee3fbd2ce17969157cdeab18592 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Jun 2021 10:56:43 -0400 Subject: [PATCH 0720/1519] Tests/IncludeDirectories: Include system headers via angle brackets This is typically how projects include them, and cl's `-external:{I,W}` flags suppress warnings only when included through angle brackets. --- Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp | 3 ++- .../SystemIncludeDirectories/imported_consumer.cpp | 2 +- Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp index a13f08fdc07..3da308d5d88 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp @@ -1,5 +1,6 @@ -#include "config_iface.h" +#include + #include "upstream.h" int consumer() diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp index 1dbe819e131..53759b11c5a 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp @@ -1,5 +1,5 @@ -#include "systemlib.h" +#include int main() { diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h index a670c2a48d0..3daf69eb6ca 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h @@ -2,7 +2,7 @@ #ifndef UPSTREAM_H #define UPSTREAM_H -#include "systemlib.h" +#include #ifdef _WIN32 __declspec(dllexport) From 809f7b0c3af8d46610ae0963e061415b50f2a363 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 2 Jun 2021 19:20:25 -0400 Subject: [PATCH 0721/1519] Tests/IncludeDirectories: fix copy pasta for otherlib --- .../IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt index dee39c8264b..ff52c985d9a 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt @@ -52,7 +52,7 @@ target_compile_options(somelib PRIVATE -Werror=unused-variable) # add a target which consumes a relative system include add_library(otherlib upstream.cpp) target_link_libraries(otherlib PUBLIC somelib) -target_compile_options(somelib PRIVATE -Werror=unused-variable) +target_compile_options(otherlib PRIVATE -Werror=unused-variable) macro(do_try_compile error_option) set(TC_ARGS From 20ab49193ba1196421909b7910c9e0c7a30fa31f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 2 Jun 2021 19:19:45 -0400 Subject: [PATCH 0722/1519] Tests/IncludeDirectories: factor out applying flags to targets --- .../SystemIncludeDirectories/CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt index ff52c985d9a..7874d5e03ca 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt @@ -6,9 +6,13 @@ project(SystemIncludeDirectories) add_library(systemlib systemlib.cpp) target_include_directories(systemlib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/systemlib") +function (apply_error_flags target) + target_compile_options(${target} PRIVATE -Werror=unused-variable) +endfunction () + add_library(upstream upstream.cpp) target_link_libraries(upstream LINK_PUBLIC systemlib) -target_compile_options(upstream PRIVATE -Werror=unused-variable) +apply_error_flags(upstream) target_include_directories(upstream SYSTEM PUBLIC $ @@ -29,7 +33,7 @@ endif() add_library(consumer consumer.cpp) target_link_libraries(consumer upstream config_specific) -target_compile_options(consumer PRIVATE -Werror=unused-variable) +apply_error_flags(consumer) add_library(iface IMPORTED INTERFACE) set_property(TARGET iface PROPERTY INTERFACE_INCLUDE_DIRECTORIES @@ -38,21 +42,21 @@ set_property(TARGET iface PROPERTY INTERFACE_INCLUDE_DIRECTORIES add_library(imported_consumer imported_consumer.cpp) target_link_libraries(imported_consumer iface) -target_compile_options(imported_consumer PRIVATE -Werror=unused-variable) +apply_error_flags(imported_consumer) add_library(imported_consumer2 imported_consumer.cpp) target_link_libraries(imported_consumer2 imported_consumer) -target_compile_options(imported_consumer2 PRIVATE -Werror=unused-variable) +apply_error_flags(imported_consumer2) # add a target which has a relative system include add_library(somelib imported_consumer.cpp) target_include_directories(somelib SYSTEM PUBLIC "systemlib_header_only") -target_compile_options(somelib PRIVATE -Werror=unused-variable) +apply_error_flags(somelib) # add a target which consumes a relative system include add_library(otherlib upstream.cpp) target_link_libraries(otherlib PUBLIC somelib) -target_compile_options(otherlib PRIVATE -Werror=unused-variable) +apply_error_flags(otherlib) macro(do_try_compile error_option) set(TC_ARGS From 399a3204bb2d198cc660cd83e0de39ad95658498 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 2 Jun 2021 19:21:38 -0400 Subject: [PATCH 0723/1519] Tests/IncludeDirectories: align sibling predicates --- Tests/IncludeDirectories/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index d4c19c79b52..0f0f1395fac 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required (VERSION 2.6) project(IncludeDirectories) if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4) - OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR CMAKE_C_COMPILER_ID STREQUAL AppleClang) + OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") + OR CMAKE_C_COMPILER_ID STREQUAL AppleClang) AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR STREQUAL "Ninja" OR (CMAKE_GENERATOR STREQUAL "Xcode" AND NOT XCODE_VERSION VERSION_LESS 6.0))) From 5a5c85dffd72972987cb542a4b6c9e606920cbb5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 2 Jun 2021 19:22:35 -0400 Subject: [PATCH 0724/1519] Tests/IncludeDirectories: support MSVC in system include tests --- Tests/IncludeDirectories/CMakeLists.txt | 23 ++++++++++++------- .../SystemIncludeDirectories/CMakeLists.txt | 12 ++++++++-- .../CMakeLists.txt | 4 ++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index 0f0f1395fac..4c488e61591 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -3,17 +3,24 @@ project(IncludeDirectories) if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4) OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - OR CMAKE_C_COMPILER_ID STREQUAL AppleClang) + OR CMAKE_C_COMPILER_ID STREQUAL AppleClang + OR ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC" AND + CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "19.29.30036.3" AND + NOT CMAKE_GENERATOR MATCHES "Visual Studio")) # No support for VS generators yet. AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR STREQUAL "Ninja" OR (CMAKE_GENERATOR STREQUAL "Xcode" AND NOT XCODE_VERSION VERSION_LESS 6.0))) - include(CheckCXXCompilerFlag) - check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test) - if(run_sys_includes_test) - # The Bullseye wrapper appears to break the -isystem effect. - execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE out ERROR_VARIABLE out) - if("x${out}" MATCHES "Bullseye") - set(run_sys_includes_test 0) + if ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC") + set(run_sys_includes_test 1) + else () + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test) + if(run_sys_includes_test) + # The Bullseye wrapper appears to break the -isystem effect. + execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE out ERROR_VARIABLE out) + if("x${out}" MATCHES "Bullseye") + set(run_sys_includes_test 0) + endif() endif() endif() if (run_sys_includes_test) diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt index 7874d5e03ca..a746a681b04 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt @@ -7,7 +7,11 @@ add_library(systemlib systemlib.cpp) target_include_directories(systemlib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/systemlib") function (apply_error_flags target) - target_compile_options(${target} PRIVATE -Werror=unused-variable) + if (MSVC) + target_compile_options(${target} PRIVATE /we4101) + else () + target_compile_options(${target} PRIVATE -Werror=unused-variable) + endif () endfunction () add_library(upstream upstream.cpp) @@ -65,7 +69,11 @@ macro(do_try_compile error_option) LINK_LIBRARIES iface ) if (${error_option} STREQUAL WITH_ERROR) - list(APPEND TC_ARGS COMPILE_DEFINITIONS -Werror=unused-variable) + if (MSVC) + list(APPEND TC_ARGS COMPILE_DEFINITIONS /we4101) + else () + list(APPEND TC_ARGS COMPILE_DEFINITIONS -Werror=unused-variable) + endif () endif() try_compile(${TC_ARGS}) endmacro() diff --git a/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt index 70dfa017bd7..5d58633e592 100644 --- a/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt +++ b/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt @@ -7,14 +7,14 @@ set_target_properties(c_interface PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "$<$:${CMAKE_CURRENT_SOURCE_DIR}>" INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "$<$:${CMAKE_CURRENT_SOURCE_DIR}>" ) -target_compile_options(c_interface INTERFACE "$<$:-Werror=unused-variable>") +target_compile_options(c_interface INTERFACE "$<$:-Werror=unused-variable>;$<$:/we4101>") add_library(cxx_interface INTERFACE) set_target_properties(cxx_interface PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "$<$:${CMAKE_CURRENT_SOURCE_DIR}/cxx_system_include>" INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "$<$:${CMAKE_CURRENT_SOURCE_DIR}/cxx_system_include>" ) -target_compile_options(cxx_interface INTERFACE "$<$:-Werror=unused-variable>") +target_compile_options(cxx_interface INTERFACE "$<$:-Werror=unused-variable>;$<$:/we4101>") # The C header must come before the C++ header for this test to smoke out the # failure. The order of sources is how CMake determines the include cache From bd38749fd43c1d550f7c45e96a97cddb90c29437 Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Wed, 16 Jun 2021 11:38:45 -0400 Subject: [PATCH 0725/1519] ctest: allow test output to add labels Parse test output for .... If found, add this value to the list of labels associated with this test. --- Help/command/ctest_test.rst | 15 ++++++++++ Help/release/dev/ctest-runtime-labels.rst | 7 +++++ Source/CTest/cmCTestRunTest.cxx | 17 +++++++++++ Source/CTest/cmCTestTestHandler.cxx | 2 ++ Source/CTest/cmCTestTestHandler.h | 1 + Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 13 +++++++++ .../ctest_test/TestExtraLabels-check.cmake | 28 +++++++++++++++++++ 7 files changed, 83 insertions(+) create mode 100644 Help/release/dev/ctest-runtime-labels.rst create mode 100644 Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 2153c90de35..03ec1a4b089 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -270,3 +270,18 @@ The following example demonstrates how to specify a custom value for the std::cout << "My Custom Details Value" << std::endl; + +Additional Labels +""""""""""""""""" + +The following example demonstrates how to add additional labels to a test +at runtime. + +.. code-block:: c++ + + std::cout << + "Custom Label 1\n" << + "Custom Label 2" << std::endl; + +Use the :prop_test:`LABELS` test property instead for labels that can be +determined at configure time. diff --git a/Help/release/dev/ctest-runtime-labels.rst b/Help/release/dev/ctest-runtime-labels.rst new file mode 100644 index 00000000000..7ce0b64113b --- /dev/null +++ b/Help/release/dev/ctest-runtime-labels.rst @@ -0,0 +1,7 @@ +ctest-runtime-labels +-------------------- + +* :manual:`ctest(1)` learned to recognize labels attached to a test at run time. + Previously it was only possible to attach labels to tests at configure time + by using the :prop_test:`LABELS` test property. + See :ref:`Additional Test Measurements` for more information. diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index a8921134b35..50072c5fa98 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestRunTest.h" +#include #include #include // IWYU pragma: keep #include @@ -44,7 +45,9 @@ void cmCTestRunTest::CheckOutput(std::string const& line) // Check for special CTest XML tags in this line of output. // If any are found, this line is excluded from ProcessOutput. if (!line.empty() && line.find("TestHandler->CustomCompletionStatusRegex.find(line)) { + ctest_tag_found = true; this->TestResult.CustomCompletionStatus = this->TestHandler->CustomCompletionStatusRegex.match(1); cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -52,6 +55,20 @@ void cmCTestRunTest::CheckOutput(std::string const& line) << "Test Details changed to '" << this->TestResult.CustomCompletionStatus << "'" << std::endl); + } else if (this->TestHandler->CustomLabelRegex.find(line)) { + ctest_tag_found = true; + auto label = this->TestHandler->CustomLabelRegex.match(1); + auto& labels = this->TestProperties->Labels; + if (std::find(labels.begin(), labels.end(), label) == labels.end()) { + labels.push_back(label); + std::sort(labels.begin(), labels.end()); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() + << ": " + << "Test Label added: '" << label << "'" << std::endl); + } + } + if (ctest_tag_found) { return; } } diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 730ec0f04dd..aeaf696d1a6 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -312,6 +312,8 @@ cmCTestTestHandler::cmCTestTestHandler() // regex to detect ... this->CustomCompletionStatusRegex.compile( "(.*)"); + // regex to detect ... + this->CustomLabelRegex.compile("(.*)"); } void cmCTestTestHandler::Initialize() diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index bd51738b8fc..cc19984eea1 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -360,6 +360,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler size_t TotalNumberOfTests; cmsys::RegularExpression DartStuff; cmsys::RegularExpression CustomCompletionStatusRegex; + cmsys::RegularExpression CustomLabelRegex; std::ostream* LogFile; diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index f07a12b7739..31bc0752e55 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -181,3 +181,16 @@ add_test( run_ctest(TestCompletionStatus) endfunction() run_completion_status() + +# Verify that test output can add additional labels +function(run_extra_labels) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test( + NAME custom_labels + COMMAND ${CMAKE_COMMAND} -E + echo before\nlabel2\nlabel1\nlabel3\nlabel2\nafter) +set_tests_properties(custom_labels PROPERTIES LABELS "label1") + ]]) + run_ctest(TestExtraLabels) +endfunction() +run_extra_labels() diff --git a/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake b/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake new file mode 100644 index 00000000000..beb39dec1f3 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake @@ -0,0 +1,28 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/TAG" _tag) +string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}") +file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents) + +# Check labels. +STRING(REGEX MATCHALL [[]] matches "${_test_contents}") +list(LENGTH matches n_matches) +if(NOT n_matches EQUAL 1) + string(APPEND RunCMake_TEST_FAILED "expected 1 match for label1, found ${n_matches}") +endif() +STRING(REGEX MATCHALL [[]] matches "${_test_contents}") +list(LENGTH matches n_matches) +if(NOT n_matches EQUAL 1) + string(APPEND RunCMake_TEST_FAILED "expected 1 match for label2, found ${n_matches}") +endif() +STRING(REGEX MATCHALL [[]] matches "${_test_contents}") +list(LENGTH matches n_matches) +if(NOT n_matches EQUAL 1) + string(APPEND RunCMake_TEST_FAILED "expected 1 match for label3, found ${n_matches}") +endif() + +# Check test output. +if(NOT _test_contents MATCHES "before") + string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'before' in Test.xml") +endif() +if(NOT _test_contents MATCHES "after") + string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'after' in Test.xml") +endif() From 5ef8c09a8ffe4dadd06aa25e1ed5d8f0112bf4c7 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Fri, 18 Jun 2021 00:01:12 -0400 Subject: [PATCH 0726/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 521aa2090fc..bf802ef9980 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210617) +set(CMake_VERSION_PATCH 20210618) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From c8eb35773806174480070c17785e6c8dd5dc1e4c Mon Sep 17 00:00:00 2001 From: Philippe Canal Date: Thu, 17 Jun 2021 17:59:45 -0500 Subject: [PATCH 0727/1519] CompilerId: Tolerate variables named for languages If a project or user sets a variable or cache entry named `C`, `CXX`, `CUDA`, `Fortran`, `CSharp`, or `ISPC`, we were previously comparing each enabled language name to the value of that variable, rather than the name itself. Double-quote the string to take advantage of policy `CMP0054`, but also add "x" prefixes to support projects that do not set the policy. This extends a similar fix in commit bd16a985fc (CompilerId/Features: Tolerate variables named for languages, 2021-04-28) in more places. In particular, ensure that we consider the proper list of compiler ids. Issue: #22125 --- Modules/CMakeCompilerIdDetection.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index 21977900c33..dd70d828f5d 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -13,8 +13,8 @@ endfunction() function(compiler_id_detection outvar lang) - if (NOT lang STREQUAL Fortran AND NOT lang STREQUAL CSharp - AND NOT lang STREQUAL ISPC) + if (NOT "x${lang}" STREQUAL "xFortran" AND NOT "x${lang}" STREQUAL "xCSharp" + AND NOT "x${lang}" STREQUAL "xISPC") file(GLOB lang_files "${CMAKE_ROOT}/Modules/Compiler/*-DetermineCompiler.cmake") set(nonlang CXX) @@ -42,7 +42,7 @@ function(compiler_id_detection outvar lang) # Order is relevant here. For example, compilers which pretend to be # GCC must appear before the actual GCC. - if (lang STREQUAL CXX) + if ("x${lang}" STREQUAL "xCXX") list(APPEND ordered_compilers Comeau ) @@ -70,7 +70,7 @@ function(compiler_id_detection outvar lang) Fujitsu GHS ) - if (lang STREQUAL C) + if ("x${lang}" STREQUAL "xC") list(APPEND ordered_compilers TinyCC Bruce @@ -92,13 +92,13 @@ function(compiler_id_detection outvar lang) ADSP IAR ) - if (lang STREQUAL C) + if ("x${lang}" STREQUAL "xC") list(APPEND ordered_compilers SDCC ) endif() - if(lang STREQUAL CUDA) + if("x${lang}" STREQUAL "xCUDA") set(ordered_compilers NVIDIA Clang) endif() From f29e1874adbc31c9d4643816d8b520ad4fde3b84 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 19 May 2020 10:28:26 -0400 Subject: [PATCH 0728/1519] Compiler/MSVC: use the `-external:I` flag for system includes See: #17904 --- Help/release/dev/msvc-isystem.rst | 7 +++++++ Modules/Compiler/MSVC-C.cmake | 6 ++++++ Modules/Compiler/MSVC-CXX.cmake | 6 ++++++ Source/cmLocalGenerator.cxx | 8 ++++++++ 4 files changed, 27 insertions(+) create mode 100644 Help/release/dev/msvc-isystem.rst diff --git a/Help/release/dev/msvc-isystem.rst b/Help/release/dev/msvc-isystem.rst new file mode 100644 index 00000000000..4a5d79f7dfc --- /dev/null +++ b/Help/release/dev/msvc-isystem.rst @@ -0,0 +1,7 @@ +msvc-isystem +------------ + +* The MSVC compilers learned to pass the ``-external:I`` flag for system + includes when using the :generator:`Ninja` and :generator:`NMake Makefiles` + generators. This became available as of Visual Studio 16.10 (toolchain + version 14.29.30037). diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index 9a5104bd903..73cca362047 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -63,3 +63,9 @@ endmacro() if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) set(CMAKE_C_COMPILE_OPTIONS_JMC "-JMC") endif() + +# The `/external:I` flag was made non-experimental in 19.29.30036.3. +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) + set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-external:I ") + set(_CMAKE_INCLUDE_SYSTEM_FLAG_C_WARNING "-external:W0 ") +endif () diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index f1c7450fad9..09fe851d633 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -79,3 +79,9 @@ endif() if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) set(CMAKE_CXX_COMPILE_OPTIONS_JMC "-JMC") endif() + +# The `/external:I` flag was made non-experimental in 19.29.30036.3. +if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) + set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-external:I ") + set(_CMAKE_INCLUDE_SYSTEM_FLAG_CXX_WARNING "-external:W0 ") +endif () diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3b282de98c7..a14f0850f48 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -878,9 +878,12 @@ std::string cmLocalGenerator::GetIncludeFlags( // Support special system include flag if it is available and the // normal flag is repeated for each directory. cmProp sysIncludeFlag = nullptr; + cmProp sysIncludeFlagWarning = nullptr; if (repeatFlag) { sysIncludeFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang)); + sysIncludeFlagWarning = this->Makefile->GetDefinition( + cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", lang, "_WARNING")); } cmProp fwSearchFlag = this->Makefile->GetDefinition( @@ -889,6 +892,7 @@ std::string cmLocalGenerator::GetIncludeFlags( cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG")); bool flagUsed = false; + bool sysIncludeFlagUsed = false; std::set emitted; #ifdef __APPLE__ emitted.insert("/System/Library/Frameworks"); @@ -915,6 +919,7 @@ std::string cmLocalGenerator::GetIncludeFlags( if (sysIncludeFlag && target && target->IsSystemIncludeDirectory(i, config, lang)) { includeFlags << *sysIncludeFlag; + sysIncludeFlagUsed = true; } else { includeFlags << includeFlag; } @@ -931,6 +936,9 @@ std::string cmLocalGenerator::GetIncludeFlags( } includeFlags << sep; } + if (sysIncludeFlagUsed && sysIncludeFlagWarning) { + includeFlags << *sysIncludeFlagWarning; + } std::string flags = includeFlags.str(); // remove trailing separators if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) { From 35d3e00e4e9b138dec1d1a646766fc342d04b8f5 Mon Sep 17 00:00:00 2001 From: Christopher Degawa Date: Fri, 11 Jun 2021 15:17:39 -0500 Subject: [PATCH 0729/1519] FindPkgConfig: split args if loaded from environment It's common for some people to use the PKG_CONFIG environment variable to not only load a custom pkg-config/pkgconf but also to load some default arguments such as `--static` or `--keep-system-libs` which often worked since shell scripts would call `$PKG_CONFIG --libs pkg` without quotes, but this breaks FindPkgConfig since it uses the full string as `argv[0]` and might try looking for a binary called `pkgconf --static`, instead of looking for `pkgconf` and adding `--static` as the `argv[1]` Additionally adds RunCMake.FindPkgConfig ARGN test case Fixes: #22305 Signed-off-by: Christopher Degawa --- .../dev/FindPkgConfig-PKG_CONFIG-args.rst | 5 +++ Modules/FindPkgConfig.cmake | 39 ++++++++++++++++--- .../FindPkgConfig_GET_MATCHING_ARGN.cmake | 17 ++++++++ .../RunCMake/FindPkgConfig/RunCMakeTest.cmake | 1 + .../FindPkgConfig/dummy-pkg-config.bat | 17 ++++++++ .../FindPkgConfig/dummy-pkg-config.sh | 19 +++++++++ 6 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst create mode 100644 Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake diff --git a/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst b/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst new file mode 100644 index 00000000000..44c26b544fa --- /dev/null +++ b/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst @@ -0,0 +1,5 @@ +FindPkgConfig-PKG_CONFIG-args +----------------------------- + +* The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN` + variable to specify arguments to ``pkg-config`` calls. diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 3bc9dba167a..bd54fd9dbc0 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -15,6 +15,8 @@ following variables will also be set: if pkg-config executable was found ``PKG_CONFIG_EXECUTABLE`` pathname of the pkg-config program +``PKG_CONFIG_ARGN`` + list of arguments to pass to pkg-config ``PKG_CONFIG_VERSION_STRING`` version of pkg-config (since CMake 2.8.8) @@ -29,7 +31,15 @@ set(PKG_CONFIG_VERSION 1) # find pkg-config, use PKG_CONFIG if set if((NOT PKG_CONFIG_EXECUTABLE) AND (NOT "$ENV{PKG_CONFIG}" STREQUAL "")) - set(PKG_CONFIG_EXECUTABLE "$ENV{PKG_CONFIG}" CACHE FILEPATH "pkg-config executable") + separate_arguments(PKG_CONFIG_FROM_ENV_SPLIT NATIVE_COMMAND PROGRAM SEPARATE_ARGS "$ENV{PKG_CONFIG}") + list(LENGTH PKG_CONFIG_FROM_ENV_SPLIT PKG_CONFIG_FROM_ENV_SPLIT_ARGC) + if(PKG_CONFIG_FROM_ENV_SPLIT_ARGC GREATER 0) + list(GET PKG_CONFIG_FROM_ENV_SPLIT 0 PKG_CONFIG_FROM_ENV_ARGV0) + if(PKG_CONFIG_FROM_ENV_SPLIT_ARGC GREATER 1) + list(SUBLIST PKG_CONFIG_FROM_ENV_SPLIT 1 -1 PKG_CONFIG_ARGN) + endif() + set(PKG_CONFIG_EXECUTABLE "${PKG_CONFIG_FROM_ENV_ARGV0}" CACHE FILEPATH "pkg-config executable") + endif() endif() set(PKG_CONFIG_NAMES "pkg-config") @@ -43,9 +53,12 @@ find_program(PKG_CONFIG_EXECUTABLE DOC "pkg-config executable") mark_as_advanced(PKG_CONFIG_EXECUTABLE) +set(PKG_CONFIG_ARGN "${PKG_CONFIG_ARGN}" CACHE STRING "Arguments to supply to pkg-config") +mark_as_advanced(PKG_CONFIG_ARGN) + set(_PKG_CONFIG_FAILURE_MESSAGE "") if (PKG_CONFIG_EXECUTABLE) - execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --version + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_ARGN} --version OUTPUT_VARIABLE PKG_CONFIG_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE _PKG_CONFIG_VERSION_ERROR ERROR_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE _PKG_CONFIG_VERSION_RESULT @@ -53,14 +66,18 @@ if (PKG_CONFIG_EXECUTABLE) if (NOT _PKG_CONFIG_VERSION_RESULT EQUAL 0) string(REPLACE "\n" "\n " _PKG_CONFIG_VERSION_ERROR " ${_PKG_CONFIG_VERSION_ERROR}") + if(PKG_CONFIG_ARGN) + string(REPLACE ";" " " PKG_CONFIG_ARGN " ${PKG_CONFIG_ARGN}") + endif() string(APPEND _PKG_CONFIG_FAILURE_MESSAGE "The command\n" - " \"${PKG_CONFIG_EXECUTABLE}\" --version\n" + " \"${PKG_CONFIG_EXECUTABLE}\"${PKG_CONFIG_ARGN} --version\n" " failed with output:\n${PKG_CONFIG_VERSION_STRING}\n" " stderr: \n${_PKG_CONFIG_VERSION_ERROR}\n" " result: \n${_PKG_CONFIG_VERSION_RESULT}" ) set(PKG_CONFIG_EXECUTABLE "") + set(PKG_CONFIG_ARGN "") unset(PKG_CONFIG_VERSION_STRING) endif () unset(_PKG_CONFIG_VERSION_RESULT) @@ -91,7 +108,7 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) set(_pkgconfig_invoke_result) execute_process( - COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist} + COMMAND ${PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_ARGN} ${ARGN} ${_pkglist} OUTPUT_VARIABLE _pkgconfig_invoke_result RESULT_VARIABLE _pkgconfig_failed OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -533,7 +550,7 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma # execute the query execute_process( - COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query} + COMMAND ${PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_ARGN} ${_pkg_check_modules_exist_query} RESULT_VARIABLE _pkgconfig_retval ERROR_VARIABLE _pkgconfig_error ERROR_STRIP_TRAILING_WHITESPACE) @@ -892,6 +909,18 @@ Variables Affecting Behavior .. versionadded:: 3.1 The ``PKG_CONFIG`` environment variable can be used as a hint. +.. variable:: PKG_CONFIG_ARGN + + .. versionadded:: 3.22 + + This can be set to a list of arguments to additionally pass to pkg-config + if needed. If not provided, it will be an empty string, however, if the + environment variable ``PKG_CONFIG`` is provided, this will be set to the + result of splitting the variable. + + The ``PKG_CONFIG`` environment variable can be used to provide both + ``PKG_CONFIG_EXECUTABLE`` and ``PKG_CONFIG_ARGN`` + .. variable:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH .. versionadded:: 3.1 diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake new file mode 100644 index 00000000000..e49ff22f6b8 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake @@ -0,0 +1,17 @@ +if(WIN32) + set(ENV{PKG_CONFIG} "\"${CMAKE_CURRENT_SOURCE_DIR}\\dummy-pkg-config.bat\" --static --print-errors") +else() + set(ENV{PKG_CONFIG} "\"${CMAKE_CURRENT_SOURCE_DIR}/dummy-pkg-config.sh\" --static --print-errors") +endif() + +find_package(PkgConfig REQUIRED) + +if(NOT PKG_CONFIG_ARGN STREQUAL "--static;--print-errors") + message(SEND_ERROR "PKG_CONFIG_ARGN has wrong value '${PKG_CONFIG_ARGN}'") +endif() + +_pkgconfig_invoke("none" "prefix" "output" "") + +if(NOT prefix_output STREQUAL "Received;--static;Received;--print-errors") + message(SEND_ERROR "prefix_output has wrong value '${prefix_output}'") +endif() diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index e7f008ca530..17e046a2b8c 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -12,6 +12,7 @@ run_cmake(FindPkgConfig_PKGCONFIG_PATH) run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH) run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH) run_cmake(FindPkgConfig_extract_frameworks) +run_cmake(FindPkgConfig_GET_MATCHING_ARGN) if(APPLE) run_cmake(FindPkgConfig_extract_frameworks_target) diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat index b03837030c5..c91713b257b 100755 --- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat +++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat @@ -1,5 +1,10 @@ @ECHO OFF +rem variables to get around `--static --version` printing the received +rem message and then version +set static=false +set print_errors=false + :LOOP IF "%1"=="" ( @@ -21,7 +26,19 @@ IF "%1"=="--exists" ( EXIT /B 0 ) ) +IF "%1"=="--static" ( + set static=true +) +IF "%1"=="--print-errors" ( + set print_errors=true +) SHIFT IF NOT "%~1"=="" GOTO LOOP +IF "%static%"=="true" ECHO Received --static +IF "%print_errors%"=="true" ECHO Received --print-errors + +IF "%static%"=="true" GOTO :EOF +IF "%print_errors%"=="true" GOTO :EOF + EXIT /B 255 diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh index 56bba30dd4e..4021bf7a6fe 100755 --- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh +++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh @@ -4,6 +4,11 @@ # to the --exists argument with the PKG_CONFIG_PATH environment variable # and returns 1 if they are different. +# variables to get around `--static --version` printing the received +# message and then version +static=false +print_errors=false + while [ $# -gt 0 ]; do case $1 in --version) @@ -17,7 +22,21 @@ while [ $# -gt 0 ]; do echo "Found: ${PKG_CONFIG_PATH}" [ "${last}" = "${PKG_CONFIG_PATH}" ] && exit 0 || exit 1 ;; + --static) + static=true + ;; + --print-errors) + print_errors=true + ;; esac shift done + +$static && echo "Received --static" +$print_errors && echo "Received --print-errors" + +if $static || $print_errors; then + exit 0 +fi + exit 255 From 37b24e0bedcb2be97323d119897413addcb692e2 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 18 Jun 2021 16:59:16 +0200 Subject: [PATCH 0730/1519] GNUInstallDirs: don't use lib64 on Alpine Linux Fixes: #22318 --- Modules/GNUInstallDirs.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index f7d8c36a266..d81033ca90a 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -239,6 +239,7 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set endif() if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" AND NOT CMAKE_CROSSCOMPILING + AND NOT EXISTS "/etc/alpine-release" AND NOT EXISTS "/etc/arch-release") if (EXISTS "/etc/debian_version") # is this a debian system ? if(CMAKE_LIBRARY_ARCHITECTURE) From 73898c4922a8d495d4a5907ca8f072d1c4822ec1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Jun 2021 12:28:02 -0400 Subject: [PATCH 0731/1519] Tutorial: Make code snippets linkable Extend the change from commit 9e5bbb69ea (Tutorial: Add captions for code blocks, 2021-06-11) to also add a Sphinx named target to code blocks. Name each target after the change the code block makes. --- Help/guide/tutorial/A Basic Starting Point.rst | 8 ++++++++ Help/guide/tutorial/Adding Export Configuration.rst | 6 ++++++ Help/guide/tutorial/Adding Generator Expressions.rst | 3 +++ .../tutorial/Adding Support for a Testing Dashboard.rst | 3 +++ Help/guide/tutorial/Adding System Introspection.rst | 4 ++++ .../tutorial/Adding Usage Requirements for a Library.rst | 3 +++ .../Adding a Custom Command and Generated File.rst | 5 +++++ Help/guide/tutorial/Adding a Library.rst | 7 +++++++ Help/guide/tutorial/Installing and Testing.rst | 3 +++ Help/guide/tutorial/Packaging Debug and Release.rst | 4 ++++ Help/guide/tutorial/Packaging an Installer.rst | 1 + .../tutorial/Selecting Static or Shared Libraries.rst | 5 +++++ 12 files changed, 52 insertions(+) diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index 20e4129376d..41e8479b223 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -8,6 +8,7 @@ required. This will be the starting point for our tutorial. Create a .. code-block:: cmake :caption: CMakeLists.txt + :name: CMakeLists.txt-start cmake_minimum_required(VERSION 3.10) @@ -35,6 +36,7 @@ to set the project name and version number. .. literalinclude:: Step2/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-project-VERSION :language: cmake :end-before: # specify the C++ standard @@ -43,6 +45,7 @@ code: .. literalinclude:: Step2/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-configure_file :language: cmake :start-after: # to the source code :end-before: # add the executable @@ -53,6 +56,7 @@ files. Add the following lines to the end of the ``CMakeLists.txt`` file: .. literalinclude:: Step2/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories :language: cmake :start-after: # so that we will find TutorialConfig.h @@ -61,6 +65,7 @@ directory with the following contents: .. literalinclude:: Step2/TutorialConfig.h.in :caption: TutorialConfig.h.in + :name: TutorialConfig.h.in :language: c++ When CMake configures this header file the values for @@ -75,6 +80,7 @@ Finally, let's print out the executable name and version number by updating .. literalinclude:: Step2/tutorial.cxx :caption: tutorial.cxx + :name: tutorial.cxx-print-version :language: c++ :start-after: { :end-before: // convert input to double @@ -88,6 +94,7 @@ Next let's add some C++11 features to our project by replacing ``atof`` with .. literalinclude:: Step2/tutorial.cxx :caption: tutorial.cxx + :name: tutorial.cxx-cxx11 :language: c++ :start-after: // convert input to double :end-before: // calculate square root @@ -102,6 +109,7 @@ call to ``add_executable``. .. literalinclude:: Step2/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-CXX_STANDARD :language: cmake :end-before: # configure a header file to pass some of the CMake settings diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index da0d877e9be..e5ab6a2266d 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -19,6 +19,7 @@ command in ``MathFunctions/CMakeLists.txt`` to look like: .. literalinclude:: Complete/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT :language: cmake :start-after: # install rules @@ -28,6 +29,7 @@ adding the following to the bottom of the top-level ``CMakeLists.txt``: .. literalinclude:: Complete/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-install-EXPORT :language: cmake :start-after: # install the configuration targets :end-before: include(CMakePackageConfigHelpers) @@ -54,6 +56,7 @@ directory and from an install / package. This means converting the .. literalinclude:: Step12/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-target_include_directories :language: cmake :start-after: # to find MathFunctions.h, while we don't. :end-before: # should we use our own math functions @@ -69,12 +72,14 @@ ahead and add a new file to the top-level of the project called .. literalinclude:: Step12/Config.cmake.in :caption: Config.cmake.in + :name: Config.cmake.in Then, to properly configure and install that file, add the following to the bottom of the top-level ``CMakeLists.txt``: .. literalinclude:: Step12/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-install-Config.cmake :language: cmake :start-after: # install the configuration targets :end-before: # generate the export @@ -86,6 +91,7 @@ the following to the bottom of the top level ``CMakeLists.txt``: .. literalinclude:: Step12/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-export :language: cmake :start-after: # needs to be after the install(TARGETS ) command diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index b21fc62f1da..55acb346fcd 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -39,6 +39,7 @@ So the following code: .. literalinclude:: Step10/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-CXX_STANDARD-variable-remove :language: cmake :start-after: project(Tutorial VERSION 1.0) :end-before: # control where the static and shared libraries are built so that on windows @@ -47,6 +48,7 @@ Would be replaced with: .. literalinclude:: Step11/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-cxx_std-feature :language: cmake :start-after: project(Tutorial VERSION 1.0) :end-before: # add compiler warning flags just when building this project via @@ -59,6 +61,7 @@ of compiler ids as seen below: .. literalinclude:: Step11/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-target_compile_options-genex :language: cmake :start-after: # the BUILD_INTERFACE genex :end-before: # control where the static and shared libraries are built so that on windows diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index 9cdbb343b38..26aae4f8111 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -11,6 +11,7 @@ Replace: .. code-block:: cmake :caption: CMakeLists.txt + :name: CMakeLists.txt-enable_testing-remove # enable testing enable_testing() @@ -19,6 +20,7 @@ With: .. code-block:: cmake :caption: CMakeLists.txt + :name: CMakeLists.txt-include-CTest # enable dashboard scripting include(CTest) @@ -32,6 +34,7 @@ dashboard. .. literalinclude:: Step9/CTestConfig.cmake :caption: CTestConfig.cmake + :name: CTestConfig.cmake :language: cmake The :manual:`ctest ` executable will read in this file when it runs. diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index c11f793fcb8..7210a8dbcd7 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -16,6 +16,7 @@ the ``m`` library. If ``log`` and ``exp`` are not initially found, require the .. literalinclude:: Step6/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-check_symbol_exists :language: cmake :start-after: # does this system provide the log and exp functions? :end-before: # add compile definitions @@ -25,6 +26,7 @@ If available, use :command:`target_compile_definitions` to specify .. literalinclude:: Step6/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-target_compile_definitions :language: cmake :start-after: # add compile definitions :end-before: # install rules @@ -36,6 +38,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the .. literalinclude:: Step6/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx + :name: MathFunctions/mysqrt.cxx-ifdef :language: c++ :start-after: // if we have both log and exp then use them :end-before: // do ten iterations @@ -44,6 +47,7 @@ We will also need to modify ``mysqrt.cxx`` to include ``cmath``. .. literalinclude:: Step6/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx + :name: MathFunctions/mysqrt.cxx-include-cmath :language: c++ :end-before: #include diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index 8ef9cc66079..a8e914edaf8 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -23,6 +23,7 @@ doesn't. Add the following lines to the end of .. literalinclude:: Step4/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE :language: cmake :start-after: # to find MathFunctions.h @@ -32,6 +33,7 @@ remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level .. literalinclude:: Step4/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-remove-EXTRA_INCLUDES :language: cmake :start-after: # add the MathFunctions library :end-before: # add the executable @@ -40,6 +42,7 @@ And here: .. literalinclude:: Step4/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES :language: cmake :start-after: # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst index c60379aaca5..70c66956231 100644 --- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst +++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst @@ -28,6 +28,7 @@ First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for .. literalinclude:: Step7/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-add_executable-MakeTable :language: cmake :start-after: # first we add the executable that generates the table :end-before: # add the command to generate the source code @@ -37,6 +38,7 @@ by running MakeTable. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h :language: cmake :start-after: # add the command to generate the source code :end-before: # add the main library @@ -47,6 +49,7 @@ of sources for the library MathFunctions. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-add_library-Table.h :language: cmake :start-after: # add the main library :end-before: # state that anybody linking @@ -56,6 +59,7 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h :language: cmake :start-after: # state that we depend on our bin :end-before: # install rules @@ -65,6 +69,7 @@ Now let's use the generated table. First, modify ``mysqrt.cxx`` to include .. literalinclude:: Step7/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx + :name: MathFunctions/mysqrt.cxx :language: c++ :start-after: // a hack square root calculation using simple operations diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index 02f7ed13e8f..180636141f6 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -17,6 +17,7 @@ directory: .. literalinclude:: Step3/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt :language: cmake To make use of the new library we will add an :command:`add_subdirectory` @@ -27,6 +28,7 @@ last few lines of the top-level ``CMakeLists.txt`` file should now look like: .. code-block:: cmake :caption: CMakeLists.txt + :name: CMakeLists.txt-add_subdirectory # add the MathFunctions library add_subdirectory(MathFunctions) @@ -50,6 +52,7 @@ occurrence. The first step is to add an option to the top-level .. literalinclude:: Step3/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-option :language: cmake :start-after: # should we use our own math functions :end-before: # add the MathFunctions library @@ -66,6 +69,7 @@ file to look like the following: .. literalinclude:: Step3/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS :language: cmake :start-after: # add the MathFunctions library @@ -81,6 +85,7 @@ need it: .. literalinclude:: Step3/tutorial.cxx :caption: tutorial.cxx + :name: tutorial.cxx-ifdef-include :language: c++ :start-after: // should we include the MathFunctions header :end-before: int main @@ -90,6 +95,7 @@ function is used: .. literalinclude:: Step3/tutorial.cxx :caption: tutorial.cxx + :name: tutorial.cxx-ifdef-const :language: c++ :start-after: // which square root function should we use? :end-before: std::cout << "The square root of @@ -99,6 +105,7 @@ Since the source code now requires ``USE_MYMATH`` we can add it to .. literalinclude:: Step3/TutorialConfig.h.in :caption: TutorialConfig.h.in + :name: TutorialConfig.h.in-cmakedefine :language: c++ :lines: 4 diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 53f03631a2c..2fc3202e5f2 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -14,6 +14,7 @@ So to the end of ``MathFunctions/CMakeLists.txt`` we add: .. literalinclude:: Step5/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-install-TARGETS :language: cmake :start-after: # install rules @@ -21,6 +22,7 @@ And to the end of the top-level ``CMakeLists.txt`` we add: .. literalinclude:: Step5/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-install-TARGETS :language: cmake :start-after: # add the install targets :end-before: # enable testing @@ -65,6 +67,7 @@ the application is working correctly. .. literalinclude:: Step5/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-enable_testing :language: cmake :start-after: # enable testing diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst index c2bf1b5641f..91b46a77823 100644 --- a/Help/guide/tutorial/Packaging Debug and Release.rst +++ b/Help/guide/tutorial/Packaging Debug and Release.rst @@ -18,6 +18,7 @@ Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level .. literalinclude:: Complete/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-CMAKE_DEBUG_POSTFIX-variable :language: cmake :start-after: project(Tutorial VERSION 1.0) :end-before: target_compile_features(tutorial_compiler_flags @@ -26,6 +27,7 @@ And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable: .. literalinclude:: Complete/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-DEBUG_POSTFIX-property :language: cmake :start-after: # add the executable :end-before: # add the binary tree to the search path for include files @@ -36,6 +38,7 @@ Let's also add version numbering to the ``MathFunctions`` library. In .. literalinclude:: Complete/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-VERSION-properties :language: cmake :start-after: # setup the version numbering :end-before: # install rules @@ -72,6 +75,7 @@ projects to install. In this case, we want to install both debug and release. .. literalinclude:: Complete/MultiCPackConfig.cmake :caption: MultiCPackConfig.cmake + :name: MultiCPackConfig.cmake :language: cmake From the ``Step12`` directory, run :manual:`cpack ` specifying our diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst index f3a5e12d5db..5eb3e3e5f64 100644 --- a/Help/guide/tutorial/Packaging an Installer.rst +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -13,6 +13,7 @@ few lines to the bottom of our top-level ``CMakeLists.txt`` file. .. literalinclude:: Step8/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-include-CPack :language: cmake :start-after: # setup installer diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst index 85dcbf56fca..2d5f70e06af 100644 --- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -21,6 +21,7 @@ The first step is to update the starting section of the top-level .. literalinclude:: Step10/CMakeLists.txt :caption: CMakeLists.txt + :name: CMakeLists.txt-option-BUILD_SHARED_LIBS :language: cmake :end-before: # add the binary tree @@ -34,6 +35,7 @@ The end result is that ``MathFunctions/CMakeLists.txt`` should look like: .. literalinclude:: Step10/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-add_library-STATIC :language: cmake :lines: 1-36,42- @@ -42,6 +44,7 @@ Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and .. literalinclude:: Step10/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx + :name: MathFunctions/mysqrt.cxx-namespace :language: c++ We also need to make some changes in ``tutorial.cxx``, so that it no longer @@ -55,6 +58,7 @@ Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: .. literalinclude:: Step10/MathFunctions/MathFunctions.h :caption: MathFunctions/MathFunctions.h + :name: MathFunctions/MathFunctions.h :language: c++ At this point, if you build everything, you may notice that linking fails @@ -65,6 +69,7 @@ SqrtLibrary to be ``True`` no matter the build type. .. literalinclude:: Step10/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-POSITION_INDEPENDENT_CODE :language: cmake :lines: 37-42 From 2abce794096fed9a301f9f732000d62ae0bed374 Mon Sep 17 00:00:00 2001 From: Heiko Thiel Date: Fri, 18 Jun 2021 18:23:01 +0200 Subject: [PATCH 0732/1519] Help: Clarify the usage scope of source_group Fixes: #18856 --- Help/command/source_group.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Help/command/source_group.rst b/Help/command/source_group.rst index 5db1ec8c54d..a4b5bf1c6b8 100644 --- a/Help/command/source_group.rst +++ b/Help/command/source_group.rst @@ -11,6 +11,9 @@ There are two different signatures to create source groups. Defines a group into which sources will be placed in project files. This is intended to set up file tabs in Visual Studio. +The group is scoped in the directory where the command is called, +and applies to sources in targets created in that directory. + The options are: ``TREE`` From 1dd0eae4fc54e2c15176088ac6b9b7b42802b6f6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 18 Jun 2021 13:56:02 -0400 Subject: [PATCH 0733/1519] Tests: Fix xcode version detection for Xcode 13 on ARM Running `xcode -version` on an ARM box prints content to stderr: objc[...]: Class ... is implemented in both... One of the two will be used. Which one is undefined. Capture and parse only stdout. Otherwise we might configure test behavior for the wrong version of Xcode. --- Tests/BuildDepends/Project/CMakeLists.txt | 2 +- Tests/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index c2576f3e3f9..7fddf4b03eb 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -8,7 +8,7 @@ if(APPLE) else() execute_process( COMMAND xcodebuild -version - OUTPUT_VARIABLE _version ERROR_VARIABLE _version + OUTPUT_VARIABLE _version ERROR_VARIABLE _version_err ) if(_version MATCHES "^Xcode ([0-9]+(\\.[0-9]+)*)") set(CMake_TEST_XCODE_VERSION "${CMAKE_MATCH_1}") diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 8e7c04fbd0c..bb83feab413 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -321,7 +321,7 @@ if(BUILD_TESTING) else() execute_process( COMMAND xcodebuild -version - OUTPUT_VARIABLE _version ERROR_VARIABLE _version + OUTPUT_VARIABLE _version ERROR_VARIABLE _version_err ) if(_version MATCHES "^Xcode ([0-9]+(\\.[0-9]+)*)") set(CMake_TEST_XCODE_VERSION "${CMAKE_MATCH_1}") From 4e518a852a42bda0a87b3b1eeb101ca56e1e169e Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sat, 19 Jun 2021 00:01:13 -0400 Subject: [PATCH 0734/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bf802ef9980..33b11493b06 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210618) +set(CMake_VERSION_PATCH 20210619) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 93a63425b6b1625da3212c3f4f2ddec64c89b575 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Sun, 20 Jun 2021 00:02:10 -0400 Subject: [PATCH 0735/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 33b11493b06..a9e88052a07 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210619) +set(CMake_VERSION_PATCH 20210620) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 360ff17dc6e3dba2af56b13fa43b246633e13465 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sun, 20 Jun 2021 15:40:45 +1000 Subject: [PATCH 0736/1519] ExternalProject: Use ${ref}^0 to avoid MSYS/Cygwin shell substitutions In 5e941a545b (ExternalProject: Ensure git fetch if updating to hash we don't have yet, 2021-05-09), the form ${ref}^{commit} was used to ensure the ref was treated as a commit. When running under a MSYS2 or Cygwin shell, the {commit} part can be translated by the shell, leaving it as ${ref}^commit, which git doesn't understand. Use the equivalent but safer form ${ref}^0, since it won't be subject to the shell substitution issue. Fixes: #22299 --- Modules/ExternalProject-gitupdate.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/ExternalProject-gitupdate.cmake.in b/Modules/ExternalProject-gitupdate.cmake.in index 461e3235407..0de2372ecfe 100644 --- a/Modules/ExternalProject-gitupdate.cmake.in +++ b/Modules/ExternalProject-gitupdate.cmake.in @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5) function(get_hash_for_ref ref out_var err_var) execute_process( - COMMAND "@git_EXECUTABLE@" rev-parse "${ref}^{commit}" + COMMAND "@git_EXECUTABLE@" rev-parse "${ref}^0" WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code OUTPUT_VARIABLE ref_hash From 858164d15518cc6accc570b5e6cd00d162963c7a Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Mon, 21 Jun 2021 00:01:20 -0400 Subject: [PATCH 0737/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a9e88052a07..c615a6b00e1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210620) +set(CMake_VERSION_PATCH 20210621) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2e1149874d34b63cc16c7330ce1ef5ef779e5140 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Mon, 14 Jun 2021 19:57:59 +0100 Subject: [PATCH 0738/1519] cmSystemTools: Support multiple binary formats This prepares the code to handle both the ELF and XCOFF being enabled by trying to parse an ELF file first and if that fails falling back to XCOFF. --- Source/cmSystemTools.cxx | 215 +++++++++++++++++++++++++-------------- 1 file changed, 139 insertions(+), 76 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 10d2e50a4c1..488e69c5321 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -48,6 +48,8 @@ #if defined(CMake_USE_ELF_PARSER) # include "cmELF.h" +#else +class cmELF; #endif #if defined(CMake_USE_MACH_PARSER) @@ -2491,7 +2493,6 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath, return false; } -#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER) std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have, cm::string_view const& want) { @@ -2523,9 +2524,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have, // The desired rpath was not found. return std::string::npos; } -#endif -#if defined(CMake_USE_ELF_PARSER) namespace { struct cmSystemToolsRPathInfo { @@ -2539,11 +2538,19 @@ using EmptyCallback = std::function; using AdjustCallback = std::function&, const std::string&, const char*, std::string*)>; -// FIXME: Dispatch if multiple formats are supported. -bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback, - const AdjustCallback& adjustCallback, std::string* emsg, - bool* changed) +cm::optional AdjustRPathELF(std::string const& file, + const EmptyCallback& emptyCallback, + const AdjustCallback& adjustCallback, + std::string* emsg, bool* changed) { +#if !defined(CMake_USE_ELF_PARSER) + (void)file; + (void)emptyCallback; + (void)adjustCallback; + (void)emsg; + (void)changed; + return cm::nullopt; // Cannot handle ELF files. +#else if (changed) { *changed = false; } @@ -2553,6 +2560,9 @@ bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback, { // Parse the ELF binary. cmELF elf(file.c_str()); + if (!elf) { + return cm::nullopt; // Not a valid ELF file. + } // Get the RPATH and RUNPATH entries from it. int se_count = 0; @@ -2668,6 +2678,7 @@ bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback, *changed = true; } return true; +#endif } std::function MakeEmptyCallback( @@ -2679,21 +2690,26 @@ std::function MakeEmptyCallback( // okay. return true; } +#if defined(CMake_USE_ELF_PARSER) if (emsg) { *emsg = cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ", elf.GetErrorMessage()); } +#else + static_cast(emsg); + static_cast(elf); +#endif return false; }; -}; +} } -bool cmSystemTools::ChangeRPath(std::string const& file, - std::string const& oldRPath, - std::string const& newRPath, - bool removeEnvironmentRPath, std::string* emsg, - bool* changed) +cm::optional ChangeRPathELF(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, + std::string* emsg, bool* changed) { auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath]( cm::optional& outRPath, @@ -2741,13 +2757,13 @@ bool cmSystemTools::ChangeRPath(std::string const& file, return true; }; - return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, - changed); + return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback, + emsg, changed); } -bool cmSystemTools::SetRPath(std::string const& file, - std::string const& newRPath, std::string* emsg, - bool* changed) +static cm::optional SetRPathELF(std::string const& file, + std::string const& newRPath, + std::string* emsg, bool* changed) { auto adjustCallback = [newRPath](cm::optional& outRPath, const std::string& inRPath, @@ -2759,22 +2775,31 @@ bool cmSystemTools::SetRPath(std::string const& file, return true; }; - return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, - changed); + return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback, + emsg, changed); } -#elif defined(CMake_USE_XCOFF_PARSER) -bool cmSystemTools::ChangeRPath(std::string const& file, - std::string const& oldRPath, - std::string const& newRPath, - bool removeEnvironmentRPath, std::string* emsg, - bool* changed) +static cm::optional ChangeRPathXCOFF(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, + std::string* emsg, bool* changed) { if (changed) { *changed = false; } - +#if !defined(CMake_USE_XCOFF_PARSER) + (void)file; + (void)oldRPath; + (void)newRPath; + (void)removeEnvironmentRPath; + (void)emsg; + return cm::nullopt; +#else bool chg = false; cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite); + if (!xcoff) { + return cm::nullopt; // Not a valid XCOFF file + } if (cm::optional maybeLibPath = xcoff.GetLibPath()) { cm::string_view libPath = *maybeLibPath; // Make sure the current rpath contains the old rpath. @@ -2830,31 +2855,47 @@ bool cmSystemTools::ChangeRPath(std::string const& file, *changed = chg; } return true; +#endif } -bool cmSystemTools::SetRPath(std::string const& /*file*/, - std::string const& /*newRPath*/, - std::string* /*emsg*/, bool* /*changed*/) +static cm::optional SetRPathXCOFF(std::string const& /*file*/, + std::string const& /*newRPath*/, + std::string* /*emsg*/, + bool* /*changed*/) { - return false; + return cm::nullopt; // Not implemented. } -#else -bool cmSystemTools::ChangeRPath(std::string const& /*file*/, - std::string const& /*oldRPath*/, - std::string const& /*newRPath*/, - bool /*removeEnvironmentRPath*/, - std::string* /*emsg*/, bool* /*changed*/) + +bool cmSystemTools::ChangeRPath(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, std::string* emsg, + bool* changed) { + if (cm::optional result = ChangeRPathELF( + file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) { + return result.value(); + } + if (cm::optional result = ChangeRPathXCOFF( + file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) { + return result.value(); + } return false; } -bool cmSystemTools::SetRPath(std::string const& /*file*/, - std::string const& /*newRPath*/, - std::string* /*emsg*/, bool* /*changed*/) +bool cmSystemTools::SetRPath(std::string const& file, + std::string const& newRPath, std::string* emsg, + bool* changed) { + if (cm::optional result = SetRPathELF(file, newRPath, emsg, changed)) { + return result.value(); + } + if (cm::optional result = + SetRPathXCOFF(file, newRPath, emsg, changed)) { + return result.value(); + } return false; } -#endif bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, const char* lhss, const char* rhss) @@ -2989,11 +3030,15 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs) return cm_strverscmp(lhs.c_str(), rhs.c_str()); } -// FIXME: Dispatch if multiple formats are supported. -#if defined(CMake_USE_ELF_PARSER) -bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, - bool* removed) +static cm::optional RemoveRPathELF(std::string const& file, + std::string* emsg, bool* removed) { +#if !defined(CMake_USE_ELF_PARSER) + (void)file; + (void)emsg; + (void)removed; + return cm::nullopt; // Cannot handle ELF files. +#else if (removed) { *removed = false; } @@ -3005,6 +3050,9 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, { // Parse the ELF binary. cmELF elf(file.c_str()); + if (!elf) { + return cm::nullopt; // Not a valid ELF file. + } // Get the RPATH and RUNPATH entries from it and sort them by index // in the dynamic section header. @@ -3130,16 +3178,24 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, *removed = true; } return true; +#endif } -#elif defined(CMake_USE_XCOFF_PARSER) -bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, - bool* removed) + +static cm::optional RemoveRPathXCOFF(std::string const& file, + std::string* emsg, bool* removed) { if (removed) { *removed = false; } - +#if !defined(CMake_USE_XCOFF_PARSER) + (void)file; + (void)emsg; + return cm::nullopt; // Cannot handle XCOFF files. +#else cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite); + if (!xcoff) { + return cm::nullopt; // Not a valid XCOFF file. + } bool rm = xcoff.RemoveLibPath(); if (!xcoff) { if (emsg) { @@ -3152,55 +3208,62 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, *removed = rm; } return true; +#endif } -#else -bool cmSystemTools::RemoveRPath(std::string const& /*file*/, - std::string* /*emsg*/, bool* /*removed*/) +bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, + bool* removed) { + if (cm::optional result = RemoveRPathELF(file, emsg, removed)) { + return result.value(); + } + if (cm::optional result = RemoveRPathXCOFF(file, emsg, removed)) { + return result.value(); + } return false; } -#endif -// FIXME: Dispatch if multiple formats are supported. bool cmSystemTools::CheckRPath(std::string const& file, std::string const& newRPath) { #if defined(CMake_USE_ELF_PARSER) // Parse the ELF binary. cmELF elf(file.c_str()); - - // Get the RPATH or RUNPATH entry from it. - cmELF::StringEntry const* se = elf.GetRPath(); - if (!se) { - se = elf.GetRunPath(); - } - - // Make sure the current rpath contains the new rpath. - if (newRPath.empty()) { + if (elf) { + // Get the RPATH or RUNPATH entry from it. + cmELF::StringEntry const* se = elf.GetRPath(); if (!se) { - return true; + se = elf.GetRunPath(); } - } else { - if (se && - cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) { - return true; + + // Make sure the current rpath contains the new rpath. + if (newRPath.empty()) { + if (!se) { + return true; + } + } else { + if (se && + cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) { + return true; + } } + return false; } - return false; -#elif defined(CMake_USE_XCOFF_PARSER) +#endif +#if defined(CMake_USE_XCOFF_PARSER) // Parse the XCOFF binary. cmXCOFF xcoff(file.c_str()); - if (cm::optional libPath = xcoff.GetLibPath()) { - if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) { - return true; + if (xcoff) { + if (cm::optional libPath = xcoff.GetLibPath()) { + if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) { + return true; + } } + return false; } - return false; -#else +#endif (void)file; (void)newRPath; return false; -#endif } bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir) From 25e82666e42cb3bdcac52e60067960c34ff50f5e Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jun 2021 11:20:33 -0400 Subject: [PATCH 0739/1519] Help: Add 3.20 release note section for 3.20.{3,4,5} Make it clear that the notes for these patch releases were not forgotten, and that there were simply no changes to documented features or interfaces. --- Help/release/3.20.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst index f77304fcffd..da27174d7bc 100644 --- a/Help/release/3.20.rst +++ b/Help/release/3.20.rst @@ -362,3 +362,10 @@ Changes made since CMake 3.20.0 include the following. a special case to recognize oneAPI 2021.1 Fortran as ``IntelLLVM``. The oneAPI 2021.2 Fortran compiler defines the proper identification macro and so is identified as ``IntelLLVM`` by all CMake 3.20 versions. + +3.20.3, 3.20.4, 3.20.5 +---------------------- + +These versions made no changes to documented features or interfaces. +Some implementation updates were made to support ecosystem changes +and/or fix regressions. From efa5e1f367ac76cb7aa919929ece1f4799cdc4b2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jun 2021 11:23:19 -0400 Subject: [PATCH 0740/1519] CMake 3.20.5 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 47107996224..1e17de9229c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 4) +set(CMake_VERSION_PATCH 5) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ea02397dab2289a58326c0701e8d2b4da4361252 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Tue, 22 Jun 2021 00:01:10 -0400 Subject: [PATCH 0741/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c615a6b00e1..d7cb1f479df 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210621) +set(CMake_VERSION_PATCH 20210622) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1d9009c27a5999f7793871e7f034ecdc3e8b280d Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Mon, 21 Jun 2021 21:25:12 -0400 Subject: [PATCH 0742/1519] CUDA: Implement CMAKE_USER_MAKE_RULES_OVERRIDE[_CUDA] This is implemented by other languages, and is documented for all languages. This was accidentally left out of CUDA. --- Modules/CMakeCUDAInformation.cmake | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 541d207f84a..a2946f45841 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -36,6 +36,25 @@ if(CMAKE_CUDA_COMPILER_ID) endif() +# This should be included before the _INIT variables are +# used to initialize the cache. Since the rule variables +# have if blocks on them, users can still define them here. +# But, it should still be after the platform file so changes can +# be made to those values. + +if(CMAKE_USER_MAKE_RULES_OVERRIDE) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}") +endif() + +if(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA "${_override}") +endif() + + if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_CUDA_FLAG) set(CMAKE_SHARED_LIBRARY_RUNTIME_CUDA_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}) endif() From cadf2b632e6a09945ef4907e96e66fb3aa922e0c Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Mon, 21 Jun 2021 17:35:03 +0100 Subject: [PATCH 0743/1519] Fix -Wpessimizing-move warnings in QCMake::loadPresets() --- Source/QtDialog/QCMake.cxx | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index e6faef47033..859c18dad30 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -550,17 +550,14 @@ void QCMake::loadPresets() } QCMakePreset preset; - preset.name = std::move(QString::fromLocal8Bit(p.Name.data())); - preset.displayName = - std::move(QString::fromLocal8Bit(p.DisplayName.data())); - preset.description = - std::move(QString::fromLocal8Bit(p.Description.data())); - preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data())); - preset.architecture = - std::move(QString::fromLocal8Bit(p.Architecture.data())); + preset.name = QString::fromLocal8Bit(p.Name.data()); + preset.displayName = QString::fromLocal8Bit(p.DisplayName.data()); + preset.description = QString::fromLocal8Bit(p.Description.data()); + preset.generator = QString::fromLocal8Bit(p.Generator.data()); + preset.architecture = QString::fromLocal8Bit(p.Architecture.data()); preset.setArchitecture = !p.ArchitectureStrategy || p.ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set; - preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data())); + preset.toolset = QString::fromLocal8Bit(p.Toolset.data()); preset.setToolset = !p.ToolsetStrategy || p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set; preset.enabled = it.Expanded && it.Expanded->ConditionResult && From 88e56c2e5aa5a89c646250c42412a96d181f7aa7 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Mon, 21 Jun 2021 15:46:37 +0100 Subject: [PATCH 0744/1519] Enable compiler warnings when compiling CMake with Clang I noticed that I wasn't getting any compiler warnings when testing my merge requests locally. Turns out this happens because I am compiling using Clang rather than GCC, so no warning flags are added to the build. d06a9bdf3ab47231cc91b78dac77bd50de390565 enabled warnings by default for GCC > 4.2, but Clang supports them too. This has been the case since at least Clang 3.0 (I couldn't test any older versions on godbolt.org). For AppleClang, we can also assume that the warning flags are supported. According to Wikipedia Clang became the default compiler starting with Xcode 4.2, and the table on https://trac.macports.org/wiki/XcodeVersionInfo, states that XCode 4.2 Clang was based on upstream Clang 3.0, which supports all the warning flags. The warning flags are currently not added when compiling with clang-cl since this exposes some pre-existing warnings that need to be fixed first. --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44b433ac8f2..6016cd654db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -812,8 +812,12 @@ CMAKE_SETUP_TESTING() if(NOT CMake_TEST_EXTERNAL_CMAKE) if(NOT CMake_VERSION_IS_RELEASE) - if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND - NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2) + if((CMAKE_C_COMPILER_ID STREQUAL "GNU" AND + NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2) OR + (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND + NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 3.0 AND + NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") OR + CMAKE_C_COMPILER_ID STREQUAL "AppleClang") set(C_FLAGS_LIST -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common -Wundef From fd2aa87278b06b996a8843e0cb1b17d9e8a94716 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Wed, 23 Jun 2021 00:01:09 -0400 Subject: [PATCH 0745/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d7cb1f479df..894f119d66d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210622) +set(CMake_VERSION_PATCH 20210623) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0aae790a5edc2f8cc7501f61c011409c55d32d89 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 23 Jun 2021 09:01:47 -0400 Subject: [PATCH 0746/1519] CMake 3.21.0-rc1 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ad174a7687a..6e24a6147ab 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 0) +set(CMake_VERSION_RC 1) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 0106842af437923eb92d5077105631dc575ed51b Mon Sep 17 00:00:00 2001 From: Heiko Thiel Date: Wed, 23 Jun 2021 17:24:09 +0200 Subject: [PATCH 0747/1519] Help: Clarify condition of tree command from source_group. --- Help/command/source_group.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Help/command/source_group.rst b/Help/command/source_group.rst index a4b5bf1c6b8..83ae2864cfc 100644 --- a/Help/command/source_group.rst +++ b/Help/command/source_group.rst @@ -22,7 +22,8 @@ The options are: CMake will automatically detect, from ```` files paths, source groups it needs to create, to keep structure of source groups analogically to the actual files and directories structure in the project. Paths of ```` - files will be cut to be relative to ````. + files will be cut to be relative to ````. The command fails if the + paths within ``src`` do not start with ``root``. ``PREFIX`` .. versionadded:: 3.8 From a4b6743a3bba9c591a7750facec2627934879ff0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 23 Jun 2021 12:41:07 -0400 Subject: [PATCH 0748/1519] bootstrap: Compile with _FILE_OFFSET_BITS=64 on Linux To avoid problems accessing filesystem, explicitly use 64-bit file offsets in case the compilation model is 32-bit. This change was made for the main CMake build by commit 5b10f96793 (Linux: Compile with _FILE_OFFSET_BITS=64 on 32-bit Linux, 2020-09-23, v3.19.0-rc1~112^2), but conditionally on 32-bit Linux. For bootstrap, just always add the definition instead of trying to detect the architecture. Fixes: #22328 --- bootstrap | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bootstrap b/bootstrap index f8d2f693c2f..dc5ed0b4776 100755 --- a/bootstrap +++ b/bootstrap @@ -1747,6 +1747,16 @@ if test "x${cmake_ansi_cxx_flags}" != "x"; then cmake_cxx_flags="${cmake_ansi_cxx_flags} ${cmake_cxx_flags}" fi +system_flags='' +case "${cmake_system}" in + # Ensure filesystem access uses 64-bit offsets even on 32-bit hosts. + *Linux*) system_flags='-D_FILE_OFFSET_BITS=64' ;; +esac +if test "x${system_flags}" != "x"; then + cmake_c_flags="${cmake_c_flags} ${system_flags}" + cmake_cxx_flags="${cmake_cxx_flags} ${system_flags}" +fi + if test "x${cmake_c_flags}" != "x"; then cmake_c_flags="${cmake_c_flags} " fi From 18038042ed16cfbc7515c42f01652c17f0d65dbc Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 23 Jun 2021 13:33:05 -0400 Subject: [PATCH 0749/1519] cmelf: Add script to import the FreeBSD ELF headers These headers will be used to provide the ELF parsing code on all host operating systems (including those that don't have an ELF header, e.g. macOS). This will also allow removing various OS-dependent #ifdefs from the cmELF code. Add a script that was used to automate this import. Co-authored-by: Alex Richardson --- Utilities/Scripts/update-elf.bash | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 Utilities/Scripts/update-elf.bash diff --git a/Utilities/Scripts/update-elf.bash b/Utilities/Scripts/update-elf.bash new file mode 100755 index 00000000000..1a065bad8bd --- /dev/null +++ b/Utilities/Scripts/update-elf.bash @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -e +set -x +shopt -s dotglob + +readonly name="elf" +readonly ownership="FreeBSD Upstream " +readonly subtree="Utilities/cmelf" +readonly repo="https://github.com/freebsd/freebsd-src.git" +readonly tag="main" +readonly shortlog=false +readonly paths=" + sys/sys/elf32.h + sys/sys/elf64.h + sys/sys/elf_common.h +" + +extract_source () { + git_archive + pushd "${extractdir}/${name}-reduced" + echo "* -whitespace" > .gitattributes + mv sys/sys/* . + sed -i -e 's//"elf_common.h"/g' -e 's/u_int32_t/uint32_t/g' *.h + popd +} + +. "${BASH_SOURCE%/*}/update-third-party.bash" From 7a0a37ca41924bb46b850db1e3d19d84d4757f3d Mon Sep 17 00:00:00 2001 From: FreeBSD Upstream Date: Wed, 23 Jun 2021 10:39:18 -0600 Subject: [PATCH 0750/1519] elf 2021-06-23 (f13da247) Code extracted from: https://github.com/freebsd/freebsd-src.git at commit f13da24715a75ce0fdac31062866877d980aa908 (main). --- .gitattributes | 1 + elf32.h | 265 +++++++++ elf64.h | 269 +++++++++ elf_common.h | 1492 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 2027 insertions(+) create mode 100644 .gitattributes create mode 100644 elf32.h create mode 100644 elf64.h create mode 100644 elf_common.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..562b12e16eb --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/elf32.h b/elf32.h new file mode 100644 index 00000000000..20d2ec254c6 --- /dev/null +++ b/elf32.h @@ -0,0 +1,265 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint64_t Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Shared object information, found in SHT_MIPS_LIBLIST. + */ + +typedef struct { + Elf32_Word l_name; /* The name of a shared object. */ + Elf32_Word l_time_stamp; /* 32-bit timestamp. */ + Elf32_Word l_checksum; /* Checksum of visible symbols, sizes. */ + Elf32_Word l_version; /* Interface version string index. */ + Elf32_Word l_flags; /* Flags (LL_*). */ +} Elf32_Lib; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +typedef struct { + Elf32_Word ch_type; + Elf32_Word ch_size; + Elf32_Word ch_addralign; +} Elf32_Chdr; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/elf64.h b/elf64.h new file mode 100644 index 00000000000..6efe147163c --- /dev/null +++ b/elf64.h @@ -0,0 +1,269 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Shared object information, found in SHT_MIPS_LIBLIST. + */ + +typedef struct { + Elf64_Word l_name; /* The name of a shared object. */ + Elf64_Word l_time_stamp; /* 64-bit timestamp. */ + Elf64_Word l_checksum; /* Checksum of visible symbols, sizes. */ + Elf64_Word l_version; /* Interface version string index. */ + Elf64_Word l_flags; /* Flags (LL_*). */ +} Elf64_Lib; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +typedef struct { + Elf64_Word ch_type; + Elf64_Word ch_reserved; + Elf64_Xword ch_size; + Elf64_Xword ch_addralign; +} Elf64_Chdr; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/elf_common.h b/elf_common.h new file mode 100644 index 00000000000..395c45b58e4 --- /dev/null +++ b/elf_common.h @@ -0,0 +1,1492 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2017, 2018 Dell EMC + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +#ifndef LOCORE +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; +typedef Elf_Note Elf_Nhdr; +#endif + +/* + * Option kinds. + */ +#define ODK_NULL 0 /* undefined */ +#define ODK_REGINFO 1 /* register usage info */ +#define ODK_EXCEPTIONS 2 /* exception processing info */ +#define ODK_PAD 3 /* section padding */ +#define ODK_HWPATCH 4 /* hardware patch applied */ +#define ODK_FILL 5 /* fill value used by the linker */ +#define ODK_TAGS 6 /* reserved space for tools */ +#define ODK_HWAND 7 /* hardware AND patch applied */ +#define ODK_HWOR 8 /* hardware OR patch applied */ +#define ODK_GP_GROUP 9 /* GP group for text/data sections */ +#define ODK_IDENT 10 /* ID information */ +#define ODK_PAGESIZE 11 /* page size information */ + +/* + * ODK_EXCEPTIONS info field masks. + */ +#define OEX_FPU_MIN 0x0000001f /* min FPU exception required */ +#define OEX_FPU_MAX 0x00001f00 /* max FPU exception allowed */ +#define OEX_PAGE0 0x00010000 /* page zero must be mapped */ +#define OEX_SMM 0x00020000 /* run in sequential memory mode */ +#define OEX_PRECISEFP 0x00040000 /* run in precise FP exception mode */ +#define OEX_DISMISS 0x00080000 /* dismiss invalid address traps */ + +/* + * ODK_PAD info field masks. + */ +#define OPAD_PREFIX 0x0001 +#define OPAD_POSTFIX 0x0002 +#define OPAD_SYMBOL 0x0004 + +/* + * ODK_HWPATCH info field masks. + */ +#define OHW_R4KEOP 0x00000001 /* patch for R4000 branch at end-of-page bug */ +#define OHW_R8KPFETCH 0x00000002 /* R8000 prefetch bug may occur */ +#define OHW_R5KEOP 0x00000004 /* patch for R5000 branch at end-of-page bug */ +#define OHW_R5KCVTL 0x00000008 /* R5000 cvt.[ds].l bug: clean == 1 */ +#define OHW_R10KLDL 0x00000010UL /* need patch for R10000 misaligned load */ + +/* + * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks. + */ +#define OHWA0_R4KEOP_CHECKED 0x00000001 /* object checked for R4000 end-of-page bug */ +#define OHWA0_R4KEOP_CLEAN 0x00000002 /* object verified clean for R4000 end-of-page bug */ +#define OHWO0_FIXADE 0x00000001 /* object requires call to fixade */ + +/* + * ODK_IDENT/ODK_GP_GROUP info field masks. + */ +#define OGP_GROUP 0x0000ffff /* GP group number */ +#define OGP_SELF 0x00010000 /* GP group is self-contained */ + +/* + * The header for GNU-style hash sections. + */ + +#ifndef LOCORE +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; +#endif + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_FENIXOS 16 /* FenixOS */ +#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */ +#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */ +#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ +#define ELFOSABI_GNU ELFOSABI_LINUX + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_IAMCU 6 /* Intel MCU. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. + and MPRC of Peking University */ +#define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ +#define EM_RISCV 243 /* RISC-V */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/** + * e_flags + */ +#define EF_ARM_RELEXEC 0x1 +#define EF_ARM_HASENTRY 0x2 +#define EF_ARM_SYMSARESORTED 0x4 +#define EF_ARM_DYNSYMSUSESEGIDX 0x8 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_LE8 0x00400000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_EABIMASK 0xFF000000 +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 +#define EF_ARM_INTERWORK 0x00000004 +#define EF_ARM_APCS_26 0x00000008 +#define EF_ARM_APCS_FLOAT 0x00000010 +#define EF_ARM_PIC 0x00000020 +#define EF_ARM_ALIGN8 0x00000040 +#define EF_ARM_NEW_ABI 0x00000080 +#define EF_ARM_OLD_ABI 0x00000100 +#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 +#define EF_ARM_SOFT_FLOAT EF_ARM_ABI_FLOAT_SOFT /* Pre-V5 ABI name */ +#define EF_ARM_ABI_FLOAT_HARD 0x00000400 +#define EF_ARM_VFP_FLOAT EF_ARM_ABI_FLOAT_HARD /* Pre-V5 ABI name */ +#define EF_ARM_MAVERICK_FLOAT 0x00000800 + +#define EF_MIPS_NOREORDER 0x00000001 +#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ +#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */ +#define EF_MIPS_UCODE 0x00000010 +#define EF_MIPS_ABI2 0x00000020 /* N32 */ +#define EF_MIPS_OPTIONS_FIRST 0x00000080 +#define EF_MIPS_ABI 0x0000F000 +#define EF_MIPS_ABI_O32 0x00001000 +#define EF_MIPS_ABI_O64 0x00002000 +#define EF_MIPS_ABI_EABI32 0x00003000 +#define EF_MIPS_ABI_EABI64 0x00004000 +#define EF_MIPS_ARCH_ASE 0x0F000000 /* Architectural extensions */ +#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* MDMX multimedia extension */ +#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* MIPS-16 ISA extensions */ +#define EF_MIPS_ARCH 0xF0000000 /* Architecture field */ +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code */ +#define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code */ +#define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code */ +#define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code */ +#define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code */ + +#define EF_PPC_EMB 0x80000000 +#define EF_PPC_RELOCATABLE 0x00010000 +#define EF_PPC_RELOCATABLE_LIB 0x00008000 + +#define EF_RISCV_RVC 0x00000001 +#define EF_RISCV_FLOAT_ABI_MASK 0x00000006 +#define EF_RISCV_FLOAT_ABI_SOFT 0x00000000 +#define EF_RISCV_FLOAT_ABI_SINGLE 0x000002 +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x000004 +#define EF_RISCV_FLOAT_ABI_QUAD 0x00000006 +#define EF_RISCV_RVE 0x00000008 +#define EF_RISCV_TSO 0x00000010 + +#define EF_SPARC_EXT_MASK 0x00ffff00 +#define EF_SPARC_32PLUS 0x00000100 +#define EF_SPARC_SUN_US1 0x00000200 +#define EF_SPARC_HAL_R1 0x00000200 +#define EF_SPARC_SUN_US3 0x00000800 + +#define EF_SPARCV9_MM 0x00000003 +#define EF_SPARCV9_TSO 0x00000000 +#define EF_SPARCV9_PSO 0x00000001 +#define EF_SPARCV9_RMO 0x00000002 + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_FBSD_CACHED SHN_LOOS /* Transient, for sys/kern/link_elf_obj + linker only: Cached global in local + symtab. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_X86_64_UNWIND 0x70000001 /* unwind information */ +#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND + +#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking + pre-emption map. */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility + attributes. */ +#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ +#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ +#define SHT_MIPS_LIBLIST 0x70000000 +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 +#define SHT_MIPS_GPTAB 0x70000003 +#define SHT_MIPS_UCODE 0x70000004 +#define SHT_MIPS_DEBUG 0x70000005 +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 +#define SHT_MIPS_ABIFLAGS 0x7000002a + +#define SHT_SPARC_GOTDATA 0x70000000 + +#define SHTORDERED +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_COMPRESSED 0x800 /* Section contains compressed data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Flags for section groups. */ +#define GRP_COMDAT 0x1 /* COMDAT semantics. */ + +/* + * Flags / mask for .gnu.versym sections. + */ +#define VERSYM_VERSION 0x7fff +#define VERSYM_HIDDEN 0x8000 + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_DUMP_DELTA 0x6fb5d000 /* va->pa map for kernel dumps + (currently arm). */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_ARM_ARCHEXT 0x70000000 /* ARM arch compat information. */ +#define PT_ARM_EXIDX 0x70000001 /* ARM exception unwind tables. */ +#define PT_MIPS_REGINFO 0x70000000 /* MIPS register usage info */ +#define PT_MIPS_RTPROC 0x70000001 /* MIPS runtime procedure tbl */ +#define PT_MIPS_OPTIONS 0x70000002 /* MIPS e_flags value*/ +#define PT_MIPS_ABIFLAGS 0x70000003 /* MIPS fp mode */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +#define PT_OPENBSD_RANDOMIZE 0x65A3DBE6 /* OpenBSD random data segment */ +#define PT_OPENBSD_WXNEEDED 0x65A3DBE7 /* OpenBSD EXEC/WRITE pages needed */ +#define PT_OPENBSD_BOOTDATA 0x65A41BE6 /* OpenBSD section for boot args */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + termination functions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', odd == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_SUNW_ASLR 0x60000023 /* ASLR control */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE 0x6ffffdfc /* feature holder */ +#define DT_FEATURE_1 DT_FEATURE +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_TLSDESC_PLT 0x6ffffef6 /* loc. of PLT for tlsdesc resolver */ +#define DT_TLSDESC_GOT 0x6ffffef7 /* loc. of GOT for tlsdesc resolver */ +#define DT_GNU_CONFLICT 0x6ffffef8 /* address of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* address of library list */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ + +#define DT_ARM_SYMTABSZ 0x70000001 +#define DT_ARM_PREEMPTMAP 0x70000002 + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 + +#define DT_MIPS_RLD_VERSION 0x70000001 +#define DT_MIPS_TIME_STAMP 0x70000002 +#define DT_MIPS_ICHECKSUM 0x70000003 +#define DT_MIPS_IVERSION 0x70000004 +#define DT_MIPS_FLAGS 0x70000005 +#define DT_MIPS_BASE_ADDRESS 0x70000006 +#define DT_MIPS_CONFLICT 0x70000008 +#define DT_MIPS_LIBLIST 0x70000009 +#define DT_MIPS_LOCAL_GOTNO 0x7000000a +#define DT_MIPS_CONFLICTNO 0x7000000b +#define DT_MIPS_LIBLISTNO 0x70000010 +#define DT_MIPS_SYMTABNO 0x70000011 +#define DT_MIPS_UNREFEXTNO 0x70000012 +#define DT_MIPS_GOTSYM 0x70000013 +#define DT_MIPS_HIPAGENO 0x70000014 +#define DT_MIPS_RLD_MAP 0x70000016 +#define DT_MIPS_DELTA_CLASS 0x70000017 +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 +#define DT_MIPS_DELTA_INSTANCE 0x70000019 +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001A +#define DT_MIPS_DELTA_RELOC 0x7000001B +#define DT_MIPS_DELTA_RELOC_NO 0x7000001C +#define DT_MIPS_DELTA_SYM 0x7000001D +#define DT_MIPS_DELTA_SYM_NO 0x7000001E +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 +#define DT_MIPS_CXX_FLAGS 0x70000022 +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 +#define DT_MIPS_INTERFACE 0x7000002A +#define DT_MIPS_DYNSTR_ALIGN 0x7000002B +#define DT_MIPS_INTERFACE_SIZE 0x7000002C +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002D +#define DT_MIPS_PERF_SUFFIX 0x7000002E +#define DT_MIPS_COMPACT_SIZE 0x7000002F +#define DT_MIPS_GP_VALUE 0x70000030 +#define DT_MIPS_AUX_DYNAMIC 0x70000031 +#define DT_MIPS_PLTGOT 0x70000032 +#define DT_MIPS_RLD_OBJ_UPDATE 0x70000033 +#define DT_MIPS_RWPLT 0x70000034 +#define DT_MIPS_RLD_MAP_REL 0x70000035 + +#define DT_PPC_GOT 0x70000000 +#define DT_PPC_TLSOPT 0x70000001 + +#define DT_PPC64_GLINK 0x70000000 +#define DT_PPC64_OPD 0x70000001 +#define DT_PPC64_OPDSZ 0x70000002 +#define DT_PPC64_TLSOPT 0x70000003 + +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ +#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ +#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ +#define DF_1_PIE 0x08000000 /* Is position-independent executable */ + +/* Values for l_flags. */ +#define LL_NONE 0x0 /* no flags */ +#define LL_EXACT_MATCH 0x1 /* require an exact match */ +#define LL_IGNORE_INT_VER 0x2 /* ignore version incompatibilities */ +#define LL_REQUIRE_MINOR 0x4 +#define LL_EXPORTS 0x8 +#define LL_DELAY_LOAD 0x10 +#define LL_DELTA 0x20 + +/* Note section names */ +#define ELF_NOTE_FREEBSD "FreeBSD" +#define ELF_NOTE_NETBSD "NetBSD" +#define ELF_NOTE_SOLARIS "SUNW Solaris" +#define ELF_NOTE_GNU "GNU" + +/* Values for n_type used in executables. */ +#define NT_FREEBSD_ABI_TAG 1 +#define NT_FREEBSD_NOINIT_TAG 2 +#define NT_FREEBSD_ARCH_TAG 3 +#define NT_FREEBSD_FEATURE_CTL 4 + +/* NT_FREEBSD_FEATURE_CTL desc[0] bits */ +#define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001 +#define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002 +#define NT_FREEBSD_FCTL_STKGAP_DISABLE 0x00000004 +#define NT_FREEBSD_FCTL_WXNEEDED 0x00000008 +#define NT_FREEBSD_FCTL_LA48 0x00000010 +#define NT_FREEBSD_FCTL_ASG_DISABLE 0x00000020 /* ASLR STACK GAP Disable */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ +#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */ +#define NT_PROCSTAT_FILES 9 /* Procstat files data. */ +#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ +#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */ +#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */ +#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ +#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ +#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ +#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ +#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */ +#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */ +#define NT_ARM_VFP 0x400 /* ARM VFP registers */ + +/* GNU note types. */ +#define NT_GNU_ABI_TAG 1 +#define NT_GNU_HWCAP 2 +#define NT_GNU_BUILD_ID 3 +#define NT_GNU_GOLD_VERSION 4 +#define NT_GNU_PROPERTY_TYPE_0 5 + +#define GNU_PROPERTY_LOPROC 0xc0000000 +#define GNU_PROPERTY_HIPROC 0xdfffffff + +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 + +#define GNU_PROPERTY_X86_FEATURE_1_IBT 0x00000001 +#define GNU_PROPERTY_X86_FEATURE_1_SHSTK 0x00000002 + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Start of operating system reserved range. */ +#define STB_GNU_UNIQUE 10 /* Unique symbol (GNU) */ +#define STB_HIOS 12 /* End of operating system reserved range. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* Start of processor reserved range. */ +#define STT_SPARC_REGISTER 13 /* SPARC register information. */ +#define STT_HIPROC 15 /* End of processor reserved range. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* Values for ch_type (compressed section headers). */ +#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE */ +#define ELFCOMPRESS_LOOS 0x60000000 /* OS-specific */ +#define ELFCOMPRESS_HIOS 0x6fffffff +#define ELFCOMPRESS_LOPROC 0x70000000 /* Processor-specific */ +#define ELFCOMPRESS_HIPROC 0x7fffffff + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags. */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP. */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ +#define AT_TIMEKEEP 22 /* Pointer to timehands. */ +#define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ +#define AT_HWCAP 25 /* CPU feature flags. */ +#define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ +#define AT_ARGC 28 /* Argument count */ +#define AT_ARGV 29 /* Argument vector */ +#define AT_ENVC 30 /* Environment count */ +#define AT_ENVV 31 /* Environment vector */ +#define AT_PS_STRINGS 32 /* struct ps_strings */ +#define AT_FXRNG 33 /* Pointer to root RNG seed version. */ + +#define AT_COUNT 34 /* Count of defined aux entry types. */ + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_SIZE32 38 +#define R_386_TLS_GOTDESC 39 +#define R_386_TLS_DESC_CALL 40 +#define R_386_TLS_DESC 41 +#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ +#define R_386_GOT32X 43 + +#define R_AARCH64_NONE 0 /* No relocation */ +#define R_AARCH64_ABS64 257 /* Absolute offset */ +#define R_AARCH64_ABS32 258 /* Absolute, 32-bit overflow check */ +#define R_AARCH64_ABS16 259 /* Absolute, 16-bit overflow check */ +#define R_AARCH64_PREL64 260 /* PC relative */ +#define R_AARCH64_PREL32 261 /* PC relative, 32-bit overflow check */ +#define R_AARCH64_PREL16 262 /* PC relative, 16-bit overflow check */ +#define R_AARCH64_TSTBR14 279 /* TBZ/TBNZ immediate */ +#define R_AARCH64_CONDBR19 280 /* Conditional branch immediate */ +#define R_AARCH64_JUMP26 282 /* Branch immediate */ +#define R_AARCH64_CALL26 283 /* Call immediate */ +#define R_AARCH64_COPY 1024 /* Copy data from shared object */ +#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ +#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ +#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ +#define R_AARCH64_TLS_DTPREL64 1028 +#define R_AARCH64_TLS_DTPMOD64 1029 +#define R_AARCH64_TLS_TPREL64 1030 +#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ +#define R_AARCH64_IRELATIVE 1032 + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_64 18 /* Direct 64 bit */ +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 /* GOT HI 16 bit */ +#define R_MIPS_GOT_LO16 23 /* GOT LO 16 bit */ +#define R_MIPS_SUB 24 +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ +#define R_MIPS_JALR 37 +#define R_MIPS_TLS_GD 42 +#define R_MIPS_COPY 126 +#define R_MIPS_JUMP_SLOT 127 + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 +#define R_PPC_IRELATIVE 248 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +/* + * RISC-V relocation types. + */ + +/* Relocation types used by the dynamic linker. */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 + +/* Relocation types not used by the dynamic linker. */ +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 +#define R_RISCV_32_PCREL 57 +#define R_RISCV_IRELATIVE 58 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_PC64 24 /* PC-relative 64 bit signed sym value. */ +#define R_X86_64_GOTOFF64 25 +#define R_X86_64_GOTPC32 26 +#define R_X86_64_GOT64 27 +#define R_X86_64_GOTPCREL64 28 +#define R_X86_64_GOTPC64 29 +#define R_X86_64_GOTPLT64 30 +#define R_X86_64_PLTOFF64 31 +#define R_X86_64_SIZE32 32 +#define R_X86_64_SIZE64 33 +#define R_X86_64_GOTPC32_TLSDESC 34 +#define R_X86_64_TLSDESC_CALL 35 +#define R_X86_64_TLSDESC 36 +#define R_X86_64_IRELATIVE 37 +#define R_X86_64_RELATIVE64 38 +/* 39 and 40 were BND-related, already decomissioned */ +#define R_X86_64_GOTPCRELX 41 +#define R_X86_64_REX_GOTPCRELX 42 + +#define ELF_BSDF_SIGFASTBLK 0x0001 /* Kernel supports fast sigblock */ + +#endif /* !_SYS_ELF_COMMON_H_ */ From 55d9199f7c67237837724bd8b317bd99a904e515 Mon Sep 17 00:00:00 2001 From: Kitware Robot Date: Thu, 24 Jun 2021 00:01:11 -0400 Subject: [PATCH 0751/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 894f119d66d..554e9a943c3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210623) +set(CMake_VERSION_PATCH 20210624) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From fe3f846e1b88341529686ee7dd334b01fe9e705e Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Thu, 19 Nov 2020 11:33:23 -0600 Subject: [PATCH 0752/1519] Makefiles: Add support for building Fortran intrinsics Fixes: #21463 --- Help/manual/cmake-properties.7.rst | 1 + .../Fortran_BUILDING_INSTRINSIC_MODULES.rst | 14 ++++ Source/LexerParser/cmFortranParser.cxx | 78 ++++++++++--------- Source/LexerParser/cmFortranParser.y | 4 + Source/cmDependsFortran.cxx | 17 +++- Source/cmDependsFortran.h | 3 +- Source/cmFortranParser.h | 5 ++ Source/cmFortranParserImpl.cxx | 13 ++++ Source/cmGeneratorTarget.cxx | 8 ++ Source/cmGeneratorTarget.h | 1 + Source/cmMakefileTargetGenerator.cxx | 7 ++ 11 files changed, 110 insertions(+), 41 deletions(-) create mode 100644 Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5f18a824755..4212913a96f 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -202,6 +202,7 @@ Properties on Targets /prop_tgt/EXPORT_NAME /prop_tgt/EXPORT_PROPERTIES /prop_tgt/FOLDER + /prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES /prop_tgt/Fortran_FORMAT /prop_tgt/Fortran_MODULE_DIRECTORY /prop_tgt/Fortran_PREPROCESS diff --git a/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst new file mode 100644 index 00000000000..518bca72689 --- /dev/null +++ b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst @@ -0,0 +1,14 @@ +Fortran_BUILDING_INSTRINSIC_MODULES +----------------------------------- + +Instructs the CMake Fortran preprocessor that the target is building +Fortran intrinsics for building a Fortran compiler. + +This property is off by default and should be turned only on projects +that build a Fortran compiler. It should not be turned on for projects +that use a Fortran compiler. + +Turning this property on will correctly add dependencies for building +Fortran intrinsic modules whereas turning the property off will ignore +Fortran intrinsic modules in the dependency graph as they are supplied +by the compiler itself. diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 3f3dddeb4e7..50e97529bf3 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -600,12 +600,12 @@ static const yytype_int8 yytranslate[] = static const yytype_uint8 yyrline[] = { 0, 101, 101, 101, 104, 108, 113, 122, 128, 135, - 140, 144, 149, 157, 162, 167, 172, 177, 182, 187, - 192, 197, 201, 205, 209, 213, 214, 219, 219, 219, - 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, - 225, 225, 226, 226, 227, 227, 228, 228, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247 + 140, 144, 149, 161, 166, 171, 176, 181, 186, 191, + 196, 201, 205, 209, 213, 217, 218, 223, 223, 223, + 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, + 229, 229, 230, 230, 231, 231, 232, 232, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251 }; #endif @@ -1747,142 +1747,146 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); } + if (cmsysString_strcasecmp((yyvsp[-4].string), "intrinsic") == 0) { + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUseIntrinsic(parser, (yyvsp[-2].string)); + } free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1754 "cmFortranParser.cxx" +#line 1758 "cmFortranParser.cxx" break; case 13: /* stmt: INCLUDE STRING other EOSTMT */ -#line 157 "cmFortranParser.y" +#line 161 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1764 "cmFortranParser.cxx" +#line 1768 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ -#line 162 "cmFortranParser.y" +#line 166 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1774 "cmFortranParser.cxx" +#line 1778 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ -#line 167 "cmFortranParser.y" +#line 171 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1784 "cmFortranParser.cxx" +#line 1788 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ -#line 172 "cmFortranParser.y" +#line 176 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1794 "cmFortranParser.cxx" +#line 1798 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ -#line 177 "cmFortranParser.y" +#line 181 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1804 "cmFortranParser.cxx" +#line 1808 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ -#line 182 "cmFortranParser.y" +#line 186 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1814 "cmFortranParser.cxx" +#line 1818 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ -#line 187 "cmFortranParser.y" +#line 191 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1824 "cmFortranParser.cxx" +#line 1828 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ -#line 192 "cmFortranParser.y" +#line 196 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1834 "cmFortranParser.cxx" +#line 1838 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ -#line 197 "cmFortranParser.y" +#line 201 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1843 "cmFortranParser.cxx" +#line 1847 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ -#line 201 "cmFortranParser.y" +#line 205 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1852 "cmFortranParser.cxx" +#line 1856 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ -#line 205 "cmFortranParser.y" +#line 209 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1861 "cmFortranParser.cxx" +#line 1865 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ -#line 209 "cmFortranParser.y" +#line 213 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1870 "cmFortranParser.cxx" +#line 1874 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ -#line 231 "cmFortranParser.y" +#line 235 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1876 "cmFortranParser.cxx" +#line 1880 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ -#line 238 "cmFortranParser.y" +#line 242 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1882 "cmFortranParser.cxx" +#line 1886 "cmFortranParser.cxx" break; -#line 1886 "cmFortranParser.cxx" +#line 1890 "cmFortranParser.cxx" default: break; } @@ -2107,6 +2111,6 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); return yyresult; } -#line 250 "cmFortranParser.y" +#line 254 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index a3e1c24b12b..8ef19035c6f 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -151,6 +151,10 @@ stmt: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, $5); } + if (cmsysString_strcasecmp($3, "intrinsic") == 0) { + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUseIntrinsic(parser, $5); + } free($3); free($5); } diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index bca26b9caaf..6024cf62400 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -163,12 +163,17 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory(); } + bool building_intrinsics = + !mf->GetSafeDefinition("CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES") + .empty(); + // Actually write dependencies to the streams. using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap; ObjectInfoMap const& objInfo = this->Internal->ObjectInfo; for (auto const& i : objInfo) { if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir, - makeDepends, internalDepends)) { + makeDepends, internalDepends, + building_intrinsics)) { return false; } } @@ -307,7 +312,8 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, std::string const& mod_dir, std::string const& stamp_dir, std::ostream& makeDepends, - std::ostream& internalDepends) + std::ostream& internalDepends, + bool buildingIntrinsics) { // Get the source file for this object. std::string const& src = info.Source; @@ -339,8 +345,13 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, makeDepends << '\n'; } + std::set req = info.Requires; + if (buildingIntrinsics) { + req.insert(info.Intrinsics.begin(), info.Intrinsics.end()); + } + // Write module requirements to the output stream. - for (std::string const& i : info.Requires) { + for (std::string const& i : req) { // Require only modules not provided in the same source. if (info.Provides.find(i) != info.Provides.cend()) { continue; diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 0d407bc3bc0..a74db91f3d7 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -72,7 +72,8 @@ class cmDependsFortran : public cmDepends std::string const& mod_dir, std::string const& stamp_dir, std::ostream& makeDepends, - std::ostream& internalDepends); + std::ostream& internalDepends, + bool buildingIntrinsics); // The source file from which to start scanning. std::string SourceFile; diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 1b14d17772e..70fe5374ce1 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -40,6 +40,8 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser); /* Callbacks for parser. */ void cmFortranParser_Error(cmFortranParser* parser, const char* message); void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name); +void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser, + const char* module_name); void cmFortranParser_RuleLineDirective(cmFortranParser* parser, const char* filename); void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name); @@ -99,6 +101,9 @@ class cmFortranSourceInfo std::set Provides; std::set Requires; + // Set of intrinsic modules. + std::set Intrinsics; + // Set of files included in the translation unit. std::set Includes; }; diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index 054a2a93e6f..efcc5bb2e65 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -197,6 +197,19 @@ void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name) parser->Info.Requires.insert(parser->ModName(mod_name)); } +void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser, + const char* module_name) +{ + if (parser->InPPFalseBranch) { + return; + } + + // syntax: "use, intrinsic:: module_name" + // requires: "module_name.mod" + std::string const& mod_name = cmSystemTools::LowerCase(module_name); + parser->Info.Intrinsics.insert(parser->ModName(mod_name)); +} + void cmFortranParser_RuleLineDirective(cmFortranParser* parser, const char* filename) { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f268c6c3e6f..34797c5c538 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6175,6 +6175,14 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory( return this->FortranModuleDirectory; } +bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const +{ + if (cmProp prop = this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) { + return cmIsOn(*prop); + } + return false; +} + std::string cmGeneratorTarget::CreateFortranModuleDirectory( std::string const& working_dir) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index ed66fb1a819..0619279cfc7 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -832,6 +832,7 @@ class cmGeneratorTarget std::string const& config) const; std::string GetFortranModuleDirectory(std::string const& working_dir) const; + bool IsFortranBuildingInstrinsicModules() const; const std::string& GetSourcesProperty() const; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 6d8376c6788..d6145f85666 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1380,6 +1380,13 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" << this->GeneratorTarget->GetFortranModuleDirectory(working_dir) << "\")\n"; + + if (this->GeneratorTarget->IsFortranBuildingInstrinsicModules()) { + *this->InfoFileStream + << "\n" + << "# Fortran compiler is building intrinsic modules.\n" + << "set(CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES ON) \n"; + } /* clang-format on */ // and now write the rule to use it From 96e362fdc9c6b138461919c96ef5e5a712dad8fb Mon Sep 17 00:00:00 2001 From: Paul Zehner Date: Thu, 24 Jun 2021 12:09:52 +0900 Subject: [PATCH 0753/1519] Fujitsu: Add IPO support for Fortran --- Modules/Compiler/Fujitsu.cmake | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Modules/Compiler/Fujitsu.cmake b/Modules/Compiler/Fujitsu.cmake index 13bc57c90dd..78495cb9378 100644 --- a/Modules/Compiler/Fujitsu.cmake +++ b/Modules/Compiler/Fujitsu.cmake @@ -26,6 +26,16 @@ macro(__compiler_fujitsu lang) set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") + # IPO flag + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + if ("${lang}" STREQUAL "Fortran") + # Supported by Fortran compiler only + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-Klto") + else() + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + endif() + # How to actually call the compiler set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE " -E $<$:-Cpp> > ") From b3bf33539bd48797adb8c072ff883043fda7b09c Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima <15070-e-kwsm@users.noreply.gitlab.kitware.com> Date: Thu, 24 Jun 2021 06:50:36 +0900 Subject: [PATCH 0754/1519] FindOpenMP: Link with OpenMP flags on Fujitsu Fixes: #22332 --- Modules/FindOpenMP.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index e982e2d593c..929a8098825 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -570,6 +570,10 @@ foreach(LANG IN LISTS OpenMP_FINDLIST) separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}") set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "$<$:${_OpenMP_${LANG}_OPTIONS}>") + if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu") + set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY + INTERFACE_LINK_OPTIONS "${OpenMP_${LANG}_FLAGS}") + endif() unset(_OpenMP_${LANG}_OPTIONS) endif() if(OpenMP_${LANG}_INCLUDE_DIRS) From e21188df8bd08a5f306afc09bcb829d148b982d5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 24 Jun 2021 10:55:58 -0400 Subject: [PATCH 0755/1519] cmELF: Open file explicitly in binary mode ELF is a binary format. --- Source/cmELF.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index deffdb6467c..01dc0b1d6ee 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -683,7 +683,7 @@ const long cmELF::TagMipsRldMapRel = 0; cmELF::cmELF(const char* fname) { // Try to open the file. - auto fin = cm::make_unique(fname); + auto fin = cm::make_unique(fname, std::ios::binary); // Quit now if the file could not be opened. if (!fin || !*fin) { From 0da1540aaa8d36145329572938aeec6c86fb1ee7 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Thu, 17 Jun 2021 13:18:13 +0100 Subject: [PATCH 0756/1519] cmELF: Fix check for TagMipsRldMapRel DT_MIPS_RLD_MAP_REL is a machine-speicific dynamic tag, so other architectures could re-use the value of 0x70000035 to mean something else. Before using DT_MIPS_RLD_MAP_REL, we have to check that the ELF file is actually has a e_machine of EM_MIPS. --- Source/cmELF.cxx | 15 +++++++++++++++ Source/cmELF.h | 3 +++ Source/cmSystemTools.cxx | 3 +-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 01dc0b1d6ee..d96644b5b19 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -145,6 +145,7 @@ class cmELFInternal virtual std::vector EncodeDynamicEntries( const cmELF::DynamicEntryList&) = 0; virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0; + virtual bool IsMips() const = 0; virtual void PrintInfo(std::ostream& os) const = 0; // Lookup the SONAME in the DYNAMIC section. @@ -256,6 +257,12 @@ class cmELFInternalImpl : public cmELFInternal // Lookup a string from the dynamic section with the given tag. StringEntry const* GetDynamicSectionString(unsigned int tag) override; +#ifdef EM_MIPS + bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } +#else + bool IsMips() const override { false; } +#endif + // Print information about the ELF file. void PrintInfo(std::ostream& os) const override { @@ -830,6 +837,14 @@ cmELF::StringEntry const* cmELF::GetRunPath() return nullptr; } +bool cmELF::IsMIPS() const +{ + if (this->Valid()) { + return this->Internal->IsMips(); + } + return false; +} + void cmELF::PrintInfo(std::ostream& os) const { if (this->Valid()) { diff --git a/Source/cmELF.h b/Source/cmELF.h index c479e2b951d..5700a3817cb 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -98,6 +98,9 @@ class cmELF /** Get the RUNPATH field if any. */ StringEntry const* GetRunPath(); + /** Returns true if the ELF file targets a MIPS CPU. */ + bool IsMIPS() const; + /** Print human-readable information about the ELF file. */ void PrintInfo(std::ostream& os) const; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 488e69c5321..d6b82086d65 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -3102,8 +3102,7 @@ static cm::optional RemoveRPathELF(std::string const& file, entriesErased++; continue; } - if (cmELF::TagMipsRldMapRel != 0 && - it->first == cmELF::TagMipsRldMapRel) { + if (it->first == cmELF::TagMipsRldMapRel && elf.IsMIPS()) { // Background: debuggers need to know the "linker map" which contains // the addresses each dynamic object is loaded at. Most arches use // the DT_DEBUG tag which the dynamic linker writes to (directly) and From 5dfa3ddbe592add43e2985dad772f6aa44d37c0b Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 23 Jun 2021 09:24:04 +0100 Subject: [PATCH 0757/1519] cmELF: Allow building without system ELF headers Use ELF headers vendored in `Utilities/cmelf` to get the ELF constants and types. Using the same ELF definition header for all compilation targets allows removing some #ifdefs depending on the host OS since we know all required ELF constants will always be present. To reduce the size of this commit, the CMake_USE_ELF_PARSER definite will be removed in a separate commit. This allows me to use CMAKE_BUILD_WITH_INSTALL_RPATH=False and the Ninja generator on macOS, whereas before it would always give me the following error message (despite cross-compiling for an ELF-based platform): ``` The install of the target requires changing an RPATH from the build tree, but this is not supported with the Ninja generator unless on an ELF-based platform. The CMAKE_BUILD_WITH_INSTALL_RPATH variable may be set to avoid this relinking step. ``` --- Source/CMakeLists.txt | 32 +--------- Source/cmELF.cxx | 65 ++------------------ Tests/RunCMake/CMakeLists.txt | 4 +- Tests/RunCMake/file-RPATH/RunCMakeTest.cmake | 2 +- 4 files changed, 10 insertions(+), 93 deletions(-) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9a18184fd3b..39e4a9dc101 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -10,36 +10,8 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") endif() include(CheckIncludeFile) -# Check if we can build support for ELF parsing. -if(WIN32) - set(HAVE_ELF_H 0) -elseif(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") - CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H) -else() - CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H) -endif() -if(HAVE_ELF_H) - set(CMake_USE_ELF_PARSER 1) -elseif(HAIKU) - # On Haiku, we need to include elf32.h from the private headers - set(CMake_HAIKU_INCLUDE_DIRS - /boot/system/develop/headers/private/system - /boot/system/develop/headers/private/system/arch/x86 - ) - - set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS}) - CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H) - unset(CMAKE_REQUIRED_INCLUDES) - if(HAVE_ELF32_H) - set(CMake_USE_ELF_PARSER 1) - else() - unset(CMake_HAIKU_INCLUDE_DIRS) - set(CMake_USE_ELF_PARSER) - endif() -else() - set(CMake_USE_ELF_PARSER) -endif() +set(CMake_USE_ELF_PARSER 1) if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) @@ -111,7 +83,7 @@ include_directories( ${CMake_HAIKU_INCLUDE_DIRS} ) -# Check if we can build the ELF parser. +# The ELF parser can be built on all platforms. if(CMake_USE_ELF_PARSER) set(ELF_SRCS cmELF.h cmELF.cxx) endif() diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index d96644b5b19..cde7cdf3812 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -17,41 +17,9 @@ #include "cmsys/FStream.hxx" -// Include the ELF format information system header. -#if defined(__OpenBSD__) -# include -#elif defined(__HAIKU__) -# include -# include -using Elf32_Ehdr = struct Elf32_Ehdr; -using Elf32_Shdr = struct Elf32_Shdr; -using Elf32_Sym = struct Elf32_Sym; -using Elf32_Rel = struct Elf32_Rel; -using Elf32_Rela = struct Elf32_Rela; -# define ELFMAG0 0x7F -# define ELFMAG1 'E' -# define ELFMAG2 'L' -# define ELFMAG3 'F' -# define ET_NONE 0 -# define ET_REL 1 -# define ET_EXEC 2 -# define ET_DYN 3 -# define ET_CORE 4 -# define EM_386 3 -# define EM_SPARC 2 -# define EM_PPC 20 -#else -# include -#endif -#if defined(__sun) -# include // For dynamic section information -#endif -#ifdef _SCO_DS -# include // For DT_SONAME etc. -#endif -#ifndef DT_RUNPATH -# define DT_RUNPATH 29 -#endif +#include "cmelf/elf32.h" +#include "cmelf/elf64.h" +#include "cmelf/elf_common.h" // Low-level byte swapping implementation. template @@ -213,7 +181,6 @@ struct cmELFTypes32 }; // Configure the implementation template for 64-bit ELF files. -#ifndef _SCO_DS struct cmELFTypes64 { using ELF_Ehdr = Elf64_Ehdr; @@ -223,7 +190,6 @@ struct cmELFTypes64 using tagtype = ::uint64_t; static const char* GetName() { return "64-bit"; } }; -#endif // Parser implementation template. template @@ -257,11 +223,7 @@ class cmELFInternalImpl : public cmELFInternal // Lookup a string from the dynamic section with the given tag. StringEntry const* GetDynamicSectionString(unsigned int tag) override; -#ifdef EM_MIPS bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } -#else - bool IsMips() const override { false; } -#endif // Print information about the ELF file. void PrintInfo(std::ostream& os) const override @@ -346,16 +308,12 @@ class cmELFInternalImpl : public cmELFInternal eti == ET_CORE) { return true; } -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { return true; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { return true; } -#endif return false; } @@ -466,18 +424,14 @@ cmELFInternalImpl::cmELFInternalImpl(cmELF* external, break; default: { unsigned int eti = static_cast(this->ELFHeader.e_type); -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { this->ELFType = cmELF::FileTypeSpecificOS; break; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { this->ELFType = cmELF::FileTypeSpecificProc; break; } -#endif std::ostringstream e; e << "Unknown ELF file type " << eti; this->SetErrorMessage(e.str().c_str()); @@ -680,12 +634,7 @@ cmELF::StringEntry const* cmELFInternalImpl::GetDynamicSectionString( const long cmELF::TagRPath = DT_RPATH; const long cmELF::TagRunPath = DT_RUNPATH; - -#ifdef DT_MIPS_RLD_MAP_REL const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL; -#else -const long cmELF::TagMipsRldMapRel = 0; -#endif cmELF::cmELF(const char* fname) { @@ -735,15 +684,11 @@ cmELF::cmELF(const char* fname) // 32-bit ELF this->Internal = cm::make_unique>( this, std::move(fin), order); - } -#ifndef _SCO_DS - else if (ident[EI_CLASS] == ELFCLASS64) { + } else if (ident[EI_CLASS] == ELFCLASS64) { // 64-bit ELF this->Internal = cm::make_unique>( this, std::move(fin), order); - } -#endif - else { + } else { this->ErrorMessage = "ELF file class is not 32-bit or 64-bit."; return; } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index dafb174000c..256c8a66d9e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -377,8 +377,8 @@ add_RunCMake_test(ctest_upload) add_RunCMake_test(ctest_fixtures) add_RunCMake_test(file -DMSYS=${MSYS}) add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) -if(HAVE_ELF_H OR CMAKE_SYSTEM_NAME STREQUAL "AIX") - add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DHAVE_ELF_H=${HAVE_ELF_H}) +if(CMake_USE_ELF_PARSER) + add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCMake_USE_ELF_PARSER=${CMake_USE_ELF_PARSER}) endif() add_RunCMake_test(find_file) add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) diff --git a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake index eb7b4973069..e209f353a23 100644 --- a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake @@ -1,6 +1,6 @@ include(RunCMake) -if(HAVE_ELF_H) +if(CMake_USE_ELF_PARSER) run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake) endif() From 115ff6a347a96eb77abcd8df5e72e4851dcea414 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Thu, 17 Jun 2021 15:22:34 +0100 Subject: [PATCH 0758/1519] cmELF: Include the ELF parsing code unconditionally Now that the ELF definitions are provided on all platforms there is no need to keep the CMake_USE_ELF_PARSER option. --- Source/CMakeLists.txt | 10 ++---- Source/cmConfigure.cmake.h.in | 1 - Source/cmELF.h | 4 --- Source/cmFileCommand.cxx | 20 ++++------- Source/cmGeneratorTarget.cxx | 9 ++--- Source/cmSystemTools.cxx | 36 ++------------------ Tests/RunCMake/CMakeLists.txt | 4 +-- Tests/RunCMake/file-RPATH/RunCMakeTest.cmake | 4 +-- bootstrap | 1 + 9 files changed, 16 insertions(+), 73 deletions(-) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 39e4a9dc101..6446b047b21 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -11,8 +11,6 @@ endif() include(CheckIncludeFile) -set(CMake_USE_ELF_PARSER 1) - if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) set(CMake_DEFAULT_RECURSION_LIMIT 100) @@ -83,11 +81,6 @@ include_directories( ${CMake_HAIKU_INCLUDE_DIRS} ) -# The ELF parser can be built on all platforms. -if(CMake_USE_ELF_PARSER) - set(ELF_SRCS cmELF.h cmELF.cxx) -endif() - # Check if we can build the Mach-O parser. if(CMake_USE_MACH_PARSER) set(MACH_SRCS cmMachO.h cmMachO.cxx) @@ -217,7 +210,8 @@ set(SRCS cmDocumentationSection.cxx cmDynamicLoader.cxx cmDynamicLoader.h - ${ELF_SRCS} + cmELF.h + cmELF.cxx cmExprParserHelper.cxx cmExportBuildAndroidMKGenerator.h cmExportBuildAndroidMKGenerator.cxx diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index aeca6b42acb..6a419f681be 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -16,7 +16,6 @@ #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE #cmakedefine HAVE_UNSETENV -#cmakedefine CMake_USE_ELF_PARSER #cmakedefine CMake_USE_MACH_PARSER #cmakedefine CMake_USE_XCOFF_PARSER #define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@ diff --git a/Source/cmELF.h b/Source/cmELF.h index 5700a3817cb..5807c162559 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -10,10 +10,6 @@ #include #include -#if !defined(CMake_USE_ELF_PARSER) -# error "This file may be included only if CMake_USE_ELF_PARSER is enabled." -#endif - class cmELFInternal; /** \class cmELF diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 0ad59c7b5d3..1e3076f88dc 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -31,6 +31,7 @@ #include "cmArgumentParser.h" #include "cmCMakePath.h" #include "cmCryptoHash.h" +#include "cmELF.h" #include "cmExecutionStatus.h" #include "cmFSPermissions.h" #include "cmFileCopier.h" @@ -64,10 +65,6 @@ # include "cmFileLockResult.h" #endif -#if defined(CMake_USE_ELF_PARSER) -# include "cmELF.h" -#endif - #if defined(_WIN32) # include #endif @@ -1242,8 +1239,12 @@ bool HandleReadElfCommand(std::vector const& args, return false; } -#if defined(CMake_USE_ELF_PARSER) cmELF elf(fileNameArg.c_str()); + if (!elf) { + status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg, + "\" that is not a valid ELF file.")); + return false; + } if (!arguments.RPath.empty()) { if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { @@ -1261,15 +1262,6 @@ bool HandleReadElfCommand(std::vector const& args, } return true; -#else - std::string error = "ELF parser not available on this platform."; - if (arguments.Error.empty()) { - status.SetError(error); - return false; - } - status.GetMakefile().AddDefinition(arguments.Error, error); - return true; -#endif } bool HandleInstallCommand(std::vector const& args, diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f268c6c3e6f..aff32a496b3 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2142,7 +2142,6 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const return true; } -#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER) // Enable if the rpath flag uses a separator and the target uses // binaries we know how to edit. std::string ll = this->GetLinkerLanguage(config); @@ -2155,21 +2154,17 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const // CMAKE_EXECUTABLE_FORMAT. if (cmProp fmt = this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) { -# if defined(CMake_USE_ELF_PARSER) if (*fmt == "ELF") { return true; } -# endif -# if defined(CMake_USE_XCOFF_PARSER) +#if defined(CMake_USE_XCOFF_PARSER) if (*fmt == "XCOFF") { return true; } -# endif +#endif } } } -#endif - static_cast(config); return false; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index d6b82086d65..f082ae84bbf 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -20,6 +20,7 @@ #include #include "cmDuration.h" +#include "cmELF.h" #include "cmMessageMetadata.h" #include "cmProcessOutput.h" #include "cmRange.h" @@ -46,12 +47,6 @@ # include "cmCryptoHash.h" #endif -#if defined(CMake_USE_ELF_PARSER) -# include "cmELF.h" -#else -class cmELF; -#endif - #if defined(CMake_USE_MACH_PARSER) # include "cmMachO.h" #endif @@ -2448,14 +2443,12 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message, bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath, std::string& soname) { -// For ELF shared libraries use a real parser to get the correct -// soname. -#if defined(CMake_USE_ELF_PARSER) + // For ELF shared libraries use a real parser to get the correct + // soname. cmELF elf(fullPath.c_str()); if (elf) { return elf.GetSOName(soname); } -#endif // If the file is not a symlink we have no guess for its soname. if (!cmSystemTools::FileIsSymlink(fullPath)) { @@ -2543,14 +2536,6 @@ cm::optional AdjustRPathELF(std::string const& file, const AdjustCallback& adjustCallback, std::string* emsg, bool* changed) { -#if !defined(CMake_USE_ELF_PARSER) - (void)file; - (void)emptyCallback; - (void)adjustCallback; - (void)emsg; - (void)changed; - return cm::nullopt; // Cannot handle ELF files. -#else if (changed) { *changed = false; } @@ -2678,7 +2663,6 @@ cm::optional AdjustRPathELF(std::string const& file, *changed = true; } return true; -#endif } std::function MakeEmptyCallback( @@ -2690,16 +2674,11 @@ std::function MakeEmptyCallback( // okay. return true; } -#if defined(CMake_USE_ELF_PARSER) if (emsg) { *emsg = cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ", elf.GetErrorMessage()); } -#else - static_cast(emsg); - static_cast(elf); -#endif return false; }; } @@ -3033,12 +3012,6 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs) static cm::optional RemoveRPathELF(std::string const& file, std::string* emsg, bool* removed) { -#if !defined(CMake_USE_ELF_PARSER) - (void)file; - (void)emsg; - (void)removed; - return cm::nullopt; // Cannot handle ELF files. -#else if (removed) { *removed = false; } @@ -3177,7 +3150,6 @@ static cm::optional RemoveRPathELF(std::string const& file, *removed = true; } return true; -#endif } static cm::optional RemoveRPathXCOFF(std::string const& file, @@ -3224,7 +3196,6 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, bool cmSystemTools::CheckRPath(std::string const& file, std::string const& newRPath) { -#if defined(CMake_USE_ELF_PARSER) // Parse the ELF binary. cmELF elf(file.c_str()); if (elf) { @@ -3247,7 +3218,6 @@ bool cmSystemTools::CheckRPath(std::string const& file, } return false; } -#endif #if defined(CMake_USE_XCOFF_PARSER) // Parse the XCOFF binary. cmXCOFF xcoff(file.c_str()); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 256c8a66d9e..59fa9dcae3e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -377,9 +377,7 @@ add_RunCMake_test(ctest_upload) add_RunCMake_test(ctest_fixtures) add_RunCMake_test(file -DMSYS=${MSYS}) add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) -if(CMake_USE_ELF_PARSER) - add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCMake_USE_ELF_PARSER=${CMake_USE_ELF_PARSER}) -endif() +add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(find_file) add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) add_RunCMake_test(find_package -DMSYS=${MSYS}) diff --git a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake index e209f353a23..1ca2e757a69 100644 --- a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake @@ -1,8 +1,6 @@ include(RunCMake) -if(CMake_USE_ELF_PARSER) - run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake) -endif() +run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake) if(CMAKE_SYSTEM_NAME STREQUAL "AIX") run_cmake_command(XCOFF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/XCOFF.cmake) diff --git a/bootstrap b/bootstrap index f8d2f693c2f..540743d3c5e 100755 --- a/bootstrap +++ b/bootstrap @@ -324,6 +324,7 @@ CMAKE_CXX_SOURCES="\ cmDefinePropertyCommand \ cmDefinitions \ cmDocumentationFormatter \ + cmELF \ cmEnableLanguageCommand \ cmEnableTestingCommand \ cmExecProgramCommand \ From af9bd6c53f69ac6f772442a258aac912b0920ace Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 24 Jun 2021 15:28:32 +0200 Subject: [PATCH 0759/1519] Help: UseJava reorganization Fixes: #22155 --- Modules/UseJava.cmake | 805 ++++++++++++++++++++++++------------------ 1 file changed, 454 insertions(+), 351 deletions(-) diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 30b40a079a6..ef63ac34b02 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -5,442 +5,545 @@ UseJava ------- -Use Module for Java - -This file provides functions for Java. It is assumed that +This file provides support for ``Java``. It is assumed that :module:`FindJava` has already been loaded. See :module:`FindJava` for -information on how to load Java into your CMake project. +information on how to load Java into your ``CMake`` project. + +Synopsis +^^^^^^^^ + +.. parsed-literal:: + + `Creating and Installing JARS`_ + `add_jar`_ ( [SOURCES] [...] ...) + `install_jar`_ ( DESTINATION [COMPONENT ]) + `install_jni_symlink`_ ( DESTINATION [COMPONENT ]) + + `Header Generation`_ + `create_javah`_ ((TARGET | GENERATED_FILES ) CLASSES ... ...) + + `Exporting JAR Targets`_ + `install_jar_exports`_ (TARGETS ... FILE DESTINATION ...) + `export_jars`_ (TARGETS ... [NAMESPACE ] FILE ) + + `Finding JARs`_ + `find_jar`_ ( NAMES [...] [PATHS [... ENV ]] ...) + + `Creating Java Documentation`_ + `create_javadoc`_ ( (PACKAGES [...] | FILES [...]) ...) Creating And Installing JARs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: cmake - - add_jar( - [SOURCES] [...] [...] - [RESOURCES NAMESPACE ... [NAMESPACE ...]... ] - [INCLUDE_JARS [...]] - [ENTRY_POINT ] - [VERSION ] - [OUTPUT_NAME ] - [OUTPUT_DIR ] - [GENERATE_NATIVE_HEADERS - [DESTINATION (|INSTALL [BUILD ])]] - ) - -This command creates a ``.jar``. It compiles the given -```` files and adds the given ```` files to -the jar file. Source files can be java files or listing files -(prefixed by ``@``). If only resource files are given then just a jar file -is created. - -.. versionadded:: 3.21 - The ``RESOURCES`` parameter adds the named ```` files to the jar - by stripping the source file path and placing the file beneath ```` - within the jar. - -For example:: - - RESOURCES NAMESPACE "/com/my/namespace" "a/path/to/resource.txt" - -results in a resource accessible via ``/com/my/namespace/resource.txt`` -within the jar. - -Resources may be added without adjusting the namespace by adding them to -the list of ``SOURCES`` (original behavior), in this case, resource -paths must be relative to ``CMAKE_CURRENT_SOURCE_DIR``. Adding resources -without using the ``RESOURCES`` parameter in out of source builds will -almost certainly result in confusion. - -.. note:: - - Adding resources via the ``SOURCES`` parameter relies upon a hard-coded - list of file extensions which are tested to determine whether they compile - (e.g. File.java). ``SOURCES`` files which match the extensions are compiled. - Files which do not match are treated as resources. To include uncompiled - resources matching those file extensions use the ``RESOURCES`` parameter. - -The list of ``INCLUDE_JARS`` are added to the classpath when -compiling the java sources and also to the dependencies of the target. -``INCLUDE_JARS`` also accepts other target names created by ``add_jar()``. -For backwards compatibility, jar files listed as sources are ignored (as -they have been since the first version of this module). - -.. versionadded:: 3.4 - Support for response files (prefixed by ``@``) in the ``SOURCES`` list. - -The default ``OUTPUT_DIR`` can also be changed by setting the variable -``CMAKE_JAVA_TARGET_OUTPUT_DIR``. - -.. versionadded:: 3.11 - Optionally, using option ``GENERATE_NATIVE_HEADERS``, native header files can - be generated for methods declared as native. These files provide the - connective glue that allow your Java and C code to interact. An INTERFACE - target will be created for an easy usage of generated files. Sub-option - ``DESTINATION`` can be used to specify the output directory for generated - header files. - - ``GENERATE_NATIVE_HEADERS`` option requires, at least, version 1.8 of the JDK. - -.. versionadded:: 3.20 - ``DESTINATION`` sub-option now supports the possibility to specify different - output directories for ``BUILD`` and ``INSTALL`` steps. This is required to - export the interface target generated by ``GENERATE_NATIVE_HEADERS`` option. - If ``BUILD`` directory is not specified, a default directory will be used. - -The ``add_jar()`` function sets the following target properties on -````: - -``INSTALL_FILES`` - The files which should be installed. This is used by ``install_jar()``. -``JNI_SYMLINK`` - The JNI symlink which should be installed. This is used by - ``install_jni_symlink()``. -``JAR_FILE`` - The location of the jar file so that you can include it. -``CLASSDIR`` - The directory where the class files can be found. For example to use them - with ``javah``. - -.. versionadded:: 3.20 - The target generated by option ``GENERATE_NATIVE_HEADERS`` has the property - ``NATIVE_HEADERS_DIRECTORY`` which specify the directory holding the native - headers. - -.. code-block:: cmake - - install_jar( ) - install_jar( DESTINATION [COMPONENT ]) - -This command installs the ```` files to the given -````. It should be called in the same scope as ``add_jar()`` or -it will fail. - -The ``install_jar()`` function sets the ``INSTALL_DESTINATION`` target -property on jars so installed. This property holds the ```` as -described above, and is used by ``install_jar_exports()``. You can get this -information with :command:`get_property` and the ``INSTALL_DESTINATION`` -property key. - -.. versionadded:: 3.4 - The second signature with ``DESTINATION`` and ``COMPONENT`` options. - -.. code-block:: cmake +.. _add_jar: - install_jni_symlink( ) - install_jni_symlink( DESTINATION [COMPONENT ]) - -This command installs the ```` JNI symlinks to the given -````. It should be called in the same scope as ``add_jar()`` or -it will fail. +.. command:: add_jar -.. versionadded:: 3.4 - The second signature with ``DESTINATION`` and ``COMPONENT`` options. + Creates a jar file containing java objects and, optionally, resources:: -Exporting JAR Targets -^^^^^^^^^^^^^^^^^^^^^ + add_jar( + [SOURCES] [...] [...] + [RESOURCES NAMESPACE ... [NAMESPACE ...]... ] + [INCLUDE_JARS [...]] + [ENTRY_POINT ] + [VERSION ] + [MANIFEST ] + [OUTPUT_NAME ] + [OUTPUT_DIR ] + [GENERATE_NATIVE_HEADERS + [DESTINATION (|INSTALL [BUILD ])]] + ) -.. versionadded:: 3.7 + This command creates a ``.jar``. It compiles the given + ```` files and adds the given ```` files to + the jar file. Source files can be java files or listing files + (prefixed by ``@``). If only resource files are given then just a jar file + is created. -.. code-block:: cmake + ``SOURCES`` + Compiles the specified source files and adds the result in the jar file. - install_jar_exports(TARGETS ... - [NAMESPACE ] - FILE - DESTINATION [COMPONENT ]) + .. versionadded:: 3.4 + Support for response files, prefixed by ``@``. -This command installs a target export file ```` for the named jar -targets to the given ```` directory. Its function is similar to -that of :command:`install(EXPORTS)`. + ``RESOURCES`` + .. versionadded:: 3.21 -.. versionadded:: 3.9 - The ``NAMESPACE`` option. + Adds the named ```` files to the jar by stripping the source file + path and placing the file beneath ```` within the jar. -.. code-block:: cmake + For example:: - export_jars(TARGETS ... - [NAMESPACE ] - FILE ) + RESOURCES NAMESPACE "/com/my/namespace" "a/path/to/resource.txt" -This command writes a target export file ```` for the named ```` -targets. Its function is similar to that of :command:`export`. + results in a resource accessible via ``/com/my/namespace/resource.txt`` + within the jar. -.. versionadded:: 3.9 - The ``NAMESPACE`` option. + Resources may be added without adjusting the namespace by adding them to + the list of ``SOURCES`` (original behavior), in this case, resource + paths must be relative to ``CMAKE_CURRENT_SOURCE_DIR``. Adding resources + without using the ``RESOURCES`` parameter in out of source builds will + almost certainly result in confusion. + .. note:: -Examples -"""""""" + Adding resources via the ``SOURCES`` parameter relies upon a hard-coded + list of file extensions which are tested to determine whether they + compile (e.g. File.java). ``SOURCES`` files which match the extensions + are compiled. Files which do not match are treated as resources. To + include uncompiled resources matching those file extensions use + the ``RESOURCES`` parameter. -To add compile flags to the target you can set these flags with the following -variable: + ``INCLUDE_JARS`` + The list of jars are added to the classpath when compiling the java sources + and also to the dependencies of the target. ``INCLUDE_JARS`` also accepts + other target names created by ``add_jar()``. For backwards compatibility, + jar files listed as sources are ignored (as they have been since the first + version of this module). -.. code-block:: cmake + ``ENTRY_POINT`` + Defines an entry point in the jar file. - set(CMAKE_JAVA_COMPILE_FLAGS -nowarn) + ``VERSION`` + Adds a version to the target output name. + The following example will create a jar file with the name + ``shibboleet-1.2.0.jar`` and will create a symlink ``shibboleet.jar`` + pointing to the jar with the version information. -To add a path or a jar file to the class path you can do this with the -``CMAKE_JAVA_INCLUDE_PATH`` variable. + .. code-block:: cmake -.. code-block:: cmake + add_jar(shibboleet shibbotleet.java VERSION 1.2.0) - set(CMAKE_JAVA_INCLUDE_PATH /usr/share/java/shibboleet.jar) + ``MANIFEST`` + Defines a custom manifest for the jar. -To use a different output name for the target you can set it with: + ``OUTPUT_NAME`` + Specify a different output name for the target. -.. code-block:: cmake + ``OUTPUT_DIR`` + Sets the directory where the jar file will be generated. If not specified, + :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory. - add_jar(foobar foobar.java OUTPUT_NAME shibboleet.jar) + ``GENERATE_NATIVE_HEADERS`` + .. versionadded:: 3.11 -To use a different output directory than ``CMAKE_CURRENT_BINARY_DIR`` you can -set it with: + Generates native header files for methods declared as native. These files + provide the connective glue that allow your Java and C code to interact. + An INTERFACE target will be created for an easy usage of generated files. + Sub-option ``DESTINATION`` can be used to specify the output directory for + generated header files. -.. code-block:: cmake + This option requires, at least, version 1.8 of the JDK. - add_jar(foobar foobar.java OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) + For an optimum usage of this option, it is recommended to include module + JNI before any call to ``add_jar()``. The produced target for native + headers can then be used to compile C/C++ sources with the + :command:`target_link_libraries` command. -To define an entry point in your jar you can set it with the ``ENTRY_POINT`` -named argument: + .. code-block:: cmake -.. code-block:: cmake + find_package(JNI) + add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native) + add_library(bar bar.cpp) + target_link_libraries(bar PRIVATE foo-native) - add_jar(example ENTRY_POINT com/examples/MyProject/Main) + .. versionadded:: 3.20 + ``DESTINATION`` sub-option now supports the possibility to specify + different output directories for ``BUILD`` and ``INSTALL`` steps. If + ``BUILD`` directory is not specified, a default directory will be used. -To define a custom manifest for the jar, you can set it with the ``MANIFEST`` -named argument: + To export the interface target generated by ``GENERATE_NATIVE_HEADERS`` + option, sub-option ``INSTALL`` of ``DESTINATION`` is required: -.. code-block:: cmake + .. code-block:: cmake - add_jar(example MANIFEST /path/to/manifest) + add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native + DESTINATION INSTALL include) + install(TARGETS foo-native EXPORT native) + install(DIRECTORY "$/" + DESTINATION include) + install(EXPORT native DESTINATION /to/export NAMESPACE foo) -To add a version to the target output name you can set it using the ``VERSION`` -named argument to ``add_jar()``. The following example will create a jar file -with the name ``shibboleet-1.0.0.jar`` and will create a symlink -``shibboleet.jar`` pointing to the jar with the version information. + Some variables can be set to customize the behavior of ``add_jar()`` as well + as the java compiler: -.. code-block:: cmake + ``CMAKE_JAVA_COMPILE_FLAGS`` + Specify additional flags to java compiler. - add_jar(shibboleet shibbotleet.java VERSION 1.2.0) + ``CMAKE_JAVA_INCLUDE_PATH`` + Specify additional paths to the class path. -If the target is a JNI library, utilize the following commands to -create a JNI symbolic link: + ``CMAKE_JNI_TARGET`` + If the target is a JNI library, sets this boolean variable to ``TRUE`` to + enable creation of a JNI symbolic link (see also + :ref:`install_jni_symlink() `). -.. code-block:: cmake + ``CMAKE_JAR_CLASSES_PREFIX`` + If multiple jars should be produced from the same java source filetree, + to prevent the accumulation of duplicate class files in subsequent jars, + set/reset ``CMAKE_JAR_CLASSES_PREFIX`` prior to calling the ``add_jar()``: - set(CMAKE_JNI_TARGET TRUE) - add_jar(shibboleet shibbotleet.java VERSION 1.2.0) - install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet) - install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR}) + .. code-block:: cmake -If a single target needs to produce more than one jar from its -java source code, to prevent the accumulation of duplicate class -files in subsequent jars, set/reset ``CMAKE_JAR_CLASSES_PREFIX`` prior -to calling the ``add_jar()`` function: + set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo) + add_jar(foo foo.java) -.. code-block:: cmake + set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar) + add_jar(bar bar.java) - set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo) - add_jar(foo foo.java) + The ``add_jar()`` function sets the following target properties on + ````: - set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar) - add_jar(bar bar.java) + ``INSTALL_FILES`` + The files which should be installed. This is used by + :ref:`install_jar() `. + ``JNI_SYMLINK`` + The JNI symlink which should be installed. This is used by + :ref:`install_jni_symlink() `. + ``JAR_FILE`` + The location of the jar file so that you can include it. + ``CLASSDIR`` + The directory where the class files can be found. For example to use them + with ``javah``. + ``NATIVE_HEADERS_DIRECTORY`` + .. versionadded:: 3.20 -For an optimum usage of option ``GENERATE_NATIVE_HEADERS``, it is recommended to -include module JNI before any call to ``add_jar()``. The produced target for -native headers can then be used to compile C/C++ sources with the -:command:`target_link_libraries` command. + The directory where native headers are generated. Defined when option + ``GENERATE_NATIVE_HEADERS`` is specified. -.. code-block:: cmake +.. _install_jar: - find_package(JNI) - add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native) - add_library(bar bar.cpp) - target_link_libraries(bar PRIVATE foo-native) +.. command:: install_jar -.. versionadded:: 3.20 - It is now possible to export the target generated by - ``GENERATE_NATIVE_HEADERS`` option. + This command installs the jar file to the given destination:: - .. code-block:: cmake + install_jar( ) + install_jar( DESTINATION [COMPONENT ]) - add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native - DESTINATION INSTALL include) - install(TARGETS foo-native EXPORT native) - install(DIRECTORY "$/" - DESTINATION include) - install(EXPORT native DESTINATION /to/export NAMESPACE foo) + This command installs the ```` file to the given + ````. It should be called in the same scope as + :ref:`add_jar() ` or it will fail. -Finding JARs -^^^^^^^^^^^^ + .. versionadded:: 3.4 + The second signature with ``DESTINATION`` and ``COMPONENT`` options. -.. code-block:: cmake - - find_jar( - | NAMES [...] - [PATHS [... ENV ]] - [VERSIONS []] - [DOC "cache documentation string"] - ) - -This command is used to find a full path to the named jar. A cache -entry named by ```` is created to store the result of this command. -If the full path to a jar is found the result is stored in the -variable and the search will not repeated unless the variable is -cleared. If nothing is found, the result will be ``-NOTFOUND``, and -the search will be attempted again next time ``find_jar()`` is invoked with -the same variable. The name of the full path to a file that is -searched for is specified by the names listed after ``NAMES`` argument. -Additional search locations can be specified after the ``PATHS`` argument. -If you require special a version of a jar file you can specify it with -the ``VERSIONS`` argument. The argument after ``DOC`` will be used for the -documentation string in the cache. - - -Javadoc -^^^^^^^ - -The ``create_javadoc()`` command can be used to create java documentation -based on files or packages. For more details please read the javadoc manpage. - -There are two main signatures for ``create_javadoc()``. The first signature -works with package names on a path with source files. - -.. code-block:: cmake - - create_javadoc( - PACKAGES [...] - [SOURCEPATH ] - [CLASSPATH ] - [INSTALLPATH ] - [DOCTITLE "the documentation title"] - [WINDOWTITLE "the title of the document"] - [AUTHOR TRUE|FALSE] - [USE TRUE|FALSE] - [VERSION TRUE|FALSE] - ) + ``DESTINATION`` + Specify the directory on disk to which a file will be installed. -For example: - -.. code-block:: cmake - - create_javadoc(my_example_doc - PACKAGES com.example.foo com.example.bar - SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}" - CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH} - WINDOWTITLE "My example" - DOCTITLE "

My example

" - AUTHOR TRUE - USE TRUE - VERSION TRUE - ) - -The second signature for ``create_javadoc()`` works on a given list of -files. - -.. code-block:: cmake - - create_javadoc( - FILES [...] - [CLASSPATH ] - [INSTALLPATH ] - [DOCTITLE "the documentation title"] - [WINDOWTITLE "the title of the document"] - [AUTHOR TRUE|FALSE] - [USE TRUE|FALSE] - [VERSION TRUE|FALSE] - ) + ``COMPONENT`` + Specify an installation component name with which the install rule is + associated, such as "runtime" or "development". -For example: + The ``install_jar()`` command sets the following target properties + on ````: -.. code-block:: cmake + ``INSTALL_DESTINATION`` + Holds the ```` as described above, and is used by + :ref:`install_jar_exports() `. - create_javadoc(my_example_doc - FILES ${example_SRCS} - CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH} - WINDOWTITLE "My example" - DOCTITLE "

My example

" - AUTHOR TRUE - USE TRUE - VERSION TRUE - ) +.. _install_jni_symlink: -Both signatures share most of the options. These options are the same -as what you can find in the javadoc manpage. Please look at the -manpage for ``CLASSPATH``, ``DOCTITLE``, ``WINDOWTITLE``, ``AUTHOR``, ``USE`` -and ``VERSION``. +.. command:: install_jni_symlink -If you don't set the ``INSTALLPATH``, then by default the documentation will -be installed to : + Installs JNI symlinks for target generated by :ref:`add_jar() `:: -:: + install_jni_symlink( ) + install_jni_symlink( DESTINATION [COMPONENT ]) - ${CMAKE_INSTALL_PREFIX}/share/javadoc/ + This command installs the ```` JNI symlinks to the given + ````. It should be called in the same scope as + :ref:`add_jar() ` or it will fail. + .. versionadded:: 3.4 + The second signature with ``DESTINATION`` and ``COMPONENT`` options. + + ``DESTINATION`` + Specify the directory on disk to which a file will be installed. + + ``COMPONENT`` + Specify an installation component name with which the install rule is + associated, such as "runtime" or "development". + + Utilize the following commands to create a JNI symbolic link: + + .. code-block:: cmake + + set(CMAKE_JNI_TARGET TRUE) + add_jar(shibboleet shibbotleet.java VERSION 1.2.0) + install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet) + install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR}) Header Generation ^^^^^^^^^^^^^^^^^ -.. code-block:: cmake +.. _create_javah: + +.. command:: create_javah + + .. versionadded:: 3.4 + + Generates C header files for java classes:: + + create_javah(TARGET | GENERATED_FILES + CLASSES ... + [CLASSPATH ...] + [DEPENDS ...] + [OUTPUT_NAME |OUTPUT_DIR ] + ) + + .. deprecated:: 3.11 + This command will no longer be supported starting with version 10 of the JDK + due to the `suppression of javah tool `_. + The :ref:`add_jar(GENERATE_NATIVE_HEADERS) ` command should be + used instead. + + Create C header files from java classes. These files provide the connective + glue that allow your Java and C code to interact. + + There are two main signatures for ``create_javah()``. The first signature + returns generated files through variable specified by the ``GENERATED_FILES`` + option. For example: + + .. code-block:: cmake + + create_javah(GENERATED_FILES files_headers + CLASSES org.cmake.HelloWorld + CLASSPATH hello.jar + ) + + The second signature for ``create_javah()`` creates a target which + encapsulates header files generation. E.g. + + .. code-block:: cmake + + create_javah(TARGET target_headers + CLASSES org.cmake.HelloWorld + CLASSPATH hello.jar + ) + + Both signatures share same options. + + ``CLASSES`` + Specifies Java classes used to generate headers. - create_javah(TARGET | GENERATED_FILES - CLASSES ... - [CLASSPATH ...] - [DEPENDS ...] - [OUTPUT_NAME |OUTPUT_DIR ] - ) + ``CLASSPATH`` + Specifies various paths to look up classes. Here ``.class`` files, jar + files or targets created by command add_jar can be used. -.. versionadded:: 3.4 + ``DEPENDS`` + Targets on which the javah target depends. -.. deprecated:: 3.11 - This command will no longer be supported starting with version 10 of the JDK - due to the `suppression of javah tool `_. - The ``add_jar(GENERATE_NATIVE_HEADERS)`` command should be used instead. + ``OUTPUT_NAME`` + Concatenates the resulting header files for all the classes listed by + option ``CLASSES`` into ````. Same behavior as option ``-o`` of + ``javah`` tool. -Create C header files from java classes. These files provide the connective glue -that allow your Java and C code to interact. + ``OUTPUT_DIR`` + Sets the directory where the header files will be generated. Same behavior + as option ``-d`` of ``javah`` tool. If not specified, + :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory. -There are two main signatures for ``create_javah()``. The first signature -returns generated files through variable specified by the ``GENERATED_FILES`` -option. For example: +Exporting JAR Targets +^^^^^^^^^^^^^^^^^^^^^ + +.. _install_jar_exports: + +.. command:: install_jar_exports + + .. versionadded:: 3.7 + + Installs a target export file:: + + install_jar_exports(TARGETS ... + [NAMESPACE ] + FILE + DESTINATION [COMPONENT ]) + + This command installs a target export file ```` for the named jar + targets to the given ```` directory. Its function is similar to + that of :command:`install(EXPORT)`. + + ``TARGETS`` + List of targets created by :ref:`add_jar() ` command. + + ``NAMESPACE`` + .. versionadded:: 3.9 + + The ```` value will be prepend to the target names as they are + written to the import file. -.. code-block:: cmake + ``FILE`` + Specify name of the export file. - create_javah(GENERATED_FILES files_headers - CLASSES org.cmake.HelloWorld - CLASSPATH hello.jar - ) -The second signature for ``create_javah()`` creates a target which encapsulates -header files generation. E.g. + ``DESTINATION`` + Specify the directory on disk to which a file will be installed. -.. code-block:: cmake + ``COMPONENT`` + Specify an installation component name with which the install rule is + associated, such as "runtime" or "development". - create_javah(TARGET target_headers - CLASSES org.cmake.HelloWorld - CLASSPATH hello.jar - ) +.. _export_jars: -Both signatures share same options. +.. command:: export_jars -``CLASSES ...`` - Specifies Java classes used to generate headers. + .. versionadded:: 3.7 + + Writes a target export file:: + + export_jars(TARGETS ... + [NAMESPACE ] + FILE ) + + This command writes a target export file ```` for the named ```` + targets. Its function is similar to that of :command:`export`. + + ``TARGETS`` + List of targets created by :ref:`add_jar() ` command. + + ``NAMESPACE`` + .. versionadded:: 3.9 + + The ```` value will be prepend to the target names as they are + written to the import file. + + ``FILE`` + Specify name of the export file. + +Finding JARs +^^^^^^^^^^^^ -``CLASSPATH ...`` - Specifies various paths to look up classes. Here .class files, jar files or - targets created by command add_jar can be used. +.. _find_jar: -``DEPENDS ...`` - Targets on which the javah target depends. +.. command:: find_jar -``OUTPUT_NAME `` - Concatenates the resulting header files for all the classes listed by option - ``CLASSES`` into ````. Same behavior as option ``-o`` of javah tool. + Finds the specified jar file:: + + find_jar( + | NAMES [...] + [PATHS [... ENV ]] + [VERSIONS []] + [DOC "cache documentation string"] + ) + + This command is used to find a full path to the named jar. A cache + entry named by ```` is created to store the result of this command. + If the full path to a jar is found the result is stored in the + variable and the search will not repeated unless the variable is + cleared. If nothing is found, the result will be ``-NOTFOUND``, and + the search will be attempted again next time ``find_jar()`` is invoked with + the same variable. + + ``NAMES`` + Specify one or more possible names for the jar file. + + ``PATHS`` + Specify directories to search in addition to the default locations. + The ``ENV`` var sub-option reads paths from a system environment variable. + + ``VERSIONS`` + Specify jar versions. + + ``DOC`` + Specify the documentation string for the ```` cache entry. + +Creating Java Documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _create_javadoc: + +.. command:: create_javadoc + + Creates java documentation based on files and packages:: + + create_javadoc( + (PACKAGES [...] | FILES [...]) + [SOURCEPATH ] + [CLASSPATH ] + [INSTALLPATH ] + [DOCTITLE ] + [WINDOWTITLE ] + [AUTHOR (TRUE|FALSE)] + [USE (TRUE|FALSE)] + [VERSION (TRUE|FALSE)] + ) + + The ``create_javadoc()`` command can be used to create java documentation. + There are two main signatures for ``create_javadoc()``. + + The first signature works with package names on a path with source files: + + .. code-block:: cmake + + create_javadoc(my_example_doc + PACKAGES com.example.foo com.example.bar + SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}" + CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH} + WINDOWTITLE "My example" + DOCTITLE "

My example

" + AUTHOR TRUE + USE TRUE + VERSION TRUE + ) + + The second signature for ``create_javadoc()`` works on a given list of files: + + .. code-block:: cmake -``OUTPUT_DIR `` - Sets the directory where the header files will be generated. Same behavior - as option ``-d`` of javah tool. If not specified, - :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory. + create_javadoc(my_example_doc + FILES java/A.java java/B.java + CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH} + WINDOWTITLE "My example" + DOCTITLE "

My example

" + AUTHOR TRUE + USE TRUE + VERSION TRUE + ) + + Both signatures share most of the options. For more details please read the + javadoc manpage. + + ``PACKAGES`` + Specify java packages. + + ``FILES`` + Specify java source files. If relative paths are specified, they are + relative to :variable:`CMAKE_CURRENT_SOURCE_DIR`. + + ``SOURCEPATH`` + Specify the directory where to look for packages. By default, + :variable:`CMAKE_CURRENT_SOURCE_DIR` directory is used. + + ``CLASSPATH`` + Specify where to find user class files. Same behavior as option + ``-classpath`` of ``javadoc`` tool. + + ``INSTALLPATH`` + Specify where to install the java documentation. If you specified, the + documentation will be installed to + ``${CMAKE_INSTALL_PREFIX}/share/javadoc/``. + + ``DOCTITLE`` + Specify the title to place near the top of the overview summary file. + Same behavior as option ``-doctitle`` of ``javadoc`` tool. + + ``WINDOWTITLE`` + Specify the title to be placed in the HTML ```` tag. Same behavior + as option ``-windowtitle`` of ``javadoc`` tool. + + ``AUTHOR`` + When value ``TRUE`` is specified, includes the ``@author`` text in the + generated docs. Same behavior as option ``-author`` of ``javadoc`` tool. + + ``USE`` + When value ``TRUE`` is specified, creates class and package usage pages. + Includes one Use page for each documented class and package. Same behavior + as option ``-use`` of ``javadoc`` tool. + + ``VERSION`` + When value ``TRUE`` is specified, includes the version text in the + generated docs. Same behavior as option ``-version`` of ``javadoc`` tool. #]=======================================================================] function (__java_copy_file src dest comment) From ed295f63ec4123f9e0fba57fc6af9362ef7eb011 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 25 Jun 2021 00:01:08 -0400 Subject: [PATCH 0760/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 554e9a943c3..b808234cc71 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210624) +set(CMake_VERSION_PATCH 20210625) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f03d54bfc1c9353b0fadfc204d119de6e073aa28 Mon Sep 17 00:00:00 2001 From: Gregor Jasny <gregor.jasny@logmein.com> Date: Fri, 25 Jun 2021 12:26:31 +0200 Subject: [PATCH 0761/1519] ASM_NASM: Do not generate depfiles with YASM In 3aec26660a (Merge topic 'nasm_add_deps', 2021-03-03) the ASM_NASM language enabled the generation of GCC compatible depfiles for NASM. Unfortunatly, those are not supported by YASM. Fixes: #22341 --- Modules/CMakeASM_NASMInformation.cmake | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Modules/CMakeASM_NASMInformation.cmake b/Modules/CMakeASM_NASMInformation.cmake index 27b93ec0990..dad2750e800 100644 --- a/Modules/CMakeASM_NASMInformation.cmake +++ b/Modules/CMakeASM_NASMInformation.cmake @@ -38,13 +38,15 @@ if(NOT CMAKE_ASM_NASM_COMPILE_OBJECT) set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>") endif() -set(CMAKE_DEPFILE_FLAGS_ASM_NASM "-MD <DEP_FILE> -MT <DEP_TARGET>") - -if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) - AND CMAKE_GENERATOR MATCHES "Makefiles|WMake") - # dependencies are computed by the compiler itself - set(CMAKE_ASM_NASM_DEPFILE_FORMAT gcc) - set(CMAKE_ASM_NASM_DEPENDS_USE_COMPILER TRUE) +if(CMAKE_ASM_NASM_COMPILER_ID STREQUAL "NASM") + set(CMAKE_DEPFILE_FLAGS_ASM_NASM "-MD <DEP_FILE> -MT <DEP_TARGET>") + + if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake") + # dependencies are computed by the compiler itself + set(CMAKE_ASM_NASM_DEPFILE_FORMAT gcc) + set(CMAKE_ASM_NASM_DEPENDS_USE_COMPILER TRUE) + endif() endif() # Load the generic ASMInformation file: From d7159f9591282d719ec7e43af0fa3e49639f14c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= <congdanhqx@gmail.com> Date: Thu, 24 Jun 2021 21:58:51 +0700 Subject: [PATCH 0762/1519] Ninja: Fix LINK_WHAT_YOU_USE link flag placement Move `-Wl,--no-as-needed` from the `<FLAGS>` placeholder to `<LINK_FLAGS>`, as it is in the Makefile generators. Fixes: #22342 --- Source/cmNinjaNormalTargetGenerator.cxx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 9a48047be0c..5a4c6521d84 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -1156,16 +1156,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], config); + if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { + vars["LINK_FLAGS"] += " -Wl,--no-as-needed"; + } vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); vars["MANIFESTS"] = this->GetManifests(config); vars["AIX_EXPORTS"] = this->GetAIXExports(config); vars["LINK_PATH"] = frameworkPath + linkPath; - std::string lwyuFlags; - if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - lwyuFlags = " -Wl,--no-as-needed"; - } // Compute architecture specific link flags. Yes, these go into a different // variable for executables, probably due to a mistake made when duplicating @@ -1174,7 +1173,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( std::string t = vars["FLAGS"]; localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), config); - t += lwyuFlags; vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; @@ -1182,7 +1180,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( config); vars["ARCH_FLAGS"] = t; t.clear(); - t += lwyuFlags; localGen.AddLanguageFlagsForLinking( t, gt, this->TargetLinkLanguage(config), config); vars["LANGUAGE_COMPILE_FLAGS"] = t; From 43375c641830e13185d166a72563c858c0ae904d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 25 Jun 2021 09:50:18 -0400 Subject: [PATCH 0763/1519] Help: Remove unnecessary Sphinx versionadded markup in VS toolset selection In a document that says "New in version 3.14", we do not need any blocks that say "New in version 3.8". --- Help/generator/VS_TOOLSET_HOST_ARCH.txt | 18 +++++++----------- Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt | 11 +++++++++++ Help/generator/Visual Studio 12 2013.rst | 2 +- Help/generator/Visual Studio 14 2015.rst | 2 +- Help/generator/Visual Studio 15 2017.rst | 2 +- 5 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH.txt b/Help/generator/VS_TOOLSET_HOST_ARCH.txt index 069638bd2de..029363115b6 100644 --- a/Help/generator/VS_TOOLSET_HOST_ARCH.txt +++ b/Help/generator/VS_TOOLSET_HOST_ARCH.txt @@ -1,11 +1,7 @@ -.. versionadded:: 3.8 - For each toolset that comes with this version of Visual Studio, there are - variants that are themselves compiled for 32-bit (``x86``) and - 64-bit (``x64``) hosts (independent of the architecture they target). - |VS_TOOLSET_HOST_ARCH_DEFAULT| - One may explicitly request use of either the 32-bit or 64-bit host tools - by adding either ``host=x86`` or ``host=x64`` to the toolset specification. - See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. - -.. versionadded:: 3.14 - Added support for ``host=x86`` option. +For each toolset that comes with this version of Visual Studio, there are +variants that are themselves compiled for 32-bit (``x86``) and +64-bit (``x64``) hosts (independent of the architecture they target). +|VS_TOOLSET_HOST_ARCH_DEFAULT| +One may explicitly request use of either the 32-bit or 64-bit host tools +by adding either ``host=x86`` or ``host=x64`` to the toolset specification. +See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt b/Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt new file mode 100644 index 00000000000..069638bd2de --- /dev/null +++ b/Help/generator/VS_TOOLSET_HOST_ARCH_LEGACY.txt @@ -0,0 +1,11 @@ +.. versionadded:: 3.8 + For each toolset that comes with this version of Visual Studio, there are + variants that are themselves compiled for 32-bit (``x86``) and + 64-bit (``x64``) hosts (independent of the architecture they target). + |VS_TOOLSET_HOST_ARCH_DEFAULT| + One may explicitly request use of either the 32-bit or 64-bit host tools + by adding either ``host=x86`` or ``host=x64`` to the toolset specification. + See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. + +.. versionadded:: 3.14 + Added support for ``host=x86`` option. diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst index b5fa1bf490a..3b4b1f26d6a 100644 --- a/Help/generator/Visual Studio 12 2013.rst +++ b/Help/generator/Visual Studio 12 2013.rst @@ -46,4 +46,4 @@ via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 32-bit variant even on a 64-bit host. -.. include:: VS_TOOLSET_HOST_ARCH.txt +.. include:: VS_TOOLSET_HOST_ARCH_LEGACY.txt diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst index 9c616414f05..825772329d0 100644 --- a/Help/generator/Visual Studio 14 2015.rst +++ b/Help/generator/Visual Studio 14 2015.rst @@ -44,7 +44,7 @@ via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 32-bit variant even on a 64-bit host. -.. include:: VS_TOOLSET_HOST_ARCH.txt +.. include:: VS_TOOLSET_HOST_ARCH_LEGACY.txt .. _`Windows 10 SDK Maximum Version for VS 2015`: diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst index a002f2ff6d6..a80c57d822b 100644 --- a/Help/generator/Visual Studio 15 2017.rst +++ b/Help/generator/Visual Studio 15 2017.rst @@ -63,4 +63,4 @@ via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 32-bit variant even on a 64-bit host. -.. include:: VS_TOOLSET_HOST_ARCH.txt +.. include:: VS_TOOLSET_HOST_ARCH_LEGACY.txt From b610b7a35cd62ce180ef3f5be4fabd9336f3fe51 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 25 Jun 2021 09:04:56 -0400 Subject: [PATCH 0764/1519] VS: Update v142 CL flag table for VS 17.0 Preview 1 Run the command python3 Source/cmConvertMSBuildXMLToJSON.py -t v142 \ 'c:/.../MSBuild/Microsoft/VC/v160/1033/cl.xml' To generate `v142_CL.json` locally. Manually move new and updated settings over to `Templates/MSBuild/FlagTables/v142_CL.json`. --- Templates/MSBuild/FlagTables/v142_CL.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index c21a3def6ab..49776d0fe03 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -475,6 +475,13 @@ "value": "stdcpp14", "flags": [] }, + { + "name": "LanguageStandard", + "switch": "std:c++20", + "comment": "ISO C++20 Standard", + "value": "stdcpp20", + "flags": [] + }, { "name": "LanguageStandard", "switch": "std:c++17", From a95cbf389015ed71443921e5815369cff30349ee Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 25 Jun 2021 11:29:27 -0400 Subject: [PATCH 0765/1519] Tests: Shorten RunCMake.GenEx-* case names Reduce the length of the longest path on disk needed by the tests. --- ...ILE_LANGUAGE-add_custom_command-stderr.txt | 10 ------- ...PILE_LANGUAGE-add_custom_target-stderr.txt | 10 ------- .../GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake | 18 ++++++------ ...T_PROPERTY.cmake => TARGET_PROPERTY.cmake} | 0 ...sult.txt => add_custom_command-result.txt} | 0 ...derr.txt => add_custom_command-stderr.txt} | 2 +- ...command.cmake => add_custom_command.cmake} | 0 ...esult.txt => add_custom_target-result.txt} | 0 ...tderr.txt => add_custom_target-stderr.txt} | 2 +- ...m_target.cmake => add_custom_target.cmake} | 0 ...e-result.txt => add_executable-result.txt} | 0 ...t-stderr.txt => add_executable-stderr.txt} | 2 +- ..._executable.cmake => add_executable.cmake} | 0 ...rary-result.txt => add_library-result.txt} | 0 ...able-stderr.txt => add_library-stderr.txt} | 2 +- ...GE-add_library.cmake => add_library.cmake} | 0 ...dd_test-result.txt => add_test-result.txt} | 0 .../add_test-stderr.txt | 10 +++++++ ...LANGUAGE-add_test.cmake => add_test.cmake} | 0 ...-install-result.txt => install-result.txt} | 0 ...-install-stderr.txt => install-stderr.txt} | 0 ...E_LANGUAGE-install.cmake => install.cmake} | 0 ...s-result.txt => target_sources-result.txt} | 0 .../target_sources-stderr.txt | 10 +++++++ ...get_sources.cmake => target_sources.cmake} | 0 ...-unknown-lang.cmake => unknown-lang.cmake} | 0 .../RunCMakeTest.cmake | 18 ++++++------ ...T_PROPERTY.cmake => TARGET_PROPERTY.cmake} | 0 ...sult.txt => add_custom_command-result.txt} | 0 ...derr.txt => add_custom_command-stderr.txt} | 2 +- ...command.cmake => add_custom_command.cmake} | 0 ...esult.txt => add_custom_target-result.txt} | 0 ...tderr.txt => add_custom_target-stderr.txt} | 2 +- ...m_target.cmake => add_custom_target.cmake} | 0 ...e-result.txt => add_executable-result.txt} | 0 ...y-stderr.txt => add_executable-stderr.txt} | 2 +- ..._executable.cmake => add_executable.cmake} | 0 ...rary-result.txt => add_library-result.txt} | 0 ...able-stderr.txt => add_library-stderr.txt} | 2 +- ...ID-add_library.cmake => add_library.cmake} | 0 ...dd_test-result.txt => add_test-result.txt} | 0 ...dd_test-stderr.txt => add_test-stderr.txt} | 2 +- ...G_AND_ID-add_test.cmake => add_test.cmake} | 0 ...-install-result.txt => install-result.txt} | 0 ...-install-stderr.txt => install-stderr.txt} | 0 ...ANG_AND_ID-install.cmake => install.cmake} | 0 ...s-result.txt => target_sources-result.txt} | 0 ...d-stderr.txt => target_sources-stderr.txt} | 2 +- ...get_sources.cmake => target_sources.cmake} | 0 ...-unknown-lang.cmake => unknown-lang.cmake} | 0 .../GenEx-DEVICE_LINK/RunCMakeTest.cmake | 28 +++++++++---------- ...sult.txt => add_custom_command-result.txt} | 0 ...derr.txt => add_custom_command-stderr.txt} | 2 +- ...command.cmake => add_custom_command.cmake} | 0 ...esult.txt => add_custom_target-result.txt} | 0 ...tderr.txt => add_custom_target-stderr.txt} | 2 +- ...m_target.cmake => add_custom_target.cmake} | 0 ...e-result.txt => add_executable-result.txt} | 0 ...y-stderr.txt => add_executable-stderr.txt} | 2 +- ..._executable.cmake => add_executable.cmake} | 0 ...rary-result.txt => add_library-result.txt} | 0 ...rces-stderr.txt => add_library-stderr.txt} | 2 +- ...NK-add_library.cmake => add_library.cmake} | 0 ...dd_test-result.txt => add_test-result.txt} | 0 ...dd_test-stderr.txt => add_test-stderr.txt} | 2 +- ...ICE_LINK-add_test.cmake => add_test.cmake} | 0 ...-install-result.txt => install-result.txt} | 0 ...-install-stderr.txt => install-stderr.txt} | 0 ...EVICE_LINK-install.cmake => install.cmake} | 0 ...nds-result.txt => link_depends-result.txt} | 0 ...nds-stderr.txt => link_depends-stderr.txt} | 0 ...-link_depends.cmake => link_depends.cmake} | 0 ... => target_compile_definitions-result.txt} | 0 ... => target_compile_definitions-stderr.txt} | 2 +- ...cmake => target_compile_definitions.cmake} | 0 ....txt => target_compile_options-result.txt} | 0 ....txt => target_compile_options-stderr.txt} | 2 +- ...ons.cmake => target_compile_options.cmake} | 0 ... => target_include_directories-result.txt} | 0 ... => target_include_directories-stderr.txt} | 2 +- ...cmake => target_include_directories.cmake} | 0 ...txt => target_link_directories-result.txt} | 0 ...txt => target_link_directories-stderr.txt} | 2 +- ...es.cmake => target_link_directories.cmake} | 0 ...t.txt => target_link_libraries-result.txt} | 0 ...r.txt => target_link_libraries-stderr.txt} | 2 +- ...ries.cmake => target_link_libraries.cmake} | 0 ...s-result.txt => target_sources-result.txt} | 0 ...e-stderr.txt => target_sources-stderr.txt} | 2 +- ...get_sources.cmake => target_sources.cmake} | 0 ...NK-try_compile.cmake => try_compile.cmake} | 0 .../GenEx-HOST_LINK/RunCMakeTest.cmake | 28 +++++++++---------- ...sult.txt => add_custom_command-result.txt} | 0 ...derr.txt => add_custom_command-stderr.txt} | 2 +- ...command.cmake => add_custom_command.cmake} | 0 ...esult.txt => add_custom_target-result.txt} | 0 ...tderr.txt => add_custom_target-stderr.txt} | 2 +- ...m_target.cmake => add_custom_target.cmake} | 0 ...e-result.txt => add_executable-result.txt} | 0 ...y-stderr.txt => add_executable-stderr.txt} | 2 +- ..._executable.cmake => add_executable.cmake} | 0 ...rary-result.txt => add_library-result.txt} | 0 ...rces-stderr.txt => add_library-stderr.txt} | 2 +- ...NK-add_library.cmake => add_library.cmake} | 0 ...dd_test-result.txt => add_test-result.txt} | 0 ...dd_test-stderr.txt => add_test-stderr.txt} | 2 +- ...OST_LINK-add_test.cmake => add_test.cmake} | 0 ...-install-result.txt => install-result.txt} | 0 ...-install-stderr.txt => install-stderr.txt} | 0 ...{HOST_LINK-install.cmake => install.cmake} | 0 ...nds-result.txt => link_depends-result.txt} | 0 ...nds-stderr.txt => link_depends-stderr.txt} | 0 ...-link_depends.cmake => link_depends.cmake} | 0 ... => target_compile_definitions-result.txt} | 0 ... => target_compile_definitions-stderr.txt} | 2 +- ...cmake => target_compile_definitions.cmake} | 0 ....txt => target_compile_options-result.txt} | 0 ....txt => target_compile_options-stderr.txt} | 2 +- ...ons.cmake => target_compile_options.cmake} | 0 ... => target_include_directories-result.txt} | 0 ... => target_include_directories-stderr.txt} | 2 +- ...cmake => target_include_directories.cmake} | 0 ...txt => target_link_directories-result.txt} | 0 ...txt => target_link_directories-stderr.txt} | 2 +- ...es.cmake => target_link_directories.cmake} | 0 ...t.txt => target_link_libraries-result.txt} | 0 ...r.txt => target_link_libraries-stderr.txt} | 2 +- ...ries.cmake => target_link_libraries.cmake} | 0 ...s-result.txt => target_sources-result.txt} | 0 ...e-stderr.txt => target_sources-stderr.txt} | 2 +- ...get_sources.cmake => target_sources.cmake} | 0 ...NK-try_compile.cmake => try_compile.cmake} | 0 ...INK_LANGUAGE-add_custom_command-stderr.txt | 9 ------ ...LINK_LANGUAGE-add_custom_target-stderr.txt | 9 ------ .../LINK_LANGUAGE-target_sources-stderr.txt | 9 ------ .../GenEx-LINK_LANGUAGE/RunCMakeTest.cmake | 26 ++++++++--------- ...sult.txt => add_custom_command-result.txt} | 0 ...derr.txt => add_custom_command-stderr.txt} | 2 +- ...command.cmake => add_custom_command.cmake} | 0 ...esult.txt => add_custom_target-result.txt} | 0 ...tderr.txt => add_custom_target-stderr.txt} | 2 +- ...m_target.cmake => add_custom_target.cmake} | 0 ...e-result.txt => add_executable-result.txt} | 0 ...t-stderr.txt => add_executable-stderr.txt} | 2 +- ..._executable.cmake => add_executable.cmake} | 0 ...rary-result.txt => add_library-result.txt} | 0 ...rate-stderr.txt => add_library-stderr.txt} | 2 +- ...GE-add_library.cmake => add_library.cmake} | 0 ...dd_test-result.txt => add_test-result.txt} | 0 .../GenEx-LINK_LANGUAGE/add_test-stderr.txt | 9 ++++++ ...LANGUAGE-add_test.cmake => add_test.cmake} | 0 ...te-result.txt => file_generate-result.txt} | 0 .../file_generate-stderr.txt | 9 ++++++ ...ile_generate.cmake => file_generate.cmake} | 0 ...-install-result.txt => install-result.txt} | 0 ...-install-stderr.txt => install-stderr.txt} | 0 ...K_LANGUAGE-install.cmake => install.cmake} | 0 ...s-result.txt => target_sources-result.txt} | 0 .../target_sources-stderr.txt | 9 ++++++ ...get_sources.cmake => target_sources.cmake} | 0 ...-unknown-lang.cmake => unknown-lang.cmake} | 0 ...ge1-result.txt => wrong-usage1-result.txt} | 0 ...ge2-stderr.txt => wrong-usage1-stderr.txt} | 2 +- ...-wrong-usage1.cmake => wrong-usage1.cmake} | 0 ...ge2-result.txt => wrong-usage2-result.txt} | 0 ...ge3-stderr.txt => wrong-usage2-stderr.txt} | 2 +- ...-wrong-usage2.cmake => wrong-usage2.cmake} | 0 ...ge3-result.txt => wrong-usage3-result.txt} | 0 ...ge1-stderr.txt => wrong-usage3-stderr.txt} | 2 +- ...-wrong-usage3.cmake => wrong-usage3.cmake} | 0 ...ge4-result.txt => wrong-usage4-result.txt} | 0 ...ge4-stderr.txt => wrong-usage4-stderr.txt} | 2 +- ...-wrong-usage4.cmake => wrong-usage4.cmake} | 0 .../GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake | 24 ++++++++-------- ...sult.txt => add_custom_command-result.txt} | 0 ...derr.txt => add_custom_command-stderr.txt} | 2 +- ...command.cmake => add_custom_command.cmake} | 0 ...esult.txt => add_custom_target-result.txt} | 0 ...tderr.txt => add_custom_target-stderr.txt} | 2 +- ...m_target.cmake => add_custom_target.cmake} | 0 ...e-result.txt => add_executable-result.txt} | 0 ...y-stderr.txt => add_executable-stderr.txt} | 2 +- ..._executable.cmake => add_executable.cmake} | 0 ...rary-result.txt => add_library-result.txt} | 0 ...able-stderr.txt => add_library-stderr.txt} | 2 +- ...ID-add_library.cmake => add_library.cmake} | 0 ...dd_test-result.txt => add_test-result.txt} | 0 ...dd_test-stderr.txt => add_test-stderr.txt} | 2 +- ...G_AND_ID-add_test.cmake => add_test.cmake} | 0 ...te-result.txt => file_generate-result.txt} | 0 ...te-stderr.txt => file_generate-stderr.txt} | 2 +- ...ile_generate.cmake => file_generate.cmake} | 0 ...-install-result.txt => install-result.txt} | 0 ...-install-stderr.txt => install-stderr.txt} | 0 ...ANG_AND_ID-install.cmake => install.cmake} | 0 ...s-result.txt => target_sources-result.txt} | 0 ...s-stderr.txt => target_sources-stderr.txt} | 2 +- ...get_sources.cmake => target_sources.cmake} | 0 ...-unknown-lang.cmake => unknown-lang.cmake} | 0 ...ge1-result.txt => wrong-usage1-result.txt} | 0 ...ge2-stderr.txt => wrong-usage1-stderr.txt} | 2 +- ...-wrong-usage1.cmake => wrong-usage1.cmake} | 0 ...ge2-result.txt => wrong-usage2-result.txt} | 0 ...ge3-stderr.txt => wrong-usage2-stderr.txt} | 2 +- ...-wrong-usage2.cmake => wrong-usage2.cmake} | 0 ...ge3-result.txt => wrong-usage3-result.txt} | 0 ...ge1-stderr.txt => wrong-usage3-stderr.txt} | 2 +- ...-wrong-usage3.cmake => wrong-usage3.cmake} | 0 .../RunCMakeTest.cmake | 10 +++---- ...T_RUNTIME_DLLS-check.cmake => check.cmake} | 0 ...TARGET_RUNTIME_DLLS.cmake => shared.cmake} | 0 ...LS-static-result.txt => static-result.txt} | 0 ...LS-static-stderr.txt => static-stderr.txt} | 2 +- ...RUNTIME_DLLS-static.cmake => static.cmake} | 0 ...> target_link_libraries-cycle1-result.txt} | 0 ...> target_link_libraries-cycle1-stderr.txt} | 2 +- ...ake => target_link_libraries-cycle1.cmake} | 0 ...> target_link_libraries-cycle2-result.txt} | 0 ...> target_link_libraries-cycle2-stderr.txt} | 2 +- ...ake => target_link_libraries-cycle2.cmake} | 0 ...ries.cmake => target_link_libraries.cmake} | 0 221 files changed, 176 insertions(+), 176 deletions(-) delete mode 100644 Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt delete mode 100644 Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-TARGET_PROPERTY.cmake => TARGET_PROPERTY.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_custom_command-result.txt => add_custom_command-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_library-stderr.txt => add_custom_command-stderr.txt} (82%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_custom_command.cmake => add_custom_command.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_custom_target-result.txt => add_custom_target-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-target_sources-stderr.txt => add_custom_target-stderr.txt} (80%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_custom_target.cmake => add_custom_target.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_executable-result.txt => add_executable-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_test-stderr.txt => add_executable-stderr.txt} (83%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_executable.cmake => add_executable.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_library-result.txt => add_library-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_executable-stderr.txt => add_library-stderr.txt} (80%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_library.cmake => add_library.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_test-result.txt => add_test-result.txt} (100%) create mode 100644 Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-add_test.cmake => add_test.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-install-result.txt => install-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-install-stderr.txt => install-stderr.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-install.cmake => install.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-target_sources-result.txt => target_sources-result.txt} (100%) create mode 100644 Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-target_sources.cmake => target_sources.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANGUAGE/{COMPILE_LANGUAGE-unknown-lang.cmake => unknown-lang.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-TARGET_PROPERTY.cmake => TARGET_PROPERTY.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_custom_command-result.txt => add_custom_command-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-target_sources-stderr.txt => add_custom_command-stderr.txt} (73%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_custom_command.cmake => add_custom_command.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_custom_target-result.txt => add_custom_target-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_custom_target-stderr.txt => add_custom_target-stderr.txt} (82%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_custom_target.cmake => add_custom_target.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_executable-result.txt => add_executable-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_library-stderr.txt => add_executable-stderr.txt} (84%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_executable.cmake => add_executable.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_library-result.txt => add_library-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_executable-stderr.txt => add_library-stderr.txt} (83%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_library.cmake => add_library.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_test-result.txt => add_test-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_test-stderr.txt => add_test-stderr.txt} (85%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_test.cmake => add_test.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-install-result.txt => install-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-install-stderr.txt => install-stderr.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-install.cmake => install.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-target_sources-result.txt => target_sources-result.txt} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-add_custom_command-stderr.txt => target_sources-stderr.txt} (71%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-target_sources.cmake => target_sources.cmake} (100%) rename Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/{COMPILE_LANG_AND_ID-unknown-lang.cmake => unknown-lang.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_custom_command-result.txt => add_custom_command-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_custom_target-stderr.txt => add_custom_command-stderr.txt} (73%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_custom_command.cmake => add_custom_command.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_custom_target-result.txt => add_custom_target-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_custom_command-stderr.txt => add_custom_target-stderr.txt} (72%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_custom_target.cmake => add_custom_target.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_executable-result.txt => add_executable-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_library-stderr.txt => add_executable-stderr.txt} (77%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_executable.cmake => add_executable.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_library-result.txt => add_library-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_sources-stderr.txt => add_library-stderr.txt} (75%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_library.cmake => add_library.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_test-result.txt => add_test-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_test-stderr.txt => add_test-stderr.txt} (78%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_test.cmake => add_test.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-install-result.txt => install-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-install-stderr.txt => install-stderr.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-install.cmake => install.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-link_depends-result.txt => link_depends-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-link_depends-stderr.txt => link_depends-stderr.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-link_depends.cmake => link_depends.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_compile_definitions-result.txt => target_compile_definitions-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_compile_definitions-stderr.txt => target_compile_definitions-stderr.txt} (69%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_compile_definitions.cmake => target_compile_definitions.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_compile_options-result.txt => target_compile_options-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_compile_options-stderr.txt => target_compile_options-stderr.txt} (71%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_compile_options.cmake => target_compile_options.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_include_directories-result.txt => target_include_directories-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_link_directories-stderr.txt => target_include_directories-stderr.txt} (71%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_include_directories.cmake => target_include_directories.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_link_directories-result.txt => target_link_directories-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_include_directories-stderr.txt => target_link_directories-stderr.txt} (69%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_link_directories.cmake => target_link_directories.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_link_libraries-result.txt => target_link_libraries-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_link_libraries-stderr.txt => target_link_libraries-stderr.txt} (71%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_link_libraries.cmake => target_link_libraries.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_sources-result.txt => target_sources-result.txt} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-add_executable-stderr.txt => target_sources-stderr.txt} (75%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-target_sources.cmake => target_sources.cmake} (100%) rename Tests/RunCMake/GenEx-DEVICE_LINK/{DEVICE_LINK-try_compile.cmake => try_compile.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_custom_command-result.txt => add_custom_command-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_custom_target-stderr.txt => add_custom_command-stderr.txt} (73%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_custom_command.cmake => add_custom_command.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_custom_target-result.txt => add_custom_target-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_custom_command-stderr.txt => add_custom_target-stderr.txt} (73%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_custom_target.cmake => add_custom_target.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_executable-result.txt => add_executable-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_library-stderr.txt => add_executable-stderr.txt} (77%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_executable.cmake => add_executable.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_library-result.txt => add_library-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_sources-stderr.txt => add_library-stderr.txt} (75%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_library.cmake => add_library.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_test-result.txt => add_test-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_test-stderr.txt => add_test-stderr.txt} (78%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_test.cmake => add_test.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-install-result.txt => install-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-install-stderr.txt => install-stderr.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-install.cmake => install.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-link_depends-result.txt => link_depends-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-link_depends-stderr.txt => link_depends-stderr.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-link_depends.cmake => link_depends.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_compile_definitions-result.txt => target_compile_definitions-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_compile_definitions-stderr.txt => target_compile_definitions-stderr.txt} (69%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_compile_definitions.cmake => target_compile_definitions.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_compile_options-result.txt => target_compile_options-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_compile_options-stderr.txt => target_compile_options-stderr.txt} (71%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_compile_options.cmake => target_compile_options.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_include_directories-result.txt => target_include_directories-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_link_directories-stderr.txt => target_include_directories-stderr.txt} (71%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_include_directories.cmake => target_include_directories.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_link_directories-result.txt => target_link_directories-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_include_directories-stderr.txt => target_link_directories-stderr.txt} (69%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_link_directories.cmake => target_link_directories.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_link_libraries-result.txt => target_link_libraries-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_link_libraries-stderr.txt => target_link_libraries-stderr.txt} (72%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_link_libraries.cmake => target_link_libraries.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_sources-result.txt => target_sources-result.txt} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-add_executable-stderr.txt => target_sources-stderr.txt} (75%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-target_sources.cmake => target_sources.cmake} (100%) rename Tests/RunCMake/GenEx-HOST_LINK/{HOST_LINK-try_compile.cmake => try_compile.cmake} (100%) delete mode 100644 Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt delete mode 100644 Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt delete mode 100644 Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_custom_command-result.txt => add_custom_command-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_library-stderr.txt => add_custom_command-stderr.txt} (81%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_custom_command.cmake => add_custom_command.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_custom_target-result.txt => add_custom_target-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_executable-stderr.txt => add_custom_target-stderr.txt} (79%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_custom_target.cmake => add_custom_target.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_executable-result.txt => add_executable-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_test-stderr.txt => add_executable-stderr.txt} (82%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_executable.cmake => add_executable.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_library-result.txt => add_library-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-file_generate-stderr.txt => add_library-stderr.txt} (81%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_library.cmake => add_library.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_test-result.txt => add_test-result.txt} (100%) create mode 100644 Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-add_test.cmake => add_test.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-file_generate-result.txt => file_generate-result.txt} (100%) create mode 100644 Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-file_generate.cmake => file_generate.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-install-result.txt => install-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-install-stderr.txt => install-stderr.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-install.cmake => install.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-target_sources-result.txt => target_sources-result.txt} (100%) create mode 100644 Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-target_sources.cmake => target_sources.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-unknown-lang.cmake => unknown-lang.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage1-result.txt => wrong-usage1-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage2-stderr.txt => wrong-usage1-stderr.txt} (77%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage1.cmake => wrong-usage1.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage2-result.txt => wrong-usage2-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage3-stderr.txt => wrong-usage2-stderr.txt} (77%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage2.cmake => wrong-usage2.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage3-result.txt => wrong-usage3-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage1-stderr.txt => wrong-usage3-stderr.txt} (77%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage3.cmake => wrong-usage3.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage4-result.txt => wrong-usage4-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage4-stderr.txt => wrong-usage4-stderr.txt} (72%) rename Tests/RunCMake/GenEx-LINK_LANGUAGE/{LINK_LANGUAGE-wrong-usage4.cmake => wrong-usage4.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_custom_command-result.txt => add_custom_command-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_custom_target-stderr.txt => add_custom_command-stderr.txt} (78%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_custom_command.cmake => add_custom_command.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_custom_target-result.txt => add_custom_target-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_custom_command-stderr.txt => add_custom_target-stderr.txt} (77%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_custom_target.cmake => add_custom_target.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_executable-result.txt => add_executable-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_library-stderr.txt => add_executable-stderr.txt} (80%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_executable.cmake => add_executable.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_library-result.txt => add_library-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_executable-stderr.txt => add_library-stderr.txt} (79%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_library.cmake => add_library.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_test-result.txt => add_test-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_test-stderr.txt => add_test-stderr.txt} (82%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-add_test.cmake => add_test.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-file_generate-result.txt => file_generate-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-file_generate-stderr.txt => file_generate-stderr.txt} (81%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-file_generate.cmake => file_generate.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-install-result.txt => install-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-install-stderr.txt => install-stderr.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-install.cmake => install.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-target_sources-result.txt => target_sources-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-target_sources-stderr.txt => target_sources-stderr.txt} (73%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-target_sources.cmake => target_sources.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-unknown-lang.cmake => unknown-lang.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage1-result.txt => wrong-usage1-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage2-stderr.txt => wrong-usage1-stderr.txt} (78%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage1.cmake => wrong-usage1.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage2-result.txt => wrong-usage2-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage3-stderr.txt => wrong-usage2-stderr.txt} (77%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage2.cmake => wrong-usage2.cmake} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage3-result.txt => wrong-usage3-result.txt} (100%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage1-stderr.txt => wrong-usage3-stderr.txt} (77%) rename Tests/RunCMake/GenEx-LINK_LANG_AND_ID/{LINK_LANG_AND_ID-wrong-usage3.cmake => wrong-usage3.cmake} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-check.cmake => check.cmake} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS.cmake => shared.cmake} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-static-result.txt => static-result.txt} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-static-stderr.txt => static-stderr.txt} (80%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-static.cmake => static.cmake} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt => target_link_libraries-cycle1-result.txt} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt => target_link_libraries-cycle1-stderr.txt} (64%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake => target_link_libraries-cycle1.cmake} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt => target_link_libraries-cycle2-result.txt} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt => target_link_libraries-cycle2-stderr.txt} (65%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake => target_link_libraries-cycle2.cmake} (100%) rename Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/{TARGET_RUNTIME_DLLS-target_link_libraries.cmake => target_link_libraries.cmake} (100%) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt deleted file mode 100644 index c8f773a0a55..00000000000 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-stderr.txt +++ /dev/null @@ -1,10 +0,0 @@ -CMake Error at COMPILE_LANGUAGE-add_custom_command.cmake:2 \(add_custom_command\): - Error evaluating generator expression: - - \$<COMPILE_LANGUAGE> - - \$<COMPILE_LANGUAGE:...> may only be used to specify include directories, - compile definitions, compile options, and to evaluate components of the - file\(GENERATE\) command. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt deleted file mode 100644 index 7025838b175..00000000000 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-stderr.txt +++ /dev/null @@ -1,10 +0,0 @@ -CMake Error at COMPILE_LANGUAGE-add_custom_target.cmake:1 \(add_custom_target\): - Error evaluating generator expression: - - \$<COMPILE_LANGUAGE> - - \$<COMPILE_LANGUAGE:...> may only be used to specify include directories, - compile definitions, compile options, and to evaluate components of the - file\(GENERATE\) command. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake index 15a5e79eb48..3e6e08083b9 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/RunCMakeTest.cmake @@ -1,11 +1,11 @@ include(RunCMake) -run_cmake(COMPILE_LANGUAGE-add_custom_target) -run_cmake(COMPILE_LANGUAGE-add_custom_command) -run_cmake(COMPILE_LANGUAGE-install) -run_cmake(COMPILE_LANGUAGE-target_sources) -run_cmake(COMPILE_LANGUAGE-add_executable) -run_cmake(COMPILE_LANGUAGE-add_library) -run_cmake(COMPILE_LANGUAGE-add_test) -run_cmake(COMPILE_LANGUAGE-unknown-lang) -run_cmake(COMPILE_LANGUAGE-TARGET_PROPERTY) +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(install) +run_cmake(target_sources) +run_cmake(add_executable) +run_cmake(add_library) +run_cmake(add_test) +run_cmake(unknown-lang) +run_cmake(TARGET_PROPERTY) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-TARGET_PROPERTY.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/TARGET_PROPERTY.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-TARGET_PROPERTY.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/TARGET_PROPERTY.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-stderr.txt similarity index 82% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-stderr.txt index 2ac9b76ac5e..72f0fc85722 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANGUAGE-add_library.cmake:1 \(add_library\): +CMake Error at add_custom_command.cmake:2 \(add_custom_command\): Error evaluating generator expression: \$<COMPILE_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_command.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_command.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-stderr.txt similarity index 80% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-stderr.txt index 8e7f88125c9..a8ef8d7443f 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANGUAGE-target_sources.cmake:2 \(target_sources\): +CMake Error at add_custom_target.cmake:1 \(add_custom_target\): Error evaluating generator expression: \$<COMPILE_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_custom_target.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_custom_target.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-stderr.txt similarity index 83% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-stderr.txt index fd8a731f138..2e7cc3e62fd 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANGUAGE-add_test.cmake:5 \(add_test\): +CMake Error at add_executable.cmake:1 \(add_executable\): Error evaluating generator expression: \$<COMPILE_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_executable.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-stderr.txt similarity index 80% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-stderr.txt index 8d05e59a0ef..ffbac65991f 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_executable-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANGUAGE-add_executable.cmake:1 \(add_executable\): +CMake Error at add_library.cmake:1 \(add_library\): Error evaluating generator expression: \$<COMPILE_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_library.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_library.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt new file mode 100644 index 00000000000..2f13655f128 --- /dev/null +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at add_test.cmake:5 \(add_test\): + Error evaluating generator expression: + + \$<COMPILE_LANGUAGE> + + \$<COMPILE_LANGUAGE:...> may only be used to specify include directories, + compile definitions, compile options, and to evaluate components of the + file\(GENERATE\) command. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-add_test.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/add_test.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install-stderr.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-install.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/install.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt new file mode 100644 index 00000000000..f552e956da9 --- /dev/null +++ b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at target_sources.cmake:2 \(target_sources\): + Error evaluating generator expression: + + \$<COMPILE_LANGUAGE> + + \$<COMPILE_LANGUAGE:...> may only be used to specify include directories, + compile definitions, compile options, and to evaluate components of the + file\(GENERATE\) command. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-target_sources.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/target_sources.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-unknown-lang.cmake b/Tests/RunCMake/GenEx-COMPILE_LANGUAGE/unknown-lang.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANGUAGE/COMPILE_LANGUAGE-unknown-lang.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANGUAGE/unknown-lang.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake index 68bd05d2e1e..3e6e08083b9 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/RunCMakeTest.cmake @@ -1,11 +1,11 @@ include(RunCMake) -run_cmake(COMPILE_LANG_AND_ID-add_custom_target) -run_cmake(COMPILE_LANG_AND_ID-add_custom_command) -run_cmake(COMPILE_LANG_AND_ID-install) -run_cmake(COMPILE_LANG_AND_ID-target_sources) -run_cmake(COMPILE_LANG_AND_ID-add_executable) -run_cmake(COMPILE_LANG_AND_ID-add_library) -run_cmake(COMPILE_LANG_AND_ID-add_test) -run_cmake(COMPILE_LANG_AND_ID-unknown-lang) -run_cmake(COMPILE_LANG_AND_ID-TARGET_PROPERTY) +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(install) +run_cmake(target_sources) +run_cmake(add_executable) +run_cmake(add_library) +run_cmake(add_test) +run_cmake(unknown-lang) +run_cmake(TARGET_PROPERTY) diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-TARGET_PROPERTY.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/TARGET_PROPERTY.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-TARGET_PROPERTY.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/TARGET_PROPERTY.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-stderr.txt similarity index 73% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-stderr.txt index 3ecbdc36089..0c3c3f9f6b4 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANG_AND_ID-target_sources.cmake:2 \(target_sources\): +CMake Error at add_custom_command.cmake:2 \(add_custom_command\): Error evaluating generator expression: \$<COMPILE_LANG_AND_ID> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_command.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-stderr.txt similarity index 82% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-stderr.txt index 589e64b4ec5..ae85ca6c0a1 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANG_AND_ID-add_custom_target.cmake:2 \(add_custom_target\): +CMake Error at add_custom_target.cmake:2 \(add_custom_target\): Error evaluating generator expression: \$<COMPILE_LANG_AND_ID:LANG,ID> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_target.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_custom_target.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-stderr.txt similarity index 84% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-stderr.txt index 4cbf000ea03..ed03f204b3d 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANG_AND_ID-add_library.cmake:2 \(add_library\): +CMake Error at add_executable.cmake:1 \(add_executable\): Error evaluating generator expression: \$<COMPILE_LANG_AND_ID:C,MSVC> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_executable.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-stderr.txt similarity index 83% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-stderr.txt index 3b3f38d370e..0014c16c40d 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_executable-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANG_AND_ID-add_executable.cmake:1 \(add_executable\): +CMake Error at add_library.cmake:2 \(add_library\): Error evaluating generator expression: \$<COMPILE_LANG_AND_ID:C,MSVC> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_library.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_library.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-stderr.txt similarity index 85% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-stderr.txt index 26a5940f3ba..73b1a7d15fe 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANG_AND_ID-add_test.cmake:5 \(add_test\): +CMake Error at add_test.cmake:5 \(add_test\): Error evaluating generator expression: \$<COMPILE_LANG_AND_ID:CXX,GNU> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_test.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/add_test.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install-stderr.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-install.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/install.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-result.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources-result.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-result.txt diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-stderr.txt similarity index 71% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-stderr.txt index 2ee96ed14c3..ea6fbbf44b2 100644 --- a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-add_custom_command-stderr.txt +++ b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at COMPILE_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_command\): +CMake Error at target_sources.cmake:2 \(target_sources\): Error evaluating generator expression: \$<COMPILE_LANG_AND_ID> diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-target_sources.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/target_sources.cmake diff --git a/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-unknown-lang.cmake b/Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/unknown-lang.cmake similarity index 100% rename from Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/COMPILE_LANG_AND_ID-unknown-lang.cmake rename to Tests/RunCMake/GenEx-COMPILE_LANG_AND_ID/unknown-lang.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake index 80633e2580e..1ce98f0fd28 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/RunCMakeTest.cmake @@ -1,18 +1,18 @@ include(RunCMake) -run_cmake(DEVICE_LINK-add_custom_target) -run_cmake(DEVICE_LINK-add_custom_command) -run_cmake(DEVICE_LINK-install) -run_cmake(DEVICE_LINK-add_executable) -run_cmake(DEVICE_LINK-add_library) -run_cmake(DEVICE_LINK-add_test) -run_cmake(DEVICE_LINK-target_sources) -run_cmake(DEVICE_LINK-target_compile_definitions) -run_cmake(DEVICE_LINK-target_compile_options) -run_cmake(DEVICE_LINK-target_include_directories) -run_cmake(DEVICE_LINK-target_link_libraries) -run_cmake(DEVICE_LINK-target_link_directories) -run_cmake(DEVICE_LINK-try_compile) +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(install) +run_cmake(add_executable) +run_cmake(add_library) +run_cmake(add_test) +run_cmake(target_sources) +run_cmake(target_compile_definitions) +run_cmake(target_compile_options) +run_cmake(target_include_directories) +run_cmake(target_link_libraries) +run_cmake(target_link_directories) +run_cmake(try_compile) if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)") - run_cmake(DEVICE_LINK-link_depends) + run_cmake(link_depends) endif() diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-stderr.txt similarity index 73% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-stderr.txt index cdd3043a280..273c3b2be18 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-add_custom_target.cmake:[0-9]+ \(add_custom_target\): +CMake Error at add_custom_command.cmake:[0-9]+ \(add_custom_command\): Error evaluating generator expression: \$<DEVICE_LINK> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_command.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-stderr.txt similarity index 72% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-stderr.txt index eb15834c5f5..0c015fa6f6c 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_command-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-add_custom_command.cmake:[0-9]+ \(add_custom_command\): +CMake Error at add_custom_target.cmake:[0-9]+ \(add_custom_target\): Error evaluating generator expression: \$<DEVICE_LINK> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_custom_target.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_custom_target.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-stderr.txt index 4477e00ae59..3d5bfb37209 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-add_library.cmake:[0-9]+ \(add_library\): +CMake Error at add_executable.cmake:[0-9]+ \(add_executable\): Error evaluating generator expression: \$<DEVICE_LINK:empty.c> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_executable.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_executable.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_library-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-stderr.txt similarity index 75% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_library-stderr.txt index c9b602d8426..5b8448b6968 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-target_sources.cmake:[0-9]+ \(target_sources\): +CMake Error at add_library.cmake:[0-9]+ \(add_library\): Error evaluating generator expression: \$<DEVICE_LINK:empty.c> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_library.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_library.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_library.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_test-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-stderr.txt similarity index 78% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_test-stderr.txt index 99561fe2ccc..56f8ce7e699 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-add_test.cmake:[0-9]+ \(add_test\): +CMake Error at add_test.cmake:[0-9]+ \(add_test\): Error evaluating generator expression: \$<DEVICE_LINK> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/add_test.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_test.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/add_test.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/install-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/install-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/install-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/install-stderr.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/install.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-install.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/install.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/link_depends-stderr.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/link_depends.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-link_depends.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/link_depends.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-stderr.txt similarity index 69% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-stderr.txt index c0185e3a7a0..e6bd546a4da 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\): +CMake Error at target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\): Error evaluating generator expression: \$<DEVICE_LINK:DEF> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_definitions.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_definitions.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-stderr.txt similarity index 71% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-stderr.txt index 34ca4f23693..31e0eca5c35 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-target_compile_options.cmake:[0-9]+ \(target_compile_options\): +CMake Error at target_compile_options.cmake:[0-9]+ \(target_compile_options\): Error evaluating generator expression: \$<DEVICE_LINK:-OPT> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_compile_options.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_compile_options.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-stderr.txt similarity index 71% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-stderr.txt index d924916a5b8..b104e1bee5d 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-target_link_directories.cmake:[0-9]+ \(target_link_directories\): +CMake Error at target_include_directories.cmake:[0-9]+ \(target_include_directories\): Error evaluating generator expression: \$<DEVICE_LINK:/DIR> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_include_directories.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-stderr.txt similarity index 69% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-stderr.txt index 4d1642d7812..a2f9c52d635 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_include_directories-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-target_include_directories.cmake:[0-9]+ \(target_include_directories\): +CMake Error at target_link_directories.cmake:[0-9]+ \(target_link_directories\): Error evaluating generator expression: \$<DEVICE_LINK:/DIR> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_directories.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_link_directories.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-stderr.txt similarity index 71% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-stderr.txt index 1436fa8fed5..ce2aeee24e0 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-target_link_libraries.cmake:[0-9]+ \(target_link_libraries\): +CMake Error at target_link_libraries.cmake:[0-9]+ \(target_link_libraries\): Error evaluating generator expression: \$<DEVICE_LINK:lib> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_link_libraries.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_link_libraries.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-result.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources-result.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-result.txt diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-stderr.txt b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-stderr.txt similarity index 75% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-stderr.txt rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-stderr.txt index 56b595c7451..341b0f88507 100644 --- a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-add_executable-stderr.txt +++ b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at DEVICE_LINK-add_executable.cmake:[0-9]+ \(add_executable\): +CMake Error at target_sources.cmake:[0-9]+ \(target_sources\): Error evaluating generator expression: \$<DEVICE_LINK:empty.c> diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/target_sources.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-target_sources.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/target_sources.cmake diff --git a/Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake b/Tests/RunCMake/GenEx-DEVICE_LINK/try_compile.cmake similarity index 100% rename from Tests/RunCMake/GenEx-DEVICE_LINK/DEVICE_LINK-try_compile.cmake rename to Tests/RunCMake/GenEx-DEVICE_LINK/try_compile.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake index 9e3eeec4161..1ce98f0fd28 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-HOST_LINK/RunCMakeTest.cmake @@ -1,18 +1,18 @@ include(RunCMake) -run_cmake(HOST_LINK-add_custom_target) -run_cmake(HOST_LINK-add_custom_command) -run_cmake(HOST_LINK-install) -run_cmake(HOST_LINK-add_executable) -run_cmake(HOST_LINK-add_library) -run_cmake(HOST_LINK-add_test) -run_cmake(HOST_LINK-target_sources) -run_cmake(HOST_LINK-target_compile_definitions) -run_cmake(HOST_LINK-target_compile_options) -run_cmake(HOST_LINK-target_include_directories) -run_cmake(HOST_LINK-target_link_libraries) -run_cmake(HOST_LINK-target_link_directories) -run_cmake(HOST_LINK-try_compile) +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(install) +run_cmake(add_executable) +run_cmake(add_library) +run_cmake(add_test) +run_cmake(target_sources) +run_cmake(target_compile_definitions) +run_cmake(target_compile_options) +run_cmake(target_include_directories) +run_cmake(target_link_libraries) +run_cmake(target_link_directories) +run_cmake(try_compile) if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)") - run_cmake(HOST_LINK-link_depends) + run_cmake(link_depends) endif() diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-stderr.txt similarity index 73% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-stderr.txt index c44202a70c5..0eb5e3388b6 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-add_custom_target.cmake:[0-9]+ \(add_custom_target\): +CMake Error at add_custom_command.cmake:[0-9]+ \(add_custom_command\): Error evaluating generator expression: \$<HOST_LINK> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_command.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/add_custom_command.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-stderr.txt similarity index 73% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-stderr.txt index 5ad41b96d82..ffb0c3dcdcc 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_command-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-add_custom_command.cmake:[0-9]+ \(add_custom_command\): +CMake Error at add_custom_target.cmake:[0-9]+ \(add_custom_target\): Error evaluating generator expression: \$<HOST_LINK> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_custom_target.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_custom_target.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/add_custom_target.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_executable-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_executable-stderr.txt index 4bd27bec973..59732d8d0bf 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/add_executable-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-add_library.cmake:[0-9]+ \(add_library\): +CMake Error at add_executable.cmake:[0-9]+ \(add_executable\): Error evaluating generator expression: \$<HOST_LINK:empty.c> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_executable.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/add_executable.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_library-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_library-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_library-stderr.txt similarity index 75% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_library-stderr.txt index 0e255681251..4e9fea10b62 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/add_library-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-target_sources.cmake:[0-9]+ \(target_sources\): +CMake Error at add_library.cmake:[0-9]+ \(add_library\): Error evaluating generator expression: \$<HOST_LINK:empty.c> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_library.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_library.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/add_library.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_test-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_test-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/add_test-stderr.txt similarity index 78% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/add_test-stderr.txt index 012ad210a64..11912ddee54 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/add_test-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-add_test.cmake:[0-9]+ \(add_test\): +CMake Error at add_test.cmake:[0-9]+ \(add_test\): Error evaluating generator expression: \$<HOST_LINK> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test.cmake b/Tests/RunCMake/GenEx-HOST_LINK/add_test.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_test.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/add_test.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/install-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/install-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/install-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/install-stderr.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install.cmake b/Tests/RunCMake/GenEx-HOST_LINK/install.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-install.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/install.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/link_depends-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/link_depends-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/link_depends-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/link_depends-stderr.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends.cmake b/Tests/RunCMake/GenEx-HOST_LINK/link_depends.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-link_depends.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/link_depends.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-stderr.txt similarity index 69% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-stderr.txt index 6ab3c14d88a..09982e10817 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\): +CMake Error at target_compile_definitions.cmake:[0-9]+ \(target_compile_definitions\): Error evaluating generator expression: \$<HOST_LINK:DEF> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_definitions.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/target_compile_definitions.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-stderr.txt similarity index 71% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-stderr.txt index 0f5bbc38c6a..42ff6635f2e 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-target_compile_options.cmake:[0-9]+ \(target_compile_options\): +CMake Error at target_compile_options.cmake:[0-9]+ \(target_compile_options\): Error evaluating generator expression: \$<HOST_LINK:-OPT> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_compile_options.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_compile_options.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/target_compile_options.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-stderr.txt similarity index 71% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-stderr.txt index 5225a52531c..1c83da30779 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-target_link_directories.cmake:[0-9]+ \(target_link_directories\): +CMake Error at target_include_directories.cmake:[0-9]+ \(target_include_directories\): Error evaluating generator expression: \$<HOST_LINK:/DIR> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_include_directories.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/target_include_directories.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-stderr.txt similarity index 69% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-stderr.txt index 9a2634a22a2..0b54018092f 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_include_directories-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-target_include_directories.cmake:[0-9]+ \(target_include_directories\): +CMake Error at target_link_directories.cmake:[0-9]+ \(target_link_directories\): Error evaluating generator expression: \$<HOST_LINK:/DIR> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_link_directories.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_directories.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/target_link_directories.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-stderr.txt similarity index 72% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-stderr.txt index 6c4441f3c4f..bf46e3ad4fc 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-target_link_libraries.cmake:[0-9]+ \(target_link_libraries\): +CMake Error at target_link_libraries.cmake:[0-9]+ \(target_link_libraries\): Error evaluating generator expression: \$<HOST_LINK:lib> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_link_libraries.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/target_link_libraries.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-result.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources-result.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_sources-result.txt diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-stderr.txt b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-stderr.txt similarity index 75% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-stderr.txt rename to Tests/RunCMake/GenEx-HOST_LINK/target_sources-stderr.txt index b3955157780..547c2e544f0 100644 --- a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-add_executable-stderr.txt +++ b/Tests/RunCMake/GenEx-HOST_LINK/target_sources-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at HOST_LINK-add_executable.cmake:[0-9]+ \(add_executable\): +CMake Error at target_sources.cmake:[0-9]+ \(target_sources\): Error evaluating generator expression: \$<HOST_LINK:empty.c> diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources.cmake b/Tests/RunCMake/GenEx-HOST_LINK/target_sources.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-target_sources.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/target_sources.cmake diff --git a/Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake b/Tests/RunCMake/GenEx-HOST_LINK/try_compile.cmake similarity index 100% rename from Tests/RunCMake/GenEx-HOST_LINK/HOST_LINK-try_compile.cmake rename to Tests/RunCMake/GenEx-HOST_LINK/try_compile.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt deleted file mode 100644 index 0b0d458fd82..00000000000 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-stderr.txt +++ /dev/null @@ -1,9 +0,0 @@ -CMake Error at LINK_LANGUAGE-add_custom_command.cmake:2 \(add_custom_command\): - Error evaluating generator expression: - - \$<LINK_LANGUAGE> - - \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link - libraries, link directories, link options and link depends. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt deleted file mode 100644 index 92da6345425..00000000000 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-stderr.txt +++ /dev/null @@ -1,9 +0,0 @@ -CMake Error at LINK_LANGUAGE-add_custom_target.cmake:1 \(add_custom_target\): - Error evaluating generator expression: - - \$<LINK_LANGUAGE> - - \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link - libraries, link directories, link options and link depends. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt deleted file mode 100644 index d8121cce691..00000000000 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-stderr.txt +++ /dev/null @@ -1,9 +0,0 @@ -CMake Error at LINK_LANGUAGE-target_sources.cmake:2 \(target_sources\): - Error evaluating generator expression: - - \$<LINK_LANGUAGE> - - \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link - libraries, link directories, link options and link depends. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake index 4cf0c047dce..53320ac5a9f 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/RunCMakeTest.cmake @@ -1,15 +1,15 @@ include(RunCMake) -run_cmake(LINK_LANGUAGE-add_custom_target) -run_cmake(LINK_LANGUAGE-add_custom_command) -run_cmake(LINK_LANGUAGE-install) -run_cmake(LINK_LANGUAGE-target_sources) -run_cmake(LINK_LANGUAGE-add_executable) -run_cmake(LINK_LANGUAGE-add_library) -run_cmake(LINK_LANGUAGE-add_test) -run_cmake(LINK_LANGUAGE-unknown-lang) -run_cmake(LINK_LANGUAGE-wrong-usage1) -run_cmake(LINK_LANGUAGE-wrong-usage2) -run_cmake(LINK_LANGUAGE-wrong-usage3) -run_cmake(LINK_LANGUAGE-wrong-usage4) -run_cmake(LINK_LANGUAGE-file_generate) +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(install) +run_cmake(target_sources) +run_cmake(add_executable) +run_cmake(add_library) +run_cmake(add_test) +run_cmake(unknown-lang) +run_cmake(wrong-usage1) +run_cmake(wrong-usage2) +run_cmake(wrong-usage3) +run_cmake(wrong-usage4) +run_cmake(file_generate) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-stderr.txt similarity index 81% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-stderr.txt index 1bacdeb4c86..2ac7add7650 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-add_library.cmake:1 \(add_library\): +CMake Error at add_custom_command.cmake:2 \(add_custom_command\): Error evaluating generator expression: \$<LINK_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_command.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_command.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-stderr.txt similarity index 79% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-stderr.txt index 3bdc8e493e5..5e54baefdfe 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-add_executable.cmake:1 \(add_executable\): +CMake Error at add_custom_target.cmake:1 \(add_custom_target\): Error evaluating generator expression: \$<LINK_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_custom_target.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_custom_target.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-stderr.txt similarity index 82% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-stderr.txt index f22efde7ecd..06c00fcfee2 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-add_test.cmake:5 \(add_test\): +CMake Error at add_executable.cmake:1 \(add_executable\): Error evaluating generator expression: \$<LINK_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_executable.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_executable.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-stderr.txt similarity index 81% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-stderr.txt index 21d26de5f16..6e312a14e8c 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-file_generate.cmake:3 \(file\): +CMake Error at add_library.cmake:1 \(add_library\): Error evaluating generator expression: \$<LINK_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_library.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_library.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt new file mode 100644 index 00000000000..3deb92326ec --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at add_test.cmake:5 \(add_test\): + Error evaluating generator expression: + + \$<LINK_LANGUAGE> + + \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link + libraries, link directories, link options and link depends. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-add_test.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/add_test.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt new file mode 100644 index 00000000000..0e3d6814e69 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at file_generate.cmake:3 \(file\): + Error evaluating generator expression: + + \$<LINK_LANGUAGE> + + \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link + libraries, link directories, link options and link depends. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-file_generate.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/file_generate.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/install-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/install-stderr.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/install.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-install.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/install.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt new file mode 100644 index 00000000000..4c63a6e6c9c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at target_sources.cmake:2 \(target_sources\): + Error evaluating generator expression: + + \$<LINK_LANGUAGE> + + \$<LINK_LANGUAGE:...> may only be used with binary targets to specify link + libraries, link directories, link options and link depends. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-target_sources.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/target_sources.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-unknown-lang.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/unknown-lang.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-unknown-lang.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/unknown-lang.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-stderr.txt index 7fe43101bc6..58562b3b71c 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-wrong-usage2.cmake:4 \(target_compile_options\): +CMake Error at wrong-usage1.cmake:4 \(target_compile_definitions\): Error evaluating generator expression: \$<LINK_LANGUAGE:C> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage1.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-stderr.txt index cb20e996ded..46fbc674952 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-wrong-usage3.cmake:4 \(target_include_directories\): +CMake Error at wrong-usage2.cmake:4 \(target_compile_options\): Error evaluating generator expression: \$<LINK_LANGUAGE:C> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage2.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage2.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-stderr.txt index 1e3a83b9270..2cabc904826 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage1-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-wrong-usage1.cmake:4 \(target_compile_definitions\): +CMake Error at wrong-usage3.cmake:4 \(target_include_directories\): Error evaluating generator expression: \$<LINK_LANGUAGE:C> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage3.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage3.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-result.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-result.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-stderr.txt similarity index 72% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-stderr.txt index ee36912dfe0..3679760049e 100644 --- a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANGUAGE-wrong-usage4.cmake:7 \(target_link_libraries\): +CMake Error at wrong-usage4.cmake:7 \(target_link_libraries\): Error evaluating generator expression: \$<LINK_LANGUAGE> diff --git a/Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4.cmake b/Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANGUAGE/LINK_LANGUAGE-wrong-usage4.cmake rename to Tests/RunCMake/GenEx-LINK_LANGUAGE/wrong-usage4.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake index 5bb6590a6cd..74a179c25ac 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/RunCMakeTest.cmake @@ -1,14 +1,14 @@ include(RunCMake) -run_cmake(LINK_LANG_AND_ID-add_custom_target) -run_cmake(LINK_LANG_AND_ID-add_custom_command) -run_cmake(LINK_LANG_AND_ID-install) -run_cmake(LINK_LANG_AND_ID-target_sources) -run_cmake(LINK_LANG_AND_ID-add_executable) -run_cmake(LINK_LANG_AND_ID-add_library) -run_cmake(LINK_LANG_AND_ID-add_test) -run_cmake(LINK_LANG_AND_ID-unknown-lang) -run_cmake(LINK_LANG_AND_ID-wrong-usage1) -run_cmake(LINK_LANG_AND_ID-wrong-usage2) -run_cmake(LINK_LANG_AND_ID-wrong-usage3) -run_cmake(LINK_LANG_AND_ID-file_generate) +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(install) +run_cmake(target_sources) +run_cmake(add_executable) +run_cmake(add_library) +run_cmake(add_test) +run_cmake(unknown-lang) +run_cmake(wrong-usage1) +run_cmake(wrong-usage2) +run_cmake(wrong-usage3) +run_cmake(file_generate) diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-stderr.txt similarity index 78% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-stderr.txt index 0749c449aab..412e3adb258 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-add_custom_target.cmake:2 \(add_custom_target\): +CMake Error at add_custom_command.cmake:2 \(add_custom_command\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:LANG,ID> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_command.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-stderr.txt index 2ff62bc424d..a927b208ae2 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_command-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_command\): +CMake Error at add_custom_target.cmake:2 \(add_custom_target\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:LANG,ID> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_custom_target.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_custom_target.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-stderr.txt similarity index 80% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-stderr.txt index be46e287a1c..c58cbdf1261 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-add_library.cmake:2 \(add_library\): +CMake Error at add_executable.cmake:1 \(add_executable\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:C,MSVC> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_executable.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-stderr.txt similarity index 79% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-stderr.txt index 595312a72f4..46a32d0200e 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_executable-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-add_executable.cmake:1 \(add_executable\): +CMake Error at add_library.cmake:2 \(add_library\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:C,MSVC> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_library.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_library.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-stderr.txt similarity index 82% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-stderr.txt index 2a29492e841..989329868df 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-add_test.cmake:5 \(add_test\): +CMake Error at add_test.cmake:5 \(add_test\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:CXX,GNU> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-add_test.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/add_test.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-stderr.txt similarity index 81% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-stderr.txt index e57b55c1c74..fa05f8d901a 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-file_generate.cmake:3 \(file\): +CMake Error at file_generate.cmake:3 \(file\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:C,GNU> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-file_generate.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/file_generate.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-stderr.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install-stderr.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-install.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/install.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-stderr.txt similarity index 73% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-stderr.txt index e86602a0f1e..aecf1245b20 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-target_sources.cmake:2 \(target_sources\): +CMake Error at target_sources.cmake:2 \(target_sources\): Error evaluating generator expression: \$<LINK_LANG_AND_ID> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-target_sources.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/target_sources.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-unknown-lang.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/unknown-lang.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-unknown-lang.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/unknown-lang.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-stderr.txt similarity index 78% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-stderr.txt index 53bdcb2a501..729cc2f1aeb 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-wrong-usage2.cmake:4 \(target_compile_options\): +CMake Error at wrong-usage1.cmake:4 \(target_compile_definitions\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:C,GNU> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage1.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-stderr.txt index a34a2ea5798..786c16d1c7f 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-wrong-usage3.cmake:4 \(target_include_directories\): +CMake Error at wrong-usage2.cmake:4 \(target_compile_options\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:C,GNU> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage2.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage2.cmake diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-result.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3-result.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-result.txt diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-stderr.txt b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-stderr.txt similarity index 77% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-stderr.txt rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-stderr.txt index 95611c310f6..31679a125f0 100644 --- a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage1-stderr.txt +++ b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at LINK_LANG_AND_ID-wrong-usage1.cmake:4 \(target_compile_definitions\): +CMake Error at wrong-usage3.cmake:4 \(target_include_directories\): Error evaluating generator expression: \$<LINK_LANG_AND_ID:C,GNU> diff --git a/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3.cmake b/Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3.cmake similarity index 100% rename from Tests/RunCMake/GenEx-LINK_LANG_AND_ID/LINK_LANG_AND_ID-wrong-usage3.cmake rename to Tests/RunCMake/GenEx-LINK_LANG_AND_ID/wrong-usage3.cmake diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake index edc495c94cb..a48b525bbaa 100644 --- a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/RunCMakeTest.cmake @@ -1,7 +1,7 @@ include(RunCMake) -run_cmake(TARGET_RUNTIME_DLLS) -run_cmake(TARGET_RUNTIME_DLLS-static) -run_cmake(TARGET_RUNTIME_DLLS-target_link_libraries) -run_cmake(TARGET_RUNTIME_DLLS-target_link_libraries-cycle1) -run_cmake(TARGET_RUNTIME_DLLS-target_link_libraries-cycle2) +run_cmake(shared) +run_cmake(static) +run_cmake(target_link_libraries) +run_cmake(target_link_libraries-cycle1) +run_cmake(target_link_libraries-cycle2) diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-check.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-check.cmake rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/check.cmake diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS.cmake rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/shared.cmake diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-result.txt rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-result.txt diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt similarity index 80% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt index 7ce588a7421..af68c9689ad 100644 --- a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static-stderr.txt +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at TARGET_RUNTIME_DLLS-static\.cmake:[0-9]+ \(file\): +CMake Error at static\.cmake:[0-9]+ \(file\): Error evaluating generator expression: \$<TARGET_RUNTIME_DLLS:static> diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.cmake similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-static.cmake rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/static.cmake diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-result.txt rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-result.txt diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt similarity index 64% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt index 8cfcf7e41a1..b6ae09941ef 100644 --- a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1-stderr.txt +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at TARGET_RUNTIME_DLLS-target_link_libraries-cycle1\.cmake:[0-9]+ \(add_library\): +CMake Error at target_link_libraries-cycle1\.cmake:[0-9]+ \(add_library\): The SOURCES of "lib1" use a generator expression that depends on the SOURCES themselves\. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1.cmake similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle1.cmake rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle1.cmake diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-result.txt similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-result.txt rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-result.txt diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt similarity index 65% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt index bacbf63b7d4..9a845f967e9 100644 --- a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2-stderr.txt +++ b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at TARGET_RUNTIME_DLLS-target_link_libraries-cycle2\.cmake:[0-9]+ \(add_library\): +CMake Error at target_link_libraries-cycle2\.cmake:[0-9]+ \(add_library\): The SOURCES of "(lib1|lib2)" use a generator expression that depends on the SOURCES themselves\. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2.cmake similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries-cycle2.cmake rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries-cycle2.cmake diff --git a/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries.cmake b/Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries.cmake similarity index 100% rename from Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/TARGET_RUNTIME_DLLS-target_link_libraries.cmake rename to Tests/RunCMake/GenEx-TARGET_RUNTIME_DLLS/target_link_libraries.cmake From 97e2828d14b7afbf4e22a3ea5b4ecf49f1f7c6f2 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.github.com> Date: Sun, 20 Jun 2021 02:56:02 -0400 Subject: [PATCH 0766/1519] Fortran: Subsume F90 check into ABI check Follow the approach from commit 1d21dd0f7c (enable_language: Assume compiler works if ABI detection compiles, 2020-05-25, v3.18.0-rc1~93^2) to avoid a redundant check for F90 support. Almost all maintained Fortran compilers support F90 these days. Fixes: #22222 --- Modules/CMakeFortranCompilerABI.F90 | 48 ++++++++++++++++++++++++++ Modules/CMakeTestFortranCompiler.cmake | 9 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 Modules/CMakeFortranCompilerABI.F90 diff --git a/Modules/CMakeFortranCompilerABI.F90 b/Modules/CMakeFortranCompilerABI.F90 new file mode 100644 index 00000000000..4a1715331d9 --- /dev/null +++ b/Modules/CMakeFortranCompilerABI.F90 @@ -0,0 +1,48 @@ +program CMakeFortranCompilerABI + +implicit none + +integer :: i(1) = 0 +where (i==0) i=1 +if (any(i/=1)) stop 1 +! showing Fortran 90 syntax is OK + +#if 0 +! Address Size +#endif +#if defined(_LP64) +PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(_M_IA64) +PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(_M_X64) +PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(_M_AMD64) +PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(__x86_64__) +PRINT *, 'INFO:sizeof_dptr[8]' + +#elif defined(_ILP32) +PRINT *, 'INFO:sizeof_dptr[4]' +#elif defined(_M_IX86) +PRINT *, 'INFO:sizeof_dptr[4]' +#elif defined(__i386__) +PRINT *, 'INFO:sizeof_dptr[4]' + +#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8 +PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 4 +PRINT *, 'INFO:sizeof_dptr[4]' +#elif defined(__SIZEOF_SIZE_T__) && __SIZEOF_SIZE_T__ == 8 +PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(__SIZEOF_SIZE_T__) && __SIZEOF_SIZE_T__ == 4 +PRINT *, 'INFO:sizeof_dptr[4]' +#endif + +#if 0 +! Application Binary Interface +#endif +#if defined(__ELF__) +PRINT *, 'INFO:abi[ELF]' +#endif +PRINT *, 'ABI Detection' +end program diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index 10fb0a7a660..4fdec948e29 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -17,11 +17,18 @@ unset(CMAKE_Fortran_COMPILER_WORKS CACHE) # Try to identify the ABI and configure it into CMakeFortranCompiler.cmake include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) -CMAKE_DETERMINE_COMPILER_ABI(Fortran ${CMAKE_ROOT}/Modules/CMakeFortranCompilerABI.F) +CMAKE_DETERMINE_COMPILER_ABI(Fortran ${CMAKE_ROOT}/Modules/CMakeFortranCompilerABI.F90) if(CMAKE_Fortran_ABI_COMPILED) # The compiler worked so skip dedicated test below. set(CMAKE_Fortran_COMPILER_WORKS TRUE) + set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 1) message(STATUS "Check for working Fortran compiler: ${CMAKE_Fortran_COMPILER} - skipped") +else() + cmake_determine_compiler_abi(Fortran ${CMAKE_ROOT}/Modules/CMakeFortranCompilerABI.F) + if(CMAKE_Fortran_ABI_COMPILED) + set(CMAKE_Fortran_COMPILER_WORKS TRUE) + message(STATUS "Check for working Fortran 77 compiler: ${CMAKE_Fortran_COMPILER} - skipped") + endif() endif() # This file is used by EnableLanguage in cmGlobalGenerator to From c46b265839c408ba04edc6ae7c96bc257547f43c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 24 Jun 2021 16:12:31 -0400 Subject: [PATCH 0767/1519] VS: Add Visual Studio 17 2022 generator Fixes: #22339 --- Help/generator/Visual Studio 17 2022.rst | 61 +++++++++++++ Help/manual/cmake-generators.7.rst | 1 + Help/release/3.21.rst | 4 + Help/variable/MSVC_VERSION.rst | 3 + .../cmCMakeHostSystemInformationCommand.cxx | 16 ++++ Source/cmGlobalVisualStudio10Generator.cxx | 2 + Source/cmGlobalVisualStudioGenerator.cxx | 11 +++ Source/cmGlobalVisualStudioGenerator.h | 3 +- ...cmGlobalVisualStudioVersionedGenerator.cxx | 91 +++++++++++++++++++ .../cmGlobalVisualStudioVersionedGenerator.h | 3 + Source/cmVisualStudioGeneratorOptions.cxx | 1 + Source/cmake.cxx | 6 +- Tests/CMakeLists.txt | 8 +- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 2 +- .../GeneratorPlatform/RunCMakeTest.cmake | 4 +- .../GeneratorToolset/RunCMakeTest.cmake | 10 +- .../TestToolsetHostArchNone.cmake | 2 +- Tests/VSExternalInclude/CMakeLists.txt | 4 +- 18 files changed, 218 insertions(+), 14 deletions(-) create mode 100644 Help/generator/Visual Studio 17 2022.rst diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst new file mode 100644 index 00000000000..c53f8b79a49 --- /dev/null +++ b/Help/generator/Visual Studio 17 2022.rst @@ -0,0 +1,61 @@ +Visual Studio 17 2022 +--------------------- + +.. versionadded:: 3.21 + +Generates Visual Studio 17 (VS 2022) project files. + +.. warning:: + + This is experimental and based on "Visual Studio 2022 Preview 1.1". + As of this version of CMake, VS 2022 has not been released. + +Project Types +^^^^^^^^^^^^^ + +Only Visual C++ and C# projects may be generated. Other types of +projects (JavaScript, Powershell, Python, etc.) are not supported. + +Instance Selection +^^^^^^^^^^^^^^^^^^ + +VS 2022 supports multiple installations on the same machine. +The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a +cache entry containing the absolute path to a Visual Studio instance. +If the value is not specified explicitly by the user or a toolchain file, +CMake queries the Visual Studio Installer to locate VS instances, chooses +one, and sets the variable as a cache entry to hold the value persistently. + +When CMake first chooses an instance, if the ``VS170COMNTOOLS`` environment +variable is set and points to the ``Common7/Tools`` directory within +one of the instances, that instance will be used. Otherwise, if more +than one instance is installed we do not define which one is chosen +by default. + +Platform Selection +^^^^^^^^^^^^^^^^^^ + +The default target platform name (architecture) is that of the host +and is provided in the :variable:`CMAKE_VS_PLATFORM_NAME_DEFAULT` variable. + +The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps +via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +name (architecture). For example: + +* ``cmake -G "Visual Studio 17 2022" -A Win32`` +* ``cmake -G "Visual Studio 17 2022" -A x64`` +* ``cmake -G "Visual Studio 17 2022" -A ARM`` +* ``cmake -G "Visual Studio 17 2022" -A ARM64`` + +Toolset Selection +^^^^^^^^^^^^^^^^^ + +The ``v142`` toolset that comes with VS 17 2022 Preview 1.1 is selected by +default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps +via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. + +.. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: + By default this generator uses the 64-bit variant on x64 hosts and + the 32-bit variant otherwise. + +.. include:: VS_TOOLSET_HOST_ARCH.txt diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 8ca2bf6444e..663b18d4651 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -91,6 +91,7 @@ Visual Studio Generators /generator/Visual Studio 14 2015 /generator/Visual Studio 15 2017 /generator/Visual Studio 16 2019 + /generator/Visual Studio 17 2022 Other Generators ^^^^^^^^^^^^^^^^ diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 04354dba723..1f7a4a15fe4 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -26,6 +26,10 @@ Presets Generators ---------- +* The :generator:`Visual Studio 17 2022` generator was added. This is + experimental and based on "Visual Studio 2022 Preview 1.1" because this + version of VS has not been released. + * The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to add linker launcher tools along with the linker for ``C``, ``CXX``, ``OBJC``, and ``OBJCXX`` languages. diff --git a/Help/variable/MSVC_VERSION.rst b/Help/variable/MSVC_VERSION.rst index 45df37fa002..241eb0384e3 100644 --- a/Help/variable/MSVC_VERSION.rst +++ b/Help/variable/MSVC_VERSION.rst @@ -20,5 +20,8 @@ Known version numbers are:: 1910-1919 = VS 15.0 (v141 toolset) 1920-1929 = VS 16.0 (v142 toolset) +.. + 1930-1939 = VS 17.0 (v143 toolset) + See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` and :variable:`MSVC_TOOLSET_VERSION` variable. diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 26e9af0279a..05505688764 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -171,6 +171,22 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } + } else if (key == "VS_17_DIR") { + // If generating for the VS 17 IDE, use the same instance. + cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); + if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 17 ")) { + cmGlobalVisualStudioVersionedGenerator* vs17gen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); + if (vs17gen->GetVSInstance(value)) { + return true; + } + } + + // Otherwise, find a VS 17 instance ourselves. + cmVSSetupAPIHelper vsSetupAPIHelper(17); + if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { + cmSystemTools::ConvertToUnixSlashes(value); + } #endif } else { std::string e = "does not recognize <key> " + key; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index fc2665b42ba..fdb71554ce1 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1277,6 +1277,8 @@ const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const return "15.0"; case cmGlobalVisualStudioGenerator::VS16: return "16.0"; + case cmGlobalVisualStudioGenerator::VS17: + return "17.0"; } return ""; } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index c23ee94511e..cdecea03a49 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -104,6 +104,8 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const return "15.0"; case cmGlobalVisualStudioGenerator::VS16: return "16.0"; + case cmGlobalVisualStudioGenerator::VS17: + return "17.0"; } return ""; } @@ -170,6 +172,15 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) fout << "# Visual Studio Version 16\n"; } break; + case cmGlobalVisualStudioGenerator::VS17: + // Visual Studio 17 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) { + fout << "# Visual Studio Express 17 for Windows Desktop\n"; + } else { + fout << "# Visual Studio Version 17\n"; + } + break; } } diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 3bfcbd04d97..151f39f12da 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -38,7 +38,8 @@ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator /* VS13 = 130 was skipped */ VS14 = 140, VS15 = 150, - VS16 = 160 + VS16 = 160, + VS17 = 170 }; virtual ~cmGlobalVisualStudioGenerator(); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index c8213c54c74..a2b525897a2 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -79,6 +79,8 @@ static unsigned int VSVersionToMajor( return 15; case cmGlobalVisualStudioGenerator::VS16: return 16; + case cmGlobalVisualStudioGenerator::VS17: + return 17; } return 0; } @@ -101,6 +103,9 @@ static const char* VSVersionToToolset( return "v141"; case cmGlobalVisualStudioGenerator::VS16: return "v142"; + case cmGlobalVisualStudioGenerator::VS17: + // FIXME: VS 2022 Preview 1 uses v142. Will it be v143 later? + return "v142"; } return ""; } @@ -118,6 +123,7 @@ static const char* VSVersionToAndroidToolset( return "Clang_3_8"; case cmGlobalVisualStudioGenerator::VS15: case cmGlobalVisualStudioGenerator::VS16: + case cmGlobalVisualStudioGenerator::VS17: return "Clang_5_0"; } return ""; @@ -219,6 +225,7 @@ cmGlobalVisualStudioVersionedGenerator::NewFactory15() } static const char vs16generatorName[] = "Visual Studio 16 2019"; +static const char vs17generatorName[] = "Visual Studio 17 2022"; // Map generator name without year to name with year. static const char* cmVS16GenName(const std::string& name, std::string& genName) @@ -235,6 +242,20 @@ static const char* cmVS16GenName(const std::string& name, std::string& genName) return p; } +static const char* cmVS17GenName(const std::string& name, std::string& genName) +{ + if (strncmp(name.c_str(), vs17generatorName, + sizeof(vs17generatorName) - 6) != 0) { + return 0; + } + const char* p = name.c_str() + sizeof(vs17generatorName) - 6; + if (cmHasLiteralPrefix(p, " 2022")) { + p += 5; + } + genName = std::string(vs17generatorName) + p; + return p; +} + class cmGlobalVisualStudioVersionedGenerator::Factory16 : public cmGlobalGeneratorFactory { @@ -299,6 +320,70 @@ cmGlobalVisualStudioVersionedGenerator::NewFactory16() return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory16); } +class cmGlobalVisualStudioVersionedGenerator::Factory17 + : public cmGlobalGeneratorFactory +{ +public: + std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( + const std::string& name, bool /*allowArch*/, cmake* cm) const override + { + std::string genName; + const char* p = cmVS17GenName(name, genName); + if (!p) { + return std::unique_ptr<cmGlobalGenerator>(); + } + if (!*p) { + return std::unique_ptr<cmGlobalGenerator>( + new cmGlobalVisualStudioVersionedGenerator( + cmGlobalVisualStudioGenerator::VS17, cm, genName, "")); + } + return std::unique_ptr<cmGlobalGenerator>(); + } + + void GetDocumentation(cmDocumentationEntry& entry) const override + { + entry.Name = std::string(vs17generatorName); + entry.Brief = "Generates Visual Studio 2022 project files. " + "Use -A option to specify architecture."; + } + + std::vector<std::string> GetGeneratorNames() const override + { + std::vector<std::string> names; + names.push_back(vs17generatorName); + return names; + } + + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return true; } + + std::vector<std::string> GetKnownPlatforms() const override + { + std::vector<std::string> platforms; + platforms.emplace_back("x64"); + platforms.emplace_back("Win32"); + platforms.emplace_back("ARM"); + platforms.emplace_back("ARM64"); + return platforms; + } + + std::string GetDefaultPlatformName() const override + { + return VSHostPlatformName(); + } +}; + +std::unique_ptr<cmGlobalGeneratorFactory> +cmGlobalVisualStudioVersionedGenerator::NewFactory17() +{ + return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory17); +} + cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( VSVersion version, cmake* cm, const std::string& name, std::string const& platformInGeneratorName) @@ -339,6 +424,11 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( return genName == this->GetName(); } break; + case cmGlobalVisualStudioGenerator::VS17: + if (cmVS17GenName(name, genName)) { + return genName == this->GetName(); + } + break; } return false; } @@ -446,6 +536,7 @@ cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision() return "2.0"; case cmGlobalVisualStudioGenerator::VS15: case cmGlobalVisualStudioGenerator::VS16: + case cmGlobalVisualStudioGenerator::VS17: return "3.0"; } return ""; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index e6c19e4b349..f07492dff52 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -21,6 +21,7 @@ class cmGlobalVisualStudioVersionedGenerator public: static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory15(); static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory16(); + static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory17(); bool MatchesGeneratorName(const std::string& name) const override; @@ -68,5 +69,7 @@ class cmGlobalVisualStudioVersionedGenerator friend class Factory15; class Factory16; friend class Factory16; + class Factory17; + friend class Factory17; mutable cmVSSetupAPIHelper vsSetupAPIHelper; }; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 505d58ac3ad..058ffb49580 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -75,6 +75,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() case cmGlobalVisualStudioGenerator::VS14: case cmGlobalVisualStudioGenerator::VS15: case cmGlobalVisualStudioGenerator::VS16: + case cmGlobalVisualStudioGenerator::VS17: // by default VS puts <ExceptionHandling></ExceptionHandling> empty // for a project, to make our projects look the same put a new line // and space over for the closing </ExceptionHandling> as the default diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 78688592909..14f66d9e707 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2201,7 +2201,9 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() "\\Setup\\VC;ProductDir", // ";InstallDir" // }; - if (cmVSSetupAPIHelper(16).IsVSInstalled()) { + if (cmVSSetupAPIHelper(17).IsVSInstalled()) { + found = "Visual Studio 17 2022"; + } else if (cmVSSetupAPIHelper(16).IsVSInstalled()) { found = "Visual Studio 16 2019"; } else if (cmVSSetupAPIHelper(15).IsVSInstalled()) { found = "Visual Studio 15 2017"; @@ -2505,6 +2507,8 @@ void cmake::AddDefaultGenerators() { #if defined(_WIN32) && !defined(__CYGWIN__) # if !defined(CMAKE_BOOT_MINGW) + this->Generators.push_back( + cmGlobalVisualStudioVersionedGenerator::NewFactory17()); this->Generators.push_back( cmGlobalVisualStudioVersionedGenerator::NewFactory16()); this->Generators.push_back( diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 6d7355492fe..341aba63511 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -209,9 +209,12 @@ if(BUILD_TESTING) if(CMAKE_HOST_WIN32 AND COMMAND cmake_host_system_information) set(info_vs15 "VS_15_DIR") set(info_vs16 "VS_16_DIR") + set(info_vs17 "VS_17_DIR") set(vs_versions) if(WIN32) - if(NOT CMAKE_VERSION VERSION_LESS 3.14) + if(NOT CMAKE_VERSION VERSION_LESS 3.21.20210624) + set(vs_versions vs15 vs16 vs17) + elseif(NOT CMAKE_VERSION VERSION_LESS 3.14) set(vs_versions vs15 vs16) elseif(NOT CMAKE_VERSION VERSION_LESS 3.8) set(vs_versions vs15) @@ -2459,6 +2462,9 @@ if(BUILD_TESTING) if(vs16 AND CMake_TEST_ANDROID_VS16) add_test_VSAndroid(vs16 "Visual Studio 16 2019" "ARM") endif() + if(vs17 AND CMake_TEST_ANDROID_VS17) + add_test_VSAndroid(vs17 "Visual Studio 17 2022" "ARM") + endif() if (APPLE) if (CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index c4d3e4ae614..c58b1d06df2 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -313,7 +313,7 @@ function(run_EnvironmentGenerator) unset(ENV{CMAKE_GENERATOR_PLATFORM}) endif() # Instance is available since VS 2017. - if(RunCMake_GENERATOR MATCHES "Visual Studio (15|16).*") + if(RunCMake_GENERATOR MATCHES "Visual Studio 1[567].*") set(ENV{CMAKE_GENERATOR_INSTANCE} "invalid") # Envvar shouldn't affect existing build tree run_cmake_command(Envgen-instance-existing ${CMAKE_COMMAND} -E chdir .. diff --git a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake index 83e63f91853..a7519c373c9 100644 --- a/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorPlatform/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_PLATFORM "") run_cmake(NoPlatform) -if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$") +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[0124567])( 20[0-9][0-9])?$") set(RunCMake_GENERATOR_PLATFORM "x64") run_cmake(x64Platform) else() @@ -17,7 +17,7 @@ set(RunCMake_TEST_OPTIONS -A "Test Platform" -A "Extra Platform") run_cmake(TwoPlatforms) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[012456])( 20[0-9][0-9])?$") +if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio ([89]|1[0124567])( 20[0-9][0-9])?$") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestPlatform-toolchain.cmake) run_cmake(TestPlatformToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index faed8f7d4d8..a7423918fdc 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -1,6 +1,6 @@ include(RunCMake) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]") run_cmake(VsNormal) include("${RunCMake_BINARY_DIR}/VsNormal-build/defaults.cmake" OPTIONAL) message(STATUS "VsNormal: platform='${VsNormal_Platform}' toolset='${VsNormal_Toolset}'") @@ -9,7 +9,7 @@ endif() set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=0.0") @@ -43,7 +43,7 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") set(RunCMake_GENERATOR_TOOLSET "${VsNormal_Toolset},customFlagTableDir=does_not_exist") run_cmake(BadToolsetCustomFlagTableDir) endif() - if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[2456]") + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[24567]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) set(RunCMake_GENERATOR_TOOLSET ",host=x64") @@ -58,7 +58,7 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") run_cmake(BadToolsetHostArch) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x86") run_cmake(BadToolsetHostArchTwice) - if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]") + if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[567]") set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=Test Path") run_cmake(TestToolsetVCTargetsPathOnly) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version") @@ -109,7 +109,7 @@ set(RunCMake_TEST_OPTIONS -T "Test Toolset" -T "Extra Toolset") run_cmake(TwoToolsets) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]|Xcode") +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[0124567]|Xcode") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake) run_cmake(TestToolsetToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake index 085bb6b1734..854f3dc4df6 100644 --- a/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake @@ -1,7 +1,7 @@ message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE='${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}'") -if(CMAKE_GENERATOR MATCHES "Visual Studio 1[6]") +if(CMAKE_GENERATOR MATCHES "Visual Studio 1[67]") cmake_host_system_information(RESULT is_64_bit QUERY IS_64BIT) if(is_64_bit) if(NOT "${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}" STREQUAL "x64") diff --git a/Tests/VSExternalInclude/CMakeLists.txt b/Tests/VSExternalInclude/CMakeLists.txt index e38df8e81ac..a3fd8d8ebeb 100644 --- a/Tests/VSExternalInclude/CMakeLists.txt +++ b/Tests/VSExternalInclude/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.8.12) project(VSExternalInclude) -if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[0124567]") set(PROJECT_EXT vcxproj) else() set(PROJECT_EXT vcproj) @@ -55,7 +55,7 @@ add_dependencies(VSExternalInclude lib2) # and the sln file can no longer be the only source # of that depend. So, for VS 10 make the executable # depend on lib1 and lib2 -if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[012456]") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio 1[0124567]") add_dependencies(VSExternalInclude lib1) endif() From 93c718791e4e81f37dcc3413b3e847d94313d5c9 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 24 Jun 2021 16:25:42 -0400 Subject: [PATCH 0768/1519] VS: Use 64-bit MSBuild in VS 2022 Visual Studio 17 2022 is now a 64-bit native application. It places the 64-bit `MSBuild.exe` in the `PATH` of VS command prompts, so prefer it for this version and above. This was previously attempted for older VS versions, but reverted by commit f3cedf381e (VS: Revert "Use MSBuild matching toolset host architecture", 2019-03-12, v3.14.0~1^2). For now, do not use the 64-bit MSBuild for VS 16 and below. Fixes: #18219 --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index a2b525897a2..aafc9d5e963 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -716,6 +716,12 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() // Ask Visual Studio Installer tool. std::string vs; if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + if (this->Version >= cmGlobalVisualStudioGenerator::VS17) { + msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + } msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe"; if (cmSystemTools::FileExists(msbuild)) { return msbuild; From a3cafa4237930d1ec1bcbdddc8a9c592e32458ca Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Mon, 21 Jun 2021 13:16:29 -0400 Subject: [PATCH 0769/1519] compile_features: Ignore features that map to languages that aren't enabled Remove the Cuda/ConsumeCompileFeatures test as it only existed to validate that using `cxx_std_XY` would cause the paired language (CUDA) to also build in mode XY. --- ...compile_features-ignore-disabled-langs.rst | 5 +++++ Source/cmStandardLevelResolver.cxx | 4 ++++ Tests/Cuda/CMakeLists.txt | 1 - .../ConsumeCompileFeatures/CMakeLists.txt | 16 --------------- Tests/Cuda/ConsumeCompileFeatures/main.cu | 20 ------------------- Tests/Cuda/ConsumeCompileFeatures/static.cpp | 10 ---------- Tests/Cuda/ConsumeCompileFeatures/static.cu | 9 --------- .../cxx_not_enabled-stderr.txt | 6 ++---- 8 files changed, 11 insertions(+), 60 deletions(-) create mode 100644 Help/release/dev/target_compile_features-ignore-disabled-langs.rst delete mode 100644 Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt delete mode 100644 Tests/Cuda/ConsumeCompileFeatures/main.cu delete mode 100644 Tests/Cuda/ConsumeCompileFeatures/static.cpp delete mode 100644 Tests/Cuda/ConsumeCompileFeatures/static.cu diff --git a/Help/release/dev/target_compile_features-ignore-disabled-langs.rst b/Help/release/dev/target_compile_features-ignore-disabled-langs.rst new file mode 100644 index 00000000000..0eba1259ca2 --- /dev/null +++ b/Help/release/dev/target_compile_features-ignore-disabled-langs.rst @@ -0,0 +1,5 @@ +target_compile_features-ignore-disabled-langs +--------------------------------------------- + +* :command:`target_compile_features` learned to ignored features for languages that + aren't enabled. diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 37ed4c130ac..74b9d6fd547 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -387,6 +387,10 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( return false; } + if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) { + return true; + } + const char* features = this->CompileFeaturesAvailable(lang, error); if (!features) { return false; diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt index be5ccac5094..669c412dff8 100644 --- a/Tests/Cuda/CMakeLists.txt +++ b/Tests/Cuda/CMakeLists.txt @@ -4,7 +4,6 @@ macro (add_cuda_test_macro name) PROPERTY LABELS "CUDA") endmacro () -add_cuda_test_macro(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures) add_cuda_test_macro(Cuda.CXXStandardSetTwice CXXStandardSetTwice) add_cuda_test_macro(Cuda.ObjectLibrary CudaObjectLibrary) add_cuda_test_macro(Cuda.MixedStandardLevels1 MixedStandardLevels1) diff --git a/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt b/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt deleted file mode 100644 index b01b9d7f0bd..00000000000 --- a/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 3.18) -project(ConsumeCompileFeatures CXX CUDA) -#Goal for this example: - -#build a c++11 library that express a c++11 public compile feature -#link a cuda library and verify it builds with c++11 enabled - -#build a standalone c++/cuda mixed executable where we express a c++11 -#compile feature. - - -add_library(CudaConsumeLib STATIC static.cpp static.cu) -target_compile_features(CudaConsumeLib PUBLIC cxx_nullptr) - -add_executable(CudaConsumeCompileFeatures main.cu) -target_link_libraries(CudaConsumeCompileFeatures PRIVATE CudaConsumeLib) diff --git a/Tests/Cuda/ConsumeCompileFeatures/main.cu b/Tests/Cuda/ConsumeCompileFeatures/main.cu deleted file mode 100644 index bc3245013cb..00000000000 --- a/Tests/Cuda/ConsumeCompileFeatures/main.cu +++ /dev/null @@ -1,20 +0,0 @@ - -#include <iostream> - -int static_cxx11_func(int); - -void test_functions() -{ - auto x = static_cxx11_func(int(42)); - std::cout << x << std::endl; -} - -int main(int argc, char** argv) -{ - test_functions(); - std::cout - << "this executable doesn't use cuda code, just call methods defined" - << std::endl; - std::cout << "in libraries that have cuda code" << std::endl; - return 0; -} diff --git a/Tests/Cuda/ConsumeCompileFeatures/static.cpp b/Tests/Cuda/ConsumeCompileFeatures/static.cpp deleted file mode 100644 index 565d52e1052..00000000000 --- a/Tests/Cuda/ConsumeCompileFeatures/static.cpp +++ /dev/null @@ -1,10 +0,0 @@ - - -#include <type_traits> - -int static_cuda11_func(int); - -int static_cxx11_func(int x) -{ - return static_cuda11_func(x) + std::integral_constant<int, 32>::value; -} diff --git a/Tests/Cuda/ConsumeCompileFeatures/static.cu b/Tests/Cuda/ConsumeCompileFeatures/static.cu deleted file mode 100644 index 73e43a8657e..00000000000 --- a/Tests/Cuda/ConsumeCompileFeatures/static.cu +++ /dev/null @@ -1,9 +0,0 @@ - -#include <type_traits> - -using tt = std::true_type; -using ft = std::false_type; -int __host__ static_cuda11_func(int x) -{ - return x * x + std::integral_constant<int, 17>::value; -} diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt index 5b4761c60ba..cf4c540c7c5 100644 --- a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt +++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt @@ -1,4 +1,2 @@ -^CMake Error at cxx_not_enabled.cmake:[0-9]+ \(target_compile_features\): - target_compile_features cannot use features from non-enabled language CXX -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\)$ +^CMake Error:.*CMake can not determine linker language for target: main.* +CMake Generate step failed. Build files cannot be regenerated correctly.$ From cd809b8ea4b21c459d79df228b9579b08ffd99fe Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 26 Jun 2021 00:01:09 -0400 Subject: [PATCH 0770/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b808234cc71..82864197e98 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210625) +set(CMake_VERSION_PATCH 20210626) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 66a0f46f9f311806d9654a6a89cead89ce4da27b Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 27 Jun 2021 00:01:07 -0400 Subject: [PATCH 0771/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 82864197e98..8fa63c3ceb8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210626) +set(CMake_VERSION_PATCH 20210627) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 25d7cd9671993aeef0d3b3cbe860bc1f56750246 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 28 Jun 2021 00:01:16 -0400 Subject: [PATCH 0772/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8fa63c3ceb8..bdc71d9ae63 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210627) +set(CMake_VERSION_PATCH 20210628) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 894645d4a6f2edb86923347dd1a7f4808b430ced Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Mon, 28 Jun 2021 08:17:25 -0400 Subject: [PATCH 0773/1519] Help/CMP0102: mention the varible that controls CMP0102 warnings This was missed in the review of !4150, but was noticed during discussion of #22353. --- Help/policy/CMP0102.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Help/policy/CMP0102.rst b/Help/policy/CMP0102.rst index 78b5584808a..08024bfd384 100644 --- a/Help/policy/CMP0102.rst +++ b/Help/policy/CMP0102.rst @@ -22,6 +22,8 @@ already exist in the cache. This policy was introduced in CMake version 3.17. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. Unlike many policies, CMake version |release| does *not* warn -when this policy is not set and simply uses ``OLD`` behavior. +when this policy is not set and simply uses ``OLD`` behavior. See +documentation of the :variable:`CMAKE_POLICY_WARNING_CMP0102 +<CMAKE_POLICY_WARNING_CMP<NNNN>>` variable to control the warning. .. include:: DEPRECATED.txt From 1e3d3c52841ac7981879f691c07f28ffaf2ffce5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 28 Jun 2021 09:10:16 -0400 Subject: [PATCH 0774/1519] TestDriver: Avoid declaring local variable after statement Move a declaration added by commit 3f6ff4b5db (create_test_sourcelist: add test driver option to run all tests, 2021-04-27, v3.21.0-rc1~257^2) into its own scope. --- Templates/TestDriver.cxx.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index e3efa794d15..61134172edc 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -136,9 +136,11 @@ int main(int ac, char* av[]) t = clock(); status = (*cmakeGeneratedFunctionMapEntries[i].func)(ac, av); t = clock() - t; - double time_taken = ((double)t) / CLOCKS_PER_SEC; status_message = (status == -1) ? "not ok" : "ok"; - printf("%s %d %s # %f\n", status_message, i + 1, name, time_taken); + { + double time_taken = ((double)t) / CLOCKS_PER_SEC; + printf("%s %d %s # %f\n", status_message, i + 1, name, time_taken); + } } printf("All tests finished.\n"); From 82ea0aeae4f800e74c07fb7a180f04245c59a3e4 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 28 Jun 2021 09:53:48 -0400 Subject: [PATCH 0775/1519] Help: Clarify 3.21 release note on supportedPlatforms Avoid implying that the field is always present. Fixes: #22352 --- Help/release/3.21.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 1f7a4a15fe4..204880b7b42 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -57,9 +57,9 @@ Command-Line * :manual:`cmake(1)` gained the ``--toolchain <path/to/file>`` command-line option to specify a toolchain file. -* :manual:`cmake(1)` ``-E capabilities`` output now contains for each - generator a ``supportedPlatforms`` field listing platforms known to - be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. +* :manual:`cmake(1)` ``-E capabilities`` output, for some generators, + may now contain a ``supportedPlatforms`` field listing platforms + known to be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. * Messages printed to a terminal now may be colored by message type. From cf222635313f3ca644e327df444c37fad1781e7f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 28 Jun 2021 09:58:52 -0400 Subject: [PATCH 0776/1519] Help/dev/experimental: Link to published P1689R4 --- Help/dev/experimental.rst | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 9cf33ebfaea..2380de4b7f2 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -39,13 +39,7 @@ to the file specified by the ``<DEP_FILE>`` placeholder, and write module dependencies to the file specified by the ``<DYNDEP_FILE>`` placeholder. The module dependencies should be written in the format described -by the `P1689r3`_ paper, with the following updates: - -* Omit the ``outputs``, ``inputs``, and ``depends`` fields from - each entry in the ``rules`` array. They are unused. -* Flatten ``future-compile`` members directly into each rule. -* Factor a ``primary-output`` field out of the now-flattened ``outputs``. -* The ``work-directory`` field is optional. +by the `P1689r4`_ paper. Compiler writers may try out their scanning functionality using the `cxx-modules-sandbox`_ test project, modified to set variables @@ -72,5 +66,5 @@ the GCC documentation, but the relevant section for the purposes of CMake is: -- GCC module mapper documentation .. _`D1483r1`: https://mathstuf.fedorapeople.org/fortran-modules/fortran-modules.html -.. _`P1689r3`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1689r3.html +.. _`P1689r4`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1689r4.html .. _`cxx-modules-sandbox`: https://github.com/mathstuf/cxx-modules-sandbox From a5011a2fbfe4ae1f04913fd490f49a1624c1e04d Mon Sep 17 00:00:00 2001 From: Alex Sweet <asweet@ss8.com> Date: Sun, 27 Jun 2021 17:14:17 -0700 Subject: [PATCH 0777/1519] Tests: Cleanup CTestTestSerialInDepends lockfile at test start When any test under CTestTestSerialInDepends starts, delete the lockfile for that test in case it wasn't deleted at the end of the last test run. Fixes: #22351 --- Tests/CTestTestSerialInDepends/test.ctest | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/CTestTestSerialInDepends/test.ctest b/Tests/CTestTestSerialInDepends/test.ctest index 28ee09436be..cf0d314fbf3 100644 --- a/Tests/CTestTestSerialInDepends/test.ctest +++ b/Tests/CTestTestSerialInDepends/test.ctest @@ -2,6 +2,9 @@ set(CTEST_RUN_CURRENT_SCRIPT 0) set(LOCK_FILE "${TEST_NAME}.lock") +# Delete the old lock file in case it's lingering from a previous failed test run +file(REMOVE "${LOCK_FILE}") + if("${TEST_NAME}" STREQUAL "i_want_to_be_alone") file(GLOB LOCK_FILES *.lock) if(LOCK_FILES) From 63177678d063fb0051541054d7657fb0c3177ea0 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Sat, 26 Jun 2021 15:32:38 +0900 Subject: [PATCH 0778/1519] Tests/RunCMake/Ninja.*: Sanitize NINJA_STATUS since we expect default behavior FYI, NINJA_STATUS is "[%f/%t] " by default. --- Tests/RunCMake/Ninja/RunCMakeTest.cmake | 3 +++ Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 8c91b34d9d8..3f239b974d7 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -18,6 +18,9 @@ else() message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}") endif() +# Sanitize NINJA_STATUS since we expect default behavior. +unset(ENV{NINJA_STATUS}) + if(CMAKE_HOST_WIN32) run_cmake(SelectCompilerWindows) else() diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index e7acbc2845c..559c8f79664 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -5,6 +5,9 @@ include(RunCMake) set(RunCMake_GENERATOR "Ninja Multi-Config") set(RunCMake_GENERATOR_IS_MULTI_CONFIG 1) +# Sanitize NINJA_STATUS since we expect default behavior. +unset(ENV{NINJA_STATUS}) + function(check_files dir) cmake_parse_arguments(_check_files "" "" "INCLUDE;EXCLUDE" ${ARGN}) From 7993aa30753f87e486a8dd3922521124ec949feb Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" <ferdnyc@gmail.com> Date: Sat, 26 Jun 2021 03:10:19 -0400 Subject: [PATCH 0779/1519] Help: Add versionadded tags to cmake-generator-expressions(7) --- Help/manual/cmake-generator-expressions.7.rst | 110 +++++++++++++++++- 1 file changed, 105 insertions(+), 5 deletions(-) diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 05b7bc020fa..5d508cb0dd7 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -94,6 +94,8 @@ String Comparisons .. genex:: $<IN_LIST:string,list> + .. versionadded:: 3.12 + ``1`` if ``string`` is member of the semicolon-separated ``list``, else ``0``. Uses case-sensitive comparisons. @@ -111,10 +113,14 @@ String Comparisons .. genex:: $<VERSION_LESS_EQUAL:v1,v2> + .. versionadded:: 3.7 + ``1`` if ``v1`` is a version less than or equal to ``v2``, else ``0``. .. genex:: $<VERSION_GREATER_EQUAL:v1,v2> + .. versionadded:: 3.7 + ``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``. Variable Queries @@ -122,6 +128,8 @@ Variable Queries .. genex:: $<TARGET_EXISTS:target> + .. versionadded:: 3.12 + ``1`` if ``target`` exists, else ``0``. .. genex:: $<CONFIG:cfgs> @@ -155,6 +163,8 @@ Variable Queries .. genex:: $<CUDA_COMPILER_ID:compiler_ids> + .. versionadded:: 3.15 + where ``compiler_ids`` is a comma-separated list. ``1`` if the CMake's compiler id of the CUDA compiler matches any one of the entries in ``compiler_ids``, otherwise ``0``. @@ -162,6 +172,8 @@ Variable Queries .. genex:: $<OBJC_COMPILER_ID:compiler_ids> + .. versionadded:: 3.16 + where ``compiler_ids`` is a comma-separated list. ``1`` if the CMake's compiler id of the Objective-C compiler matches any one of the entries in ``compiler_ids``, otherwise ``0``. @@ -169,6 +181,8 @@ Variable Queries .. genex:: $<OBJCXX_COMPILER_ID:compiler_ids> + .. versionadded:: 3.16 + where ``compiler_ids`` is a comma-separated list. ``1`` if the CMake's compiler id of the Objective-C++ compiler matches any one of the entries in ``compiler_ids``, otherwise ``0``. @@ -190,6 +204,8 @@ Variable Queries .. genex:: $<ISPC_COMPILER_ID:compiler_ids> + .. versionadded:: 3.19 + where ``compiler_ids`` is a comma-separated list. ``1`` if the CMake's compiler id of the ISPC compiler matches any one of the entries in ``compiler_ids``, otherwise ``0``. @@ -207,16 +223,22 @@ Variable Queries .. genex:: $<CUDA_COMPILER_VERSION:version> + .. versionadded:: 3.15 + ``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. .. genex:: $<OBJC_COMPILER_VERSION:version> + .. versionadded:: 3.16 + ``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. .. genex:: $<OBJCXX_COMPILER_VERSION:version> + .. versionadded:: 3.16 + ``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. @@ -232,6 +254,8 @@ Variable Queries .. genex:: $<ISPC_COMPILER_VERSION:version> + .. versionadded:: 3.19 + ``1`` if the version of the ISPC compiler matches ``version``, otherwise ``0``. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. @@ -244,6 +268,8 @@ Variable Queries .. genex:: $<COMPILE_FEATURES:features> + .. versionadded:: 3.1 + where ``features`` is a comma-spearated list. Evaluates to ``1`` if all of the ``features`` are available for the 'head' target, and ``0`` otherwise. If this expression is used while evaluating @@ -257,6 +283,8 @@ Variable Queries .. genex:: $<COMPILE_LANG_AND_ID:language,compiler_ids> + .. versionadded:: 3.15 + ``1`` when the language used for compilation unit matches ``language`` and the CMake's compiler id of the language compiler matches any one of the entries in ``compiler_ids``, otherwise ``0``. This expression is a short form @@ -294,6 +322,8 @@ Variable Queries .. genex:: $<COMPILE_LANGUAGE:languages> + .. versionadded:: 3.3 + ``1`` when the language used for compilation unit matches any of the entries in ``languages``, otherwise ``0``. This expression may be used to specify compile options, compile definitions, and include directories for source files of a @@ -340,6 +370,8 @@ Variable Queries .. genex:: $<LINK_LANG_AND_ID:language,compiler_ids> + .. versionadded:: 3.18 + ``1`` when the language used for link step matches ``language`` and the CMake's compiler id of the language linker matches any one of the entries in ``compiler_ids``, otherwise ``0``. This expression is a short form for the @@ -380,6 +412,8 @@ Variable Queries .. genex:: $<LINK_LANGUAGE:languages> + .. versionadded:: 3.18 + ``1`` when the language used for link step matches any of the entries in ``languages``, otherwise ``0``. This expression may be used to specify link libraries, link options, link directories and link dependencies of a @@ -443,6 +477,8 @@ Variable Queries .. genex:: $<DEVICE_LINK:list> + .. versionadded:: 3.18 + Returns the list if it is the device link step, an empty list otherwise. The device link step is controlled by :prop_tgt:`CUDA_SEPARABLE_COMPILATION` and :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and @@ -451,6 +487,8 @@ Variable Queries .. genex:: $<HOST_LINK:list> + .. versionadded:: 3.18 + Returns the list if it is the normal link step, an empty list otherwise. This expression is mainly useful when a device link step is also involved (see ``$<DEVICE_LINK:list>`` generator expression). This expression can only @@ -533,6 +571,8 @@ that must be ``0`` or ``1``. .. genex:: $<IF:condition,true_string,false_string> + .. versionadded:: 3.8 + Evaluates to ``true_string`` if ``condition`` is ``1``. Otherwise evaluates to ``false_string``. @@ -557,10 +597,14 @@ String Transformations .. genex:: $<REMOVE_DUPLICATES:list> + .. versionadded:: 3.15 + Removes duplicated items in the given ``list``. .. genex:: $<FILTER:list,INCLUDE|EXCLUDE,regex> + .. versionadded:: 3.15 + Includes or removes items from ``list`` that match the regular expression ``regex``. .. genex:: $<LOWER_CASE:string> @@ -573,12 +617,16 @@ String Transformations .. genex:: $<GENEX_EVAL:expr> + .. versionadded:: 3.12 + Content of ``expr`` evaluated as a generator expression in the current context. This enables consumption of generator expressions whose evaluation results itself in generator expressions. .. genex:: $<TARGET_GENEX_EVAL:tgt,expr> + .. versionadded:: 3.12 + Content of ``expr`` evaluated as a generator expression in the context of ``tgt`` target. This enables consumption of custom target properties that themselves contain generator expressions. @@ -647,11 +695,15 @@ Variable Queries .. genex:: $<OBJC_COMPILER_ID> + .. versionadded:: 3.16 + The CMake's compiler id of the OBJC compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. .. genex:: $<OBJCXX_COMPILER_ID> + .. versionadded:: 3.16 + The CMake's compiler id of the OBJCXX compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. @@ -667,6 +719,8 @@ Variable Queries .. genex:: $<ISPC_COMPILER_ID> + .. versionadded:: 3.19 + The CMake's compiler id of the ISPC compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable. @@ -687,11 +741,15 @@ Variable Queries .. genex:: $<OBJC_COMPILER_VERSION> + .. versionadded:: 3.16 + The version of the OBJC compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. .. genex:: $<OBJCXX_COMPILER_VERSION> + .. versionadded:: 3.16 + The version of the OBJCXX compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. @@ -707,11 +765,15 @@ Variable Queries .. genex:: $<ISPC_COMPILER_VERSION> + .. versionadded:: 3.19 + The version of the ISPC compiler used. See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable. .. genex:: $<COMPILE_LANGUAGE> + .. versionadded:: 3.3 + The compile language of source files when evaluating compile options. See :ref:`the related boolean expression <Boolean COMPILE_LANGUAGE Generator Expression>` @@ -720,6 +782,8 @@ Variable Queries .. genex:: $<LINK_LANGUAGE> + .. versionadded:: 3.18 + The link language of target when evaluating link options. See :ref:`the related boolean expression <Boolean LINK_LANGUAGE Generator Expression>` ``$<LINK_LANGUAGE:language>`` @@ -750,6 +814,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_NAME_IF_EXISTS:tgt> + .. versionadded:: 3.12 + The target name ``tgt`` if the target exists, an empty string otherwise. Note that ``tgt`` is not added as a dependency of the target this @@ -761,6 +827,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_FILE_BASE_NAME:tgt> + .. versionadded:: 3.15 + Base name of ``tgt``, i.e. ``$<TARGET_FILE_NAME:tgt>`` without prefix and suffix. For example, if the ``tgt`` filename is ``libbase.so``, the base name is ``base``. @@ -780,6 +848,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_FILE_PREFIX:tgt> + .. versionadded:: 3.15 + Prefix of the ``tgt`` filename (such as ``lib``). See also the :prop_tgt:`PREFIX` target property. @@ -789,6 +859,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_FILE_SUFFIX:tgt> + .. versionadded:: 3.15 + Suffix of the ``tgt`` filename (extension such as ``.so`` or ``.exe``). See also the :prop_tgt:`SUFFIX` target property. @@ -819,6 +891,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_LINKER_FILE_BASE_NAME:tgt> + .. versionadded:: 3.15 + Base name of file used to link the target ``tgt``, i.e. ``$<TARGET_LINKER_FILE_NAME:tgt>`` without prefix and suffix. For example, if target file name is ``libbase.a``, the base name is ``base``. @@ -837,6 +911,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_LINKER_FILE_PREFIX:tgt> + .. versionadded:: 3.15 + Prefix of file used to link target ``tgt``. See also the :prop_tgt:`PREFIX` and :prop_tgt:`IMPORT_PREFIX` target @@ -847,6 +923,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_LINKER_FILE_SUFFIX:tgt> + .. versionadded:: 3.15 + Suffix of file used to link where ``tgt`` is the name of a target. The suffix corresponds to the file extension (such as ".so" or ".lib"). @@ -890,6 +968,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_PDB_FILE:tgt> + .. versionadded:: 3.1 + Full path to the linker generated program database file (.pdb) where ``tgt`` is the name of a target. @@ -899,6 +979,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_PDB_FILE_BASE_NAME:tgt> + .. versionadded:: 3.15 + Base name of the linker generated program database file (.pdb) where ``tgt`` is the name of a target. @@ -917,6 +999,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_PDB_FILE_NAME:tgt> + .. versionadded:: 3.1 + Name of the linker generated program database file (.pdb). Note that ``tgt`` is not added as a dependency of the target this @@ -924,6 +1008,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_PDB_FILE_DIR:tgt> + .. versionadded:: 3.1 + Directory of the linker generated program database file (.pdb). Note that ``tgt`` is not added as a dependency of the target this @@ -931,6 +1017,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_BUNDLE_DIR:tgt> + .. versionadded:: 3.9 + Full path to the bundle directory (``my.app``, ``my.framework``, or ``my.bundle``) where ``tgt`` is the name of a target. @@ -939,6 +1027,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_BUNDLE_CONTENT_DIR:tgt> + .. versionadded:: 3.9 + Full path to the bundle content directory where ``tgt`` is the name of a target. For the macOS SDK it leads to ``my.app/Contents``, ``my.framework``, or ``my.bundle/Contents``. For all other SDKs (e.g. iOS) it leads to @@ -964,6 +1054,8 @@ which is just the string ``tgt``. .. genex:: $<TARGET_RUNTIME_DLLS:tgt> + .. versionadded:: 3.21 + List of DLLs that the target depends on at runtime. This is determined by the locations of all the ``SHARED`` and ``MODULE`` targets in the target's transitive dependencies. Using this generator expression on targets other @@ -1003,6 +1095,8 @@ Output-Related Expressions .. genex:: $<LINK_ONLY:...> + .. versionadded:: 3.1 + Content of ``...`` except when evaluated in a link interface while propagating :ref:`Target Usage Requirements`, in which case it is the empty string. @@ -1028,18 +1122,24 @@ Output-Related Expressions .. genex:: $<TARGET_OBJECTS:objLib> + .. versionadded:: 3.1 + List of objects resulting from build of ``objLib``. .. genex:: $<SHELL_PATH:...> + .. versionadded:: 3.4 + Content of ``...`` converted to shell path style. For example, slashes are converted to backslashes in Windows shells and drive letters are converted to posix paths in MSYS shells. The ``...`` must be an absolute path. - The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>` - of paths, in which case each path is converted individually and a result - list is generated using the shell path separator (``:`` on POSIX and - ``;`` on Windows). Be sure to enclose the argument containing this genex - in double quotes in CMake source code so that ``;`` does not split arguments. + + .. versionadded:: 3.14 + The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>` + of paths, in which case each path is converted individually and a result + list is generated using the shell path separator (``:`` on POSIX and + ``;`` on Windows). Be sure to enclose the argument containing this genex + in double quotes in CMake source code so that ``;`` does not split arguments. .. genex:: $<OUTPUT_CONFIG:...> From b07253f7544e2e51a7551e342f28500fabd830b1 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 28 Jun 2021 10:58:15 -0400 Subject: [PATCH 0780/1519] ci: update keyserver URL The `sks-keyservers.net` keyserver pool is no longer provided. Switch to `keyserver.ubuntu.com` instead. --- .gitlab/ci/docker/debian10/install_rvm.sh | 2 +- .gitlab/ci/docker/fedora34/install_rvm.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/docker/debian10/install_rvm.sh b/.gitlab/ci/docker/debian10/install_rvm.sh index 2bea5119ad9..75c5adcb234 100755 --- a/.gitlab/ci/docker/debian10/install_rvm.sh +++ b/.gitlab/ci/docker/debian10/install_rvm.sh @@ -8,7 +8,7 @@ apt-get install -y \ gnupg2 \ procps -gpg2 --keyserver hkp://pool.sks-keyservers.net \ +gpg2 --keyserver hkps://keyserver.ubuntu.com \ --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 \ 7D2BAF1CF37B13E2069D6956105BD0E739499BDB diff --git a/.gitlab/ci/docker/fedora34/install_rvm.sh b/.gitlab/ci/docker/fedora34/install_rvm.sh index 6d4fa97f901..fca51045faf 100755 --- a/.gitlab/ci/docker/fedora34/install_rvm.sh +++ b/.gitlab/ci/docker/fedora34/install_rvm.sh @@ -2,7 +2,7 @@ set -e -gpg2 --keyserver hkp://pool.sks-keyservers.net \ +gpg2 --keyserver hkps://keyserver.ubuntu.com \ --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 \ 7D2BAF1CF37B13E2069D6956105BD0E739499BDB From 53cb34cb2365557396e123cfa9bac1366ace3fe1 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 28 Jun 2021 10:59:58 -0400 Subject: [PATCH 0781/1519] ci: add freeglut to Debian and Fedora base images --- .gitlab/ci/docker/debian10-aarch64/install_deps.sh | 1 + .gitlab/ci/docker/debian10/install_deps.sh | 1 + .gitlab/ci/docker/fedora34/install_deps.sh | 1 + .gitlab/os-linux.yml | 6 +++--- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh index fea502ec575..f2ffcd6204f 100755 --- a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh +++ b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh @@ -27,6 +27,7 @@ apt-get install -y \ apt-get install -y \ alsa-utils \ doxygen graphviz \ + freeglut3-dev \ gnutls-dev \ libarchive-dev \ libblas-dev \ diff --git a/.gitlab/ci/docker/debian10/install_deps.sh b/.gitlab/ci/docker/debian10/install_deps.sh index 4bb03bc6bc7..14dc67dcc28 100755 --- a/.gitlab/ci/docker/debian10/install_deps.sh +++ b/.gitlab/ci/docker/debian10/install_deps.sh @@ -27,6 +27,7 @@ apt-get install -y \ apt-get install -y \ alsa-utils \ doxygen graphviz \ + freeglut3-dev \ gnutls-dev \ libarchive-dev \ libblas-dev \ diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 19923730c96..878b5f868d6 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -51,6 +51,7 @@ dnf install --setopt=install_weak_deps=False -y \ doxygen \ expat-devel \ fontconfig-devel \ + freeglut-devel \ freetype-devel \ gdal-devel \ gettext \ diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 06b98ccad09..8ce795e89c3 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -45,7 +45,7 @@ ### Debian .debian10: - image: "kitware/cmake:ci-debian10-x86_64-2021-05-11" + image: "kitware/cmake:ci-debian10-x86_64-2021-06-28" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -60,7 +60,7 @@ CMake_SKIP_INSTALL: 1 .debian10_aarch64: - image: "kitware/cmake:ci-debian10-aarch64-2021-05-11" + image: "kitware/cmake:ci-debian10-aarch64-2021-06-28" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -69,7 +69,7 @@ ### Fedora .fedora34: - image: "kitware/cmake:ci-fedora34-x86_64-2021-06-10" + image: "kitware/cmake:ci-fedora34-x86_64-2021-06-28" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" From 3faa3d3a38bb9b7664ae0127028b7bc556b64703 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 28 Jun 2021 12:58:02 -0400 Subject: [PATCH 0782/1519] curl: backport upstream fix to 7.77.0 regression Backport upstream curl commit `ee97f1769` (schannel: set ALPN length correctly for HTTP/2, 2021-05-26) to get a fix to curl issue 7138, a regression in 7.77.0. Fixes: #22355 --- Utilities/cmcurl/lib/vtls/schannel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c index 2bcf11db257..3286a9e9fc0 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.c +++ b/Utilities/cmcurl/lib/vtls/schannel.c @@ -874,6 +874,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2) { + alpn_buffer[cur++] = ALPN_H2_LENGTH; memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH); cur += ALPN_H2_LENGTH; infof(data, "schannel: ALPN, offering %s\n", ALPN_H2); From bf4ae1c2b242e6a37034fac7efd86b0786130bfb Mon Sep 17 00:00:00 2001 From: KWSys Upstream <kwrobot@kitware.com> Date: Mon, 28 Jun 2021 13:30:45 -0400 Subject: [PATCH 0783/1519] KWSys 2021-06-28 (0648cb1a) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 0648cb1ac5c91430b190f32319c528345b280dc3 (master). Upstream Shortlog ----------------- Ben Boeckel (2): df91e5f1 EncodingC: use NULL for pointers ab959cd2 SystemInformation: fix typo in comment Björn Esser (2): b4a2a03c testDynamicLoader: Use LIBDL_SO macro if defined. b954dd54 testDynamicLoader: Use LIBC_SO if LIBDL_SO is not defined by glibc anymore. --- EncodingC.c | 2 +- SystemInformation.cxx | 2 +- testDynamicLoader.cxx | 23 +++++++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/EncodingC.c b/EncodingC.c index e12236afe5a..13127f1acc6 100644 --- a/EncodingC.c +++ b/EncodingC.c @@ -60,7 +60,7 @@ size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n) char* kwsysEncoding_DupToNarrow(const wchar_t* str) { char* ret = NULL; - size_t length = kwsysEncoding_wcstombs(0, str, 0) + 1; + size_t length = kwsysEncoding_wcstombs(NULL, str, 0) + 1; if (length > 0) { ret = (char*)malloc(length); if (ret) { diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 117ff8d1ecf..12f9139cc93 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -1383,7 +1383,7 @@ void SymbolProperties::Initialize(void* address) } # else // second fallback use builtin backtrace_symbols -// to decode the bactrace. +// to decode the backtrace. # endif } #endif // don't define this class if we're not using it diff --git a/testDynamicLoader.cxx b/testDynamicLoader.cxx index 703ad4dcd48..9ba204e788a 100644 --- a/testDynamicLoader.cxx +++ b/testDynamicLoader.cxx @@ -8,6 +8,25 @@ # include <be/kernel/OS.h> /* disable_debugger() API. */ #endif +// Needed for __GLIBC__ test macro. +#ifdef __linux__ +# include <features.h> +#endif + +// Will define LIBDL_SO macro on systems with glibc. +#ifdef __GLIBC__ +# include <gnu/lib-names.h> +// Define to LIBC_SO, if not defined by above header. +# ifndef LIBDL_SO +# define LIBDL_SO LIBC_SO +# endif +#endif + +// Define the LIBDL_SO macro, if not defined above. +#ifndef LIBDL_SO +# define LIBDL_SO "libdl.so" +#endif + // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. #if 0 @@ -107,8 +126,8 @@ int testDynamicLoader(int argc, char* argv[]) // This one is actually fun to test, since dlopen is by default // loaded...wonder why :) res += TestDynamicLoader("foobar.lib", "dlopen", 0, 1, 0); - res += TestDynamicLoader("libdl.so", "dlopen", 1, 1, 1); - res += TestDynamicLoader("libdl.so", "TestDynamicLoader", 1, 0, 1); + res += TestDynamicLoader(LIBDL_SO, "dlopen", 1, 1, 1); + res += TestDynamicLoader(LIBDL_SO, "TestDynamicLoader", 1, 0, 1); #endif // Now try on the generated library std::string libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynload"); From 06d2c3fce453365e36fc3d3c483bc9130268c7d9 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 29 Jun 2021 00:01:13 -0400 Subject: [PATCH 0784/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bdc71d9ae63..eb5b522a0bc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210628) +set(CMake_VERSION_PATCH 20210629) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 16208ac1132b5624743c3ea534f610541d90ab8f Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 29 Jun 2021 13:36:28 +0200 Subject: [PATCH 0785/1519] CMP0126: Add control for warnings Fixes: #22353 --- Help/policy/CMP0126.rst | 4 +++- .../variable/CMAKE_POLICY_WARNING_CMPNNNN.rst | 2 ++ Source/cmMakefile.cxx | 23 ++++++++++++++++--- Source/cmProjectCommand.cxx | 4 ++-- .../CMP0126/CMP0126-WARN-default.cmake | 3 +++ .../RunCMake/CMP0126/CMP0126-WARN-stderr.txt | 10 ++++++++ Tests/RunCMake/CMP0126/CMP0126-WARN.cmake | 5 ++++ Tests/RunCMake/CMP0126/RunCMakeTest.cmake | 2 ++ 8 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake create mode 100644 Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0126/CMP0126-WARN.cmake diff --git a/Help/policy/CMP0126.rst b/Help/policy/CMP0126.rst index 4c8e9281424..0ced8fa5aae 100644 --- a/Help/policy/CMP0126.rst +++ b/Help/policy/CMP0126.rst @@ -15,6 +15,8 @@ behavior for this policy is to keep the normal variable of the same name. This policy was introduced in CMake version 3.21. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. Unlike many policies, CMake version |release| does *not* warn when the policy -is not set and simply uses ``OLD`` behavior. +is not set and simply uses ``OLD`` behavior. See documentation of the +:variable:`CMAKE_POLICY_WARNING_CMP0126 <CMAKE_POLICY_WARNING_CMP<NNNN>>` +variable to control the warning. .. include:: DEPRECATED.txt diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst index 9f68741a511..b991db2df31 100644 --- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst +++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst @@ -29,6 +29,8 @@ warn by default: policy :policy:`CMP0112`. * ``CMAKE_POLICY_WARNING_CMP0116`` controls the warning for policy :policy:`CMP0116`. +* ``CMAKE_POLICY_WARNING_CMP0126`` controls the warning for + policy :policy:`CMP0126`. This variable should not be set by a project in CMake code. Project developers running CMake may set this variable in their cache to diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index d2d34f9fb74..c970abe8a76 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1962,9 +1962,26 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, } } this->GetCMakeInstance()->AddCacheEntry(name, value, doc, type); - if (this->GetPolicyStatus(cmPolicies::CMP0126) != cmPolicies::NEW) { - // if there was a definition then remove it - this->StateSnapshot.RemoveDefinition(name); + switch (this->GetPolicyStatus(cmPolicies::CMP0126)) { + case cmPolicies::WARN: + if (this->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0126") && + this->IsNormalDefinitionSet(name)) { + this->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0126), + "\nFor compatibility with older versions of CMake, normal " + "variable \"", + name, "\" will be removed from the current scope.")); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + // if there was a definition then remove it + this->StateSnapshot.RemoveDefinition(name); + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + break; } } diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index acdb09f3361..6950c19efa7 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -71,7 +71,7 @@ bool cmProjectCommand(std::vector<std::string> const& args, // CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build // will work. if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) { - mf.AddDefinition("CMAKE_PROJECT_NAME", projectName); + mf.RemoveDefinition("CMAKE_PROJECT_NAME"); mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName, "Value Computed by CMake", cmStateEnums::STATIC); } @@ -395,7 +395,7 @@ static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name, // in the same CMakeLists.txt file, and it is the top level // CMakeLists.txt file, then go with the last one. if (!mf.GetDefinition(name) || mf.IsRootMakefile()) { - mf.AddDefinition(name, value); + mf.RemoveDefinition(name); mf.AddCacheDefinition(name, value, "Value Computed by CMake", cmStateEnums::STATIC); } diff --git a/Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake b/Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake new file mode 100644 index 00000000000..3147fc432ee --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-WARN-default.cmake @@ -0,0 +1,3 @@ + +set(MY_VAR 1) +set(MY_VAR 2 CACHE STRING "") diff --git a/Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt b/Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt new file mode 100644 index 00000000000..2301511e83b --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-WARN-stderr.txt @@ -0,0 +1,10 @@ +CMake Warning \(dev\) at CMP0126-WARN.cmake:[0-9]+ \(set\): + Policy CMP0126 is not set: set\(CACHE\) does not remove a normal variable of + the same name\. Run "cmake --help-policy CMP0126" for policy details\. Use + the cmake_policy command to set the policy and suppress this warning\. + + For compatibility with older versions of CMake, normal variable "MY_VAR" + will be removed from the current scope\. +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/CMP0126/CMP0126-WARN.cmake b/Tests/RunCMake/CMP0126/CMP0126-WARN.cmake new file mode 100644 index 00000000000..111c8243457 --- /dev/null +++ b/Tests/RunCMake/CMP0126/CMP0126-WARN.cmake @@ -0,0 +1,5 @@ + +set(CMAKE_POLICY_WARNING_CMP0126 1) + +set(MY_VAR 1) +set(MY_VAR 2 CACHE STRING "") diff --git a/Tests/RunCMake/CMP0126/RunCMakeTest.cmake b/Tests/RunCMake/CMP0126/RunCMakeTest.cmake index ae988f4c68d..77c38784c7c 100644 --- a/Tests/RunCMake/CMP0126/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMP0126/RunCMakeTest.cmake @@ -4,3 +4,5 @@ run_cmake(CMP0126-OLD) run_cmake_with_options(CMP0126-OLD_CL -DVAR=3) run_cmake(CMP0126-NEW) run_cmake_with_options(CMP0126-NEW_CL -DVAR=3) +run_cmake(CMP0126-WARN) +run_cmake(CMP0126-WARN-default) From 3a0effcd16f657a13390cfd27a13ca334df1ac98 Mon Sep 17 00:00:00 2001 From: Yuichiro Utsumi <utsumi.yuichiro@jp.fujitsu.com> Date: Tue, 29 Jun 2021 06:38:18 +0000 Subject: [PATCH 0786/1519] FujitsuClang: Set CMAKE_<LANG>_COMPILER_AR and CMAKE_<LANG>_COMPILER_RANLIB Fixes: #22337 --- Modules/Compiler/FujitsuClang-FindBinUtils.cmake | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Modules/Compiler/FujitsuClang-FindBinUtils.cmake diff --git a/Modules/Compiler/FujitsuClang-FindBinUtils.cmake b/Modules/Compiler/FujitsuClang-FindBinUtils.cmake new file mode 100644 index 00000000000..4a6401d957b --- /dev/null +++ b/Modules/Compiler/FujitsuClang-FindBinUtils.cmake @@ -0,0 +1,6 @@ +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR ar) +set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB ranlib) From 6ce97c2248ca62f7154f6b3eb44119b2a010aa87 Mon Sep 17 00:00:00 2001 From: Yuichiro Utsumi <utsumi.yuichiro@jp.fujitsu.com> Date: Tue, 29 Jun 2021 08:32:45 +0000 Subject: [PATCH 0787/1519] FujitsuClang: Change LTO option from -flto=thin to -flto Since -flto=thin is not supported officially in FujitsuClang, change to -flto. --- Modules/Compiler/Clang.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index 7035d934604..f885eb0234e 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -56,6 +56,7 @@ else() set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "AppleClang" __is_apple_clang) + string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "FujitsuClang" __is_fujitsu_clang) # '-flto=thin' available since Clang 3.9 and Xcode 8 # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm @@ -65,6 +66,8 @@ else() if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 8.0) set(_CMAKE_LTO_THIN FALSE) endif() + elseif(__is_fujitsu_clang) + set(_CMAKE_LTO_THIN FALSE) else() if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9) set(_CMAKE_LTO_THIN FALSE) From 61a737b088717201c331b83bd8794149e5d112e5 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Tue, 29 Jun 2021 11:27:07 +0900 Subject: [PATCH 0788/1519] cmGlobalNinjaGenerator: Rename SupportsConsolePool to SupportsDirectConsole Use a name that is not ninja-specific. --- Source/cmGlobalNinjaGenerator.cxx | 6 +++--- Source/cmGlobalNinjaGenerator.h | 2 +- Source/cmLocalNinjaGenerator.cxx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 963118fd626..bfc50c888fc 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -382,7 +382,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( if (restat) { vars["restat"] = "1"; } - if (uses_terminal && this->SupportsConsolePool()) { + if (uses_terminal && this->SupportsDirectConsole()) { vars["pool"] = "console"; } else if (!job_pool.empty()) { vars["pool"] = job_pool; @@ -1847,7 +1847,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) // Use 'console' pool to get non buffered output of the CMake re-run call // Available since Ninja 1.5 - if (this->SupportsConsolePool()) { + if (this->SupportsDirectConsole()) { reBuild.Variables["pool"] = "console"; } @@ -1941,7 +1941,7 @@ std::string cmGlobalNinjaGenerator::NinjaCmd() const return "ninja"; } -bool cmGlobalNinjaGenerator::SupportsConsolePool() const +bool cmGlobalNinjaGenerator::SupportsDirectConsole() const { return this->NinjaSupportsConsolePool; } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index bb4ce2bf202..9aa1152485a 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -406,7 +406,7 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator return "1.10.2"; } static std::string RequiredNinjaVersionForCodePage() { return "1.11"; } - bool SupportsConsolePool() const; + bool SupportsDirectConsole() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; bool SupportsMultilineDepfile() const; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 7f7b1e7d734..9f8e7ed4cbe 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -279,7 +279,7 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion(); // Ninja generator uses the 'console' pool if available (>= 1.5) - if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) { + if (this->GetGlobalNinjaGenerator()->SupportsDirectConsole()) { requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool(); } From 1db4d7462808e9af5e2a6de029943d51a521f52c Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Tue, 29 Jun 2021 11:27:07 +0900 Subject: [PATCH 0789/1519] cmGlobalCommonGenerator: Add SupportsDirectConsole Default to `true` since this is used by Makefile generators. The Ninja generator already overrides it to use a version check. --- Source/cmGlobalCommonGenerator.h | 3 +++ Source/cmGlobalNinjaGenerator.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h index 2aa9d27829e..21cfd1175b9 100644 --- a/Source/cmGlobalCommonGenerator.h +++ b/Source/cmGlobalCommonGenerator.h @@ -42,4 +42,7 @@ class cmGlobalCommonGenerator : public cmGlobalGenerator std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const; bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t, const std::string& config); + +protected: + virtual bool SupportsDirectConsole() const { return true; } }; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 9aa1152485a..ce471229f2f 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -406,7 +406,7 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator return "1.10.2"; } static std::string RequiredNinjaVersionForCodePage() { return "1.11"; } - bool SupportsDirectConsole() const; + bool SupportsDirectConsole() const override; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; bool SupportsMultilineDepfile() const; From 23af78bb78b924b52b180049eb2ce62a4339251e Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Sun, 27 Jun 2021 06:45:26 +0900 Subject: [PATCH 0790/1519] cmGlobalCommonGenerator: Adopt GetEditCacheTargetName The implementation is the same for both Makefile and Ninja generators. --- Source/cmGlobalCommonGenerator.h | 1 + Source/cmGlobalNinjaGenerator.h | 1 - Source/cmGlobalUnixMakefileGenerator3.h | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h index 21cfd1175b9..c641240f3d2 100644 --- a/Source/cmGlobalCommonGenerator.h +++ b/Source/cmGlobalCommonGenerator.h @@ -45,4 +45,5 @@ class cmGlobalCommonGenerator : public cmGlobalGenerator protected: virtual bool SupportsDirectConsole() const { return true; } + const char* GetEditCacheTargetName() const override { return "edit_cache"; } }; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index ce471229f2f..519be3fdf3b 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -220,7 +220,6 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator { return "package_source"; } - const char* GetEditCacheTargetName() const override { return "edit_cache"; } const char* GetRebuildCacheTargetName() const override { return "rebuild_cache"; diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 7c950cca128..3073f72ffb0 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -228,7 +228,6 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator { return "package_source"; } - const char* GetEditCacheTargetName() const override { return "edit_cache"; } const char* GetRebuildCacheTargetName() const override { return "rebuild_cache"; From da0f74b5a1f120157d401b1430b36550a924db34 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 10:59:05 -0400 Subject: [PATCH 0791/1519] VS: Add ARM64EC to supported platforms for VS 16 and 17 In commit 4ea3a88625 (MSVC: Add support for targeting ARM64EC, 2020-12-30, v3.20.0-rc1~121^2) the `ARM64EC` platform was accidentally added to the list for VS 15 (2017) instead of VS 16 (2019). Its omission from the list of platforms was then repeated for VS 17 (2022). Issue: #21724 --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index aafc9d5e963..4fab0b930b9 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -211,7 +211,6 @@ class cmGlobalVisualStudioVersionedGenerator::Factory15 platforms.emplace_back("Win32"); platforms.emplace_back("ARM"); platforms.emplace_back("ARM64"); - platforms.emplace_back("ARM64EC"); return platforms; } @@ -305,6 +304,7 @@ class cmGlobalVisualStudioVersionedGenerator::Factory16 platforms.emplace_back("Win32"); platforms.emplace_back("ARM"); platforms.emplace_back("ARM64"); + platforms.emplace_back("ARM64EC"); return platforms; } @@ -369,6 +369,7 @@ class cmGlobalVisualStudioVersionedGenerator::Factory17 platforms.emplace_back("Win32"); platforms.emplace_back("ARM"); platforms.emplace_back("ARM64"); + platforms.emplace_back("ARM64EC"); return platforms; } From 7cb4ad7e3990c879088b7573d136509989ed3f5b Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Sun, 27 Jun 2021 06:45:26 +0900 Subject: [PATCH 0792/1519] cmGlobalCommonGenerator: Adopt GetEditCacheCommand Move the implementation from the Makefile generator so it can be later used by the Ninja generator too. --- Source/cmGlobalCommonGenerator.cxx | 34 +++++++++++++++++++++-- Source/cmGlobalCommonGenerator.h | 1 + Source/cmGlobalUnixMakefileGenerator3.cxx | 30 -------------------- Source/cmGlobalUnixMakefileGenerator3.h | 1 - 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 9e5bbca003a..a4112db7dc2 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -16,8 +16,8 @@ #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" - -class cmake; +#include "cmSystemTools.h" +#include "cmake.h" cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm) : cmGlobalGenerator(cm) @@ -95,3 +95,33 @@ bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig( } return !t.ExcludedFromAllInConfigs.empty(); } + +std::string cmGlobalCommonGenerator::GetEditCacheCommand() const +{ + // If generating for an extra IDE, the edit_cache target cannot + // launch a terminal-interactive tool, so always use cmake-gui. + if (!this->GetExtraGeneratorName().empty()) { + return cmSystemTools::GetCMakeGUICommand(); + } + + // Use an internal cache entry to track the latest dialog used + // to edit the cache, and use that for the edit_cache target. + cmake* cm = this->GetCMakeInstance(); + std::string editCacheCommand = cm->GetCMakeEditCommand(); + if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") || + !editCacheCommand.empty()) { + if (editCacheCommand.empty()) { + editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); + } + if (editCacheCommand.empty()) { + editCacheCommand = cmSystemTools::GetCMakeGUICommand(); + } + if (!editCacheCommand.empty()) { + cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), + "Path to cache edit program executable.", + cmStateEnums::INTERNAL); + } + } + cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); + return edit_cmd ? *edit_cmd : std::string(); +} diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h index c641240f3d2..fed9ce81b12 100644 --- a/Source/cmGlobalCommonGenerator.h +++ b/Source/cmGlobalCommonGenerator.h @@ -46,4 +46,5 @@ class cmGlobalCommonGenerator : public cmGlobalGenerator protected: virtual bool SupportsDirectConsole() const { return true; } const char* GetEditCacheTargetName() const override { return "edit_cache"; } + std::string GetEditCacheCommand() const override; }; diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 9c3de1eed6f..d9f94a12ce8 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -78,36 +78,6 @@ void cmGlobalUnixMakefileGenerator3::GetDocumentation( entry.Brief = "Generates standard UNIX makefiles."; } -std::string cmGlobalUnixMakefileGenerator3::GetEditCacheCommand() const -{ - // If generating for an extra IDE, the edit_cache target cannot - // launch a terminal-interactive tool, so always use cmake-gui. - if (!this->GetExtraGeneratorName().empty()) { - return cmSystemTools::GetCMakeGUICommand(); - } - - // Use an internal cache entry to track the latest dialog used - // to edit the cache, and use that for the edit_cache target. - cmake* cm = this->GetCMakeInstance(); - std::string editCacheCommand = cm->GetCMakeEditCommand(); - if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") || - !editCacheCommand.empty()) { - if (editCacheCommand.empty()) { - editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); - } - if (editCacheCommand.empty()) { - editCacheCommand = cmSystemTools::GetCMakeGUICommand(); - } - if (!editCacheCommand.empty()) { - cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), - "Path to cache edit program executable.", - cmStateEnums::INTERNAL); - } - } - cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); - return edit_cmd ? *edit_cmd : std::string(); -} - void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 3073f72ffb0..94ee47633b8 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -277,7 +277,6 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator private: const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; } - std::string GetEditCacheCommand() const override; std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>, cmStateSnapshot::StrictWeakOrder> From 51bf4094fb7c3bf82c6e51d8e6b55e0cc289e5a5 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Thu, 24 Jun 2021 22:13:08 +0900 Subject: [PATCH 0793/1519] Ninja: Use `ccmake` for `edit_cache` If `ninja` is new enough to support the console pool, and `ccmake` is available, use it for `edit_cache`. --- Help/release/dev/ninja-edit_cache.rst | 5 +++++ Source/cmGlobalCommonGenerator.cxx | 2 +- Source/cmGlobalNinjaGenerator.cxx | 7 ------- Source/cmGlobalNinjaGenerator.h | 1 - 4 files changed, 6 insertions(+), 9 deletions(-) create mode 100644 Help/release/dev/ninja-edit_cache.rst diff --git a/Help/release/dev/ninja-edit_cache.rst b/Help/release/dev/ninja-edit_cache.rst new file mode 100644 index 00000000000..9083f56c181 --- /dev/null +++ b/Help/release/dev/ninja-edit_cache.rst @@ -0,0 +1,5 @@ +ninja-edit_cache +---------------- + +* The :ref:`Ninja Generators` now implement the ``edit_cache`` target + using :manual:`ccmake(1)` if available. diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index a4112db7dc2..a8e0f235a48 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -110,7 +110,7 @@ std::string cmGlobalCommonGenerator::GetEditCacheCommand() const std::string editCacheCommand = cm->GetCMakeEditCommand(); if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") || !editCacheCommand.empty()) { - if (editCacheCommand.empty()) { + if (this->SupportsDirectConsole() && editCacheCommand.empty()) { editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); } if (editCacheCommand.empty()) { diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index bfc50c888fc..2d36fd87284 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1019,13 +1019,6 @@ bool cmGlobalNinjaGenerator::HasRule(const std::string& name) // Private virtual overrides -std::string cmGlobalNinjaGenerator::GetEditCacheCommand() const -{ - // Ninja by design does not run interactive tools in the terminal, - // so our only choice is cmake-gui. - return cmSystemTools::GetCMakeGUICommand(); -} - void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 519be3fdf3b..ec73475db5d 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -488,7 +488,6 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator std::string DefaultFileConfig; private: - std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; void CheckNinjaFeatures(); void CheckNinjaCodePage(); From 9b53eca317e52dffa1ba8972981af7b40392e323 Mon Sep 17 00:00:00 2001 From: Alex Sweet <asweet@ss8.com> Date: Tue, 29 Jun 2021 07:13:20 -0700 Subject: [PATCH 0794/1519] CPack/RPM: Fix weak dep support RPM 4.11.3 for el7 contains backported support for the RPM weak dep tags. It only supports querying those tags, but rpmbuild can not make use of them. Since CPack relies on rpmbuild --querytags to check for support, this commit switches to rpm --suggests to check for support of weak dependencies. Fixes: #22350 --- Help/cpack_gen/rpm.rst | 6 +++-- Modules/Internal/CPack/CPackRPM.cmake | 15 +++++++++++++ .../CPack/tests/SUGGESTS/VerifyResult.cmake | 20 ++++++++--------- .../CPack/tests/SUGGESTS/test_suggests.spec | 22 +++++++++++++++++++ 4 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst index 5260a1d7c30..322ab68aa33 100644 --- a/Help/cpack_gen/rpm.rst +++ b/Help/cpack_gen/rpm.rst @@ -394,8 +394,10 @@ List of CPack RPM generator specific variables: * Mandatory : NO * Default : - - May be used to set weak RPM dependencies (suggests). Note that you must - enclose the complete requires string between quotes. + May be used to set weak RPM dependencies (suggests). If ``rpmbuild`` doesn't + support the ``Suggests`` tag, CPack will emit a warning and ignore this + variable. Note that you must enclose the complete requires string between + quotes. .. variable:: CPACK_RPM_PACKAGE_PROVIDES CPACK_RPM_<component>_PACKAGE_PROVIDES diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index bece2dd1de2..47d2a5c7fee 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -1074,6 +1074,21 @@ function(cpack_rpm_generate_package) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE "\n" ";" RPMBUILD_TAG_LIST "${RPMBUILD_TAG_LIST}") + # In some versions of RPM, weak dependency tags are present in the --querytags + # list, but unsupported by rpmbuild. A different method must be used to check + # if they are supported. + + execute_process( + COMMAND ${RPM_EXECUTABLE} --suggests + ERROR_QUIET + RESULT_VARIABLE RPMBUILD_SUGGESTS_RESULT) + + if(NOT RPMBUILD_SUGGESTS_RESULT EQUAL 0) + foreach(_WEAK_DEP SUGGESTS RECOMMENDS SUPPLEMENTS ENHANCES) + list(REMOVE_ITEM RPMBUILD_TAG_LIST ${_WEAK_DEP}) + endforeach() + endif() + if(CPACK_RPM_PACKAGE_EPOCH) set(TMP_RPM_EPOCH "Epoch: ${CPACK_RPM_PACKAGE_EPOCH}") endif() diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake index 61ce752fe92..d1d615be71c 100644 --- a/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake @@ -1,15 +1,13 @@ -execute_process(COMMAND ${RPMBUILD_EXECUTABLE} --querytags - OUTPUT_VARIABLE RPMBUILD_CAPS - RESULT_VARIABLE RPMBUILD_CAPS_RESULT) +# CPack uses `rpm --suggests` to check if rpmbuild supports the "Suggests:" tag. +# This test intentionally uses a different method (build a test .spec) so any +# problems will be caught early if functionality should change in the future. +execute_process( + COMMAND ${RPMBUILD_EXECUTABLE} --nobuild test_suggests.spec + ERROR_QUIET + RESULT_VARIABLE RPMBUILD_SUGGESTS_RESULT) -if(NOT RPMBUILD_CAPS_RESULT) - string(REPLACE "\n" ";" RPMBUILD_CAPS "${RPMBUILD_CAPS}") - cmake_policy(PUSH) - cmake_policy(SET CMP0057 NEW) - if(SUGGESTS IN_LIST RPMBUILD_CAPS) - set(should_contain_suggests_tag_ true) - endif() - cmake_policy(POP) +if(RPMBUILD_SUGGESTS_RESULT EQUAL 0) + set(should_contain_suggests_tag_ true) endif() # Only verify that suggests tag is present only if that tag is supported. diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec b/Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec new file mode 100644 index 00000000000..e766fa95ced --- /dev/null +++ b/Tests/RunCMake/CPack/tests/SUGGESTS/test_suggests.spec @@ -0,0 +1,22 @@ +# This spec file is used to check if the provided version of rpmbuild supports the "Suggests:" tag + +Name: test +Version: 0 +Release: 1 +Summary: test +License: test + +Suggests: suggested_package + +%description + + +%prep + +%build +%configure +%install +%clean +%files +%doc +%changelog From c6aaaf066a39485bf34869ccae5b5d4fac04f0b9 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 12:53:02 -0400 Subject: [PATCH 0795/1519] DetermineCompiler: Restore identification of MSVC with no INCLUDE dirs Since commit bd844387df (ROCMClang: Add the ROCm toolkit derived clang compiler to CMake, 2020-08-28, v3.21.0-rc1~66^2~6), our generated compiler id source file contains a preprocessor condition of the form #elif ... && __has_include(...) When MSVC is invoked with no include directories in the `INCLUDE` environment variable or in `-I` flags, its implementation of `__has_include` errors out immediately. This breaks identification of the compiler. Work around the problem by adding a fallback attempt to compile the identification source using a dummy include directory. --- Modules/CMakeDetermineCCompiler.cmake | 4 ++++ Modules/CMakeDetermineCXXCompiler.cmake | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index cd07ba983b7..ca497f1f909 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -85,6 +85,10 @@ else() # ARMClang need target options "--target=arm-arm-none-eabi -mcpu=cortex-m3" + + # MSVC needs at least one include directory for __has_include to function, + # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags. + "-I__does_not_exist__" ) endif() if(CMAKE_C_COMPILER_TARGET) diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 3d1a7bba28a..e297f90b756 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -80,6 +80,10 @@ else() # ARMClang need target options "--target=arm-arm-none-eabi -mcpu=cortex-m3" + + # MSVC needs at least one include directory for __has_include to function, + # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags. + "-I__does_not_exist__" ) endif() From e27a76f1311ab4ad1be07df018ac748d4b725cea Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 15:57:16 -0400 Subject: [PATCH 0796/1519] target_link_libraries: Restore transitive out-of-dir linking Refactoring in commit 7f506b95a7 (cmGeneratorTarget: Refactor link item lookup, 2021-05-26, v3.21.0-rc1~103^2~4) accidentally dropped the persistent lookup scope tracking across multiple items that was added by commit f0e67da061 (target_link_libraries: Fix out-of-dir linking of a list of targets, 2020-01-14, v3.17.0-rc1~149^2). This broke a transitive out-of-dir linking case not covered by our test suite. Restore the scope tracking and add a test case. Fixes: #22363 --- Source/cmGeneratorTarget.cxx | 14 ++++++++------ Source/cmGeneratorTarget.h | 7 ++++++- .../target_link_libraries/CMakeLists.txt | 2 ++ .../target_link_libraries/SubDirA/CMakeLists.txt | 4 ++++ .../target_link_libraries/SubDirB/CMakeLists.txt | 4 ++++ Tests/CMakeCommands/target_link_libraries/TopDir.c | 6 ++++++ 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f268c6c3e6f..f1ef130afed 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6346,11 +6346,11 @@ bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, } cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( - std::string const& n, cmListFileBacktrace const& bt) const + std::string const& n, cmListFileBacktrace const& bt, + LookupLinkItemScope* scope) const { cm::optional<cmLinkItem> maybeItem; - cmLocalGenerator const* lg = this->LocalGenerator; - if (this->IsLinkLookupScope(n, lg)) { + if (this->IsLinkLookupScope(n, scope->LG)) { return maybeItem; } @@ -6358,7 +6358,7 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( if (name == this->GetName() || name.empty()) { return maybeItem; } - maybeItem = this->ResolveLinkItem(name, bt, lg); + maybeItem = this->ResolveLinkItem(name, bt, scope->LG); return maybeItem; } @@ -6385,9 +6385,10 @@ void cmGeneratorTarget::ExpandLinkItems( &dagChecker, this, headTarget->LinkerLanguage), libs); cmMakefile const* mf = this->LocalGenerator->GetMakefile(); + LookupLinkItemScope scope{ this->LocalGenerator }; for (std::string const& lib : libs) { if (cm::optional<cmLinkItem> maybeItem = - this->LookupLinkItem(lib, cge->GetBacktrace())) { + this->LookupLinkItem(lib, cge->GetBacktrace(), &scope)) { if (!maybeItem->Target) { // Report explicitly linked object files separately. std::string const& maybeObj = maybeItem->AsStr(); @@ -7089,9 +7090,10 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); std::vector<std::string> deps = cmExpandedList(info->SharedDeps); + LookupLinkItemScope scope{ this->LocalGenerator }; for (std::string const& dep : deps) { if (cm::optional<cmLinkItem> maybeItem = - this->LookupLinkItem(dep, cmListFileBacktrace())) { + this->LookupLinkItem(dep, cmListFileBacktrace(), &scope)) { iface.SharedDeps.emplace_back(std::move(*maybeItem)); } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index ed66fb1a819..6d2aa85ed29 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1042,8 +1042,13 @@ class cmGeneratorTarget bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const; + struct LookupLinkItemScope + { + cmLocalGenerator const* LG; + }; cm::optional<cmLinkItem> LookupLinkItem(std::string const& n, - cmListFileBacktrace const& bt) const; + cmListFileBacktrace const& bt, + LookupLinkItemScope* scope) const; std::vector<BT<std::string>> GetSourceFilePaths( std::string const& config) const; diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index aa8e21a68cd..07ec4e32db3 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -140,6 +140,8 @@ cmake_policy(PUSH) cmake_policy(SET CMP0022 NEW) cmake_policy(SET CMP0079 NEW) add_executable(TopDir TopDir.c) +add_library(TopDirInterface INTERFACE) +target_link_libraries(TopDir PRIVATE TopDirInterface) add_subdirectory(SubDirA) add_subdirectory(SubDirB) target_link_libraries(SubDirB TopDirImported) diff --git a/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt index 4dae1039576..df7c483c6ab 100644 --- a/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/SubDirA/CMakeLists.txt @@ -3,6 +3,8 @@ add_executable(SubDirA SubDirA.c) # Link to a target imported in this directory that would not normally # be visible to the directory in which TopDir is defined. target_link_libraries(TopDir PUBLIC SameNameImported) +# Do the same through an interface library in the top. +target_link_libraries(TopDirInterface INTERFACE SameNameImported2) # Link SubDirA to a target imported in this directory that has the same # name as a target imported in SubDirB's directory. SubDirB will also @@ -13,3 +15,5 @@ target_link_libraries(SubDirA PRIVATE SameNameImported) # Distinguish this copy by having a unique usage requirement. add_library(SameNameImported IMPORTED INTERFACE) target_compile_definitions(SameNameImported INTERFACE DEF_SameNameImportedSubDirA) +add_library(SameNameImported2 INTERFACE IMPORTED) +target_compile_definitions(SameNameImported2 INTERFACE DEF_SameNameImported2SubDirA) diff --git a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt index 06d1111046c..9af577c01ea 100644 --- a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt @@ -3,6 +3,8 @@ add_executable(SubDirB SubDirB.c) # Link to a target imported in this directory that would not normally # be visible to the directory in which TopDir is defined. target_link_libraries(TopDir PUBLIC debug SameNameImported optimized SameNameImported) +# Do the same through an interface library in the top. +target_link_libraries(TopDirInterface INTERFACE debug SameNameImported2 optimized SameNameImported2) # Link to a list of targets imported in this directory that would not # normally be visible to the directory in which TopDir is defined. @@ -17,3 +19,5 @@ target_link_libraries(SubDirA PRIVATE SameNameImported) # Distinguish this copy by having a unique usage requirement. add_library(SameNameImported IMPORTED INTERFACE) target_compile_definitions(SameNameImported INTERFACE DEF_SameNameImportedSubDirB) +add_library(SameNameImported2 INTERFACE IMPORTED) +target_compile_definitions(SameNameImported2 INTERFACE DEF_SameNameImported2SubDirB) diff --git a/Tests/CMakeCommands/target_link_libraries/TopDir.c b/Tests/CMakeCommands/target_link_libraries/TopDir.c index d8066e5cae1..708b5c1fa9a 100644 --- a/Tests/CMakeCommands/target_link_libraries/TopDir.c +++ b/Tests/CMakeCommands/target_link_libraries/TopDir.c @@ -4,6 +4,12 @@ #ifndef DEF_SameNameImportedSubDirB # error "DEF_SameNameImportedSubDirB is not defined but should be!" #endif +#ifndef DEF_SameNameImported2SubDirA +# error "DEF_SameNameImported2SubDirA is not defined but should be!" +#endif +#ifndef DEF_SameNameImported2SubDirB +# error "DEF_SameNameImported2SubDirB is not defined but should be!" +#endif #ifdef DEF_TopDirImported # error "DEF_TopDirImported is defined but should not be!" #endif From 82183329a5ea8c2ef0158bf6f94946741c189723 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 30 Jun 2021 00:01:09 -0400 Subject: [PATCH 0797/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index eb5b522a0bc..245217a5b9a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210629) +set(CMake_VERSION_PATCH 20210630) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e610e99ad34a545ac67f1977e78ea59a52fdcf79 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 07:51:35 -0400 Subject: [PATCH 0798/1519] CMake 3.21.0-rc2 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6e24a6147ab..7542fa149d5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 1) +set(CMake_VERSION_RC 2) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 9028195a22514ca008c3aae5de0e58e1a112e34e Mon Sep 17 00:00:00 2001 From: Alexey Rogachevskiy <sfalexrog@gmail.com> Date: Wed, 30 Jun 2021 15:23:07 +0300 Subject: [PATCH 0799/1519] CPackDeb: sort package files before generating deb file This should make the order in which the files are added to md5sums and archives is stable, thus making package files more reproducible. Fixes: #22361 --- Source/CPack/cmCPackDebGenerator.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 006d66d3b13..db30a0d663c 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackDebGenerator.h" +#include <algorithm> #include <cstdlib> #include <cstring> #include <map> @@ -525,6 +526,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, return 0; } this->packageFiles = gl.GetFiles(); + // Sort files so that they have a reproducible order + std::sort(this->packageFiles.begin(), this->packageFiles.end()); } int res = this->createDeb(); @@ -551,6 +554,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, return 0; } this->packageFiles = gl.GetFiles(); + // Sort files so that they have a reproducible order + std::sort(this->packageFiles.begin(), this->packageFiles.end()); res = this->createDbgsymDDeb(); if (res != 1) { @@ -672,6 +677,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( return 0; } this->packageFiles = gl.GetFiles(); + // Sort files so that they have a reproducible order + std::sort(this->packageFiles.begin(), this->packageFiles.end()); int res = this->createDeb(); if (res != 1) { From a0d3494afacc28ec75318470b806cea06e90eb99 Mon Sep 17 00:00:00 2001 From: Alexey Rogachevskiy <sfalexrog@gmail.com> Date: Wed, 30 Jun 2021 15:24:48 +0300 Subject: [PATCH 0800/1519] Tests: update MD5SUMS test to have several files The test is now updated to check the order of files in the md5sums. --- Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake | 2 +- Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake | 3 ++- Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake index d1a3a5fb2db..f8592151e21 100644 --- a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/bar;/bar/CMakeLists.txt;/baz;/baz/CMakeLists.txt;/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake index fbdda9c88ab..13af0977391 100644 --- a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake @@ -1,3 +1,4 @@ set(whitespaces_ "[\t\n\r ]*") -set(md5sums_md5sums "^.* usr/foo/CMakeLists\.txt${whitespaces_}$") +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_}$") verifyDebControl("${FOUND_FILE_1}" "md5sums" "md5sums") diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake index 15c5892666f..3c922d2cefd 100644 --- a/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake @@ -1,4 +1,6 @@ install(FILES CMakeLists.txt DESTINATION foo COMPONENT test) +install(FILES CMakeLists.txt DESTINATION bar COMPONENT test) +install(FILES CMakeLists.txt DESTINATION baz COMPONENT test) if(PACKAGING_TYPE STREQUAL "COMPONENT") set(CPACK_COMPONENTS_ALL test) From ab06f781821205ebf6a015e857d4cd9fa49f06b7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 09:31:55 -0400 Subject: [PATCH 0801/1519] Help: Document VS generator support for Intel Fortran Extend the list of project types added by commit a82eb539f0 (Help: Describe the type of Visual Studio projects that can be generated, 2018-08-04, v3.13.0-rc1~227^2) to mention that Fortran projects are supported with Intel compiler integration. --- Help/generator/Visual Studio 10 2010.rst | 5 +++-- Help/generator/Visual Studio 11 2012.rst | 5 +++-- Help/generator/Visual Studio 12 2013.rst | 5 +++-- Help/generator/Visual Studio 14 2015.rst | 5 +++-- Help/generator/Visual Studio 15 2017.rst | 5 +++-- Help/generator/Visual Studio 16 2019.rst | 5 +++-- Help/generator/Visual Studio 17 2022.rst | 5 +++-- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst index b4376d88bd5..c065550361d 100644 --- a/Help/generator/Visual Studio 10 2010.rst +++ b/Help/generator/Visual Studio 10 2010.rst @@ -9,8 +9,9 @@ generator using the name ``Visual Studio 10`` without the year component. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (Database, Website, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (Database, +Website, etc.) are not supported. Platform Selection ^^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 11 2012.rst b/Help/generator/Visual Studio 11 2012.rst index 932548bd2a7..3952228fe90 100644 --- a/Help/generator/Visual Studio 11 2012.rst +++ b/Help/generator/Visual Studio 11 2012.rst @@ -9,8 +9,9 @@ generator using the name "Visual Studio 11" without the year component. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (JavaScript, Database, Website, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (JavaScript, +Database, Website, etc.) are not supported. Platform Selection ^^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst index 3b4b1f26d6a..54a4d7eb9f3 100644 --- a/Help/generator/Visual Studio 12 2013.rst +++ b/Help/generator/Visual Studio 12 2013.rst @@ -9,8 +9,9 @@ generator using the name "Visual Studio 12" without the year component. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (JavaScript, Powershell, Python, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (JavaScript, +Powershell, Python, etc.) are not supported. Platform Selection ^^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst index 825772329d0..d704ab271e8 100644 --- a/Help/generator/Visual Studio 14 2015.rst +++ b/Help/generator/Visual Studio 14 2015.rst @@ -8,8 +8,9 @@ Generates Visual Studio 14 (VS 2015) project files. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (JavaScript, Powershell, Python, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (JavaScript, +Powershell, Python, etc.) are not supported. Platform Selection ^^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst index a80c57d822b..a4f5f98e3cd 100644 --- a/Help/generator/Visual Studio 15 2017.rst +++ b/Help/generator/Visual Studio 15 2017.rst @@ -8,8 +8,9 @@ Generates Visual Studio 15 (VS 2017) project files. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (JavaScript, Powershell, Python, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (JavaScript, +Powershell, Python, etc.) are not supported. Instance Selection ^^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 16 2019.rst b/Help/generator/Visual Studio 16 2019.rst index 3da80915adb..72399e0a25a 100644 --- a/Help/generator/Visual Studio 16 2019.rst +++ b/Help/generator/Visual Studio 16 2019.rst @@ -8,8 +8,9 @@ Generates Visual Studio 16 (VS 2019) project files. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (JavaScript, Powershell, Python, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (JavaScript, +Powershell, Python, etc.) are not supported. Instance Selection ^^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index c53f8b79a49..06deda463f0 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -13,8 +13,9 @@ Generates Visual Studio 17 (VS 2022) project files. Project Types ^^^^^^^^^^^^^ -Only Visual C++ and C# projects may be generated. Other types of -projects (JavaScript, Powershell, Python, etc.) are not supported. +Only Visual C++ and C# projects may be generated (and Fortran with +Intel compiler integration). Other types of projects (JavaScript, +Powershell, Python, etc.) are not supported. Instance Selection ^^^^^^^^^^^^^^^^^^ From d76cb12905df6d76fe3ee5376913e5d61161f71d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 09:40:23 -0400 Subject: [PATCH 0802/1519] Add deprecation warnings for policies CMP0088 and below The OLD behaviors of all policies are deprecated, but only by documentation. Add an explicit deprecation diagnostic for policies introduced in CMake 3.14 and below to encourage projects to port away from setting policies to OLD. --- Source/cmMakefile.cxx | 7 +++---- .../GeneratorExpression/CMP0085-OLD-stderr.txt | 8 ++++++++ Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt | 10 ++++++++++ Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt | 8 ++++++++ Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt | 10 ++++++++++ Tests/RunCMake/install/CMP0087-OLD-stderr.txt | 8 ++++++++ 6 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt create mode 100644 Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt create mode 100644 Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt create mode 100644 Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt create mode 100644 Tests/RunCMake/install/CMP0087-OLD-stderr.txt diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index c970abe8a76..a2d64e23588 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4426,13 +4426,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, return false; } - // Deprecate old policies, especially those that require a lot - // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 && + // Deprecate old policies. + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0088 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. - id == cmPolicies::CMP0065))) { + id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083))) { this->IssueMessage(MessageType::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } diff --git a/Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt b/Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt new file mode 100644 index 00000000000..cae367903a4 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt @@ -0,0 +1,8 @@ +^CMake Deprecation Warning at CMakeLists.txt:[0-9]+ \(cmake_minimum_required\): + The OLD behavior for policy CMP0085 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/UseSWIG/CMP0086-OLD-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt new file mode 100644 index 00000000000..fca7a73a436 --- /dev/null +++ b/Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0086-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0086 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/add_subdirectory/CMP0082-OLD-stderr.txt b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt new file mode 100644 index 00000000000..50838c38f85 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt @@ -0,0 +1,8 @@ +^CMake Deprecation Warning at CMakeLists.txt:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0082 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/find_package/CMP0084-OLD-stderr.txt b/Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt new file mode 100644 index 00000000000..0db83aa8b89 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0084-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0084 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/CMP0087-OLD-stderr.txt b/Tests/RunCMake/install/CMP0087-OLD-stderr.txt new file mode 100644 index 00000000000..5233ebc5b56 --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-OLD-stderr.txt @@ -0,0 +1,8 @@ +^CMake Deprecation Warning at CMP0087-OLD/CMakeLists.txt:5 \(cmake_policy\): + The OLD behavior for policy CMP0087 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.$ From 83a3db56317bf0ef3b41c4fc437a6a31d36c8b73 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 09:41:37 -0400 Subject: [PATCH 0803/1519] export: Increase maximum policy version in exported files to 3.20 The files generatd by `install(EXPORT)` and `export()` commands are known to work with policies as of CMake 3.20, so enable them in sufficiently new CMake versions. --- Source/cmExportFileGenerator.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index dd611de6b68..c69d484486f 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -924,13 +924,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.19 (this upper limit may be reviewed + // policy settings for up to CMake 3.20 (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. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.6...3.19)\n"; + << "cmake_policy(VERSION 2.6...3.20)\n"; /* clang-format on */ } From 2c209097b9c29aae4ed2bd414e5c48fe6f4e148e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 09:42:46 -0400 Subject: [PATCH 0804/1519] Configure CMake itself with policies through CMake 3.20 --- CMakeLists.txt | 2 +- Utilities/Doxygen/CMakeLists.txt | 2 +- Utilities/Sphinx/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6016cd654db..1261eb053b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -cmake_minimum_required(VERSION 3.1...3.19 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1...3.20 FATAL_ERROR) 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) diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt index 0ccb72124bf..69b4e2fd4ea 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.1...3.19 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.20 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/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index 32efd4842bd..a71dfcdfaab 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.1...3.19 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.20 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) From 03bd9c4c10741073e9f39dee6c5ee6000a2b1da2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 14:18:54 -0400 Subject: [PATCH 0805/1519] cmMakefile: Add helper to initialize CMAKE_CONFIGURATION_TYPES Factor out duplicate code from the Ninja Multi-Config, Visual Studio, and Xcode generators. --- Source/cmGlobalNinjaGenerator.cxx | 9 +-------- Source/cmGlobalVisualStudio7Generator.cxx | 9 +-------- Source/cmGlobalXCodeGenerator.cxx | 9 +-------- Source/cmMakefile.cxx | 13 +++++++++++++ Source/cmMakefile.h | 2 ++ 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 2d36fd87284..47a931dd187 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -920,14 +920,7 @@ void cmGlobalNinjaGenerator::EnableLanguage( std::vector<std::string> const& langs, cmMakefile* mf, bool optional) { if (this->IsMultiConfig()) { - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;RelWithDebInfo", - "Semicolon separated list of supported configuration types, only " - "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything " - "else will be ignored", - cmStateEnums::STRING); - } + mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;RelWithDebInfo"); } this->cmGlobalGenerator::EnableLanguage(langs, mf, optional); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 0c85a044e1e..f8aa1729e4c 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -107,14 +107,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage( { mf->AddDefinition("CMAKE_GENERATOR_RC", "rc"); mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", - "Semicolon separated list of supported configuration types, " - "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " - "anything else will be ignored.", - cmStateEnums::STRING); - } + mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo"); // Create list of configurations requested by user's cache, if any. this->cmGlobalVisualStudioGenerator::EnableLanguage(lang, mf, optional); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 693a11c9a1b..f5139424148 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -431,14 +431,7 @@ void cmGlobalXCodeGenerator::EnableLanguage( { mf->AddDefinition("XCODE", "1"); mf->AddDefinition("XCODE_VERSION", this->VersionString); - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", - "Semicolon separated list of supported configuration types, " - "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " - "anything else will be ignored.", - cmStateEnums::STRING); - } + mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo"); mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); this->ComputeArchitectures(mf); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index c970abe8a76..120cae72399 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3182,6 +3182,19 @@ void cmMakefile::RemoveVariablesInString(std::string& source, } } +void cmMakefile::InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault) +{ + if (this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { + return; + } + this->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", genDefault, + "Semicolon separated list of supported configuration types, " + "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " + "anything else will be ignored.", + cmStateEnums::STRING); +} + std::string cmMakefile::GetDefaultConfiguration() const { if (this->GetGlobalGenerator()->IsMultiConfig()) { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 77e9c740505..14c1a0fc6f1 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -310,6 +310,8 @@ class cmMakefile */ void SetProjectName(std::string const& name); + void InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault); + /* Get the default configuration */ std::string GetDefaultConfiguration() const; From e96169a3eca6f3cda5aa3e9dac2c7e0b6041b44d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 13:53:38 -0400 Subject: [PATCH 0806/1519] Help: Cross-reference CMAKE_CONFIGURATION_TYPES from CMAKE_BUILD_TYPE The other direction is already linked. --- Help/variable/CMAKE_BUILD_TYPE.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst index 405f7d5901c..dd892fa4ad2 100644 --- a/Help/variable/CMAKE_BUILD_TYPE.rst +++ b/Help/variable/CMAKE_BUILD_TYPE.rst @@ -23,3 +23,6 @@ Note that configuration names are case-insensitive. The value of this variable will be the same as it is specified when invoking CMake. For instance, if ``-DCMAKE_BUILD_TYPE=ReLeAsE`` is specified, then the value of ``CMAKE_BUILD_TYPE`` will be ``ReLeAsE``. + +See :variable:`CMAKE_CONFIGURATION_TYPES` for specifying the configuration +with multi-config generators. From 6986a382a912f4b982f4b20a6e04ff1d773ef1eb Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 13:55:26 -0400 Subject: [PATCH 0807/1519] Help: Document when CMAKE_BUILD_TYPE and CMAKE_CONFIGURATION_TYPES are set Fixes: #19247 --- Help/variable/CMAKE_BUILD_TYPE.rst | 5 +++++ Help/variable/CMAKE_CONFIGURATION_TYPES.rst | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst index dd892fa4ad2..b29678a7902 100644 --- a/Help/variable/CMAKE_BUILD_TYPE.rst +++ b/Help/variable/CMAKE_BUILD_TYPE.rst @@ -24,5 +24,10 @@ variable will be the same as it is specified when invoking CMake. For instance, if ``-DCMAKE_BUILD_TYPE=ReLeAsE`` is specified, then the value of ``CMAKE_BUILD_TYPE`` will be ``ReLeAsE``. +This variable is initialized by the first :command:`project` or +:command:`enable_language` command called in a project when a new build +tree is first created. A toolchain-specific default is chosen when a +language is enabled. + See :variable:`CMAKE_CONFIGURATION_TYPES` for specifying the configuration with multi-config generators. diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst index 8fcc798696c..15fea4b6a34 100644 --- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst +++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst @@ -8,5 +8,9 @@ such as ``Debug``, ``Release``, ``RelWithDebInfo`` etc. This has reasonable defaults on most platforms, but can be extended to provide other build types. +This variable is initialized by the first :command:`project` or +:command:`enable_language` command called in a project when a new build +tree is first created. The default value is generator-specific. + See :variable:`CMAKE_BUILD_TYPE` for specifying the configuration with single-config generators. From e216b9bbd331e77e59634690a2be98f087acaf2c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 13:34:28 -0400 Subject: [PATCH 0808/1519] cmake: Allow CMAKE_BUILD_TYPE to be set by environment variable When no `CMAKE_BUILD_TYPE` is explicitly specified while creating a new build tree, check for an environment variable of the same name. Issue: #20983 --- Help/envvar/CMAKE_BUILD_TYPE.rst | 10 ++++++++++ Help/manual/cmake-env-variables.7.rst | 1 + Help/release/dev/env-init-configs.rst | 5 +++++ Help/variable/CMAKE_BUILD_TYPE.rst | 5 +++-- Source/cmGlobalGenerator.cxx | 12 ++++++++++++ Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt | 2 ++ Tests/RunCMake/CommandLine/EnvBuildType.cmake | 2 ++ .../CommandLine/EnvBuildTypeIgnore-stdout.txt | 2 ++ Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake | 1 + Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 11 +++++++++++ 10 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 Help/envvar/CMAKE_BUILD_TYPE.rst create mode 100644 Help/release/dev/env-init-configs.rst create mode 100644 Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvBuildType.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake diff --git a/Help/envvar/CMAKE_BUILD_TYPE.rst b/Help/envvar/CMAKE_BUILD_TYPE.rst new file mode 100644 index 00000000000..f798aff1fa4 --- /dev/null +++ b/Help/envvar/CMAKE_BUILD_TYPE.rst @@ -0,0 +1,10 @@ +CMAKE_BUILD_TYPE +---------------- + +.. versionadded:: 3.22 + +.. include:: ENV_VAR.txt + +The ``CMAKE_BUILD_TYPE`` environment variable specifies a default value +for the :variable:`CMAKE_BUILD_TYPE` variable when there is no explicit +configuration given on the first run while creating a new build tree. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index fa38588a855..ab974a071f5 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -30,6 +30,7 @@ Environment Variables that Control the Build /envvar/CMAKE_APPLE_SILICON_PROCESSOR /envvar/CMAKE_BUILD_PARALLEL_LEVEL + /envvar/CMAKE_BUILD_TYPE /envvar/CMAKE_CONFIG_TYPE /envvar/CMAKE_EXPORT_COMPILE_COMMANDS /envvar/CMAKE_GENERATOR diff --git a/Help/release/dev/env-init-configs.rst b/Help/release/dev/env-init-configs.rst new file mode 100644 index 00000000000..fe334b74ed0 --- /dev/null +++ b/Help/release/dev/env-init-configs.rst @@ -0,0 +1,5 @@ +env-init-configs +---------------- + +* The :envvar:`CMAKE_BUILD_TYPE` environment variable was added to + provide a default value for the :variable:`CMAKE_BUILD_TYPE` variable. diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst index b29678a7902..9ad1481e4ba 100644 --- a/Help/variable/CMAKE_BUILD_TYPE.rst +++ b/Help/variable/CMAKE_BUILD_TYPE.rst @@ -26,8 +26,9 @@ value of ``CMAKE_BUILD_TYPE`` will be ``ReLeAsE``. This variable is initialized by the first :command:`project` or :command:`enable_language` command called in a project when a new build -tree is first created. A toolchain-specific default is chosen when a -language is enabled. +tree is first created. If the :envvar:`CMAKE_BUILD_TYPE` environment +variable is set, its value is used. Otherwise, a toolchain-specific +default is chosen when a language is enabled. See :variable:`CMAKE_CONFIGURATION_TYPES` for specifying the configuration with multi-config generators. diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 91937781243..cad7855aa83 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -498,6 +498,18 @@ bool cmGlobalGenerator::CheckLanguages( void cmGlobalGenerator::EnableLanguage( std::vector<std::string> const& languages, cmMakefile* mf, bool optional) { + if (!this->IsMultiConfig()) { + std::string envBuildType; + if (!mf->GetDefinition("CMAKE_BUILD_TYPE") && + cmSystemTools::GetEnv("CMAKE_BUILD_TYPE", envBuildType)) { + mf->AddCacheDefinition( + "CMAKE_BUILD_TYPE", envBuildType, + "Choose the type of build. Options include: empty, " + "Debug, Release, RelWithDebInfo, MinSizeRel.", + cmStateEnums::STRING); + } + } + if (languages.empty()) { cmSystemTools::Error("EnableLanguage must have a lang specified!"); cmSystemTools::SetFatalErrorOccured(); diff --git a/Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt b/Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt new file mode 100644 index 00000000000..03b92a75c16 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt @@ -0,0 +1,2 @@ +-- ENV{CMAKE_BUILD_TYPE}='BuildTypeEnv' +-- CMAKE_BUILD_TYPE='BuildTypeEnv' diff --git a/Tests/RunCMake/CommandLine/EnvBuildType.cmake b/Tests/RunCMake/CommandLine/EnvBuildType.cmake new file mode 100644 index 00000000000..e5e6d04b8b5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvBuildType.cmake @@ -0,0 +1,2 @@ +message(STATUS "ENV{CMAKE_BUILD_TYPE}='$ENV{CMAKE_BUILD_TYPE}'") +message(STATUS "CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}'") diff --git a/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt new file mode 100644 index 00000000000..4a26732991f --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt @@ -0,0 +1,2 @@ +-- ENV{CMAKE_BUILD_TYPE}='BuildTypeEnv' +-- CMAKE_BUILD_TYPE='BuildTypeOpt' diff --git a/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake new file mode 100644 index 00000000000..f21666f73c6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake @@ -0,0 +1 @@ +include(EnvBuildType.cmake) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index c58b1d06df2..e86e66344d1 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -344,6 +344,17 @@ if(RunCMake_GENERATOR MATCHES "Unix Makefiles" OR RunCMake_GENERATOR MATCHES "Ni run_EnvironmentExportCompileCommands() endif() +function(run_EnvironmentBuildType) + set(ENV{CMAKE_BUILD_TYPE} "BuildTypeEnv") + run_cmake(EnvBuildType) + run_cmake_with_options(EnvBuildTypeIgnore -DCMAKE_BUILD_TYPE=BuildTypeOpt) + unset(ENV{CMAKE_BUILD_TYPE}) +endfunction() + +if(RunCMake_GENERATOR MATCHES "Make|^Ninja$") + run_EnvironmentBuildType() +endif() + function(run_EnvironmentToolchain) set(ENV{CMAKE_TOOLCHAIN_FILE} "${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake") run_cmake(EnvToolchainAbsolute) From ef56eefc9bb9ae0ad23c80c01a3e15086dcf207e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 29 Jun 2021 16:58:16 -0400 Subject: [PATCH 0809/1519] cmake: Allow CMAKE_CONFIGURATION_TYPES to be set by environment variable When no `CMAKE_CONFIGURATION_TYPES` is explicitly specified while creating a new build tree, check for an environment variable of the same name. Issue: #20983 --- Help/envvar/CMAKE_CONFIGURATION_TYPES.rst | 11 +++++++++++ Help/manual/cmake-env-variables.7.rst | 1 + Help/release/dev/env-init-configs.rst | 4 ++++ Help/variable/CMAKE_CONFIGURATION_TYPES.rst | 4 +++- Source/cmMakefile.cxx | 6 +++++- Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt | 2 ++ Tests/RunCMake/CommandLine/EnvConfigTypes.cmake | 2 ++ .../CommandLine/EnvConfigTypesIgnore-stdout.txt | 2 ++ Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake | 1 + Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 9 +++++++++ 10 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 Help/envvar/CMAKE_CONFIGURATION_TYPES.rst create mode 100644 Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvConfigTypes.cmake create mode 100644 Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt create mode 100644 Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake diff --git a/Help/envvar/CMAKE_CONFIGURATION_TYPES.rst b/Help/envvar/CMAKE_CONFIGURATION_TYPES.rst new file mode 100644 index 00000000000..833aa4a9fd1 --- /dev/null +++ b/Help/envvar/CMAKE_CONFIGURATION_TYPES.rst @@ -0,0 +1,11 @@ +CMAKE_CONFIGURATION_TYPES +------------------------- + +.. versionadded:: 3.22 + +.. include:: ENV_VAR.txt + +The ``CMAKE_CONFIGURATION_TYPES`` environment variable specifies a +default value for the :variable:`CMAKE_CONFIGURATION_TYPES` variable +when there is no explicit configuration given on the first run while +creating a new build tree. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index ab974a071f5..3db189efffd 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -31,6 +31,7 @@ Environment Variables that Control the Build /envvar/CMAKE_APPLE_SILICON_PROCESSOR /envvar/CMAKE_BUILD_PARALLEL_LEVEL /envvar/CMAKE_BUILD_TYPE + /envvar/CMAKE_CONFIGURATION_TYPES /envvar/CMAKE_CONFIG_TYPE /envvar/CMAKE_EXPORT_COMPILE_COMMANDS /envvar/CMAKE_GENERATOR diff --git a/Help/release/dev/env-init-configs.rst b/Help/release/dev/env-init-configs.rst index fe334b74ed0..5c9892d9f8f 100644 --- a/Help/release/dev/env-init-configs.rst +++ b/Help/release/dev/env-init-configs.rst @@ -3,3 +3,7 @@ env-init-configs * The :envvar:`CMAKE_BUILD_TYPE` environment variable was added to provide a default value for the :variable:`CMAKE_BUILD_TYPE` variable. + +* The :envvar:`CMAKE_CONFIGURATION_TYPES` environment variable was added to + provide a default value for the :variable:`CMAKE_CONFIGURATION_TYPES` + variable. diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst index 15fea4b6a34..5298a725308 100644 --- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst +++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst @@ -10,7 +10,9 @@ types. This variable is initialized by the first :command:`project` or :command:`enable_language` command called in a project when a new build -tree is first created. The default value is generator-specific. +tree is first created. If the :envvar:`CMAKE_CONFIGURATION_TYPES` +environment variable is set, its value is used. Otherwise, the default +value is generator-specific. See :variable:`CMAKE_BUILD_TYPE` for specifying the configuration with single-config generators. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 120cae72399..3c4e9cd423d 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3187,8 +3187,12 @@ void cmMakefile::InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault) if (this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { return; } + std::string initConfigs; + if (!cmSystemTools::GetEnv("CMAKE_CONFIGURATION_TYPES", initConfigs)) { + initConfigs = genDefault; + } this->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", genDefault, + "CMAKE_CONFIGURATION_TYPES", initConfigs, "Semicolon separated list of supported configuration types, " "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " "anything else will be ignored.", diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt b/Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt new file mode 100644 index 00000000000..bfec18f9da7 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt @@ -0,0 +1,2 @@ +-- ENV{CMAKE_CONFIGURATION_TYPES}='ConfigTypesEnv' +-- CMAKE_CONFIGURATION_TYPES='ConfigTypesEnv' diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypes.cmake b/Tests/RunCMake/CommandLine/EnvConfigTypes.cmake new file mode 100644 index 00000000000..8c9b63a9a7d --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvConfigTypes.cmake @@ -0,0 +1,2 @@ +message(STATUS "ENV{CMAKE_CONFIGURATION_TYPES}='$ENV{CMAKE_CONFIGURATION_TYPES}'") +message(STATUS "CMAKE_CONFIGURATION_TYPES='${CMAKE_CONFIGURATION_TYPES}'") diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt new file mode 100644 index 00000000000..7800a4f0d19 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt @@ -0,0 +1,2 @@ +-- ENV{CMAKE_CONFIGURATION_TYPES}='ConfigTypesEnv' +-- CMAKE_CONFIGURATION_TYPES='ConfigTypesOpt' diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake new file mode 100644 index 00000000000..fcbbaea55b1 --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake @@ -0,0 +1 @@ +include(EnvConfigTypes.cmake) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index e86e66344d1..0b26b890124 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -351,8 +351,17 @@ function(run_EnvironmentBuildType) unset(ENV{CMAKE_BUILD_TYPE}) endfunction() +function(run_EnvironmentConfigTypes) + set(ENV{CMAKE_CONFIGURATION_TYPES} "ConfigTypesEnv") + run_cmake(EnvConfigTypes) + run_cmake_with_options(EnvConfigTypesIgnore -DCMAKE_CONFIGURATION_TYPES=ConfigTypesOpt) + unset(ENV{CMAKE_CONFIGURATION_TYPES}) +endfunction() + if(RunCMake_GENERATOR MATCHES "Make|^Ninja$") run_EnvironmentBuildType() +elseif(RunCMake_GENERATOR MATCHES "Ninja Multi-Config|Visual Studio|Xcode") + run_EnvironmentConfigTypes() endif() function(run_EnvironmentToolchain) From 722270ff502522ed88b14a48263f335939b0acac Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Sat, 1 May 2021 14:03:41 -0400 Subject: [PATCH 0810/1519] ci: update to 3.21.0-rc2 for CI usage This version includes JUnit support in CTest. --- .gitlab/ci/cmake.ps1 | 6 +++--- .gitlab/ci/cmake.sh | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.gitlab/ci/cmake.ps1 b/.gitlab/ci/cmake.ps1 index 3d6fb81ed57..a16fe459baf 100755 --- a/.gitlab/ci/cmake.ps1 +++ b/.gitlab/ci/cmake.ps1 @@ -1,8 +1,8 @@ $erroractionpreference = "stop" -$version = "3.19.7" -$sha256sum = "E6788D6E23B3026C37FCFA7658075D6B5F9113F26FAE17FE372AD4A7EE62D5FD" -$filename = "cmake-$version-win64-x64" +$version = "3.21.0-rc2" +$sha256sum = "AF88454243BCBAF9F537458562D669DAF0DBEDA8C0FD82C1D93BC2B4285AE4C7" +$filename = "cmake-$version-windows-x86_64" $tarball = "$filename.zip" $outdir = $pwd.Path diff --git a/.gitlab/ci/cmake.sh b/.gitlab/ci/cmake.sh index e02eb8a33e6..ff59d2867bc 100755 --- a/.gitlab/ci/cmake.sh +++ b/.gitlab/ci/cmake.sh @@ -2,22 +2,22 @@ set -e -readonly version="3.19.3" +readonly version="3.21.0-rc2" case "$(uname -s)-$(uname -m)" in Linux-x86_64) shatool="sha256sum" - sha256sum="c18b65697e9679e5c88dccede08c323cd3d3730648e59048047bba82097e0ffc" - platform="Linux-x86_64" + sha256sum="31d4f5f4bb8793127eb441c8311fd4baad4d2a86c26fd37b43d4ef23887c332e" + platform="linux-x86_64" ;; Linux-aarch64) shatool="sha256sum" - sha256sum="66e507c97ffb586d7ca6567890808b792c8eb004b645706df6fbf27826a395a2" - platform="Linux-aarch64" + sha256sum="437565f32e3f28fd8322f96a5472b196825eaf5ef6139e1c383afe624decc476" + platform="linux-aarch64" ;; Darwin-*) shatool="shasum -a 256" - sha256sum="a6b79ad05f89241a05797510e650354d74ff72cc988981cdd1eb2b3b2bda66ac" + sha256sum="5ab0ee4edb45de33080f571cf69300b2abd92dc02a9c624b3c289a4a14cab160" platform="macos-universal" ;; *) From cb5c03ed04488d9976f0afaee59e901050c82c82 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Sat, 1 May 2021 14:05:18 -0400 Subject: [PATCH 0811/1519] gitlab-ci: upload JUnit reports for builds GitLab can render test results which come from JUnit files and inform which tests have started failing on an MR. --- .gitlab-ci.yml | 8 ++++++++ .gitlab/artifacts.yml | 11 +++++++++++ .gitlab/ci/ctest_test.cmake | 1 + .gitlab/ci/ctest_test_external.cmake | 1 + 4 files changed, 21 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bbed2e2003d..2ead13b08dd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -163,6 +163,7 @@ test:debian10-ninja: - .debian10_ninja - .cmake_test_linux_release - .linux_builder_tags_qt + - .cmake_junit_artifacts - .run_dependent - .needs_centos6_x86_64 @@ -171,6 +172,7 @@ test:debian10-aarch64-ninja: - .debian10_aarch64_ninja - .cmake_test_linux_release - .linux_builder_tags_aarch64_qt + - .cmake_junit_artifacts - .run_dependent - .needs_centos7_aarch64 variables: @@ -209,6 +211,7 @@ test:fedora34-makefiles-nospace: - .fedora34_makefiles - .cmake_test_linux_release - .linux_builder_tags_qt + - .cmake_junit_artifacts - .run_dependent - .needs_centos6_x86_64 variables: @@ -221,6 +224,7 @@ test:cuda10.2-nvidia: - .cuda10.2_nvidia - .cmake_test_linux_release - .linux_builder_tags_cuda + - .cmake_junit_artifacts - .run_dependent - .needs_centos6_x86_64 @@ -259,6 +263,7 @@ test:fedora34-ninja-multi: - .fedora34_ninja_multi - .cmake_test_linux_external - .linux_builder_tags_qt + - .cmake_junit_artifacts - .run_dependent dependencies: - test:fedora34-ninja @@ -625,6 +630,7 @@ test:macos-x86_64-xcode: - .macos_x86_64_xcode - .cmake_test_macos_external - .macos_x86_64_builder_ext_tags + - .cmake_junit_artifacts - .run_dependent dependencies: - test:macos-x86_64-ninja @@ -636,6 +642,7 @@ test:macos-arm64-xcode: - .macos_arm64_xcode - .cmake_test_macos_external - .macos_arm64_builder_ext_tags + - .cmake_junit_artifacts - .run_dependent dependencies: - test:macos-arm64-ninja @@ -717,6 +724,7 @@ test:windows-vs2019-x64: - .windows_vs2019_x64 - .cmake_test_windows_external - .windows_builder_ext_tags + - .cmake_junit_artifacts - .run_dependent dependencies: - test:windows-vs2019-x64-ninja diff --git a/.gitlab/artifacts.yml b/.gitlab/artifacts.yml index edd313f5aa9..45e4c5b526d 100644 --- a/.gitlab/artifacts.yml +++ b/.gitlab/artifacts.yml @@ -82,11 +82,22 @@ - build/cmake-*.tar.gz - build/cmake-*.zip +.cmake_junit_artifacts: + artifacts: + expire_in: 1d + when: always + reports: + junit: + - build/junit.xml + .cmake_test_artifacts: artifacts: expire_in: 1d # External testing can be useful even if test jobs fail. when: always + reports: + junit: + - build/junit.xml paths: # Take the install tree. - build/install/ diff --git a/.gitlab/ci/ctest_test.cmake b/.gitlab/ci/ctest_test.cmake index facf9ba4ba1..b02d032fa50 100644 --- a/.gitlab/ci/ctest_test.cmake +++ b/.gitlab/ci/ctest_test.cmake @@ -20,6 +20,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/ctest_exclusions.cmake") ctest_test( PARALLEL_LEVEL "${nproc}" TEST_LOAD "${nproc}" + OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml" RETURN_VALUE test_result EXCLUDE "${test_exclusions}") ctest_submit(PARTS Test) diff --git a/.gitlab/ci/ctest_test_external.cmake b/.gitlab/ci/ctest_test_external.cmake index 6576c263291..48e910b9966 100644 --- a/.gitlab/ci/ctest_test_external.cmake +++ b/.gitlab/ci/ctest_test_external.cmake @@ -74,6 +74,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/ctest_exclusions.cmake") ctest_test( PARALLEL_LEVEL "${nproc}" TEST_LOAD "${nproc}" + OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml" RETURN_VALUE test_result ${ctest_label_args} EXCLUDE "${test_exclusions}") From 8cce0ad32fba98dc3e3f6cdd952d07a955479357 Mon Sep 17 00:00:00 2001 From: Chuck Atkins <chuck.atkins@kitware.com> Date: Wed, 30 Jun 2021 16:51:06 -0400 Subject: [PATCH 0812/1519] FindMPI: Fix missing static warning in the mpi test source --- Modules/FindMPI/test_mpi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Modules/FindMPI/test_mpi.c b/Modules/FindMPI/test_mpi.c index 7c96d54a8ff..70d7e1d3e01 100644 --- a/Modules/FindMPI/test_mpi.c +++ b/Modules/FindMPI/test_mpi.c @@ -7,15 +7,15 @@ #endif #if defined(MPI_VERSION) && defined(MPI_SUBVERSION) -const char mpiver_str[] = { 'I', 'N', - 'F', 'O', - ':', 'M', - 'P', 'I', - '-', 'V', - 'E', 'R', - '[', ('0' + MPI_VERSION), - '.', ('0' + MPI_SUBVERSION), - ']', '\0' }; +const static char mpiver_str[] = { 'I', 'N', + 'F', 'O', + ':', 'M', + 'P', 'I', + '-', 'V', + 'E', 'R', + '[', ('0' + MPI_VERSION), + '.', ('0' + MPI_SUBVERSION), + ']', '\0' }; #endif int main(int argc, char* argv[]) From 5333ee1de4f93996d23fc8f1ae4ba87ad632bc51 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 1 Jul 2021 00:01:13 -0400 Subject: [PATCH 0813/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 245217a5b9a..b4937dd13dd 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210630) +set(CMake_VERSION_PATCH 20210701) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From af11ea8d0c70d79282812bab58de795a86cecc56 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann <joerg.bornemann@qt.io> Date: Wed, 30 Jun 2021 12:18:21 +0200 Subject: [PATCH 0814/1519] AutoGen: Fix needless compilation of mocs_compilation.cpp For an AUTOMOC'ed target foo, when depfiles are used, there are the following dependencies: foo_autogen -> foo_autogen/timestamp foo_autogen/mocs_compilation.cpp -> foo_autogen/timestamp The first is used to trigger AUTOGEN. The second erroneously triggers a recompilation of mocs_compilation.cpp when any source file of target foo is touched. Remove the latter dependency and replace it with an order-only dependency from foo_autogen/mocs_compilation.cpp to foo_autogen_timestamp_deps. That is achieved by making mocs_compilation.cpp or its per-configuration variants byproduct(s) of the timestamp file. Fixes: #22338 --- Source/cmQtAutoGenInitializer.cxx | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 2894201c9b3..4dd78e514f5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1111,11 +1111,30 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Register info file as generated by CMake this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile); + // Determine whether to use a depfile for the AUTOGEN target. + const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && + this->GlobalGen->GetName().find("Ninja") != std::string::npos; + // Files provided by the autogen target std::vector<std::string> autogenByproducts; + std::vector<std::string> timestampByproducts; if (this->Moc.Enabled) { this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true); - autogenByproducts.push_back(this->Moc.CompilationFileGenex); + if (useNinjaDepfile) { + if (this->MultiConfig) { + // Make all mocs_compilation_<CONFIG>.cpp files byproducts of the + // ${target}_autogen/timestamp custom command. + // We cannot just use Moc.CompilationFileGenex here, because that + // custom command runs cmake_autogen for each configuration. + for (const auto& p : this->Moc.CompilationFile.Config) { + timestampByproducts.push_back(p.second); + } + } else { + timestampByproducts.push_back(this->Moc.CompilationFileGenex); + } + } else { + autogenByproducts.push_back(this->Moc.CompilationFileGenex); + } } if (this->Uic.Enabled) { @@ -1265,8 +1284,6 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->AutogenTarget.DependFiles.begin(), this->AutogenTarget.DependFiles.end()); - const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && - this->GlobalGen->GetName().find("Ninja") != std::string::npos; if (useNinjaDepfile) { // Create a custom command that generates a timestamp file and // has a depfile assigned. The depfile is created by JobDepFilesMergeT. @@ -1327,8 +1344,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->AddGeneratedSource(outputFile, this->Moc); const std::string no_main_dependency; this->LocalGen->AddCustomCommandToOutput( - outputFile, dependencies, no_main_dependency, commandLines, - autogenComment.c_str(), this->Dir.Work.c_str(), + { outputFile }, timestampByproducts, dependencies, no_main_dependency, + /*implicit_depends=*/{}, commandLines, autogenComment.c_str(), + this->Dir.Work.c_str(), /*cmp0116=*/cmPolicies::NEW, /*replace=*/false, /*escapeOldStyle=*/false, /*uses_terminal=*/false, From 7817aa6fa4097a2c642ff1333be72f93a6e32ed1 Mon Sep 17 00:00:00 2001 From: Zack Galbreath <zack.galbreath@kitware.com> Date: Wed, 23 Jun 2021 15:34:59 -0400 Subject: [PATCH 0815/1519] ctest: improve test for runtime labels Check for the whole expected output string rather than particular substrings. This verifies that newlines are stripped for any <CTestLabel> lines found in the test output. --- Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake b/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake index beb39dec1f3..eaa50d1550d 100644 --- a/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake +++ b/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake @@ -20,9 +20,6 @@ if(NOT n_matches EQUAL 1) endif() # Check test output. -if(NOT _test_contents MATCHES "before") - string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'before' in Test.xml") -endif() -if(NOT _test_contents MATCHES "after") - string(APPEND RunCMake_TEST_FAILED "Could not find expected string 'after' in Test.xml") +if(NOT _test_contents MATCHES "<Value>before\nafter\n</Value>") + string(APPEND RunCMake_TEST_FAILED "Could not find expected output in Test.xml") endif() From bf6965fbb8f01bd105ffb57e1f2c2b1fc34fe697 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 11:11:14 -0400 Subject: [PATCH 0816/1519] ci: add cuda9.2 base image --- .gitlab/ci/docker/cuda9.2/Dockerfile | 5 +++++ .gitlab/ci/docker/cuda9.2/install_deps.sh | 14 ++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .gitlab/ci/docker/cuda9.2/Dockerfile create mode 100755 .gitlab/ci/docker/cuda9.2/install_deps.sh diff --git a/.gitlab/ci/docker/cuda9.2/Dockerfile b/.gitlab/ci/docker/cuda9.2/Dockerfile new file mode 100644 index 00000000000..7eae886b53e --- /dev/null +++ b/.gitlab/ci/docker/cuda9.2/Dockerfile @@ -0,0 +1,5 @@ +FROM nvidia/cuda:9.2-devel-ubuntu16.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/cuda9.2/install_deps.sh b/.gitlab/ci/docker/cuda9.2/install_deps.sh new file mode 100755 index 00000000000..146f98255c1 --- /dev/null +++ b/.gitlab/ci/docker/cuda9.2/install_deps.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -e + +apt-get update + +# Install development tools. +apt-get install -y \ + g++ \ + clang-3.8 \ + curl \ + git + +apt-get clean From 6b0b6efc75463ebeb8b9c2681957d3ac5528b5ec Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 30 Jun 2021 11:14:12 -0400 Subject: [PATCH 0817/1519] gitlab-ci: add job testing cuda9.2 with Ninja Multi-Config --- .gitlab-ci.yml | 10 ++++++++++ .gitlab/ci/configure_cuda9.2_nvidia.cmake | 3 +++ .gitlab/ci/env_cuda9.2_nvidia.sh | 4 ++++ .gitlab/os-linux.yml | 15 +++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 .gitlab/ci/configure_cuda9.2_nvidia.cmake create mode 100644 .gitlab/ci/env_cuda9.2_nvidia.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d224088e9d0..5040700096b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -216,6 +216,16 @@ test:fedora34-makefiles-nospace: CMAKE_CI_BUILD_NAME: fedora34_makefiles_nospace CMAKE_CI_JOB_NIGHTLY: "true" +test:cuda9.2-nvidia: + extends: + - .cuda9.2_nvidia + - .cmake_test_linux_release + - .linux_builder_tags_cuda + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + test:cuda10.2-nvidia: extends: - .cuda10.2_nvidia diff --git a/.gitlab/ci/configure_cuda9.2_nvidia.cmake b/.gitlab/ci/configure_cuda9.2_nvidia.cmake new file mode 100644 index 00000000000..519699b0ccf --- /dev/null +++ b/.gitlab/ci/configure_cuda9.2_nvidia.cmake @@ -0,0 +1,3 @@ +set(CMake_TEST_CUDA "NVIDIA" CACHE STRING "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/env_cuda9.2_nvidia.sh b/.gitlab/ci/env_cuda9.2_nvidia.sh new file mode 100644 index 00000000000..16bfba4eeea --- /dev/null +++ b/.gitlab/ci/env_cuda9.2_nvidia.sh @@ -0,0 +1,4 @@ +export CC=/usr/bin/clang-3.8 +export CXX=/usr/bin/clang++-3.8 +export CUDAHOSTCXX=/usr/bin/g++-5 +export CUDACXX=/usr/local/cuda/bin/nvcc diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 8ce795e89c3..cd1195bb5cb 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -208,6 +208,21 @@ ### CUDA builds +.cuda9.2: + image: "kitware/cmake:ci-cuda9.2-x86_64-2021-07-01" + + variables: + GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" + CMAKE_ARCH: x86_64 + CTEST_LABELS: "CUDA" + +.cuda9.2_nvidia: + extends: .cuda9.2 + + variables: + CMAKE_CONFIGURATION: cuda9.2_nvidia + CMAKE_GENERATOR: "Ninja Multi-Config" + .cuda10.2: image: "kitware/cmake:ci-cuda10.2-x86_64-2021-06-16" From 9c310ff0752913c438660a5f0ffed9f4d905a2b7 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <michael@scivision.dev> Date: Wed, 30 Jun 2021 20:02:55 -0400 Subject: [PATCH 0818/1519] Help: Note C_STANDARD values added in CMake 3.21 Issue: #22366 --- Help/prop_tgt/C_STANDARD.rst | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Help/prop_tgt/C_STANDARD.rst b/Help/prop_tgt/C_STANDARD.rst index e22b775d13e..ecba2a8f1f1 100644 --- a/Help/prop_tgt/C_STANDARD.rst +++ b/Help/prop_tgt/C_STANDARD.rst @@ -11,7 +11,26 @@ flag such as ``-std=gnu11`` to the compile line. For compilers that have no notion of a C standard level, such as Microsoft Visual C++ before VS 16.7, this property has no effect. -Supported values are ``90``, ``99``, ``11``, ``17``, ``23``. +Supported values are: + +``90`` + C89/C90 + +``99`` + C99 + +``11`` + C11 + +``17`` + .. versionadded:: 3.21 + + C17 + +``23`` + .. versionadded:: 3.21 + + C23 If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This From d9301458417acefc4f325796b3672b5039171961 Mon Sep 17 00:00:00 2001 From: Dan Ibanez <daibane@sandia.gov> Date: Tue, 29 Jun 2021 20:38:03 -0600 Subject: [PATCH 0819/1519] FindCUDATookit: Fix ordering of libraries in imported targets Before this a downstream code linking to `CUDA::cusparse_static` and `CUDA::curand_static` would get a link line with `libcusparse_static.a`, then `libculibos.a`, then `libcurand_static.a`. Use `IMPORTED_LOCATION` to tell CMake about the proper dependency ordering where `libculibos.a` comes last, because the other two libraries depend on `libculibos.a`. Fixes: #22365 --- Modules/FindCUDAToolkit.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 8801cb1bff2..4c535b9f244 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -844,9 +844,9 @@ if(CUDAToolkit_FOUND) mark_as_advanced(CUDA_${lib_name}_LIBRARY) if (NOT TARGET CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY) - add_library(CUDA::${lib_name} IMPORTED INTERFACE) + add_library(CUDA::${lib_name} UNKNOWN IMPORTED) target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}") - target_link_libraries(CUDA::${lib_name} INTERFACE "${CUDA_${lib_name}_LIBRARY}") + set_property(TARGET CUDA::${lib_name} PROPERTY IMPORTED_LOCATION "${CUDA_${lib_name}_LIBRARY}") foreach(dep ${arg_DEPS}) if(TARGET CUDA::${dep}) target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dep}) From e93245ec64bec6e5f63388e4b4714c7a9d3cbf51 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 1 Jul 2021 12:56:17 -0400 Subject: [PATCH 0820/1519] DetermineCompiler: Restore identification of MSVC with no INCLUDE or LIB Update the change from commit c6aaaf066a (DetermineCompiler: Restore identification of MSVC with no INCLUDE dirs, 2021-06-29, v3.21.0-rc2~6^2) to also work with no `LIB` dirs. Add the `-c` flag to compile an object file without linking. --- Modules/CMakeDetermineCCompiler.cmake | 3 ++- Modules/CMakeDetermineCXXCompiler.cmake | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index ca497f1f909..0f80f9cffc1 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -88,7 +88,8 @@ else() # MSVC needs at least one include directory for __has_include to function, # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags. - "-I__does_not_exist__" + # Also avoid linking so this works with no LIB env var. + "-c -I__does_not_exist__" ) endif() if(CMAKE_C_COMPILER_TARGET) diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index e297f90b756..556518f496f 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -83,7 +83,8 @@ else() # MSVC needs at least one include directory for __has_include to function, # but custom toolchains may run MSVC with no INCLUDE env var and no -I flags. - "-I__does_not_exist__" + # Also avoid linking so this works with no LIB env var. + "-c -I__does_not_exist__" ) endif() From 5489ce74b349ed31d6abb6ee5a0aaa17b10b474d Mon Sep 17 00:00:00 2001 From: Zack Galbreath <zack.galbreath@kitware.com> Date: Thu, 1 Jul 2021 12:40:41 -0400 Subject: [PATCH 0821/1519] ctest: support <CTestMeasurement> for runtime measurements Teach CTest to parse output for <CTestMeasurement> in addition to <DartMeasurement> for measurements defined at runtime. Use a new class (cmCTestTestMeasurementXMLParser) derived from cmXMLParser to parse the data and attributes these XML elements. This is an improvement over our previous approach of using a series of regular expressions. As part of this commit we also rename some member variables and methods to make their purpose more clear. DartStuff -> AllTestMeasurementsRegex DartStuff1 -> SingleTestMeasurementRegex DartString -> TestMeasurementsOutput GenerateDartOutput() -> GenerateCTestXML() GenerateRegressionImages() -> RecordCustomTestMeasurements() cmCTestRunTest::DartProcessing() -> ParseOutputForMeasurements() --- Help/command/ctest_test.rst | 30 +-- Source/CMakeLists.txt | 1 + Source/CTest/cmCTestMemCheckHandler.cxx | 2 +- Source/CTest/cmCTestMemCheckHandler.h | 4 +- Source/CTest/cmCTestRunTest.cxx | 20 +- Source/CTest/cmCTestRunTest.h | 2 +- Source/CTest/cmCTestTestHandler.cxx | 192 +++++------------- Source/CTest/cmCTestTestHandler.h | 12 +- .../CTest/cmCTestTestMeasurementXMLParser.cxx | 26 +++ .../CTest/cmCTestTestMeasurementXMLParser.h | 21 ++ Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 12 ++ .../ctest_test/TestMeasurements-check.cmake | 18 ++ 12 files changed, 171 insertions(+), 169 deletions(-) create mode 100644 Source/CTest/cmCTestTestMeasurementXMLParser.cxx create mode 100644 Source/CTest/cmCTestTestMeasurementXMLParser.h diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 03ec1a4b089..caac6057b1f 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -186,29 +186,33 @@ Check the `CDash test measurement documentation <https://github.com/Kitware/CDash/blob/master/docs/test_measurements.md>`_ for more information on the types of test measurements that CDash recognizes. +Starting in version 3.22, CTest can parse custom measurements from tags named +``<CTestMeasurement>`` or ``<CTestMeasurementFile>``. The older names +``<DartMeasurement>`` and ``<DartMeasurementFile>`` are still supported. + The following example demonstrates how to output a variety of custom test measurements. .. code-block:: c++ std::cout << - "<DartMeasurement type=\"numeric/double\" name=\"score\">28.3</DartMeasurement>" + "<CTestMeasurement type=\"numeric/double\" name=\"score\">28.3</CTestMeasurement>" << std::endl; std::cout << - "<DartMeasurement type=\"text/string\" name=\"color\">red</DartMeasurement>" + "<CTestMeasurement type=\"text/string\" name=\"color\">red</CTestMeasurement>" << std::endl; std::cout << - "<DartMeasurement type=\"text/link\" name=\"CMake URL\">https://cmake.org</DartMeasurement>" + "<CTestMeasurement type=\"text/link\" name=\"CMake URL\">https://cmake.org</CTestMeasurement>" << std::endl; std::cout << - "<DartMeasurement type=\"text/preformatted\" name=\"Console Output\">" << + "<CTestMeasurement type=\"text/preformatted\" name=\"Console Output\">" << "line 1.\n" << " \033[31;1m line 2. Bold red, and indented!\033[0;0ml\n" << "line 3. Not bold or indented...\n" << - "</DartMeasurement>" << std::endl; + "</CTestMeasurement>" << std::endl; Image Measurements """""""""""""""""" @@ -218,16 +222,16 @@ The following example demonstrates how to upload test images to CDash. .. code-block:: c++ std::cout << - "<DartMeasurementFile type=\"image/jpg\" name=\"TestImage\">" << - "/dir/to/test_img.jpg</DartMeasurementFile>" << std::endl; + "<CTestMeasurementFile type=\"image/jpg\" name=\"TestImage\">" << + "/dir/to/test_img.jpg</CTestMeasurementFile>" << std::endl; std::cout << - "<DartMeasurementFile type=\"image/gif\" name=\"ValidImage\">" << - "/dir/to/valid_img.gif</DartMeasurementFile>" << std::endl; + "<CTestMeasurementFile type=\"image/gif\" name=\"ValidImage\">" << + "/dir/to/valid_img.gif</CTestMeasurementFile>" << std::endl; std::cout << - "<DartMeasurementFile type=\"image/png\" name=\"AlgoResult\"> << - "/dir/to/img.png</DartMeasurementFile>" + "<CTestMeasurementFile type=\"image/png\" name=\"AlgoResult\"> << + "/dir/to/img.png</CTestMeasurementFile>" << std::endl; Images will be displayed together in an interactive comparison mode on CDash @@ -253,8 +257,8 @@ The following example demonstrates how to upload non-image files to CDash. .. code-block:: c++ std::cout << - "<DartMeasurementFile type=\"file\" name=\"MyTestInputData\">" << - "/dir/to/data.csv</DartMeasurementFile>" << std::endl; + "<CTestMeasurementFile type=\"file\" name=\"MyTestInputData\">" << + "/dir/to/data.csv</CTestMeasurementFile>" << std::endl; If the name of the file to upload is known at configure time, you can use the :prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6446b047b21..d8ba784bac6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -960,6 +960,7 @@ set(CTEST_SRCS cmCTest.cxx CTest/cmCTestSubmitHandler.cxx CTest/cmCTestTestCommand.cxx CTest/cmCTestTestHandler.cxx + CTest/cmCTestTestMeasurementXMLParser.cxx CTest/cmCTestUpdateCommand.cxx CTest/cmCTestUpdateHandler.cxx CTest/cmCTestUploadCommand.cxx diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 125d0034d31..6bb8e79c16a 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -305,7 +305,7 @@ int cmCTestMemCheckHandler::GetDefectCount() const return this->DefectCount; } -void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) +void cmCTestMemCheckHandler::GenerateCTestXML(cmXMLWriter& xml) { if (!this->CTest->GetProduceXML()) { return; diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index b200c4394e3..a63a24df15b 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -119,9 +119,9 @@ class cmCTestMemCheckHandler : public cmCTestTestHandler bool InitializeMemoryChecking(); /** - * Generate the Dart compatible output + * Generate CTest DynamicAnalysis.xml files */ - void GenerateDartOutput(cmXMLWriter& xml) override; + void GenerateCTestXML(cmXMLWriter& xml) override; std::vector<std::string> CustomPreMemCheck; std::vector<std::string> CustomPostMemCheck; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 50072c5fa98..4e9b0f049b1 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -262,7 +262,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) *this->TestHandler->LogFile << "Test time = " << buf << std::endl; } - this->DartProcessing(); + this->ParseOutputForMeasurements(); // if this is doing MemCheck then all the output needs to be put into // Output since that is what is parsed by cmCTestMemCheckHandler @@ -698,18 +698,22 @@ void cmCTestRunTest::ComputeArguments() } } -void cmCTestRunTest::DartProcessing() +void cmCTestRunTest::ParseOutputForMeasurements() { if (!this->ProcessOutput.empty() && - this->ProcessOutput.find("<DartMeasurement") != std::string::npos) { - if (this->TestHandler->DartStuff.find(this->ProcessOutput)) { - this->TestResult.DartString = this->TestHandler->DartStuff.match(1); + (this->ProcessOutput.find("<DartMeasurement") != std::string::npos || + this->ProcessOutput.find("<CTestMeasurement") != std::string::npos)) { + if (this->TestHandler->AllTestMeasurementsRegex.find( + this->ProcessOutput)) { + this->TestResult.TestMeasurementsOutput = + this->TestHandler->AllTestMeasurementsRegex.match(1); // keep searching and replacing until none are left - while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) { + while (this->TestHandler->SingleTestMeasurementRegex.find( + this->ProcessOutput)) { // replace the exact match for the string cmSystemTools::ReplaceString( - this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(), - ""); + this->ProcessOutput, + this->TestHandler->SingleTestMeasurementRegex.match(1).c_str(), ""); } } } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 863ac1bfdf1..a4981c3b286 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -109,7 +109,7 @@ class cmCTestRunTest private: bool NeedsToRepeat(); - void DartProcessing(); + void ParseOutputForMeasurements(); void ExeNotFound(std::string exe); bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout, std::vector<std::string>* environment, diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index aeaf696d1a6..72b86c168d2 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -32,6 +32,7 @@ #include "cmCTest.h" #include "cmCTestMultiProcessHandler.h" #include "cmCTestResourceGroupsLexerHelper.h" +#include "cmCTestTestMeasurementXMLParser.h" #include "cmDuration.h" #include "cmExecutionStatus.h" #include "cmGeneratedFileStream.h" @@ -303,16 +304,23 @@ cmCTestTestHandler::cmCTestTestHandler() // Support for JUnit XML output. this->JUnitXMLFileName = ""; - // regex to detect <DartMeasurement>...</DartMeasurement> - this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)"); - // regex to detect each individual <DartMeasurement>...</DartMeasurement> - this->DartStuff1.compile( - "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)"); + // Regular expressions to scan test output for custom measurements. - // regex to detect <CTestDetails>...</CTestDetails> + // Capture the whole section of test output from the first opening + // <(CTest|Dart)Measurement*> tag to the last </(CTest|Dart)Measurement*> + // closing tag. + this->AllTestMeasurementsRegex.compile( + "(<(CTest|Dart)Measurement.*/(CTest|Dart)Measurement[a-zA-Z]*>)"); + + // Capture a single <(CTest|Dart)Measurement*> XML element. + this->SingleTestMeasurementRegex.compile( + "(<(CTest|Dart)Measurement[^<]*</(CTest|Dart)Measurement[a-zA-Z]*>)"); + + // Capture content from <CTestDetails>...</CTestDetails> this->CustomCompletionStatusRegex.compile( "<CTestDetails>(.*)</CTestDetails>"); - // regex to detect <CTestLabel>...</CTestLabel> + + // Capture content from <CTestLabel>...</CTestLabel> this->CustomLabelRegex.compile("<CTestLabel>(.*)</CTestLabel>"); } @@ -694,7 +702,7 @@ bool cmCTestTestHandler::GenerateXML() return false; } cmXMLWriter xml(xmlfile); - this->GenerateDartOutput(xml); + this->GenerateCTestXML(xml); } return true; @@ -1402,7 +1410,7 @@ void cmCTestTestHandler::GenerateTestCommand( { } -void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) +void cmCTestTestHandler::GenerateCTestXML(cmXMLWriter& xml) { if (!this->CTest->GetProduceXML()) { return; @@ -1438,7 +1446,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Element("Value", result.ReturnValue); xml.EndElement(); // NamedMeasurement } - this->GenerateRegressionImages(xml, result.DartString); + this->RecordCustomTestMeasurements(xml, result.TestMeasurementsOutput); xml.StartElement("NamedMeasurement"); xml.Attribute("type", "numeric/double"); xml.Attribute("name", "Execution Time"); @@ -1978,124 +1986,48 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() } } -// Just for convenience -#define SPACE_REGEX "[ \t\r\n]" -void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, - const std::string& dart) -{ - cmsys::RegularExpression twoattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression threeattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression fourattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression cdatastart( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>" SPACE_REGEX "*<!\\[CDATA\\["); - cmsys::RegularExpression cdataend("]]>" SPACE_REGEX "*</DartMeasurement>"); - cmsys::RegularExpression measurementfile( - "<DartMeasurementFile" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurementFile>"); - - bool done = false; - std::string cxml = dart; - while (!done) { - if (twoattributes.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(twoattributes.match(1).c_str(), twoattributes.match(2)); - xml.Attribute(twoattributes.match(3).c_str(), twoattributes.match(4)); - xml.Element("Value", twoattributes.match(5)); - xml.EndElement(); - cxml.erase(twoattributes.start(), - twoattributes.end() - twoattributes.start()); - } else if (threeattributes.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(threeattributes.match(1).c_str(), - threeattributes.match(2)); - xml.Attribute(threeattributes.match(3).c_str(), - threeattributes.match(4)); - xml.Attribute(threeattributes.match(5).c_str(), - threeattributes.match(6)); - xml.Element("Value", twoattributes.match(7)); - xml.EndElement(); - cxml.erase(threeattributes.start(), - threeattributes.end() - threeattributes.start()); - } else if (fourattributes.find(cxml)) { +void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml, + std::string content) +{ + while (this->SingleTestMeasurementRegex.find(content)) { + // Extract regex match from content and parse it as an XML element. + auto measurement_str = this->SingleTestMeasurementRegex.match(1); + auto parser = cmCTestTestMeasurementXMLParser(); + parser.Parse(measurement_str.c_str()); + + if (parser.ElementName == "CTestMeasurement" || + parser.ElementName == "DartMeasurement") { xml.StartElement("NamedMeasurement"); - xml.Attribute(fourattributes.match(1).c_str(), fourattributes.match(2)); - xml.Attribute(fourattributes.match(3).c_str(), fourattributes.match(4)); - xml.Attribute(fourattributes.match(5).c_str(), fourattributes.match(6)); - xml.Attribute(fourattributes.match(7).c_str(), fourattributes.match(8)); - xml.Element("Value", twoattributes.match(9)); + xml.Attribute("type", parser.MeasurementType); + xml.Attribute("name", parser.MeasurementName); + xml.Element("Value", parser.CharacterData); xml.EndElement(); - cxml.erase(fourattributes.start(), - fourattributes.end() - fourattributes.start()); - } else if (cdatastart.find(cxml) && cdataend.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2)); - xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4)); - xml.StartElement("Value"); - xml.CData( - cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end())); - xml.EndElement(); // Value - xml.EndElement(); // NamedMeasurement - cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start()); - } else if (measurementfile.find(cxml)) { - const std::string& filename = - cmCTest::CleanString(measurementfile.match(5)); - if (cmSystemTools::FileExists(filename)) { + } else if (parser.ElementName == "CTestMeasurementFile" || + parser.ElementName == "DartMeasurementFile") { + const std::string& filename = cmCTest::CleanString(parser.CharacterData); + if (!cmSystemTools::FileExists(filename)) { + xml.StartElement("NamedMeasurement"); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("text", "text/string"); + xml.Element("Value", "File " + filename + " not found"); + xml.EndElement(); + cmCTestOptionalLog( + this->CTest, HANDLER_OUTPUT, + "File \"" << filename << "\" not found." << std::endl, this->Quiet); + } else { long len = cmSystemTools::FileLength(filename); - std::string k1 = measurementfile.match(1); - std::string v1 = measurementfile.match(2); - std::string k2 = measurementfile.match(3); - std::string v2 = measurementfile.match(4); if (len == 0) { - if (cmSystemTools::LowerCase(k1) == "type") { - v1 = "text/string"; - } - if (cmSystemTools::LowerCase(k2) == "type") { - v2 = "text/string"; - } - xml.StartElement("NamedMeasurement"); - xml.Attribute(k1.c_str(), v1); - xml.Attribute(k2.c_str(), v2); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("type", "text/string"); xml.Attribute("encoding", "none"); xml.Element("Value", "Image " + filename + " is empty"); xml.EndElement(); } else { - std::string type; - std::string name; - if (cmSystemTools::LowerCase(k1) == "type") { - type = v1; - } else if (cmSystemTools::LowerCase(k2) == "type") { - type = v2; - } - if (cmSystemTools::LowerCase(k1) == "name") { - name = v1; - } else if (cmSystemTools::LowerCase(k2) == "name") { - name = v2; - } - if (type == "file") { + if (parser.MeasurementType == "file") { // Treat this measurement like an "ATTACHED_FILE" when the type // is explicitly "file" (not an image). - this->AttachFile(xml, filename, name); + this->AttachFile(xml, filename, parser.MeasurementName); } else { cmsys::ifstream ifs(filename.c_str(), std::ios::in @@ -2112,10 +2044,8 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, encoded_buffer.get(), 1); xml.StartElement("NamedMeasurement"); - xml.Attribute(measurementfile.match(1).c_str(), - measurementfile.match(2)); - xml.Attribute(measurementfile.match(3).c_str(), - measurementfile.match(4)); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("type", parser.MeasurementType); xml.Attribute("encoding", "base64"); std::ostringstream ostr; for (size_t cc = 0; cc < rlen; cc++) { @@ -2128,25 +2058,11 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, xml.EndElement(); // NamedMeasurement } } - } else { - int idx = 4; - if (measurementfile.match(1) == "name") { - idx = 2; - } - xml.StartElement("NamedMeasurement"); - xml.Attribute("name", measurementfile.match(idx)); - xml.Attribute("text", "text/string"); - xml.Element("Value", "File " + filename + " not found"); - xml.EndElement(); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - "File \"" << filename << "\" not found." << std::endl, this->Quiet); } - cxml.erase(measurementfile.start(), - measurementfile.end() - measurementfile.start()); - } else { - done = true; } + + // Remove this element from content. + cmSystemTools::ReplaceString(content, measurement_str.c_str(), ""); } } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index cc19984eea1..1b42647f41c 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -177,7 +177,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler std::string CompletionStatus; std::string CustomCompletionStatus; std::string Output; - std::string DartString; + std::string TestMeasurementsOutput; int TestCount; cmCTestTestProperties* Properties; }; @@ -276,9 +276,9 @@ class cmCTestTestHandler : public cmCTestGenericHandler private: /** - * Generate the Dart compatible output + * Write test results in CTest's Test.xml format */ - virtual void GenerateDartOutput(cmXMLWriter& xml); + virtual void GenerateCTestXML(cmXMLWriter& xml); /** * Write test results in JUnit XML format @@ -348,8 +348,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler cmCTestResourceSpec ResourceSpec; std::string ResourceSpecFile; - void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart); - cmsys::RegularExpression DartStuff1; + void RecordCustomTestMeasurements(cmXMLWriter& xml, std::string content); void CheckLabelFilter(cmCTestTestProperties& it); void CheckLabelFilterExclude(cmCTestTestProperties& it); void CheckLabelFilterInclude(cmCTestTestProperties& it); @@ -358,7 +357,8 @@ class cmCTestTestHandler : public cmCTestGenericHandler bool UseUnion; ListOfTests TestList; size_t TotalNumberOfTests; - cmsys::RegularExpression DartStuff; + cmsys::RegularExpression AllTestMeasurementsRegex; + cmsys::RegularExpression SingleTestMeasurementRegex; cmsys::RegularExpression CustomCompletionStatusRegex; cmsys::RegularExpression CustomLabelRegex; diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.cxx b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx new file mode 100644 index 00000000000..636be2451ad --- /dev/null +++ b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx @@ -0,0 +1,26 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmCTestTestMeasurementXMLParser.h" + +#include <cstring> + +void cmCTestTestMeasurementXMLParser::StartElement(const std::string& name, + const char** attributes) +{ + this->CharacterData.clear(); + this->ElementName = name; + for (const char** attr = attributes; *attr; attr += 2) { + if (strcmp(attr[0], "name") == 0) { + this->MeasurementName = attr[1]; + } else if (strcmp(attr[0], "type") == 0) { + this->MeasurementType = attr[1]; + } + } +} + +void cmCTestTestMeasurementXMLParser::CharacterDataHandler(const char* data, + int length) +{ + this->CharacterData.append(data, length); +} diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.h b/Source/CTest/cmCTestTestMeasurementXMLParser.h new file mode 100644 index 00000000000..b2c3eb3f109 --- /dev/null +++ b/Source/CTest/cmCTestTestMeasurementXMLParser.h @@ -0,0 +1,21 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include <string> + +#include "cmXMLParser.h" + +class cmCTestTestMeasurementXMLParser : public cmXMLParser +{ +public: + cmCTestTestMeasurementXMLParser() {} + std::string CharacterData; + std::string ElementName; + std::string MeasurementName; + std::string MeasurementType; + +protected: + void StartElement(const std::string& name, const char** atts) override; + void EndElement(const std::string& /*name*/) override {} + void CharacterDataHandler(const char* data, int length) override; +}; diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index 31bc0752e55..a211c66f04b 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -157,14 +157,26 @@ add_test( NAME double_measurement COMMAND ${CMAKE_COMMAND} -E echo <DartMeasurement type="numeric/double" name="my_custom_value">1.4847</DartMeasurement>) +add_test( + NAME double_measurement2 + COMMAND ${CMAKE_COMMAND} -E + echo <CTestMeasurement type="numeric/double" name="another_custom_value">1.8474</CTestMeasurement>) add_test( NAME img_measurement COMMAND ${CMAKE_COMMAND} -E echo <DartMeasurementFile name="TestImage" type="image/png">]] ${IMAGE_DIR}/cmake-logo-16.png [[</DartMeasurementFile>) +add_test( + NAME img_measurement2 + COMMAND ${CMAKE_COMMAND} -E + echo <CTestMeasurementFile name="TestImage2" type="image/png">]] ${IMAGE_DIR}/cmake-logo-16.png [[</CTestMeasurementFile>) add_test( NAME file_measurement COMMAND ${CMAKE_COMMAND} -E echo <DartMeasurementFile name="my_test_input_data" type="file">]] ${IMAGE_DIR}/cmake-logo-16.png [[</DartMeasurementFile>) +add_test( + NAME file_measurement2 + COMMAND ${CMAKE_COMMAND} -E + echo <CTestMeasurementFile name="another_test_input_data" type="file">]] ${IMAGE_DIR}/cmake-logo-16.png [[</CTestMeasurementFile>) ]]) run_ctest(TestMeasurements) endfunction() diff --git a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake index 0095db0dec9..7e0928d5d93 100644 --- a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake +++ b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake @@ -10,13 +10,31 @@ endif() if(NOT _test_contents MATCHES "<Value>1.4847</Value>") string(APPEND RunCMake_TEST_FAILED "Could not find expected measurement value in Test.xml") endif() +# Check the other double measurement. +if(NOT _test_contents MATCHES [[NamedMeasurement type="numeric/double" name="another_custom_value"]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected <NamedMeasurement> tag(2) for type='numeric/double' in Test.xml") +endif() +if(NOT _test_contents MATCHES "<Value>1.8474</Value>") + string(APPEND RunCMake_TEST_FAILED "Could not find expected measurement value(2) in Test.xml") +endif() # Check img measurement. if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage" type="image/png" encoding="base64"]]) string(APPEND RunCMake_TEST_FAILED "Could not find expected <NamedMeasurement> tag for type='image/png' in Test.xml") endif() +# Check img measurement 2. +if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage2" type="image/png" encoding="base64"]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected <NamedMeasurement> tag(2) for type='image/png' in Test.xml") +endif() # Check file measurement. if(NOT _test_contents MATCHES [[NamedMeasurement name="my_test_input_data" encoding="base64" compression="tar/gzip" filename="cmake-logo-16.png" type="file"]]) string(APPEND RunCMake_TEST_FAILED "Could not find expected <NamedMeasurement> tag for type='file' in Test.xml") endif() +# Check file measurement 2. +if(NOT _test_contents MATCHES [[NamedMeasurement name="another_test_input_data" encoding="base64" compression="tar/gzip" filename="cmake-logo-16.png" type="file"]]) + string(APPEND RunCMake_TEST_FAILED + "Could not find expected <NamedMeasurement> tag(2) for type='file' in Test.xml") +endif() From 0962cbf21de45937c0109b953d569f6be1b7bf8f Mon Sep 17 00:00:00 2001 From: Zack Galbreath <zack.galbreath@kitware.com> Date: Thu, 1 Jul 2021 14:52:00 -0400 Subject: [PATCH 0822/1519] help: update ctest attached file example Clarify that multiple files can be attached to a given test at runtime --- Help/command/ctest_test.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index caac6057b1f..ede0c97776b 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -257,8 +257,10 @@ The following example demonstrates how to upload non-image files to CDash. .. code-block:: c++ std::cout << - "<CTestMeasurementFile type=\"file\" name=\"MyTestInputData\">" << - "/dir/to/data.csv</CTestMeasurementFile>" << std::endl; + "<CTestMeasurementFile type=\"file\" name=\"TestInputData1\">" << + "/dir/to/data1.csv</CTestMeasurementFile>\n" << + "<CTestMeasurementFile type=\"file\" name=\"TestInputData2\">" << + "/dir/to/data2.csv</CTestMeasurementFile>" << std::endl; If the name of the file to upload is known at configure time, you can use the :prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test From 4f69bf09641f51a6285902e68c1a435688ef70f8 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 2 Jul 2021 00:01:10 -0400 Subject: [PATCH 0823/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b4937dd13dd..23a44e79b40 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210701) +set(CMake_VERSION_PATCH 20210702) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3ede66e17a7160683a353c5414a131368eff4861 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 2 Jul 2021 07:24:15 -0400 Subject: [PATCH 0824/1519] Tests: Fix newline matching in several RunCMake.* cases The RunCMake infrastructure's `*-stdout.txt` expected output files interpret `\n` as a `\` and `n` rather than a newline. Use a literal newline instead. Otherwise the cases that were trying to match any configuration name via `[^\n]*` would fail on `RelWithDebInfo` because it contains the letter `n`. --- Tests/RunCMake/CPack/RPM/default_expected_stderr.txt | 3 ++- .../GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt | 6 ++++-- .../GoogleTest/GoogleTest-property-timeout1-stdout.txt | 6 ++++-- .../GoogleTest/GoogleTest-property-timeout2-stdout.txt | 6 ++++-- .../CMP0082-NEW-install-component-stdout.txt | 3 ++- .../add_subdirectory/CMP0082-NEW-install-stdout.txt | 3 ++- .../CMP0082-OLD-install-component-stdout.txt | 3 ++- .../add_subdirectory/CMP0082-OLD-install-stdout.txt | 3 ++- .../CMP0082-WARN-Nested-install-component-stdout.txt | 3 ++- .../add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt | 3 ++- .../CMP0082-WARN-NestedSub-install-component-stdout.txt | 3 ++- .../CMP0082-WARN-NestedSub-install-stdout.txt | 3 ++- .../CMP0082-WARN-NoTopInstall-install-component-stdout.txt | 3 ++- .../CMP0082-WARN-NoTopInstall-install-stdout.txt | 3 ++- .../CMP0082-WARN-None-install-component-stdout.txt | 3 ++- .../add_subdirectory/CMP0082-WARN-None-install-stdout.txt | 3 ++- .../CMP0082-WARN-install-component-stdout.txt | 3 ++- .../add_subdirectory/CMP0082-WARN-install-stdout.txt | 3 ++- 18 files changed, 42 insertions(+), 21 deletions(-) diff --git a/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt b/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt index 6c87ca0c0a5..404076bda91 100644 --- a/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt +++ b/Tests/RunCMake/CPack/RPM/default_expected_stderr.txt @@ -1 +1,2 @@ -^(CPackRPM: Will use GENERATED spec file: (/[^/]*)*/Tests/RunCMake/RPM\.[^/]*/CPack/[^-]*(-package-target)?-build((-[^-]*-subtest/)|/)_CPack_Packages/.*/RPM/SPECS/[^\.]*\.spec(\n|$))*$ +^(CPackRPM: Will use GENERATED spec file: (/[^/]*)*/Tests/RunCMake/RPM\.[^/]*/CPack/[^-]*(-package-target)?-build((-[^-]*-subtest/)|/)_CPack_Packages/.*/RPM/SPECS/[^\.]*\.spec( +|$))*$ diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt index d9de3f8e578..904ed117753 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-POST_BUILD-timeout-test-stdout.txt @@ -8,11 +8,13 @@ Debug/discovery_timeout_test_NOT_BUILT Debug/discovery_timeout_test_NOT_BUILT(\.exe)? Debug/discovery_timeout_test_NOT_BUILT Debug/discovery_timeout_test_NOT_BUILT(\.exe)? -[^\n]+discovery_timeout_test_NOT_BUILT +\.+\*\*\*Not Run +[0-9.]+ sec +[^ +]+discovery_timeout_test_NOT_BUILT +\.+\*\*\*Not Run +[0-9.]+ sec + 0% tests passed, 1 tests failed out of 1 + Total Test time \(real\) = +[0-9.]+ sec + The following tests FAILED: -[^\n]+discovery_timeout_test_NOT_BUILT \(Not Run\) +[^ +]+discovery_timeout_test_NOT_BUILT \(Not Run\) diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt index 0dda49d7c4b..5febfbfb000 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout1-stdout.txt @@ -1,10 +1,12 @@ Test project .*GoogleTest-build [ \t]*Start [0-9]+: property_timeout.case_no_discovery -[^\n]+property_timeout.case_no_discovery +\.+\*\*\*Timeout +[0-9.]+ sec +[^ +]+property_timeout.case_no_discovery +\.+\*\*\*Timeout +[0-9.]+ sec + 0% tests passed, 1 tests failed out of 1 + Total Test time \(real\) = +[0-9.]+ sec + The following tests FAILED: -[^\n]*property_timeout.case_no_discovery \(Timeout\) +[^ +]*property_timeout.case_no_discovery \(Timeout\) diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt index 72cea558ecc..c9c7198406c 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-property-timeout2-stdout.txt @@ -1,10 +1,12 @@ Test project .*GoogleTest-build [ \t]*Start [0-9]+: property_timeout.case_with_discovery -[^\n]+property_timeout.case_with_discovery +\.+\*\*\*Timeout +[0-9.]+ sec +[^ +]+property_timeout.case_with_discovery +\.+\*\*\*Timeout +[0-9.]+ sec + 0% tests passed, 1 tests failed out of 1 + Total Test time \(real\) = +[0-9.]+ sec + The following tests FAILED: -[^\n]*property_timeout.case_with_discovery \(Timeout\) +[^ +]*property_timeout.case_with_discovery \(Timeout\) diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt index 7d76ed959c2..169f0ccb2aa 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-component-stdout.txt @@ -1,4 +1,5 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- sub -- top$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt index 35b0bb5e14f..426114b592d 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-NEW-install-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- sub -- top$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt index 4b39789f764..b26500ef62b 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-component-stdout.txt @@ -1,4 +1,5 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt index 8f3a5f71d51..fcd556cb402 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-install-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt index 4b39789f764..b26500ef62b 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-component-stdout.txt @@ -1,4 +1,5 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt index 8f3a5f71d51..fcd556cb402 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-Nested-install-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt index 4b39789f764..b26500ef62b 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-component-stdout.txt @@ -1,4 +1,5 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt index 8f3a5f71d51..fcd556cb402 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NestedSub-install-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt index f7a331df2b5..c6020bd4664 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-component-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt index 6f22ae24dd5..658386b6269 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-NoTopInstall-install-stdout.txt @@ -1,2 +1,3 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt index 157ab37e2c9..ad070d58017 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-component-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- top$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt index 9e15872bd97..5a44e46af0e 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-None-install-stdout.txt @@ -1,2 +1,3 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- top$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt index 4b39789f764..b26500ef62b 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-component-stdout.txt @@ -1,4 +1,5 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- Install component: "Unspecified" -- top -- sub$ diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt index 8f3a5f71d51..fcd556cb402 100644 --- a/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt +++ b/Tests/RunCMake/add_subdirectory/CMP0082-WARN-install-stdout.txt @@ -1,3 +1,4 @@ -^-- Install configuration: "[^\n]*" +^-- Install configuration: "[^ +]*" -- top -- sub$ From 46c89c77de3216088afe11ffba33321b2cbb81e2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 2 Jul 2021 07:26:46 -0400 Subject: [PATCH 0825/1519] gitlab-ci: Rename CI config variable to avoid conflict with CMAKE_BUILD_TYPE Since commit e216b9bbd3 (cmake: Allow CMAKE_BUILD_TYPE to be set by environment variable, 2021-06-29), the `CMAKE_BUILD_TYPE` environment variable is interpreted by CMake, and can affect the test suite. Rename our CI config variable to avoid conflict. --- .gitlab/ci/configure_common.cmake | 4 ++-- .gitlab/ci/gitlab_ci.cmake | 4 ++-- .gitlab/os-linux.yml | 4 ++-- .gitlab/os-windows.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab/ci/configure_common.cmake b/.gitlab/ci/configure_common.cmake index 436e5824f4e..a711f3bda42 100644 --- a/.gitlab/ci/configure_common.cmake +++ b/.gitlab/ci/configure_common.cmake @@ -6,8 +6,8 @@ set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY "ON" CACHE BOOL "") set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "") set(CMake_TEST_INSTALL "OFF" CACHE BOOL "") -if (NOT "$ENV{CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_BUILD_TYPE "$ENV{CMAKE_BUILD_TYPE}" CACHE STRING "") +if (NOT "$ENV{CMAKE_CI_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE "$ENV{CMAKE_CI_BUILD_TYPE}" CACHE STRING "") endif () if (NOT configure_no_sccache) diff --git a/.gitlab/ci/gitlab_ci.cmake b/.gitlab/ci/gitlab_ci.cmake index f1662158045..697162c7dd1 100644 --- a/.gitlab/ci/gitlab_ci.cmake +++ b/.gitlab/ci/gitlab_ci.cmake @@ -26,8 +26,8 @@ set(CTEST_SITE "gitlab-ci") set(ctest_model "Experimental") # Default to Release builds. -if (NOT "$ENV{CMAKE_BUILD_TYPE}" STREQUAL "") - set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_BUILD_TYPE}") +if (NOT "$ENV{CMAKE_CI_BUILD_TYPE}" STREQUAL "") + set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CI_BUILD_TYPE}") endif () if (NOT CTEST_BUILD_CONFIGURATION) set(CTEST_BUILD_CONFIGURATION "Release") diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 8ce795e89c3..95cab05e59f 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -90,7 +90,7 @@ variables: CMAKE_CONFIGURATION: fedora34_clang_analyzer - CMAKE_BUILD_TYPE: Debug + CMAKE_CI_BUILD_TYPE: Debug CTEST_NO_WARNINGS_ALLOWED: 1 CMake_SKIP_INSTALL: 1 @@ -168,7 +168,7 @@ .fedora_memcheck: variables: - CMAKE_BUILD_TYPE: RelWithDebInfo + CMAKE_CI_BUILD_TYPE: RelWithDebInfo .fedora_asan_addon: extends: .fedora_memcheck diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index fb72ff14ee8..90ff0a8ff07 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -28,7 +28,7 @@ # Debug and RelWithDebinfo build types use the `/Zi` which results in # uncacheable compiations. # https://github.com/mozilla/sccache/issues/242 - CMAKE_BUILD_TYPE: Release + CMAKE_CI_BUILD_TYPE: Release CTEST_NO_WARNINGS_ALLOWED: 1 .windows_vs2019_x64_ninja: From 6a6efdcaedc6f87fbafd40af5305cabdced450c4 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Thu, 1 Jul 2021 11:47:52 +0200 Subject: [PATCH 0826/1519] Makefiles: Normalize compiler-generated depfile paths Even though Makefile generators pass source files and include directories by absolute path to the compiler, the compiler may generate depfile paths relative to the current working directory. For example, `ccache` with `CCACHE_BASEDIR` may transform paths this way. When reading a depfile, convert relative dependencies to absolute paths before placing them in `compiler_depend.make`, which is later evaluated in the top-level build directory. Fixes: #22364 --- Source/cmDependsCompiler.cxx | 4 +++- Source/cmGccDepfileReader.cxx | 8 +++++--- Source/cmGccDepfileReader.h | 11 +++++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx index 2b48df96934..09f55997bf4 100644 --- a/Source/cmDependsCompiler.cxx +++ b/Source/cmDependsCompiler.cxx @@ -131,7 +131,9 @@ bool cmDependsCompiler::CheckDependencies( depends.emplace_back(std::move(line)); } } else if (format == "gcc"_s) { - auto deps = cmReadGccDepfile(depFile.c_str()); + auto deps = cmReadGccDepfile( + depFile.c_str(), this->LocalGenerator->GetCurrentBinaryDirectory(), + GccDepfilePrependPaths::Deps); if (!deps) { continue; } diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx index 6436baac87b..d30dbc3090c 100644 --- a/Source/cmGccDepfileReader.cxx +++ b/Source/cmGccDepfileReader.cxx @@ -12,8 +12,9 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath, - const std::string& prefix) +cm::optional<cmGccDepfileContent> cmReadGccDepfile( + const char* filePath, const std::string& prefix, + GccDepfilePrependPaths prependPaths) { cmGccDepfileLexerHelper helper; if (!helper.readFile(filePath)) { @@ -23,7 +24,8 @@ cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath, for (auto& dep : *deps) { for (auto& rule : dep.rules) { - if (!prefix.empty() && !cmSystemTools::FileIsFullPath(rule)) { + if (prependPaths == GccDepfilePrependPaths::All && !prefix.empty() && + !cmSystemTools::FileIsFullPath(rule)) { rule = cmStrCat(prefix, '/', rule); } if (cmSystemTools::FileIsFullPath(rule)) { diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h index c8a37485c71..24334924461 100644 --- a/Source/cmGccDepfileReader.h +++ b/Source/cmGccDepfileReader.h @@ -8,8 +8,15 @@ #include "cmGccDepfileReaderTypes.h" +enum class GccDepfilePrependPaths +{ + All, + Deps, +}; + /* - * Read dependencies file and append prefix to all relative paths + * Read dependencies file and prepend prefix to all relative paths */ cm::optional<cmGccDepfileContent> cmReadGccDepfile( - const char* filePath, const std::string& prefix = {}); + const char* filePath, const std::string& prefix = {}, + GccDepfilePrependPaths prependPaths = GccDepfilePrependPaths::All); From 94a84dc0af227e574e2a9950cf2c830e2f57218f Mon Sep 17 00:00:00 2001 From: Alexander Neumann <neumann@imt.uni-luebeck.de> Date: Fri, 2 Jul 2021 17:06:31 +0200 Subject: [PATCH 0827/1519] FindPkgConfig: add pkgconf to the search list. --- Modules/FindPkgConfig.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index bd54fd9dbc0..d39bbd03a8f 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -46,6 +46,7 @@ set(PKG_CONFIG_NAMES "pkg-config") if(CMAKE_HOST_WIN32) list(PREPEND PKG_CONFIG_NAMES "pkg-config.bat") endif() +list(PREPEND PKG_CONFIG_NAMES "pkgconf") find_program(PKG_CONFIG_EXECUTABLE NAMES ${PKG_CONFIG_NAMES} From bece79f9bea1aa61d578429b63da76879ac5e5ba Mon Sep 17 00:00:00 2001 From: Christopher Degawa <ccom@randomderp.com> Date: Fri, 11 Jun 2021 15:38:44 -0500 Subject: [PATCH 0828/1519] Tests: Add case covering FindGLUT variables and imported targets Signed-off-by: Christopher Degawa <ccom@randomderp.com> --- .../ci/configure_debian10_aarch64_ninja.cmake | 1 + .gitlab/ci/configure_debian10_ninja.cmake | 1 + .gitlab/ci/configure_fedora34_makefiles.cmake | 1 + Tests/CMakeLists.txt | 1 + Tests/FindGLUT/CMakeLists.txt | 9 +++++++++ Tests/FindGLUT/Test/CMakeLists.txt | 17 +++++++++++++++++ Tests/FindGLUT/Test/main.c | 11 +++++++++++ 7 files changed, 41 insertions(+) create mode 100644 Tests/FindGLUT/CMakeLists.txt create mode 100644 Tests/FindGLUT/Test/CMakeLists.txt create mode 100644 Tests/FindGLUT/Test/main.c diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index 4d8dde6d9e6..a6b7cb50a3e 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -16,6 +16,7 @@ set(CMake_TEST_FindGDAL "ON" CACHE BOOL "") set(CMake_TEST_FindGIF "ON" CACHE BOOL "") set(CMake_TEST_FindGit "ON" CACHE BOOL "") set(CMake_TEST_FindGLEW "ON" CACHE BOOL "") +set(CMake_TEST_FindGLUT "ON" CACHE BOOL "") set(CMake_TEST_FindGnuTLS "ON" CACHE BOOL "") set(CMake_TEST_FindGSL "ON" CACHE BOOL "") set(CMake_TEST_FindGTest "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index 732624ad525..10d0997baff 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -16,6 +16,7 @@ set(CMake_TEST_FindGDAL "ON" CACHE BOOL "") set(CMake_TEST_FindGIF "ON" CACHE BOOL "") set(CMake_TEST_FindGit "ON" CACHE BOOL "") set(CMake_TEST_FindGLEW "ON" CACHE BOOL "") +set(CMake_TEST_FindGLUT "ON" CACHE BOOL "") set(CMake_TEST_FindGnuTLS "ON" CACHE BOOL "") set(CMake_TEST_FindGSL "ON" CACHE BOOL "") set(CMake_TEST_FindGTest "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora34_makefiles.cmake b/.gitlab/ci/configure_fedora34_makefiles.cmake index 48786e45731..d4bdb6a11e9 100644 --- a/.gitlab/ci/configure_fedora34_makefiles.cmake +++ b/.gitlab/ci/configure_fedora34_makefiles.cmake @@ -16,6 +16,7 @@ set(CMake_TEST_FindGDAL "ON" CACHE BOOL "") set(CMake_TEST_FindGIF "ON" CACHE BOOL "") set(CMake_TEST_FindGit "ON" CACHE BOOL "") set(CMake_TEST_FindGLEW "ON" CACHE BOOL "") +set(CMake_TEST_FindGLUT "ON" CACHE BOOL "") set(CMake_TEST_FindGnuTLS "ON" CACHE BOOL "") set(CMake_TEST_FindGSL "ON" CACHE BOOL "") set(CMake_TEST_FindGTest "ON" CACHE BOOL "") diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 341aba63511..388ff207a81 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1442,6 +1442,7 @@ if(BUILD_TESTING) GIF Git GLEW + GLUT GnuTLS GSL GTK2 diff --git a/Tests/FindGLUT/CMakeLists.txt b/Tests/FindGLUT/CMakeLists.txt new file mode 100644 index 00000000000..e75ec408bfc --- /dev/null +++ b/Tests/FindGLUT/CMakeLists.txt @@ -0,0 +1,9 @@ +add_test(NAME FindGLUT.Test COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindGLUT/Test" + "${CMake_BINARY_DIR}/Tests/FindGLUT/Test" + ${build_generator_args} + --build-project TestFindGLUT + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V + ) diff --git a/Tests/FindGLUT/Test/CMakeLists.txt b/Tests/FindGLUT/Test/CMakeLists.txt new file mode 100644 index 00000000000..0f4e5367397 --- /dev/null +++ b/Tests/FindGLUT/Test/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.21) +project(TestFindGLUT C) +include(CTest) + +find_package(GLUT REQUIRED) + +add_executable(testglut_tgt main.c) +target_link_libraries(testglut_tgt GLUT::GLUT) +add_test(NAME testglut_tgt COMMAND testglut_tgt) + +add_executable(testglut_var main.c) +target_include_directories(testglut_var PRIVATE ${GLUT_INCLUDE_DIRS}) +target_link_libraries(testglut_var PRIVATE ${GLUT_LIBRARIES}) +add_test(NAME testglut_var COMMAND testglut_var) + +set_tests_properties(testglut_tgt testglut_var + PROPERTIES WILL_FAIL true) diff --git a/Tests/FindGLUT/Test/main.c b/Tests/FindGLUT/Test/main.c new file mode 100644 index 00000000000..1c8569c1290 --- /dev/null +++ b/Tests/FindGLUT/Test/main.c @@ -0,0 +1,11 @@ +#include <GL/glut.h> +#include <stdio.h> + +int main() +{ + /* The following should call exit(1) and print + freeglut ERROR: Function <glutCreateWindow> called + without first calling 'glutInit'. + to stderr */ + glutCreateWindow("gluttest"); +} From f3f040118736eb793a2615247ed7e0ed5d5bd939 Mon Sep 17 00:00:00 2001 From: Christopher Degawa <ccom@randomderp.com> Date: Fri, 11 Jun 2021 15:38:44 -0500 Subject: [PATCH 0829/1519] FindGLUT: Reduce if/else nesting and indentation Signed-off-by: Christopher Degawa <ccom@randomderp.com> --- Modules/FindGLUT.cmake | 127 +++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 68 deletions(-) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 2770c604dea..53ff727ed25 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -42,7 +42,7 @@ Also defined, but not for general use are: include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) -if (WIN32) +if(WIN32) find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h PATHS ${GLUT_ROOT_PATH}/include ) find_library( GLUT_glut_LIBRARY_RELEASE NAMES glut glut32 freeglut @@ -57,83 +57,74 @@ if (WIN32) ) mark_as_advanced(GLUT_glut_LIBRARY_RELEASE GLUT_glut_LIBRARY_DEBUG) select_library_configurations(GLUT_glut) -else () - - if (APPLE) - find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR}) - find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX") - find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX") - mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY) - - if(GLUT_cocoa_LIBRARY AND NOT TARGET GLUT::Cocoa) - add_library(GLUT::Cocoa UNKNOWN IMPORTED) - # Cocoa should always be a Framework, but we check to make sure. - if(GLUT_cocoa_LIBRARY MATCHES "/([^/]+)\\.framework$") - set(_glut_cocoa "${GLUT_cocoa_LIBRARY}/${CMAKE_MATCH_1}") - if(EXISTS "${_glut_cocoa}.tbd") - string(APPEND _glut_cocoa ".tbd") - endif() - set_target_properties(GLUT::Cocoa PROPERTIES - IMPORTED_LOCATION "${_glut_cocoa}") - else() - set_target_properties(GLUT::Cocoa PROPERTIES - IMPORTED_LOCATION "${GLUT_cocoa_LIBRARY}") +elseif(APPLE) + find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR}) + find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX") + find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX") + mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY) + + if(GLUT_cocoa_LIBRARY AND NOT TARGET GLUT::Cocoa) + add_library(GLUT::Cocoa UNKNOWN IMPORTED) + # Cocoa should always be a Framework, but we check to make sure. + if(GLUT_cocoa_LIBRARY MATCHES "/([^/]+)\\.framework$") + set(_glut_cocoa "${GLUT_cocoa_LIBRARY}/${CMAKE_MATCH_1}") + if(EXISTS "${_glut_cocoa}.tbd") + string(APPEND _glut_cocoa ".tbd") endif() - endif() - else () - - if (BEOS) - - set(_GLUT_INC_DIR /boot/develop/headers/os/opengl) - set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86) - + set_target_properties(GLUT::Cocoa PROPERTIES + IMPORTED_LOCATION "${_glut_cocoa}") else() - - find_library( GLUT_Xi_LIBRARY Xi - /usr/openwin/lib - ) - mark_as_advanced(GLUT_Xi_LIBRARY) - - find_library( GLUT_Xmu_LIBRARY Xmu - /usr/openwin/lib - ) - mark_as_advanced(GLUT_Xmu_LIBRARY) - - if(GLUT_Xi_LIBRARY AND NOT TARGET GLUT::Xi) - add_library(GLUT::Xi UNKNOWN IMPORTED) - set_target_properties(GLUT::Xi PROPERTIES - IMPORTED_LOCATION "${GLUT_Xi_LIBRARY}") - endif() - - if(GLUT_Xmu_LIBRARY AND NOT TARGET GLUT::Xmu) - add_library(GLUT::Xmu UNKNOWN IMPORTED) - set_target_properties(GLUT::Xmu PROPERTIES - IMPORTED_LOCATION "${GLUT_Xmu_LIBRARY}") - endif() - - endif () - - find_path( GLUT_INCLUDE_DIR GL/glut.h - /usr/include/GL - /usr/openwin/share/include - /usr/openwin/include - /opt/graphics/OpenGL/include - /opt/graphics/OpenGL/contrib/libglut - ${_GLUT_INC_DIR} + set_target_properties(GLUT::Cocoa PROPERTIES + IMPORTED_LOCATION "${GLUT_cocoa_LIBRARY}") + endif() + endif() +else() + if(BEOS) + set(_GLUT_INC_DIR /boot/develop/headers/os/opengl) + set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86) + else() + find_library( GLUT_Xi_LIBRARY Xi + /usr/openwin/lib ) + mark_as_advanced(GLUT_Xi_LIBRARY) - find_library( GLUT_glut_LIBRARY glut + find_library( GLUT_Xmu_LIBRARY Xmu /usr/openwin/lib - ${_GLUT_glut_LIB_DIR} ) - mark_as_advanced(GLUT_glut_LIBRARY) + mark_as_advanced(GLUT_Xmu_LIBRARY) - unset(_GLUT_INC_DIR) - unset(_GLUT_glut_LIB_DIR) + if(GLUT_Xi_LIBRARY AND NOT TARGET GLUT::Xi) + add_library(GLUT::Xi UNKNOWN IMPORTED) + set_target_properties(GLUT::Xi PROPERTIES + IMPORTED_LOCATION "${GLUT_Xi_LIBRARY}") + endif() + + if(GLUT_Xmu_LIBRARY AND NOT TARGET GLUT::Xmu) + add_library(GLUT::Xmu UNKNOWN IMPORTED) + set_target_properties(GLUT::Xmu PROPERTIES + IMPORTED_LOCATION "${GLUT_Xmu_LIBRARY}") + endif() endif () -endif () + find_path( GLUT_INCLUDE_DIR GL/glut.h + /usr/include/GL + /usr/openwin/share/include + /usr/openwin/include + /opt/graphics/OpenGL/include + /opt/graphics/OpenGL/contrib/libglut + ${_GLUT_INC_DIR} + ) + + find_library( GLUT_glut_LIBRARY glut + /usr/openwin/lib + ${_GLUT_glut_LIB_DIR} + ) + + unset(_GLUT_INC_DIR) + unset(_GLUT_glut_LIB_DIR) +endif() +mark_as_advanced(GLUT_glut_LIBRARY) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_glut_LIBRARY GLUT_INCLUDE_DIR) From f90d15458a9a98180fcc95158f2ab5d2b1ad3152 Mon Sep 17 00:00:00 2001 From: Christopher Degawa <ccom@randomderp.com> Date: Fri, 11 Jun 2021 15:38:44 -0500 Subject: [PATCH 0830/1519] FindGLUT: Use pkg-config to find flags if available FindGLUT fails to properly link a static libglut as it does not list the dependencies needed. Signed-off-by: Christopher Degawa <ccom@randomderp.com> --- Modules/FindGLUT.cmake | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 53ff727ed25..dd0975d3951 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -41,6 +41,41 @@ Also defined, but not for general use are: #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +function(_add_glut_target_simple) + if(TARGET GLUT::GLUT) + return() + endif() + add_library(GLUT::GLUT INTERFACE IMPORTED) + if(GLUT_INCLUDE_DIRS) + target_include_directories(GLUT::GLUT SYSTEM + INTERFACE "${GLUT_INCLUDE_DIRS}") + endif() + if(GLUT_LIBRARIES) + target_link_libraries(GLUT::GLUT INTERFACE ${GLUT_LIBRARIES}) + endif() + if(GLUT_LDFLAGS) + target_link_options(GLUT::GLUT INTERFACE ${GLUT_LDFLAGS}) + endif() + if(GLUT_CFLAGS) + separate_arguments(GLUT_CFLAGS_SPLIT UNIX_COMMAND "${GLUT_CFLAGS}") + target_compile_options(GLUT::GLUT INTERFACE ${GLUT_CFLAGS_SPLIT}) + endif() + + set_property(TARGET GLUT::GLUT APPEND PROPERTY + IMPORTED_LOCATION "${GLUT_glut_LIBRARY}") +endfunction() + +find_package(PkgConfig) +if(PKG_CONFIG_FOUND) + pkg_check_modules(GLUT glut) + if(GLUT_FOUND) + _add_glut_target_simple() + FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_FOUND) + return() + endif() +endif() if(WIN32) find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h @@ -126,7 +161,6 @@ else() endif() mark_as_advanced(GLUT_glut_LIBRARY) -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_glut_LIBRARY GLUT_INCLUDE_DIR) if (GLUT_FOUND) From 51485993e769ce01d49b0500664a2ac6cab0e38d Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 3 Jul 2021 00:01:12 -0400 Subject: [PATCH 0831/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 23a44e79b40..17c30ff59a1 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210702) +set(CMake_VERSION_PATCH 20210703) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 52dec01729c2afc0f4ffc04286ac5aec043e35aa Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 28 Jun 2021 15:54:49 +1000 Subject: [PATCH 0832/1519] Help: Add missing versionadded 3.21 for file(RENAME) options --- Help/command/file.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Help/command/file.rst b/Help/command/file.rst index b6ed41660f9..8ce27ff0924 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -703,10 +703,14 @@ Move a file or directory within a filesystem from ``<oldname>`` to The options are: ``RESULT <result>`` + .. versionadded:: 3.21 + Set ``<result>`` variable to ``0`` on success or an error message otherwise. If ``RESULT`` is not specified and the operation fails, an error is emitted. ``NO_REPLACE`` + .. versionadded:: 3.21 + If the ``<newname>`` path already exists, do not replace it. If ``RESULT <result>`` is used, the result variable will be set to ``NO_REPLACE``. Otherwise, an error is emitted. From 308e5b30c900cb4aa1009ee8e25908a41060d992 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Tue, 29 Jun 2021 17:25:19 +1000 Subject: [PATCH 0833/1519] Help: Tighten install(SCRIPT) wording for ALL_COMPONENTS option In particular, mention the mutually exclusive nature with the COMPONENT option. Fix the inconsistent way the versionadded details were added for that text too. --- Help/command/install.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Help/command/install.rst b/Help/command/install.rst index acfaa486d13..ace53b3f906 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -693,7 +693,8 @@ Custom Installation Logic .. code-block:: cmake install([[SCRIPT <file>] [CODE <code>]] - [COMPONENT <component>] [EXCLUDE_FROM_ALL] [ALL_COMPONENTS] [...]) + [ALL_COMPONENTS | COMPONENT <component>] + [EXCLUDE_FROM_ALL] [...]) The ``SCRIPT`` form will invoke the given CMake script files during installation. If the script file name is a relative path it will be @@ -708,11 +709,11 @@ example, the code will print a message during installation. -The option ``ALL_COMPONENTS`` - .. versionadded:: 3.21 - - Run the custom installation script code for every component of a - component-specific installation. +.. versionadded:: 3.21 + When the ``ALL_COMPONENTS`` option is given, the custom installation + script code will be executed for every component of a component-specific + installation. This option is mutually exclusive with the ``COMPONENT`` + option. .. versionadded:: 3.14 ``<file>`` or ``<code>`` may use "generator expressions" with the syntax From 7f6552745d679859a6ca7d86f92e8f65daea466c Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 4 Jul 2021 00:01:09 -0400 Subject: [PATCH 0834/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 17c30ff59a1..38b23f33373 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210703) +set(CMake_VERSION_PATCH 20210704) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 24b76eaa93447d3521b55c5233036ce3ca752d6b Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 3 Jul 2021 19:00:14 +1000 Subject: [PATCH 0835/1519] Help: Improve readability and accuracy of runtime deps-related content Duplicated textual patterns are factored out to make the text more readable. The POST_INCLUDE_FILES and POST_EXCLUDE_FILES were also previously missing from the main syntax block for install(RUNTIME_DEPENDENCY_SET). --- Help/command/file.rst | 6 ++- Help/command/install.rst | 113 +++++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 55 deletions(-) diff --git a/Help/command/file.rst b/Help/command/file.rst index 8ce27ff0924..943bf7c1b86 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -189,8 +189,10 @@ the ``<format>`` and ``UTC`` options. Recursively get the list of libraries depended on by the given files. Please note that this sub-command is not intended to be used in project mode. -Instead, use it in an :command:`install(CODE)` or :command:`install(SCRIPT)` -block. For example: +It is intended for use at install time, either from code generated by the +:command:`install(RUNTIME_DEPENDENCY_SET)` command, or from code provided by +the project via :command:`install(CODE)` or :command:`install(SCRIPT)`. +For example: .. code-block:: cmake diff --git a/Help/command/install.rst b/Help/command/install.rst index ace53b3f906..c6af4897e0f 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -346,10 +346,10 @@ top level: This option causes all runtime dependencies of installed executable, shared library, and module targets to be added to the specified runtime dependency - set. This set can then be installed later on with an + set. This set can then be installed with an `install(RUNTIME_DEPENDENCY_SET)`_ command. - This argument and the ``RUNTIME_DEPENDENCIES`` argument are mutually + This keyword and the ``RUNTIME_DEPENDENCIES`` keyword are mutually exclusive. ``RUNTIME_DEPENDENCIES`` @@ -361,13 +361,28 @@ top level: arguments are used to determine the properties (``DESTINATION``, ``COMPONENT``, etc.) of the installation of these dependencies. - ``RUNTIME_DEPENDENCIES`` is semantically equivalent to calling - ``install(TARGETS ... RUNTIME_DEPENDENCY_SET)`` and then - `install(RUNTIME_DEPENDENCY_SET)`_ with a randomly generated name. It accepts - all of the same options as `install(RUNTIME_DEPENDENCY_SET)`_. + ``RUNTIME_DEPENDENCIES`` is semantically equivalent to the following pair + of calls: - This argument and the ``RUNTIME_DEPENDENCY_SET`` argument are mutually - exclusive. + .. code-block:: cmake + + install(TARGETS ... RUNTIME_DEPENDENCY_SET <set-name>) + install(RUNTIME_DEPENDENCY_SET <set-name> args...) + + where ``<set-name>`` will be a randomly generated set name. + The ``args...`` may include any of the following keywords supported by + the `install(RUNTIME_DEPENDENCY_SET)`_ command: + + * ``DIRECTORIES`` + * ``PRE_INCLUDE_REGEXES`` + * ``PRE_EXCLUDE_REGEXES`` + * ``POST_INCLUDE_REGEXES`` + * ``POST_EXCLUDE_REGEXES`` + * ``POST_INCLUDE_FILES`` + * ``POST_EXCLUDE_FILES`` + + The ``RUNTIME_DEPENDENCIES`` and ``RUNTIME_DEPENDENCY_SET`` keywords are + mutually exclusive. One or more groups of properties may be specified in a single call to the ``TARGETS`` form of this command. A target may be installed more than @@ -446,14 +461,10 @@ not installed. In the case of :prop_tgt:`FRAMEWORK` libraries, :prop_tgt:`MACOSX_BUNDLE` executables, and :prop_tgt:`BUNDLE` CFBundles, the entire directory is installed. -``IMPORTED_RUNTIME_ARTIFACTS`` accepts the following additional arguments: - -``RUNTIME_DEPENDENCY_SET`` - - This option causes all runtime dependencies of installed executable, shared - library, and module targets to be added to the specified runtime dependency - set. This set can then be installed later on with an - `install(RUNTIME_DEPENDENCY_SET)`_ command. +The ``RUNTIME_DEPENDENCY_SET`` option causes the runtime artifacts of the +imported executable, shared library, and module library ``targets`` to be +added to the ``<set-name>`` runtime dependency set. This set can then be +installed with an `install(RUNTIME_DEPENDENCY_SET)`_ command. Installing Files ^^^^^^^^^^^^^^^^ @@ -837,50 +848,46 @@ Installing Runtime Dependencies [PRE_EXCLUDE_REGEXES regexes...] [POST_INCLUDE_REGEXES regexes...] [POST_EXCLUDE_REGEXES regexes...] + [POST_INCLUDE_FILES files...] + [POST_EXCLUDE_FILES files...] [DIRECTORIES directories...] ) -Installs a runtime dependency set created by one or more +Installs a runtime dependency set previously created by one or more `install(TARGETS)`_ or `install(IMPORTED_RUNTIME_ARTIFACTS)`_ commands. The dependencies of targets belonging to a runtime dependency set are installed in the ``RUNTIME`` destination and component on DLL platforms, and in the ``LIBRARY`` destination and component on non-DLL platforms. macOS frameworks -are installed in the ``FRAMEWORK`` destination and component. The generated -install script calls :command:`file(GET_RUNTIME_DEPENDENCIES)` on the -build-tree files to calculate the runtime dependencies, with the build-tree -executable files as the ``EXECUTABLES`` argument, the build-tree shared -libraries as the ``LIBRARIES`` argument, and the build-tree modules as the -``MODULES`` argument. If one of the executables is a :prop_tgt:`MACOSX_BUNDLE` -executable on a macOS platform, that executable is passed as the -``BUNDLE_EXECUTABLE`` argument. If ``RUNTIME_DEPENDENCY_SET`` is specified on -a macOS platform, at most one :prop_tgt:`MACOSX_BUNDLE` executable may be in -the runtime dependency set. The :prop_tgt:`MACOSX_BUNDLE` property has no -effect on non-macOS platforms. Targets built within the build tree will never -be installed as runtime dependencies, nor will their own dependencies, unless -the targets themselves are installed with `install(TARGETS)`_. - -This argument accepts the following sub-arguments: - -``DIRECTORIES <directories>`` - List of directories to be passed as the ``DIRECTORIES`` argument of - :command:`file(GET_RUNTIME_DEPENDENCIES)`. This argument supports - :manual:`generator expressions <cmake-generator-expressions(7)>`. If a - ``DIRECTORIES`` argument evaluates to an empty string, it is not passed to - :command:`file(GET_RUNTIME_DEPENDENCIES)`. - -``PRE_INCLUDE_REGEXES <regexes>``, ``PRE_EXCLUDE_REGEXES <regexes>``, ``POST_INCLUDE_REGEXES <regexes>``, ``POST_EXCLUDE_REGEXES <regexes>`` - List of regular expressions to be passed as their respective arguments to - :command:`file(GET_RUNTIME_DEPENDENCIES)`. These arguments support - :manual:`generator expressions <cmake-generator-expressions(7)>`. If an - argument evaluates to an empty string, it is not passed to - :command:`file(GET_RUNTIME_DEPENDENCIES)`. - -``POST_INCLUDE_FILES <files>``, ``POST_EXCLUDE_FILES <files>`` - List of files to be passed as their respective arguments to - :command:`file(GET_RUNTIME_DEPENDENCIES)`. These arguments support - :manual:`generator expressions <cmake-generator-expressions(7)>`. If an - argument evaluates to an empty string, it is not passed to - :command:`file(GET_RUNTIME_DEPENDENCIES)`. +are installed in the ``FRAMEWORK`` destination and component. +Targets built within the build tree will never be installed as runtime +dependencies, nor will their own dependencies, unless the targets themselves +are installed with `install(TARGETS)`_. + +The generated install script calls :command:`file(GET_RUNTIME_DEPENDENCIES)` +on the build-tree files to calculate the runtime dependencies. The build-tree +executable files are passed as the ``EXECUTABLES`` argument, the build-tree +shared libraries as the ``LIBRARIES`` argument, and the build-tree modules as +the ``MODULES`` argument. On macOS, if one of the executables is a +:prop_tgt:`MACOSX_BUNDLE`, that executable is passed as the +``BUNDLE_EXECUTABLE`` argument. At most one such bundle executable may be in +the runtime dependency set on macOS. The :prop_tgt:`MACOSX_BUNDLE` property +has no effect on other platforms. Note that +:command:`file(GET_RUNTIME_DEPENDENCIES)` only supports collecting the runtime +dependencies for Windows, Linux and macOS platforms, so +``install(RUNTIME_DEPENDENCY_SET)`` has the same limitation. + +The following sub-arguments are forwarded through as the corresponding +arguments to :command:`file(GET_RUNTIME_DEPENDENCIES)` (for those that provide +a non-empty list of directories, regular expressions or files). They all +support :manual:`generator expressions <cmake-generator-expressions(7)>`. + +* ``DIRECTORIES <directories>`` +* ``PRE_INCLUDE_REGEXES <regexes>`` +* ``PRE_EXCLUDE_REGEXES <regexes>`` +* ``POST_INCLUDE_REGEXES <regexes>`` +* ``POST_EXCLUDE_REGEXES <regexes>`` +* ``POST_INCLUDE_FILES <files>`` +* ``POST_EXCLUDE_FILES <files>`` Generated Installation Script ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 28979a59683a955b45b9a6fdcf0170e1d7826934 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 5 Jul 2021 00:01:22 -0400 Subject: [PATCH 0836/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 38b23f33373..2ce65d4b755 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210704) +set(CMake_VERSION_PATCH 20210705) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a27fa90aa1bc88a1633c51a8e6951373d6c62499 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 6 Jul 2021 00:01:10 -0400 Subject: [PATCH 0837/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2ce65d4b755..b4bfbccb8a2 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210705) +set(CMake_VERSION_PATCH 20210706) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 71a2664ebb0fd6a8d56eadee058aecc431a40594 Mon Sep 17 00:00:00 2001 From: Gregor Jasny <gregor.jasny@logmein.com> Date: Tue, 6 Jul 2021 09:22:52 +0200 Subject: [PATCH 0838/1519] Xcode: Ignore deprecated build system With Xcode 13 the key to suppress the check has changed. Tested with Xcode 12.5 and 13.0-beta2. --- Source/cmGlobalXCodeGenerator.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 693a11c9a1b..77403b076ac 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -4617,7 +4617,11 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( switch (this->XcodeBuildSystem) { case BuildSystem::One: xout.Element("string", "Original"); - xout.Element("key", "DisableBuildSystemDeprecationWarning"); + if (this->XcodeVersion >= 130) { + xout.Element("key", "DisableBuildSystemDeprecationDiagnostic"); + } else { + xout.Element("key", "DisableBuildSystemDeprecationWarning"); + } xout.Element("true"); break; case BuildSystem::Twelve: From 0d54276c82f7903792d36955a29760142d7b729c Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Tue, 6 Jul 2021 08:43:13 -0400 Subject: [PATCH 0839/1519] Correct CUDAToolkit_VERSION_MINOR variable name typo --- Modules/FindCUDAToolkit.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 8801cb1bff2..4235904dd28 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -410,7 +410,7 @@ Result variables ``CUDAToolkit_VERSION_MAJOR`` The major version of the CUDA Toolkit. -``CUDAToolkit_VERSION_MAJOR`` +``CUDAToolkit_VERSION_MINOR`` The minor version of the CUDA Toolkit. ``CUDAToolkit_VERSION_PATCH`` From 0602e358588690de71988b9e39dbc60c627cba0b Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Mon, 5 Jul 2021 19:40:52 -0400 Subject: [PATCH 0840/1519] Intel/Fortran: Avoid recording warning 5117 lines in CMakeError.log --- Modules/CMakeDetermineCompilerId.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index bd1e732530f..fb5d7731ef8 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -722,7 +722,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} # Check the result of compilation. if(CMAKE_${lang}_COMPILER_ID_RESULT # Intel Fortran warns and ignores preprocessor lines without /fpp - OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "Bad # preprocessor line" + OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "warning #5117: Bad # preprocessor line" ) # Compilation failed. set(MSG @@ -733,7 +733,10 @@ ${CMAKE_${lang}_COMPILER_ID_RESULT} ${CMAKE_${lang}_COMPILER_ID_OUTPUT} ") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}") + # Log the output unless we recognize it as a known-bad case. + if(NOT CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "warning #5117: Bad # preprocessor line") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}") + endif() # Some languages may know the correct/desired set of flags and want to fail right away if they don't work. # This is currently only used by CUDA. From d9a3c9fad52a522da0dcc8093770fb9e59a1e21e Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Tue, 6 Jul 2021 14:36:27 -0400 Subject: [PATCH 0841/1519] CMakePresets.json: Make --list-presets show presets with no generator Fixes: #22389 --- Source/cmake.cxx | 3 +++ Tests/RunCMake/CMakePresets/ListPresets-stdout.txt | 7 ++++--- Tests/RunCMake/CMakePresets/ListPresets.json.in | 5 ++++- Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt | 7 ++++--- .../CMakePresets/ListPresetsNoSuchPreset-stdout.txt | 7 ++++--- .../RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt | 7 ++++--- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 14f66d9e707..73f5ad5b87b 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1687,6 +1687,9 @@ void cmake::PrintPresetList(const cmCMakePresetsFile& file) const this->GetRegisteredGenerators(generators, false); auto filter = [&generators](const cmCMakePresetsFile::ConfigurePreset& preset) -> bool { + if (preset.Generator.empty()) { + return true; + } auto condition = [&preset](const GeneratorInfo& info) -> bool { return info.name == preset.Generator; }; diff --git a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt index 60d6adbd98a..97eedae7c6b 100644 --- a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt +++ b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt @@ -1,6 +1,7 @@ ^Not searching for unused variables given on the command line\. Available configure presets: - "zzzzzz" - Sleepy - "aaaaaaaa" - Screaming - "mmmmmm"$ + "zzzzzz" - Sleepy + "aaaaaaaa" - Screaming + "mmmmmm" + "no-generator"$ diff --git a/Tests/RunCMake/CMakePresets/ListPresets.json.in b/Tests/RunCMake/CMakePresets/ListPresets.json.in index 2ef3797daf2..160098c537f 100644 --- a/Tests/RunCMake/CMakePresets/ListPresets.json.in +++ b/Tests/RunCMake/CMakePresets/ListPresets.json.in @@ -1,5 +1,5 @@ { - "version": 1, + "version": 3, "configurePresets": [ { "name": "zzzzzz", @@ -18,6 +18,9 @@ "generator": "@RunCMake_GENERATOR@", "binaryDir": "${sourceDir}/build/mmmmmm" }, + { + "name": "no-generator" + }, { "name": "invalid-generator", "generator": "Invalid Generator", diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt index 60d6adbd98a..97eedae7c6b 100644 --- a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt +++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt @@ -1,6 +1,7 @@ ^Not searching for unused variables given on the command line\. Available configure presets: - "zzzzzz" - Sleepy - "aaaaaaaa" - Screaming - "mmmmmm"$ + "zzzzzz" - Sleepy + "aaaaaaaa" - Screaming + "mmmmmm" + "no-generator"$ diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt index 60d6adbd98a..97eedae7c6b 100644 --- a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt +++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt @@ -1,6 +1,7 @@ ^Not searching for unused variables given on the command line\. Available configure presets: - "zzzzzz" - Sleepy - "aaaaaaaa" - Screaming - "mmmmmm"$ + "zzzzzz" - Sleepy + "aaaaaaaa" - Screaming + "mmmmmm" + "no-generator"$ diff --git a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt index 60d6adbd98a..97eedae7c6b 100644 --- a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt +++ b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt @@ -1,6 +1,7 @@ ^Not searching for unused variables given on the command line\. Available configure presets: - "zzzzzz" - Sleepy - "aaaaaaaa" - Screaming - "mmmmmm"$ + "zzzzzz" - Sleepy + "aaaaaaaa" - Screaming + "mmmmmm" + "no-generator"$ From 5650bebc2fa19db4572b6e445c8b28ee9e733732 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Mon, 5 Jul 2021 10:50:56 -0400 Subject: [PATCH 0842/1519] Help: Note CXX_STANDARD values added vs. CMake version --- Help/prop_tgt/CXX_STANDARD.rst | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst index be0dab565c2..b10d201738f 100644 --- a/Help/prop_tgt/CXX_STANDARD.rst +++ b/Help/prop_tgt/CXX_STANDARD.rst @@ -11,7 +11,31 @@ flag such as ``-std=gnu++11`` to the compile line. For compilers that have no notion of a standard level, such as Microsoft Visual C++ before 2015 Update 3, this has no effect. -Supported values are ``98``, ``11``, ``14``, ``17``, ``20``, ``23``. +Supported values are: + +``98`` + C++98 + +``11`` + C++11 + +``14`` + C++14 + +``17`` + .. versionadded:: 3.8 + + C++17 + +``20`` + .. versionadded:: 3.12 + + C++20 + +``23`` + .. versionadded:: 3.20 + + C++23 If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This From 429fb28f25752352db876f634d3b317962cfeb7d Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:11:42 +0200 Subject: [PATCH 0843/1519] cmLocalGenerator: Factor out repeated condition into local variable --- Source/cmLocalGenerator.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a14f0850f48..f58f1420abc 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1247,9 +1247,11 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( } } + bool const isCorCxx = (lang == "C" || lang == "CXX"); + // Checks if this is not an excluded (implicit) include directory. auto notExcluded = [this, &implicitSet, &implicitExclude, - &lang](std::string const& dir) { + isCorCxx](std::string const& dir) { return ( // Do not exclude directories that are not in an excluded set. ((!cm::contains(implicitSet, this->GlobalGenerator->GetRealPath(dir))) && @@ -1258,8 +1260,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // they are implicitly searched by the compiler. They are meant to be // user-specified directories that can be re-ordered or converted to // -isystem without breaking real compiler builtin headers. - || - ((lang == "C" || lang == "CXX") && cm::contains(this->EnvCPATH, dir))); + || (isCorCxx && cm::contains(this->EnvCPATH, dir))); }; // Get the target-specific include directories. From 1a9ebd1694aeeb97dc073c0dde75ddb8cd91794b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 6 Jul 2021 19:40:16 -0400 Subject: [PATCH 0844/1519] FindMPI: Honor MPI_CXX_SKIP_MPICXX when set as a normal variable Express the cache entry with `option()`. In combination with policies CMP0077 and CMP0102, this allows project code to control the switch with a variable: ``` set(MPI_CXX_SKIP_MPICXX TRUE) find_package(MPI COMPONENTS CXX) ``` --- Modules/FindMPI.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index c48decbb9fb..43fdace09ba 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -1440,7 +1440,7 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() if(_MPI_FIND_${LANG}) if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) - set(MPI_CXX_SKIP_MPICXX FALSE CACHE BOOL "If true, the MPI-2 C++ bindings are disabled using definitions.") + option(MPI_CXX_SKIP_MPICXX "If true, the MPI-2 C++ bindings are disabled using definitions." FALSE) mark_as_advanced(MPI_CXX_SKIP_MPICXX) endif() if(NOT (MPI_${LANG}_LIB_NAMES AND (MPI_${LANG}_INCLUDE_PATH OR MPI_${LANG}_INCLUDE_DIRS OR MPI_${LANG}_COMPILER_INCLUDE_DIRS))) From 0f1efb58c8ac1b6f38f384d33903159ccf7b6608 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 7 Jul 2021 00:01:11 -0400 Subject: [PATCH 0845/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b4bfbccb8a2..090efd6ace4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210706) +set(CMake_VERSION_PATCH 20210707) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3fd56472c6b6a78ba47cea0905a1694a7e6cec38 Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:11:42 +0200 Subject: [PATCH 0846/1519] cmLocalGenerator: Store realpath lookup result in a variable --- Source/cmLocalGenerator.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index f58f1420abc..051b15ae7fa 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1251,10 +1251,11 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // Checks if this is not an excluded (implicit) include directory. auto notExcluded = [this, &implicitSet, &implicitExclude, - isCorCxx](std::string const& dir) { + isCorCxx](std::string const& dir) -> bool { + std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir); return ( // Do not exclude directories that are not in an excluded set. - ((!cm::contains(implicitSet, this->GlobalGenerator->GetRealPath(dir))) && + ((!cm::contains(implicitSet, real_dir)) && (!cm::contains(implicitExclude, dir))) // Do not exclude entries of the CPATH environment variable even though // they are implicitly searched by the compiler. They are meant to be From 10969fd003919ba32072ead5d134e024bd37f228 Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:11:42 +0200 Subject: [PATCH 0847/1519] cmLocalGenerator: Remove unnecessary parentheses in a condition --- Source/cmLocalGenerator.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 051b15ae7fa..5fbff6c4292 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1253,15 +1253,15 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( auto notExcluded = [this, &implicitSet, &implicitExclude, isCorCxx](std::string const& dir) -> bool { std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir); - return ( + return // Do not exclude directories that are not in an excluded set. - ((!cm::contains(implicitSet, real_dir)) && - (!cm::contains(implicitExclude, dir))) + (!cm::contains(implicitSet, real_dir) && + !cm::contains(implicitExclude, dir)) // Do not exclude entries of the CPATH environment variable even though // they are implicitly searched by the compiler. They are meant to be // user-specified directories that can be re-ordered or converted to // -isystem without breaking real compiler builtin headers. - || (isCorCxx && cm::contains(this->EnvCPATH, dir))); + || (isCorCxx && cm::contains(this->EnvCPATH, dir)); }; // Get the target-specific include directories. From 86595b300297c9572eea5710837f5bb12251c62f Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:11:42 +0200 Subject: [PATCH 0848/1519] cmLocalGenerator: Clarify check for membership in multiple sets --- Source/cmLocalGenerator.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 5fbff6c4292..cfda21f5a62 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1254,9 +1254,9 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( isCorCxx](std::string const& dir) -> bool { std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir); return - // Do not exclude directories that are not in an excluded set. - (!cm::contains(implicitSet, real_dir) && - !cm::contains(implicitExclude, dir)) + // Do not exclude directories that are not in any excluded set. + !(cm::contains(implicitSet, real_dir) || + cm::contains(implicitExclude, dir)) // Do not exclude entries of the CPATH environment variable even though // they are implicitly searched by the compiler. They are meant to be // user-specified directories that can be re-ordered or converted to From 5c02964aff0e126980fe327ad1601665d9fcabfe Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:11:42 +0200 Subject: [PATCH 0849/1519] cmLocalGenerator: Simplify CPATH lookup loop --- Source/cmLocalGenerator.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index cfda21f5a62..30df4c49a83 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -107,10 +107,9 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) { std::vector<std::string> cpath; cmSystemTools::GetPath(cpath, "CPATH"); - for (std::string& cp : cpath) { + for (std::string const& cp : cpath) { if (cmSystemTools::FileIsFullPath(cp)) { - cp = cmSystemTools::CollapseFullPath(cp); - this->EnvCPATH.emplace(std::move(cp)); + this->EnvCPATH.emplace(cmSystemTools::CollapseFullPath(cp)); } } } From c00f928ce1aba90c0b3fe8d6112eacd0f5494ec3 Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:11:42 +0200 Subject: [PATCH 0850/1519] Do not exclude include directory symlinks to entries of CPATH Extend the fix from commit 2d0b0e2b9d (Do not exclude include directories made implicit by CPATH, 2019-05-29, v3.14.5~2^2) to cover include directories that are symlinks to paths listed in `CPATH`. Compare resolved paths against resolved entries of `CPATH`. Resolve the entries as late as possible in case symlinks change. Fixes: #22383 --- Source/cmLocalGenerator.cxx | 16 +++++++++++++--- Source/cmLocalGenerator.h | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 30df4c49a83..3d36acdd7c0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -109,7 +109,7 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) cmSystemTools::GetPath(cpath, "CPATH"); for (std::string const& cp : cpath) { if (cmSystemTools::FileIsFullPath(cp)) { - this->EnvCPATH.emplace(cmSystemTools::CollapseFullPath(cp)); + this->EnvCPATH.emplace_back(cmSystemTools::CollapseFullPath(cp)); } } } @@ -1248,8 +1248,18 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( bool const isCorCxx = (lang == "C" || lang == "CXX"); + // Resolve symlinks in CPATH for comparison with resolved include paths. + // We do this here instead of when EnvCPATH is populated in case symlinks + // on disk have changed in the meantime. + std::set<std::string> resolvedEnvCPATH; + if (isCorCxx) { + for (std::string const& i : this->EnvCPATH) { + resolvedEnvCPATH.emplace(this->GlobalGenerator->GetRealPath(i)); + } + } + // Checks if this is not an excluded (implicit) include directory. - auto notExcluded = [this, &implicitSet, &implicitExclude, + auto notExcluded = [this, &implicitSet, &implicitExclude, &resolvedEnvCPATH, isCorCxx](std::string const& dir) -> bool { std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir); return @@ -1260,7 +1270,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // they are implicitly searched by the compiler. They are meant to be // user-specified directories that can be re-ordered or converted to // -isystem without breaking real compiler builtin headers. - || (isCorCxx && cm::contains(this->EnvCPATH, dir)); + || (isCorCxx && cm::contains(resolvedEnvCPATH, real_dir)); }; // Get the target-specific include directories. diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 993280ac2da..cafb34d279b 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -587,7 +587,7 @@ class cmLocalGenerator : public cmOutputConverter std::string::size_type ObjectPathMax; std::set<std::string> ObjectMaxPathViolations; - std::set<std::string> EnvCPATH; + std::vector<std::string> EnvCPATH; using GeneratorTargetMap = std::unordered_map<std::string, cmGeneratorTarget*>; From 0c1b9b3516b52b02497b83d41294941c6210f29b Mon Sep 17 00:00:00 2001 From: Ye Luo <yeluo@anl.gov> Date: Sun, 4 Jul 2021 14:44:49 -0500 Subject: [PATCH 0851/1519] FindMPI: Choose definitions for MPI_CXX_SKIP_MPICXX before first use Fixes: #22391 --- Modules/FindMPI.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index c48decbb9fb..744f5a9adf9 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -1443,6 +1443,7 @@ foreach(LANG IN ITEMS C CXX Fortran) set(MPI_CXX_SKIP_MPICXX FALSE CACHE BOOL "If true, the MPI-2 C++ bindings are disabled using definitions.") mark_as_advanced(MPI_CXX_SKIP_MPICXX) endif() + _MPI_adjust_compile_definitions(${LANG}) if(NOT (MPI_${LANG}_LIB_NAMES AND (MPI_${LANG}_INCLUDE_PATH OR MPI_${LANG}_INCLUDE_DIRS OR MPI_${LANG}_COMPILER_INCLUDE_DIRS))) set(MPI_${LANG}_TRIED_IMPLICIT FALSE) set(MPI_${LANG}_WORKS_IMPLICIT FALSE) @@ -1547,7 +1548,6 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() _MPI_assemble_libraries(${LANG}) - _MPI_adjust_compile_definitions(${LANG}) # We always create imported targets even if they're empty _MPI_create_imported_target(${LANG}) From 9ce235fe5d0c99bba534f3134225a2c259a17134 Mon Sep 17 00:00:00 2001 From: Marc Ruiz <marc.ruiz@gmail.com> Date: Tue, 6 Jul 2021 11:58:36 +0200 Subject: [PATCH 0852/1519] CPack/NSIS: Update language list in template Fixes: #22382 --- Modules/Internal/CPack/NSIS.template.in | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index 0a9c4877da4..848691f4410 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -564,21 +564,27 @@ FunctionEnd ;Languages !insertmacro MUI_LANGUAGE "English" ;first language is the default language + !insertmacro MUI_LANGUAGE "Afrikaans" !insertmacro MUI_LANGUAGE "Albanian" !insertmacro MUI_LANGUAGE "Arabic" + !insertmacro MUI_LANGUAGE "Asturian" !insertmacro MUI_LANGUAGE "Basque" !insertmacro MUI_LANGUAGE "Belarusian" !insertmacro MUI_LANGUAGE "Bosnian" !insertmacro MUI_LANGUAGE "Breton" !insertmacro MUI_LANGUAGE "Bulgarian" + !insertmacro MUI_LANGUAGE "Catalan" + !insertmacro MUI_LANGUAGE "Corsican" !insertmacro MUI_LANGUAGE "Croatian" !insertmacro MUI_LANGUAGE "Czech" !insertmacro MUI_LANGUAGE "Danish" !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "Esperanto" !insertmacro MUI_LANGUAGE "Estonian" !insertmacro MUI_LANGUAGE "Farsi" !insertmacro MUI_LANGUAGE "Finnish" !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "Galician" !insertmacro MUI_LANGUAGE "German" !insertmacro MUI_LANGUAGE "Greek" !insertmacro MUI_LANGUAGE "Hebrew" @@ -597,22 +603,29 @@ FunctionEnd !insertmacro MUI_LANGUAGE "Malay" !insertmacro MUI_LANGUAGE "Mongolian" !insertmacro MUI_LANGUAGE "Norwegian" + !insertmacro MUI_LANGUAGE "NorwegianNynorsk" + !insertmacro MUI_LANGUAGE "Pashto" !insertmacro MUI_LANGUAGE "Polish" !insertmacro MUI_LANGUAGE "Portuguese" !insertmacro MUI_LANGUAGE "PortugueseBR" !insertmacro MUI_LANGUAGE "Romanian" !insertmacro MUI_LANGUAGE "Russian" + !insertmacro MUI_LANGUAGE "ScotsGaelic" !insertmacro MUI_LANGUAGE "Serbian" !insertmacro MUI_LANGUAGE "SerbianLatin" !insertmacro MUI_LANGUAGE "SimpChinese" !insertmacro MUI_LANGUAGE "Slovak" !insertmacro MUI_LANGUAGE "Slovenian" !insertmacro MUI_LANGUAGE "Spanish" + !insertmacro MUI_LANGUAGE "SpanishInternational" !insertmacro MUI_LANGUAGE "Swedish" + !insertmacro MUI_LANGUAGE "Tatar" !insertmacro MUI_LANGUAGE "Thai" !insertmacro MUI_LANGUAGE "TradChinese" !insertmacro MUI_LANGUAGE "Turkish" !insertmacro MUI_LANGUAGE "Ukrainian" + !insertmacro MUI_LANGUAGE "Uzbek" + !insertmacro MUI_LANGUAGE "Vietnamese" !insertmacro MUI_LANGUAGE "Welsh" ;-------------------------------- From 84036d30d4bae01ed94602ebce7a404300fd7e5f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 7 Jul 2021 12:21:27 -0400 Subject: [PATCH 0853/1519] IntelLLVM: Fix C/C++ standard level flags on Windows In commit a90d2a9eed (IntelLLVM: Add support for Intel LLVM-based compilers, 2020-11-02, v3.20.0-rc1~89^2~20) we accidentally left out activation of the C/C++ standard level selection logic when IntelLLVM is targeting the MSVC ABI. Fixes: #22388 --- Modules/Compiler/IntelLLVM-C.cmake | 6 +----- Modules/Compiler/IntelLLVM-CXX.cmake | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake index beb713242fc..d69d0647783 100644 --- a/Modules/Compiler/IntelLLVM-C.cmake +++ b/Modules/Compiler/IntelLLVM-C.cmake @@ -55,8 +55,4 @@ else() set(CMAKE_C17_EXTENSION_COMPILE_OPTION "") endif() -if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - __compiler_check_default_language_standard(C 2020 17) -else() - set(CMAKE_C_STANDARD_DEFAULT "") -endif() +__compiler_check_default_language_standard(C 2020 17) diff --git a/Modules/Compiler/IntelLLVM-CXX.cmake b/Modules/Compiler/IntelLLVM-CXX.cmake index 4c0c26e2e9c..979988846d7 100644 --- a/Modules/Compiler/IntelLLVM-CXX.cmake +++ b/Modules/Compiler/IntelLLVM-CXX.cmake @@ -62,8 +62,4 @@ else() set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-Qstd=c++20") endif() -if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - __compiler_check_default_language_standard(CXX 2020 14) -else() - set(CMAKE_CXX_STANDARD_DEFAULT "") -endif() +__compiler_check_default_language_standard(CXX 2020 14) From 5115dd1e2c6651c7f4d5992d05300c248302886b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 7 Jul 2021 12:21:27 -0400 Subject: [PATCH 0854/1519] IntelLLVM: Fix C/C++ standard level flags on Windows In commit a90d2a9eed (IntelLLVM: Add support for Intel LLVM-based compilers, 2020-11-02, v3.20.0-rc1~89^2~20) we accidentally left out activation of the C/C++ standard level selection logic when IntelLLVM is targeting the MSVC ABI. Fixes: #22388 --- Modules/Compiler/IntelLLVM-C.cmake | 10 +++------- Modules/Compiler/IntelLLVM-CXX.cmake | 6 +----- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake index fce2971cacc..9b1c376b13c 100644 --- a/Modules/Compiler/IntelLLVM-C.cmake +++ b/Modules/Compiler/IntelLLVM-C.cmake @@ -49,10 +49,6 @@ else() set(CMAKE_C11_EXTENSION_COMPILE_OPTION "") endif() -if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - # FIXME: The compiler actually defaults to C17, but - # CMake does not yet model or detect that standard. - __compiler_check_default_language_standard(C 2020 11) -else() - set(CMAKE_C_STANDARD_DEFAULT "") -endif() +# FIXME: The compiler actually defaults to C17, but +# CMake does not yet model or detect that standard. +__compiler_check_default_language_standard(C 2020 11) diff --git a/Modules/Compiler/IntelLLVM-CXX.cmake b/Modules/Compiler/IntelLLVM-CXX.cmake index 4c0c26e2e9c..979988846d7 100644 --- a/Modules/Compiler/IntelLLVM-CXX.cmake +++ b/Modules/Compiler/IntelLLVM-CXX.cmake @@ -62,8 +62,4 @@ else() set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-Qstd=c++20") endif() -if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - __compiler_check_default_language_standard(CXX 2020 14) -else() - set(CMAKE_CXX_STANDARD_DEFAULT "") -endif() +__compiler_check_default_language_standard(CXX 2020 14) From 266fc8ada550a29d46fd35c2c147de2436137978 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 7 Jul 2021 13:22:16 -0400 Subject: [PATCH 0855/1519] FindCUDAToolkit: Properly document the version support --- Modules/FindCUDAToolkit.cmake | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 8801cb1bff2..7c3e9a9903d 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -75,12 +75,17 @@ The CUDA Toolkit search behavior uses the following order: (2) ensure that the correct ``nvcc`` executable shows up in ``$PATH`` for :command:`find_program` to find. +Arguments +^^^^^^^^^ + +``[<version>]`` + The ``[<version>]`` argument requests a version with which the package found + should be compatible. See :ref:`find_package version format <FIND_PACKAGE_VERSION_FORMAT>` + for more details. + Options ^^^^^^^ -``VERSION`` - If specified, describes the version of the CUDA Toolkit to search for. - ``REQUIRED`` If specified, configuration will error if a suitable CUDA Toolkit is not found. From 94cad518bcc0ad52cd1457f2d92cab9b8437f5b8 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 8 Jul 2021 00:01:09 -0400 Subject: [PATCH 0856/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 090efd6ace4..22a528ac727 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210707) +set(CMake_VERSION_PATCH 20210708) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 018d300ca03c6ecea6b6b15d8c5caa7693eef84b Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 7 Jul 2021 11:23:31 -0400 Subject: [PATCH 0857/1519] Check*CompilerFlag: Do not set result as a normal variable too This was previously fixed by commit d46590910c (Check*CompilerFlag: Do not set result as a normal variable too, 2020-09-21, v3.18.3~1^2^2), but was regressed by refactoring in commit 90dead024c (CheckCompilerFlag: unified way to check compiler flags per language, 2020-09-25, v3.19.0-rc1~88^2) due to the changes being developed concurrently. Fix it again, and add a test case. Fixes: #21207 --- Modules/Internal/CheckCompilerFlag.cmake | 1 - Tests/TryCompile/CMakeLists.txt | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Modules/Internal/CheckCompilerFlag.cmake b/Modules/Internal/CheckCompilerFlag.cmake index 6b2a11e5664..99efc372e1a 100644 --- a/Modules/Internal/CheckCompilerFlag.cmake +++ b/Modules/Internal/CheckCompilerFlag.cmake @@ -73,7 +73,6 @@ int main(void) { return 0; }]=]) foreach(v IN LISTS _locale_vars) set(ENV{${v}} ${_locale_vars_saved_${v}}) endforeach() - set(${_var} "${${_var}}" PARENT_SCOPE) endfunction () cmake_policy(POP) diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index 0c6b9382cc7..0d44f218400 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -305,11 +305,21 @@ unset(C_BOGUS_FLAG CACHE) include(CheckCCompilerFlag) CHECK_C_COMPILER_FLAG(${C_DD}-_this_is_not_a_flag_ C_BOGUS_FLAG) TEST_FAIL(C_BOGUS_FLAG "CHECK_C_COMPILER_FLAG() succeeded, but should have failed") +unset(C_BOGUS_FLAG CACHE) +if(DEFINED C_BOGUS_FLAG) + # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable + message(SEND_ERROR "CHECK_C_COMPILER_FLAG shouldn't construct C_BOGUS_FLAG as a normal variable") +endif() unset(CXX_BOGUS_FLAG CACHE) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG(${CXX_DD}-_this_is_not_a_flag_ CXX_BOGUS_FLAG) TEST_FAIL(CXX_BOGUS_FLAG "CHECK_CXX_COMPILER_FLAG() succeeded, but should have failed") +unset(CXX_BOGUS_FLAG CACHE) +if(DEFINED CXX_BOGUS_FLAG) + # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable + message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG shouldn't construct CXX_BOGUS_FLAG as a normal variable") +endif() if(CMAKE_C_COMPILER_ID STREQUAL "GNU") unset(C_STRICT_PROTOTYPES CACHE) From 8a93de080c7c053237b3f34bc4f8312434e524bf Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Thu, 8 Jul 2021 13:02:15 +0200 Subject: [PATCH 0858/1519] cmGeneratorTarget: Add method for LINKER: prefix translation --- Source/cmGeneratorTarget.cxx | 7 +++++++ Source/cmGeneratorTarget.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f035bd01fdb..300c13b557c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4461,6 +4461,13 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( // Last step: replace "LINKER:" prefixed elements by // actual linker wrapper + return this->ResolveLinkerWrapper(result, language); +} + +std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper( + std::vector<BT<std::string>>& result, const std::string& language) const +{ + // replace "LINKER:" prefixed elements by actual linker wrapper const std::string wrapper(this->Makefile->GetSafeDefinition( "CMAKE_" + language + (this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG" diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index e1909a4dce0..09f4167c764 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -498,6 +498,9 @@ class cmGeneratorTarget std::vector<BT<std::string>> GetLinkOptions( std::string const& config, std::string const& language) const; + std::vector<BT<std::string>>& ResolveLinkerWrapper( + std::vector<BT<std::string>>& result, const std::string& language) const; + void GetStaticLibraryLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const; From a2e9fe38e43bd73513cde410f83e53e0c31ec6d6 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin <eugene.shalygin@gmail.com> Date: Wed, 7 Jul 2021 14:41:34 +0200 Subject: [PATCH 0859/1519] find_package: Add variable to make package REQUIRED Add a `CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable is complement to `CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` with just the opposite behaviour: it turns non-required find_package call into the required one. While optional package dependencies usually result in simple and clean build logic, sometimes people want to be sure those optional dependencies will be found and used. Examples are reproducible builds and build instructions for 3rd parties. People choose to make find_package calls REQUIRED and put them behind an option(). Such workarounds blend build logic with build environment management and do not look elegant. --- Auxiliary/vim/syntax/cmake.vim | 1 + Help/command/find_package.rst | 11 +++++++-- Help/manual/cmake-packages.7.rst | 4 +++- Help/manual/cmake-variables.7.rst | 1 + .../release/dev/find_package-required-var.rst | 5 ++++ ...CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst | 2 ++ ...CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst | 14 +++++++++++ Source/cmFindPackageCommand.cxx | 24 ++++++++++++++++--- .../MissingNormalForceRequired-result.txt | 1 + .../MissingNormalForceRequired-stderr.txt | 20 ++++++++++++++++ .../MissingNormalForceRequired.cmake | 3 +++ .../RequiredOptionValuesClash-result.txt | 1 + .../RequiredOptionValuesClash-stderr.txt | 11 +++++++++ .../RequiredOptionValuesClash.cmake | 5 ++++ .../RunCMake/find_package/RunCMakeTest.cmake | 2 ++ 15 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/find_package-required-var.rst create mode 100644 Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst create mode 100644 Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt create mode 100644 Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt create mode 100644 Tests/RunCMake/find_package/MissingNormalForceRequired.cmake create mode 100644 Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt create mode 100644 Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt create mode 100644 Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index d2a04fec2b7..3cc26d0c9a1 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -2807,6 +2807,7 @@ syn keyword cmakeKWfind_package contained \ ABI \ BUNDLE \ CMAKE_DISABLE_FIND_PACKAGE_ + \ CMAKE_REQUIRE_FIND_PACKAGE_ \ CMAKE_FIND_ROOT_PATH_BOTH \ COMPONENTS \ CONFIG diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 3dfd62fc32c..7febd5d0a55 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -448,8 +448,15 @@ which the file is found. The :variable:`CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS` variable may be set to ``TRUE`` before calling ``find_package`` in order to resolve symbolic links and store the real path to the file. -Every non-REQUIRED ``find_package`` call can be disabled by setting the -:variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to ``TRUE``. +Every non-REQUIRED ``find_package`` call can be disabled or made REQUIRED: + +* Setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable + to ``TRUE`` disables the package. + +* Setting the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable + to ``TRUE`` makes the package REQUIRED. + +Setting both variables to ``TRUE`` simultaneously is an error. Package File Interface Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst index 4b2934a8edd..52621052b61 100644 --- a/Help/manual/cmake-packages.7.rst +++ b/Help/manual/cmake-packages.7.rst @@ -74,7 +74,9 @@ package. By setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to ``TRUE``, the ``<PackageName>`` package will not be searched, and will always -be ``NOTFOUND``. +be ``NOTFOUND``. Likewise, setting the +:variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` to ``TRUE`` will make the +package REQUIRED. .. _`Config File Packages`: diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 39fbbed39fc..8521657e41d 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -230,6 +230,7 @@ Variables that Change Behavior /variable/CMAKE_PROJECT_INCLUDE_BEFORE /variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE /variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE + /variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName /variable/CMAKE_SKIP_INSTALL_ALL_DEPENDENCY /variable/CMAKE_STAGING_PREFIX /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS diff --git a/Help/release/dev/find_package-required-var.rst b/Help/release/dev/find_package-required-var.rst new file mode 100644 index 00000000000..36935ef9e20 --- /dev/null +++ b/Help/release/dev/find_package-required-var.rst @@ -0,0 +1,5 @@ +find_package-required-var +------------------------- + +* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable was added + to turn a non-REQUIRED :command:`find_package` call into a REQUIRED one. diff --git a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst index ed600202ced..f77e939163a 100644 --- a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst +++ b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst @@ -14,3 +14,5 @@ the package has already been found in a previous CMake run, the variables which have been stored in the cache will still be there. In that case it is recommended to remove the cache variables for this package from the cache using the cache editor or :manual:`cmake(1)` ``-U`` + +See also the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable. diff --git a/Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst new file mode 100644 index 00000000000..893f1aec80d --- /dev/null +++ b/Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst @@ -0,0 +1,14 @@ +CMAKE_REQUIRE_FIND_PACKAGE_<PackageName> +---------------------------------------- + +.. versionadded:: 3.22 + +Variable for making :command:`find_package` call ``REQUIRED``. + +Every non-``REQUIRED`` :command:`find_package` call in a project can be +turned into ``REQUIRED`` by setting the variable +``CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>`` to ``TRUE``. +This can be used to assert assumptions about build environment and to +ensure the build will fail early if they do not hold. + +See also the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable. diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index fba736eed64..a0de74c8dc2 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -478,17 +478,35 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->VersionMaxPatch, this->VersionMaxTweak); } + const std::string makePackageRequiredVar = + cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name); + const bool makePackageRequiredSet = + this->Makefile->IsOn(makePackageRequiredVar); + if (makePackageRequiredSet) { + if (this->Required) { + this->Makefile->IssueMessage( + MessageType::WARNING, + cmStrCat("for module ", this->Name, + " already called with REQUIRED, thus ", + makePackageRequiredVar, " has no effect.")); + } else { + this->Required = true; + } + } + std::string disableFindPackageVar = cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name); if (this->Makefile->IsOn(disableFindPackageVar)) { if (this->Required) { this->SetError( - cmStrCat("for module ", this->Name, " called with REQUIRED, but ", - disableFindPackageVar, + cmStrCat("for module ", this->Name, + (makePackageRequiredSet + ? " was made REQUIRED with " + makePackageRequiredVar + : " called with REQUIRED, "), + " but ", disableFindPackageVar, " is enabled. A REQUIRED package cannot be disabled.")); return false; } - return true; } diff --git a/Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt b/Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt b/Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt new file mode 100644 index 00000000000..f6c0b44a039 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt @@ -0,0 +1,20 @@ +CMake Error at MissingNormalForceRequired.cmake:2 \(find_package\): + No "FindNotHere.cmake" found in CMAKE_MODULE_PATH\. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Warning \(dev\) at MissingNormalForceRequired.cmake:2 \(find_package\): + FindNotHere.cmake must either be part of this project itself, in this case + adjust CMAKE_MODULE_PATH so that it points to the correct location inside + its source tree\. + + Or it must be installed by a package which has already been found via + find_package\(\)\. In this case make sure that package has indeed been found + and adjust CMAKE_MODULE_PATH to contain the location where that package has + installed FindNotHere\.cmake\. This must be a location provided by that + package. This error in general means that the buildsystem of this project + is relying on a Find-module without ensuring that it is actually available\. + +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/find_package/MissingNormalForceRequired.cmake b/Tests/RunCMake/find_package/MissingNormalForceRequired.cmake new file mode 100644 index 00000000000..5935316c839 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingNormalForceRequired.cmake @@ -0,0 +1,3 @@ +set(CMAKE_REQUIRE_FIND_PACKAGE_NotHere ON) +find_package(NotHere MODULE) +message(FATAL_ERROR "This error must not be reachable.") diff --git a/Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt b/Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt b/Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt new file mode 100644 index 00000000000..b4fdd98d218 --- /dev/null +++ b/Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at RequiredOptionValuesClash.cmake:4 \(find_package\): + find_package for module Foo was made REQUIRED with + CMAKE_REQUIRE_FIND_PACKAGE_Foo but CMAKE_DISABLE_FIND_PACKAGE_Foo is + enabled. A REQUIRED package cannot be disabled. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Error at RequiredOptionValuesClash.cmake:5 \(message\): + This error must not be reachable\. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake b/Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake new file mode 100644 index 00000000000..04fece72974 --- /dev/null +++ b/Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake @@ -0,0 +1,5 @@ +set(CMAKE_DISABLE_FIND_PACKAGE_Foo ON) +set(CMAKE_REQUIRE_FIND_PACKAGE_Foo ON) + +find_package(Foo) +message(FATAL_ERROR "This error must not be reachable.") diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index 3ba04c8bd77..b20a88950cd 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -6,6 +6,7 @@ run_cmake(ComponentRequiredAndOptional) run_cmake(FromPATHEnv) run_cmake(FromPrefixPath) run_cmake(MissingNormal) +run_cmake(MissingNormalForceRequired) run_cmake(MissingNormalRequired) run_cmake(MissingNormalVersion) run_cmake(MissingNormalWarnNoModuleOld) @@ -23,6 +24,7 @@ run_cmake(PackageRootNestedConfig) run_cmake(PackageRootNestedModule) run_cmake(PolicyPush) run_cmake(PolicyPop) +run_cmake(RequiredOptionValuesClash) run_cmake(SetFoundFALSE) run_cmake(WrongVersion) run_cmake(WrongVersionConfig) From bf810c75ac1dd2302daf71538550134210d64b3c Mon Sep 17 00:00:00 2001 From: Jean-Marc Hengen <jean-marc.hengen@zuehlke.com> Date: Wed, 7 Jul 2021 22:32:44 +0200 Subject: [PATCH 0860/1519] IAR: Use placeholders in linker and archiver rules Update the IAR linker and archiver rules to use the `<CMAKE_LINKER>` and `<CMAKE_AR>` placeholders instead of hard-coding the tool names. Fixes: #22395 --- Modules/Compiler/IAR.cmake | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index b8c07700919..8bfc3efe409 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -66,10 +66,10 @@ macro(__compiler_iar_ilink lang) string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG") endif() - set(CMAKE_${lang}_LINK_EXECUTABLE "\"${CMAKE_IAR_LINKER}\" --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") - set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "\"${CMAKE_IAR_ARCHIVE}\" <TARGET> --create <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_IAR_ARCHIVE}\" <TARGET> --create <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_APPEND "\"${CMAKE_IAR_ARCHIVE}\" <TARGET> --replace <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> <TARGET> --replace <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_FINISH "") set(CMAKE_LINKER "${CMAKE_IAR_LINKER}" CACHE FILEPATH "The IAR linker" FORCE) @@ -102,9 +102,9 @@ macro(__compiler_iar_xlink lang) string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG") endif() - set(CMAKE_${lang}_LINK_EXECUTABLE "\"${CMAKE_IAR_LINKER}\" -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") - set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "\"${CMAKE_IAR_AR}\" <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_IAR_AR}\" <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_APPEND "") set(CMAKE_${lang}_ARCHIVE_FINISH "") From 627aca946b991165c55ed04e4dd5cf013c473e58 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 8 Jul 2021 08:31:43 -0400 Subject: [PATCH 0861/1519] Help: Document when OBJC_STANDARD values as definition list --- Help/prop_tgt/OBJC_STANDARD.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Help/prop_tgt/OBJC_STANDARD.rst b/Help/prop_tgt/OBJC_STANDARD.rst index 2143ff92d97..2d27bcf0005 100644 --- a/Help/prop_tgt/OBJC_STANDARD.rst +++ b/Help/prop_tgt/OBJC_STANDARD.rst @@ -9,7 +9,16 @@ This property specifies the OBJC standard whose features are requested to build this target. For some compilers, this results in adding a flag such as ``-std=gnu11`` to the compile line. -Supported values are ``90``, ``99`` and ``11``. +Supported values are: + +``90`` + Objective C89/C90 + +``99`` + Objective C99 + +``11`` + Objective C11 If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This From bdb59839b989c3262725ddac62ac96432c435394 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 7 Jul 2021 13:55:49 -0400 Subject: [PATCH 0862/1519] Help: Document when OBJCXX_STANDARD values were added --- Help/prop_tgt/OBJCXX_STANDARD.rst | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Help/prop_tgt/OBJCXX_STANDARD.rst b/Help/prop_tgt/OBJCXX_STANDARD.rst index 96088af9616..654e6877d99 100644 --- a/Help/prop_tgt/OBJCXX_STANDARD.rst +++ b/Help/prop_tgt/OBJCXX_STANDARD.rst @@ -9,7 +9,27 @@ This property specifies the ObjC++ standard whose features are requested to build this target. For some compilers, this results in adding a flag such as ``-std=gnu++11`` to the compile line. -Supported values are ``98``, ``11``, ``14``, ``17``, ``20``, ``23``. +Supported values are: + +``98`` + Objective C++98 + +``11`` + Objective C++11 + +``14`` + Objective C++14 + +``17`` + Objective C++17 + +``20`` + Objective C++20 + +``23`` + .. versionadded:: 3.20 + + Objective C++23 If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This From d69b46bf01f30fdd8a1484c36bc159617df97b62 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 7 Jul 2021 13:56:12 -0400 Subject: [PATCH 0863/1519] Help: Document when CUDA_STANDARD values were added Note that some CUDA C++ language standard levels were added before any compilers actually supported them. In such cases, the value of `CUDA_STANDARD` gracefully degrades to the highest supported by the compiler (unless `CUDA_STANDARD_REQUIRED` is enabled). Therefore we can document support for each value based on when CMake learned of it. --- Help/prop_tgt/CUDA_STANDARD.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst index 6517035a297..5ef57be70c2 100644 --- a/Help/prop_tgt/CUDA_STANDARD.rst +++ b/Help/prop_tgt/CUDA_STANDARD.rst @@ -9,7 +9,29 @@ This property specifies the CUDA/C++ standard whose features are requested to build this target. For some compilers, this results in adding a flag such as ``-std=gnu++11`` to the compile line. -Supported values are ``98``, ``03``, ``11``, ``14``, ``17``, ``20``, ``23``. +Supported values are: + +``98`` + CUDA C++98 + +``11`` + CUDA C++11 + +``14`` + CUDA C++14 + +``17`` + CUDA C++17 + +``20`` + .. versionadded:: 3.12 + + CUDA C++20 + +``23`` + .. versionadded:: 3.20 + + CUDA C++23 If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This From 4c757fa3c8a8d5bc32b8d169b2ebfb7781f3ea0c Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Thu, 8 Jul 2021 09:17:21 -0400 Subject: [PATCH 0864/1519] Help/prop_test/ENVIRONMENT: clarify the scope of the changes The "restored" bit is an implementation detail as it could also be implemented by passing a crafted environment to `execve` or `CreateProcess` arguments. Instead, state that the environment changes only affects the test with the property set. --- Help/prop_test/ENVIRONMENT.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/prop_test/ENVIRONMENT.rst b/Help/prop_test/ENVIRONMENT.rst index 102c7922f6b..43bcdbe1b01 100644 --- a/Help/prop_test/ENVIRONMENT.rst +++ b/Help/prop_test/ENVIRONMENT.rst @@ -5,5 +5,5 @@ Specify environment variables that should be defined for running a test. If set to a list of environment variables and values of the form ``MYVAR=value`` those environment variables will be defined while running -the test. The environment is restored to its previous state after the -test is done. +the test. The environment changes from this property do not affect other +tests. From 2df4badc5f5902ae6808cb3c4b0c3c8484686b5d Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Mon, 5 Jul 2021 11:37:02 -0400 Subject: [PATCH 0865/1519] Help: Note PROJECT_IS_TOP_LEVEL behavior w.r.t. ExternalProject Extend the documentation added by commit 96a7040107 (project: Define variables indicating whether project is top level, 2021-03-24, v3.21.0-rc1~443^2) to give some examples of how the variables are set in each context. --- Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst | 10 ++++++++++ Help/variable/PROJECT_IS_TOP_LEVEL.rst | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst b/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst index 953e9783fd5..6718ecfd95a 100644 --- a/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst +++ b/Help/variable/PROJECT-NAME_IS_TOP_LEVEL.rst @@ -9,3 +9,13 @@ level ``CMakeLists.txt`` file. To obtain the value from the most recent call to :command:`project` in the current directory scope or above, see the :variable:`PROJECT_IS_TOP_LEVEL` variable. + +The variable value will be true in: + +* the top-level directory of the project +* the top-level directory of an external project added by :module:`ExternalProject` + +The variable value will be false in: + +* a directory added by :command:`add_subdirectory` +* a directory added by :module:`FetchContent` diff --git a/Help/variable/PROJECT_IS_TOP_LEVEL.rst b/Help/variable/PROJECT_IS_TOP_LEVEL.rst index e5eb6c1231e..ad61fecc059 100644 --- a/Help/variable/PROJECT_IS_TOP_LEVEL.rst +++ b/Help/variable/PROJECT_IS_TOP_LEVEL.rst @@ -19,3 +19,13 @@ options: if(PROJECT_IS_TOP_LEVEL) include(CTest) endif() + +The variable value will be true in: + +* the top-level directory of the project +* the top-level directory of an external project added by :module:`ExternalProject` + +The variable value will be false in: + +* a directory added by :command:`add_subdirectory` +* a directory added by :module:`FetchContent` From 554ebf643dfad2eb6877c3d5530b005cee453513 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 8 Jul 2021 09:46:27 -0400 Subject: [PATCH 0866/1519] CMake 3.21.0-rc3 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7542fa149d5..65bdb2cb9a0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 2) +set(CMake_VERSION_RC 3) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 854dcb0d01676f444d0aae9e6a095a80c5819496 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Thu, 8 Jul 2021 23:10:06 +0900 Subject: [PATCH 0867/1519] cmMakefile: Split out CreateNewTarget from AddNewTarget `CreateNewTarget` tells whether the target is inserted or not. --- Source/cmMakefile.cxx | 20 ++++++++++++++------ Source/cmMakefile.h | 5 +++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f6ecf8e3f46..7ac51133777 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2118,15 +2118,23 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName, cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, const std::string& name) { - auto it = this->Targets - .emplace(name, - cmTarget(name, type, cmTarget::VisibilityNormal, this, - cmTarget::PerConfig::Yes)) - .first; + return &this->CreateNewTarget(name, type).first; +} + +std::pair<cmTarget&, bool> cmMakefile::CreateNewTarget( + const std::string& name, cmStateEnums::TargetType type, + cmTarget::PerConfig perConfig) +{ + auto ib = this->Targets.emplace( + name, cmTarget(name, type, cmTarget::VisibilityNormal, this, perConfig)); + auto it = ib.first; + if (!ib.second) { + return std::make_pair(std::ref(it->second), false); + } this->OrderedTargets.push_back(&it->second); this->GetGlobalGenerator()->IndexTarget(&it->second); this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name); - return &it->second; + return std::make_pair(std::ref(it->second), true); } cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 14c1a0fc6f1..5886c86ef4a 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -13,6 +13,7 @@ #include <stack> #include <string> #include <unordered_map> +#include <utility> #include <vector> #include <cm/optional> @@ -230,6 +231,10 @@ class cmMakefile cmTarget* AddImportedTarget(const std::string& name, cmStateEnums::TargetType type, bool global); + std::pair<cmTarget&, bool> CreateNewTarget( + const std::string& name, cmStateEnums::TargetType type, + cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes); + cmTarget* AddNewTarget(cmStateEnums::TargetType type, const std::string& name); From 8a812dde61e0c309184100ef5d80fb2047c7d6b0 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Thu, 8 Jul 2021 23:10:06 +0900 Subject: [PATCH 0868/1519] cmGlobalGenerator: Use cmMakefile::CreateNewTarget to add global targets `cmMakefile::CreateNewTarget` updates also `cmMakefile::OrderedTargets`. --- Source/cmGlobalGenerator.cxx | 21 ++++++++++++--------- Source/cmGlobalGenerator.h | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index cad7855aa83..5d3fdce0cf7 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1263,10 +1263,8 @@ void cmGlobalGenerator::Configure() this->CreateDefaultGlobalTargets(globalTargets); for (const auto& mf : this->Makefiles) { - auto& targets = mf->GetTargets(); for (GlobalTargetInfo const& globalTarget : globalTargets) { - targets.emplace(globalTarget.Name, - this->CreateGlobalTarget(globalTarget, mf.get())); + this->CreateGlobalTarget(globalTarget, mf.get()); } } } @@ -2824,12 +2822,19 @@ bool cmGlobalGenerator::UseFolderProperty() const return false; } -cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, - cmMakefile* mf) +void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, + cmMakefile* mf) { // Package - cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET, - cmTarget::VisibilityNormal, mf, gti.PerConfig); + auto tb = + mf->CreateNewTarget(gti.Name, cmStateEnums::GLOBAL_TARGET, gti.PerConfig); + + // Do nothing if gti.Name is already used + if (!tb.second) { + return; + } + + cmTarget& target = tb.first; target.SetProperty("EXCLUDE_FROM_ALL", "TRUE"); std::vector<std::string> no_outputs; @@ -2853,8 +2858,6 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, if (this->UseFolderProperty()) { target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder()); } - - return target; } std::string cmGlobalGenerator::GenerateRuleFile( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 147146e134d..f0b59bf25df 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -596,7 +596,7 @@ class cmGlobalGenerator void AddGlobalTarget_RebuildCache( std::vector<GlobalTargetInfo>& targets) const; void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets); - cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf); + void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf); std::string FindMakeProgramFile; std::string ConfiguredFilesPath; From 9e9ab61e2ff248cd7b0b702decd4f967cd7becdf Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4civic@gmail.com> Date: Thu, 24 Jun 2021 18:42:53 +0900 Subject: [PATCH 0869/1519] cmGlobalGenerator: Process targets in a stable order `cmMakefile::Targets` is meant for efficient lookup but does not have a stable order. Use `cmMakefile::OrderedTargets` instead. --- Source/cmGlobalGenerator.cxx | 5 ++--- Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 5d3fdce0cf7..15a73045b65 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1781,9 +1781,8 @@ void cmGlobalGenerator::CreateGeneratorTargets( std::map<cmTarget*, cmGeneratorTarget*> const& importedMap) { if (targetTypes == AllTargets) { - for (auto& target : mf->GetTargets()) { - cmTarget* t = &target.second; - lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(t, lg)); + for (cmTarget* target : mf->GetOrderedTargets()) { + lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(target, lg)); } } diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt index 95fc5caeca6..39415afa308 100644 --- a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt +++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt @@ -1,3 +1,3 @@ -CMake Error: Bad parameter for VS_DPI_AWARE: Bar CMake Error: Bad parameter for VS_DPI_AWARE: Foo +CMake Error: Bad parameter for VS_DPI_AWARE: Bar CMake Generate step failed. Build files cannot be regenerated correctly. From a5e865c178b0ce3f273c1131972d8c3733deac4b Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 9 Jul 2021 00:01:15 -0400 Subject: [PATCH 0870/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 22a528ac727..acafe1ed270 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210708) +set(CMake_VERSION_PATCH 20210709) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0de1f1503bfdc990a7e6f62e6b486c872838e85d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 9 Jul 2021 07:48:55 -0400 Subject: [PATCH 0871/1519] FindJPEG: Revert "Search for 'turbojpeg' and 'turbojpeg-static' too" Revert commit 74cc2e3326 (FindJPEG: Search for 'turbojpeg' and 'turbojpeg-static' too, 2021-01-09, v3.20.0-rc1~176^2) pending further investigation. The "turbo" variants are not drop-in replacements on all platforms. Fixes: #22333 --- Modules/FindJPEG.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindJPEG.cmake b/Modules/FindJPEG.cmake index add2486c365..3f243ded577 100644 --- a/Modules/FindJPEG.cmake +++ b/Modules/FindJPEG.cmake @@ -58,7 +58,7 @@ Obsolete variables find_path(JPEG_INCLUDE_DIR jpeglib.h) -set(jpeg_names ${JPEG_NAMES} jpeg jpeg-static libjpeg libjpeg-static turbojpeg turbojpeg-static) +set(jpeg_names ${JPEG_NAMES} jpeg jpeg-static libjpeg libjpeg-static) foreach(name ${jpeg_names}) list(APPEND jpeg_names_debug "${name}d") endforeach() From bb5fc38209df343490be31dd34a65816b0799b59 Mon Sep 17 00:00:00 2001 From: Lisa Welsch <lisa.welsch@etm.at> Date: Thu, 8 Jul 2021 15:12:36 +0200 Subject: [PATCH 0872/1519] CPack/RPM: Add option to set %global __requires_exclude_from --- Help/cpack_gen/rpm.rst | 11 +++++++++++ Help/release/dev/cpack-rpm-requires-exclude-from.rst | 6 ++++++ Modules/Internal/CPack/CPackRPM.cmake | 12 ++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 Help/release/dev/cpack-rpm-requires-exclude-from.rst diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst index 322ab68aa33..f6274f9dc93 100644 --- a/Help/cpack_gen/rpm.rst +++ b/Help/cpack_gen/rpm.rst @@ -1035,3 +1035,14 @@ Source RPM packaging has its own set of variables: example:: set(CPACK_RPM_BUILDREQUIRES "python >= 2.5.0, cmake >= 2.8") + +.. VARIABLE:: CPACK_RPM_REQUIRES_EXCLUDE_FROM + + * Mandatory : NO + * Default : - + + May be used to keep the dependency generator from scanning specific files + or directories for dependencies. Note that you can use a regular + expression that matches all of the directories or files, for example:: + + set(CPACK_RPM_REQUIRES_EXCLUDE_FROM "bin/libqsqloci.*\\.so.*") diff --git a/Help/release/dev/cpack-rpm-requires-exclude-from.rst b/Help/release/dev/cpack-rpm-requires-exclude-from.rst new file mode 100644 index 00000000000..71259015cde --- /dev/null +++ b/Help/release/dev/cpack-rpm-requires-exclude-from.rst @@ -0,0 +1,6 @@ +cpack-rpm-requires-exclude-from +------------------------------- + +* The :cpack_gen:`CPack RPM Generator` gained the + :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option avoid scanning + specific paths for dependencies. diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index 47d2a5c7fee..bfb42f30489 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -1162,6 +1162,16 @@ function(cpack_rpm_generate_package) set(TMP_RPM_SPEC_INSTALL_POST "%define __spec_install_post ${CPACK_RPM_SPEC_INSTALL_POST}") endif() + # CPACK_RPM_REQUIRES_EXCLUDE_FROM + # May be defined to keep the dependency generator from + # scanning specific files or directories for deps. + if(CPACK_RPM_REQUIRES_EXCLUDE_FROM) + if(CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: User defined CPACK_RPM_REQUIRES_EXCLUDE_FROM = ${CPACK_RPM_REQUIRES_EXCLUDE_FROM}") + endif() + set(TMP_RPM_REQUIRES_EXCLUDE_FROM "%global __requires_exclude_from ${CPACK_RPM_REQUIRES_EXCLUDE_FROM}") + endif() + # CPACK_RPM_POST_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE) # CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE) # CPACK_RPM_POST_TRANS_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_TRANS_SCRIPT_FILE) @@ -1650,6 +1660,7 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ \@FILE_NAME_DEFINE\@ %define _unpackaged_files_terminate_build 0 \@TMP_RPM_SPEC_INSTALL_POST\@ +\@TMP_RPM_REQUIRES_EXCLUDE_FROM\@ \@CPACK_RPM_SPEC_MORE_DEFINE\@ \@CPACK_RPM_COMPRESSION_TYPE_TMP\@ @@ -1784,6 +1795,7 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@ \@FILE_NAME_DEFINE\@ %define _unpackaged_files_terminate_build 0 \@TMP_RPM_SPEC_INSTALL_POST\@ +\@TMP_RPM_REQUIRES_EXCLUDE_FROM\@ \@CPACK_RPM_SPEC_MORE_DEFINE\@ \@CPACK_RPM_COMPRESSION_TYPE_TMP\@ From de4f1f26b0a3217f7caf842c50857b1ac90d9b7d Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Fri, 2 Jul 2021 09:54:38 -0400 Subject: [PATCH 0873/1519] CTest: add an ENVIRONMENT_MODIFICATION property This property allows projects to modify environment variables at test time rather than trying to guess what the state should be based on what is present at configure time. Of particular interest is the ability to use a `PATH` present at test time while adding entries known to be necessary for the test itself. There are multiple operations provided to modify variables, including: - setting and unsetting - appending and prepending as: - strings - path lists - CMake lists Additionally, a `reset` action is provided to cancel any prior modifications to that particular variable in the case of incremental additions to the test property. --- Auxiliary/vim/syntax/cmake.vim | 1 + Help/manual/cmake-properties.7.rst | 1 + Help/prop_test/ENVIRONMENT_MODIFICATION.rst | 33 ++++ .../dev/ctest-environment-modifications.rst | 7 + Source/CTest/cmCTestMultiProcessHandler.cxx | 5 + Source/CTest/cmCTestRunTest.cxx | 145 +++++++++++++++++- Source/CTest/cmCTestRunTest.h | 1 + Source/CTest/cmCTestTestHandler.cxx | 2 + Source/CTest/cmCTestTestHandler.h | 1 + Tests/Environment/CMakeLists.txt | 35 +++++ Tests/Environment/check_mod.cmake | 55 +++++++ Tests/RunCMake/CMakeLists.txt | 1 + .../ctest_environment/CMakeLists.txt.in | 3 + ...RONMENT_MODIFICATION-invalid-op-result.txt | 1 + ...RONMENT_MODIFICATION-invalid-op-stderr.txt | 1 + .../ENVIRONMENT_MODIFICATION-invalid-op.cmake | 6 + ...VIRONMENT_MODIFICATION-no-colon-result.txt | 1 + ...VIRONMENT_MODIFICATION-no-colon-stderr.txt | 1 + .../ENVIRONMENT_MODIFICATION-no-colon.cmake | 6 + ...IRONMENT_MODIFICATION-no-equals-result.txt | 1 + ...IRONMENT_MODIFICATION-no-equals-stderr.txt | 1 + .../ENVIRONMENT_MODIFICATION-no-equals.cmake | 6 + .../ctest_environment/RunCMakeTest.cmake | 12 ++ .../RunCMake/ctest_environment/test.cmake.in | 16 ++ 24 files changed, 339 insertions(+), 3 deletions(-) create mode 100644 Help/prop_test/ENVIRONMENT_MODIFICATION.rst create mode 100644 Help/release/dev/ctest-environment-modifications.rst create mode 100644 Tests/Environment/check_mod.cmake create mode 100644 Tests/RunCMake/ctest_environment/CMakeLists.txt.in create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt create mode 100644 Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake create mode 100644 Tests/RunCMake/ctest_environment/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/ctest_environment/test.cmake.in diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index d2a04fec2b7..f936ca035bd 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -160,6 +160,7 @@ syn keyword cmakeProperty contained \ ENABLED_LANGUAGES \ ENABLE_EXPORTS \ ENVIRONMENT + \ ENVIRONMENT_MODIFICATION \ EXCLUDE_FROM_ALL \ EXCLUDE_FROM_DEFAULT_BUILD \ EXPORT_NAME diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 4212913a96f..c71e8ffdfbe 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -451,6 +451,7 @@ Properties on Tests /prop_test/DEPENDS /prop_test/DISABLED /prop_test/ENVIRONMENT + /prop_test/ENVIRONMENT_MODIFICATION /prop_test/FAIL_REGULAR_EXPRESSION /prop_test/FIXTURES_CLEANUP /prop_test/FIXTURES_REQUIRED diff --git a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst new file mode 100644 index 00000000000..ffd5de4afdb --- /dev/null +++ b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst @@ -0,0 +1,33 @@ +ENVIRONMENT_MODIFICATION +------------------------ + +Specify environment variables that should be modified for running a test. Note +that the operations performed by this property are performed after the +:prop_test:`ENVIRONMENT` property is already applied. + +If set to a list of environment variables and values of the form +``MYVAR=OP:VALUE``. Entries are considered in the order specified in the +property's value. The ``OP`` may be one of: + + - ``reset``: Reset to the unmodified value, ignoring all modifications to + ``MYVAR`` prior to this entry. Note that this will reset the variable to + the value set by :prop_test:`ENVIRONMENT`, if it was set, and otherwise + to its state from the rest of the CTest execution. + - ``set``: Replaces the current value of ``MYVAR`` with ``VALUE``. + - ``unset``: Unsets the current value of ``MYVAR``. + - ``string_append``: Appends ``VALUE`` to the current value of ``MYVAR``. + - ``string_prepend``: Prepends ``VALUE`` to the current value of ``MYVAR``. + - ``path_list_append``: Appends ``VALUE`` to the current value of ``MYVAR`` + using the platform-specific list separator. + - ``path_list_prepend``: Prepends ``VALUE`` to the current value of + ``MYVAR`` using the platform-specific list separator. + - ``cmake_list_append``: Appends ``VALUE`` to the current value of ``MYVAR`` + using ``;`` as the separator. + - ``cmake_list_prepend``: Prepends ``VALUE`` to the current value of + ``MYVAR`` using ``;`` as the separator. + +Unrecognized ``OP`` values will result in the test failing before it is +executed. This is so that future operations may be added without changing +valid behavior of existing tests. + +The environment changes from this property do not affect other tests. diff --git a/Help/release/dev/ctest-environment-modifications.rst b/Help/release/dev/ctest-environment-modifications.rst new file mode 100644 index 00000000000..64265f00d2d --- /dev/null +++ b/Help/release/dev/ctest-environment-modifications.rst @@ -0,0 +1,7 @@ +ctest-environment-modifications +------------------------------- + +* :manual:`ctest(1)` learned to be able to modify the environment for a test + through the :prop_test:`ENVIRONMENT_MODIFICATION` property. This is allows + for updates to environment variables based on the environment present at + test time. diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 86a8e00a626..d90c4a64651 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -1026,6 +1026,11 @@ static Json::Value DumpCTestProperties( properties.append(DumpCTestProperty( "ENVIRONMENT", DumpToJsonArray(testProperties.Environment))); } + if (!testProperties.EnvironmentModification.empty()) { + properties.append(DumpCTestProperty( + "ENVIRONMENT_MODIFICATION", + DumpToJsonArray(testProperties.EnvironmentModification))); + } if (!testProperties.ErrorRegularExpressions.empty()) { properties.append(DumpCTestProperty( "FAIL_REGULAR_EXPRESSION", diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 4e9b0f049b1..20f0ed3884c 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -8,12 +8,16 @@ #include <cstdint> #include <cstdio> #include <cstring> +#include <functional> #include <iomanip> #include <ratio> #include <sstream> #include <utility> #include <cm/memory> +#include <cm/optional> +#include <cm/string_view> +#include <cmext/string_view> #include "cmsys/RegularExpression.hxx" @@ -640,6 +644,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout, &this->TestProperties->Environment, + &this->TestProperties->EnvironmentModification, &this->TestProperties->Affinity); } @@ -696,6 +701,17 @@ void cmCTestRunTest::ComputeArguments() cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": " << env << std::endl); } + if (!this->TestProperties->EnvironmentModification.empty()) { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": " + << "Environment variable modifications: " + << std::endl); + } + for (std::string const& envmod : + this->TestProperties->EnvironmentModification) { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->Index << ": " << envmod << std::endl); + } } void cmCTestRunTest::ParseOutputForMeasurements() @@ -719,9 +735,11 @@ void cmCTestRunTest::ParseOutputForMeasurements() } } -bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, - std::vector<std::string>* environment, - std::vector<size_t>* affinity) +bool cmCTestRunTest::ForkProcess( + cmDuration testTimeOut, bool explicitTimeout, + std::vector<std::string>* environment, + std::vector<std::string>* environment_modification, + std::vector<size_t>* affinity) { this->TestProcess->SetId(this->Index); this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory); @@ -770,6 +788,127 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, } } + if (environment_modification && !environment_modification->empty()) { + std::map<std::string, cm::optional<std::string>> env_application; + +#ifdef _WIN32 + char path_sep = ';'; +#else + char path_sep = ':'; +#endif + + auto apply_diff = + [&env_application](const std::string& name, + std::function<void(std::string&)> const& apply) { + auto entry = env_application.find(name); + std::string output; + if (entry != env_application.end() && entry->second) { + output = *entry->second; + } + apply(output); + entry->second = output; + }; + + bool err_occurred = false; + + for (auto const& envmod : *environment_modification) { + // Split on `=` + auto const eq_loc = envmod.find_first_of('='); + if (eq_loc == std::string::npos) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error: Missing `=` after the variable name in: " + << envmod << std::endl); + err_occurred = true; + continue; + } + 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) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error: Missing `:` after the operation in: " << envmod + << std::endl); + err_occurred = true; + continue; + } + 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 = env_application.find(name); + if (entry != env_application.end()) { + env_application.erase(entry); + } + } else if (op == "set"_s) { + env_application[name] = value; + } else if (op == "unset"_s) { + env_application[name] = {}; + } 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 { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Error: Unrecognized environment manipulation argument: " + << op << std::endl); + err_occurred = true; + continue; + } + } + + if (err_occurred) { + return false; + } + + for (auto const& env_apply : env_application) { + if (env_apply.second) { + auto const env_update = + cmStrCat(env_apply.first, '=', *env_apply.second); + cmSystemTools::PutEnv(env_update); + envMeasurement << env_update << std::endl; + } else { + cmSystemTools::UnsetEnv(env_apply.first.c_str()); + // Signify that this variable is being actively unset + envMeasurement << "#" << env_apply.first << "=" << std::endl; + } + } + } + if (this->UseAllocatedResources) { std::vector<std::string> envLog; this->SetupResourcesEnvironment(&envLog); diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index a4981c3b286..2082156b8ff 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -113,6 +113,7 @@ class cmCTestRunTest void ExeNotFound(std::string exe); bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout, std::vector<std::string>* environment, + std::vector<std::string>* environment_modification, std::vector<size_t>* affinity); void WriteLogOutputTop(size_t completed, size_t total); // Run post processing of the process output for MemCheck diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 72b86c168d2..c29c124bacc 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -2245,6 +2245,8 @@ bool cmCTestTestHandler::SetTestsProperties( cmExpandList(val, rt.Depends); } else if (key == "ENVIRONMENT"_s) { cmExpandList(val, rt.Environment); + } else if (key == "ENVIRONMENT_MODIFICATION"_s) { + cmExpandList(val, rt.EnvironmentModification); } else if (key == "LABELS"_s) { std::vector<std::string> Labels = cmExpandedList(val); rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end()); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 1b42647f41c..f2da320b0b0 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -151,6 +151,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler // return code of test which will mark test as "not run" int SkipReturnCode; std::vector<std::string> Environment; + std::vector<std::string> EnvironmentModification; std::vector<std::string> Labels; std::set<std::string> LockedResources; std::set<std::string> FixturesSetup; diff --git a/Tests/Environment/CMakeLists.txt b/Tests/Environment/CMakeLists.txt index 2b18d24666a..17009bd838c 100644 --- a/Tests/Environment/CMakeLists.txt +++ b/Tests/Environment/CMakeLists.txt @@ -9,6 +9,7 @@ add_test(Environment1 Environment) add_test(Environment2 Environment) add_test(EchoEnvironment1 ${CMAKE_COMMAND} -E environment) add_test(EchoEnvironment2 ${CMAKE_COMMAND} -E environment) +add_test(EchoEnvironment3 ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/check_mod.cmake") # Make sure "CMAKE_ENV.*Happy Thanksgiving" is in the output of # the "1" tests: @@ -24,3 +25,37 @@ set_tests_properties(Environment1 EchoEnvironment1 PROPERTIES set_tests_properties(Environment2 EchoEnvironment2 PROPERTIES FAIL_REGULAR_EXPRESSION "CMAKE_ENV.*Happy Thanksgiving" ) + +set_property(TEST EchoEnvironment3 + PROPERTY ENVIRONMENT_MODIFICATION + # Variables expected to be unset. + "UNSET_EXPLICIT=set:value" + "UNSET_EXPLICIT=unset:" + "UNSET_VIA_RESET=set:value" + "UNSET_VIA_RESET=reset:" + + # Direct settings. + "DIRECT=set:old" + "DIRECT=set:new" + + # String manipulation. + "STRING_MANIP=set:-core-" + "STRING_MANIP=string_append:post-" + "STRING_MANIP=string_prepend:-pre" + "STRING_MANIP=string_append:suffix" + "STRING_MANIP=string_prepend:prefix" + + # Path manipulation. + "PATH_MANIP=set:core" + "PATH_MANIP=path_list_append:post" + "PATH_MANIP=path_list_prepend:pre" + "PATH_MANIP=path_list_append:suffix" + "PATH_MANIP=path_list_prepend:prefix" + + # CMake list manipulation. + "CMAKE_LIST_MANIP=set:core" + "CMAKE_LIST_MANIP=cmake_list_append:post" + "CMAKE_LIST_MANIP=cmake_list_prepend:pre" + "CMAKE_LIST_MANIP=cmake_list_append:suffix" + "CMAKE_LIST_MANIP=cmake_list_prepend:prefix" +) diff --git a/Tests/Environment/check_mod.cmake b/Tests/Environment/check_mod.cmake new file mode 100644 index 00000000000..16d02f26a95 --- /dev/null +++ b/Tests/Environment/check_mod.cmake @@ -0,0 +1,55 @@ +execute_process( + COMMAND ${CMAKE_COMMAND} -E environment + OUTPUT_VARIABLE out + ERROR_VARIABLE err + RESULT_VARIABLE res) + +if (res) + message(FATAL_ERROR "Failed with exit code ${res}: ${err}") +endif () + +if (CMAKE_HOST_WIN32) + set(path_sep ";") +else () + set(path_sep ":") +endif () + +set(unexpect_UNSET_EXPLICIT "") +set(unexpect_UNSET_VIA_RESET "") +set(expect_DIRECT "new") +set(expect_STRING_MANIP "prefix-pre-core-post-suffix") +set(expect_PATH_MANIP "prefix${path_sep}pre${path_sep}core${path_sep}post${path_sep}suffix") +set(expect_CMAKE_LIST_MANIP "prefix;pre;core;post;suffix") + +set(expected_vars + DIRECT + STRING_MANIP + PATH_MANIP + CMAKE_LIST_MANIP) + +while (out) + string(FIND "${out}" "\n" nl_pos) + string(SUBSTRING "${out}" 0 "${nl_pos}" line) + math(EXPR line_next "${nl_pos} + 1") + string(SUBSTRING "${out}" "${line_next}" -1 out) + + string(FIND "${line}" "=" eq_pos) + string(SUBSTRING "${line}" 0 "${eq_pos}" name) + math(EXPR value_start "${eq_pos} + 1") + string(SUBSTRING "${line}" "${value_start}" -1 value) + + if (DEFINED "unexpect_${name}") + message(SEND_ERROR "Found `${name}=${value}` when it should have been unset") + elseif (DEFINED "expect_${name}") + list(REMOVE_ITEM expected_vars "${name}") + if (expect_${name} STREQUAL value) + message(STATUS "Found `${name}=${value}` as expected") + else () + message(SEND_ERROR "Found `${name}=${value}` when it should have been ${expect_${name}}") + endif () + endif () +endwhile () + +if (expected_vars) + message(SEND_ERROR "Did not test expected variables: ${expected_vars}") +endif () diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 59fa9dcae3e..5e0fefd73f3 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -374,6 +374,7 @@ add_RunCMake_test(ctest_disabled_test) add_RunCMake_test(ctest_skipped_test) add_RunCMake_test(ctest_update) add_RunCMake_test(ctest_upload) +add_RunCMake_test(ctest_environment) add_RunCMake_test(ctest_fixtures) add_RunCMake_test(file -DMSYS=${MSYS}) add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) diff --git a/Tests/RunCMake/ctest_environment/CMakeLists.txt.in b/Tests/RunCMake/ctest_environment/CMakeLists.txt.in new file mode 100644 index 00000000000..c9c4a645efd --- /dev/null +++ b/Tests/RunCMake/ctest_environment/CMakeLists.txt.in @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.21.0) +project("@CASE_NAME@" NONE) +include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake") diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt new file mode 100644 index 00000000000..b57e2deb77b --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt new file mode 100644 index 00000000000..5b56d6fb0b4 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt @@ -0,0 +1 @@ +Error: Unrecognized environment manipulation argument: unknown diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake new file mode 100644 index 00000000000..d6ca4b2eed0 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake @@ -0,0 +1,6 @@ +include(CTest) +add_test(NAME cmake_version COMMAND "${CMAKE_COMMAND}" --version) + +set_property(TEST cmake_version + PROPERTY ENVIRONMENT_MODIFICATION + INVALID_OP=unknown:) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt new file mode 100644 index 00000000000..b57e2deb77b --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt new file mode 100644 index 00000000000..3ba6ba7b14a --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt @@ -0,0 +1 @@ +Error: Missing `:` after the operation in: MISSING_COLON=unset diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake new file mode 100644 index 00000000000..601dd8b40aa --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake @@ -0,0 +1,6 @@ +include(CTest) + +add_test(NAME cmake_version COMMAND "${CMAKE_COMMAND}" --version) +set_property(TEST cmake_version + PROPERTY ENVIRONMENT_MODIFICATION + MISSING_COLON=unset) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt new file mode 100644 index 00000000000..b57e2deb77b --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt new file mode 100644 index 00000000000..20bc9a59967 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt @@ -0,0 +1 @@ +Error: Missing `=` after the variable name in: MISSING_EQUAL diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake new file mode 100644 index 00000000000..18448cf4194 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake @@ -0,0 +1,6 @@ +include(CTest) + +add_test(NAME cmake_version COMMAND "${CMAKE_COMMAND}" --version) +set_property(TEST cmake_version + PROPERTY ENVIRONMENT_MODIFICATION + MISSING_EQUAL) diff --git a/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake new file mode 100644 index 00000000000..3447779f3b8 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake @@ -0,0 +1,12 @@ +include(RunCTest) + +# Isolate our ctest runs from external environment. +unset(ENV{CTEST_PARALLEL_LEVEL}) +unset(ENV{CTEST_OUTPUT_ON_FAILURE}) + +set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}") +set(RunCTest_VERBOSE_FLAG "-VV") + +run_ctest(ENVIRONMENT_MODIFICATION-invalid-op) +run_ctest(ENVIRONMENT_MODIFICATION-no-colon) +run_ctest(ENVIRONMENT_MODIFICATION-no-equals) diff --git a/Tests/RunCMake/ctest_environment/test.cmake.in b/Tests/RunCMake/ctest_environment/test.cmake.in new file mode 100644 index 00000000000..ca23c832fb7 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/test.cmake.in @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.7) + +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") + +set(ctest_test_args "@CASE_CTEST_TEST_ARGS@") +ctest_start(Experimental) +ctest_configure() +ctest_build() +ctest_test(${ctest_test_args}) From 9c5132a586562c00511fd8ff2bac0250c70dae95 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 9 Jul 2021 14:49:01 +0200 Subject: [PATCH 0874/1519] PGI: Fix "LINKER:" prefix generated separator Fix a typo from commit 66ea1a3795 (LINK_OPTIONS: Add support of "LINKER:" prefix, 2018-04-30, v3.13.0-rc1~437^2). --- Modules/Compiler/PGI.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Compiler/PGI.cmake b/Modules/Compiler/PGI.cmake index 4f8b90b13b8..d111be9ab61 100644 --- a/Modules/Compiler/PGI.cmake +++ b/Modules/Compiler/PGI.cmake @@ -26,7 +26,7 @@ macro(__compiler_pgi lang) endif() set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") - set(CMAKE_${lang}_LINKER_WRAPPER_FLAG ",") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le AND (NOT CMAKE_HOST_WIN32 OR CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 16.3)) From 14e57e9637964594461711954c6c906bc22eb7c7 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 2 Jul 2021 10:47:32 +0200 Subject: [PATCH 0875/1519] LINK_WHAT_YOU_USE feature: externalize configuration Currently, this feature is only supported on ELF platforms. So, the property LINK_WHAT_YOU_USE will be ignored for other plateforms. Moreover, flags and commands are now controled by CMake variables. Fixes: #20174 --- Help/manual/cmake-variables.7.rst | 2 ++ Help/prop_tgt/LINK_WHAT_YOU_USE.rst | 24 ++++++++----- .../dev/LINK_WHAT_USE_USE-configuration.rst | 5 +++ .../CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst | 9 +++++ Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst | 2 +- .../CMAKE_LINK_WHAT_YOU_USE_CHECK.rst | 10 ++++++ Modules/CMakeCInformation.cmake | 10 ++++-- Modules/CMakeCUDAInformation.cmake | 9 +++++ Modules/CMakeCXXInformation.cmake | 9 +++++ Modules/CMakeFortranInformation.cmake | 9 +++++ Modules/CMakeHIPInformation.cmake | 9 +++++ Modules/CMakeOBJCInformation.cmake | 9 +++++ Modules/CMakeOBJCXXInformation.cmake | 9 +++++ Modules/CMakeSwiftInformation.cmake | 9 +++++ Source/cmCommonTargetGenerator.h | 1 + Source/cmLocalGenerator.cxx | 24 +++++++++++++ Source/cmLocalGenerator.h | 2 ++ .../cmMakefileExecutableTargetGenerator.cxx | 23 +++++++----- Source/cmMakefileLibraryTargetGenerator.cxx | 25 +++++++------ Source/cmNinjaNormalTargetGenerator.cxx | 36 +++++++++++-------- Source/cmcmd.cxx | 11 +++--- 21 files changed, 195 insertions(+), 52 deletions(-) create mode 100644 Help/release/dev/LINK_WHAT_USE_USE-configuration.rst create mode 100644 Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst create mode 100644 Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 39fbbed39fc..02d0beba18f 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -427,6 +427,7 @@ Variables that Control the Build /variable/CMAKE_LANG_LINKER_LAUNCHER /variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG /variable/CMAKE_LANG_LINK_LIBRARY_FLAG + /variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG /variable/CMAKE_LANG_VISIBILITY_PRESET /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG @@ -437,6 +438,7 @@ Variables that Control the Build /variable/CMAKE_LINK_LIBRARY_FILE_FLAG /variable/CMAKE_LINK_LIBRARY_FLAG /variable/CMAKE_LINK_WHAT_YOU_USE + /variable/CMAKE_LINK_WHAT_YOU_USE_CHECK /variable/CMAKE_MACOSX_BUNDLE /variable/CMAKE_MACOSX_RPATH /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG diff --git a/Help/prop_tgt/LINK_WHAT_YOU_USE.rst b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst index 2ed93adfd97..d6de0d49c75 100644 --- a/Help/prop_tgt/LINK_WHAT_YOU_USE.rst +++ b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst @@ -1,16 +1,22 @@ LINK_WHAT_YOU_USE ---------------------------- +----------------- .. versionadded:: 3.7 -This is a boolean option that when set to ``TRUE`` will automatically run -``ldd -r -u`` on the target after it is linked. In addition, the linker flag -``-Wl,--no-as-needed`` will be passed to the target with the link command so -that all libraries specified on the command line will be linked into the -target. This will result in the link producing a list of libraries that -provide no symbols used by this target but are being linked to it. -This is only applicable to executable and shared library targets and -will only work when ld and ldd accept the flags used. +This is a boolean option that, when set to ``TRUE``, will automatically run +contents of variable :variable:`CMAKE_LINK_WHAT_YOU_USE_CHECK` on the target +after it is linked. In addition, the linker flag specified by variable +:variable:`CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG` will be passed to the target +with the link command so that all libraries specified on the command line will +be linked into the target. This will result in the link producing a list of +libraries that provide no symbols used by this target but are being linked to +it. + +.. note:: + + For now, it is only supported for ``ELF`` platforms and is only applicable to + executable and shared or module library targets. This property will be + ignored for any other targets and configurations. This property is initialized by the value of the :variable:`CMAKE_LINK_WHAT_YOU_USE` variable if it is set diff --git a/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst b/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst new file mode 100644 index 00000000000..990ed36e012 --- /dev/null +++ b/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst @@ -0,0 +1,5 @@ +LINK_WHAT_YOU_USE-configuration +------------------------------- + +* Configuration for :prop_tgt:`LINK_WHAT_YOU_USE` feature is now controlled by + ``CMake`` variables and only active for ``ELF`` platforms. diff --git a/Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst b/Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst new file mode 100644 index 00000000000..50045303968 --- /dev/null +++ b/Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst @@ -0,0 +1,9 @@ +CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG +----------------------------------- + +.. versionadded:: 3.22 + +Linker flag to be used to configure linker so that all specified libraries on +the command line will be linked into the target. + +See also variable :variable:`CMAKE_LINK_WHAT_YOU_USE_CHECK`. diff --git a/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst index 06b3aa89bad..bca4519a8fd 100644 --- a/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst +++ b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst @@ -1,5 +1,5 @@ CMAKE_LINK_WHAT_YOU_USE ---------------------------------- +----------------------- .. versionadded:: 3.7 diff --git a/Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst b/Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst new file mode 100644 index 00000000000..e626641bc80 --- /dev/null +++ b/Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst @@ -0,0 +1,10 @@ +CMAKE_LINK_WHAT_YOU_USE_CHECK +----------------------------- + +.. versionadded:: 3.22 + +Defines the command executed after the link step to check libraries usage. +This check is currently only defined on ``ELF`` platforms with value +``ldd -u -r``. + +See also :variable:`CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG` variables. diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index 6be1865755a..665f3092786 100644 --- a/Modules/CMakeCInformation.cmake +++ b/Modules/CMakeCInformation.cmake @@ -91,6 +91,14 @@ if(CMAKE_USER_MAKE_RULES_OVERRIDE_C) set(CMAKE_USER_MAKE_RULES_OVERRIDE_C "${_override}") endif() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_C_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_C_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() # for most systems a module is the same as a shared library # so unless the variable CMAKE_MODULE_EXISTS is set just @@ -196,5 +204,3 @@ if(NOT CMAKE_EXECUTABLE_RPATH_LINK_C_FLAG) endif() set(CMAKE_C_INFORMATION_LOADED 1) - - diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index a2946f45841..e9cfed607bf 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -100,6 +100,15 @@ if(NOT CMAKE_MODULE_EXISTS) set(CMAKE_SHARED_MODULE_CREATE_CUDA_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS}) endif() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_CUDA_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_CUDA_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + # add the flags to the cache based # on the initial values computed in the platform/*.cmake files # use _INIT variables so that this only happens the first time diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake index 944d236097c..53abf378d50 100644 --- a/Modules/CMakeCXXInformation.cmake +++ b/Modules/CMakeCXXInformation.cmake @@ -193,6 +193,15 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) endif() endforeach() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + # add the flags to the cache based # on the initial values computed in the platform/*.cmake files # use _INIT variables so that this only happens the first time diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake index 9a4ce6357b0..0f71c6f0472 100644 --- a/Modules/CMakeFortranInformation.cmake +++ b/Modules/CMakeFortranInformation.cmake @@ -157,6 +157,15 @@ if(NOT CMAKE_INCLUDE_FLAG_Fortran) set(CMAKE_INCLUDE_FLAG_Fortran ${CMAKE_INCLUDE_FLAG_C}) endif() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_Fortran_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_Fortran_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + set(CMAKE_VERBOSE_MAKEFILE FALSE CACHE BOOL "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo.") set(CMAKE_Fortran_FLAGS_INIT "$ENV{FFLAGS} ${CMAKE_Fortran_FLAGS_INIT}") diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake index ec37e1c91ae..9862f247fcf 100644 --- a/Modules/CMakeHIPInformation.cmake +++ b/Modules/CMakeHIPInformation.cmake @@ -68,6 +68,15 @@ if(NOT CMAKE_MODULE_EXISTS) set(CMAKE_SHARED_MODULE_CREATE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS}) endif() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_HIP_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_HIP_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + # add the flags to the cache based # on the initial values computed in the platform/*.cmake files # use _INIT variables so that this only happens the first time diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake index ac67d013cc4..4c697da3d1e 100644 --- a/Modules/CMakeOBJCInformation.cmake +++ b/Modules/CMakeOBJCInformation.cmake @@ -91,6 +91,15 @@ if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC) set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC "${_override}") endif() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_OBJC_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_OBJC_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + # for most systems a module is the same as a shared library # so unless the variable CMAKE_MODULE_EXISTS is set just diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake index 70e8579a90b..a6d824f102a 100644 --- a/Modules/CMakeOBJCXXInformation.cmake +++ b/Modules/CMakeOBJCXXInformation.cmake @@ -189,6 +189,15 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) endif() endforeach() +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_OBJCXX_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_OBJCXX_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + # add the flags to the cache based # on the initial values computed in the platform/*.cmake files # use _INIT variables so that this only happens the first time diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake index 8f0909c997c..ecad1d51e80 100644 --- a/Modules/CMakeSwiftInformation.cmake +++ b/Modules/CMakeSwiftInformation.cmake @@ -70,6 +70,15 @@ set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O") set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g") set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize") +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + if(NOT DEFINED CMAKE_Swift_LINK_WHAT_YOU_USE_FLAG) + set(CMAKE_Swift_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed") + endif() + if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK) + set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r) + endif() +endif() + cmake_initialize_per_config_variable(CMAKE_Swift_FLAGS "Swift Compiler Flags") # NOTE(compnerd) we do not have an object compile rule since we build the objects as part of the link step diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index a156a41aff0..e1a4f8bb5bf 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -40,6 +40,7 @@ class cmCommonTargetGenerator cmLocalCommonGenerator* LocalCommonGenerator; cmGlobalCommonGenerator* GlobalCommonGenerator; std::vector<std::string> ConfigNames; + bool UseLWYU = false; void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a14f0850f48..6b88a03d317 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3047,6 +3047,30 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags( } } +bool cmLocalGenerator::AppendLWYUFlags(std::string& flags, + const cmGeneratorTarget* target, + const std::string& lang) +{ + auto useLWYU = target->GetPropertyAsBool("LINK_WHAT_YOU_USE") && + (target->GetType() == cmStateEnums::TargetType::EXECUTABLE || + target->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY || + target->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY); + + if (useLWYU) { + const auto& lwyuFlag = this->GetMakefile()->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_LINK_WHAT_YOU_USE_FLAG")); + useLWYU = !lwyuFlag.empty(); + + if (useLWYU) { + std::vector<BT<std::string>> lwyuOpts; + lwyuOpts.emplace_back(lwyuFlag); + this->AppendFlags(flags, target->ResolveLinkerWrapper(lwyuOpts, lang)); + } + } + + return useLWYU; +} + void cmLocalGenerator::AppendCompileOptions(std::string& options, std::string const& options_list, const char* regex) const diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 993280ac2da..3c896f71014 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -171,6 +171,8 @@ class cmLocalGenerator : public cmOutputConverter cmGeneratorTarget* target, const std::string& config, const std::string& lang); + bool AppendLWYUFlags(std::string& flags, const cmGeneratorTarget* target, + const std::string& lang); enum class IncludePathStyle { diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 3a2744e3feb..306b38f6c1e 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -397,9 +397,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->GetLinkLibsCMP0065( linkLanguage, *this->GeneratorTarget)); - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed"); - } + this->UseLWYU = this->LocalGenerator->AppendLWYUFlags( + linkFlags, this->GeneratorTarget, linkLanguage); // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( @@ -577,12 +576,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.Launcher = linkerLauncher.c_str(); } - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - std::string cmakeCommand = - cmStrCat(this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), - " -E __run_co_compile --lwyu=", targetOutPathReal); - real_link_commands.push_back(std::move(cmakeCommand)); + if (this->UseLWYU) { + cmProp lwyuCheck = + this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + if (lwyuCheck) { + std::string cmakeCommand = cmStrCat( + this->LocalGenerator->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); + cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck); + cmakeCommand += cmStrCat(" --source=", targetOutPathReal); + real_link_commands.push_back(std::move(cmakeCommand)); + } } std::string launcher; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index d0e3837dd57..64992f2d4e5 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -178,9 +178,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, this->GetConfigName()); - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed"); - } + this->UseLWYU = this->LocalGenerator->AppendLWYUFlags( + extraFlags, this->GeneratorTarget, linkLanguage); + this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -871,13 +871,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Get the set of commands. std::string linkRule = this->GetLinkRule(linkRuleVar); cmExpandList(linkRule, real_link_commands); - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") && - (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) { - std::string cmakeCommand = cmStrCat( - this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), - " -E __run_co_compile --lwyu=", targetOutPathReal); - real_link_commands.push_back(std::move(cmakeCommand)); + if (this->UseLWYU) { + cmProp lwyuCheck = + this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + if (lwyuCheck) { + std::string cmakeCommand = cmStrCat( + this->LocalGenerator->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); + cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck); + cmakeCommand += cmStrCat(" --source=", targetOutPathReal); + real_link_commands.push_back(std::move(cmakeCommand)); + } } // Expand placeholders. diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 5a4c6521d84..93a54c25776 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -581,17 +581,23 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( } } cmExpandList(linkCmdStr, linkCmds); - if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - std::string cmakeCommand = cmStrCat( - this->GetLocalGenerator()->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), - " -E __run_co_compile --lwyu="); - cmGeneratorTarget& gt = *this->GetGeneratorTarget(); - std::string targetOutputReal = this->ConvertToNinjaPath( - gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, - /*realname=*/true)); - cmakeCommand += targetOutputReal; - linkCmds.push_back(std::move(cmakeCommand)); + if (this->UseLWYU) { + cmProp lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + if (lwyuCheck) { + std::string cmakeCommand = cmStrCat( + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); + cmakeCommand += + this->GetLocalGenerator()->EscapeForShell(*lwyuCheck); + + std::string targetOutputReal = + this->ConvertToNinjaPath(this->GetGeneratorTarget()->GetFullPath( + config, cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true)); + cmakeCommand += cmStrCat(" --source=", targetOutputReal); + linkCmds.push_back(std::move(cmakeCommand)); + } } return linkCmds; } @@ -1156,9 +1162,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], config); - if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - vars["LINK_FLAGS"] += " -Wl,--no-as-needed"; - } + + this->UseLWYU = this->GetLocalGenerator()->AppendLWYUFlags( + vars["LINK_FLAGS"], this->GetGeneratorTarget(), + this->TargetLinkLanguage(config)); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); vars["MANIFESTS"] = this->GetManifests(config); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 1f4c0b8052a..1e0f497d7c7 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -385,18 +385,15 @@ int HandleTidy(const std::string& runCmd, const std::string& sourceFile, return ret; } -int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */, +int HandleLWYU(const std::string& runCmd, const std::string& sourceFile, const std::vector<std::string>&) { // Construct the ldd -r -u (link what you use lwyu) command line // ldd -u -r lwuy target - std::vector<std::string> lwyu_cmd; - lwyu_cmd.emplace_back("ldd"); - lwyu_cmd.emplace_back("-u"); - lwyu_cmd.emplace_back("-r"); - lwyu_cmd.push_back(runCmd); + std::vector<std::string> lwyu_cmd = cmExpandedList(runCmd, true); + lwyu_cmd.push_back(sourceFile); - // Run the ldd -u -r command line. + // Run the lwyu check command line, currently ldd is expected. // Capture its stdout and hide its stderr. // Ignore its return code because the tool always returns non-zero // if there are any warnings, but we just want to warn. From 6eea123e3a97a6dce3b059777b688a49429bb951 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 9 Jul 2021 10:56:52 -0400 Subject: [PATCH 0876/1519] Tests: Fix RunCMake.try_compile C/CXX standards with IntelLLVM MSVC mode Since commit 84036d30d4 (IntelLLVM: Fix C/C++ standard level flags on Windows, 2021-07-07, v3.21.0-rc3~8^2~1) we activate C/C++ standard level logic for IntelLLVM when targeting the MSVC ABI. Update the `RunCMake.try_compile` test to be aware of this even when CMake is itself configured by an older CMake that does not know this. --- Tests/RunCMake/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index dafb174000c..86cb849fea2 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -443,6 +443,17 @@ function(add_RunCMake_test_try_compile) set(CMAKE_C_STANDARD_DEFAULT 11) endif() endif() + if(CMAKE_VERSION VERSION_LESS 3.20.6 AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xIntelLLVM" AND "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") + # Older CMake versions accidentally set the default standards to empty when + # IntelLLVM targets the MSVC ABI, thus not activating standard selection. + # Approximate the logic from IntelLLVM-{C,CXX}.cmake. + if(DEFINED CMAKE_C_STANDARD_DEFAULT AND "${CMAKE_C_STANDARD_DEFAULT}" STREQUAL "") + set(CMAKE_C_STANDARD_DEFAULT 17) + endif() + if(DEFINED CMAKE_CXX_STANDARD_DEFAULT AND "${CMAKE_CXX_STANDARD_DEFAULT}" STREQUAL "") + set(CMAKE_CXX_STANDARD_DEFAULT 14) + endif() + endif() foreach(var CMAKE_SYSTEM_NAME CMAKE_C_COMPILER_ID From 1c14691a86ab8c6939dd04707dc2a92125fa8629 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sun, 7 Feb 2021 11:27:21 +0200 Subject: [PATCH 0877/1519] CMakeCCompilerId: Fix C standard detection in Clang and IntelLLVM MSVC mode Clang does not define `__STDC__` if in MSVC compatibility mode, but does define `__STDC_VERSION__`. Avoid the fallback for this combination. This backports commit 7596d8b951 (CMakeCCompilerId: Fix C standard detection in Clang MSVC mode, 2021-02-07, v3.21.0-rc1~587^2~14) to the 3.20 release series. This is needed since commit 5115dd1e2c (IntelLLVM: Fix C/C++ standard level flags on Windows, 2021-07-07, v3.21.0-rc3~7^2^2) now that we activate C/C++ standard level logic for IntelLLVM when targeting the MSVC ABI. --- Modules/CMakeCCompilerId.c.in | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index 14e1282c835..0bc8f5adee7 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -33,9 +33,8 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; @CMAKE_C_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_C_COMPILER_ID_ERROR_FOR_TEST@ -#if !defined(__STDC__) -# if (defined(_MSC_VER) && !defined(__clang__)) \ - || (defined(__ibmxl__) || defined(__IBMC__)) +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) # define C_DIALECT "90" # else # define C_DIALECT From 1c227583a4d331de94d35dd0bab7c8a5fb1697cd Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 9 Jul 2021 10:56:52 -0400 Subject: [PATCH 0878/1519] Tests: Fix RunCMake.try_compile C/CXX standards with IntelLLVM MSVC mode Since commit 5115dd1e2c (IntelLLVM: Fix C/C++ standard level flags on Windows, 2021-07-07, v3.21.0-rc3~7^2^2) we activate C/C++ standard level logic for IntelLLVM when targeting the MSVC ABI. Update the `RunCMake.try_compile` test to be aware of this even when CMake is itself configured by an older CMake that does not know this. --- Tests/RunCMake/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index c81796cfa11..95f28f6734b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -420,6 +420,19 @@ function(add_RunCMake_test_try_compile) set(CMAKE_C_STANDARD_DEFAULT "") endif() endif() + if(CMAKE_VERSION VERSION_LESS 3.20.6 AND "x${CMAKE_C_COMPILER_ID}" STREQUAL "xIntelLLVM" AND "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") + # Older CMake versions accidentally set the default standards to empty when + # IntelLLVM targets the MSVC ABI, thus not activating standard selection. + # Approximate the logic from IntelLLVM-{C,CXX}.cmake. + if(DEFINED CMAKE_C_STANDARD_DEFAULT AND "${CMAKE_C_STANDARD_DEFAULT}" STREQUAL "") + # FIXME: The compiler actually defaults to C17, but + # CMake does not yet model or detect that standard. + set(CMAKE_C_STANDARD_DEFAULT 11) + endif() + if(DEFINED CMAKE_CXX_STANDARD_DEFAULT AND "${CMAKE_CXX_STANDARD_DEFAULT}" STREQUAL "") + set(CMAKE_CXX_STANDARD_DEFAULT 14) + endif() + endif() foreach(var CMAKE_SYSTEM_NAME CMAKE_C_COMPILER_ID From d1bece92d508edec5a390783ffb245acf22ac5ac Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 9 Jul 2021 17:31:20 +0200 Subject: [PATCH 0879/1519] UseSWIG: Use swig generated dependencies for Visual Studio --- Help/release/dev/UseSWIG-dependencies.rst | 6 ++++++ Modules/UseSWIG.cmake | 25 ++++++++++++++++------- Tests/UseSWIG/CMakeLists.txt | 2 +- 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 Help/release/dev/UseSWIG-dependencies.rst diff --git a/Help/release/dev/UseSWIG-dependencies.rst b/Help/release/dev/UseSWIG-dependencies.rst new file mode 100644 index 00000000000..a3ec29e713f --- /dev/null +++ b/Help/release/dev/UseSWIG-dependencies.rst @@ -0,0 +1,6 @@ +UseSWIG-dependencies +-------------------- + +* :module:`UseSWIG` module gained the capability, for + :ref:`Visual Studio Generators` to use `swig` tool to generate implicit + dependencies. diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 5c8f152bb7e..9808861cd26 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -192,12 +192,17 @@ ensure generated files will receive the required settings. If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool itself. This property is only meaningful for :ref:`Makefile <Makefile Generators>`, - :ref:`Ninja <Ninja Generators>` and :generator:`Xcode` generators. Default - value is ``FALSE``. + :ref:`Ninja <Ninja Generators>`, :generator:`Xcode`, and + :ref:`Visual Studio <Visual Studio Generators>` + (:generator:`Visual Studio 11 2012` and above) generators. Default value is + ``FALSE``. .. versionadded:: 3.21 Added the support of :generator:`Xcode` generator. + .. versionadded:: 3.22 + Added the support of :ref:`Visual Studio Generators`. + ``SWIG_MODULE_NAME`` Specify the actual import name of the module in the target language. This is required if it cannot be scanned automatically from source @@ -342,8 +347,10 @@ as well as ``SWIG``: If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool itself. This variable is only meaningful for :ref:`Makefile <Makefile Generators>`, - :ref:`Ninja <Ninja Generators>` and :generator:`Xcode` generators. Default - value is ``FALSE``. + :ref:`Ninja <Ninja Generators>`, :generator:`Xcode`, and + :ref:`Visual Studio <Visual Studio Generators>` + (:generator:`Visual Studio 11 2012` and above) generators. Default value is + ``FALSE``. Source file property ``USE_SWIG_DEPENDENCIES``, if not defined, will be initialized with the value of this variable. @@ -351,6 +358,9 @@ as well as ``SWIG``: .. versionadded:: 3.21 Added the support of :generator:`Xcode` generator. + .. versionadded:: 3.22 + Added the support of :ref:`Visual Studio Generators`. + #]=======================================================================] cmake_policy(PUSH) @@ -515,7 +525,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) endif() set (use_swig_dependencies ${SWIG_USE_SWIG_DEPENDENCIES}) - if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode") + if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode|Visual Studio (1[1-9]|[2-9][0-9])") get_property(use_swig_dependencies_set SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES SET) if (use_swig_dependencies_set) get_property(use_swig_dependencies SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES) @@ -840,8 +850,9 @@ function(SWIG_ADD_LIBRARY name) set(SWIG_SOURCE_FILE_EXTENSIONS ".i") endif() - if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode") - # For Makefiles and Ninja generators, use SWIG generated dependencies + if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode|Visual Studio (1[1-9]|[2-9][0-9])") + # For Makefiles, Ninja, Xcode and Visual Studio generators, + # use SWIG generated dependencies if requested if (NOT DEFINED SWIG_USE_SWIG_DEPENDENCIES) set (SWIG_USE_SWIG_DEPENDENCIES OFF) endif() diff --git a/Tests/UseSWIG/CMakeLists.txt b/Tests/UseSWIG/CMakeLists.txt index f1b2f321484..c3f9e033a7d 100644 --- a/Tests/UseSWIG/CMakeLists.txt +++ b/Tests/UseSWIG/CMakeLists.txt @@ -67,7 +67,7 @@ add_test(NAME UseSWIG.BasicPerl COMMAND --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2" - AND CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode") + AND CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode|Visual Studio (1[1-9]|[2-9][0-9])") add_test(NAME UseSWIG.Depfile.BasicPython COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test From 2e124fa22d41d76ba6d3bdb6243a729350b20720 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 9 Jul 2021 13:35:05 -0400 Subject: [PATCH 0880/1519] ci: add hip4.2 base image --- .gitlab/ci/docker/hip4.2/Dockerfile | 7 +++++++ .gitlab/ci/docker/hip4.2/install_deps.sh | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .gitlab/ci/docker/hip4.2/Dockerfile create mode 100755 .gitlab/ci/docker/hip4.2/install_deps.sh diff --git a/.gitlab/ci/docker/hip4.2/Dockerfile b/.gitlab/ci/docker/hip4.2/Dockerfile new file mode 100644 index 00000000000..563e94f4798 --- /dev/null +++ b/.gitlab/ci/docker/hip4.2/Dockerfile @@ -0,0 +1,7 @@ +FROM rocm/dev-ubuntu-20.04:4.2 +MAINTAINER Brad King <brad.king@kitware.com> + +ENV PATH="/opt/rocm/bin:$PATH" + +COPY install_deps.sh /root/install_deps.sh +RUN sh /root/install_deps.sh diff --git a/.gitlab/ci/docker/hip4.2/install_deps.sh b/.gitlab/ci/docker/hip4.2/install_deps.sh new file mode 100755 index 00000000000..2b45bc92863 --- /dev/null +++ b/.gitlab/ci/docker/hip4.2/install_deps.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +set -e + +apt-get update + +# Install development tools. +apt-get install -y --no-install-recommends \ + g++ \ + curl \ + git + +apt-get clean From 71ab24015f170493ab21bab48cb15d65506faad7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 9 Jul 2021 13:39:52 -0400 Subject: [PATCH 0881/1519] gitlab-ci: add job testing hip4.2 with Ninja Multi-Config --- .gitlab-ci.yml | 10 ++++++++++ .gitlab/ci/configure_hip4.2_radeon.cmake | 3 +++ .gitlab/os-linux.yml | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 .gitlab/ci/configure_hip4.2_radeon.cmake diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 857ef73fa24..a964b46da36 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -248,6 +248,16 @@ test:cuda10.2-clang: variables: CMAKE_CI_JOB_NIGHTLY: "true" +test:hip4.2-radeon: + extends: + - .hip4.2_radeon + - .cmake_test_linux_release + - .linux_builder_tags_radeon + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + build:fedora34-ninja: extends: - .fedora34_ninja diff --git a/.gitlab/ci/configure_hip4.2_radeon.cmake b/.gitlab/ci/configure_hip4.2_radeon.cmake new file mode 100644 index 00000000000..58036b05a02 --- /dev/null +++ b/.gitlab/ci/configure_hip4.2_radeon.cmake @@ -0,0 +1,3 @@ +set(CMake_TEST_HIP "ON" CACHE BOOL "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 65a4282cc42..1513c904dc1 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -245,6 +245,23 @@ CMAKE_CONFIGURATION: cuda10.2_clang CTEST_NO_WARNINGS_ALLOWED: 1 +### HIP builds + +.hip4.2: + image: "kitware/cmake:ci-hip4.2-x86_64-2021-07-09" + + variables: + GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" + CMAKE_ARCH: x86_64 + CTEST_LABELS: "HIP" + +.hip4.2_radeon: + extends: .hip4.2 + + variables: + CMAKE_CONFIGURATION: hip4.2_radeon + CMAKE_GENERATOR: "Ninja Multi-Config" + ## Tags .linux_builder_tags: @@ -277,6 +294,13 @@ - docker - linux +.linux_builder_tags_radeon: + tags: + - cmake + - radeon + - docker + - linux + .linux_builder_tags_aarch64: tags: - cmake From 4f5957d72d32a6518b2fac0eba00e8e5b8931c70 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 10 Jul 2021 00:01:09 -0400 Subject: [PATCH 0882/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index acafe1ed270..19d219c78fc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210709) +set(CMake_VERSION_PATCH 20210710) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3c521b89f1a4d10a55a142d74e4eab02716943a0 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 11 Jul 2021 00:01:06 -0400 Subject: [PATCH 0883/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 19d219c78fc..f5c16bfd60e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210710) +set(CMake_VERSION_PATCH 20210711) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 52a73d1654603671cc9be70771f3dea5dfbdffed Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 12 Jul 2021 00:01:19 -0400 Subject: [PATCH 0884/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f5c16bfd60e..1029ed84fb6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210711) +set(CMake_VERSION_PATCH 20210712) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2114d717a0aa76684f5d95e60453175a5ba22059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= <sergio.martins@kdab.com> Date: Sat, 10 Jul 2021 15:21:59 +0100 Subject: [PATCH 0885/1519] Help: Fix preset example cmakeMinimumRequired Since commit 8bc5c8961e (CMakePresets.json: Add the ability to conditionally disable presets, 2021-03-10, v3.21.0-rc1~464^2) the example requires presets version 3 support, which is not available until CMake 3.21. CMake 3.20.0 can't open v3 presets. Make cmakeMinimumRequired compatible with the example's version. --- Help/manual/presets/example.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json index 346f3425126..b08445a471d 100644 --- a/Help/manual/presets/example.json +++ b/Help/manual/presets/example.json @@ -2,7 +2,7 @@ "version": 3, "cmakeMinimumRequired": { "major": 3, - "minor": 20, + "minor": 21, "patch": 0 }, "configurePresets": [ From 57dcde19da24d211bad945fbbe7851abbf9bdab3 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 12 Jul 2021 14:57:06 +0000 Subject: [PATCH 0886/1519] Find{BLAS,LAPACK}: Avoid clobbering results when no vendor is requested Logic added by commit 4c74c86f40 (FindBLAS/LAPACK: Add support for the Fujitsu SSL2 library, 2021-01-27, v3.21.0-rc1~402^2~1) accidentally expressed a boolean condition without proper grouping. The pattern was then copied by commit 2c9e623e31 (Find{BLAS,LAPACK}: Add support for the NVHPC LAPACK library, 2021-05-05, v3.21.0-rc1~192^2). The resulting logic incorrectly tries Fujitsu and NVHPC vendors even after results are found from another vendor, and then erases those. Fix the grouping. Fixes: #22403 --- Modules/FindBLAS.cmake | 4 ++-- Modules/FindLAPACK.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index e04831803d0..726ff75bf88 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -1110,8 +1110,8 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") endif() # Fujitsu SSL2 Library? -if(NOT BLAS_LIBRARIES AND - BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All") +if(NOT BLAS_LIBRARIES + AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All")) if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP") set(_ssl2_suffix BLAMP) else() diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index b8a33636561..3146e06d44e 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -550,7 +550,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # Fujitsu SSL2 Library? if(NOT LAPACK_LIBRARIES - AND BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All") + AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All")) if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP") set(_ssl2_suffix BLAMP) else() @@ -582,7 +582,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # NVHPC Library? if(NOT LAPACK_LIBRARIES - AND BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All") + AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All")) check_lapack_libraries( LAPACK_LIBRARIES LAPACK From 31ac4b916525126c5d7f3a944a749b8989a456c5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 12 Jul 2021 11:08:35 -0400 Subject: [PATCH 0887/1519] ci: Verify that Intel MKL is found when it is the only BLAS/LAPACK Issue: #22403 --- .gitlab/ci/configure_intelcompiler_common.cmake | 12 ++++++++---- Tests/FindBLAS/CMakeLists.txt | 14 ++++++++++++-- Tests/FindBLAS/Test/CMakeLists.txt | 3 ++- Tests/FindLAPACK/CMakeLists.txt | 14 ++++++++++++-- Tests/FindLAPACK/Test/CMakeLists.txt | 3 ++- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake index df3a69615d1..be175e42d5d 100644 --- a/.gitlab/ci/configure_intelcompiler_common.cmake +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -1,6 +1,10 @@ -set(CMake_TEST_FindBLAS "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindLAPACK "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC "Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindBLAS "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindBLAS_All "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindBLAS_STATIC_All "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindLAPACK "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindLAPACK_All "Intel10_64lp" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") +set(CMake_TEST_FindLAPACK_STATIC_All "Intel10_64lp" CACHE STRING "") include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt index 31c701e4b3a..482cee876e3 100644 --- a/Tests/FindBLAS/CMakeLists.txt +++ b/Tests/FindBLAS/CMakeLists.txt @@ -6,6 +6,11 @@ foreach(variant IN LISTS CMake_TEST_FindBLAS) set(vendor "${variant}") set(alt_compiler "") endif() + if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_All) + set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_All}") + else() + set(EXPECT_All "") + endif() add_test(NAME FindBLAS.Test_${variant} COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test @@ -13,7 +18,7 @@ foreach(variant IN LISTS CMake_TEST_FindBLAS) "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}" ${build_generator_args} --build-project TestFindBLAS - --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} + --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) endforeach() @@ -26,6 +31,11 @@ foreach(variant IN LISTS CMake_TEST_FindBLAS_STATIC) set(vendor "${variant}") set(alt_compiler "") endif() + if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_STATIC_All) + set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_STATIC_All}") + else() + set(EXPECT_All "") + endif() add_test(NAME FindBLAS.Test_${variant}_Static COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test @@ -33,7 +43,7 @@ foreach(variant IN LISTS CMake_TEST_FindBLAS_STATIC) "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}_Static" ${build_generator_args} --build-project TestFindBLAS - --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON + --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) endforeach() diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt index 98e12d5947c..73797496a80 100644 --- a/Tests/FindBLAS/Test/CMakeLists.txt +++ b/Tests/FindBLAS/Test/CMakeLists.txt @@ -12,7 +12,8 @@ add_executable(test_var main.c) target_link_libraries(test_var PRIVATE ${BLAS_LIBRARIES}) add_test(NAME test_var COMMAND test_var) -if(BLA_VENDOR STREQUAL "Intel10_64lp") +if((BLA_VENDOR STREQUAL "Intel10_64lp") OR + (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64lp")) if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64") message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_lp64:\n ${BLAS_LIBRARIES}") endif() diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt index 26cfa87629d..535c7b60e2a 100644 --- a/Tests/FindLAPACK/CMakeLists.txt +++ b/Tests/FindLAPACK/CMakeLists.txt @@ -6,6 +6,11 @@ foreach(variant IN LISTS CMake_TEST_FindLAPACK) set(vendor "${variant}") set(alt_compiler "") endif() + if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_All) + set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_All}") + else() + set(EXPECT_All "") + endif() add_test(NAME FindLAPACK.Test_${variant} COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test @@ -13,7 +18,7 @@ foreach(variant IN LISTS CMake_TEST_FindLAPACK) "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}" ${build_generator_args} --build-project TestFindLAPACK - --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} + --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) endforeach() @@ -26,6 +31,11 @@ foreach(variant IN LISTS CMake_TEST_FindLAPACK_STATIC) set(vendor "${variant}") set(alt_compiler "") endif() + if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_STATIC_All) + set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_STATIC_All}") + else() + set(EXPECT_All "") + endif() add_test(NAME FindLAPACK.Test_${variant}_Static COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test @@ -33,7 +43,7 @@ foreach(variant IN LISTS CMake_TEST_FindLAPACK_STATIC) "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}_Static" ${build_generator_args} --build-project TestFindLAPACK - --build-options ${build_options} ${alt_compiler} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON + --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) endforeach() diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt index bb334824bc2..23a43acec49 100644 --- a/Tests/FindLAPACK/Test/CMakeLists.txt +++ b/Tests/FindLAPACK/Test/CMakeLists.txt @@ -12,7 +12,8 @@ add_executable(test_var main.c) target_link_libraries(test_var PRIVATE ${LAPACK_LIBRARIES}) add_test(NAME test_var COMMAND test_var) -if(BLA_VENDOR STREQUAL "Intel10_64lp") +if((BLA_VENDOR STREQUAL "Intel10_64lp") OR + (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64lp")) if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64") message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_lp64:\n ${LAPACK_LIBRARIES}") endif() From 542bd343e3eb5b824046649c0335a56dd2497f8e Mon Sep 17 00:00:00 2001 From: Asit Dhal <dhal.asitk@gmail.com> Date: Sun, 11 Jul 2021 20:33:01 +0200 Subject: [PATCH 0888/1519] VS: Always enable CMAKE_MSVCIDE_RUN_PATH Do not require a language to be enabled. Fixes: #22343 --- Source/cmLocalVisualStudioGenerator.cxx | 2 +- Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt | 3 +++ .../CheckEnvironmentVar-build-stdout.txt | 1 + .../CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake | 2 ++ Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake | 8 ++++++++ Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat | 1 + Tests/RunCMake/CMakeLists.txt | 1 + 7 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt create mode 100644 Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt create mode 100644 Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake create mode 100644 Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake create mode 100755 Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 002f484bcbb..46f9d315f1a 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -171,7 +171,7 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( // for visual studio IDE add extra stuff to the PATH // if CMAKE_MSVCIDE_RUN_PATH is set. - if (this->Makefile->GetDefinition("MSVC_IDE")) { + if (this->GetGlobalGenerator()->IsVisualStudio()) { cmProp extraPath = this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH"); if (extraPath) { script += newline; diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt new file mode 100644 index 00000000000..bbc08e6f400 --- /dev/null +++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.21) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt new file mode 100644 index 00000000000..f0f2efc27a7 --- /dev/null +++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt @@ -0,0 +1 @@ +This message is printed by echo_message.bat diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake new file mode 100644 index 00000000000..63d6068a911 --- /dev/null +++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake @@ -0,0 +1,2 @@ +set(CMAKE_MSVCIDE_RUN_PATH "${CMAKE_SOURCE_DIR}") +add_custom_target(main COMMAND echo_message) diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake new file mode 100644 index 00000000000..a424ff214a4 --- /dev/null +++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake @@ -0,0 +1,8 @@ +include(RunCMake) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CheckEnvironmentVar-build) +run_cmake(CheckEnvironmentVar) +set(RunCMake_TEST_NO_CLEAN 1) +run_cmake_command(CheckEnvironmentVar-build ${CMAKE_COMMAND} --build . --config Debug --target main) +unset(RunCMake_TEST_BINARY_DIR) +unset(RunCMake_TEST_NO_CLEAN) diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat new file mode 100755 index 00000000000..9037d02f1ac --- /dev/null +++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat @@ -0,0 +1 @@ +echo This message is printed by echo_message.bat diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 59fa9dcae3e..de01ba6813c 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -544,6 +544,7 @@ if(CMake_TEST_FindGTK2) endif() if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") + add_RunCMake_test(CMAKE_MSVCIDE_RUN_PATH) add_RunCMake_test(include_external_msproject -DVS_PLATFORM_NAME=${CMAKE_VS_PLATFORM_NAME}) if("${CMAKE_GENERATOR}" MATCHES "Visual Studio (9|10)" AND NOT CMAKE_VS_DEVENV_COMMAND) set(NO_USE_FOLDERS 1) From 113cc4c684a7fba7bb72284d654e8615b201a018 Mon Sep 17 00:00:00 2001 From: earnal <etienne.arnal@gmail.com> Date: Fri, 9 Jul 2021 22:45:01 +0000 Subject: [PATCH 0889/1519] libuv: Allow windows UNC path with forward slashes Fix libuv issue 3159 in CMake while integration in upstream libuv is pending. Fixes: #22141 --- Utilities/cmlibuv/src/win/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c index 04718dbdb2f..aada889e16d 100644 --- a/Utilities/cmlibuv/src/win/process.c +++ b/Utilities/cmlibuv/src/win/process.c @@ -169,7 +169,10 @@ static WCHAR* search_path_join_test(const WCHAR* dir, size_t cwd_len) { WCHAR *result, *result_pos; DWORD attrs; - if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') { + if ( + (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') || + (dir_len > 2 && dir[0] == L'/' && dir[1] == L'/') + ) { /* It's a UNC path so ignore cwd */ cwd_len = 0; } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) { From 2065bd73cb6a9a3bc463c5bb0dc6877433782973 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 2 Jul 2021 14:12:45 -0400 Subject: [PATCH 0890/1519] cmState: Construct with mode --- Source/CTest/cmCTestTestHandler.cxx | 2 +- Source/cmState.cxx | 12 ++++-------- Source/cmState.h | 15 +++++++-------- Source/cmake.cxx | 3 +-- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 72b86c168d2..b60a664ef47 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -2165,7 +2165,7 @@ bool cmCTestTestHandler::SetTestsProperties( // Ensure we have complete triples otherwise the data is corrupt. if (triples.size() % 3 == 0) { - cmState state; + cmState state(cmState::Unknown); rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot()); // the first entry represents the top of the trace so we need to diff --git a/Source/cmState.cxx b/Source/cmState.cxx index ce6eb311e6f..b235abd4e41 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -26,7 +26,8 @@ #include "cmSystemTools.h" #include "cmake.h" -cmState::cmState() +cmState::cmState(Mode mode) + : StateMode(mode) { this->CacheManager = cm::make_unique<cmCacheManager>(); this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>(); @@ -771,17 +772,12 @@ unsigned int cmState::GetCacheMinorVersion() const cmState::Mode cmState::GetMode() const { - return this->CurrentMode; + return this->StateMode; } std::string cmState::GetModeString() const { - return ModeToString(this->CurrentMode); -} - -void cmState::SetMode(cmState::Mode mode) -{ - this->CurrentMode = mode; + return ModeToString(this->StateMode); } std::string cmState::ModeToString(cmState::Mode mode) diff --git a/Source/cmState.h b/Source/cmState.h index 9951b9acfee..c7f6a1e0185 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -35,12 +35,6 @@ class cmState friend class cmStateSnapshot; public: - cmState(); - ~cmState(); - - cmState(const cmState&) = delete; - cmState& operator=(const cmState&) = delete; - enum Mode { Unknown, @@ -51,6 +45,12 @@ class cmState CPack, }; + cmState(Mode mode); + ~cmState(); + + cmState(const cmState&) = delete; + cmState& operator=(const cmState&) = delete; + static const std::string& GetTargetTypeName( cmStateEnums::TargetType targetType); @@ -207,7 +207,6 @@ class cmState Mode GetMode() const; std::string GetModeString() const; - void SetMode(Mode mode); static std::string ModeToString(Mode mode); @@ -258,5 +257,5 @@ class cmState bool NMake = false; bool MSYSShell = false; bool NinjaMulti = false; - Mode CurrentMode = Unknown; + Mode StateMode = Unknown; }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 73f5ad5b87b..a2b2571be84 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -162,11 +162,10 @@ cmake::cmake(Role role, cmState::Mode mode) #ifndef CMAKE_BOOTSTRAP , VariableWatch(cm::make_unique<cmVariableWatch>()) #endif - , State(cm::make_unique<cmState>()) + , State(cm::make_unique<cmState>(mode)) , Messenger(cm::make_unique<cmMessenger>()) { this->TraceFile.close(); - this->State->SetMode(mode); this->CurrentSnapshot = this->State->CreateBaseSnapshot(); #ifdef __APPLE__ From 6c440ea3ce36d4c5b1629f111f376e809c7e99b2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 2 Jul 2021 14:23:38 -0400 Subject: [PATCH 0891/1519] cmake: Model normal and try-compile project kinds explicitly Construct with the project kind instead of mutating state after construction. --- Source/cmListFileCache.cxx | 4 ++-- Source/cmMakefile.cxx | 4 ++-- Source/cmState.cxx | 23 ++++++++++------------- Source/cmState.h | 15 ++++++++++----- Source/cmake.cxx | 17 ++++++----------- Source/cmake.h | 4 ++-- 6 files changed, 32 insertions(+), 35 deletions(-) diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 4f7c9594441..2e444f229e3 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -548,7 +548,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const } cmListFileContext lfc = this->TopEntry->Context; cmStateSnapshot bottom = this->GetBottom(); - if (!bottom.GetState()->GetIsInTryCompile()) { + if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) { lfc.FilePath = cmSystemTools::RelativeIfUnder( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } @@ -579,7 +579,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const out << "Call Stack (most recent call first):\n"; } cmListFileContext lfc = cur->Context; - if (!bottom.GetState()->GetIsInTryCompile()) { + if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) { lfc.FilePath = cmSystemTools::RelativeIfUnder( bottom.GetState()->GetSourceDirectory(), lfc.FilePath); } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 7ac51133777..6d477a7660b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3567,8 +3567,8 @@ int cmMakefile::TryCompile(const std::string& srcdir, // make sure the same generator is used // use this program as the cmake to be run, it should not // be run that way but the cmake object requires a vailid path - cmake cm(cmake::RoleProject, cmState::Project); - cm.SetIsInTryCompile(true); + cmake cm(cmake::RoleProject, cmState::Project, + cmState::ProjectKind::TryCompile); auto gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); if (!gg) { this->IssueMessage(MessageType::INTERNAL_ERROR, diff --git a/Source/cmState.cxx b/Source/cmState.cxx index b235abd4e41..bdb5bda1939 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -26,8 +26,9 @@ #include "cmSystemTools.h" #include "cmake.h" -cmState::cmState(Mode mode) +cmState::cmState(Mode mode, ProjectKind projectKind) : StateMode(mode) + , StateProjectKind(projectKind) { this->CacheManager = cm::make_unique<cmCacheManager>(); this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>(); @@ -382,16 +383,6 @@ void cmState::ClearEnabledLanguages() this->EnabledLanguages.clear(); } -bool cmState::GetIsInTryCompile() const -{ - return this->IsInTryCompile; -} - -void cmState::SetIsInTryCompile(bool b) -{ - this->IsInTryCompile = b; -} - bool cmState::GetIsGeneratorMultiConfig() const { return this->IsGeneratorMultiConfig; @@ -594,8 +585,9 @@ cmProp cmState::GetGlobalProperty(const std::string& prop) std::vector<std::string> commands = this->GetCommandNames(); this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str()); } else if (prop == "IN_TRY_COMPILE") { - this->SetGlobalProperty("IN_TRY_COMPILE", - this->IsInTryCompile ? "1" : "0"); + this->SetGlobalProperty( + "IN_TRY_COMPILE", + this->StateProjectKind == ProjectKind::TryCompile ? "1" : "0"); } else if (prop == "GENERATOR_IS_MULTI_CONFIG") { this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG", this->IsGeneratorMultiConfig ? "1" : "0"); @@ -799,6 +791,11 @@ std::string cmState::ModeToString(cmState::Mode mode) return "UNKNOWN"; } +cmState::ProjectKind cmState::GetProjectKind() const +{ + return this->StateProjectKind; +} + std::string const& cmState::GetBinaryDirectory() const { return this->BinaryDirectory; diff --git a/Source/cmState.h b/Source/cmState.h index c7f6a1e0185..8561fc0c4fd 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -45,7 +45,13 @@ class cmState CPack, }; - cmState(Mode mode); + enum class ProjectKind + { + Normal, + TryCompile, + }; + + cmState(Mode mode, ProjectKind projectKind = ProjectKind::Normal); ~cmState(); cmState(const cmState&) = delete; @@ -141,9 +147,6 @@ class cmState void SetEnabledLanguages(std::vector<std::string> const& langs); void ClearEnabledLanguages(); - bool GetIsInTryCompile() const; - void SetIsInTryCompile(bool b); - bool GetIsGeneratorMultiConfig() const; void SetIsGeneratorMultiConfig(bool b); @@ -210,6 +213,8 @@ class cmState static std::string ModeToString(Mode mode); + ProjectKind GetProjectKind() const; + private: friend class cmake; void AddCacheEntry(const std::string& key, const char* value, @@ -247,7 +252,6 @@ class cmState std::string SourceDirectory; std::string BinaryDirectory; - bool IsInTryCompile = false; bool IsGeneratorMultiConfig = false; bool WindowsShell = false; bool WindowsVSIDE = false; @@ -258,4 +262,5 @@ class cmState bool MSYSShell = false; bool NinjaMulti = false; Mode StateMode = Unknown; + ProjectKind StateProjectKind = ProjectKind::Normal; }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a2b2571be84..ab8309d6824 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -156,13 +156,13 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, } #endif -cmake::cmake(Role role, cmState::Mode mode) +cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind) : CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory()) , FileTimeCache(cm::make_unique<cmFileTimeCache>()) #ifndef CMAKE_BOOTSTRAP , VariableWatch(cm::make_unique<cmVariableWatch>()) #endif - , State(cm::make_unique<cmState>(mode)) + , State(cm::make_unique<cmState>(mode, projectKind)) , Messenger(cm::make_unique<cmMessenger>()) { this->TraceFile.close(); @@ -1842,7 +1842,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) std::vector<std::string> argsSplit = cmExpandedList(var, true); // erase the property to avoid infinite recursion this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", ""); - if (this->State->GetIsInTryCompile()) { + if (this->GetIsInTryCompile()) { return 0; } std::vector<SaveCacheEntry> saved; @@ -2110,7 +2110,7 @@ int cmake::ActualConfigure() // 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 - if (!this->State->GetIsInTryCompile()) { + if (!this->GetIsInTryCompile()) { this->GlobalGenerator->ClearEnabledLanguages(); this->TruncateOutputLog("CMakeOutput.log"); @@ -2621,19 +2621,14 @@ void cmake::SetProgressCallback(ProgressCallbackType f) void cmake::UpdateProgress(const std::string& msg, float prog) { - if (this->ProgressCallback && !this->State->GetIsInTryCompile()) { + if (this->ProgressCallback && !this->GetIsInTryCompile()) { this->ProgressCallback(msg, prog); } } bool cmake::GetIsInTryCompile() const { - return this->State->GetIsInTryCompile(); -} - -void cmake::SetIsInTryCompile(bool b) -{ - this->State->SetIsInTryCompile(b); + return this->State->GetProjectKind() == cmState::ProjectKind::TryCompile; } void cmake::AppendGlobalGeneratorsDocumentation( diff --git a/Source/cmake.h b/Source/cmake.h index 5a2a88fac7f..12cce7e8ed0 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -168,7 +168,8 @@ class cmake static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0; /// Default constructor - cmake(Role role, cmState::Mode mode); + cmake(Role role, cmState::Mode mode, + cmState::ProjectKind projectKind = cmState::ProjectKind::Normal); /// Destructor ~cmake(); @@ -356,7 +357,6 @@ class cmake //! Is this cmake running as a result of a TRY_COMPILE command bool GetIsInTryCompile() const; - void SetIsInTryCompile(bool b); #ifndef CMAKE_BOOTSTRAP void SetWarningFromPreset(const std::string& name, From b2c03347b07e24a5298361451277264fda8fdb4c Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Mon, 12 Jul 2021 15:38:43 -0400 Subject: [PATCH 0892/1519] file(GET_RUNTIME_DEPENDENCIES): Check architecture of dependencies Fixes: #22106 --- Source/cmBinUtilsLinuxELFLinker.cxx | 43 ++++++++++++++++++- Source/cmBinUtilsLinuxELFLinker.h | 4 ++ Source/cmELF.cxx | 16 +++++++ Source/cmELF.h | 4 ++ .../linux-notfile-all-stderr.txt | 5 +-- 5 files changed, 66 insertions(+), 6 deletions(-) diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx index 9ce403dcc05..99707a3f705 100644 --- a/Source/cmBinUtilsLinuxELFLinker.cxx +++ b/Source/cmBinUtilsLinuxELFLinker.cxx @@ -18,6 +18,10 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#ifdef CMake_USE_ELF_PARSER +# include "cmELF.h" +#endif + static std::string ReplaceOrigin(const std::string& rpath, const std::string& origin) { @@ -86,6 +90,24 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( std::string const& file, cmStateEnums::TargetType /* unused */) { std::vector<std::string> parentRpaths; + +#ifdef CMake_USE_ELF_PARSER + cmELF elf(file.c_str()); + if (!elf) { + return false; + } + if (elf.GetMachine() != 0) { + if (this->Machine != 0) { + if (elf.GetMachine() != this->Machine) { + this->SetError("All files must have the same architecture."); + return false; + } + } else { + this->Machine = elf.GetMachine(); + } + } +#endif + return this->ScanDependencies(file, parentRpaths); } @@ -150,13 +172,29 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( return true; } +namespace { +bool FileHasArchitecture(const char* filename, std::uint16_t machine) +{ +#ifdef CMake_USE_ELF_PARSER + cmELF elf(filename); + if (!elf) { + return false; + } + return machine == 0 || machine == elf.GetMachine(); +#else + return true; +#endif +} +} + bool cmBinUtilsLinuxELFLinker::ResolveDependency( std::string const& name, std::vector<std::string> const& searchPaths, std::string& path, bool& resolved) { for (auto const& searchPath : searchPaths) { path = cmStrCat(searchPath, '/', name); - if (cmSystemTools::PathExists(path)) { + if (cmSystemTools::PathExists(path) && + FileHasArchitecture(path.c_str(), this->Machine)) { resolved = true; return true; } @@ -164,7 +202,8 @@ bool cmBinUtilsLinuxELFLinker::ResolveDependency( for (auto const& searchPath : this->Archive->GetSearchDirectories()) { path = cmStrCat(searchPath, '/', name); - if (cmSystemTools::PathExists(path)) { + if (cmSystemTools::PathExists(path) && + FileHasArchitecture(path.c_str(), this->Machine)) { std::ostringstream warning; warning << "Dependency " << name << " found in search directory:\n " << searchPath diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h index 4e7e36d4c8b..395ed567b48 100644 --- a/Source/cmBinUtilsLinuxELFLinker.h +++ b/Source/cmBinUtilsLinuxELFLinker.h @@ -3,6 +3,9 @@ #pragma once +#include "cmConfigure.h" // IWYU pragma: keep + +#include <cstdint> #include <memory> #include <string> #include <vector> @@ -29,6 +32,7 @@ class cmBinUtilsLinuxELFLinker : public cmBinUtilsLinker std::unique_ptr<cmLDConfigTool> LDConfigTool; bool HaveLDConfigPaths = false; std::vector<std::string> LDConfigPaths; + std::uint16_t Machine = 0; bool ScanDependencies(std::string const& file, std::vector<std::string> const& parentRpaths); diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index deffdb6467c..9a474e32c57 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -168,6 +168,9 @@ class cmELFInternal // Return the recorded ELF type. cmELF::FileType GetFileType() const { return this->ELFType; } + // Return the recorded machine. + std::uint16_t GetMachine() const { return this->Machine; } + protected: // Data common to all ELF class implementations. @@ -183,6 +186,9 @@ class cmELFInternal // The ELF file type. cmELF::FileType ELFType; + // The ELF architecture. + std::uint16_t Machine; + // Whether we need to byte-swap structures read from the stream. bool NeedSwap; @@ -478,6 +484,8 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external, } } + this->Machine = this->ELFHeader.e_machine; + // Load the section headers. this->SectionHeaders.resize(this->ELFHeader.e_shnum); for (ELF_Half i = 0; i < this->ELFHeader.e_shnum; ++i) { @@ -757,6 +765,14 @@ cmELF::FileType cmELF::GetFileType() const return FileTypeInvalid; } +std::uint16_t cmELF::GetMachine() const +{ + if (this->Valid()) { + return this->Internal->GetMachine(); + } + return 0; +} + unsigned int cmELF::GetNumberOfSections() const { if (this->Valid()) { diff --git a/Source/cmELF.h b/Source/cmELF.h index c479e2b951d..f88ebe99208 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstdint> #include <iosfwd> #include <memory> #include <string> @@ -72,6 +73,9 @@ class cmELF /** Get the type of the file opened. */ FileType GetFileType() const; + /** Get the machine of the file opened. */ + std::uint16_t GetMachine() const; + /** Get the number of ELF sections present. */ unsigned int GetNumberOfSections() const; diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt index d9758c579e2..5b863220abc 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt @@ -1,5 +1,2 @@ ^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): - file Failed to run objdump on: - - [^ -]*/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-build/root-all/bin/\.\./lib/libtest\.so$ + file Could not resolve file libtest\.so$ From 5aeda18297222c2a0c9e5b067adc1d0d736a78bf Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Mon, 12 Jul 2021 15:40:37 -0400 Subject: [PATCH 0893/1519] file(GET_RUNTIME_DEPENDENCIES): Use cmELF unconditionally Starting with CMake 3.22, cmELF.h is always available, so use it unconditionally. --- Source/cmBinUtilsLinuxELFLinker.cxx | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx index 99707a3f705..a69c00d306b 100644 --- a/Source/cmBinUtilsLinuxELFLinker.cxx +++ b/Source/cmBinUtilsLinuxELFLinker.cxx @@ -11,6 +11,7 @@ #include <cmsys/RegularExpression.hxx> #include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h" +#include "cmELF.h" #include "cmLDConfigLDConfigTool.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -18,10 +19,6 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#ifdef CMake_USE_ELF_PARSER -# include "cmELF.h" -#endif - static std::string ReplaceOrigin(const std::string& rpath, const std::string& origin) { @@ -91,7 +88,6 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( { std::vector<std::string> parentRpaths; -#ifdef CMake_USE_ELF_PARSER cmELF elf(file.c_str()); if (!elf) { return false; @@ -106,7 +102,6 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( this->Machine = elf.GetMachine(); } } -#endif return this->ScanDependencies(file, parentRpaths); } @@ -175,15 +170,11 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies( namespace { bool FileHasArchitecture(const char* filename, std::uint16_t machine) { -#ifdef CMake_USE_ELF_PARSER cmELF elf(filename); if (!elf) { return false; } return machine == 0 || machine == elf.GetMachine(); -#else - return true; -#endif } } From 805fa791d10c31ba629306328c2f491708e3e88b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 12 Jul 2021 06:09:35 +0300 Subject: [PATCH 0894/1519] CPack/DEB: Avoid overriding user-provided `postinst` and `postrm` When a user provides `CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA` or `CPACK_DEBIAN_<comp>_PACKAGE_CONTROL_EXTRA` variables in `CMakeLists.txt` and the package contains dynamic libraries, the `CPackDeb.cmake` sets `CPACK_ADD_LDCONFIG_CALL` to `1`. Later it analyzes if defaulted `postinst`/`postrm` should be generated trying to check if the user provides any in `CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA` variable. However, the `foreach` loop uses the invalid variable `PACKAGE_CONTROL_EXTRA` instead, so these files gonna be overridden. Fix the variable name. Fixes: #22410 --- Modules/Internal/CPack/CPackDeb.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index 2ceab10bc1c..967ad7bc130 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -673,7 +673,7 @@ function(cpack_deb_prepare_package_vars) if(CPACK_ADD_LDCONFIG_CALL) set(CPACK_DEBIAN_GENERATE_POSTINST 1) set(CPACK_DEBIAN_GENERATE_POSTRM 1) - foreach(f IN LISTS PACKAGE_CONTROL_EXTRA) + foreach(f IN LISTS CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA) get_filename_component(n "${f}" NAME) if(n STREQUAL "postinst") set(CPACK_DEBIAN_GENERATE_POSTINST 0) From 68b961d36178027faa16dad22ab1637b67144577 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 12 Jul 2021 23:50:43 +0300 Subject: [PATCH 0895/1519] CPack/DEB: Add postinst/postrm ldconfig for multi-arch lib dirs Fixes: #22411 --- Modules/Internal/CPack/CPackDeb.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index 2ceab10bc1c..1ef0aff3abe 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -662,10 +662,12 @@ function(cpack_deb_prepare_package_vars) # add ldconfig call in default postrm and postint set(CPACK_ADD_LDCONFIG_CALL 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) - # all files in CPACK_DEB_SHARED_OBJECT_FILES have dot at the beginning - if(_DIR STREQUAL "./lib" OR _DIR STREQUAL "./usr/lib") + get_filename_component(_PARENT_DIR ${_DIR} DIRECTORY) + if(_DIR IN_LIST _LDCONF_DEFAULTS OR _PARENT_DIR IN_LIST _LDCONF_DEFAULTS) set(CPACK_ADD_LDCONFIG_CALL 1) endif() endforeach() From 15bd593f4f620f185ffb2f733071c2de1f9dcd9e Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 13 Jul 2021 00:01:11 -0400 Subject: [PATCH 0896/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1029ed84fb6..fc80b1fb53d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210712) +set(CMake_VERSION_PATCH 20210713) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 700abe7bca0486a2d67383b2e8e364db241566b5 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 00:51:59 +0300 Subject: [PATCH 0897/1519] Refactor: Drop useless assignments of `retval` before return --- Source/CPack/cmCPackDebGenerator.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index db30a0d663c..14f3f50cbdd 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -508,8 +508,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake" << std::endl); - retval = 0; - return retval; + return 0; } { // Isolate globbing of binaries vs. dbgsyms @@ -660,8 +659,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake" << std::endl); - retval = 0; - return retval; + return 0; } cmsys::Glob gl; From 45a6fa0c336d4fcecde8017aafa626c7eceec074 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 00:56:10 +0300 Subject: [PATCH 0898/1519] Refactor: Drop unnecessary `if` before `return` --- Source/CPack/cmCPackDebGenerator.cxx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 14f3f50cbdd..43d732eef84 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -834,10 +834,7 @@ int cmCPackDebGenerator::createDeb() this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"), this->packageFiles); - if (!gen.generate()) { - return 0; - } - return 1; + return gen.generate(); } int cmCPackDebGenerator::createDbgsymDDeb() @@ -890,10 +887,7 @@ int cmCPackDebGenerator::createDbgsymDDeb() this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"), this->packageFiles); - if (!gen.generate()) { - return 0; - } - return 1; + return gen.generate(); } bool cmCPackDebGenerator::SupportsComponentInstallation() const From 008321595afed33352bfa575894251e9ac3ed1bd Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 01:10:33 +0300 Subject: [PATCH 0899/1519] Refactor: Change return value to bool for private members The `cmCPackDebGenerator::createDeb()` and `cmCPackDebGenerator::createDbgsymDDeb()` in fact have boolean return value. --- Source/CPack/cmCPackDebGenerator.cxx | 25 +++++++------------------ Source/CPack/cmCPackDebGenerator.h | 4 ++-- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 43d732eef84..0216a4ac514 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -481,7 +481,6 @@ int cmCPackDebGenerator::InitializeInternal() int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, std::string const& packageName) { - int retval = 1; // Begin the archive for this pack std::string localToplevel(initialTopLevel); std::string packageFileName( @@ -529,10 +528,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, std::sort(this->packageFiles.begin(), this->packageFiles.end()); } - int res = this->createDeb(); - if (res != 1) { - retval = 0; - } + bool retval = this->createDeb(); // add the generated package to package file names list packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); @@ -556,10 +552,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, // Sort files so that they have a reproducible order std::sort(this->packageFiles.begin(), this->packageFiles.end()); - res = this->createDbgsymDDeb(); - if (res != 1) { - retval = 0; - } + retval = this->createDbgsymDDeb() || retval; // add the generated package to package file names list packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', @@ -567,7 +560,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, this->packageFileNames.push_back(std::move(packageFileName)); } - return retval; + return int(retval); } int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) @@ -616,7 +609,6 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) int cmCPackDebGenerator::PackageComponentsAllInOne( const std::string& compInstDirName) { - int retval = 1; /* Reset package file name list it will be populated during the * component packaging run*/ this->packageFileNames.clear(); @@ -678,15 +670,12 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( // Sort files so that they have a reproducible order std::sort(this->packageFiles.begin(), this->packageFiles.end()); - int res = this->createDeb(); - if (res != 1) { - retval = 0; - } + bool retval = this->createDeb(); // add the generated package to package file names list packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); this->packageFileNames.push_back(std::move(packageFileName)); - return retval; + return int(retval); } int cmCPackDebGenerator::PackageFiles() @@ -710,7 +699,7 @@ int cmCPackDebGenerator::PackageFiles() return this->PackageComponentsAllInOne(""); } -int cmCPackDebGenerator::createDeb() +bool cmCPackDebGenerator::createDeb() { std::map<std::string, std::string> controlValues; @@ -837,7 +826,7 @@ int cmCPackDebGenerator::createDeb() return gen.generate(); } -int cmCPackDebGenerator::createDbgsymDDeb() +bool cmCPackDebGenerator::createDbgsymDDeb() { // Packages containing debug symbols follow the same structure as .debs // but have different metadata and content. diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index ee8f39af6e7..502746cf5e2 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -63,8 +63,8 @@ class cmCPackDebGenerator : public cmCPackGenerator const std::string& componentName) override; private: - int createDeb(); - int createDbgsymDDeb(); + bool createDeb(); + bool createDbgsymDDeb(); std::vector<std::string> packageFiles; }; From 7fd3134ea16d2d1fbf08fa5a5d28059d62067ad6 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 01:48:38 +0300 Subject: [PATCH 0900/1519] Refactor: cmCPackDebGenerator::PackageComponents handle `else` first Also, return early to reduce nesting level of the function body. --- Source/CPack/cmCPackDebGenerator.cxx | 54 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 0216a4ac514..fef8bde853c 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -565,40 +565,40 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) { - int retval = 1; - /* Reset package file name list it will be populated during the - * component packaging run*/ + // Reset package file name list it will be populated during the + // component packaging run this->packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); + int retval = 1; // The default behavior is to have one package by component group // unless CPACK_COMPONENTS_IGNORE_GROUP is specified. - if (!ignoreGroup) { - for (auto const& compG : this->ComponentGroups) { - cmCPackLogger(cmCPackLog::LOG_VERBOSE, - "Packaging component group: " << compG.first << std::endl); - // Begin the archive for this group - retval &= this->PackageOnePack(initialTopLevel, compG.first); - } - // Handle Orphan components (components not belonging to any groups) + if (ignoreGroup) { + // CPACK_COMPONENTS_IGNORE_GROUPS is set + // We build 1 package per component for (auto const& comp : this->Components) { - // Does the component belong to a group? - if (comp.second.Group == nullptr) { - cmCPackLogger( - cmCPackLog::LOG_VERBOSE, - "Component <" - << comp.second.Name - << "> does not belong to any group, package it separately." - << std::endl); - // Begin the archive for this orphan component - retval &= this->PackageOnePack(initialTopLevel, comp.first); - } + retval &= this->PackageOnePack(initialTopLevel, comp.first); } - } - // CPACK_COMPONENTS_IGNORE_GROUPS is set - // We build 1 package per component - else { - for (auto const& comp : this->Components) { + return retval; + } + + for (auto const& compG : this->ComponentGroups) { + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Packaging component group: " << compG.first << std::endl); + // Begin the archive for this group + retval &= this->PackageOnePack(initialTopLevel, compG.first); + } + // Handle Orphan components (components not belonging to any groups) + for (auto const& comp : this->Components) { + // Does the component belong to a group? + if (comp.second.Group == nullptr) { + cmCPackLogger( + cmCPackLog::LOG_VERBOSE, + "Component <" + << comp.second.Name + << "> does not belong to any group, package it separately." + << std::endl); + // Begin the archive for this orphan component retval &= this->PackageOnePack(initialTopLevel, comp.first); } } From c8f298ae0808675ddd70341f7c83348bc092fb3f Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 02:29:44 +0300 Subject: [PATCH 0901/1519] Refactor: Extract packaged files finder into a function --- Source/CPack/cmCPackDebGenerator.cxx | 79 ++++++++++++---------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index fef8bde853c..70670af0b85 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -8,6 +8,7 @@ #include <map> #include <ostream> #include <set> +#include <stdexcept> #include <utility> #include "cmsys/Glob.hxx" @@ -463,6 +464,23 @@ bool DebGenerator::generateDeb() const return true; } +std::vector<std::string> findFilesIn(const std::string& path) +{ + cmsys::Glob gl; + std::string findExpr = path + "/*"; + gl.RecurseOn(); + gl.SetRecurseListDirs(true); + gl.SetRecurseThroughSymlinks(false); + if (!gl.FindFiles(findExpr)) { + throw std::runtime_error( + "Cannot find any files in the installed directory"); + } + std::vector<std::string> files{ gl.GetFiles() }; + // Sort files so that they have a reproducible order + std::sort(files.begin(), files.end()); + return files; +} + } // end anonymous namespace cmCPackDebGenerator::cmCPackDebGenerator() = default; @@ -510,54 +528,34 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, return 0; } - { // Isolate globbing of binaries vs. dbgsyms - cmsys::Glob gl; - std::string findExpr(this->GetOption("GEN_WDIR")); - findExpr += "/*"; - gl.RecurseOn(); - gl.SetRecurseListDirs(true); - gl.SetRecurseThroughSymlinks(false); - if (!gl.FindFiles(findExpr)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find any files in the installed directory" - << std::endl); - return 0; - } - this->packageFiles = gl.GetFiles(); - // Sort files so that they have a reproducible order - std::sort(this->packageFiles.begin(), this->packageFiles.end()); + try { + this->packageFiles = findFilesIn(this->GetOption("GEN_WDIR")); + } catch (const std::runtime_error& ex) { + cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); + return 0; } bool retval = this->createDeb(); // add the generated package to package file names list packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); - this->packageFileNames.push_back(std::move(packageFileName)); + this->packageFileNames.emplace_back(std::move(packageFileName)); if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && this->GetOption("GEN_DBGSYMDIR")) { - cmsys::Glob gl; - std::string findExpr(this->GetOption("GEN_DBGSYMDIR")); - findExpr += "/*"; - gl.RecurseOn(); - gl.SetRecurseListDirs(true); - gl.SetRecurseThroughSymlinks(false); - if (!gl.FindFiles(findExpr)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find any files in the installed directory" - << std::endl); + try { + this->packageFiles = findFilesIn(this->GetOption("GEN_DBGSYMDIR")); + } catch (const std::runtime_error& ex) { + cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); return 0; } - this->packageFiles = gl.GetFiles(); - // Sort files so that they have a reproducible order - std::sort(this->packageFiles.begin(), this->packageFiles.end()); retval = this->createDbgsymDDeb() || retval; // add the generated package to package file names list packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME")); - this->packageFileNames.push_back(std::move(packageFileName)); + this->packageFileNames.emplace_back(std::move(packageFileName)); } return int(retval); @@ -654,27 +652,18 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( return 0; } - cmsys::Glob gl; - std::string findExpr(this->GetOption("GEN_WDIR")); - findExpr += "/*"; - gl.RecurseOn(); - gl.SetRecurseListDirs(true); - gl.SetRecurseThroughSymlinks(false); - if (!gl.FindFiles(findExpr)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find any files in the installed directory" - << std::endl); + try { + this->packageFiles = findFilesIn(this->GetOption("GEN_WDIR")); + } catch (const std::runtime_error& ex) { + cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); return 0; } - this->packageFiles = gl.GetFiles(); - // Sort files so that they have a reproducible order - std::sort(this->packageFiles.begin(), this->packageFiles.end()); bool retval = this->createDeb(); // add the generated package to package file names list packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); - this->packageFileNames.push_back(std::move(packageFileName)); + this->packageFileNames.emplace_back(std::move(packageFileName)); return int(retval); } From 593ff734b08779bc2ac3f7d5975c2d12dfa5614b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 02:58:17 +0300 Subject: [PATCH 0902/1519] CPack/DEB: dbgsym package not generated for non-component packaging Fix: #19735 --- Source/CPack/cmCPackDebGenerator.cxx | 81 +++++++++---------- Source/CPack/cmCPackDebGenerator.h | 1 + Tests/RunCMake/CPack/RunCMakeTest.cmake | 1 + .../CPack/tests/DEBUGINFO/ExpectedFiles.cmake | 66 +++++++++------ .../RunCMake/CPack/tests/DEBUGINFO/test.cmake | 2 + 5 files changed, 81 insertions(+), 70 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 70670af0b85..cbdcf49c380 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -528,37 +528,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, return 0; } - try { - this->packageFiles = findFilesIn(this->GetOption("GEN_WDIR")); - } catch (const std::runtime_error& ex) { - cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); - return 0; - } - - bool retval = this->createDeb(); - // add the generated package to package file names list - packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); - this->packageFileNames.emplace_back(std::move(packageFileName)); - - if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && - this->GetOption("GEN_DBGSYMDIR")) { - try { - this->packageFiles = findFilesIn(this->GetOption("GEN_DBGSYMDIR")); - } catch (const std::runtime_error& ex) { - cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); - return 0; - } - - retval = this->createDbgsymDDeb() || retval; - // add the generated package to package file names list - packageFileName = - cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME")); - this->packageFileNames.emplace_back(std::move(packageFileName)); - } - - return int(retval); + return this->createDebPackages(); } int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) @@ -652,19 +622,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( return 0; } - try { - this->packageFiles = findFilesIn(this->GetOption("GEN_WDIR")); - } catch (const std::runtime_error& ex) { - cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); - return 0; - } - - bool retval = this->createDeb(); - // add the generated package to package file names list - packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); - this->packageFileNames.emplace_back(std::move(packageFileName)); - return int(retval); + return this->createDebPackages(); } int cmCPackDebGenerator::PackageFiles() @@ -688,6 +646,40 @@ int cmCPackDebGenerator::PackageFiles() return this->PackageComponentsAllInOne(""); } +bool cmCPackDebGenerator::createDebPackages() +{ + try { + this->packageFiles = findFilesIn(this->GetOption("GEN_WDIR")); + } catch (const std::runtime_error& ex) { + cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); + return 0; + } + + bool retval = this->createDeb(); + // add the generated package to package file names list + this->packageFileNames.emplace_back( + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"))); + + if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && + this->GetOption("GEN_DBGSYMDIR")) { + try { + this->packageFiles = findFilesIn(this->GetOption("GEN_DBGSYMDIR")); + } catch (const std::runtime_error& ex) { + cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); + return 0; + } + + retval = this->createDbgsymDDeb() || retval; + // add the generated package to package file names list + this->packageFileNames.emplace_back( + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"))); + } + + return int(retval); +} + bool cmCPackDebGenerator::createDeb() { std::map<std::string, std::string> controlValues; @@ -855,7 +847,6 @@ bool cmCPackDebGenerator::createDbgsymDDeb() DebGenerator gen( this->Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"), this->GetOption("GEN_DBGSYMDIR"), - this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), this->GetOption("CPACK_TEMPORARY_DIRECTORY"), this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"), diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index 502746cf5e2..61a6616d3f6 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -63,6 +63,7 @@ class cmCPackDebGenerator : public cmCPackGenerator const std::string& componentName) override; private: + bool createDebPackages(); bool createDeb(); bool createDbgsymDDeb(); diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 746ff8b1c07..7997c785f07 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -7,6 +7,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake") run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM.CUSTOM_BINARY_SPEC_FILE" false "MONOLITHIC;COMPONENT") run_cpack_test(CUSTOM_NAMES "RPM.CUSTOM_NAMES;DEB.CUSTOM_NAMES;TGZ;DragNDrop" true "COMPONENT") run_cpack_test(DEBUGINFO "RPM.DEBUGINFO;DEB.DEBUGINFO" true "COMPONENT") +run_cpack_test(DEBUGINFO "DEB.DEBUGINFO" true "MONOLITHIC") run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM.DEFAULT_PERMISSIONS;DEB.DEFAULT_PERMISSIONS" false "MONOLITHIC;COMPONENT") run_cpack_test(DEPENDENCIES "RPM.DEPENDENCIES;DEB.DEPENDENCIES" true "COMPONENT") run_cpack_test(DIST "RPM.DIST" false "MONOLITHIC") diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake index cf4aa510ac2..b3e64857fb2 100644 --- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake @@ -1,8 +1,5 @@ set(whitespaces_ "[\t\n\r ]*") -set(EXPECTED_FILES_COUNT "6") -set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) - if(GENERATOR_TYPE STREQUAL "RPM") set(NAME "Debuginfo") set(DEBUG_SUFFIX "debuginfo") @@ -15,30 +12,49 @@ elseif(GENERATOR_TYPE STREQUAL "DEB") set(DEBUG_PKG "ddeb") endif() -set(EXPECTED_FILE_1_NAME "${NAME}") -set(EXPECTED_FILE_1_COMPONENT "applications") -set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") +set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) -set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.${PKG}") -set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(EXPECTED_FILES_COUNT "6") -set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.${PKG}") -set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") + set(EXPECTED_FILE_1_NAME "${NAME}") + set(EXPECTED_FILE_1_COMPONENT "applications") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") -set(EXPECTED_FILE_4 "${NAME}-applications-${DEBUG_SUFFIX}*.${DEBUG_PKG}") -if(GENERATOR_TYPE STREQUAL "RPM") - set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*") -elseif(GENERATOR_TYPE STREQUAL "DEB") - set(EXPECTED_FILE_CONTENT_4 ".*/usr/lib/debug/.build-id/.*\.debug.*") -endif() + set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.${PKG}") + set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") -if(GENERATOR_TYPE STREQUAL "RPM") - set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm") - set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*") -elseif(GENERATOR_TYPE STREQUAL "DEB") - set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb") - set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*") -endif() + set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.${PKG}") + set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") + + set(EXPECTED_FILE_4 "${NAME}-applications-${DEBUG_SUFFIX}*.${DEBUG_PKG}") + if(GENERATOR_TYPE STREQUAL "RPM") + set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*") + elseif(GENERATOR_TYPE STREQUAL "DEB") + set(EXPECTED_FILE_CONTENT_4 ".*/usr/lib/debug/.build-id/.*\.debug.*") + endif() + + if(GENERATOR_TYPE STREQUAL "RPM") + set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm") + set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*") + elseif(GENERATOR_TYPE STREQUAL "DEB") + set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb") + set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*") + endif() + + set(EXPECTED_FILE_6 "TestDinfo-pkg*-appheaders.${PKG}") + set(EXPECTED_FILE_CONTENT_6_LIST "/include;/include/test_lib.hpp") -set(EXPECTED_FILE_6 "TestDinfo-pkg*-appheaders.${PKG}") -set(EXPECTED_FILE_CONTENT_6_LIST "/include;/include/test_lib.hpp") +elseif(PACKAGING_TYPE STREQUAL "MONOLITHIC" AND GENERATOR_TYPE STREQUAL "DEB") + set(EXPECTED_FILES_COUNT "2") + + set(EXPECTED_FILE_1 "TestDinfo-pkg.deb") + set( + EXPECTED_FILE_CONTENT_1_LIST + "/bar;/bar/CMakeLists.txt;/bas;/bas/libtest_lib.so;/foo;/foo/test_prog;/include;/include/test_lib.hpp" + ) + + set(EXPECTED_FILE_2 "TestDinfo-pkg-dbgsym.ddeb") + set(EXPECTED_FILE_CONTENT_2 ".*/usr/lib/debug/.build-id/.*\.debug.*") + +endif() diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake index 9ff1f8a0495..e9cebbf8d6e 100644 --- a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake +++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake @@ -28,6 +28,8 @@ install(TARGETS test_prog DESTINATION foo COMPONENT applications) install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers) install(TARGETS test_lib DESTINATION bas COMPONENT libs) +set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) + set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT") set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON) set(CPACK_DEBIAN_APPLICATIONS_FILE_NAME "DEB-DEFAULT") From 7add10f288e956d45781726784867847c268efa4 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 04:50:32 +0300 Subject: [PATCH 0903/1519] Refactor: Deduplicate code of `createDebPackages()` Also, fix incorrect `retval` accumulation. --- Source/CPack/cmCPackDebGenerator.cxx | 41 +++++++++++++--------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index cbdcf49c380..210ef6424f9 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -648,35 +648,32 @@ int cmCPackDebGenerator::PackageFiles() bool cmCPackDebGenerator::createDebPackages() { - try { - this->packageFiles = findFilesIn(this->GetOption("GEN_WDIR")); - } catch (const std::runtime_error& ex) { - cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); - return 0; - } - - bool retval = this->createDeb(); - // add the generated package to package file names list - this->packageFileNames.emplace_back( - cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"))); - - if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && - this->GetOption("GEN_DBGSYMDIR")) { + auto make_package = [this](const char* const path, const char* const output, + bool (cmCPackDebGenerator::*creator)()) -> bool { try { - this->packageFiles = findFilesIn(this->GetOption("GEN_DBGSYMDIR")); + this->packageFiles = findFilesIn(this->GetOption(path)); } catch (const std::runtime_error& ex) { cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); return 0; } - retval = this->createDbgsymDDeb() || retval; - // add the generated package to package file names list - this->packageFileNames.emplace_back( - cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"))); + if ((this->*creator)()) { + // add the generated package to package file names list + this->packageFileNames.emplace_back( + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + this->GetOption(output))); + return true; + } + return false; + }; + bool retval = make_package("GEN_WDIR", "GEN_CPACK_OUTPUT_FILE_NAME", + &cmCPackDebGenerator::createDeb); + if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && + this->GetOption("GEN_DBGSYMDIR")) { + retval = make_package("GEN_DBGSYMDIR", "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME", + &cmCPackDebGenerator::createDbgsymDDeb) && + retval; } - return int(retval); } From 13549674cc8f2b72380aa4a367fef3bce26a5131 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 05:03:54 +0300 Subject: [PATCH 0904/1519] Refactor: Avoid duplicate calls to `GetOption("GEN_DBGSYMDIR")` --- Source/CPack/cmCPackDebGenerator.cxx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 210ef6424f9..675f6f8cd4f 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -648,29 +648,31 @@ int cmCPackDebGenerator::PackageFiles() bool cmCPackDebGenerator::createDebPackages() { - auto make_package = [this](const char* const path, const char* const output, + auto make_package = [this](const char* const path, + const char* const output_var, bool (cmCPackDebGenerator::*creator)()) -> bool { try { - this->packageFiles = findFilesIn(this->GetOption(path)); + this->packageFiles = findFilesIn(path); } catch (const std::runtime_error& ex) { cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl); - return 0; + return false; } if ((this->*creator)()) { // add the generated package to package file names list this->packageFileNames.emplace_back( cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', - this->GetOption(output))); + this->GetOption(output_var))); return true; } return false; }; - bool retval = make_package("GEN_WDIR", "GEN_CPACK_OUTPUT_FILE_NAME", - &cmCPackDebGenerator::createDeb); - if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && - this->GetOption("GEN_DBGSYMDIR")) { - retval = make_package("GEN_DBGSYMDIR", "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME", + bool retval = + make_package(this->GetOption("GEN_WDIR"), "GEN_CPACK_OUTPUT_FILE_NAME", + &cmCPackDebGenerator::createDeb); + const char* const dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); + if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && dbgsymdir_path) { + retval = make_package(dbgsymdir_path, "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDbgsymDDeb) && retval; } From afcc5449e877c122bff03cffa1f70c70196817ad Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 05:49:22 +0300 Subject: [PATCH 0905/1519] Refactor: Use `cmStrToLong` instead of `std::strtol` --- Source/CPack/cmCPackDebGenerator.cxx | 35 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 675f6f8cd4f..a93cd98e063 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -3,7 +3,6 @@ #include "cmCPackDebGenerator.h" #include <algorithm> -#include <cstdlib> #include <cstring> #include <map> #include <ostream> @@ -56,7 +55,7 @@ class DebGenerator const std::string TopLevelDir; const std::string TemporaryDir; const char* DebianArchiveType; - int NumThreads; + long NumThreads; const std::map<std::string, std::string> ControlValues; const bool GenShLibs; const std::string ShLibsFilename; @@ -100,19 +99,19 @@ DebGenerator::DebGenerator( debianCompressionType = "gzip"; } - if (!strcmp(debianCompressionType, "lzma")) { + if (!std::strcmp(debianCompressionType, "lzma")) { this->CompressionSuffix = ".lzma"; this->TarCompressionType = cmArchiveWrite::CompressLZMA; - } else if (!strcmp(debianCompressionType, "xz")) { + } else if (!std::strcmp(debianCompressionType, "xz")) { this->CompressionSuffix = ".xz"; this->TarCompressionType = cmArchiveWrite::CompressXZ; - } else if (!strcmp(debianCompressionType, "bzip2")) { + } else if (!std::strcmp(debianCompressionType, "bzip2")) { this->CompressionSuffix = ".bz2"; this->TarCompressionType = cmArchiveWrite::CompressBZip2; - } else if (!strcmp(debianCompressionType, "gzip")) { + } else if (!std::strcmp(debianCompressionType, "gzip")) { this->CompressionSuffix = ".gz"; this->TarCompressionType = cmArchiveWrite::CompressGZip; - } else if (!strcmp(debianCompressionType, "none")) { + } else if (!std::strcmp(debianCompressionType, "none")) { this->CompressionSuffix.clear(); this->TarCompressionType = cmArchiveWrite::CompressNone; } else { @@ -121,16 +120,15 @@ DebGenerator::DebGenerator( << debianCompressionType << std::endl); } - if (numThreads == nullptr) { - numThreads = "1"; - } - - char* endptr; - this->NumThreads = static_cast<int>(strtol(numThreads, &endptr, 10)); - if (numThreads != endptr && *endptr != '\0') { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Unrecognized number of threads: " << numThreads - << std::endl); + if (numThreads != nullptr) { + if (!cmStrToLong(numThreads, &this->NumThreads)) { + this->NumThreads = 1; + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Unrecognized number of threads: " << numThreads + << std::endl); + } + } else { + this->NumThreads = 1; } } @@ -189,7 +187,8 @@ bool DebGenerator::generateDataTar() const return false; } cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType, - this->DebianArchiveType, 0, this->NumThreads); + this->DebianArchiveType, 0, + static_cast<int>(this->NumThreads)); data_tar.Open(); // uid/gid should be the one of the root user, and this root user has From 161f1f42d6400f4de85767108c090991c41326fe Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 13 Jul 2021 09:33:52 -0400 Subject: [PATCH 0906/1519] Help: Clarify 'cmake --build' signature alternatives Documentation added by * commit 4f4f2028b8 (Help: Add documentation for buildPresets and testPresets, 2021-01-13, v3.20.0-rc1~51^2~7) * commit 676ecf0d37 (cmake-presets: Add build and test presets, 2020-12-14, v3.20.0-rc1~51^2~6) used square brackets in the `cmake --build` signature to indicate non-optional alternatives, which is not a typical convention. A common convention is to use parentheses instead, but in this case it is probably clearer to list the two signatures separately. Fixes: #22413 --- Help/manual/cmake.1.rst | 3 ++- Source/cmakemain.cxx | 5 ++++- .../BuildDir--build--parallel-bad-number-stderr.txt | 2 +- .../CommandLine/BuildDir--build--parallel-large-stderr.txt | 2 +- .../BuildDir--build--parallel-no-space-bad-number-stderr.txt | 2 +- .../CommandLine/BuildDir--build--parallel-zero-stderr.txt | 2 +- .../CommandLine/BuildDir--build-jobs-bad-number-stderr.txt | 2 +- .../CommandLine/BuildDir--build-jobs-large-stderr.txt | 2 +- .../BuildDir--build-jobs-no-space-bad-number-stderr.txt | 2 +- .../CommandLine/BuildDir--build-jobs-zero-stderr.txt | 2 +- ...ldDir--build-multiple-targets-with-clean-first-stderr.txt | 2 +- ...dDir--build-multiple-targets-with-clean-second-stderr.txt | 2 +- Tests/RunCMake/CommandLine/build-no-dir-stderr.txt | 2 +- .../CommandLine/build-unknown-command-long-stderr.txt | 2 +- .../build-unknown-command-partial-match-stderr.txt | 2 +- .../CommandLine/build-unknown-command-short-stderr.txt | 2 +- 16 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 2d639b68ecf..e23ddd8231c 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -408,7 +408,8 @@ project binary tree: .. code-block:: shell - cmake --build [<dir> | --preset <preset>] [<options>] [-- <build-tool-options>] + cmake --build <dir> [<options>] [-- <build-tool-options>] + cmake --build --preset <preset> [<options>] [-- <build-tool-options>] This abstracts a native build tool's command-line interface with the following options: diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index d83183f3909..1725375d95a 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -600,7 +600,10 @@ int do_build(int ac, char const* const* av) if (dir.empty() && presetName.empty() && !listPresets) { /* clang-format off */ std::cerr << - "Usage: cmake --build [<dir> | --preset <preset>] [options] [-- [native-options]]\n" + "Usage: cmake --build <dir> " + " [options] [-- [native-options]]\n" + " cmake --build --preset <preset>" + " [options] [-- [native-options]]\n" "Options:\n" " <dir> = Project binary directory to be built.\n" " --preset <preset>, --preset=<preset>\n" diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt index 16f8be8b0e9..96de4d17dbd 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-bad-number-stderr.txt @@ -1,3 +1,3 @@ ^'--parallel' invalid number '12ab' given\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt index e7b9aaaf2aa..0bb806ff43f 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-large-stderr.txt @@ -1,3 +1,3 @@ ^The <jobs> value is too large\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt index 16f8be8b0e9..96de4d17dbd 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-no-space-bad-number-stderr.txt @@ -1,3 +1,3 @@ ^'--parallel' invalid number '12ab' given\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt index d1241f46dbc..b965d4a47c2 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build--parallel-zero-stderr.txt @@ -1,3 +1,3 @@ ^The <jobs> value requires a positive integer argument\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt index d52b16583a8..97e90ec99a6 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-bad-number-stderr.txt @@ -1,3 +1,3 @@ ^'-j' invalid number '12ab' given\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt index e7b9aaaf2aa..0bb806ff43f 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-large-stderr.txt @@ -1,3 +1,3 @@ ^The <jobs> value is too large\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt index d52b16583a8..97e90ec99a6 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-no-space-bad-number-stderr.txt @@ -1,3 +1,3 @@ ^'-j' invalid number '12ab' given\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt index d1241f46dbc..b965d4a47c2 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-jobs-zero-stderr.txt @@ -1,3 +1,3 @@ ^The <jobs> value requires a positive integer argument\. + -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt index 2dd9bc42495..c15fdbabd9e 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt @@ -1,2 +1,2 @@ ^Error: Building 'clean' and other targets together is not supported\. -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt index 2dd9bc42495..c15fdbabd9e 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt @@ -1,2 +1,2 @@ ^Error: Building 'clean' and other targets together is not supported\. -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt b/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt index 9b4d26bc29e..4811bea2f7b 100644 --- a/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt @@ -1 +1 @@ -^Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +^Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt index c8f1a03cb82..559e4b61350 100644 --- a/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-unknown-command-long-stderr.txt @@ -1,2 +1,2 @@ ^Unknown argument --invalid-command -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt index e4ad6b2da41..1f44c4e33fc 100644 --- a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt @@ -1,2 +1,2 @@ ^Unknown argument --targetinvalid -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt index a6cfeceaced..4f5ba558bcf 100644 --- a/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt +++ b/Tests/RunCMake/CommandLine/build-unknown-command-short-stderr.txt @@ -1,2 +1,2 @@ ^Unknown argument -invalid-command -Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\] +Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\] From 9dc007e17c80e354e51e68fa94f1fa7e2636f0e4 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 13 Jul 2021 16:37:54 +0300 Subject: [PATCH 0907/1519] Refactor: Drop redundand `std::endl` calls in the middle of output --- Source/CPack/cmCPackDebGenerator.cxx | 88 ++++++++++++++++------------ 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index a93cd98e063..5b031857ee3 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -249,11 +249,15 @@ bool DebGenerator::generateDataTar() const // do not recurse because the loop will do it if (!data_tar.Add(file, topLevelLength, ".", false)) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem adding file to tar:" - << std::endl - << "#top level directory: " << this->WorkDir << std::endl - << "#file: " << file << std::endl - << "#error:" << data_tar.GetError() << std::endl); + "Problem adding file to tar:\n" + "#top level directory: " + << this->WorkDir + << "\n" + "#file: " + << file + << "\n" + "#error:" + << data_tar.GetError() << std::endl); return false; } } @@ -335,11 +339,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const !control_tar.Add(this->WorkDir + "/control", this->WorkDir.length(), ".")) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << this->WorkDir << std::endl - << "#file: \"control\" or \"md5sums\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); + "Error adding file to tar:\n" + "#top level directory: " + << this->WorkDir + << "\n" + "#file: \"control\" or \"md5sums\"\n" + "#error:" + << control_tar.GetError() << std::endl); return false; } @@ -347,11 +353,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const if (this->GenShLibs) { if (!control_tar.Add(this->ShLibsFilename, this->WorkDir.length(), ".")) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << this->WorkDir << std::endl - << "#file: \"shlibs\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); + "Error adding file to tar:\n" + "#top level directory: " + << this->WorkDir + << "\n" + "#file: \"shlibs\"\n" + "#error:" + << control_tar.GetError() << std::endl); return false; } } @@ -361,11 +369,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const control_tar.SetPermissions(permission755); if (!control_tar.Add(this->PostInst, this->WorkDir.length(), ".")) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << this->WorkDir << std::endl - << "#file: \"postinst\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); + "Error adding file to tar:\n" + "#top level directory: " + << this->WorkDir + << "\n" + "#file: \"postinst\"\n" + "#error:" + << control_tar.GetError() << std::endl); return false; } control_tar.SetPermissions(permission644); @@ -375,11 +385,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const control_tar.SetPermissions(permission755); if (!control_tar.Add(this->PostRm, this->WorkDir.length(), ".")) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error adding file to tar:" - << std::endl - << "#top level directory: " << this->WorkDir << std::endl - << "#file: \"postinst\"" << std::endl - << "#error:" << control_tar.GetError() << std::endl); + "Error adding file to tar:\n" + "#top level directory: " + << this->WorkDir + << "\n" + "#file: \"postinst\"\n" + "#error:" + << control_tar.GetError() << std::endl); return false; } control_tar.SetPermissions(permission644); @@ -413,11 +425,12 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const // if we can copy the file, it means it does exist, let's add it: if (!cmsys::SystemTools::FileExists(i)) { cmCPackLogger(cmCPackLog::LOG_WARNING, - "Adding file to tar:" << std::endl - << "#top level directory: " - << this->WorkDir << std::endl - << "#missing file: " << i - << std::endl); + "Adding file to tar:\n" + "#top level directory: " + << this->WorkDir + << "\n" + "#missing file: " + << i << std::endl); } if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) { @@ -452,12 +465,15 @@ bool DebGenerator::generateDeb() const !deb.Add(tlDir + "control.tar.gz", tlDir.length()) || !deb.Add(tlDir + "data.tar" + this->CompressionSuffix, tlDir.length())) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error creating debian package:" - << std::endl - << "#top level directory: " << this->TopLevelDir - << std::endl - << "#file: " << this->OutputName << std::endl - << "#error:" << deb.GetError() << std::endl); + "Error creating debian package:\n" + "#top level directory: " + << this->TopLevelDir + << "\n" + "#file: " + << this->OutputName + << "\n" + "#error:" + << deb.GetError() << std::endl); return false; } return true; From d9fcbb06f2e39b5290f22ebc0e2c5076ae026ccd Mon Sep 17 00:00:00 2001 From: Axel Huebl <axel.huebl@plasma.ninja> Date: Thu, 24 Jun 2021 14:44:21 -0700 Subject: [PATCH 0908/1519] FindMPI: Interrogate Cray compiler Cray traditionally does not ship mpicc/mpic++ compiler wrappers. Due to that, the traditional CMake logic to find MPI is to *only* support MPI on Cray systems if either 1. Cray Wrappers are used for compiling, or 2. an auxiliary MPI executable is found. On many new Exascale prototypes, using the Cray wrappers for develop work is extremely painful. Vendors such as AMD and integrators such as HPE seem not to go well in lock-step in Cray programming envs, making offloading with Cray wrappers too challenging. On the other hand, using the working experimental Vendor compilers works well, as long as one does not need MPI. Extend the fallback MPI search logic by also interrogating the CC/cc/ftn binaries if found for their MPI flags. This does not change existing logic, i.e. using the Cray wrappers directly, but provides an additional way to get MPI programs compiled on Cray. Fixes: #22368 --- Modules/FindMPI.cmake | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 0b0d2d37480..f64c4b8a1b8 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -105,7 +105,7 @@ This module performs a four step search for an MPI implementation: 1. Search for ``MPIEXEC_EXECUTABLE`` and, if found, use its base directory. 2. Check if the compiler has MPI support built-in. This is the case if the user passed a - compiler wrapper as ``CMAKE_<LANG>_COMPILER`` or if they're on a Cray system. + compiler wrapper as ``CMAKE_<LANG>_COMPILER`` or if they use Cray system compiler wrappers. 3. Attempt to find an MPI compiler wrapper and determine the compiler information from it. 4. Try to find an MPI implementation that does not ship such a wrapper by guessing settings. Currently, only Microsoft MPI and MPICH2 on Windows are supported. @@ -333,6 +333,11 @@ set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95 mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r mpixlf mpixlf_r mpxlf mpxlf_r) +# Cray Compiler names +set(_MPI_Cray_C_COMPILER_NAMES cc) +set(_MPI_Cray_CXX_COMPILER_NAMES CC) +set(_MPI_Cray_Fortran_COMPILER_NAMES ftn) + # Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler, # attempt all of them. # By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper @@ -488,6 +493,26 @@ function (_MPI_interrogate_compiler LANG) endif() endif() + # Cray compiler wrappers come usually without a separate mpicc/c++/ftn, but offer + # --cray-print-opts=... + if (NOT MPI_COMPILER_RETURN EQUAL 0) + _MPI_check_compiler(${LANG} "--cray-print-opts=cflags" + MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) + + if (MPI_COMPILER_RETURN EQUAL 0) + # Pass --no-as-needed so the mpi library is always linked. Otherwise, the + # Cray compiler wrapper puts an --as-needed flag around the mpi library, + # and it is not linked unless code directly refers to it. + _MPI_check_compiler(${LANG} "--no-as-needed;--cray-print-opts=libs" + MPI_LINK_CMDLINE MPI_COMPILER_RETURN) + + if (NOT MPI_COMPILER_RETURN EQUAL 0) + unset(MPI_COMPILE_CMDLINE) + unset(MPI_LINK_CMDLINE) + endif() + endif() + endif() + # MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the # -showme commands are more specialized. if (NOT MPI_COMPILER_RETURN EQUAL 0) @@ -1520,6 +1545,29 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() endif() + # We are on a Cray, environment identfier: PE_ENV is set (CRAY), and + # have NOT found an mpic++-like compiler wrapper (previous block), + # and we do NOT use the Cray cc/CC compiler wrappers as CC/CXX CMake + # compiler. + # So as a last resort, we now interrogate cc/CC/ftn for MPI flags. + if(DEFINED ENV{PE_ENV} AND NOT "${MPI_${LANG}_COMPILER}") + set(MPI_PINNED_COMPILER TRUE) + find_program(MPI_${LANG}_COMPILER + NAMES ${_MPI_Cray_${LANG}_COMPILER_NAMES} + PATH_SUFFIXES bin sbin + DOC "MPI compiler for ${LANG}" + ) + + # If we haven't made the implicit compiler test yet, perform it now. + if(NOT MPI_${LANG}_TRIED_IMPLICIT) + _MPI_create_imported_target(${LANG}) + _MPI_check_lang_works(${LANG} TRUE) + endif() + + set(MPI_${LANG}_WORKS_IMPLICIT TRUE) + _MPI_interrogate_compiler(${LANG}) + endif() + if(NOT MPI_PINNED_COMPILER AND NOT MPI_${LANG}_WRAPPER_FOUND) # If MPI_PINNED_COMPILER wasn't given, and the MPI compiler we potentially found didn't work, we withdraw it. set(MPI_${LANG}_COMPILER "MPI_${LANG}_COMPILER-NOTFOUND" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE) From 36979f5b438b39599b074a291ad3cca3bfafc6bc Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 13 Jul 2021 10:28:48 -0400 Subject: [PATCH 0909/1519] FindPkgConfig: Tolerate PKG_CONFIG_SYSTEM_LIBRARY_PATH in environment Tell `pkg-config --libs` not to filter out `-L` flags for entries of `PKG_CONFIG_SYSTEM_LIBRARY_PATH` (and `LIBRARY_PATH` for `pkgconf`). We should always search everywhere the `.pc` file expects. Fixes: #22148 --- Modules/FindPkgConfig.cmake | 12 ++++++++ .../FindPkgConfig_LIBRARY_PATH-stdout.txt | 3 ++ .../FindPkgConfig_LIBRARY_PATH.cmake | 29 +++++++++++++++++++ .../RunCMake/FindPkgConfig/RunCMakeTest.cmake | 4 +++ 4 files changed, 48 insertions(+) create mode 100644 Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt create mode 100644 Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index d39bbd03a8f..a28f6bcd1f7 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -403,6 +403,14 @@ macro(_pkg_set_path_internal) unset(_lib_dirs) unset(_pkgconfig_path) endif() + + # Tell pkg-config not to strip any -L paths so we can search them all. + if(DEFINED ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS}) + set(_pkgconfig_allow_system_libs_old "$ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS}") + else() + unset(_pkgconfig_allow_system_libs_old) + endif() + set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 0) endmacro() macro(_pkg_restore_path_internal) @@ -410,6 +418,10 @@ macro(_pkg_restore_path_internal) # Restore the environment variable set(ENV{PKG_CONFIG_PATH} "${_pkgconfig_path_old}") endif() + if(DEFINED _pkgconfig_allow_system_libs_old) + set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} "${_pkgconfig_allow_system_libs_old}") + unset(_pkgconfig_allow_system_libs_old) + endif() unset(_extra_paths) unset(_pkgconfig_path_old) diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt new file mode 100644 index 00000000000..6615d805a60 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt @@ -0,0 +1,3 @@ +-- ZOT_LIBRARIES='zot' +-- ZOT_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/zot/lib/prefix-zot-suffix' +-- ZOT_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/zot/lib;-lzot' diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake new file mode 100644 index 00000000000..9f654b50a90 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake @@ -0,0 +1,29 @@ +find_package(PkgConfig REQUIRED) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/pkgconfig/zot.pc" " +prefix=${CMAKE_CURRENT_BINARY_DIR}/zot +libdir=\${prefix}/lib + +Name: Zot +Description: Dummy packaget to test LIBRARY_DIR support +Version: 1.0 +Libs: -L\${libdir} -lzot +") + +# Create a "library" file to find in libdir. +set(CMAKE_FIND_LIBRARY_PREFIXES "prefix-") +set(CMAKE_FIND_LIBRARY_SUFFIXES "-suffix") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/prefix-zot-suffix") + +# 'pkg-config --libs' drops -L flags in PKG_CONFIG_SYSTEM_LIBRARY_PATH by default. +set(ENV{PKG_CONFIG_SYSTEM_LIBRARY_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib") + +# 'pkgconf --libs' also drops -L flags in LIBRARY_PATH by default. +set(ENV{LIBRARY_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib") + +set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/pkgconfig") +pkg_check_modules(ZOT REQUIRED zot) + +message(STATUS "ZOT_LIBRARIES='${ZOT_LIBRARIES}'") +message(STATUS "ZOT_LINK_LIBRARIES='${ZOT_LINK_LIBRARIES}'") +message(STATUS "ZOT_LDFLAGS='${ZOT_LDFLAGS}'") diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index 17e046a2b8c..81a473221eb 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -31,4 +31,8 @@ if (PKG_CONFIG_FOUND) run_cmake(FindPkgConfig_VERSION_OPERATORS) run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME) run_cmake(FindPkgConfig_empty_target) + + if(NOT RunCMake_BINARY_DIR MATCHES " ") + run_cmake(FindPkgConfig_LIBRARY_PATH) + endif() endif () From 33f0505f015c766b62a9c6b0d3961fe71b405d06 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 22 Jun 2021 12:59:37 -0400 Subject: [PATCH 0910/1519] cmGeneratorTarget: Simplify ExpandLinkItems signature --- Source/cmGeneratorTarget.cxx | 47 +++++++++++++----------------------- Source/cmGeneratorTarget.h | 7 ++---- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 300c13b557c..47975afca54 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6372,12 +6372,12 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( return maybeItem; } -void cmGeneratorTarget::ExpandLinkItems( - std::string const& prop, std::string const& value, std::string const& config, - cmGeneratorTarget const* headTarget, bool usage_requirements_only, - std::vector<cmLinkItem>& items, std::vector<cmLinkItem>& objects, - bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition, - bool& hadLinkLanguageSensitiveCondition) const +void cmGeneratorTarget::ExpandLinkItems(std::string const& prop, + std::string const& value, + std::string const& config, + cmGeneratorTarget const* headTarget, + bool usage_requirements_only, + cmLinkInterface& iface) const { // Keep this logic in sync with ComputeLinkImplementationLibraries. cmGeneratorExpression ge; @@ -6406,17 +6406,17 @@ void cmGeneratorTarget::ExpandLinkItems( cmSourceFile const* sf = mf->GetSource(maybeObj, cmSourceFileLocationKind::Known); if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { - objects.emplace_back(std::move(*maybeItem)); + iface.Objects.emplace_back(std::move(*maybeItem)); continue; } } } - items.emplace_back(std::move(*maybeItem)); + iface.Libraries.emplace_back(std::move(*maybeItem)); } } - hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); - hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition(); - hadLinkLanguageSensitiveCondition = + iface.HadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); + iface.HadContextSensitiveCondition = cge->GetHadContextSensitiveCondition(); + iface.HadLinkLanguageSensitiveCondition = cge->GetHadLinkLanguageSensitiveCondition(); } @@ -6918,10 +6918,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( if (explicitLibraries) { // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config, - headTarget, usage_requirements_only, iface.Libraries, - iface.Objects, iface.HadHeadSensitiveCondition, - iface.HadContextSensitiveCondition, - iface.HadLinkLanguageSensitiveCondition); + headTarget, usage_requirements_only, iface); return; } @@ -6942,22 +6939,15 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( !this->PolicyWarnedCMP0022 && !usage_requirements_only) { // Compare the link implementation fallback link interface to the // preferred new link interface property and warn if different. - std::vector<cmLinkItem> ifaceLibs; - std::vector<cmLinkItem> ifaceObjects; + cmLinkInterface ifaceNew; static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if (cmProp newExplicitLibraries = this->GetProperty(newProp)) { - bool hadHeadSensitiveConditionDummy = false; - bool hadContextSensitiveConditionDummy = false; - bool hadLinkLanguageSensitiveConditionDummy = false; this->ExpandLinkItems(newProp, *newExplicitLibraries, config, - headTarget, usage_requirements_only, ifaceLibs, - ifaceObjects, hadHeadSensitiveConditionDummy, - hadContextSensitiveConditionDummy, - hadLinkLanguageSensitiveConditionDummy); + headTarget, usage_requirements_only, ifaceNew); } - if (ifaceLibs != iface.Libraries) { + if (ifaceNew.Libraries != iface.Libraries) { std::string oldLibraries = cmJoin(impl->Libraries, ";"); - std::string newLibraries = cmJoin(ifaceLibs, ";"); + std::string newLibraries = cmJoin(ifaceNew.Libraries, ";"); if (oldLibraries.empty()) { oldLibraries = "(empty)"; } @@ -7095,10 +7085,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.Multiplicity = info->Multiplicity; cmExpandList(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, - headTarget, usage_requirements_only, iface.Libraries, - iface.Objects, iface.HadHeadSensitiveCondition, - iface.HadContextSensitiveCondition, - iface.HadLinkLanguageSensitiveCondition); + headTarget, usage_requirements_only, iface); std::vector<std::string> deps = cmExpandedList(info->SharedDeps); LookupLinkItemScope scope{ this->LocalGenerator }; for (std::string const& dep : deps) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 09f4167c764..bd4e08fc59f 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1041,11 +1041,8 @@ class cmGeneratorTarget std::string const& config, const cmGeneratorTarget* headTarget, bool usage_requirements_only, - std::vector<cmLinkItem>& items, - std::vector<cmLinkItem>& objects, - bool& hadHeadSensitiveCondition, - bool& hadContextSensitiveCondition, - bool& hadLinkLanguageSensitiveCondition) const; + cmLinkInterface& iface) const; + struct LookupLinkItemScope { cmLocalGenerator const* LG; From 8112480921557ef7d290b3ff3038c22152539d53 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 22 Jun 2021 13:05:04 -0400 Subject: [PATCH 0911/1519] cmGeneratorTarget: Clarify ExpandLinkItems local variable role --- Source/cmGeneratorTarget.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 47975afca54..793375006b8 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6399,19 +6399,22 @@ void cmGeneratorTarget::ExpandLinkItems(std::string const& prop, for (std::string const& lib : libs) { if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(lib, cge->GetBacktrace(), &scope)) { - if (!maybeItem->Target) { + cmLinkItem item = std::move(*maybeItem); + + if (!item.Target) { // Report explicitly linked object files separately. - std::string const& maybeObj = maybeItem->AsStr(); + std::string const& maybeObj = item.AsStr(); if (cmSystemTools::FileIsFullPath(maybeObj)) { cmSourceFile const* sf = mf->GetSource(maybeObj, cmSourceFileLocationKind::Known); if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { - iface.Objects.emplace_back(std::move(*maybeItem)); + iface.Objects.emplace_back(std::move(item)); continue; } } } - iface.Libraries.emplace_back(std::move(*maybeItem)); + + iface.Libraries.emplace_back(std::move(item)); } } iface.HadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); From ff97944806d2d49ced0a11447659f7a6b2036e26 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 22 Jun 2021 13:09:01 -0400 Subject: [PATCH 0912/1519] cmGeneratorTarget: Clarify cmLinkImplItem constructor call --- Source/cmGeneratorTarget.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 793375006b8..c021e0fb063 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -7628,6 +7628,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr, this->LinkerLanguage); + bool const fromGenex = evaluated != *le; cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; @@ -7699,7 +7700,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } } - impl.Libraries.emplace_back(std::move(item), evaluated != *le); + impl.Libraries.emplace_back(std::move(item), fromGenex); } std::set<std::string> const& seenProps = cge->GetSeenTargetProperties(); From d9e4b474320a68b51ca3aa4a91ac0671ffc3981f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 24 Jun 2021 13:38:05 -0400 Subject: [PATCH 0913/1519] cmGeneratorTarget: Clarify logic recognizing explicit link interface --- Source/cmGeneratorTarget.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index c021e0fb063..17237bb5069 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6916,20 +6916,20 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( return; } iface.Exists = true; + + // If CMP0022 is NEW then the plain tll signature sets the + // INTERFACE_LINK_LIBRARIES property. Even if the project + // clears it, the link interface is still explicit. iface.Explicit = cmp0022NEW || explicitLibraries; if (explicitLibraries) { // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config, headTarget, usage_requirements_only, iface); - return; } - // If CMP0022 is NEW then the plain tll signature sets the - // INTERFACE_LINK_LIBRARIES, so if we get here then the project - // cleared the property explicitly and we should not fall back - // to the link implementation. - if (cmp0022NEW) { + // If the link interface is explicit, do not fall back to the link impl. + if (iface.Explicit) { return; } From e274bd6fd94af75f14b62e713b66a923b1c24378 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 14 Jul 2021 00:01:12 -0400 Subject: [PATCH 0914/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fc80b1fb53d..1393da92654 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210713) +set(CMake_VERSION_PATCH 20210714) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 509ef50a06fd690a85ca245a7221d001a3d6937f Mon Sep 17 00:00:00 2001 From: Lingkai Dong <lingkai.dong@arm.com> Date: Tue, 13 Jul 2021 15:32:04 +0100 Subject: [PATCH 0915/1519] ARMClang: Fix regression in check for working compiler Given the compiler to use, `CMakeFindBinUtils.cmake` automatically determines a number of tools including linker (CMAKE_LINKER) and archiver (CMAKE_AR) and stores them in a generated file `CMakeCCompiler.cmake` as non-CACHE entries. The compiler-specific ARMClang.cmake then tries to override CMAKE_LINKER and CMAKE_AR as CACHE entries. Following the introduction of CMP0126, which is set to NEW in the test for a working compiler, setting a CACHE entry does not replace a normal entry of the same name anymore, resulting in a failed test due to wrong linker and archiver. To fix this, set CMAKE_LINKER and CMAKE_AR for ARMClang directly in `CMakeFindBinUtils.cmake` as is done for other compilers. Check for them in `ARMClang.cmake` to safeguard cases when a project explicitly includes `ARMClang.cmake` prior to compiler determination (which some projects do to work around other problems in older CMake versions). --- Modules/CMakeFindBinUtils.cmake | 3 +++ Modules/Compiler/ARMClang.cmake | 17 ++++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index ec6bc8d8ce3..3162ec57fa7 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -134,6 +134,9 @@ else() list(PREPEND _CMAKE_READELF_NAMES "llvm-readelf") list(PREPEND _CMAKE_DLLTOOL_NAMES "llvm-dlltool") list(PREPEND _CMAKE_ADDR2LINE_NAMES "llvm-addr2line") + elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL ARMClang) + list(PREPEND _CMAKE_AR_NAMES "armar") + list(PREPEND _CMAKE_LINKER_NAMES "armlink") endif() list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE) diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake index 354c11ddbf2..c83922079a3 100644 --- a/Modules/Compiler/ARMClang.cmake +++ b/Modules/Compiler/ARMClang.cmake @@ -1,6 +1,12 @@ if(_ARMClang_CMAKE_LOADED) return() endif() + +# This file requires CMAKE_LINKER and CMAKE_AR set by CMakeFindBinUtils.cmake. +if(NOT (DEFINED CMAKE_LINKER AND DEFINED CMAKE_AR)) + return() +endif() + set(_ARMClang_CMAKE_LOADED TRUE) # Save the CMP0123 setting in a variable used both below and by try_compile. @@ -9,19 +15,8 @@ cmake_policy(GET CMP0123 CMAKE_ARMClang_CMP0123) cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST -get_filename_component(_CMAKE_C_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH) -get_filename_component(_CMAKE_CXX_TOOLCHAIN_LOCATION "${CMAKE_CXX_COMPILER}" PATH) - set(CMAKE_EXECUTABLE_SUFFIX ".elf") -find_program(CMAKE_ARMClang_LINKER armlink HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" ) -find_program(CMAKE_ARMClang_AR armar HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" ) - -set(CMAKE_LINKER "${CMAKE_ARMClang_LINKER}" CACHE FILEPATH "The ARMClang linker" FORCE) -mark_as_advanced(CMAKE_ARMClang_LINKER) -set(CMAKE_AR "${CMAKE_ARMClang_AR}" CACHE FILEPATH "The ARMClang archiver" FORCE) -mark_as_advanced(CMAKE_ARMClang_AR) - if (CMAKE_LINKER MATCHES "armlink") set(__CMAKE_ARMClang_USING_armlink TRUE) set(CMAKE_LIBRARY_PATH_FLAG "--userlibpath=") From ff7a2e37bfff23ce1751a93b3eba179fbf32a9b6 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 10:10:23 -0400 Subject: [PATCH 0916/1519] CMake 3.21.0 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 65bdb2cb9a0..590cf9cac54 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 3) +#set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From fc54e68c053436c22c4c17a3c265f59974852179 Mon Sep 17 00:00:00 2001 From: Seth R Johnson <johnsonsr@ornl.gov> Date: Tue, 13 Jul 2021 18:14:10 -0400 Subject: [PATCH 0917/1519] Find{BLAS,LAPACK}: improve found message on Cray With Cray compiler wrappers (implicitly tested on OLCF Spock) the BLAS and LAPACK libraries are automatically linked as necessary through the wrapper script and programming environment. With this change, the configure output is: ``` -- Found BLAS: implicitly linked <snip> -- Found LAPACK: implicitly linked ``` rather than ``` -- Found BLAS: 1 <snip> -- Found LAPACK: LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES ``` --- Modules/FindBLAS.cmake | 2 ++ Modules/FindLAPACK.cmake | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 726ff75bf88..a6fd2c9ca53 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -386,6 +386,8 @@ if(BLA_VENDOR STREQUAL "All") ) endif() if(BLAS_WORKS) + # Give a more helpful "found" message + set(BLAS_WORKS "implicitly linked") set(_blas_fphsa_req_var BLAS_WORKS) endif() endif() diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 3146e06d44e..d753244e3ea 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -350,7 +350,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) "lib/${LAPACK_mkl_ARCH_NAME}" ) - # First try empty lapack libs + # First try empty lapack libs (implicitly linked or automatic from BLAS) if(NOT ${_LIBRARIES}) check_lapack_libraries( ${_LIBRARIES} @@ -363,6 +363,11 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) "${LAPACK_mkl_LIB_PATH_SUFFIXES}" "${_BLAS_LIBRARIES}" ) + if(LAPACK_WORKS AND NOT _BLAS_LIBRARIES) + # Give a more helpful "found" message + set(LAPACK_WORKS "implicitly linked") + set(_lapack_fphsa_req_var LAPACK_WORKS) + endif() endif() # Then try the search libs From 76487b04b152b2dc6abc258b21306f58c57a3e80 Mon Sep 17 00:00:00 2001 From: Seth R Johnson <johnsonsr@ornl.gov> Date: Tue, 13 Jul 2021 21:27:52 -0400 Subject: [PATCH 0918/1519] Find{BLAS,LAPACK}: clean variables --- Modules/FindBLAS.cmake | 35 +++++++++++++++++++---------------- Modules/FindLAPACK.cmake | 21 ++++++++++++--------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index a6fd2c9ca53..0898240edf1 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -441,7 +441,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") if(BLA_F95) set(BLAS_mkl_SEARCH_SYMBOL "sgemm_f95") - set(_LIBRARIES BLAS95_LIBRARIES) + set(_BLAS_LIBRARIES BLAS95_LIBRARIES) if(WIN32) # Find the main file (32-bit or 64-bit) set(BLAS_SEARCH_LIBS_WIN_MAIN "") @@ -503,7 +503,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") endif() else() set(BLAS_mkl_SEARCH_SYMBOL sgemm) - set(_LIBRARIES BLAS_LIBRARIES) + set(_BLAS_LIBRARIES BLAS_LIBRARIES) if(WIN32) # Find the main file (32-bit or 64-bit) set(BLAS_SEARCH_LIBS_WIN_MAIN "") @@ -615,15 +615,15 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") "lib/${BLAS_mkl_ARCH_NAME}" ) - foreach(IT ${BLAS_SEARCH_LIBS}) - string(REPLACE " " ";" SEARCH_LIBS ${IT}) - if(NOT ${_LIBRARIES}) + foreach(_search ${BLAS_SEARCH_LIBS}) + string(REPLACE " " ";" _search ${_search}) + if(NOT ${_BLAS_LIBRARIES}) check_blas_libraries( - ${_LIBRARIES} + ${_BLAS_LIBRARIES} BLAS ${BLAS_mkl_SEARCH_SYMBOL} "" - "${SEARCH_LIBS}" + "${_search}" "${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}" "${BLAS_mkl_MKLROOT}" "${BLAS_mkl_LIB_PATH_SUFFIXES}" @@ -631,6 +631,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") endif() endforeach() + unset(_search) unset(BLAS_mkl_ILP_MODE) unset(BLAS_mkl_INTFACE) unset(BLAS_mkl_THREADING) @@ -736,14 +737,14 @@ if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All") # Check for 64bit Integer support if(BLA_VENDOR MATCHES "_ilp64") - set(BLAS_armpl_LIB "armpl_ilp64") + set(_blas_armpl_lib "armpl_ilp64") else() - set(BLAS_armpl_LIB "armpl_lp64") + set(_blas_armpl_lib "armpl_lp64") endif() # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp if(BLA_VENDOR MATCHES "_mp") - set(BLAS_armpl_LIB "${BLAS_armpl_LIB}_mp") + set(_blas_armpl_lib "${_blas_armpl_lib}_mp") endif() if(NOT BLAS_LIBRARIES) @@ -752,13 +753,13 @@ if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All") BLAS sgemm "" - "${BLAS_armpl_LIB}" + "${_blas_armpl_lib}" "" "" "" ) endif() - + set(_blas_armpl_lib) endif() # FLAME's blis library? (https://github.com/flame/blis) @@ -1089,11 +1090,11 @@ endif() # Elbrus Math Library? if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") - set(BLAS_EML_LIB "eml") + set(_blas_eml_lib "eml") # Check for OpenMP support, VIA BLA_VENDOR of eml_mt if(BLA_VENDOR MATCHES "_mt") - set(BLAS_EML_LIB "${BLAS_EML_LIB}_mt") + set(_blas_eml_lib "${BLAS_EML_LIB}_mt") endif() if(NOT BLAS_LIBRARIES) @@ -1102,13 +1103,13 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") BLAS sgemm "" - "${BLAS_EML_LIB}" + "${_blas_eml_lib}" "" "" "" ) endif() - + set(_blas_eml_lib) endif() # Fujitsu SSL2 Library? @@ -1165,3 +1166,5 @@ if(NOT BLA_F95) endif() _add_blas_target() +unset(_blas_fphsa_req_var) +unset(_BLAS_LIBRARIES) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index d753244e3ea..aa5423a434c 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -298,7 +298,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) if(BLA_F95) set(LAPACK_mkl_SEARCH_SYMBOL "cheev_f95") - set(_LIBRARIES LAPACK95_LIBRARIES) + set(_LAPACK_LIBRARIES LAPACK95_LIBRARIES) set(_BLAS_LIBRARIES ${BLAS95_LIBRARIES}) # old @@ -311,7 +311,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) "mkl_lapack95_${LAPACK_mkl_ILP_MODE}") else() set(LAPACK_mkl_SEARCH_SYMBOL "cheev") - set(_LIBRARIES LAPACK_LIBRARIES) + set(_LAPACK_LIBRARIES LAPACK_LIBRARIES) set(_BLAS_LIBRARIES ${BLAS_LIBRARIES}) # old and new >= 10.3 @@ -351,9 +351,9 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) ) # First try empty lapack libs (implicitly linked or automatic from BLAS) - if(NOT ${_LIBRARIES}) + if(NOT ${_LAPACK_LIBRARIES}) check_lapack_libraries( - ${_LIBRARIES} + ${_LAPACK_LIBRARIES} LAPACK ${LAPACK_mkl_SEARCH_SYMBOL} "" @@ -371,15 +371,15 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) endif() # Then try the search libs - foreach(IT ${LAPACK_SEARCH_LIBS}) - string(REPLACE " " ";" SEARCH_LIBS ${IT}) - if(NOT ${_LIBRARIES}) + foreach(_search ${LAPACK_SEARCH_LIBS}) + string(REPLACE " " ";" _search ${_search}) + if(NOT ${_LAPACK_LIBRARIES}) check_lapack_libraries( - ${_LIBRARIES} + ${_LAPACK_LIBRARIES} LAPACK ${LAPACK_mkl_SEARCH_SYMBOL} "" - "${SEARCH_LIBS}" + "${_search}" "${CMAKE_THREAD_LIBS_INIT};${LAPACK_mkl_LM};${LAPACK_mkl_LDL}" "${LAPACK_mkl_MKLROOT}" "${LAPACK_mkl_LIB_PATH_SUFFIXES}" @@ -388,6 +388,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) endif() endforeach() + unset(_search) unset(LAPACK_mkl_ILP_MODE) unset(LAPACK_mkl_SEARCH_SYMBOL) unset(LAPACK_mkl_LM) @@ -651,3 +652,5 @@ if(LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES") endif() _add_lapack_target() +unset(_lapack_fphsa_req_var) +unset(_LAPACK_LIBRARIES) From 79e139e3d317ced27f4b01db8ca977913a8ea370 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 14 Jul 2021 13:25:51 -0400 Subject: [PATCH 0919/1519] ci: use CMake 3.21.0 --- .gitlab/ci/cmake.ps1 | 4 ++-- .gitlab/ci/cmake.sh | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab/ci/cmake.ps1 b/.gitlab/ci/cmake.ps1 index a16fe459baf..5d01e3f9e33 100755 --- a/.gitlab/ci/cmake.ps1 +++ b/.gitlab/ci/cmake.ps1 @@ -1,7 +1,7 @@ $erroractionpreference = "stop" -$version = "3.21.0-rc2" -$sha256sum = "AF88454243BCBAF9F537458562D669DAF0DBEDA8C0FD82C1D93BC2B4285AE4C7" +$version = "3.21.0" +$sha256sum = "C7B88C907A753F4EC86E43DDC89F91F70BF1B011859142F7F29E6D51EA4ABB3C" $filename = "cmake-$version-windows-x86_64" $tarball = "$filename.zip" diff --git a/.gitlab/ci/cmake.sh b/.gitlab/ci/cmake.sh index ff59d2867bc..c37f6dc55ff 100755 --- a/.gitlab/ci/cmake.sh +++ b/.gitlab/ci/cmake.sh @@ -2,22 +2,22 @@ set -e -readonly version="3.21.0-rc2" +readonly version="3.21.0" case "$(uname -s)-$(uname -m)" in Linux-x86_64) shatool="sha256sum" - sha256sum="31d4f5f4bb8793127eb441c8311fd4baad4d2a86c26fd37b43d4ef23887c332e" + sha256sum="d54ef6909f519740bc85cec07ff54574cd1e061f9f17357d9ace69f61c6291ce" platform="linux-x86_64" ;; Linux-aarch64) shatool="sha256sum" - sha256sum="437565f32e3f28fd8322f96a5472b196825eaf5ef6139e1c383afe624decc476" + sha256sum="b1e46825bf370f45f8f47c3a497b1122759ee41fbd60187e525f517a4b0934eb" platform="linux-aarch64" ;; Darwin-*) shatool="shasum -a 256" - sha256sum="5ab0ee4edb45de33080f571cf69300b2abd92dc02a9c624b3c289a4a14cab160" + sha256sum="c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" platform="macos-universal" ;; *) From 731cfd45fda72cd0962efe049b252645bc536c68 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 14 Jul 2021 15:23:48 -0400 Subject: [PATCH 0920/1519] Help/ctest_memcheck: mention `ctest_test` arguments These are handled internally by inheriting `ctest_test`'s argument bindings. Synchronize the documentation. --- Help/command/ctest_memcheck.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Help/command/ctest_memcheck.rst b/Help/command/ctest_memcheck.rst index f655c2eb2e0..8b79077946f 100644 --- a/Help/command/ctest_memcheck.rst +++ b/Help/command/ctest_memcheck.rst @@ -17,10 +17,15 @@ Perform the :ref:`CTest MemCheck Step` as a :ref:`Dashboard Client`. [EXCLUDE_FIXTURE_SETUP <regex>] [EXCLUDE_FIXTURE_CLEANUP <regex>] [PARALLEL_LEVEL <level>] + [RESOURCE_SPEC_FILE <file>] [TEST_LOAD <threshold>] [SCHEDULE_RANDOM <ON|OFF>] + [STOP_ON_FAILURE] [STOP_TIME <time-of-day>] [RETURN_VALUE <result-var>] + [CAPTURE_CMAKE_ERROR <result-var>] + [REPEAT <mode>:<n>] + [OUTPUT_JUNIT <file>] [DEFECT_COUNT <defect-count-var>] [QUIET] ) From 32ff836e2adcfefd9ff8f7bd24d20da30c42c62f Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 14 Jul 2021 16:47:16 -0400 Subject: [PATCH 0921/1519] TestDriver: suppress deprecated header lints for time.h Similar to the other includes, this one should be suppressed as well. --- Templates/TestDriver.cxx.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index 61134172edc..845f799ec67 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -2,7 +2,7 @@ #include <stdio.h> /* NOLINT */ #include <stdlib.h> /* NOLINT */ #include <string.h> /* NOLINT */ -#include <time.h> +#include <time.h> /* NOLINT */ #if defined(_MSC_VER) #pragma warning(disable : 4996) /* deprecation */ From 0bb3d457cbc57246c32a4d51d55390c40396043e Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 14 Jul 2021 19:53:54 -0400 Subject: [PATCH 0922/1519] TestDriver: use `CM_NULL` to avoid lints about `nullptr` usage --- Templates/TestDriver.cxx.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index 845f799ec67..6ced8001ca2 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -122,7 +122,7 @@ int main(int ac, char* av[]) if (run_all == 1) { clock_t t; int status = 0; - const char* status_message = NULL; + const char* status_message = CM_NULL; printf("TAP version 13\n"); printf("1..%d\n", NumTests); for (i = 0; i < NumTests; ++i) { From 769c539d599ca1911e4d63a2b8e248d1e26bd078 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 15 Jul 2021 00:01:14 -0400 Subject: [PATCH 0923/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1393da92654..520ac4bd708 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210714) +set(CMake_VERSION_PATCH 20210715) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1aba3a8367f8e9a6f12e409f170008d930f87855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st> Date: Thu, 15 Jul 2021 12:26:40 +0300 Subject: [PATCH 0924/1519] libuv: Fix building with mingw toolchains for ARM/AArch64 This is a backport of f9ad802fa5dd5afe6730f8e00cfdbf98f1d7a969 from the v1.x branch from upstream libuv: mingw: fix building for ARM/AArch64 Don't use x86 inline assembly in these cases, but fall back to __sync_fetch_and_or, similar to _InterlockedOr8 in the MSVC case. This corresponds to what is done in src/unix/atomic-ops.h, where ARM/AArch64 cases end up implementing cmpxchgi with __sync_val_compare_and_swap. PR-URL: https://github.com/libuv/libuv/pull/3236 Reviewed-By: Jameson Nash <vtjnash@gmail.com> --- Utilities/cmlibuv/src/win/atomicops-inl.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Utilities/cmlibuv/src/win/atomicops-inl.h b/Utilities/cmlibuv/src/win/atomicops-inl.h index 52713cf305f..2f984c6db0b 100644 --- a/Utilities/cmlibuv/src/win/atomicops-inl.h +++ b/Utilities/cmlibuv/src/win/atomicops-inl.h @@ -39,10 +39,11 @@ static char INLINE uv__atomic_exchange_set(char volatile* target) { return _InterlockedOr8(target, 1); } -#else /* GCC */ +#else /* GCC, Clang in mingw mode */ -/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ static inline char uv__atomic_exchange_set(char volatile* target) { +#if defined(__i386__) || defined(__x86_64__) + /* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ const char one = 1; char old_value; __asm__ __volatile__ ("lock xchgb %0, %1\n\t" @@ -50,6 +51,9 @@ static inline char uv__atomic_exchange_set(char volatile* target) { : "0"(one), "m"(*target) : "memory"); return old_value; +#else + return __sync_fetch_and_or(target, 1); +#endif } #endif From 3ddd7f35760055fc501d454f9029f3987536957b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 15 Jul 2021 12:58:44 -0400 Subject: [PATCH 0925/1519] enable_language: Fix test for working compiler with CMP0126 NEW behavior Update the logic that converts a `try_compile` result from a cache entry to a normal variable to tolerate an existing normal variable under CMP0126 NEW behavior. Otherwise the `try_compile` result is ignored because CMake uses the false value of the normal variable, and CMake incorrectly reports that the compiler does not work. This went unnoticed for some languages (e.g. C and CXX) because the check for a working compiler is skipped if ABI detection works. It does affect other languages (e.g. CSharp). Fixes: #22423 --- Modules/CMakeTestCCompiler.cmake | 3 +++ Modules/CMakeTestCSharpCompiler.cmake | 3 +++ Modules/CMakeTestCUDACompiler.cmake | 4 ++++ Modules/CMakeTestCXXCompiler.cmake | 3 +++ Modules/CMakeTestFortranCompiler.cmake | 3 +++ Modules/CMakeTestHIPCompiler.cmake | 3 +++ Modules/CMakeTestOBJCCompiler.cmake | 3 +++ Modules/CMakeTestOBJCXXCompiler.cmake | 3 +++ Modules/CMakeTestSwiftCompiler.cmake | 3 +++ Tests/CSharpOnly/CMakeLists.txt | 3 +++ 10 files changed, 31 insertions(+) diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index 03f2db2d225..ae5aa27af93 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -50,6 +50,9 @@ if(NOT CMAKE_C_COMPILER_WORKS) "int main(int argc, char* argv[])\n" "#endif\n" "{ (void)argv; return argc-1;}\n") + # Clear result from normal variable. + unset(CMAKE_C_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_C_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c OUTPUT_VARIABLE __CMAKE_C_COMPILER_OUTPUT) diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake index 1119a45632c..adea250fa0e 100644 --- a/Modules/CMakeTestCSharpCompiler.cmake +++ b/Modules/CMakeTestCSharpCompiler.cmake @@ -30,6 +30,9 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS) " }" "}" ) + # Clear result from normal variable. + unset(CMAKE_CSharp_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_BINARY_DIR} "${test_compile_file}" OUTPUT_VARIABLE __CMAKE_CSharp_COMPILER_OUTPUT ) diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index a18947bb439..25a365358b9 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -36,6 +36,10 @@ if(NOT CMAKE_CUDA_COMPILER_WORKS) "#endif\n" "int main(){return 0;}\n") + # Clear result from normal variable. + unset(CMAKE_CUDA_COMPILER_WORKS) + + # Puts test result in cache variable. try_compile(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu OUTPUT_VARIABLE __CMAKE_CUDA_COMPILER_OUTPUT) diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index 0d2d0b05304..bbe35334be7 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -43,6 +43,9 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) "# error \"The CMAKE_CXX_COMPILER is set to a C compiler\"\n" "#endif\n" "int main(){return 0;}\n") + # Clear result from normal variable. + unset(CMAKE_CXX_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_CXX_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx OUTPUT_VARIABLE __CMAKE_CXX_COMPILER_OUTPUT) diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index 10fb0a7a660..f25788df49a 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -36,6 +36,9 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS) PRINT *, 'Hello' END ") + # Clear result from normal variable. + unset(CMAKE_Fortran_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_Fortran_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake index d9fcc9d8fea..62f06573ad3 100644 --- a/Modules/CMakeTestHIPCompiler.cmake +++ b/Modules/CMakeTestHIPCompiler.cmake @@ -46,6 +46,9 @@ if(NOT CMAKE_HIP_COMPILER_WORKS) "# error \"The CMAKE_HIP_COMPILER is set to a C/CXX compiler\"\n" "#endif\n" "int main(){return 0;}\n") + # Clear result from normal variable. + unset(CMAKE_HIP_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_HIP_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip OUTPUT_VARIABLE __CMAKE_HIP_COMPILER_OUTPUT) diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake index 298272b85a6..20d1f8be932 100644 --- a/Modules/CMakeTestOBJCCompiler.cmake +++ b/Modules/CMakeTestOBJCCompiler.cmake @@ -47,6 +47,9 @@ if(NOT CMAKE_OBJC_COMPILER_WORKS) "#endif\n" "int main(int argc, char* argv[])\n" "{ (void)argv; return argc-1;}\n") + # Clear result from normal variable. + unset(CMAKE_OBJC_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT) diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake index 36e3efc509f..4f7185f7008 100644 --- a/Modules/CMakeTestOBJCXXCompiler.cmake +++ b/Modules/CMakeTestOBJCXXCompiler.cmake @@ -46,6 +46,9 @@ if(NOT CMAKE_OBJCXX_COMPILER_WORKS) "# error \"The CMAKE_OBJCXX_COMPILER is not an Objective-C++ compiler\"\n" "#endif\n" "int main(){return 0;}\n") + # Clear result from normal variable. + unset(CMAKE_OBJCXX_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT) diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake index d98dc9dfa3b..2f2546f865b 100644 --- a/Modules/CMakeTestSwiftCompiler.cmake +++ b/Modules/CMakeTestSwiftCompiler.cmake @@ -23,6 +23,9 @@ if(NOT CMAKE_Swift_COMPILER_WORKS) PrintTestCompilerStatus("Swift") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift "print(\"CMake\")\n") + # Clear result from normal variable. + unset(CMAKE_Swift_COMPILER_WORKS) + # Puts test result in cache variable. try_compile(CMAKE_Swift_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift OUTPUT_VARIABLE __CMAKE_Swift_COMPILER_OUTPUT) diff --git a/Tests/CSharpOnly/CMakeLists.txt b/Tests/CSharpOnly/CMakeLists.txt index f7928b675f9..efac58cc6f7 100644 --- a/Tests/CSharpOnly/CMakeLists.txt +++ b/Tests/CSharpOnly/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.3) +if(POLICY CMP0126) + cmake_policy(SET CMP0126 NEW) +endif() # a simple CSharp only test case project (CSharpOnly CSharp) From b8d6a21e48d2b331e86f68931a83d56133694204 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 15 Jul 2021 12:45:26 -0400 Subject: [PATCH 0926/1519] VS: Recognize CSharp VS 2019 compiler version v142 --- Modules/CMakeCSharpCompilerId.cs.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/CMakeCSharpCompilerId.cs.in b/Modules/CMakeCSharpCompilerId.cs.in index 987f63aa806..5afe08fd96d 100644 --- a/Modules/CMakeCSharpCompilerId.cs.in +++ b/Modules/CMakeCSharpCompilerId.cs.in @@ -15,6 +15,8 @@ namespace CSharp + "Visual Studio" #elif PlatformToolsetv141 + "Visual Studio" +#elif PlatformToolsetv142 + + "Visual Studio" #else + "unknown" #endif @@ -45,6 +47,8 @@ namespace CSharp + "2015" #elif PlatformToolsetv141 + "2017" +#elif PlatformToolsetv142 + + "2019" #else + "9999" #endif From 63c1262375bc111ad191568d29dbb6d6b8bb34f4 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:04:42 -0400 Subject: [PATCH 0927/1519] VS: Improve v142 CL flag table LanguageStandard ordering --- Templates/MSBuild/FlagTables/v142_CL.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 49776d0fe03..b3637186ce1 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -477,16 +477,16 @@ }, { "name": "LanguageStandard", - "switch": "std:c++20", - "comment": "ISO C++20 Standard", - "value": "stdcpp20", + "switch": "std:c++17", + "comment": "ISO C++17 Standard", + "value": "stdcpp17", "flags": [] }, { "name": "LanguageStandard", - "switch": "std:c++17", - "comment": "ISO C++17 Standard", - "value": "stdcpp17", + "switch": "std:c++20", + "comment": "ISO C++20 Standard", + "value": "stdcpp20", "flags": [] }, { From 7adfd890fb8c44738d64f7ade5eec62f6bafb3df Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 15 Jul 2021 10:44:16 -0400 Subject: [PATCH 0928/1519] VS: Add CSharp VS 2022 compiler version and flag table v143 While the flag tables for C and C++ were generated from MSBuild `.xml` files, the CSharp flag tables were written by hand. Copy the `v142` flag table to use for the `v143` toolset. --- Modules/CMakeCSharpCompilerId.cs.in | 4 + Templates/MSBuild/FlagTables/v143_CSharp.json | 553 ++++++++++++++++++ 2 files changed, 557 insertions(+) create mode 100644 Templates/MSBuild/FlagTables/v143_CSharp.json diff --git a/Modules/CMakeCSharpCompilerId.cs.in b/Modules/CMakeCSharpCompilerId.cs.in index 5afe08fd96d..b43ec043ec5 100644 --- a/Modules/CMakeCSharpCompilerId.cs.in +++ b/Modules/CMakeCSharpCompilerId.cs.in @@ -17,6 +17,8 @@ namespace CSharp + "Visual Studio" #elif PlatformToolsetv142 + "Visual Studio" +#elif PlatformToolsetv143 + + "Visual Studio" #else + "unknown" #endif @@ -49,6 +51,8 @@ namespace CSharp + "2017" #elif PlatformToolsetv142 + "2019" +#elif PlatformToolsetv143 + + "2022" #else + "9999" #endif diff --git a/Templates/MSBuild/FlagTables/v143_CSharp.json b/Templates/MSBuild/FlagTables/v143_CSharp.json new file mode 100644 index 00000000000..ae1bd47bf6b --- /dev/null +++ b/Templates/MSBuild/FlagTables/v143_CSharp.json @@ -0,0 +1,553 @@ +[ + { + "name": "ProjectName", + "switch": "out:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "OutputType", + "switch": "target:exe", + "comment": "", + "value": "Exe", + "flags": [] + }, + { + "name": "OutputType", + "switch": "target:winexe", + "comment": "", + "value": "Winexe", + "flags": [] + }, + { + "name": "OutputType", + "switch": "target:library", + "comment": "", + "value": "Library", + "flags": [] + }, + { + "name": "OutputType", + "switch": "target:module", + "comment": "", + "value": "Module", + "flags": [] + }, + { + "name": "DocumentationFile", + "switch": "doc", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "Platform", + "switch": "platform:x86", + "comment": "", + "value": "x86", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:Itanium", + "comment": "", + "value": "Itanium", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:x64", + "comment": "", + "value": "x64", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:arm", + "comment": "", + "value": "arm", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:anycpu32bitpreferred", + "comment": "", + "value": "anycpu32bitpreferred", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:anycpu", + "comment": "", + "value": "anycpu", + "flags": [] + }, + { + "name": "References", + "switch": "reference:", + "comment": "mit alias", + "value": "", + "flags": [] + }, + { + "name": "References", + "switch": "reference:", + "comment": "dateiliste", + "value": "", + "flags": [] + }, + { + "name": "AddModules", + "switch": "addmodule:", + "comment": "", + "value": "", + "flags": [ + "SemicolonAppendable" + ] + }, + { + "name": "Win32Resource", + "switch": "win32res:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "ApplicationIcon", + "switch": "win32icon:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "ApplicationManifest", + "switch": "win32manifest:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "NoWin32Manifest", + "switch": "nowin32manifest", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DefineDebug", + "switch": "debug", + "comment": "", + "value": "true", + "flags": [ + "Continue" + ] + }, + { + "name": "DebugSymbols", + "switch": "debug", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DebugSymbols", + "switch": "debug-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "DebugSymbols", + "switch": "debug+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:none", + "comment": "", + "value": "none", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:full", + "comment": "", + "value": "full", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:pdbonly", + "comment": "", + "value": "pdbonly", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:portable", + "comment": "", + "value": "portable", + "flags": [] + }, + { + "name": "Optimize", + "switch": "optimize", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "Optimize", + "switch": "optimize-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "Optimize", + "switch": "optimize+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "TreatWarningsAsErrors", + "switch": "warnaserror", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "TreatWarningsAsErrors", + "switch": "warnaserror-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "TreatWarningsAsErrors", + "switch": "warnaserror+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror-", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror+", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired", + "CommaAppendable" + ] + }, + { + "name": "WarningLevel", + "switch": "warn:0", + "comment": "", + "value": "0", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:1", + "comment": "", + "value": "1", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:2", + "comment": "", + "value": "2", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:3", + "comment": "", + "value": "3", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:4", + "comment": "", + "value": "4", + "flags": [] + }, + { + "name": "NoWarn", + "switch": "nowarn:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired", + "CommaAppendable" + ] + }, + { + "name": "CheckForOverflowUnderflow", + "switch": "checked", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "CheckForOverflowUnderflow", + "switch": "checked-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "CheckForOverflowUnderflow", + "switch": "checked+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AllowUnsafeBlocks", + "switch": "unsafe", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AllowUnsafeBlocks", + "switch": "unsafe-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "AllowUnsafeBlocks", + "switch": "unsafe+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DefineConstants", + "switch": "define:", + "comment": "", + "value": "", + "flags": [ + "SemicolonAppendable", + "UserValue" + ] + }, + { + "name": "LangVersion", + "switch": "langversion:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "DelaySign", + "switch": "delaysign", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DelaySign", + "switch": "delaysign-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "DelaySign", + "switch": "delaysign+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AssemblyOriginatorKeyFile", + "switch": "keyfile", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "KeyContainerName", + "switch": "keycontainer", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "NoLogo", + "switch": "nologo", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "NoConfig", + "switch": "noconfig", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "BaseAddress", + "switch": "baseaddress:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "CodePage", + "switch": "codepage", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "Utf8Output", + "switch": "utf8output", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "MainEntryPoint", + "switch": "main:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "GenerateFullPaths", + "switch": "fullpaths", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "FileAlignment", + "switch": "filealign", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "PdbFile", + "switch": "pdb:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "NoStandardLib", + "switch": "nostdlib", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "NoStandardLib", + "switch": "nostdlib-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "NoStandardLib", + "switch": "nostdlib+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "SubsystemVersion", + "switch": "subsystemversion", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "AdditionalLibPaths", + "switch": "lib:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:none", + "comment": "Do Not Send Report", + "value": "none", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:prompt", + "comment": "Prompt Immediately", + "value": "prompt", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:queue", + "comment": "Queue For Next Login", + "value": "queue", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:send", + "comment": "Send Automatically", + "value": "send", + "flags": [] + } +] From c152d08c52f64c0f2004d894da686b2ccd69fe3f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 12:47:17 -0400 Subject: [PATCH 0929/1519] VS: Add v143 flag tables for VS 17.0 Preview 2 Run the commands python3 Source/cmConvertMSBuildXMLToJSON.py -t v143 \ 'c:/.../2022/Preview/MSBuild/Microsoft/VC/v170/1033/cl.xml' python3 Source/cmConvertMSBuildXMLToJSON.py -t v143 \ 'c:/.../2022/Preview/MSBuild/Microsoft/VC/v170/1033/link.xml' To generate `Templates/MSBuild/FlagTables/v143_{CL,Link}.json`. We can re-use `Templates/MSBuild/FlagTables/v14_LIB.json`. --- Templates/MSBuild/FlagTables/v143_CL.json | 1553 +++++++++++++++++++ Templates/MSBuild/FlagTables/v143_Link.json | 1429 +++++++++++++++++ 2 files changed, 2982 insertions(+) create mode 100644 Templates/MSBuild/FlagTables/v143_CL.json create mode 100644 Templates/MSBuild/FlagTables/v143_Link.json diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json new file mode 100644 index 00000000000..918fe81cdbb --- /dev/null +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -0,0 +1,1553 @@ +[ + { + "name": "DebugInformationFormat", + "switch": "", + "comment": "None", + "value": "None", + "flags": [] + }, + { + "name": "DebugInformationFormat", + "switch": "Z7", + "comment": "C7 compatible", + "value": "OldStyle", + "flags": [] + }, + { + "name": "DebugInformationFormat", + "switch": "Zi", + "comment": "Program Database", + "value": "ProgramDatabase", + "flags": [] + }, + { + "name": "DebugInformationFormat", + "switch": "ZI", + "comment": "Program Database for Edit And Continue", + "value": "EditAndContinue", + "flags": [] + }, + { + "name": "CompileAsManaged", + "switch": "", + "comment": "No Common Language RunTime Support", + "value": "false", + "flags": [] + }, + { + "name": "CompileAsManaged", + "switch": "clr", + "comment": "Common Language RunTime Support", + "value": "true", + "flags": [] + }, + { + "name": "CompileAsManaged", + "switch": "clr:pure", + "comment": "Pure MSIL Common Language RunTime Support", + "value": "Pure", + "flags": [] + }, + { + "name": "CompileAsManaged", + "switch": "clr:safe", + "comment": "Safe MSIL Common Language RunTime Support", + "value": "Safe", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "W0", + "comment": "Turn Off All Warnings", + "value": "TurnOffAllWarnings", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "W1", + "comment": "Level1", + "value": "Level1", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "W2", + "comment": "Level2", + "value": "Level2", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "W3", + "comment": "Level3", + "value": "Level3", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "W4", + "comment": "Level4", + "value": "Level4", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "Wall", + "comment": "EnableAllWarnings", + "value": "EnableAllWarnings", + "flags": [] + }, + { + "name": "DiagnosticsFormat", + "switch": "diagnostics:caret", + "comment": "Caret", + "value": "Caret", + "flags": [] + }, + { + "name": "DiagnosticsFormat", + "switch": "diagnostics:column", + "comment": "Column Info", + "value": "Column", + "flags": [] + }, + { + "name": "DiagnosticsFormat", + "switch": "diagnostics:classic", + "comment": "Classic", + "value": "Classic", + "flags": [] + }, + { + "name": "Optimization", + "switch": "", + "comment": "Custom", + "value": "Custom", + "flags": [] + }, + { + "name": "Optimization", + "switch": "Od", + "comment": "Disabled", + "value": "Disabled", + "flags": [] + }, + { + "name": "Optimization", + "switch": "O1", + "comment": "Maximum Optimization (Favor Size)", + "value": "MinSpace", + "flags": [] + }, + { + "name": "Optimization", + "switch": "O2", + "comment": "Maximum Optimization (Favor Speed)", + "value": "MaxSpeed", + "flags": [] + }, + { + "name": "Optimization", + "switch": "Ox", + "comment": "Optimizations (Favor Speed)", + "value": "Full", + "flags": [] + }, + { + "name": "InlineFunctionExpansion", + "switch": "", + "comment": "Default", + "value": "Default", + "flags": [] + }, + { + "name": "InlineFunctionExpansion", + "switch": "Ob0", + "comment": "Disabled", + "value": "Disabled", + "flags": [] + }, + { + "name": "InlineFunctionExpansion", + "switch": "Ob1", + "comment": "Only __inline", + "value": "OnlyExplicitInline", + "flags": [] + }, + { + "name": "InlineFunctionExpansion", + "switch": "Ob2", + "comment": "Any Suitable", + "value": "AnySuitable", + "flags": [] + }, + { + "name": "FavorSizeOrSpeed", + "switch": "Os", + "comment": "Favor small code", + "value": "Size", + "flags": [] + }, + { + "name": "FavorSizeOrSpeed", + "switch": "Ot", + "comment": "Favor fast code", + "value": "Speed", + "flags": [] + }, + { + "name": "FavorSizeOrSpeed", + "switch": "", + "comment": "Neither", + "value": "Neither", + "flags": [] + }, + { + "name": "ExceptionHandling", + "switch": "EHa", + "comment": "Yes with SEH Exceptions", + "value": "Async", + "flags": [] + }, + { + "name": "ExceptionHandling", + "switch": "EHsc", + "comment": "Yes", + "value": "Sync", + "flags": [] + }, + { + "name": "ExceptionHandling", + "switch": "EHs", + "comment": "Yes with Extern C functions", + "value": "SyncCThrow", + "flags": [] + }, + { + "name": "ExceptionHandling", + "switch": "", + "comment": "No", + "value": "false", + "flags": [] + }, + { + "name": "BasicRuntimeChecks", + "switch": "RTCs", + "comment": "Stack Frames", + "value": "StackFrameRuntimeCheck", + "flags": [] + }, + { + "name": "BasicRuntimeChecks", + "switch": "RTCu", + "comment": "Uninitialized variables", + "value": "UninitializedLocalUsageCheck", + "flags": [] + }, + { + "name": "BasicRuntimeChecks", + "switch": "RTC1", + "comment": "Both (/RTC1, equiv. to /RTCsu)", + "value": "EnableFastChecks", + "flags": [] + }, + { + "name": "BasicRuntimeChecks", + "switch": "", + "comment": "Default", + "value": "Default", + "flags": [] + }, + { + "name": "RuntimeLibrary", + "switch": "MT", + "comment": "Multi-threaded", + "value": "MultiThreaded", + "flags": [] + }, + { + "name": "RuntimeLibrary", + "switch": "MTd", + "comment": "Multi-threaded Debug", + "value": "MultiThreadedDebug", + "flags": [] + }, + { + "name": "RuntimeLibrary", + "switch": "MD", + "comment": "Multi-threaded DLL", + "value": "MultiThreadedDLL", + "flags": [] + }, + { + "name": "RuntimeLibrary", + "switch": "MDd", + "comment": "Multi-threaded Debug DLL", + "value": "MultiThreadedDebugDLL", + "flags": [] + }, + { + "name": "StructMemberAlignment", + "switch": "Zp1", + "comment": "1 Byte", + "value": "1Byte", + "flags": [] + }, + { + "name": "StructMemberAlignment", + "switch": "Zp2", + "comment": "2 Bytes", + "value": "2Bytes", + "flags": [] + }, + { + "name": "StructMemberAlignment", + "switch": "Zp4", + "comment": "4 Byte", + "value": "4Bytes", + "flags": [] + }, + { + "name": "StructMemberAlignment", + "switch": "Zp8", + "comment": "8 Bytes", + "value": "8Bytes", + "flags": [] + }, + { + "name": "StructMemberAlignment", + "switch": "Zp16", + "comment": "16 Bytes", + "value": "16Bytes", + "flags": [] + }, + { + "name": "StructMemberAlignment", + "switch": "", + "comment": "Default", + "value": "Default", + "flags": [] + }, + { + "name": "BufferSecurityCheck", + "switch": "GS-", + "comment": "Disable Security Check", + "value": "false", + "flags": [] + }, + { + "name": "BufferSecurityCheck", + "switch": "GS", + "comment": "Enable Security Check", + "value": "true", + "flags": [] + }, + { + "name": "ControlFlowGuard", + "switch": "guard:cf", + "comment": "Yes", + "value": "Guard", + "flags": [] + }, + { + "name": "ControlFlowGuard", + "switch": "", + "comment": "No", + "value": "false", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:SSE", + "comment": "Streaming SIMD Extensions", + "value": "StreamingSIMDExtensions", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:SSE2", + "comment": "Streaming SIMD Extensions 2", + "value": "StreamingSIMDExtensions2", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:AVX", + "comment": "Advanced Vector Extensions", + "value": "AdvancedVectorExtensions", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:AVX2", + "comment": "Advanced Vector Extensions 2", + "value": "AdvancedVectorExtensions2", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:AVX512", + "comment": "Advanced Vector Extensions 512", + "value": "AdvancedVectorExtensions512", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "arch:IA32", + "comment": "No Enhanced Instructions", + "value": "NoExtensions", + "flags": [] + }, + { + "name": "EnableEnhancedInstructionSet", + "switch": "", + "comment": "Not Set", + "value": "NotSet", + "flags": [] + }, + { + "name": "FloatingPointModel", + "switch": "fp:precise", + "comment": "Precise", + "value": "Precise", + "flags": [] + }, + { + "name": "FloatingPointModel", + "switch": "fp:strict", + "comment": "Strict", + "value": "Strict", + "flags": [] + }, + { + "name": "FloatingPointModel", + "switch": "fp:fast", + "comment": "Fast", + "value": "Fast", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "Qspectre", + "comment": "Enabled", + "value": "Spectre", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-load", + "comment": "All Loads", + "value": "SpectreLoad", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "Qspectre-load-cf", + "comment": "All Control Flow Loads", + "value": "SpectreLoadCF", + "flags": [] + }, + { + "name": "SpectreMitigation", + "switch": "", + "comment": "Disabled", + "value": "false", + "flags": [] + }, + { + "name": "ConformanceMode", + "switch": "", + "comment": "Default", + "value": "Default", + "flags": [] + }, + { + "name": "ConformanceMode", + "switch": "permissive-", + "comment": "Yes", + "value": "true", + "flags": [] + }, + { + "name": "ConformanceMode", + "switch": "permissive", + "comment": "No", + "value": "false", + "flags": [] + }, + { + "name": "LanguageStandard", + "switch": "", + "comment": "Default (ISO C++14 Standard)", + "value": "Default", + "flags": [] + }, + { + "name": "LanguageStandard", + "switch": "std:c++14", + "comment": "ISO C++14 Standard", + "value": "stdcpp14", + "flags": [] + }, + { + "name": "LanguageStandard", + "switch": "std:c++17", + "comment": "ISO C++17 Standard", + "value": "stdcpp17", + "flags": [] + }, + { + "name": "LanguageStandard", + "switch": "std:c++20", + "comment": "ISO C++20 Standard", + "value": "stdcpp20", + "flags": [] + }, + { + "name": "LanguageStandard", + "switch": "std:c++latest", + "comment": "Preview - Features from the Latest C++ Working Draft", + "value": "stdcpplatest", + "flags": [] + }, + { + "name": "LanguageStandard_C", + "switch": "", + "comment": "Default (Legacy MSVC)", + "value": "Default", + "flags": [] + }, + { + "name": "LanguageStandard_C", + "switch": "std:c11", + "comment": "ISO C11 Standard", + "value": "stdc11", + "flags": [] + }, + { + "name": "LanguageStandard_C", + "switch": "std:c17", + "comment": "ISO C17 (2018) Standard", + "value": "stdc17", + "flags": [] + }, + { + "name": "PrecompiledHeader", + "switch": "Yc", + "comment": "Create", + "value": "Create", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "PrecompiledHeader", + "switch": "Yu", + "comment": "Use", + "value": "Use", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "PrecompiledHeader", + "switch": "", + "comment": "Not Using Precompiled Headers", + "value": "NotUsing", + "flags": [] + }, + { + "name": "AssemblerOutput", + "switch": "", + "comment": "No Listing", + "value": "NoListing", + "flags": [] + }, + { + "name": "AssemblerOutput", + "switch": "FA", + "comment": "Assembly-Only Listing", + "value": "AssemblyCode", + "flags": [] + }, + { + "name": "AssemblerOutput", + "switch": "FAc", + "comment": "Assembly With Machine Code", + "value": "AssemblyAndMachineCode", + "flags": [] + }, + { + "name": "AssemblerOutput", + "switch": "FAs", + "comment": "Assembly With Source Code", + "value": "AssemblyAndSourceCode", + "flags": [] + }, + { + "name": "AssemblerOutput", + "switch": "FAcs", + "comment": "Assembly, Machine Code and Source", + "value": "All", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W0", + "comment": "Turn Off All Warnings", + "value": "TurnOffAllWarnings", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W1", + "comment": "Level1", + "value": "Level1", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W2", + "comment": "Level2", + "value": "Level2", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W3", + "comment": "Level3", + "value": "Level3", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "external:W4", + "comment": "Level4", + "value": "Level4", + "flags": [] + }, + { + "name": "ExternalWarningLevel", + "switch": "", + "comment": "Inherit Project Warning Level", + "value": "InheritWarningLevel", + "flags": [] + }, + { + "name": "CallingConvention", + "switch": "Gd", + "comment": "__cdecl", + "value": "Cdecl", + "flags": [] + }, + { + "name": "CallingConvention", + "switch": "Gr", + "comment": "__fastcall", + "value": "FastCall", + "flags": [] + }, + { + "name": "CallingConvention", + "switch": "Gz", + "comment": "__stdcall", + "value": "StdCall", + "flags": [] + }, + { + "name": "CallingConvention", + "switch": "Gv", + "comment": "__vectorcall", + "value": "VectorCall", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "", + "comment": "Default", + "value": "Default", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "TC", + "comment": "Compile as C Code", + "value": "CompileAsC", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "TP", + "comment": "Compile as C++ Code", + "value": "CompileAsCpp", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "interface", + "comment": "Compile as C++ Module Code", + "value": "CompileAsCppModule", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "internalPartition", + "comment": "Compile as C++ Module Internal Partition", + "value": "CompileAsCppModuleInternalPartition", + "flags": [] + }, + { + "name": "CompileAs", + "switch": "exportHeader", + "comment": "Compile as C++ Header Unit", + "value": "CompileAsHeaderUnit", + "flags": [] + }, + { + "name": "ErrorReporting", + "switch": "errorReport:none", + "comment": "Do Not Send Report", + "value": "None", + "flags": [] + }, + { + "name": "ErrorReporting", + "switch": "errorReport:prompt", + "comment": "Prompt Immediately", + "value": "Prompt", + "flags": [] + }, + { + "name": "ErrorReporting", + "switch": "errorReport:queue", + "comment": "Queue For Next Login", + "value": "Queue", + "flags": [] + }, + { + "name": "ErrorReporting", + "switch": "errorReport:send", + "comment": "Send Automatically", + "value": "Send", + "flags": [] + }, + { + "name": "TranslateIncludes", + "switch": "translateInclude", + "comment": "Translate Includes to Imports", + "value": "true", + "flags": [] + }, + { + "name": "SupportJustMyCode", + "switch": "JMC", + "comment": "Support Just My Code Debugging", + "value": "true", + "flags": [] + }, + { + "name": "CompileAsWinRT", + "switch": "ZW", + "comment": "Consume Windows Runtime Extension", + "value": "true", + "flags": [] + }, + { + "name": "WinRTNoStdLib", + "switch": "ZW:nostdlib", + "comment": "No Standard WinRT Libraries", + "value": "true", + "flags": [] + }, + { + "name": "SuppressStartupBanner", + "switch": "nologo", + "comment": "Suppress Startup Banner", + "value": "true", + "flags": [] + }, + { + "name": "TreatWarningAsError", + "switch": "WX-", + "comment": "Treat Warnings As Errors", + "value": "false", + "flags": [] + }, + { + "name": "TreatWarningAsError", + "switch": "WX", + "comment": "Treat Warnings As Errors", + "value": "true", + "flags": [] + }, + { + "name": "SDLCheck", + "switch": "sdl-", + "comment": "SDL checks", + "value": "false", + "flags": [] + }, + { + "name": "SDLCheck", + "switch": "sdl", + "comment": "SDL checks", + "value": "true", + "flags": [] + }, + { + "name": "MultiProcessorCompilation", + "switch": "MP", + "comment": "Multi-processor Compilation", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "ForceSynchronousPDBWrites", + "switch": "FS", + "comment": "Force Synchronous PDB Writes", + "value": "true", + "flags": [] + }, + { + "name": "EnableASAN", + "switch": "fsanitize=address", + "comment": "Enable Address Sanitizer", + "value": "true", + "flags": [] + }, + { + "name": "IntrinsicFunctions", + "switch": "Oi", + "comment": "Enable Intrinsic Functions", + "value": "true", + "flags": [] + }, + { + "name": "OmitFramePointers", + "switch": "Oy-", + "comment": "Omit Frame Pointers", + "value": "false", + "flags": [] + }, + { + "name": "OmitFramePointers", + "switch": "Oy", + "comment": "Omit Frame Pointers", + "value": "true", + "flags": [] + }, + { + "name": "EnableFiberSafeOptimizations", + "switch": "GT", + "comment": "Enable Fiber-Safe Optimizations", + "value": "true", + "flags": [] + }, + { + "name": "WholeProgramOptimization", + "switch": "GL", + "comment": "Whole Program Optimization", + "value": "true", + "flags": [] + }, + { + "name": "UndefineAllPreprocessorDefinitions", + "switch": "u", + "comment": "Undefine All Preprocessor Definitions", + "value": "true", + "flags": [] + }, + { + "name": "IgnoreStandardIncludePath", + "switch": "X", + "comment": "Ignore Standard Include Paths", + "value": "true", + "flags": [] + }, + { + "name": "PreprocessToFile", + "switch": "P", + "comment": "Preprocess to a File", + "value": "true", + "flags": [] + }, + { + "name": "PreprocessSuppressLineNumbers", + "switch": "EP", + "comment": "Preprocess Suppress Line Numbers", + "value": "true", + "flags": [] + }, + { + "name": "PreprocessKeepComments", + "switch": "C", + "comment": "Keep Comments", + "value": "true", + "flags": [] + }, + { + "name": "UseStandardPreprocessor", + "switch": "Zc:preprocessor-", + "comment": "Use Standard Conforming Preprocessor", + "value": "false", + "flags": [] + }, + { + "name": "UseStandardPreprocessor", + "switch": "Zc:preprocessor", + "comment": "Use Standard Conforming Preprocessor", + "value": "true", + "flags": [] + }, + { + "name": "StringPooling", + "switch": "GF-", + "comment": "Enable String Pooling", + "value": "false", + "flags": [] + }, + { + "name": "StringPooling", + "switch": "GF", + "comment": "Enable String Pooling", + "value": "true", + "flags": [] + }, + { + "name": "MinimalRebuild", + "switch": "Gm-", + "comment": "Enable Minimal Rebuild", + "value": "false", + "flags": [] + }, + { + "name": "MinimalRebuild", + "switch": "Gm", + "comment": "Enable Minimal Rebuild", + "value": "true", + "flags": [] + }, + { + "name": "SmallerTypeCheck", + "switch": "RTCc", + "comment": "Smaller Type Check", + "value": "true", + "flags": [] + }, + { + "name": "FunctionLevelLinking", + "switch": "Gy-", + "comment": "Enable Function-Level Linking", + "value": "false", + "flags": [] + }, + { + "name": "FunctionLevelLinking", + "switch": "Gy", + "comment": "Enable Function-Level Linking", + "value": "true", + "flags": [] + }, + { + "name": "EnableParallelCodeGeneration", + "switch": "Qpar-", + "comment": "Enable Parallel Code Generation", + "value": "false", + "flags": [] + }, + { + "name": "EnableParallelCodeGeneration", + "switch": "Qpar", + "comment": "Enable Parallel Code Generation", + "value": "true", + "flags": [] + }, + { + "name": "FloatingPointExceptions", + "switch": "fp:except-", + "comment": "Enable Floating Point Exceptions", + "value": "false", + "flags": [] + }, + { + "name": "FloatingPointExceptions", + "switch": "fp:except", + "comment": "Enable Floating Point Exceptions", + "value": "true", + "flags": [] + }, + { + "name": "CreateHotpatchableImage", + "switch": "hotpatch", + "comment": "Create Hotpatchable Image", + "value": "true", + "flags": [] + }, + { + "name": "IntelJCCErratum", + "switch": "QIntel-jcc-erratum", + "comment": "Enable Intel JCC Erratum Mitigation", + "value": "true", + "flags": [] + }, + { + "name": "GuardEHContMetadata", + "switch": "guard:ehcont-", + "comment": "Enable EH Continuation Metadata", + "value": "false", + "flags": [] + }, + { + "name": "GuardEHContMetadata", + "switch": "guard:ehcont", + "comment": "Enable EH Continuation Metadata", + "value": "true", + "flags": [] + }, + { + "name": "GuardSignedReturns", + "switch": "guard:signret-", + "comment": "Enable Signed Returns", + "value": "false", + "flags": [] + }, + { + "name": "GuardSignedReturns", + "switch": "guard:signret", + "comment": "Enable Signed Returns", + "value": "true", + "flags": [] + }, + { + "name": "DisableLanguageExtensions", + "switch": "Za", + "comment": "Disable Language Extensions", + "value": "true", + "flags": [] + }, + { + "name": "TreatWChar_tAsBuiltInType", + "switch": "Zc:wchar_t-", + "comment": "Treat WChar_t As Built in Type", + "value": "false", + "flags": [] + }, + { + "name": "TreatWChar_tAsBuiltInType", + "switch": "Zc:wchar_t", + "comment": "Treat WChar_t As Built in Type", + "value": "true", + "flags": [] + }, + { + "name": "ForceConformanceInForLoopScope", + "switch": "Zc:forScope-", + "comment": "Force Conformance in For Loop Scope", + "value": "false", + "flags": [] + }, + { + "name": "ForceConformanceInForLoopScope", + "switch": "Zc:forScope", + "comment": "Force Conformance in For Loop Scope", + "value": "true", + "flags": [] + }, + { + "name": "RemoveUnreferencedCodeData", + "switch": "Zc:inline", + "comment": "Remove unreferenced code and data", + "value": "true", + "flags": [] + }, + { + "name": "EnforceTypeConversionRules", + "switch": "Zc:rvalueCast-", + "comment": "Enforce type conversion rules", + "value": "false", + "flags": [] + }, + { + "name": "EnforceTypeConversionRules", + "switch": "Zc:rvalueCast", + "comment": "Enforce type conversion rules", + "value": "true", + "flags": [] + }, + { + "name": "RuntimeTypeInfo", + "switch": "GR-", + "comment": "Enable Run-Time Type Information", + "value": "false", + "flags": [] + }, + { + "name": "RuntimeTypeInfo", + "switch": "GR", + "comment": "Enable Run-Time Type Information", + "value": "true", + "flags": [] + }, + { + "name": "OpenMPSupport", + "switch": "openmp-", + "comment": "Open MP Support", + "value": "false", + "flags": [] + }, + { + "name": "OpenMPSupport", + "switch": "openmp", + "comment": "Open MP Support", + "value": "true", + "flags": [] + }, + { + "name": "EnableModules", + "switch": "experimental:module", + "comment": "Enable Experimental C++ Standard Library Modules", + "value": "true", + "flags": [] + }, + { + "name": "ExpandAttributedSource", + "switch": "Fx", + "comment": "Expand Attributed Source", + "value": "true", + "flags": [] + }, + { + "name": "UseUnicodeForAssemblerListing", + "switch": "FAu", + "comment": "Use Unicode For Assembler Listing", + "value": "true", + "flags": [] + }, + { + "name": "GenerateModuleDependencies", + "switch": "sourceDependencies:directives", + "comment": "Generate Module Dependenices File", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "GenerateXMLDocumentationFiles", + "switch": "doc", + "comment": "Generate XML Documentation Files", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "GenerateSourceDependencies", + "switch": "sourceDependencies", + "comment": "Generate Source Dependencies File", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "BrowseInformation", + "switch": "FR", + "comment": "Enable Browse Information", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "TreatAngleIncludeAsExternal", + "switch": "external:anglebrackets", + "comment": "Treat Files Included with Angle Brackets as External", + "value": "true", + "flags": [] + }, + { + "name": "ExternalTemplatesDiagnostics", + "switch": "external:templates-", + "comment": "Template Diagnostics in External Headers", + "value": "true", + "flags": [] + }, + { + "name": "DisableAnalyzeExternal", + "switch": "analyze:external-", + "comment": "Disable Code Analysis for External Headers", + "value": "true", + "flags": [] + }, + { + "name": "ShowIncludes", + "switch": "showIncludes", + "comment": "Show Includes", + "value": "true", + "flags": [] + }, + { + "name": "EnablePREfast", + "switch": "analyze-", + "comment": "Enable Code Analysis", + "value": "false", + "flags": [] + }, + { + "name": "EnablePREfast", + "switch": "analyze", + "comment": "Enable Code Analysis", + "value": "true", + "flags": [] + }, + { + "name": "UseFullPaths", + "switch": "FC", + "comment": "Use Full Paths", + "value": "true", + "flags": [] + }, + { + "name": "OmitDefaultLibName", + "switch": "Zl", + "comment": "Omit Default Library Name", + "value": "true", + "flags": [] + }, + { + "name": "AdditionalIncludeDirectories", + "switch": "I", + "comment": "Additional Include Directories", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalUsingDirectories", + "switch": "AI", + "comment": "Additional #using Directories", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalBMIDirectories", + "switch": "ifcSearchDir", + "comment": "Additional BMI Directories", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalModuleDependencies", + "switch": "reference", + "comment": "Additional Module Dependencies", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalHeaderUnitDependencies", + "switch": "headerUnit", + "comment": "Additional Header Unit Dependencies", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "PreprocessorDefinitions", + "switch": "D", + "comment": "Preprocessor Definitions", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "UndefinePreprocessorDefinitions", + "switch": "U", + "comment": "Undefine Preprocessor Definitions", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "StdIfcDirectory", + "switch": "stdIfcDir", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "ExternalDirectoriesEnv", + "switch": "external:env:", + "comment": "External Directories Environment Variables", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "DisableSpecificWarnings", + "switch": "wd", + "comment": "Disable Specific Warnings", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "ForcedIncludeFiles", + "switch": "FI", + "comment": "Forced Include File", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "ForcedUsingFiles", + "switch": "FU", + "comment": "Forced #using File", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "PREfastAdditionalOptions", + "switch": "analyze:", + "comment": "Additional Code Analysis Native options", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "PREfastAdditionalPlugins", + "switch": "analyze:plugin", + "comment": "Additional Code Analysis Native plugins", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "TreatSpecificWarningsAsErrors", + "switch": "we", + "comment": "Treat Specific Warnings As Errors", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "WarningVersion", + "switch": "Wv:", + "comment": "Warning Version", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "PreprocessOutputPath", + "switch": "Fi", + "comment": "Preprocess Output Path", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "PrecompiledHeaderFile", + "switch": "Yu", + "comment": "Precompiled Header File", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "PrecompiledHeaderFile", + "switch": "Yc", + "comment": "Precompiled Header File", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "PrecompiledHeaderOutputFile", + "switch": "Fp", + "comment": "Precompiled Header Output File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "AssemblerListingLocation", + "switch": "Fa", + "comment": "ASM List Location", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ModuleOutputFile", + "switch": "ifcOutput", + "comment": "Module Output File Name", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ModuleDependenciesFile", + "switch": "sourceDependencies:directives", + "comment": "Module Dependencies File Name", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "ObjectFileName", + "switch": "Fo", + "comment": "Object File Name", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ProgramDataBaseFileName", + "switch": "Fd", + "comment": "Program Database File Name", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "XMLDocumentationFileName", + "switch": "doc", + "comment": "XML Documentation File Name", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "SourceDependenciesFile", + "switch": "sourceDependencies", + "comment": "Source Dependencies File Name", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "BrowseInformationFile", + "switch": "FR", + "comment": "Browse Information File", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "PREfastLog", + "switch": "analyze:log", + "comment": "Code Analysis Log", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "PREfastProjectDirectory", + "switch": "analyze:projectdirectory", + "comment": "Code Analysis Project Directory", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "PREfastRulesetDirectories", + "switch": "analyze:rulesetdirectory", + "comment": "Code Analysis Ruleset Directories", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "PREfastRulesetFile", + "switch": "analyze:ruleset", + "comment": "Code Analysis Ruleset File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ProcessorNumber", + "switch": "MP", + "comment": "Number of processors", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + } +] diff --git a/Templates/MSBuild/FlagTables/v143_Link.json b/Templates/MSBuild/FlagTables/v143_Link.json new file mode 100644 index 00000000000..bdf39c7f902 --- /dev/null +++ b/Templates/MSBuild/FlagTables/v143_Link.json @@ -0,0 +1,1429 @@ +[ + { + "name": "ShowProgress", + "switch": "", + "comment": "Not Set", + "value": "NotSet", + "flags": [] + }, + { + "name": "ShowProgress", + "switch": "VERBOSE", + "comment": "Display all progress messages", + "value": "LinkVerbose", + "flags": [] + }, + { + "name": "ShowProgress", + "switch": "VERBOSE:Lib", + "comment": "For Libraries Searched", + "value": "LinkVerboseLib", + "flags": [] + }, + { + "name": "ShowProgress", + "switch": "VERBOSE:ICF", + "comment": "About COMDAT folding during optimized linking", + "value": "LinkVerboseICF", + "flags": [] + }, + { + "name": "ShowProgress", + "switch": "VERBOSE:REF", + "comment": "About data removed during optimized linking", + "value": "LinkVerboseREF", + "flags": [] + }, + { + "name": "ShowProgress", + "switch": "VERBOSE:SAFESEH", + "comment": "About Modules incompatible with SEH", + "value": "LinkVerboseSAFESEH", + "flags": [] + }, + { + "name": "ShowProgress", + "switch": "VERBOSE:CLR", + "comment": "About linker activity related to managed code", + "value": "LinkVerboseCLR", + "flags": [] + }, + { + "name": "ForceFileOutput", + "switch": "FORCE", + "comment": "Enabled", + "value": "Enabled", + "flags": [] + }, + { + "name": "ForceFileOutput", + "switch": "FORCE:MULTIPLE", + "comment": "Multiply Defined Symbol Only", + "value": "MultiplyDefinedSymbolOnly", + "flags": [] + }, + { + "name": "ForceFileOutput", + "switch": "FORCE:UNRESOLVED", + "comment": "Undefined Symbol Only", + "value": "UndefinedSymbolOnly", + "flags": [] + }, + { + "name": "CreateHotPatchableImage", + "switch": "FUNCTIONPADMIN", + "comment": "Enabled", + "value": "Enabled", + "flags": [] + }, + { + "name": "CreateHotPatchableImage", + "switch": "FUNCTIONPADMIN:5", + "comment": "X86 Image Only", + "value": "X86Image", + "flags": [] + }, + { + "name": "CreateHotPatchableImage", + "switch": "FUNCTIONPADMIN:6", + "comment": "X64 Image Only", + "value": "X64Image", + "flags": [] + }, + { + "name": "CreateHotPatchableImage", + "switch": "FUNCTIONPADMIN:16", + "comment": "Itanium Image Only", + "value": "ItaniumImage", + "flags": [] + }, + { + "name": "UACExecutionLevel", + "switch": "level='asInvoker'", + "comment": "asInvoker", + "value": "AsInvoker", + "flags": [] + }, + { + "name": "UACExecutionLevel", + "switch": "level='highestAvailable'", + "comment": "highestAvailable", + "value": "HighestAvailable", + "flags": [] + }, + { + "name": "UACExecutionLevel", + "switch": "level='requireAdministrator'", + "comment": "requireAdministrator", + "value": "RequireAdministrator", + "flags": [] + }, + { + "name": "GenerateDebugInformation", + "switch": "", + "comment": "No", + "value": "false", + "flags": [] + }, + { + "name": "GenerateDebugInformation", + "switch": "DEBUG", + "comment": "Generate Debug Information", + "value": "true", + "flags": [] + }, + { + "name": "GenerateDebugInformation", + "switch": "DEBUG:FASTLINK", + "comment": "Generate Debug Information optimized for faster links", + "value": "DebugFastLink", + "flags": [] + }, + { + "name": "GenerateDebugInformation", + "switch": "DEBUG:FULL", + "comment": "Generate Debug Information optimized for sharing and publishing", + "value": "DebugFull", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "", + "comment": "Not Set", + "value": "NotSet", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:CONSOLE", + "comment": "Console", + "value": "Console", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:WINDOWS", + "comment": "Windows", + "value": "Windows", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:NATIVE", + "comment": "Native", + "value": "Native", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:EFI_APPLICATION", + "comment": "EFI Application", + "value": "EFI Application", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", + "comment": "EFI Boot Service Driver", + "value": "EFI Boot Service Driver", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:EFI_ROM", + "comment": "EFI ROM", + "value": "EFI ROM", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:EFI_RUNTIME_DRIVER", + "comment": "EFI Runtime", + "value": "EFI Runtime", + "flags": [] + }, + { + "name": "SubSystem", + "switch": "SUBSYSTEM:POSIX", + "comment": "POSIX", + "value": "POSIX", + "flags": [] + }, + { + "name": "Driver", + "switch": "", + "comment": "Not Set", + "value": "NotSet", + "flags": [] + }, + { + "name": "Driver", + "switch": "Driver", + "comment": "Driver", + "value": "Driver", + "flags": [] + }, + { + "name": "Driver", + "switch": "DRIVER:UPONLY", + "comment": "UP Only", + "value": "UpOnly", + "flags": [] + }, + { + "name": "Driver", + "switch": "DRIVER:WDM", + "comment": "WDM", + "value": "WDM", + "flags": [] + }, + { + "name": "LinkTimeCodeGeneration", + "switch": "", + "comment": "Default", + "value": "Default", + "flags": [] + }, + { + "name": "LinkTimeCodeGeneration", + "switch": "LTCG:incremental", + "comment": "Use Fast Link Time Code Generation", + "value": "UseFastLinkTimeCodeGeneration", + "flags": [] + }, + { + "name": "LinkTimeCodeGeneration", + "switch": "LTCG", + "comment": "Use Link Time Code Generation", + "value": "UseLinkTimeCodeGeneration", + "flags": [] + }, + { + "name": "LinkTimeCodeGeneration", + "switch": "LTCG:PGInstrument", + "comment": "Profile Guided Optimization - Instrument", + "value": "PGInstrument", + "flags": [] + }, + { + "name": "LinkTimeCodeGeneration", + "switch": "LTCG:PGOptimize", + "comment": "Profile Guided Optimization - Optimization", + "value": "PGOptimization", + "flags": [] + }, + { + "name": "LinkTimeCodeGeneration", + "switch": "LTCG:PGUpdate", + "comment": "Profile Guided Optimization - Update", + "value": "PGUpdate", + "flags": [] + }, + { + "name": "GenerateWindowsMetadata", + "switch": "WINMD", + "comment": "Yes", + "value": "true", + "flags": [] + }, + { + "name": "GenerateWindowsMetadata", + "switch": "WINMD:NO", + "comment": "No", + "value": "false", + "flags": [] + }, + { + "name": "WindowsMetadataSignHash", + "switch": "WINMDSIGNHASH:SHA1", + "comment": "SHA1", + "value": "SHA1", + "flags": [] + }, + { + "name": "WindowsMetadataSignHash", + "switch": "WINMDSIGNHASH:SHA256", + "comment": "SHA256", + "value": "SHA256", + "flags": [] + }, + { + "name": "WindowsMetadataSignHash", + "switch": "WINMDSIGNHASH:SHA384", + "comment": "SHA384", + "value": "SHA384", + "flags": [] + }, + { + "name": "WindowsMetadataSignHash", + "switch": "WINMDSIGNHASH:SHA512", + "comment": "SHA512", + "value": "SHA512", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "", + "comment": "Not Set", + "value": "NotSet", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:ARM", + "comment": "MachineARM", + "value": "MachineARM", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:ARM64", + "comment": "MachineARM64", + "value": "MachineARM64", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:ARM64EC", + "comment": "MachineARM64EC", + "value": "MachineARM64EC", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:ARM64X", + "comment": "MachineARM64X", + "value": "MachineARM64X", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:EBC", + "comment": "MachineEBC", + "value": "MachineEBC", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:IA64", + "comment": "MachineIA64", + "value": "MachineIA64", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:MIPS", + "comment": "MachineMIPS", + "value": "MachineMIPS", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:MIPS16", + "comment": "MachineMIPS16", + "value": "MachineMIPS16", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:MIPSFPU", + "comment": "MachineMIPSFPU", + "value": "MachineMIPSFPU", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:MIPSFPU16", + "comment": "MachineMIPSFPU16", + "value": "MachineMIPSFPU16", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:SH4", + "comment": "MachineSH4", + "value": "MachineSH4", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:THUMB", + "comment": "MachineTHUMB", + "value": "MachineTHUMB", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:X64", + "comment": "MachineX64", + "value": "MachineX64", + "flags": [] + }, + { + "name": "TargetMachine", + "switch": "MACHINE:X86", + "comment": "MachineX86", + "value": "MachineX86", + "flags": [] + }, + { + "name": "CLRThreadAttribute", + "switch": "CLRTHREADATTRIBUTE:MTA", + "comment": "MTA threading attribute", + "value": "MTAThreadingAttribute", + "flags": [] + }, + { + "name": "CLRThreadAttribute", + "switch": "CLRTHREADATTRIBUTE:STA", + "comment": "STA threading attribute", + "value": "STAThreadingAttribute", + "flags": [] + }, + { + "name": "CLRThreadAttribute", + "switch": "CLRTHREADATTRIBUTE:NONE", + "comment": "Default threading attribute", + "value": "DefaultThreadingAttribute", + "flags": [] + }, + { + "name": "CLRImageType", + "switch": "CLRIMAGETYPE:IJW", + "comment": "Force IJW image", + "value": "ForceIJWImage", + "flags": [] + }, + { + "name": "CLRImageType", + "switch": "CLRIMAGETYPE:PURE", + "comment": "Force Pure IL Image", + "value": "ForcePureILImage", + "flags": [] + }, + { + "name": "CLRImageType", + "switch": "CLRIMAGETYPE:SAFE", + "comment": "Force Safe IL Image", + "value": "ForceSafeILImage", + "flags": [] + }, + { + "name": "CLRImageType", + "switch": "", + "comment": "Default image type", + "value": "Default", + "flags": [] + }, + { + "name": "SignHash", + "switch": "CLRSIGNHASH:SHA1", + "comment": "SHA1", + "value": "SHA1", + "flags": [] + }, + { + "name": "SignHash", + "switch": "CLRSIGNHASH:SHA256", + "comment": "SHA256", + "value": "SHA256", + "flags": [] + }, + { + "name": "SignHash", + "switch": "CLRSIGNHASH:SHA384", + "comment": "SHA384", + "value": "SHA384", + "flags": [] + }, + { + "name": "SignHash", + "switch": "CLRSIGNHASH:SHA512", + "comment": "SHA512", + "value": "SHA512", + "flags": [] + }, + { + "name": "LinkErrorReporting", + "switch": "ERRORREPORT:PROMPT", + "comment": "PromptImmediately", + "value": "PromptImmediately", + "flags": [] + }, + { + "name": "LinkErrorReporting", + "switch": "ERRORREPORT:QUEUE", + "comment": "Queue For Next Login", + "value": "QueueForNextLogin", + "flags": [] + }, + { + "name": "LinkErrorReporting", + "switch": "ERRORREPORT:SEND", + "comment": "Send Error Report", + "value": "SendErrorReport", + "flags": [] + }, + { + "name": "LinkErrorReporting", + "switch": "ERRORREPORT:NONE", + "comment": "No Error Report", + "value": "NoErrorReport", + "flags": [] + }, + { + "name": "CLRSupportLastError", + "switch": "CLRSupportLastError", + "comment": "Enabled", + "value": "Enabled", + "flags": [] + }, + { + "name": "CLRSupportLastError", + "switch": "CLRSupportLastError:NO", + "comment": "Disabled", + "value": "Disabled", + "flags": [] + }, + { + "name": "CLRSupportLastError", + "switch": "CLRSupportLastError:SYSTEMDLL", + "comment": "System Dlls Only", + "value": "SystemDlls", + "flags": [] + }, + { + "name": "LinkIncremental", + "switch": "INCREMENTAL:NO", + "comment": "Enable Incremental Linking", + "value": "false", + "flags": [] + }, + { + "name": "LinkIncremental", + "switch": "INCREMENTAL", + "comment": "Enable Incremental Linking", + "value": "true", + "flags": [] + }, + { + "name": "SuppressStartupBanner", + "switch": "NOLOGO", + "comment": "Suppress Startup Banner", + "value": "true", + "flags": [] + }, + { + "name": "LinkStatus", + "switch": "LTCG:NOSTATUS", + "comment": "Link Status", + "value": "false", + "flags": [] + }, + { + "name": "LinkStatus", + "switch": "LTCG:STATUS", + "comment": "Link Status", + "value": "true", + "flags": [] + }, + { + "name": "PreventDllBinding", + "switch": "ALLOWBIND:NO", + "comment": "Prevent Dll Binding", + "value": "false", + "flags": [] + }, + { + "name": "PreventDllBinding", + "switch": "ALLOWBIND", + "comment": "Prevent Dll Binding", + "value": "true", + "flags": [] + }, + { + "name": "TreatLinkerWarningAsErrors", + "switch": "WX:NO", + "comment": "Treat Linker Warning As Errors", + "value": "false", + "flags": [] + }, + { + "name": "TreatLinkerWarningAsErrors", + "switch": "WX", + "comment": "Treat Linker Warning As Errors", + "value": "true", + "flags": [] + }, + { + "name": "IgnoreAllDefaultLibraries", + "switch": "NODEFAULTLIB", + "comment": "Ignore All Default Libraries", + "value": "true", + "flags": [] + }, + { + "name": "GenerateManifest", + "switch": "MANIFEST:NO", + "comment": "Generate Manifest", + "value": "false", + "flags": [] + }, + { + "name": "GenerateManifest", + "switch": "MANIFEST", + "comment": "Generate Manifest", + "value": "true", + "flags": [] + }, + { + "name": "AllowIsolation", + "switch": "ALLOWISOLATION:NO", + "comment": "Allow Isolation", + "value": "false", + "flags": [] + }, + { + "name": "AllowIsolation", + "switch": "", + "comment": "Allow Isolation", + "value": "true", + "flags": [] + }, + { + "name": "EnableUAC", + "switch": "MANIFESTUAC:NO", + "comment": "Enable User Account Control (UAC)", + "value": "false", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "EnableUAC", + "switch": "MANIFESTUAC:", + "comment": "Enable User Account Control (UAC)", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "UACUIAccess", + "switch": "uiAccess='false'", + "comment": "UAC Bypass UI Protection", + "value": "false", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "UACUIAccess", + "switch": "MANIFESTUAC:", + "comment": "UAC Bypass UI Protection", + "value": "true", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "UACUIAccess", + "switch": "uiAccess='false'", + "comment": "UAC Bypass UI Protection", + "value": "false", + "flags": [] + }, + { + "name": "UACUIAccess", + "switch": "uiAccess='true'", + "comment": "UAC Bypass UI Protection", + "value": "true", + "flags": [] + }, + { + "name": "ManifestEmbed", + "switch": "manifest:embed", + "comment": "Embed Manifest", + "value": "true", + "flags": [] + }, + { + "name": "GenerateMapFile", + "switch": "MAP", + "comment": "Generate Map File", + "value": "true", + "flags": [ + "UserValue", + "UserIgnored", + "Continue" + ] + }, + { + "name": "MapExports", + "switch": "MAPINFO:EXPORTS", + "comment": "Map Exports", + "value": "true", + "flags": [] + }, + { + "name": "AssemblyDebug", + "switch": "ASSEMBLYDEBUG:DISABLE", + "comment": "Debuggable Assembly", + "value": "false", + "flags": [] + }, + { + "name": "AssemblyDebug", + "switch": "ASSEMBLYDEBUG", + "comment": "Debuggable Assembly", + "value": "true", + "flags": [] + }, + { + "name": "LargeAddressAware", + "switch": "LARGEADDRESSAWARE:NO", + "comment": "Enable Large Addresses", + "value": "false", + "flags": [] + }, + { + "name": "LargeAddressAware", + "switch": "LARGEADDRESSAWARE", + "comment": "Enable Large Addresses", + "value": "true", + "flags": [] + }, + { + "name": "TerminalServerAware", + "switch": "TSAWARE:NO", + "comment": "Terminal Server", + "value": "false", + "flags": [] + }, + { + "name": "TerminalServerAware", + "switch": "TSAWARE", + "comment": "Terminal Server", + "value": "true", + "flags": [] + }, + { + "name": "SwapRunFromCD", + "switch": "SWAPRUN:CD", + "comment": "Swap Run From CD", + "value": "true", + "flags": [] + }, + { + "name": "SwapRunFromNET", + "switch": "SWAPRUN:NET", + "comment": "Swap Run From Network", + "value": "true", + "flags": [] + }, + { + "name": "OptimizeReferences", + "switch": "OPT:NOREF", + "comment": "References", + "value": "false", + "flags": [] + }, + { + "name": "OptimizeReferences", + "switch": "OPT:REF", + "comment": "References", + "value": "true", + "flags": [] + }, + { + "name": "EnableCOMDATFolding", + "switch": "OPT:NOICF", + "comment": "Enable COMDAT Folding", + "value": "false", + "flags": [] + }, + { + "name": "EnableCOMDATFolding", + "switch": "OPT:ICF", + "comment": "Enable COMDAT Folding", + "value": "true", + "flags": [] + }, + { + "name": "IgnoreEmbeddedIDL", + "switch": "IGNOREIDL", + "comment": "Ignore Embedded IDL", + "value": "true", + "flags": [] + }, + { + "name": "AppContainer", + "switch": "APPCONTAINER", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "WindowsMetadataLinkDelaySign", + "switch": "WINMDDELAYSIGN:NO", + "comment": "Windows Metadata Delay Sign", + "value": "false", + "flags": [] + }, + { + "name": "WindowsMetadataLinkDelaySign", + "switch": "WINMDDELAYSIGN", + "comment": "Windows Metadata Delay Sign", + "value": "true", + "flags": [] + }, + { + "name": "NoEntryPoint", + "switch": "NOENTRY", + "comment": "No Entry Point", + "value": "true", + "flags": [] + }, + { + "name": "SetChecksum", + "switch": "RELEASE", + "comment": "Set Checksum", + "value": "true", + "flags": [] + }, + { + "name": "RandomizedBaseAddress", + "switch": "DYNAMICBASE:NO", + "comment": "Randomized Base Address", + "value": "false", + "flags": [] + }, + { + "name": "RandomizedBaseAddress", + "switch": "DYNAMICBASE", + "comment": "Randomized Base Address", + "value": "true", + "flags": [] + }, + { + "name": "FixedBaseAddress", + "switch": "FIXED:NO", + "comment": "Fixed Base Address", + "value": "false", + "flags": [] + }, + { + "name": "FixedBaseAddress", + "switch": "FIXED", + "comment": "Fixed Base Address", + "value": "true", + "flags": [] + }, + { + "name": "DataExecutionPrevention", + "switch": "NXCOMPAT:NO", + "comment": "Data Execution Prevention (DEP)", + "value": "false", + "flags": [] + }, + { + "name": "DataExecutionPrevention", + "switch": "NXCOMPAT", + "comment": "Data Execution Prevention (DEP)", + "value": "true", + "flags": [] + }, + { + "name": "TurnOffAssemblyGeneration", + "switch": "NOASSEMBLY", + "comment": "Turn Off Assembly Generation", + "value": "true", + "flags": [] + }, + { + "name": "SupportUnloadOfDelayLoadedDLL", + "switch": "DELAY:UNLOAD", + "comment": "Unload delay loaded DLL", + "value": "true", + "flags": [] + }, + { + "name": "SupportNobindOfDelayLoadedDLL", + "switch": "DELAY:NOBIND", + "comment": "Nobind delay loaded DLL", + "value": "true", + "flags": [] + }, + { + "name": "Profile", + "switch": "PROFILE", + "comment": "Profile", + "value": "true", + "flags": [] + }, + { + "name": "LinkDelaySign", + "switch": "DELAYSIGN:NO", + "comment": "Delay Sign", + "value": "false", + "flags": [] + }, + { + "name": "LinkDelaySign", + "switch": "DELAYSIGN", + "comment": "Delay Sign", + "value": "true", + "flags": [] + }, + { + "name": "CLRUnmanagedCodeCheck", + "switch": "CLRUNMANAGEDCODECHECK:NO", + "comment": "CLR Unmanaged Code Check", + "value": "false", + "flags": [] + }, + { + "name": "CLRUnmanagedCodeCheck", + "switch": "CLRUNMANAGEDCODECHECK", + "comment": "CLR Unmanaged Code Check", + "value": "true", + "flags": [] + }, + { + "name": "DetectOneDefinitionRule", + "switch": "ODR", + "comment": "Detect One Definition Rule violations", + "value": "true", + "flags": [] + }, + { + "name": "CETCompat", + "switch": "CETCOMPAT:NO", + "comment": "CET Shadow Stack Compatible", + "value": "false", + "flags": [] + }, + { + "name": "CETCompat", + "switch": "CETCOMPAT", + "comment": "CET Shadow Stack Compatible", + "value": "true", + "flags": [] + }, + { + "name": "ImageHasSafeExceptionHandlers", + "switch": "SAFESEH:NO", + "comment": "Image Has Safe Exception Handlers", + "value": "false", + "flags": [] + }, + { + "name": "ImageHasSafeExceptionHandlers", + "switch": "SAFESEH", + "comment": "Image Has Safe Exception Handlers", + "value": "true", + "flags": [] + }, + { + "name": "LinkControlFlowGuard", + "switch": "guard:cf", + "comment": "Control Flow Guard", + "value": "true", + "flags": [] + }, + { + "name": "LinkGuardEHContMetadata", + "switch": "guard:ehcont", + "comment": "Enable EH Continuation Metadata", + "value": "true", + "flags": [] + }, + { + "name": "LinkGuardSignedReturns", + "switch": "guard:nodelayloadsignret", + "comment": "Enable Signed Returns", + "value": "false", + "flags": [] + }, + { + "name": "LinkGuardSignedReturns", + "switch": "guard:delayloadsignret", + "comment": "Enable Signed Returns", + "value": "true", + "flags": [] + }, + { + "name": "LinkDLL", + "switch": "DLL", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AdditionalLibraryDirectories", + "switch": "LIBPATH:", + "comment": "Additional Library Directories", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "Natvis", + "switch": "NATVIS:", + "comment": "Natvis files", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "SpecifySectionAttributes", + "switch": "SECTION:", + "comment": "Specify Section Attributes", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "IgnoreSpecificDefaultLibraries", + "switch": "NODEFAULTLIB:", + "comment": "Ignore Specific Default Libraries", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AddModuleNamesToAssembly", + "switch": "ASSEMBLYMODULE:", + "comment": "Add Module to Assembly", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "EmbedManagedResourceFile", + "switch": "ASSEMBLYRESOURCE:", + "comment": "Embed Managed Resource File", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "ForceSymbolReferences", + "switch": "INCLUDE:", + "comment": "Force Symbol References", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "DelayLoadDLLs", + "switch": "DELAYLOAD:", + "comment": "Delay Loaded Dlls", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AssemblyLinkResource", + "switch": "ASSEMBLYLINKRESOURCE:", + "comment": "Assembly Link Resource", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "AdditionalManifestDependencies", + "switch": "MANIFESTDEPENDENCY:", + "comment": "Additional Manifest Dependencies", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "ManifestInput", + "switch": "manifestinput:", + "comment": "Manifest Input", + "value": "", + "flags": [ + "UserValue", + "SemicolonAppendable" + ] + }, + { + "name": "OutputFile", + "switch": "OUT:", + "comment": "Output File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "Version", + "switch": "VERSION:", + "comment": "Version", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "IncrementalLinkDatabaseFile", + "switch": "ILK:", + "comment": "Incremental Link Database File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "MSDOSStubFileName", + "switch": "STUB:", + "comment": "MS-DOS Stub File Name", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ModuleDefinitionFile", + "switch": "DEF:", + "comment": "Module Definition File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ManifestFile", + "switch": "ManifestFile:", + "comment": "Manifest File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ProgramDatabaseFile", + "switch": "PDB:", + "comment": "Generate Program Database File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "StripPrivateSymbols", + "switch": "PDBSTRIPPED:", + "comment": "Strip Private Symbols", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "MapFileName", + "switch": "MAP:", + "comment": "Map File Name", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "HeapReserveSize", + "switch": "HEAP:", + "comment": "Heap Reserve Size", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "HeapCommitSize", + "switch": "HEAP", + "comment": "Heap Commit Size", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "StackReserveSize", + "switch": "STACK:", + "comment": "Stack Reserve Size", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "StackCommitSize", + "switch": "STACK", + "comment": "Stack Commit Size", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "FunctionOrder", + "switch": "ORDER:@", + "comment": "Function Order", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ProfileGuidedDatabase", + "switch": "PGD:", + "comment": "Profile Guided Database", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "LinkTimeCodeGenerationObjectFile", + "switch": "LTCGOUT:", + "comment": "Link Time Code Generation Object File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "MidlCommandFile", + "switch": "MIDL:@", + "comment": "MIDL Commands", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "MergedIDLBaseFileName", + "switch": "IDLOUT:", + "comment": "Merged IDL Base File Name", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "TypeLibraryFile", + "switch": "TLBOUT:", + "comment": "Type Library", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "WindowsMetadataFile", + "switch": "WINMDFILE:", + "comment": "Windows Metadata File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "WindowsMetadataLinkKeyFile", + "switch": "WINMDKEYFILE:", + "comment": "Windows Metadata Key File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "WindowsMetadataKeyContainer", + "switch": "WINMDKEYCONTAINER:", + "comment": "Windows Metadata Key Container", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "EntryPointSymbol", + "switch": "ENTRY:", + "comment": "Entry Point", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "BaseAddress", + "switch": "BASE:", + "comment": "Base Address", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "ImportLibrary", + "switch": "IMPLIB:", + "comment": "Import Library", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "MergeSections", + "switch": "MERGE:", + "comment": "Merge Sections", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "LinkKeyFile", + "switch": "KEYFILE:", + "comment": "Key File", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "KeyContainer", + "switch": "KEYCONTAINER:", + "comment": "Key Container", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "TypeLibraryResourceID", + "switch": "TLBID:", + "comment": "TypeLib Resource ID", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "SectionAlignment", + "switch": "ALIGN:", + "comment": "SectionAlignment", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "PdbThreads", + "switch": "pdbthreads:", + "comment": "", + "value": "", + "flags": [ + "UserValue" + ] + }, + { + "name": "CgThreads", + "switch": "cgthreads:", + "comment": "", + "value": "", + "flags": [ + "UserValue" + ] + } +] From 9e10045552bb28f632bae592636662253c87be80 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:27:30 -0400 Subject: [PATCH 0930/1519] VS: Fix `/MANIFESTUAC:` link flag mapping for v143 Apply the changes from commit d2fcc6748a (VS: Fix `/MANIFESTUAC:NO` link flag mapping for v142, 2019-01-24, v3.14.0-rc1~74^2~4) and commit fd45cbf40e (VS: Fix `/MANIFESTUAC:` link flag mapping for v142, 2019-01-24, v3.14.0-rc1~74^2~1) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_Link.json | 29 +++------------------ 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_Link.json b/Templates/MSBuild/FlagTables/v143_Link.json index bdf39c7f902..782218790d2 100644 --- a/Templates/MSBuild/FlagTables/v143_Link.json +++ b/Templates/MSBuild/FlagTables/v143_Link.json @@ -650,26 +650,15 @@ "value": "true", "flags": [] }, - { - "name": "EnableUAC", - "switch": "MANIFESTUAC:NO", - "comment": "Enable User Account Control (UAC)", - "value": "false", - "flags": [ - "UserValue", - "UserIgnored", - "Continue" - ] - }, { "name": "EnableUAC", "switch": "MANIFESTUAC:", - "comment": "Enable User Account Control (UAC)", - "value": "true", + "comment": "", + "value": "", "flags": [ "UserValue", - "UserIgnored", - "Continue" + "UserRequired", + "SpaceAppendable" ] }, { @@ -682,16 +671,6 @@ "UserRequired" ] }, - { - "name": "UACUIAccess", - "switch": "MANIFESTUAC:", - "comment": "UAC Bypass UI Protection", - "value": "true", - "flags": [ - "UserValue", - "UserRequired" - ] - }, { "name": "UACUIAccess", "switch": "uiAccess='false'", From d3175a6079655a07174810ba5f6d344702cd6c09 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:31:37 -0400 Subject: [PATCH 0931/1519] VS: Map the link `/debug` flag for v143 Apply the changes from commit 533f95c847 (VS: Map the link `/debug` flag for v142, 2019-01-24, v3.14.0-rc1~74^2~3) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_Link.json | 28 +++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_Link.json b/Templates/MSBuild/FlagTables/v143_Link.json index 782218790d2..c52d01eb794 100644 --- a/Templates/MSBuild/FlagTables/v143_Link.json +++ b/Templates/MSBuild/FlagTables/v143_Link.json @@ -118,33 +118,41 @@ "value": "RequireAdministrator", "flags": [] }, - { - "name": "GenerateDebugInformation", - "switch": "", - "comment": "No", - "value": "false", - "flags": [] - }, { "name": "GenerateDebugInformation", "switch": "DEBUG", "comment": "Generate Debug Information", "value": "true", - "flags": [] + "flags": [ + "CaseInsensitive" + ] }, { "name": "GenerateDebugInformation", "switch": "DEBUG:FASTLINK", "comment": "Generate Debug Information optimized for faster links", "value": "DebugFastLink", - "flags": [] + "flags": [ + "CaseInsensitive" + ] }, { "name": "GenerateDebugInformation", "switch": "DEBUG:FULL", "comment": "Generate Debug Information optimized for sharing and publishing", "value": "DebugFull", - "flags": [] + "flags": [ + "CaseInsensitive" + ] + }, + { + "name": "GenerateDebugInformation", + "switch": "DEBUG:NONE", + "comment": "Produces no debugging information", + "value": "false", + "flags": [ + "CaseInsensitive" + ] }, { "name": "SubSystem", From b933584a7210ac5d81397981589267efa8a9b582 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:34:15 -0400 Subject: [PATCH 0932/1519] VS: Remove the /MERGE flag from v143 link flag table Apply the change from commit a9f992434d (VS: Remove the /MERGE flag from FlagTables, 2021-06-08, v3.21.0-rc1~58^2) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_Link.json | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_Link.json b/Templates/MSBuild/FlagTables/v143_Link.json index c52d01eb794..71d58f885aa 100644 --- a/Templates/MSBuild/FlagTables/v143_Link.json +++ b/Templates/MSBuild/FlagTables/v143_Link.json @@ -1350,15 +1350,6 @@ "UserValue" ] }, - { - "name": "MergeSections", - "switch": "MERGE:", - "comment": "Merge Sections", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "LinkKeyFile", "switch": "KEYFILE:", From 2d64b012233fec5e861cedb26f8d2a9c7c2c87d9 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:41:02 -0400 Subject: [PATCH 0933/1519] VS: Fix `/analyze:log` flag mapping for v143 Apply the change from commit fb2e418c64 (VS: Fix `/analyze:log` flag mapping for v142, 2019-01-24, v3.14.0-rc1~74^2~10) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_CL.json | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 918fe81cdbb..146ad5f2ceb 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -1352,13 +1352,12 @@ ] }, { - "name": "PREfastAdditionalOptions", - "switch": "analyze:", - "comment": "Additional Code Analysis Native options", + "name": "PREfastLog", + "switch": "analyze:log", + "comment": "Code Analysis Log", "value": "", "flags": [ - "UserValue", - "SemicolonAppendable" + "UserFollowing" ] }, { @@ -1504,15 +1503,6 @@ "UserRequired" ] }, - { - "name": "PREfastLog", - "switch": "analyze:log", - "comment": "Code Analysis Log", - "value": "", - "flags": [ - "UserValue" - ] - }, { "name": "PREfastProjectDirectory", "switch": "analyze:projectdirectory", From cccef3c5b41af2fa3ecb396f50ac32f42ba9e5f1 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:42:10 -0400 Subject: [PATCH 0934/1519] VS: Add `-Zc:inline[-]` flag table entry for v143 Apply the change from commit 0df3790371 (VS: Add `-Zc:inline[-]` flag table entry for v142, 2019-01-24, v3.14.0-rc1~74^2~9) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_CL.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 146ad5f2ceb..69d4ac3587b 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -1061,6 +1061,13 @@ "value": "true", "flags": [] }, + { + "name": "RemoveUnreferencedCodeData", + "switch": "Zc:inline-", + "comment": "Remove unreferenced code and data", + "value": "false", + "flags": [] + }, { "name": "RemoveUnreferencedCodeData", "switch": "Zc:inline", From 3322bb70813881e3998c84cecf8b9c79dcf9590b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:43:02 -0400 Subject: [PATCH 0935/1519] VS: Populate `/Y-` flag table entry for v143 Apply the change from commit 460a146e2b (VS: Populate `/Y-` flag table entry for v142, 2019-01-24, v3.14.0-rc1~74^2~8) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_CL.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 69d4ac3587b..8851c9ba11e 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -555,7 +555,7 @@ }, { "name": "PrecompiledHeader", - "switch": "", + "switch": "Y-", "comment": "Not Using Precompiled Headers", "value": "NotUsing", "flags": [] From a070d87e085b2ddc41c10951054ddbc7cb2b61aa Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:44:58 -0400 Subject: [PATCH 0936/1519] VS: Populate `-Qspectre-` flag table entry for v143 Apply the change from commit 43aa632f57 (VS: Populate `-Qspectre-` flag table entry for v142, 2019-01-24, v3.14.0-rc1~74^2~7) to the v143 flag table. Sort the longer options before the shorter ones. Remove the default variant with an empty switch. --- Templates/MSBuild/FlagTables/v143_CL.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 8851c9ba11e..b8697fb1665 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -428,9 +428,9 @@ }, { "name": "SpectreMitigation", - "switch": "Qspectre", - "comment": "Enabled", - "value": "Spectre", + "switch": "Qspectre-load-cf", + "comment": "All Control Flow Loads", + "value": "SpectreLoadCF", "flags": [] }, { @@ -442,16 +442,16 @@ }, { "name": "SpectreMitigation", - "switch": "Qspectre-load-cf", - "comment": "All Control Flow Loads", - "value": "SpectreLoadCF", + "switch": "Qspectre-", + "comment": "Disabled", + "value": "false", "flags": [] }, { "name": "SpectreMitigation", - "switch": "", - "comment": "Disabled", - "value": "false", + "switch": "Qspectre", + "comment": "Enabled", + "value": "Spectre", "flags": [] }, { From 993d706a170e7009130d5f66b2f3f5e7dda64c9b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:46:21 -0400 Subject: [PATCH 0937/1519] VS: Populate `/JMC-` flag table entry for v143 Apply the change from commit 049410c0b6 (VS: Populate `/JMC-` flag table entry for v142, 2019-01-24, v3.14.0-rc1~74^2~6) to the v143 flag table. --- Templates/MSBuild/FlagTables/v143_CL.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index b8697fb1665..35e0bd0ecb1 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -742,6 +742,13 @@ "value": "true", "flags": [] }, + { + "name": "SupportJustMyCode", + "switch": "JMC-", + "comment": "Support Just My Code Debugging", + "value": "false", + "flags": [] + }, { "name": "SupportJustMyCode", "switch": "JMC", From c167de7e7001b352c24b23ffed918b6af74b2574 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:50:04 -0400 Subject: [PATCH 0938/1519] VS: Remove empty ConformanceMode entry from flag table for v143 --- Templates/MSBuild/FlagTables/v143_CL.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 35e0bd0ecb1..5bf0666c280 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -454,13 +454,6 @@ "value": "Spectre", "flags": [] }, - { - "name": "ConformanceMode", - "switch": "", - "comment": "Default", - "value": "Default", - "flags": [] - }, { "name": "ConformanceMode", "switch": "permissive-", From ccb6083cbe2a2e2f8d0d75126dda85896940c8af Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:51:41 -0400 Subject: [PATCH 0939/1519] VS: Remove empty LanguageStandard entries from flag table for v143 --- Templates/MSBuild/FlagTables/v143_CL.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 5bf0666c280..fec5a139c9d 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -468,13 +468,6 @@ "value": "false", "flags": [] }, - { - "name": "LanguageStandard", - "switch": "", - "comment": "Default (ISO C++14 Standard)", - "value": "Default", - "flags": [] - }, { "name": "LanguageStandard", "switch": "std:c++14", @@ -503,13 +496,6 @@ "value": "stdcpplatest", "flags": [] }, - { - "name": "LanguageStandard_C", - "switch": "", - "comment": "Default (Legacy MSVC)", - "value": "Default", - "flags": [] - }, { "name": "LanguageStandard_C", "switch": "std:c11", From 3f19847b28e9f5e53131c507122bb817a24b6885 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:57:34 -0400 Subject: [PATCH 0940/1519] VS: Remove empty ExternalWarningLevel entry from flag table for v143 --- Templates/MSBuild/FlagTables/v143_CL.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index fec5a139c9d..a866fea92e8 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -609,13 +609,6 @@ "value": "Level4", "flags": [] }, - { - "name": "ExternalWarningLevel", - "switch": "", - "comment": "Inherit Project Warning Level", - "value": "InheritWarningLevel", - "flags": [] - }, { "name": "CallingConvention", "switch": "Gd", From 919fc7fd5f6273476ef0e5c4856e89475a238d91 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:54:09 -0400 Subject: [PATCH 0941/1519] VS: Remove broken EnableASAN entry from flag table for v143 Apply the change from commit 7fce2d372e (VS: Revert "Add support for ASAN -fsanitize=address flag", 2021-04-26, v3.21.0-rc1~270^2) to the v143 flag table. Issue: #21081 --- Templates/MSBuild/FlagTables/v143_CL.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index a866fea92e8..41c80001285 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -795,13 +795,6 @@ "value": "true", "flags": [] }, - { - "name": "EnableASAN", - "switch": "fsanitize=address", - "comment": "Enable Address Sanitizer", - "value": "true", - "flags": [] - }, { "name": "IntrinsicFunctions", "switch": "Oi", From 1ac1436b25bc65b47ec037c98956ac480bcbed05 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 13:59:54 -0400 Subject: [PATCH 0942/1519] VS: Fix `/sourceDependencies` flag table entries for v143 Revise the `/sourceDependencies[:directives]` table entries to properly distinguish the two options (because one is a prefix of the other), and to populate both `Generate*Dependencies` and `*DependenciesFile`. This is the manual update mentioned in commit 887e9df0c7 (VS: Update v142 CL flag table for VS 16.10, 2021-06-04, v3.21.0-rc1~77^2). --- Templates/MSBuild/FlagTables/v143_CL.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 41c80001285..9d8ddb02561 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -1116,8 +1116,6 @@ "comment": "Generate Module Dependenices File", "value": "true", "flags": [ - "UserValue", - "UserIgnored", "Continue" ] }, @@ -1138,8 +1136,6 @@ "comment": "Generate Source Dependencies File", "value": "true", "flags": [ - "UserValue", - "UserIgnored", "Continue" ] }, @@ -1430,8 +1426,7 @@ "comment": "Module Dependencies File Name", "value": "", "flags": [ - "UserValue", - "UserRequired" + "UserFollowing" ] }, { @@ -1468,8 +1463,7 @@ "comment": "Source Dependencies File Name", "value": "", "flags": [ - "UserValue", - "UserRequired" + "UserFollowing" ] }, { From 0c7f918fb1100c96e043c2f7c13732553b746ced Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 14 Jul 2021 14:05:50 -0400 Subject: [PATCH 0943/1519] VS: Update Visual Studio 17 2022 generator for Preview 2 In particular, update to toolset `v143`. Fixes: #22339 --- Help/generator/Visual Studio 17 2022.rst | 4 ++-- Help/release/3.21.rst | 13 ++++++++++++- Help/variable/MSVC_VERSION.rst | 2 -- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 3 +-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index 06deda463f0..60073658c63 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -7,7 +7,7 @@ Generates Visual Studio 17 (VS 2022) project files. .. warning:: - This is experimental and based on "Visual Studio 2022 Preview 1.1". + This is experimental and based on "Visual Studio 2022 Preview 2". As of this version of CMake, VS 2022 has not been released. Project Types @@ -51,7 +51,7 @@ name (architecture). For example: Toolset Selection ^^^^^^^^^^^^^^^^^ -The ``v142`` toolset that comes with VS 17 2022 Preview 1.1 is selected by +The ``v143`` toolset that comes with VS 17 2022 Preview 2 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 204880b7b42..3e705529fe1 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -27,7 +27,7 @@ Generators ---------- * The :generator:`Visual Studio 17 2022` generator was added. This is - experimental and based on "Visual Studio 2022 Preview 1.1" because this + experimental and based on "Visual Studio 2022 Preview 2" because this version of VS has not been released. * The :ref:`Makefile Generators` and the :generator:`Ninja` generator @@ -293,3 +293,14 @@ Other Changes `cmake.org <https://cmake.org/download/>`_ now support ``liblzma`` multi-threading. See the :variable:`CPACK_THREADS` and :variable:`CPACK_ARCHIVE_THREADS` variables. + +Updates +======= + +Changes made since CMake 3.21.0 include the following. + +3.21.1 +------ + +* The :generator:`Visual Studio 17 2022` generator is now based on + "Visual Studio 2022 Preview 2". Previously it was based on "Preview 1.1". diff --git a/Help/variable/MSVC_VERSION.rst b/Help/variable/MSVC_VERSION.rst index 241eb0384e3..cbb3a3c3828 100644 --- a/Help/variable/MSVC_VERSION.rst +++ b/Help/variable/MSVC_VERSION.rst @@ -19,8 +19,6 @@ Known version numbers are:: 1900 = VS 14.0 (v140 toolset) 1910-1919 = VS 15.0 (v141 toolset) 1920-1929 = VS 16.0 (v142 toolset) - -.. 1930-1939 = VS 17.0 (v143 toolset) See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` and diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 4fab0b930b9..79c06d6a154 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -104,8 +104,7 @@ static const char* VSVersionToToolset( case cmGlobalVisualStudioGenerator::VS16: return "v142"; case cmGlobalVisualStudioGenerator::VS17: - // FIXME: VS 2022 Preview 1 uses v142. Will it be v143 later? - return "v142"; + return "v143"; } return ""; } From 4e17e90988e9f23dece4c04f574d456309d7a50c Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 16 Jul 2021 00:01:08 -0400 Subject: [PATCH 0944/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 520ac4bd708..613d3094e56 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210715) +set(CMake_VERSION_PATCH 20210716) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From aa874dc6090cf6b6c9621572419738d105ff4ba3 Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Fri, 16 Jul 2021 10:18:31 -0400 Subject: [PATCH 0945/1519] CMakePresets.json: Fix expansion issue with empty binaryDir When resolving binaryDir into a full path from a relative path, we forgot to check if binaryDir is altogether empty, causing empty binaryDir's to resolve to the source directory. Fix this. Fixes: #22434 --- Source/cmCMakePresetsFile.cxx | 10 ++++++---- .../CMakePresets/OptionalBinaryDirFieldNoS.cmake | 4 ++++ .../CMakePresets/OptionalBinaryDirFieldNoS.json.in | 9 +++++++++ Tests/RunCMake/CMakePresets/RunCMakeTest.cmake | 5 +++++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake create mode 100644 Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index 2f9972c381c..fd578faef79 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -197,11 +197,13 @@ bool ExpandMacros(const cmCMakePresetsFile& file, std::string binaryDir = preset.BinaryDir; CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset)) - if (!cmSystemTools::FileIsFullPath(binaryDir)) { - binaryDir = cmStrCat(file.SourceDir, '/', binaryDir); + if (!binaryDir.empty()) { + if (!cmSystemTools::FileIsFullPath(binaryDir)) { + binaryDir = cmStrCat(file.SourceDir, '/', binaryDir); + } + out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir); + cmSystemTools::ConvertToUnixSlashes(out->BinaryDir); } - out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir); - cmSystemTools::ConvertToUnixSlashes(out->BinaryDir); if (!preset.InstallDir.empty()) { std::string installDir = preset.InstallDir; diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake new file mode 100644 index 00000000000..ae8a0def19f --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake @@ -0,0 +1,4 @@ +include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake) + +get_filename_component(_parent_dir "${CMAKE_SOURCE_DIR}" DIRECTORY) +test_variable(CMAKE_BINARY_DIR "" "${_parent_dir}/OptionalBinaryDirFieldNoS-build") diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in new file mode 100644 index 00000000000..0e3addd560b --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in @@ -0,0 +1,9 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "OptionalBinaryDirFieldNoS", + "generator": "@RunCMake_GENERATOR@" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 3b9806ab7ef..31bd8a44536 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -312,6 +312,11 @@ unset(CMakePresets_FILE) # Test optional generator and buildDir fields run_cmake_presets(OptionalBinaryDirField -B "${RunCMake_BINARY_DIR}/OptionalBinaryDirField/build") run_cmake_presets(OptionalGeneratorField -G "${RunCMake_GENERATOR}") +set(CMakePresets_NO_S_ARG TRUE) +set(CMakePresets_SOURCE_ARG "../OptionalBinaryDirFieldNoS") +run_cmake_presets(OptionalBinaryDirFieldNoS) +unset(CMakePresets_SOURCE_ARG) +unset(CMakePresets_NO_S_ARG) # Test the example from the documentation file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example) From 7f7e7485f3fc52ea5242bd31ff30631950604075 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 17 Jul 2021 00:01:10 -0400 Subject: [PATCH 0946/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 613d3094e56..001692f9c01 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210716) +set(CMake_VERSION_PATCH 20210717) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6d5f74fcd7dd6c6490667f92382d7fda27ce9b3e Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 17 Jul 2021 16:43:12 +1000 Subject: [PATCH 0947/1519] Help: Clarify wording of CMP0124 --- Help/policy/CMP0124.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Help/policy/CMP0124.rst b/Help/policy/CMP0124.rst index 88d03e35dda..3935166ad5e 100644 --- a/Help/policy/CMP0124.rst +++ b/Help/policy/CMP0124.rst @@ -3,14 +3,12 @@ CMP0124 .. versionadded:: 3.21 -The loop variables created by :command:`foreach` command have now their scope -restricted to the loop scope. +When this policy is set to ``NEW``, the scope of loop variables defined by the +:command:`foreach` command is restricted to the loop only. They will be unset +at the end of the loop. -Starting with CMake 3.21, the :command:`foreach` command ensures that the loop -variables have their scope restricted to the loop scope. - -The ``OLD`` behavior for this policy let the loop variables to exist, with an -empty value, in the outer scope of loop scope. +The ``OLD`` behavior for this policy still clears the loop variables at the end +of the loop, but does not unset them. This leaves them as defined, but empty. This policy was introduced in CMake version 3.21. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. From c4bc250f8cabab428f3206c196000dfc07881db5 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 17 Jul 2021 12:08:52 +1000 Subject: [PATCH 0948/1519] Help: Explain policy CMP0125 in more detail --- Help/policy/CMP0125.rst | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/Help/policy/CMP0125.rst b/Help/policy/CMP0125.rst index 19571dc2517..0b1704e90bc 100644 --- a/Help/policy/CMP0125.rst +++ b/Help/policy/CMP0125.rst @@ -4,18 +4,35 @@ CMP0125 .. versionadded:: 3.21 The :command:`find_file`, :command:`find_path`, :command:`find_library` and -:command:`find_program` commands handle cache variables in the same way -regardless of whether they are defined on the command line, with or without a -type, or using the :command:`set` command. - -Starting with CMake 3.21, the :command:`find_file`, :command:`find_path`, -:command:`find_library`, and :command:`find_program` commands ensure that the -cache variables will be used in the same way regardless how they were defined -and the result will be always successful if the searched artifact exists. - -The ``OLD`` behavior for this policy is to have the find commands' behaviors -differ depending on how the cache variable is defined. The ``NEW`` behavior for -this policy is to have consistent behavior. +:command:`find_program` commands cache their result in the variable specified +by their first argument. Prior to CMake 3.21, if a cache variable of that +name already existed before the call but the cache variable had no type, any +non-cache variable of the same name would be discarded and the cache variable +was always used (see also :policy:`CMP0126` for a different but similar +behavior). This contradicts the convention that a non-cache variable should +take precedence over a cache variable of the same name. Such a situation can +arise if a user sets a cache variable on the command line without specifying +a type, such as ``cmake -DMYVAR=blah ...`` instead of +``cmake -DMYVAR:FILEPATH=blah``. + +Related to the above, if a cache variable of the specified name already exists +and it *does* have a type, the various ``find_...()`` commands would return +that value unchanged. In particular, if it contained a relative path, it +would not be converted to an absolute path in this situation. + +When policy ``CMP0125`` is set to ``OLD`` or is unset, the behavior is as +described above. When it is set to ``NEW``, the behavior is as follows: + +* If a non-cache variable of the specified name exists when the ``find_...()`` + command is called, its value will be used regardless of whether a cache + variable of the same name already exists or not. A cache variable will not + be created in this case if no such cache variable existed before. + If a cache variable of the specified name did already exist, the cache will + be updated to match the non-cache variable. + +* The various ``find...()`` commands will always provide an absolute path in + the result variable, except where a relative path provided by a cache or + non-cache variable cannot be resolved to an existing path. This policy was introduced in CMake version 3.21. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. From 7b5fa0f7b43b6d02388aa1bbf8ad29b72976d627 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 17 Jul 2021 16:27:41 +1000 Subject: [PATCH 0949/1519] Help: Make policy CMP0126 wording more accurate The OLD behavior only removes a non-cache variable of the same name in specific circumstances. The previous wording implied that it would always occur. Also add a note about the behavior compared to the analogous CMP0077 policy, which affects the option() command in a similar but subtly different way. --- Help/policy/CMP0077.rst | 4 ++++ Help/policy/CMP0126.rst | 23 ++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Help/policy/CMP0077.rst b/Help/policy/CMP0077.rst index 174cde91bcd..d8744a9458b 100644 --- a/Help/policy/CMP0077.rst +++ b/Help/policy/CMP0077.rst @@ -46,6 +46,10 @@ name: variable of the same name exists. The normal variable is not removed. The cache entry is not created or updated and is ignored if it exists. +See :policy:`CMP0126` for a similar policy for the :command:`set(CACHE)` +command, but note that there are some differences in ``NEW`` behavior +between the two policies. + This policy was introduced in CMake version 3.13. CMake version |release| warns when the policy is not set and uses ``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` diff --git a/Help/policy/CMP0126.rst b/Help/policy/CMP0126.rst index 0ced8fa5aae..ba027b3514d 100644 --- a/Help/policy/CMP0126.rst +++ b/Help/policy/CMP0126.rst @@ -3,16 +3,25 @@ CMP0126 .. versionadded:: 3.21 -The :command:`set(CACHE)` does not remove a normal variable of the same name. +When this policy is set to ``NEW``, the :command:`set(CACHE)` command does not +remove any normal variable of the same name from the current scope. +The ``OLD`` behavior removes any normal variable of the same name from the +current scope in the following situations: -Starting with CMake 3.21, the :command:`set(CACHE)` does not remove, in the -current scope, any normal variable with the same name. +* No cache variable of that name existed previously. -The ``OLD`` behavior for this policy is to have the :command:`set(CACHE)` -command removing the normal variable of the same name, if any. The ``NEW`` -behavior for this policy is to keep the normal variable of the same name. +* A cache variable of that name existed previously, but it had no type. + This can occur when the variable was set on the command line using a form + like ``cmake -DMYVAR=blah`` instead of ``cmake -DMYVAR:STRING=blah``. -This policy was introduced in CMake version 3.21. Use the +Note that the ``NEW`` behavior has an important difference to the similar +``NEW`` behavior of policy :policy:`CMP0077`. The :command:`set(CACHE)` +command always sets the cache variable if it did not exist previously, +regardless of the ``CMP0126`` policy setting. The :command:`option` command +will *not* set the cache variable if a non-cache variable of the same name +already exists and :policy:`CMP0077` is set to ``NEW``. + +Policy ``CMP0126`` was introduced in CMake version 3.21. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. Unlike many policies, CMake version |release| does *not* warn when the policy is not set and simply uses ``OLD`` behavior. See documentation of the From 0094d12eadd9e2a72088206c1e3373894d6f5063 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 18 Jul 2021 00:01:07 -0400 Subject: [PATCH 0950/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 001692f9c01..9a6318d6069 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210717) +set(CMake_VERSION_PATCH 20210718) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 8be7694d9756f535d7f681b396cfda44e0463c64 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 18 Jul 2021 15:57:06 +1000 Subject: [PATCH 0951/1519] Help: Fix trivial typo --- Help/command/target_link_libraries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst index ac231bc8f2b..c85094aa918 100644 --- a/Help/command/target_link_libraries.rst +++ b/Help/command/target_link_libraries.rst @@ -300,7 +300,7 @@ The object files associated with an object library may be referenced by the :genex:`$<TARGET_OBJECTS>` generator expression. Such object files are placed on the link line *before* all libraries, regardless of their relative order. Additionally, an ordering dependency will be -added to the build sysstem to make sure the object library is up-to-date +added to the build system to make sure the object library is up-to-date before the dependent target links. For example, the code .. code-block:: cmake From b5a96716eb38e5859f10947e3d61bb4a8c0dffc0 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 18 Jul 2021 16:45:20 +1000 Subject: [PATCH 0952/1519] Help: Clarify which project() call PROJECT_IS_TOP_LEVEL is for --- Help/variable/PROJECT_IS_TOP_LEVEL.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Help/variable/PROJECT_IS_TOP_LEVEL.rst b/Help/variable/PROJECT_IS_TOP_LEVEL.rst index ad61fecc059..7e407045a5c 100644 --- a/Help/variable/PROJECT_IS_TOP_LEVEL.rst +++ b/Help/variable/PROJECT_IS_TOP_LEVEL.rst @@ -3,7 +3,8 @@ PROJECT_IS_TOP_LEVEL .. versionadded:: 3.21 -A boolean variable indicating whether :command:`project` was called in a top +A boolean variable indicating whether the most recently called +:command:`project` command in the current scope or above was in the top level ``CMakeLists.txt`` file. Some modules should only be included as part of the top level From fabbb69e69698b88f30fa44b4398cc9ff38ed436 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 19 Jul 2021 00:01:13 -0400 Subject: [PATCH 0953/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9a6318d6069..85be49ecc7d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210718) +set(CMake_VERSION_PATCH 20210719) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 85e740312f076404045e8a411578349549b3462f Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 14 Jul 2021 16:25:36 -0400 Subject: [PATCH 0954/1519] Help/ctest_test: add a comment to also update `ctest_memcheck` Since these commands share a common argument parser, the documentation should be kept synchronized. --- Help/command/ctest_test.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 2153c90de35..2104c47c625 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -29,6 +29,10 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`. [QUIET] ) +.. + _note: If updating the argument list here, please also update the argument + list documentation for :command:`ctest_memcheck` as well. + Run tests in the project build tree and store results in ``Test.xml`` for submission with the :command:`ctest_submit` command. From aa3ab3eb925a601e3acd2d9f569fc3183fab2f8b Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Mon, 12 Jul 2021 13:26:36 -0400 Subject: [PATCH 0955/1519] find_library: Infer library prefix and suffix when in script mode This aligns `find_library` with the documentation that states it can be called from script mode. This is done by infering the proper prefix and suffix values when `find_library` is called when the `CMAKE_FIND_LIBRARY*` are not set. This also means that `find_library` won't produce obscure error messages about unset definitions. Fixes: #22027 --- Source/cmFindLibraryCommand.cxx | 35 ++++++++++++++++--- .../FromScriptMode-stderr-darwin.txt | 4 +++ .../FromScriptMode-stderr-windows.txt | 4 +++ .../find_library/FromScriptMode-stderr.txt | 4 +++ .../find_library/FromScriptMode.cmake | 15 ++++++++ .../RunCMake/find_library/RunCMakeTest.cmake | 2 ++ 6 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt create mode 100644 Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt create mode 100644 Tests/RunCMake/find_library/FromScriptMode-stderr.txt create mode 100644 Tests/RunCMake/find_library/FromScriptMode.cmake diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 0cbe637738b..ef960d18f36 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -259,6 +259,34 @@ struct cmFindLibraryHelper }; }; +namespace { + +std::string const& get_prefixes(cmMakefile* mf) +{ +#ifdef _WIN32 + static std::string defaultPrefix = ";lib"; +#else + static std::string defaultPrefix = "lib"; +#endif + cmProp prefixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_PREFIXES"); + return (prefixProp) ? *prefixProp : defaultPrefix; +} + +std::string const& get_suffixes(cmMakefile* mf) +{ +#ifdef _WIN32 + static std::string defaultSuffix = ".lib;.dll.a;.a"; +#elif defined(__APPLE__) + static std::string defaultSuffix = ".tbd;.dylib;.so;.a"; +#elif defined(__hpux) + static std::string defaultSuffix = ".sl;.so;.a"; +#else + static std::string defaultSuffix = ".so;.a"; +#endif + cmProp suffixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_SUFFIXES"); + return (suffixProp) ? *suffixProp : defaultSuffix; +} +} cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, cmFindBase const* base) : Makefile(mf) @@ -268,10 +296,9 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, this->GG = this->Makefile->GetGlobalGenerator(); // Collect the list of library name prefixes/suffixes to try. - std::string const& prefixes_list = - this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES"); - std::string const& suffixes_list = - this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES"); + std::string const& prefixes_list = get_prefixes(this->Makefile); + std::string const& suffixes_list = get_suffixes(this->Makefile); + cmExpandList(prefixes_list, this->Prefixes, true); cmExpandList(suffixes_list, this->Suffixes, true); this->RegexFromList(this->PrefixRegexStr, this->Prefixes); diff --git a/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt new file mode 100644 index 00000000000..185720bbb4c --- /dev/null +++ b/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt @@ -0,0 +1,4 @@ +.*find_library considered the following locations.* +.*\(lib\)library_no_exist\(\\.tbd\|\\.dylib\|\\.so\|\\.a\).* +.*The item was found at.* +.*lib/libcreated.a.* diff --git a/Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt new file mode 100644 index 00000000000..501ec0ff518 --- /dev/null +++ b/Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt @@ -0,0 +1,4 @@ +.*find_library considered the following locations.* +.*\(\|lib\)library_no_exist\(\\.lib\|\\.dll\\.a\|\\.a\).* +.*The item was found at.* +.*lib/libcreated.a.* diff --git a/Tests/RunCMake/find_library/FromScriptMode-stderr.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr.txt new file mode 100644 index 00000000000..046f680766b --- /dev/null +++ b/Tests/RunCMake/find_library/FromScriptMode-stderr.txt @@ -0,0 +1,4 @@ +.*find_library considered the following locations.* +.*\(lib\)library_no_exist\(\\.so\|\\.a\).* +.*The item was found at.* +.*lib/libcreated.a.* diff --git a/Tests/RunCMake/find_library/FromScriptMode.cmake b/Tests/RunCMake/find_library/FromScriptMode.cmake new file mode 100644 index 00000000000..4d3c6990aa2 --- /dev/null +++ b/Tests/RunCMake/find_library/FromScriptMode.cmake @@ -0,0 +1,15 @@ + +if(TEMP_DIR) + file(REMOVE_RECURSE "${TEMP_DIR}") + file(MAKE_DIRECTORY "${TEMP_DIR}") + file(MAKE_DIRECTORY "${TEMP_DIR}/lib") + file(WRITE "${TEMP_DIR}/lib/libcreated.a" "created") +endif() + +set(CMAKE_FIND_DEBUG_MODE 1) +find_library(CREATED_LIBRARY NAMES library_no_exist) + +set(CMAKE_PREFIX_PATH "${TEMP_DIR}") +find_library(CREATED_LIBRARY NAMES created) +message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'") +set(CMAKE_FIND_DEBUG_MODE 0) diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index e2971733b24..ad02c821c52 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -10,3 +10,5 @@ endif() run_cmake(PrefixInPATH) run_cmake(Required) run_cmake(NO_CACHE) + +run_cmake_script(FromScriptMode "-DTEMP_DIR=${RunCMake_BINARY_DIR}/FromScriptMode-temp") From 9cebdbec77ac59a1394c3a28da43a7bf0bd37fe9 Mon Sep 17 00:00:00 2001 From: Alexey Edelev <semlanik@gmail.com> Date: Fri, 16 Jul 2021 17:24:53 +0200 Subject: [PATCH 0956/1519] AUTOUIC: Fix cyclic dependency between generated UI headers and timestamp Once the generated UI headers are created by UIC they also are involved into processing in next run on ninja. Autogen adds `ui_*.h` files to the deps file `ui_*.h` and this cause timestamp start depend on `ui_*.h`. Meanwhile `ui_*.h` depend on timestamp because of the explicit rules added by commit 1265c65b33 (AUTOUIC: Collect ui header files for Ninja generator, 2021-02-18, v3.21.0-rc1~600^2). Avoid adding `ui_*.h` to deps file at second ninja run. Fixes: #16776 --- Source/cmQtAutoMocUic.cxx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index f5c195fd1d2..2753fd57c02 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -2248,12 +2248,20 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process() std::for_each(this->MocEval().SourceMappings.begin(), this->MocEval().SourceMappings.end(), processMappingEntry); - // Remove SKIP_AUTOMOC files - dependencies.erase(std::remove_if(dependencies.begin(), dependencies.end(), - [this](const std::string& dep) { - return this->MocConst().skipped(dep); - }), - dependencies.end()); + // Remove SKIP_AUTOMOC files. + // Also remove AUTOUIC header files to avoid cyclic dependency. + dependencies.erase( + std::remove_if(dependencies.begin(), dependencies.end(), + [this](const std::string& dep) { + return this->MocConst().skipped(dep) || + std::any_of( + this->UicEval().Includes.begin(), + this->UicEval().Includes.end(), + [&dep](MappingMapT::value_type const& mapping) { + return dep == mapping.second->OutputFile; + }); + }), + dependencies.end()); // Remove duplicates to make the depfile smaller std::sort(dependencies.begin(), dependencies.end()); From f75610d49245b1ffac7526e1fc8b55080669dad7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 19 Jul 2021 15:09:36 -0400 Subject: [PATCH 0957/1519] CMakeDetermineCompilerId: Fix CMAKE_EXECUTABLE_FORMAT in CMP0126 NEW behavior Setting `CMAKE_EXECUTABLE_FORMAT` as a normal variable is unnecessary because setting it as a cache entry already makes the value visible to the calling scope. Fixes: #22433 --- Modules/CMakeDetermineCompilerId.cmake | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index bd1e732530f..e933cf4e854 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -1012,9 +1012,6 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) endif() endif() - if(NOT DEFINED CMAKE_EXECUTABLE_FORMAT) - set(CMAKE_EXECUTABLE_FORMAT) - endif() # Return the information extracted. set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE) set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE) @@ -1026,7 +1023,6 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) set(CMAKE_${lang}_COMPILER_WRAPPER "${COMPILER_WRAPPER}" PARENT_SCOPE) set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE) set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE) - set(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE) set(COMPILER_QNXNTO "${COMPILER_QNXNTO}" PARENT_SCOPE) set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE) endfunction() From c8ea886123711c3e47794bb1f297950333e4904c Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Tue, 20 Jul 2021 08:38:49 +1000 Subject: [PATCH 0958/1519] Help: Re-order file() sub-commands in Filesystem section The file(COPY_FILE) sub-command is closely related to the file(COPY) sub-command. Move the former to just before the latter for improved continuity. The file(RENAME) sub-command is also somewhat related to file(COPY_FILE), so it was also moved to keep it just before file(COPY_FILE). The file(MAKE_DIRECTORY) sub-command was also moved to just before the file(REMOVE) and file(REMOVE_RECURSE) sub-commands to keep them together and improve logical flow of operations. --- Help/command/file.rst | 56 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Help/command/file.rst b/Help/command/file.rst index 943bf7c1b86..a9cbd403c84 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -38,10 +38,10 @@ Synopsis `Filesystem`_ file({`GLOB`_ | `GLOB_RECURSE`_} <out-var> [...] [<globbing-expr>...]) + file(`MAKE_DIRECTORY`_ [<dir>...]) + file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...]) file(`RENAME`_ <oldname> <newname> [...]) file(`COPY_FILE`_ <oldname> <newname> [...]) - file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...]) - file(`MAKE_DIRECTORY`_ [<dir>...]) file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...]) file(`SIZE`_ <filename> <out-var>) file(`READ_SYMLINK`_ <linkname> <out-var>) @@ -691,6 +691,32 @@ Examples of recursive globbing include:: /dir/*.py - match all python files in /dir and subdirectories +.. _MAKE_DIRECTORY: + +.. code-block:: cmake + + file(MAKE_DIRECTORY [<directories>...]) + +Create the given directories and their parents as needed. + +.. _REMOVE: +.. _REMOVE_RECURSE: + +.. code-block:: cmake + + file(REMOVE [<files>...]) + file(REMOVE_RECURSE [<files>...]) + +Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given +files and directories, also non-empty directories. No error is emitted if a +given file does not exist. Relative input paths are evaluated with respect +to the current source directory. + +.. versionchanged:: 3.15 + Empty input paths are ignored with a warning. Previous versions of CMake + interpreted empty strings as a relative path with respect to the current + directory and removed its contents. + .. _RENAME: .. code-block:: cmake @@ -739,32 +765,6 @@ The options are: If the ``<newname>`` path already exists, do not replace it if it is the same as ``<oldname>``. Otherwise, an error is emitted. -.. _REMOVE: -.. _REMOVE_RECURSE: - -.. code-block:: cmake - - file(REMOVE [<files>...]) - file(REMOVE_RECURSE [<files>...]) - -Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given -files and directories, also non-empty directories. No error is emitted if a -given file does not exist. Relative input paths are evaluated with respect -to the current source directory. - -.. versionchanged:: 3.15 - Empty input paths are ignored with a warning. Previous versions of CMake - interpreted empty string as a relative path with respect to the current - directory and removed its contents. - -.. _MAKE_DIRECTORY: - -.. code-block:: cmake - - file(MAKE_DIRECTORY [<directories>...]) - -Create the given directories and their parents as needed. - .. _COPY: .. _INSTALL: From 8d1944c675a2240f3b71f813cbf7139429ab766c Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 18 Jul 2021 19:13:06 +1000 Subject: [PATCH 0959/1519] Help: Expand details for file(COPY_FILE) --- Help/command/file.rst | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Help/command/file.rst b/Help/command/file.rst index a9cbd403c84..f038871b7b2 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -751,6 +751,8 @@ The options are: [RESULT <result>] [ONLY_IF_DIFFERENT]) +.. versionadded:: 3.21 + Copy a file from ``<oldname>`` to ``<newname>``. Directories are not supported. Symlinks are ignored and ``<oldfile>``'s content is read and written to ``<newname>`` as a new file. @@ -762,8 +764,17 @@ The options are: If ``RESULT`` is not specified and the operation fails, an error is emitted. ``ONLY_IF_DIFFERENT`` - If the ``<newname>`` path already exists, do not replace it if it is the - same as ``<oldname>``. Otherwise, an error is emitted. + If the ``<newname>`` path already exists, do not replace it if the file's + contents are already the same as ``<oldname>`` (this avoids updating + ``<newname>``'s timestamp). + +This sub-command has some similarities to :command:`configure_file` with the +``COPYONLY`` option. An important difference is that :command:`configure_file` +creates a dependency on the source file, so CMake will be re-run if it changes. +The ``file(COPY_FILE)`` sub-command does not create such a dependency. + +See also the ``file(COPY)`` sub-command just below which provides +further file-copying capabilities. .. _COPY: .. _INSTALL: @@ -779,6 +790,11 @@ The options are: [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS <permissions>...]] [...]) +.. note:: + + For a simple file copying operation, the ``file(COPY_FILE)`` sub-command + just above may be easier to use. + The ``COPY`` signature copies files, directories, and symlinks to a destination folder. Relative input paths are evaluated with respect to the current source directory, and a relative destination is From 6521cededd88acc12d0c8211f9c2481750f6e48e Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 20 Jul 2021 00:01:10 -0400 Subject: [PATCH 0960/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 85be49ecc7d..d9a67649b03 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210719) +set(CMake_VERSION_PATCH 20210720) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 144be54dd31ad1320e3efa9b2b30876dcadd590a Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 19 Jul 2021 16:28:23 -0400 Subject: [PATCH 0961/1519] try_compile: Propagate CMP0126 to the generated test project Set policy CMP0126 to the value used in the calling project. It may affect toolchain file behavior. --- Source/cmCoreTryCompile.cxx | 7 +++++++ Tests/RunCMake/ToolchainFile/CMP0126-NEW-stderr.txt | 1 + Tests/RunCMake/ToolchainFile/CMP0126-NEW-toolchain.cmake | 1 + Tests/RunCMake/ToolchainFile/CMP0126-NEW.cmake | 2 ++ Tests/RunCMake/ToolchainFile/CMP0126-OLD-stderr.txt | 1 + Tests/RunCMake/ToolchainFile/CMP0126-OLD-toolchain.cmake | 1 + Tests/RunCMake/ToolchainFile/CMP0126-OLD.cmake | 2 ++ Tests/RunCMake/ToolchainFile/CMP0126-WARN-stderr.txt | 1 + Tests/RunCMake/ToolchainFile/CMP0126-WARN-toolchain.cmake | 1 + Tests/RunCMake/ToolchainFile/CMP0126-WARN.cmake | 2 ++ Tests/RunCMake/ToolchainFile/CMP0126-toolchain.cmake | 7 +++++++ Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake | 3 +++ 12 files changed, 29 insertions(+) create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-NEW-stderr.txt create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-NEW-toolchain.cmake create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-NEW.cmake create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-OLD-stderr.txt create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-OLD-toolchain.cmake create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-OLD.cmake create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-WARN-stderr.txt create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-WARN-toolchain.cmake create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-WARN.cmake create mode 100644 Tests/RunCMake/ToolchainFile/CMP0126-toolchain.cmake diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 8ecf2648fc6..bf181433bd3 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -570,6 +570,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, *cmp0123 == "NEW"_s ? "NEW" : "OLD"); } + /* Set cache/normal variable policy to match outer project. + It may affect toolchain files. */ + if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) != + cmPolicies::NEW) { + fprintf(fout, "cmake_policy(SET CMP0126 OLD)\n"); + } + std::string projectLangs; for (std::string const& li : testLangs) { projectLangs += " " + li; diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-NEW-stderr.txt b/Tests/RunCMake/ToolchainFile/CMP0126-NEW-stderr.txt new file mode 100644 index 00000000000..7b91b43d82e --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-NEW-stderr.txt @@ -0,0 +1 @@ +^try_compile CMP0126='NEW' VAR='1' diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-NEW-toolchain.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-NEW-toolchain.cmake new file mode 100644 index 00000000000..2f1ec86c3b6 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-NEW-toolchain.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0126-toolchain.cmake") diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-NEW.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-NEW.cmake new file mode 100644 index 00000000000..62d4df1ef02 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0126 NEW) +enable_language(C) diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-OLD-stderr.txt b/Tests/RunCMake/ToolchainFile/CMP0126-OLD-stderr.txt new file mode 100644 index 00000000000..f3c068a1e06 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-OLD-stderr.txt @@ -0,0 +1 @@ +^try_compile CMP0126='OLD' VAR='2' diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-OLD-toolchain.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-OLD-toolchain.cmake new file mode 100644 index 00000000000..2f1ec86c3b6 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-OLD-toolchain.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0126-toolchain.cmake") diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-OLD.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-OLD.cmake new file mode 100644 index 00000000000..ef821fe9710 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0126 OLD) +enable_language(C) diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-WARN-stderr.txt b/Tests/RunCMake/ToolchainFile/CMP0126-WARN-stderr.txt new file mode 100644 index 00000000000..f3c068a1e06 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-WARN-stderr.txt @@ -0,0 +1 @@ +^try_compile CMP0126='OLD' VAR='2' diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-WARN-toolchain.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-WARN-toolchain.cmake new file mode 100644 index 00000000000..2f1ec86c3b6 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-WARN-toolchain.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0126-toolchain.cmake") diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-WARN.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-WARN.cmake new file mode 100644 index 00000000000..426e2b15ed2 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-WARN.cmake @@ -0,0 +1,2 @@ +# leave CMP0126 unset +enable_language(C) diff --git a/Tests/RunCMake/ToolchainFile/CMP0126-toolchain.cmake b/Tests/RunCMake/ToolchainFile/CMP0126-toolchain.cmake new file mode 100644 index 00000000000..d5af14f06f5 --- /dev/null +++ b/Tests/RunCMake/ToolchainFile/CMP0126-toolchain.cmake @@ -0,0 +1,7 @@ +get_property(_IN_TC GLOBAL PROPERTY IN_TRY_COMPILE) +if(_IN_TC) + cmake_policy(GET CMP0126 cmp0126) + set(VAR 1) + set(VAR 2 CACHE STRING "") + message("try_compile CMP0126='${cmp0126}' VAR='${VAR}'") +endif() diff --git a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake index 304c10525ab..7744ee850cb 100644 --- a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake +++ b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake @@ -11,6 +11,9 @@ run_cmake_toolchain(CheckLanguage) run_cmake_toolchain(FlagsInit) run_cmake_toolchain(LangVars) run_cmake_toolchain(LinkFlagsInit) +run_cmake_toolchain(CMP0126-NEW) +run_cmake_toolchain(CMP0126-OLD) +run_cmake_toolchain(CMP0126-WARN) function(run_IncludeDirectories) run_cmake_toolchain(IncludeDirectories) From 1c66012f8eafb136335278d2bbb63319a01bb093 Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti <lorenzo.cappelletti@gmail.com> Date: Mon, 19 Jul 2021 10:36:34 +0200 Subject: [PATCH 0962/1519] Compiler/IAR: search for both IAR's binaries * and *.exe IAR is available for both Linux and Windows OSes. Moreover, binaries `*.exe` could be called from a Linux box, or vice versa. See also commit 01a4eec446 (IAR: Changes required for Linux, 2019-04-25, v3.15.0-rc1~185^2). Fixes: #22312 --- Modules/Compiler/IAR-FindBinUtils.cmake | 32 ++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/Modules/Compiler/IAR-FindBinUtils.cmake b/Modules/Compiler/IAR-FindBinUtils.cmake index 6c67d347939..01f6d225905 100644 --- a/Modules/Compiler/IAR-FindBinUtils.cmake +++ b/Modules/Compiler/IAR-FindBinUtils.cmake @@ -20,19 +20,31 @@ if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "A string(TOLOWER "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" _archid_lower) # Find linker - find_program(CMAKE_IAR_LINKER ilink${_archid_lower} HINTS ${__iar_hints} + find_program(CMAKE_IAR_LINKER + NAMES ilink${_archid_lower} ilink${_archid_lower}.exe + HINTS ${__iar_hints} DOC "The IAR ILINK linker") - find_program(CMAKE_IAR_ARCHIVE iarchive HINTS ${__iar_hints} + find_program(CMAKE_IAR_ARCHIVE + NAMES iarchive iarchive.exe + HINTS ${__iar_hints} DOC "The IAR archiver") # Find utility tools - find_program(CMAKE_IAR_ELFTOOL ielftool HINTS ${__iar_hints} + find_program(CMAKE_IAR_ELFTOOL + NAMES ielftool ielftool.exe + HINTS ${__iar_hints} DOC "The IAR ELF Tool") - find_program(CMAKE_IAR_ELFDUMP ielfdump${_archid_lower} HINTS ${__iar_hints} + find_program(CMAKE_IAR_ELFDUMP + NAMES ielfdump${_archid_lower} ielfdump${_archid_lower}.exe + HINTS ${__iar_hints} DOC "The IAR ELF Dumper") - find_program(CMAKE_IAR_OBJMANIP iobjmanip HINTS ${__iar_hints} + find_program(CMAKE_IAR_OBJMANIP + NAMES iobjmanip iobjmanip.exe + HINTS ${__iar_hints} DOC "The IAR ELF Object Tool") - find_program(CMAKE_IAR_SYMEXPORT isymexport HINTS ${__iar_hints} + find_program(CMAKE_IAR_SYMEXPORT + NAMES isymexport + HINTS ${__iar_hints} DOC "The IAR Absolute Symbol Exporter") mark_as_advanced(CMAKE_IAR_LINKER CMAKE_IAR_ARCHIVE CMAKE_IAR_ELFTOOL CMAKE_IAR_ELFDUMP CMAKE_IAR_OBJMANIP CMAKE_IAR_SYMEXPORT) @@ -51,9 +63,13 @@ elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUA "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") # Find the "xlink" linker and "xar" archiver: - find_program(CMAKE_IAR_LINKER xlink HINTS ${__iar_hints} + find_program(CMAKE_IAR_LINKER + NAMES xlink xlink.exe + HINTS ${__iar_hints} DOC "The IAR XLINK linker") - find_program(CMAKE_IAR_AR xar HINTS ${__iar_hints} + find_program(CMAKE_IAR_AR + NAMES xar xar.exe + HINTS ${__iar_hints} DOC "The IAR archiver") mark_as_advanced(CMAKE_IAR_LINKER CMAKE_IAR_AR) From 05a3bafe650ae7f567c50abbdf626fca9ac2b3df Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti <lorenzo.cappelletti@gmail.com> Date: Mon, 19 Jul 2021 10:29:48 +0200 Subject: [PATCH 0963/1519] Compiler/IAR: Avoid clobbering CMAKE_EXECUTABLE_SUFFIX Use `CMAKE_EXECUTABLE_SUFFIX_<LANG>` instead. Fixes: #22426 --- Modules/Compiler/IAR.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index 8bfc3efe409..a6b436a117f 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -41,7 +41,7 @@ include_guard() macro(__compiler_iar_ilink lang) - set(CMAKE_EXECUTABLE_SUFFIX ".elf") + set(CMAKE_EXECUTABLE_SUFFIX_${lang} ".elf") set(CMAKE_${lang}_OUTPUT_EXTENSION ".o") if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX") set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") @@ -77,7 +77,7 @@ macro(__compiler_iar_ilink lang) endmacro() macro(__compiler_iar_xlink lang) - set(CMAKE_EXECUTABLE_SUFFIX ".bin") + set(CMAKE_EXECUTABLE_SUFFIX_${lang} ".bin") if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX") set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") From 09bc0785eeae95e23f9ac5c2e945fa89cb994912 Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti <lorenzo.cappelletti@gmail.com> Date: Mon, 19 Jul 2021 10:31:41 +0200 Subject: [PATCH 0964/1519] Help: Document CMAKE_EXECUTABLE_SUFFIX_<LANG> explicitly Documentation for `CMAKE_EXECUTABLE_SUFFIX_<LANG>`, useful when cross-compiling, is buried in section `CMAKE_EXECUTABLE_SUFFIX`. --- Help/manual/cmake-variables.7.rst | 1 + Help/variable/CMAKE_EXECUTABLE_SUFFIX.rst | 3 ++- Help/variable/CMAKE_EXECUTABLE_SUFFIX_LANG.rst | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 Help/variable/CMAKE_EXECUTABLE_SUFFIX_LANG.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 39fbbed39fc..9cea0fbc138 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -53,6 +53,7 @@ Variables that Provide Information /variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION /variable/CMAKE_EDIT_COMMAND /variable/CMAKE_EXECUTABLE_SUFFIX + /variable/CMAKE_EXECUTABLE_SUFFIX_LANG /variable/CMAKE_EXTRA_GENERATOR /variable/CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES /variable/CMAKE_FIND_DEBUG_MODE diff --git a/Help/variable/CMAKE_EXECUTABLE_SUFFIX.rst b/Help/variable/CMAKE_EXECUTABLE_SUFFIX.rst index 356590f6fba..bc4b9df4774 100644 --- a/Help/variable/CMAKE_EXECUTABLE_SUFFIX.rst +++ b/Help/variable/CMAKE_EXECUTABLE_SUFFIX.rst @@ -6,4 +6,5 @@ The suffix for executables on this platform. The suffix to use for the end of an executable filename if any, ``.exe`` on Windows. -``CMAKE_EXECUTABLE_SUFFIX_<LANG>`` overrides this for language ``<LANG>``. +:variable:`CMAKE_EXECUTABLE_SUFFIX_<LANG>` overrides this for +language ``<LANG>``. diff --git a/Help/variable/CMAKE_EXECUTABLE_SUFFIX_LANG.rst b/Help/variable/CMAKE_EXECUTABLE_SUFFIX_LANG.rst new file mode 100644 index 00000000000..a68150ebde6 --- /dev/null +++ b/Help/variable/CMAKE_EXECUTABLE_SUFFIX_LANG.rst @@ -0,0 +1,7 @@ +CMAKE_EXECUTABLE_SUFFIX_<LANG> +------------------------------ + +The suffix to use for the end of an executable filename of ``<LANG>`` +compiler target architecture, if any. + +It overrides :variable:`CMAKE_EXECUTABLE_SUFFIX` for language ``<LANG>``. From d777ca12f60f5da31b59f34605c5eb9f1608756e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 20 Jul 2021 12:11:47 -0400 Subject: [PATCH 0965/1519] CMakeDependentOption: Revert "Allow parentheses in the depends string" Revert commit 0665d9092e (CMakeDependentOption: Allow parentheses in the depends string, 2021-06-13, v3.21.0-rc1~32^2). It broke existing use cases with parentheses in regular expressions. Also add a test for this. Fixes: #22447 --- Modules/CMakeDependentOption.cmake | 5 +---- Tests/RunCMake/CMakeDependentOption/Parentheses.cmake | 7 ------- .../{Parentheses-stdout.txt => Regex-stdout.txt} | 0 Tests/RunCMake/CMakeDependentOption/Regex.cmake | 5 +++++ Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake | 2 +- 5 files changed, 7 insertions(+), 12 deletions(-) delete mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses.cmake rename Tests/RunCMake/CMakeDependentOption/{Parentheses-stdout.txt => Regex-stdout.txt} (100%) create mode 100644 Tests/RunCMake/CMakeDependentOption/Regex.cmake diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index 0a291f24fb4..96855d28f1c 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -42,10 +42,7 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force) if(${option}_ISSET MATCHES "^${option}_ISSET$") set(${option}_AVAILABLE 1) foreach(d ${depends}) - string(REPLACE "(" " ( " _CMAKE_CDO_DEP "${d}") - string(REPLACE ")" " ) " _CMAKE_CDO_DEP "${_CMAKE_CDO_DEP}") - string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${_CMAKE_CDO_DEP}") - unset(_CMAKE_CDO_DEP) + string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") if(${CMAKE_DEPENDENT_OPTION_DEP}) else() set(${option}_AVAILABLE 0) diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake deleted file mode 100644 index c2951f1dcbf..00000000000 --- a/Tests/RunCMake/CMakeDependentOption/Parentheses.cmake +++ /dev/null @@ -1,7 +0,0 @@ -include(CMakeDependentOption) - -set(A 1) -set(B 1) -set(C 0) -cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) -message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt similarity index 100% rename from Tests/RunCMake/CMakeDependentOption/Parentheses-stdout.txt rename to Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt diff --git a/Tests/RunCMake/CMakeDependentOption/Regex.cmake b/Tests/RunCMake/CMakeDependentOption/Regex.cmake new file mode 100644 index 00000000000..8342a01b7de --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex.cmake @@ -0,0 +1,5 @@ +include(CMakeDependentOption) + +set(FOO "lower") +cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES (UPPER|lower)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake index bbdd3e58869..e1045f2317d 100644 --- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake @@ -1,3 +1,3 @@ include(RunCMake) -run_cmake_script(Parentheses) +run_cmake_script(Regex) From c7a8c9c811678bc7ccfbbfe5013d697ce95fc605 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 20 Jul 2021 12:56:29 -0400 Subject: [PATCH 0966/1519] cmMessenger: Revert to non-color messages on Windows Since commit 0a0a0f8a74 (cmMessenger: Color messages to terminal by type, 2021-05-18, v3.21.0-rc1~146^2) the message output no longer goes through our custom streambuf on Windows that converts output encoding. This can cause messages to be printed with the wrong encoding in a Windows Console. It also causes messages to have a mix of LF and CRLF newlines because `stderr` converts LF to CRLF but our custom streambuf does not. Revert to using just `cerr` for messages on Windows. Another approach will be needed to achieve color output on Windows later. Fixes: #22444 --- Source/cmakemain.cxx | 11 +++++++++++ Tests/RunCMake/message/RunCMakeTest.cmake | 2 ++ Tests/RunCMake/message/newline-script.cmake | 2 ++ Tests/RunCMake/message/newline-stdout.txt | 2 ++ Tests/RunCMake/message/newline.cmake | 9 +++++++++ 5 files changed, 26 insertions(+) create mode 100644 Tests/RunCMake/message/newline-script.cmake create mode 100644 Tests/RunCMake/message/newline-stdout.txt create mode 100644 Tests/RunCMake/message/newline.cmake diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 1725375d95a..64d93df7fc7 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -153,9 +153,20 @@ std::string cmakemainGetStack(cmake* cm) void cmakemainMessageCallback(const std::string& m, const cmMessageMetadata& md, cmake* cm) { +#if defined(_WIN32) + // FIXME: On Windows we replace cerr's streambuf with a custom + // implementation that converts our internal UTF-8 encoding to the + // console's encoding. It also does *not* replace LF with CRLF. + // Since stderr does not convert encoding and does convert LF, we + // cannot use it to print messages. Another implementation will + // be needed to print colored messages on Windows. + static_cast<void>(md); + std::cerr << m << cmakemainGetStack(cm) << "\n"; +#else cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str()); fflush(stderr); // stderr is buffered in some cases. std::cerr << cmakemainGetStack(cm) << "\n"; +#endif } void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm) diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake index 0313ed1b132..1233838a525 100644 --- a/Tests/RunCMake/message/RunCMakeTest.cmake +++ b/Tests/RunCMake/message/RunCMakeTest.cmake @@ -1,5 +1,7 @@ include(RunCMake) +run_cmake_script(newline) + run_cmake(defaultmessage) run_cmake(nomessage) run_cmake(message-internal-warning) diff --git a/Tests/RunCMake/message/newline-script.cmake b/Tests/RunCMake/message/newline-script.cmake new file mode 100644 index 00000000000..e9e3d5d3e8f --- /dev/null +++ b/Tests/RunCMake/message/newline-script.cmake @@ -0,0 +1,2 @@ +message(STATUS "one\ntwo") +message("one\ntwo") diff --git a/Tests/RunCMake/message/newline-stdout.txt b/Tests/RunCMake/message/newline-stdout.txt new file mode 100644 index 00000000000..beca44e9acf --- /dev/null +++ b/Tests/RunCMake/message/newline-stdout.txt @@ -0,0 +1,2 @@ +-- out='2d2d206f6e650a74776f0a' +-- err='6f6e650a74776f0a' diff --git a/Tests/RunCMake/message/newline.cmake b/Tests/RunCMake/message/newline.cmake new file mode 100644 index 00000000000..97afba479c5 --- /dev/null +++ b/Tests/RunCMake/message/newline.cmake @@ -0,0 +1,9 @@ +execute_process( + COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/newline-script.cmake" + OUTPUT_FILE newline-script-stdout.txt + ERROR_FILE newline-script-stderr.txt + ) +foreach(f out err) + file(READ newline-script-std${f}.txt hex HEX) + message(STATUS "${f}='${hex}'") +endforeach() From 83c82722808eb3f6c38b9069c95960378446afbb Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 20 Jul 2021 14:50:13 -0400 Subject: [PATCH 0967/1519] cmGeneratorExpressionNode: Factor out local variable for global generator --- Source/cmGeneratorExpressionNode.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index c608bf940d0..6ace49d3ca4 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1635,10 +1635,11 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode reportError(context, content->GetOriginalExpression(), e.str()); return std::string(); } - if (!context->EvaluateForBuildsystem) { - cmGlobalGenerator* gg = context->LG->GetGlobalGenerator(); + cmGlobalGenerator* gg = context->LG->GetGlobalGenerator(); + { std::string reason; - if (!gg->HasKnownObjectFileLocation(&reason)) { + if (!context->EvaluateForBuildsystem && + !gg->HasKnownObjectFileLocation(&reason)) { std::ostringstream e; e << "The evaluation of the TARGET_OBJECTS generator expression " "is only suitable for consumption by CMake (limited" From dee0b88e770282909716967b9d3f4e626827e4ae Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 21 Jul 2021 00:01:11 -0400 Subject: [PATCH 0968/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d9a67649b03..725b1242719 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210720) +set(CMake_VERSION_PATCH 20210721) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 39a18aad07fed4bc62b0fe7fc5b151631722d466 Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits <fgerlits@gmail.com> Date: Wed, 21 Jul 2021 11:11:36 +0200 Subject: [PATCH 0969/1519] FindPatch: Fix typo in find_program call There is no `NAME` option. It should be `NAMES`. The call worked with `NAME` only due to old `find_program` signature compatibility. After this, the `find_program` call works even with PATHS removed (on non-Windows systems where this PATHS is not needed). --- Modules/FindPatch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindPatch.cmake b/Modules/FindPatch.cmake index 41086517d9d..f4fe4a6149b 100644 --- a/Modules/FindPatch.cmake +++ b/Modules/FindPatch.cmake @@ -43,7 +43,7 @@ endif() # First search the PATH find_program(Patch_EXECUTABLE - NAME patch + NAMES patch PATHS ${_patch_path} DOC ${_doc} ) From 078ba4b2a47bee6575497b29c98fbbc4dc7d4dc8 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 21 Jul 2021 10:44:15 -0400 Subject: [PATCH 0970/1519] Swift: Update test case to try CMP0126 NEW behavior Extend the `SwiftOnly` test to cover the fix in commit 3ddd7f3576 (enable_language: Fix test for working compiler with CMP0126 NEW behavior, 2021-07-15), as that commit did for the `CSharpOnly` test. Fixes: #22451 --- Tests/SwiftOnly/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt index 41d14eae88e..01c2222dc14 100644 --- a/Tests/SwiftOnly/CMakeLists.txt +++ b/Tests/SwiftOnly/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.3) +if(POLICY CMP0126) + cmake_policy(SET CMP0126 NEW) +endif() # NOTE: Force the Release mode configuration as there are some issues with the # debug information handling on macOS on certain Xcode builds. From cb777dd81e71746fcd324dc157d1b41f3ae3ce24 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 20 Jul 2021 14:51:06 -0400 Subject: [PATCH 0971/1519] Ninja Multi-Config: Restore TARGET_OBJECTS support in cross-configs Since commit 2ae72ef74b (Xcode: Enable multi-arch TARGET_OBJECTS genex in [INTERFACE_]LINK_LIBRARIES, 2021-05-26, v3.21.0-rc1~126^2) the TARGET_OBJECTS genex, when referenced for linking, is now evaluated with EvaluateForBuildsystem enabled. This causes the object file paths to be computed with a buildsystem-specific placeholder for the configuration. This is normally fine because the placeholder will be evaluated by the native buildsystem tool using the proper configuration. However, the Ninja Multi-Config generator's `${CONFIGURATION}` placeholder may not have the correct value for cross-config object files. Switch back to using the per-config location of each object file for this generator. Fixes: #22436 --- Source/cmGeneratorExpressionNode.cxx | 2 +- .../NinjaMultiConfig/RunCMakeTest.cmake | 2 + ...-in-release-graph-target-ninja-check.cmake | 37 +++++++++++++++++++ Tests/RunCMake/NinjaMultiConfig/Simple.cmake | 2 +- .../SimpleSubdir/CMakeLists.txt | 9 ++++- Tests/RunCMake/NinjaMultiConfig/empty_dbg.c | 0 Tests/RunCMake/NinjaMultiConfig/empty_rel.c | 0 .../ObjectLibrary/OwnSources-stderr.txt | 16 +------- 8 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake create mode 100644 Tests/RunCMake/NinjaMultiConfig/empty_dbg.c create mode 100644 Tests/RunCMake/NinjaMultiConfig/empty_rel.c diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 6ace49d3ca4..217ebe5f9dc 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1665,7 +1665,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode gt->GetTargetObjectNames(context->Config, objects); std::string obj_dir; - if (context->EvaluateForBuildsystem) { + if (context->EvaluateForBuildsystem && !gg->SupportsCrossConfigs()) { // Use object file directory with buildsystem placeholder. obj_dir = gt->ObjectDirectory; context->HadContextSensitiveCondition = diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 559c8f79664..885ae13de82 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -100,6 +100,8 @@ run_ninja(Simple release-file build-Release.ninja ${simpleexe_Release}) run_cmake_build(Simple all-configs Release simplestatic:all) run_ninja(Simple default-build-file build.ninja simpleexe) run_cmake_build(Simple all-clean Release clean:all) +run_ninja(Simple debug-in-release-graph-target build-Release.ninja simpleexe2:Debug) +run_cmake_build(Simple all-clean Release clean:all) run_cmake_build(Simple debug-subdir Debug SimpleSubdir/all) run_ninja(Simple release-in-minsizerel-graph-subdir build-MinSizeRel.ninja SimpleSubdir/all:Release) run_cmake_build(Simple all-subdir Release SimpleSubdir/all:all) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake new file mode 100644 index 00000000000..2f81bc0533e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake @@ -0,0 +1,37 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_FILE_simpleexe_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple.cmake index 3f4ecbed24e..e2d393b6fbd 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple.cmake @@ -10,6 +10,6 @@ add_subdirectory(SimpleSubdir) add_library(simplestatic STATIC simplelib.c) include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) -generate_output_files(simpleexe simpleshared simplestatic simpleobj) +generate_output_files(simpleexe simpleexe2 simpleshared simplestatic simpleobj) file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/empty.cmake]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt index 7e754a3b3e3..0ca6d023689 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt @@ -1,4 +1,9 @@ -add_library(simpleobj OBJECT ../empty.c) -add_executable(simpleexe ../main.c $<TARGET_OBJECTS:simpleobj>) +add_library(simpleobj OBJECT ../empty.c "$<$<CONFIG:Debug>:../empty_dbg.c>" "$<$<CONFIG:Release>:../empty_rel.c>") add_library(simpleshared SHARED ../simplelib.c) + +add_executable(simpleexe ../main.c $<TARGET_OBJECTS:simpleobj>) target_link_libraries(simpleexe PRIVATE simpleshared) + +add_executable(simpleexe2 ../main.c) +target_link_libraries(simpleexe2 PRIVATE simpleshared $<TARGET_OBJECTS:simpleobj>) +set_property(TARGET simpleexe2 PROPERTY EXCLUDE_FROM_ALL 1) diff --git a/Tests/RunCMake/NinjaMultiConfig/empty_dbg.c b/Tests/RunCMake/NinjaMultiConfig/empty_dbg.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/NinjaMultiConfig/empty_rel.c b/Tests/RunCMake/NinjaMultiConfig/empty_rel.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt index 69230b63f9d..5c27b8af32f 100644 --- a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt @@ -1,19 +1,7 @@ -^CMake Error at OwnSources.cmake:[0-9]+ \(add_library\): +^(CMake Error at OwnSources.cmake:[0-9]+ \(add_library\): The SOURCES of "A" use a generator expression that depends on the SOURCES themselves. Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) -+ -CMake Error at OwnSources.cmake:[0-9]+ \(add_library\): - The SOURCES of "A" use a generator expression that depends on the SOURCES - themselves. -Call Stack \(most recent call first\): - CMakeLists.txt:[0-9]+ \(include\) -+ -CMake Error at OwnSources.cmake:[0-9]+ \(add_library\): - The SOURCES of "A" use a generator expression that depends on the SOURCES - themselves. -Call Stack \(most recent call first\): - CMakeLists.txt:[0-9]+ \(include\) -+ ++)+ CMake Generate step failed\. Build files cannot be regenerated correctly\.$ From d61bc4241d02b32f4a39abe722a9af064af3a7da Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Wed, 21 Jul 2021 20:23:30 +0300 Subject: [PATCH 0972/1519] GNU: Correct C23 flags Non-final forms aren't supported yet, unlike C++23. Seems I might've gotten confused due to that when I added these. Fixes #22453. --- Modules/Compiler/GNU-C.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 39e9c72c442..03e8d2b06df 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -42,8 +42,8 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1) endif() if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9.1) - set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c23") - set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu23") + set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x") + set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x") endif() __compiler_check_default_language_standard(C 3.4 90 5.0 11 8.1 17) From 26a76cf46d5209aec03d941fee203d23172dde75 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 22 Jul 2021 00:01:11 -0400 Subject: [PATCH 0973/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 725b1242719..07d9d413950 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210721) +set(CMake_VERSION_PATCH 20210722) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 55e4753bbb60c0da12b09837bac97a46b851ae32 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin <eugene.shalygin@gmail.com> Date: Tue, 20 Jul 2021 20:08:17 +0200 Subject: [PATCH 0974/1519] Refactor cmTargetExport removing InterfaceIncludeDirecories Because of this property in the cmTargetExport struct, exporting targets is not uniform: top-level ones have to be dealt with via the cmTargetExport objects, while all linked ones are cmGeneratorTarget objects. Let's pass this additional includedirectories via a special target property making handling exported targets uniform. --- Source/cmExportFileGenerator.cxx | 3 ++- Source/cmInstallCommand.cxx | 5 +++-- Source/cmTarget.cxx | 12 ++++++++++++ Source/cmTarget.h | 3 +++ Source/cmTargetExport.h | 1 - 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index c69d484486f..2c54077dc87 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -378,7 +378,8 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( cmGeneratorExpression ge; std::string dirs = cmGeneratorExpression::Preprocess( - tei->InterfaceIncludeDirectories, preprocessRule, true); + cmJoin(target->Target->GetInstallIncludeDirectoriesEntries(), ";"), + preprocessRule, true); this->ReplaceInstallPrefix(dirs); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs); std::string exportDirs = diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 79109b50820..687741b3dae 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -36,6 +36,7 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmProperty.h" +#include "cmRange.h" #include "cmRuntimeDependencyArchive.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -681,8 +682,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, te->LibraryGenerator = libraryGenerator.get(); te->RuntimeGenerator = runtimeGenerator.get(); te->ObjectsGenerator = objectGenerator.get(); - te->InterfaceIncludeDirectories = - cmJoin(includesArgs.GetIncludeDirs(), ";"); + target.AddInstallIncludeDirectories( + cmMakeRange(includesArgs.GetIncludeDirs())); te->NamelinkOnly = namelinkOnly; helper.Makefile->GetGlobalGenerator() ->GetExportSets()[exports] diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 76227005157..70e11a2d016 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -189,6 +189,7 @@ class cmTargetInternals std::map<std::string, BTs<std::string>> LanguageStandardProperties; std::vector<std::string> IncludeDirectoriesEntries; std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces; + std::vector<std::string> InstallIncludeDirectoriesEntries; std::vector<std::string> CompileOptionsEntries; std::vector<cmListFileBacktrace> CompileOptionsBacktraces; std::vector<std::string> CompileFeaturesEntries; @@ -1075,6 +1076,17 @@ std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const return this->impl->SystemIncludeDirectories; } +void cmTarget::AddInstallIncludeDirectories(cmStringRange const& incs) +{ + std::copy(incs.begin(), incs.end(), + std::back_inserter(this->impl->InstallIncludeDirectoriesEntries)); +} + +cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries() const +{ + return cmMakeRange(this->impl->InstallIncludeDirectoriesEntries); +} + cmStringRange cmTarget::GetIncludeDirectoriesEntries() const { return cmMakeRange(this->impl->IncludeDirectoriesEntries); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 30d9f5d067b..29130c7bf39 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -237,6 +237,9 @@ class cmTarget void AddSystemIncludeDirectories(std::set<std::string> const& incs); std::set<std::string> const& GetSystemIncludeDirectories() const; + void AddInstallIncludeDirectories(cmStringRange const& incs); + cmStringRange GetInstallIncludeDirectoriesEntries() const; + BTs<std::string> const* GetLanguageStandardProperty( const std::string& propertyName) const; diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index 1e38d84923e..19fc9319ae6 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -29,7 +29,6 @@ class cmTargetExport cmInstallTargetGenerator* FrameworkGenerator; cmInstallTargetGenerator* BundleGenerator; cmInstallFilesGenerator* HeaderGenerator; - std::string InterfaceIncludeDirectories; ///@} bool NamelinkOnly = false; From e8e19ed8f2f0d05bb7fc7e5987809a3754ad4f74 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin <eugene.shalygin@gmail.com> Date: Tue, 20 Jul 2021 21:41:36 +0200 Subject: [PATCH 0975/1519] Refactor export file generator inteface Replace cmTargetExport with const cmGeneratorTarget to allow recursive processing of exported targets and their link dependencies. --- Source/cmExportBuildFileGenerator.cxx | 6 +-- Source/cmExportBuildFileGenerator.h | 8 ++-- Source/cmExportFileGenerator.cxx | 43 +++++++++++----------- Source/cmExportFileGenerator.h | 37 +++++++++---------- Source/cmExportInstallFileGenerator.cxx | 14 +++---- Source/cmExportInstallFileGenerator.h | 8 ++-- Source/cmExportTryCompileFileGenerator.cxx | 2 +- Source/cmExportTryCompileFileGenerator.h | 5 ++- 8 files changed, 61 insertions(+), 62 deletions(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 1a31ae4afd3..4a9bf28dabb 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -254,7 +254,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( void cmExportBuildFileGenerator::HandleMissingTarget( std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget* depender, cmGeneratorTarget* dependee) + cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) { // The target is not in the export. if (!this->AppendMode) { @@ -321,7 +321,7 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg, } void cmExportBuildFileGenerator::ComplainAboutMissingTarget( - cmGeneratorTarget* depender, cmGeneratorTarget* dependee, + cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee, std::vector<std::string> const& exportFiles) { std::ostringstream e; @@ -344,7 +344,7 @@ void cmExportBuildFileGenerator::ComplainAboutMissingTarget( } std::string cmExportBuildFileGenerator::InstallNameDir( - cmGeneratorTarget* target, const std::string& config) + cmGeneratorTarget const* target, const std::string& config) { std::string install_name_dir; diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 264494dc5a4..244f526db1d 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -60,11 +60,11 @@ class cmExportBuildFileGenerator : public cmExportFileGenerator cmGeneratorTarget const* target) const; void HandleMissingTarget(std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget* depender, + cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) override; - void ComplainAboutMissingTarget(cmGeneratorTarget* depender, - cmGeneratorTarget* dependee, + void ComplainAboutMissingTarget(cmGeneratorTarget const* depender, + cmGeneratorTarget const* dependee, std::vector<std::string> const& namespaces); /** Fill in properties indicating built file locations. */ @@ -73,7 +73,7 @@ class cmExportBuildFileGenerator : public cmExportFileGenerator cmGeneratorTarget* target, ImportPropertyMap& properties); - std::string InstallNameDir(cmGeneratorTarget* target, + std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) override; std::pair<std::vector<std::string>, std::string> FindBuildExportInfo( diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 2c54077dc87..ebdbe38f57e 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -27,7 +27,6 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmTargetExport.h" static std::string cmExportFileGeneratorEscape(std::string const& str) { @@ -123,7 +122,7 @@ void cmExportFileGenerator::GenerateImportConfig( } void cmExportFileGenerator::PopulateInterfaceProperty( - const std::string& propName, cmGeneratorTarget* target, + const std::string& propName, cmGeneratorTarget const* target, ImportPropertyMap& properties) { cmProp input = target->GetProperty(propName); @@ -134,7 +133,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty( void cmExportFileGenerator::PopulateInterfaceProperty( const std::string& propName, const std::string& outputName, - cmGeneratorTarget* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { @@ -168,7 +167,7 @@ void cmExportFileGenerator::GenerateRequiredCMakeVersion( } bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty( - cmGeneratorTarget* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { @@ -196,7 +195,7 @@ static bool isSubDirectory(std::string const& a, std::string const& b) } static bool checkInterfaceDirs(const std::string& prepro, - cmGeneratorTarget* target, + cmGeneratorTarget const* target, const std::string& prop) { std::string const& installDir = @@ -335,10 +334,10 @@ static void prefixItems(std::string& exportDirs) } void cmExportFileGenerator::PopulateSourcesInterface( - cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + cmGeneratorTarget const* gt, + cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { - cmGeneratorTarget* gt = tei->Target; assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_SOURCES"; @@ -366,10 +365,10 @@ void cmExportFileGenerator::PopulateSourcesInterface( } void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( - cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + cmGeneratorTarget const* target, + cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { - cmGeneratorTarget* target = tei->Target; assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_INCLUDE_DIRECTORIES"; @@ -425,10 +424,10 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( } void cmExportFileGenerator::PopulateLinkDependsInterface( - cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + cmGeneratorTarget const* gt, + cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { - cmGeneratorTarget* gt = tei->Target; assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_LINK_DEPENDS"; @@ -456,10 +455,10 @@ void cmExportFileGenerator::PopulateLinkDependsInterface( } void cmExportFileGenerator::PopulateLinkDirectoriesInterface( - cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + cmGeneratorTarget const* gt, + cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { - cmGeneratorTarget* gt = tei->Target; assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_LINK_DIRECTORIES"; @@ -487,7 +486,7 @@ void cmExportFileGenerator::PopulateLinkDirectoriesInterface( } void cmExportFileGenerator::PopulateInterfaceProperty( - const std::string& propName, cmGeneratorTarget* target, + const std::string& propName, cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { @@ -506,7 +505,7 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop, ifaceProperties.insert(content.begin(), content.end()); } -void getCompatibleInterfaceProperties(cmGeneratorTarget* target, +void getCompatibleInterfaceProperties(cmGeneratorTarget const* target, std::set<std::string>& ifaceProperties, const std::string& config) { @@ -545,7 +544,7 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target, } void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( - cmGeneratorTarget* gtarget, ImportPropertyMap& properties) + cmGeneratorTarget const* gtarget, ImportPropertyMap& properties) { this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget, properties); @@ -597,7 +596,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties( } bool cmExportFileGenerator::AddTargetNamespace( - std::string& input, cmGeneratorTarget* target, + std::string& input, cmGeneratorTarget const* target, std::vector<std::string>& missingTargets) { cmGeneratorTarget::TargetOrString resolved = @@ -628,7 +627,7 @@ bool cmExportFileGenerator::AddTargetNamespace( } void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( - std::string& input, cmGeneratorTarget* target, + std::string& input, cmGeneratorTarget const* target, std::vector<std::string>& missingTargets, FreeTargetsReplace replace) { if (replace == NoReplaceFreeTargets) { @@ -655,7 +654,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( } void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( - std::string& input, cmGeneratorTarget* target, + std::string& input, cmGeneratorTarget const* target, std::vector<std::string>& missingTargets) { std::string::size_type pos = 0; @@ -745,7 +744,7 @@ void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/) void cmExportFileGenerator::SetImportLinkInterface( const std::string& config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, - cmGeneratorTarget* target, ImportPropertyMap& properties, + cmGeneratorTarget const* target, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { // Add the transitive link dependencies for this configuration. @@ -881,7 +880,7 @@ static std::string const& asString(cmLinkItem const& l) template <typename T> void cmExportFileGenerator::SetImportLinkProperty( - std::string const& suffix, cmGeneratorTarget* target, + std::string const& suffix, cmGeneratorTarget const* target, const std::string& propName, std::vector<T> const& entries, ImportPropertyMap& properties, std::vector<std::string>& missingTargets, ImportLinkPropertyTargetNames targetNames) @@ -1212,7 +1211,7 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode( } bool cmExportFileGenerator::PopulateExportProperties( - cmGeneratorTarget* gte, ImportPropertyMap& properties, + cmGeneratorTarget const* gte, ImportPropertyMap& properties, std::string& errorMessage) { const auto& targetProperties = gte->Target->GetProperties(); diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 45eaed04f67..24e048bca25 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -27,8 +27,6 @@ class cmGeneratorTarget; CMake_VERSION_MINOR) "." STRINGIFY(CMake_VERSION_PATCH) \ : #major "." #minor ".0") -class cmTargetExport; - /** \class cmExportFileGenerator * \brief Generate a file exporting targets from a build or install tree. * @@ -108,7 +106,7 @@ class cmExportFileGenerator }; template <typename T> void SetImportLinkProperty(std::string const& suffix, - cmGeneratorTarget* target, + cmGeneratorTarget const* target, const std::string& propName, std::vector<T> const& entries, ImportPropertyMap& properties, @@ -127,44 +125,45 @@ class cmExportFileGenerator * export set. */ virtual void HandleMissingTarget(std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget* depender, + cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) = 0; - void PopulateInterfaceProperty(const std::string&, cmGeneratorTarget* target, + void PopulateInterfaceProperty(const std::string&, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); bool PopulateInterfaceLinkLibrariesProperty( - cmGeneratorTarget* target, cmGeneratorExpression::PreprocessContext, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void PopulateInterfaceProperty(const std::string& propName, - cmGeneratorTarget* target, + cmGeneratorTarget const* target, ImportPropertyMap& properties); - void PopulateCompatibleInterfaceProperties(cmGeneratorTarget* target, + void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target, ImportPropertyMap& properties); virtual void GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, const ImportPropertyMap& properties); void PopulateIncludeDirectoriesInterface( - cmTargetExport* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void PopulateSourcesInterface( - cmTargetExport* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void PopulateLinkDirectoriesInterface( - cmTargetExport* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void PopulateLinkDependsInterface( - cmTargetExport* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void SetImportLinkInterface( const std::string& config, std::string const& suffix, cmGeneratorExpression::PreprocessContext preprocessRule, - cmGeneratorTarget* target, ImportPropertyMap& properties, + cmGeneratorTarget const* target, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); enum FreeTargetsReplace @@ -174,14 +173,14 @@ class cmExportFileGenerator }; void ResolveTargetsInGeneratorExpressions( - std::string& input, cmGeneratorTarget* target, + std::string& input, cmGeneratorTarget const* target, std::vector<std::string>& missingTargets, FreeTargetsReplace replace = NoReplaceFreeTargets); virtual void GenerateRequiredCMakeVersion(std::ostream& os, const char* versionString); - bool PopulateExportProperties(cmGeneratorTarget* gte, + bool PopulateExportProperties(cmGeneratorTarget const* gte, ImportPropertyMap& properties, std::string& errorMessage); @@ -205,20 +204,20 @@ class cmExportFileGenerator private: void PopulateInterfaceProperty(const std::string&, const std::string&, - cmGeneratorTarget* target, + cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); - bool AddTargetNamespace(std::string& input, cmGeneratorTarget* target, + bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target, std::vector<std::string>& missingTargets); void ResolveTargetsInGeneratorExpression( - std::string& input, cmGeneratorTarget* target, + std::string& input, cmGeneratorTarget const* target, std::vector<std::string>& missingTargets); virtual void ReplaceInstallPrefix(std::string& input); - virtual std::string InstallNameDir(cmGeneratorTarget* target, + virtual std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) = 0; }; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 3c69c50018f..4249cfe2dbf 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -85,8 +85,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) ImportPropertyMap properties; this->PopulateIncludeDirectoriesInterface( - te, cmGeneratorExpression::InstallInterface, properties, missingTargets); - this->PopulateSourcesInterface(te, cmGeneratorExpression::InstallInterface, + gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt, cmGeneratorExpression::InstallInterface, @@ -110,9 +110,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) cmGeneratorExpression::InstallInterface, properties, missingTargets); this->PopulateLinkDirectoriesInterface( - te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); this->PopulateLinkDependsInterface( - te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); std::string errorMessage; if (!this->PopulateExportProperties(gt, properties, errorMessage)) { @@ -447,7 +447,7 @@ cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType( void cmExportInstallFileGenerator::HandleMissingTarget( std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget* depender, cmGeneratorTarget* dependee) + cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) { const std::string name = dependee->GetName(); cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator(); @@ -499,7 +499,7 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg, } void cmExportInstallFileGenerator::ComplainAboutMissingTarget( - cmGeneratorTarget* depender, cmGeneratorTarget* dependee, + cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee, std::vector<std::string> const& exportFiles) { std::ostringstream e; @@ -521,7 +521,7 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget( } std::string cmExportInstallFileGenerator::InstallNameDir( - cmGeneratorTarget* target, const std::string& config) + cmGeneratorTarget const* target, const std::string& config) { std::string install_name_dir; diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 2d8de9d83e6..5cec2e05ece 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -63,13 +63,13 @@ class cmExportInstallFileGenerator : public cmExportFileGenerator cmTargetExport const* targetExport) const; void HandleMissingTarget(std::string& link_libs, std::vector<std::string>& missingTargets, - cmGeneratorTarget* depender, + cmGeneratorTarget const* depender, cmGeneratorTarget* dependee) override; void ReplaceInstallPrefix(std::string& input) override; - void ComplainAboutMissingTarget(cmGeneratorTarget* depender, - cmGeneratorTarget* dependee, + void ComplainAboutMissingTarget(cmGeneratorTarget const* depender, + cmGeneratorTarget const* dependee, std::vector<std::string> const& exportFiles); std::pair<std::vector<std::string>, std::string> FindNamespaces( @@ -94,7 +94,7 @@ class cmExportInstallFileGenerator : public cmExportFileGenerator ImportPropertyMap& properties, std::set<std::string>& importedLocations); - std::string InstallNameDir(cmGeneratorTarget* target, + std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) override; cmInstallExportGenerator* IEGen; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index cac60e14a85..f89d0ada483 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -126,7 +126,7 @@ void cmExportTryCompileFileGenerator::PopulateProperties( } std::string cmExportTryCompileFileGenerator::InstallNameDir( - cmGeneratorTarget* target, const std::string& config) + cmGeneratorTarget const* target, const std::string& config) { std::string install_name_dir; diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 6bf5781e88e..127b8df1516 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -36,7 +36,8 @@ class cmExportTryCompileFileGenerator : public cmExportFileGenerator { } void HandleMissingTarget(std::string&, std::vector<std::string>&, - cmGeneratorTarget*, cmGeneratorTarget*) override + cmGeneratorTarget const*, + cmGeneratorTarget*) override { } @@ -44,7 +45,7 @@ class cmExportTryCompileFileGenerator : public cmExportFileGenerator ImportPropertyMap& properties, std::set<const cmGeneratorTarget*>& emitted); - std::string InstallNameDir(cmGeneratorTarget* target, + std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) override; private: From 125bbf07b1725242fbd558579422c781506cb3d7 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Mon, 19 Jul 2021 15:49:43 -0400 Subject: [PATCH 0976/1519] CUDA: Extract nvvm libdevice location from compiler verbose output Depending on the CUDA installation the nvvm/libdevice folder can be in different locations. Since `nvcc` outputs the expected location use that when possible. --- Modules/CMakeDetermineCUDACompiler.cmake | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index e360d31271e..342425c50e1 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -192,17 +192,31 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY) get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY) endif() + + if(_CUDA_NVCC_OUT MATCHES "\\#\\$ NVVMIR_LIBRARY_DIR=([^\r\n]*)") + get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${CMAKE_MATCH_1}" ABSOLUTE) + + #We require the path to end in `/nvvm/libdevice' + if(_CUDA_NVVMIR_LIBRARY_DIR MATCHES "nvvm/libdevice$") + get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}/../.." ABSOLUTE) + set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}") + endif() + + unset(_CUDA_NVVMIR_LIBRARY_DIR) + unset(_cuda_nvvmir_dir_name) + endif() unset(_CUDA_NVCC_OUT) set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/nvlink${CMAKE_EXECUTABLE_SUFFIX}") set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/fatbinary${CMAKE_EXECUTABLE_SUFFIX}") - # In a non-scattered installation the following are equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT. # We first check for a non-scattered installation to prefer it over a scattered installation. # CMAKE_CUDA_COMPILER_LIBRARY_ROOT contains the device library. - if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvvm/libdevice") + if(DEFINED CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR) + set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR}") + elseif(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvvm/libdevice") set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/nvvm/libdevice") set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda") @@ -211,6 +225,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) else() message(FATAL_ERROR "Couldn't find CUDA library root.") endif() + unset(CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR) # CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT contains the linking stubs necessary for device linking and other low-level library files. if(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/nvidia-cuda-toolkit/bin/crt/link.stub") From f7a3031b7defbc805a39a8b23dbefe10764d956b Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 23 Jul 2021 00:01:08 -0400 Subject: [PATCH 0977/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 07d9d413950..8b4b1ab3b56 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210722) +set(CMake_VERSION_PATCH 20210723) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 5b9bfe738cfa96ca12ca82506f234aae787965e9 Mon Sep 17 00:00:00 2001 From: Jean-Marc Hengen <jean-marc.hengen@zuehlke.com> Date: Mon, 19 Jul 2021 23:14:29 +0200 Subject: [PATCH 0978/1519] IAR: Moved search logic to BinUtils. The search logic for the IAR linker, librarian and related tools is moved from `Modules/Compiler/IAR-FindBinUtils.cmake` to `Modules/CMakeFindBinUtils.cmake` by introducing an new elseif block for the IAR toolchain. The search logic was refactored to omit repeating itself. Fixes: #22425 --- Modules/CMakeFindBinUtils.cmake | 54 +++++++++++++++++ Modules/Compiler/IAR-FindBinUtils.cmake | 80 ------------------------- Modules/Compiler/IAR.cmake | 6 -- 3 files changed, 54 insertions(+), 86 deletions(-) delete mode 100644 Modules/Compiler/IAR-FindBinUtils.cmake diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 3162ec57fa7..f139ff48267 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -94,6 +94,53 @@ elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^x(Open)?W set(_CMAKE_AR_NAMES "wlib") list(APPEND _CMAKE_TOOL_VARS LINKER AR) +elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$") + # Small helper declaring an IAR tool (e.g. linker) to avoid repeating the same idiom every time + macro(__append_IAR_tool TOOL_VAR NAME) + set(_CMAKE_${TOOL_VAR}_NAMES "${NAME}" "${NAME}.exe") + list(APPEND _CMAKE_TOOL_VARS ${TOOL_VAR}) + endmacro() + + # Resolve hint path from an IAR compiler + function(__resolve_IAR_hints COMPILER RESULT) + get_filename_component(_CMAKE_IAR_HINT "${COMPILER}" REALPATH) + get_filename_component(_CMAKE_IAR_HINT "${_CMAKE_IAR_HINT}" DIRECTORY) + list(APPEND _IAR_HINTS "${_CMAKE_IAR_HINT}") + + get_filename_component(_CMAKE_IAR_HINT "${COMPILER}" DIRECTORY) + list(APPEND _IAR_HINTS "${_CMAKE_IAR_HINT}") + + set(${RESULT} "${_IAR_HINTS}" PARENT_SCOPE) + endfunction() + + __resolve_IAR_hints("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" _CMAKE_TOOLCHAIN_LOCATION) + set(_CMAKE_IAR_ITOOLS "ARM" "RX" "RH850" "RL78" "RISCV" "STM8") + set(_CMAKE_IAR_XTOOLS "AVR" "MSP430" "V850" "8051") + + if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS) + string(TOLOWER "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" _CMAKE_IAR_LOWER_ARCHITECTURE_ID) + + __append_IAR_tool(AR "iarchive") + __append_IAR_tool(LINKER "ilink${_CMAKE_IAR_LOWER_ARCHITECTURE_ID}") + + __append_IAR_tool(IAR_ELFDUMP "ielfdump${_CMAKE_IAR_LOWER_ARCHITECTURE_ID}") + __append_IAR_tool(IAR_ELFTOOL "ielftool") + __append_IAR_tool(IAR_OBJMANIP "iobjmanip") + __append_IAR_tool(IAR_SYMEXPORT "isymexport") + + unset(_CMAKE_IAR_LOWER_ARCHITECTURE_ID) + + elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_XTOOLS) + __append_IAR_tool(AR "xar") + __append_IAR_tool(LINKER "xlink") + + else() + message(FATAL_ERROR "Failed to find linker and librarian for ${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID} on ${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}.") + endif() + + unset(_CMAKE_IAR_ITOOLS) + unset(_CMAKE_IAR_XTOOLS) + # in all other cases search for ar, ranlib, etc. else() if(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN) @@ -186,3 +233,10 @@ unset(_CMAKE_TOOL_VARS) unset(_CMAKE_TOOL_CACHED) unset(_CMAKE_TOOL_NAME) unset(_CMAKE_TOOL) + +if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$") + # Set for backwards compatibility + set(CMAKE_IAR_ARCHIVE "${CMAKE_AR}" CACHE FILEPATH "The IAR archiver") + set(CMAKE_IAR_LINKER "${CMAKE_LINKER}" CACHE FILEPATH "The IAR ILINK linker") + mark_as_advanced(CMAKE_IAR_LINKER CMAKE_IAR_AR) +endif() diff --git a/Modules/Compiler/IAR-FindBinUtils.cmake b/Modules/Compiler/IAR-FindBinUtils.cmake deleted file mode 100644 index 01f6d225905..00000000000 --- a/Modules/Compiler/IAR-FindBinUtils.cmake +++ /dev/null @@ -1,80 +0,0 @@ -if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") - message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") -endif() - -# Try to find tools in the same directory as the compiler itself -get_filename_component(__iar_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" REALPATH) -get_filename_component(__iar_hint_1 "${__iar_hint_1}" DIRECTORY) - -get_filename_component(__iar_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) - -set(__iar_hints "${__iar_hint_1}" "${__iar_hint_2}") - -if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8") - - string(TOLOWER "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" _archid_lower) - - # Find linker - find_program(CMAKE_IAR_LINKER - NAMES ilink${_archid_lower} ilink${_archid_lower}.exe - HINTS ${__iar_hints} - DOC "The IAR ILINK linker") - find_program(CMAKE_IAR_ARCHIVE - NAMES iarchive iarchive.exe - HINTS ${__iar_hints} - DOC "The IAR archiver") - - # Find utility tools - find_program(CMAKE_IAR_ELFTOOL - NAMES ielftool ielftool.exe - HINTS ${__iar_hints} - DOC "The IAR ELF Tool") - find_program(CMAKE_IAR_ELFDUMP - NAMES ielfdump${_archid_lower} ielfdump${_archid_lower}.exe - HINTS ${__iar_hints} - DOC "The IAR ELF Dumper") - find_program(CMAKE_IAR_OBJMANIP - NAMES iobjmanip iobjmanip.exe - HINTS ${__iar_hints} - DOC "The IAR ELF Object Tool") - find_program(CMAKE_IAR_SYMEXPORT - NAMES isymexport - HINTS ${__iar_hints} - DOC "The IAR Absolute Symbol Exporter") - mark_as_advanced(CMAKE_IAR_LINKER CMAKE_IAR_ARCHIVE CMAKE_IAR_ELFTOOL CMAKE_IAR_ELFDUMP CMAKE_IAR_OBJMANIP CMAKE_IAR_SYMEXPORT) - - set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_CUSTOM_CODE -"set(CMAKE_IAR_LINKER \"${CMAKE_IAR_LINKER}\") -set(CMAKE_IAR_ARCHIVE \"${CMAKE_IAR_ARCHIVE}\") -set(CMAKE_IAR_ELFTOOL \"${CMAKE_IAR_ELFTOOL}\") -set(CMAKE_IAR_ELFDUMP \"${CMAKE_IAR_ELFDUMP}\") -set(CMAKE_IAR_OBJMANIP \"${CMAKE_IAR_OBJMANIP}\") -set(CMAKE_IAR_LINKER \"${CMAKE_IAR_LINKER}\") -") - -elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") - - # Find the "xlink" linker and "xar" archiver: - find_program(CMAKE_IAR_LINKER - NAMES xlink xlink.exe - HINTS ${__iar_hints} - DOC "The IAR XLINK linker") - find_program(CMAKE_IAR_AR - NAMES xar xar.exe - HINTS ${__iar_hints} - DOC "The IAR archiver") - mark_as_advanced(CMAKE_IAR_LINKER CMAKE_IAR_AR) - - set(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_CUSTOM_CODE -"set(CMAKE_IAR_LINKER \"${CMAKE_IAR_LINKER}\") -set(CMAKE_IAR_AR \"${CMAKE_IAR_AR}\") -") -endif() diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index a6b436a117f..2200a21a760 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -71,9 +71,6 @@ macro(__compiler_iar_ilink lang) set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> <TARGET> --replace <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_FINISH "") - - set(CMAKE_LINKER "${CMAKE_IAR_LINKER}" CACHE FILEPATH "The IAR linker" FORCE) - set(CMAKE_AR "${CMAKE_IAR_ARCHIVE}" CACHE FILEPATH "The IAR archiver" FORCE) endmacro() macro(__compiler_iar_xlink lang) @@ -109,7 +106,4 @@ macro(__compiler_iar_xlink lang) set(CMAKE_${lang}_ARCHIVE_FINISH "") set(CMAKE_LIBRARY_PATH_FLAG "-I") - - set(CMAKE_LINKER "${CMAKE_IAR_LINKER}" CACHE FILEPATH "The IAR linker" FORCE) - set(CMAKE_AR "${CMAKE_IAR_AR}" CACHE FILEPATH "The IAR archiver" FORCE) endmacro() From e5ec0e52f4f15f78bb973cdb03a61ef9c707c2fa Mon Sep 17 00:00:00 2001 From: Alexey Edelev <semlanik@gmail.com> Date: Thu, 22 Jul 2021 12:13:48 +0200 Subject: [PATCH 0979/1519] AUTOUIC: Fix generating of dependency rules for UI header files We could not rely on .ui files when generating the ninja rules for the generated UI header files. .ui files might be added to the target sources but never processed by AUTOUIC afterward, since UI header files are never included in a source code. Instead of adding dependency rules based on the .ui files, this approach scans non-generated source files for includes of the UI header files, as AUTOUIC does. This gives the consistent set of UI header files at configure time, that could be used to generate byproducts rules for the AUTOUIC. Also, the path to the generated UI header file depends not on the .ui file location but on the include line is used in source files. Fixes: #16776 --- Source/CMakeLists.txt | 2 + Source/cmQtAutoGen.cxx | 36 +++++++++++++ Source/cmQtAutoGen.h | 3 ++ Source/cmQtAutoGenInitializer.cxx | 53 ++++++++++--------- Source/cmQtAutoGenInitializer.h | 2 + Source/cmQtAutoGenerator.cxx | 37 ------------- Source/cmQtAutoGenerator.h | 2 - Source/cmQtAutoMocUic.cxx | 20 ++----- Source/cmQtAutoUicHelpers.cxx | 25 +++++++++ Source/cmQtAutoUicHelpers.h | 20 +++++++ .../RerunUicOnFileChange/CMakeLists.txt | 3 ++ .../UicOnFileChange/CMakeLists.txt.in | 4 +- .../UicOnFileChange/main.cpp | 4 +- .../subdir/mainwindowsubdir.ui.in | 7 +++ .../UicOnFileChange/subdir/subdircheck.cpp | 9 ++++ 15 files changed, 144 insertions(+), 83 deletions(-) create mode 100644 Source/cmQtAutoUicHelpers.cxx create mode 100644 Source/cmQtAutoUicHelpers.h create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9a18184fd3b..0142c07ecb3 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -432,6 +432,8 @@ set(SRCS cmQtAutoMocUic.h cmQtAutoRcc.cxx cmQtAutoRcc.h + cmQtAutoUicHelpers.cxx + cmQtAutoUicHelpers.h cmRST.cxx cmRST.h cmRuntimeDependencyArchive.cxx diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 57fcd2da768..898d862221f 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -384,3 +384,39 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, } return true; } + +bool cmQtAutoGen::FileRead(std::string& content, std::string const& filename, + std::string* error) +{ + content.clear(); + if (!cmSystemTools::FileExists(filename, true)) { + if (error != nullptr) { + *error = "Not a file."; + } + return false; + } + + unsigned long const length = cmSystemTools::FileLength(filename); + cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); + + // Use lambda to save destructor calls of ifs + return [&ifs, length, &content, error]() -> bool { + if (!ifs) { + if (error != nullptr) { + *error = "Opening the file for reading failed."; + } + return false; + } + content.reserve(length); + using IsIt = std::istreambuf_iterator<char>; + content.assign(IsIt{ ifs }, IsIt{}); + if (!ifs) { + content.clear(); + if (error != nullptr) { + *error = "Reading from the file failed."; + } + return false; + } + return true; + }(); +} diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 466a954a981..b9ae360291e 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -100,6 +100,9 @@ class cmQtAutoGen std::vector<std::string> const& newOpts, bool isQt5); + static bool FileRead(std::string& content, std::string const& filename, + std::string* error = nullptr); + /** @class RccLister * @brief Lists files in qrc resource files */ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 2894201c9b3..9d8086397ca 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -902,6 +902,13 @@ bool cmQtAutoGenInitializer::InitScanFiles() // The reason is that their file names might be discovered from source files // at generation time. if (this->MocOrUicEnabled()) { + std::set<std::string> uicIncludes; + auto collectUicIncludes = [&](std::unique_ptr<cmSourceFile> const& sf) { + std::string content; + FileRead(content, sf->GetFullPath()); + this->AutoUicHelpers.CollectUicIncludes(uicIncludes, content); + }; + for (const auto& sf : this->Makefile->GetSourceFiles()) { // sf->GetExtension() is only valid after sf->ResolveFullPath() ... // Since we're iterating over source files that might be not in the @@ -914,6 +921,10 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const& extLower = cmSystemTools::LowerCase(sf->GetExtension()); + bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); + bool const skipUic = + (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC) || + !this->Uic.Enabled); if (cm->IsAHeaderExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Headers, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, {}, false); @@ -921,6 +932,9 @@ bool cmQtAutoGenInitializer::InitScanFiles() addMUHeader(std::move(muf), extLower); } } + if (!skipUic && !sf->GetIsGenerated()) { + collectUicIncludes(sf); + } } else if (cm->IsACLikeSourceExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Sources, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, {}, false); @@ -928,11 +942,11 @@ bool cmQtAutoGenInitializer::InitScanFiles() addMUSource(std::move(muf)); } } + if (!skipUic && !sf->GetIsGenerated()) { + collectUicIncludes(sf); + } } else if (this->Uic.Enabled && (extLower == kw.ui)) { // .ui file - bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); - bool const skipUic = - (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC)); if (!skipUic) { // Check if the .ui file has uic options std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); @@ -942,35 +956,22 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->Uic.UiFilesWithOptions.emplace_back(fullPath, cmExpandedList(uicOpts)); } - - auto uiHeaderRelativePath = cmSystemTools::RelativePath( - this->LocalGen->GetCurrentSourceDirectory(), - cmSystemTools::GetFilenamePath(fullPath)); - - // Avoid creating a path containing adjacent slashes - if (!uiHeaderRelativePath.empty() && - uiHeaderRelativePath.back() != '/') { - uiHeaderRelativePath += '/'; - } - - auto uiHeaderFilePath = cmStrCat( - '/', uiHeaderRelativePath, "ui_"_s, - cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); - - ConfigString uiHeader; - std::string uiHeaderGenex; - this->ConfigFileNamesAndGenex( - uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s), - uiHeaderFilePath); - - this->Uic.UiHeaders.emplace_back( - std::make_pair(uiHeader, uiHeaderGenex)); } else { // Register skipped .ui file this->Uic.SkipUi.insert(fullPath); } } } + + for (const auto& include : uicIncludes) { + ConfigString uiHeader; + std::string uiHeaderGenex; + this->ConfigFileNamesAndGenex(uiHeader, uiHeaderGenex, + cmStrCat(this->Dir.Build, "/include"_s), + cmStrCat("/"_s, include)); + this->Uic.UiHeaders.emplace_back( + std::make_pair(uiHeader, uiHeaderGenex)); + } } // Process GENERATED sources and headers diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index e76817b9c43..3ec87d212d4 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -17,6 +17,7 @@ #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" +#include "cmQtAutoUicHelpers.h" class cmGeneratorTarget; class cmGlobalGenerator; @@ -170,6 +171,7 @@ class cmQtAutoGenInitializer : public cmQtAutoGen std::string ConfigDefault; std::vector<std::string> ConfigsList; std::string TargetsFolder; + cmQtAutoUicHelpers AutoUicHelpers; /** Common directories. */ struct diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 568926e3c5d..0c6b5e6dc53 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -121,43 +121,6 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename) return success; } -bool cmQtAutoGenerator::FileRead(std::string& content, - std::string const& filename, - std::string* error) -{ - content.clear(); - if (!cmSystemTools::FileExists(filename, true)) { - if (error != nullptr) { - *error = "Not a file."; - } - return false; - } - - unsigned long const length = cmSystemTools::FileLength(filename); - cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); - - // Use lambda to save destructor calls of ifs - return [&ifs, length, &content, error]() -> bool { - if (!ifs) { - if (error != nullptr) { - *error = "Opening the file for reading failed."; - } - return false; - } - content.reserve(length); - using IsIt = std::istreambuf_iterator<char>; - content.assign(IsIt{ ifs }, IsIt{}); - if (!ifs) { - content.clear(); - if (error != nullptr) { - *error = "Reading from the file failed."; - } - return false; - } - return true; - }(); -} - bool cmQtAutoGenerator::FileWrite(std::string const& filename, std::string const& content, std::string* error) diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 5c3a8adccb4..66399d7e8ae 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -70,8 +70,6 @@ class cmQtAutoGenerator : public cmQtAutoGen // -- File system methods static bool MakeParentDirectory(std::string const& filename); - static bool FileRead(std::string& content, std::string const& filename, - std::string* error = nullptr); static bool FileWrite(std::string const& filename, std::string const& content, std::string* error = nullptr); diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 2753fd57c02..86d54f9e1a7 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -30,6 +30,7 @@ #include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" +#include "cmQtAutoUicHelpers.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkerPool.h" @@ -281,7 +282,7 @@ class cmQtAutoMocUicT : public cmQtAutoGenerator std::vector<std::string> Options; std::unordered_map<std::string, UiFile> UiFiles; std::vector<std::string> SearchPaths; - cmsys::RegularExpression RegExpInclude; + cmQtAutoUicHelpers AutoUicHelpers; }; /** Uic shared variables. */ @@ -761,11 +762,7 @@ std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const return res; } -cmQtAutoMocUicT::UicSettingsT::UicSettingsT() -{ - this->RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" - "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); -} +cmQtAutoMocUicT::UicSettingsT::UicSettingsT() = default; cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default; @@ -1056,16 +1053,7 @@ void cmQtAutoMocUicT::JobParseT::UicIncludes() } std::set<std::string> includes; - { - const char* contentChars = this->Content.c_str(); - cmsys::RegularExpression const& regExp = this->UicConst().RegExpInclude; - cmsys::RegularExpressionMatch match; - while (regExp.find(contentChars, match)) { - includes.emplace(match.match(2)); - // Forward content pointer - contentChars += match.end(); - } - } + this->UicConst().AutoUicHelpers.CollectUicIncludes(includes, this->Content); this->CreateKeys(this->FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength); } diff --git a/Source/cmQtAutoUicHelpers.cxx b/Source/cmQtAutoUicHelpers.cxx new file mode 100644 index 00000000000..751ae08575a --- /dev/null +++ b/Source/cmQtAutoUicHelpers.cxx @@ -0,0 +1,25 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoUicHelpers.h" + +cmQtAutoUicHelpers::cmQtAutoUicHelpers() +{ + RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" + "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); +} + +void cmQtAutoUicHelpers::CollectUicIncludes(std::set<std::string>& includes, + const std::string& content) const +{ + if (content.find("ui_") == std::string::npos) { + return; + } + + const char* contentChars = content.c_str(); + cmsys::RegularExpressionMatch match; + while (this->RegExpInclude.find(contentChars, match)) { + includes.emplace(match.match(2)); + // Forward content pointer + contentChars += match.end(); + } +} diff --git a/Source/cmQtAutoUicHelpers.h b/Source/cmQtAutoUicHelpers.h new file mode 100644 index 00000000000..6b09a31daaa --- /dev/null +++ b/Source/cmQtAutoUicHelpers.h @@ -0,0 +1,20 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <set> +#include <string> + +#include "cmsys/RegularExpression.hxx" + +class cmQtAutoUicHelpers +{ +public: + cmQtAutoUicHelpers(); + virtual ~cmQtAutoUicHelpers() = default; + void CollectUicIncludes(std::set<std::string>& includes, + const std::string& content) const; + +private: + cmsys::RegularExpression RegExpInclude; +}; diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt index 1f636af451f..a9ccece5d5c 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt @@ -27,10 +27,12 @@ endmacro() configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY) configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY) +configure_file("${testProjectTemplateDir}/subdir/subdircheck.cpp" "${testProjectSrc}/subdir/subdircheck.cpp" COPYONLY) configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY) set(Num 1) configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) +configure_file("${testProjectTemplateDir}/subdir/mainwindowsubdir.ui.in" "${testProjectSrc}/subdir/mainwindowsubdir.ui" @ONLY) if(CMAKE_GENERATOR_INSTANCE) set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}") @@ -94,6 +96,7 @@ sleep() set(Num 2) configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) +configure_file("${testProjectTemplateDir}/subdir/mainwindowsubdir.ui.in" "${testProjectSrc}/subdir/mainwindowsubdir.ui" @ONLY) rebuild(2) execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in index fa9dd6bee32..2a1998d10fe 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in @@ -6,6 +6,8 @@ include("@CMAKE_CURRENT_LIST_DIR@/../AutogenGuiTest.cmake") # Enable CMAKE_AUTOUIC for all targets set(CMAKE_AUTOUIC ON) -add_executable(UicOnFileChange main.cpp mainwindow.ui) +add_executable(UicOnFileChange main.cpp mainwindow.ui + subdir/subdircheck.cpp subdir/mainwindowsubdir.ui +) target_include_directories(UicOnFileChange PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(UicOnFileChange ${QT_QTCORE_TARGET} ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp index fd810fa2472..39812688463 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp @@ -1,9 +1,11 @@ #include "ui_mainwindow.h" +extern bool subdircheck(); + int main(int argc, char* argv[]) { MocWidget mw; Ui::Widget mwUi; mwUi.setupUi(&mw); - return mw.objectName() == "Widget2" ? 0 : 1; + return mw.objectName() == "Widget2" && subdircheck() ? 0 : 1; } diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in new file mode 100644 index 00000000000..a6a31f6d428 --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>WidgetSubdir</class> + <widget class="MocWidget" name="WidgetSubdir@Num@"/> + <resources/> + <connections/> +</ui> diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp new file mode 100644 index 00000000000..3b36a10df8a --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp @@ -0,0 +1,9 @@ +#include "ui_mainwindowsubdir.h" + +bool subdircheck() +{ + MocWidget mw; + Ui::WidgetSubdir mwUi; + mwUi.setupUi(&mw); + return mw.objectName() == "WidgetSubdir2"; +} From 4bda03370d484ce787c0c3632eaa5a18cffa750c Mon Sep 17 00:00:00 2001 From: Joerg Bornemann <joerg.bornemann@qt.io> Date: Wed, 30 Jun 2021 12:18:21 +0200 Subject: [PATCH 0980/1519] AutoGen: Fix needless compilation of mocs_compilation.cpp For an AUTOMOC'ed target foo, when depfiles are used, there are the following dependencies: foo_autogen -> foo_autogen/timestamp foo_autogen/mocs_compilation.cpp -> foo_autogen/timestamp The first is used to trigger AUTOGEN. The second erroneously triggers a recompilation of mocs_compilation.cpp when any source file of target foo is touched. Remove the latter dependency and replace it with an order-only dependency from foo_autogen/mocs_compilation.cpp to foo_autogen_timestamp_deps. That is achieved by making mocs_compilation.cpp or its per-configuration variants byproduct(s) of the timestamp file. Fixes: #22338 --- Source/cmQtAutoGenInitializer.cxx | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 2894201c9b3..4dd78e514f5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1111,11 +1111,30 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Register info file as generated by CMake this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile); + // Determine whether to use a depfile for the AUTOGEN target. + const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && + this->GlobalGen->GetName().find("Ninja") != std::string::npos; + // Files provided by the autogen target std::vector<std::string> autogenByproducts; + std::vector<std::string> timestampByproducts; if (this->Moc.Enabled) { this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true); - autogenByproducts.push_back(this->Moc.CompilationFileGenex); + if (useNinjaDepfile) { + if (this->MultiConfig) { + // Make all mocs_compilation_<CONFIG>.cpp files byproducts of the + // ${target}_autogen/timestamp custom command. + // We cannot just use Moc.CompilationFileGenex here, because that + // custom command runs cmake_autogen for each configuration. + for (const auto& p : this->Moc.CompilationFile.Config) { + timestampByproducts.push_back(p.second); + } + } else { + timestampByproducts.push_back(this->Moc.CompilationFileGenex); + } + } else { + autogenByproducts.push_back(this->Moc.CompilationFileGenex); + } } if (this->Uic.Enabled) { @@ -1265,8 +1284,6 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->AutogenTarget.DependFiles.begin(), this->AutogenTarget.DependFiles.end()); - const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && - this->GlobalGen->GetName().find("Ninja") != std::string::npos; if (useNinjaDepfile) { // Create a custom command that generates a timestamp file and // has a depfile assigned. The depfile is created by JobDepFilesMergeT. @@ -1327,8 +1344,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->AddGeneratedSource(outputFile, this->Moc); const std::string no_main_dependency; this->LocalGen->AddCustomCommandToOutput( - outputFile, dependencies, no_main_dependency, commandLines, - autogenComment.c_str(), this->Dir.Work.c_str(), + { outputFile }, timestampByproducts, dependencies, no_main_dependency, + /*implicit_depends=*/{}, commandLines, autogenComment.c_str(), + this->Dir.Work.c_str(), /*cmp0116=*/cmPolicies::NEW, /*replace=*/false, /*escapeOldStyle=*/false, /*uses_terminal=*/false, From a915f691adbcac96bd5c3d421ef519900ee79c02 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 23 Jul 2021 12:01:21 -0400 Subject: [PATCH 0981/1519] Help: Format string(TIMESTAMP) format specifiers as a definition list Also fix the version that added `%A` and `%B`. --- Help/command/string.rst | 86 +++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/Help/command/string.rst b/Help/command/string.rst index 8ad0089afd3..6fac0e65f8a 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -449,38 +449,68 @@ be in Coordinated Universal Time (UTC) rather than local time. The optional ``<format_string>`` may contain the following format specifiers: -:: +``%%`` + .. versionadded:: 3.8 - %% A literal percent sign (%). - %d The day of the current month (01-31). - %H The hour on a 24-hour clock (00-23). - %I The hour on a 12-hour clock (01-12). - %j The day of the current year (001-366). - %m The month of the current year (01-12). - %b Abbreviated month name (e.g. Oct). - %B Full month name (e.g. October). - %M The minute of the current hour (00-59). - %s Seconds since midnight (UTC) 1-Jan-1970 (UNIX time). - %S The second of the current minute. - 60 represents a leap second. (00-60) - %U The week number of the current year (00-53). - %w The day of the current week. 0 is Sunday. (0-6) - %a Abbreviated weekday name (e.g. Fri). - %A Full weekday name (e.g. Friday). - %y The last two digits of the current year (00-99) - %Y The current year. - -.. versionadded:: 3.6 - ``%s`` format specifier (UNIX time). + A literal percent sign (%). -.. versionadded:: 3.7 - ``%a`` and ``%b`` format specifiers (abbreviated month and weekday names). +``%d`` + The day of the current month (01-31). -.. versionadded:: 3.8 - ``%%`` specifier (literal ``%``). +``%H`` + The hour on a 24-hour clock (00-23). -.. versionadded:: 3.7 - ``%A`` and ``%B`` format specifiers (full month and weekday names). +``%I`` + The hour on a 12-hour clock (01-12). + +``%j`` + The day of the current year (001-366). + +``%m`` + The month of the current year (01-12). + +``%b`` + .. versionadded:: 3.7 + + Abbreviated month name (e.g. Oct). + +``%B`` + .. versionadded:: 3.10 + + Full month name (e.g. October). + +``%M`` + The minute of the current hour (00-59). + +``%s`` + .. versionadded:: 3.6 + + Seconds since midnight (UTC) 1-Jan-1970 (UNIX time). + +``%S`` + The second of the current minute. 60 represents a leap second. (00-60) + +``%U`` + The week number of the current year (00-53). + +``%w`` + The day of the current week. 0 is Sunday. (0-6) + +``%a`` + .. versionadded:: 3.7 + + Abbreviated weekday name (e.g. Fri). + +``%A`` + .. versionadded:: 3.10 + + Full weekday name (e.g. Friday). + +``%y`` + The last two digits of the current year (00-99). + +``%Y`` + The current year. Unknown format specifiers will be ignored and copied to the output as-is. From 08131e83bcac840e2d550acff936534914d5435c Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Fri, 23 Jul 2021 13:22:59 -0400 Subject: [PATCH 0982/1519] Tests: Clean up Ninja Multi-Config test from cb777dd --- Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake | 3 +-- .../Simple-all-subdir-build-check.cmake | 12 ++++++++++++ .../Simple-all-top-ninja-check.cmake | 12 ++++++++++++ ...e-debug-in-release-graph-target-ninja-check.cmake | 6 +++--- ...mple-debug-in-release-graph-top-build-check.cmake | 12 ++++++++++++ .../Simple-debug-subdir-build-check.cmake | 3 +++ .../Simple-default-build-file-all-ninja-check.cmake | 9 +++++++++ ...ult-build-file-clean-minsizerel-ninja-check.cmake | 6 ++++++ ...Simple-default-build-file-clean-ninja-check.cmake | 9 +++++++++ .../Simple-minsizerel-top-ninja-check.cmake | 12 ++++++++++++ ...ease-in-minsizerel-graph-subdir-ninja-check.cmake | 6 ++++++ ...onfigs-all-all-in-release-graph-build-check.cmake | 6 ++++++ ...relwithdebinfo-in-release-graph-build-check.cmake | 6 ++++++ .../SimpleDefaultBuildAlias-all-ninja-check.cmake | 12 ++++++++++++ ...faultBuildAliasList-all-configs-build-check.cmake | 6 ++++++ ...ildAliasList-all-relwithdebinfo-ninja-check.cmake | 9 +++++++++ ...ultBuildAliasList-clean-configs-ninja-check.cmake | 3 +++ .../NinjaMultiConfig/SimpleSubdir/CMakeLists.txt | 1 - 18 files changed, 127 insertions(+), 6 deletions(-) diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 885ae13de82..7c100eb1eab 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -100,9 +100,8 @@ run_ninja(Simple release-file build-Release.ninja ${simpleexe_Release}) run_cmake_build(Simple all-configs Release simplestatic:all) run_ninja(Simple default-build-file build.ninja simpleexe) run_cmake_build(Simple all-clean Release clean:all) -run_ninja(Simple debug-in-release-graph-target build-Release.ninja simpleexe2:Debug) -run_cmake_build(Simple all-clean Release clean:all) run_cmake_build(Simple debug-subdir Debug SimpleSubdir/all) +run_ninja(Simple debug-in-release-graph-target build-Release.ninja simpleexe2:Debug) run_ninja(Simple release-in-minsizerel-graph-subdir build-MinSizeRel.ninja SimpleSubdir/all:Release) run_cmake_build(Simple all-subdir Release SimpleSubdir/all:all) run_ninja(Simple minsizerel-top build-MinSizeRel.ninja all) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake index de4505ccc0d..0cb6ad2e53e 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -14,6 +17,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -23,6 +29,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_MinSizeRel} ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_FILE_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_FILE_simpleshared_MinSizeRel} ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} @@ -32,6 +41,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake index c171e3d057a..d27c1ca9beb 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -18,6 +21,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -31,6 +37,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_MinSizeRel} ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_FILE_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_FILE_simpleshared_MinSizeRel} ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} @@ -44,6 +53,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake index 2f81bc0533e..8de8fde9dd1 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-target-ninja-check.cmake @@ -2,6 +2,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" INCLUDE ${GENERATED_FILES} + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} ${TARGET_OBJECT_FILES_simpleexe2_Debug} @@ -12,9 +15,6 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_OBJECT_FILES_simpleobj_Debug} EXCLUDE - ${TARGET_FILE_simpleexe_Debug} - - ${TARGET_OBJECT_FILES_simpleexe_Debug} ${TARGET_OBJECT_FILES_simplestatic_Debug} ${TARGET_OBJECT_FILES_simpleexe_Release} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake index fe980fea670..d2cb8461f17 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -18,6 +21,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -27,6 +33,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_MinSizeRel} ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_FILE_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_FILE_simpleshared_MinSizeRel} ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} @@ -40,6 +49,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake index 6bb7773fd2e..6a0190ffcb4 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-all-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-all-ninja-check.cmake index 4e6e6544178..aec10eefcb4 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-all-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-all-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -18,6 +21,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -31,6 +37,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-minsizerel-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-minsizerel-ninja-check.cmake index c09ae65b95b..b46a708d82d 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-minsizerel-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-minsizerel-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -18,6 +21,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-ninja-check.cmake index 43213dd0130..9d124cdb0f9 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-clean-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -18,6 +21,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -31,6 +37,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_MinSizeRel} ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_FILE_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_FILE_simpleshared_MinSizeRel} ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake index bf4be49271f..496d722463f 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -14,6 +17,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -23,6 +29,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_MinSizeRel} ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_FILE_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_FILE_simpleshared_MinSizeRel} ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} @@ -36,6 +45,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake index b6c77abf268..29c0187ed24 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -14,6 +17,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-all-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-all-in-release-graph-build-check.cmake index fee5951c4e4..67326d9c34a 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-all-in-release-graph-build-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-all-in-release-graph-build-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -17,6 +20,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-relwithdebinfo-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-relwithdebinfo-in-release-graph-build-check.cmake index fee5951c4e4..67326d9c34a 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-relwithdebinfo-in-release-graph-build-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleCrossConfigs-all-relwithdebinfo-in-release-graph-build-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -17,6 +20,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAlias-all-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAlias-all-ninja-check.cmake index c171e3d057a..d27c1ca9beb 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAlias-all-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAlias-all-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -18,6 +21,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -31,6 +37,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_MinSizeRel} ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_FILE_simpleexe2_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe2_MinSizeRel} + ${TARGET_FILE_simpleshared_MinSizeRel} ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} @@ -44,6 +53,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-configs-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-configs-build-check.cmake index 8ffdd20b558..4e4ec82cf0f 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-configs-build-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-configs-build-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -17,6 +20,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-relwithdebinfo-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-relwithdebinfo-ninja-check.cmake index 9e5baf91a9e..b1789b01b0a 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-relwithdebinfo-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-all-relwithdebinfo-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Debug} ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_FILE_simpleexe2_Debug} + ${TARGET_OBJECT_FILES_simpleexe2_Debug} + ${TARGET_FILE_simpleshared_Debug} ${TARGET_LINKER_FILE_simpleshared_Debug} ${TARGET_OBJECT_FILES_simpleshared_Debug} @@ -17,6 +20,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_Release} ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_FILE_simpleexe2_Release} + ${TARGET_OBJECT_FILES_simpleexe2_Release} + ${TARGET_FILE_simpleshared_Release} ${TARGET_LINKER_FILE_simpleshared_Release} ${TARGET_OBJECT_FILES_simpleshared_Release} @@ -29,6 +35,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-clean-configs-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-clean-configs-ninja-check.cmake index 3829d3e5258..9016cf4ac8f 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-clean-configs-ninja-check.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleDefaultBuildAliasList-clean-configs-ninja-check.cmake @@ -5,6 +5,9 @@ check_files("${RunCMake_TEST_BINARY_DIR}" ${TARGET_FILE_simpleexe_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_FILE_simpleexe2_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe2_RelWithDebInfo} + ${TARGET_FILE_simpleshared_RelWithDebInfo} ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt index 0ca6d023689..d81f5ab6e91 100644 --- a/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt @@ -6,4 +6,3 @@ target_link_libraries(simpleexe PRIVATE simpleshared) add_executable(simpleexe2 ../main.c) target_link_libraries(simpleexe2 PRIVATE simpleshared $<TARGET_OBJECTS:simpleobj>) -set_property(TARGET simpleexe2 PROPERTY EXCLUDE_FROM_ALL 1) From acb068b0f0f182e026e1d8f58a7cb4440e9996a0 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 24 Jul 2021 00:01:12 -0400 Subject: [PATCH 0983/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8b4b1ab3b56..8c9a0c51f25 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210723) +set(CMake_VERSION_PATCH 20210724) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f6e5743d0eb52dddd9183be65b5374ea2cd8c772 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 24 Jul 2021 15:08:21 +1000 Subject: [PATCH 0984/1519] Help: Clarify and correct wording around DEPFILE option The previous wording contradicted itself regarding whether Visual Studio generators were supported, and about when generator expressions could be used. Restructure the paragraphs and max it clearer what support was added in which CMake versions. --- Help/command/add_custom_command.rst | 41 ++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index d881a66b5c0..b45a0794d25 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -271,35 +271,40 @@ The options are: ``DEPFILE`` .. versionadded:: 3.7 - Specify a ``.d`` depfile for the :generator:`Ninja`, :generator:`Xcode` and - :ref:`Makefile <Makefile Generators>` generators. The depfile may use - "generator expressions" with the syntax ``$<...>``. See the - :manual:`generator-expressions(7) <cmake-generator-expressions(7)>` manual - for available expressions. A ``.d`` file holds dependencies usually emitted - by the custom command itself. + Specify a ``.d`` depfile which holds dependencies for the custom command. + It is usually emitted by the custom command itself. This keyword may only + be used if the generator supports it, as detailed below. - Using ``DEPFILE`` with other generators than :generator:`Ninja`, - :generator:`Xcode` or :ref:`Makefile <Makefile Generators>` is an error. + .. versionadded:: 3.7 + The :generator:`Ninja` generator supports ``DEPFILE`` since the keyword + was first added. + + .. versionadded:: 3.17 + Added the :generator:`Ninja Multi-Config` generator, which included + support for the ``DEPFILE`` keyword. .. versionadded:: 3.20 Added support for :ref:`Makefile Generators`. + .. note:: + + ``DEPFILE`` cannot be specified at the same time as the + ``IMPLICIT_DEPENDS`` option for :ref:`Makefile Generators`. + .. versionadded:: 3.21 Added support for :ref:`Visual Studio Generators` with VS 2012 and above, - for the :generator:`Xcode` generator, and for - :manual:`generator expressions <cmake-generator-expressions(7)>`. + and for the :generator:`Xcode` generator. Support for + :manual:`generator expressions <cmake-generator-expressions(7)>` was also + added. + + Using ``DEPFILE`` with generators other than those listed above is an error. If the ``DEPFILE`` argument is relative, it should be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the - ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR` - (see policy :policy:`CMP0116`. This policy is always ``NEW`` for + ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. + See policy :policy:`CMP0116`, which is always ``NEW`` for :ref:`Makefile Generators`, :ref:`Visual Studio Generators`, - and the :generator:`Xcode` generator). - - .. note:: - - For :ref:`Makefile Generators`, this option cannot be specified at the - same time as ``IMPLICIT_DEPENDS`` option. + and the :generator:`Xcode` generator. Examples: Generating Files ^^^^^^^^^^^^^^^^^^^^^^^^^^ From a87c54aba32ad6ffca522e56565c9e6dcf66f5ac Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 25 Jul 2021 00:01:08 -0400 Subject: [PATCH 0985/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8c9a0c51f25..ccb3f8b1372 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210724) +set(CMake_VERSION_PATCH 20210725) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From cdde9e5a10f22caa925d5391f406c6eaf3333f70 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 25 Jul 2021 21:31:48 +1000 Subject: [PATCH 0986/1519] Help: Improve wording and cross-referencing for ctest JUnit output --- Help/command/ctest_test.rst | 6 +++--- Help/manual/ctest.1.rst | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 2104c47c625..89787d13321 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -155,12 +155,12 @@ The options are: 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. -``OUTPUT_JUNIT`` +``OUTPUT_JUNIT <file>`` .. versionadded:: 3.21 Write test results to ``<file>`` in JUnit XML format. If ``<file>`` is a - relative path it will be placed in the build directory. If ``<file>>`` - already exists it will be overwritten. Note that the resulting JUnit XML + relative path, it will be placed in the build directory. If ``<file>`` + already exists, it will be overwritten. Note that the resulting JUnit XML file is **not** uploaded to CDash because it would be redundant with CTest's ``Test.xml`` file. diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index ab819f94ef2..03d8bf6c805 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -137,8 +137,10 @@ Options ``--output-junit <file>`` Write test results in JUnit format. - This option tells CTest to write test results to a ``<file>`` JUnit XML file. - If ``<file>`` already exists it will be overwritten. + 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 + ``-S`` option to run a dashboard script, use the ``OUTPUT_JUNIT`` keyword + with the :command:`ctest_test` command instead. ``-N,--show-only[=<format>]`` Disable actual execution of tests. From ffbd3bb42f99be35218ff34040f795fbc66eb932 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 26 Jul 2021 00:01:14 -0400 Subject: [PATCH 0987/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ccb3f8b1372..7345e44242e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210725) +set(CMake_VERSION_PATCH 20210726) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ba6d1947b6ef6186e84ee589d792bf9437f0d417 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 25 Jul 2021 21:37:59 +1000 Subject: [PATCH 0988/1519] Help: Add cross-references between test output size ctest variables --- Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst | 3 +++ Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst b/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst index 9f145c1a2a4..7e7d431e6d0 100644 --- a/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst +++ b/Help/variable/CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE.rst @@ -9,3 +9,6 @@ If a test's output contains the literal string "CTEST_FULL_OUTPUT", the output will not be truncated and may exceed the maximum size. .. include:: CTEST_CUSTOM_XXX.txt + +For controlling the output collection of passing tests, see +:variable:`CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE`. diff --git a/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst b/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst index 71ecf52bfb9..64367f9a363 100644 --- a/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst +++ b/Help/variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE.rst @@ -9,3 +9,6 @@ If a test's output contains the literal string "CTEST_FULL_OUTPUT", the output will not be truncated and may exceed the maximum size. .. include:: CTEST_CUSTOM_XXX.txt + +For controlling the output collection of failing tests, see +:variable:`CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE`. From 91968ca66845dd560bb27710488a62b2be91c8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= <congdanhqx@gmail.com> Date: Sun, 18 Jul 2021 16:49:41 +0700 Subject: [PATCH 0989/1519] Tests/CompileOptions: allow CMAKE_BUILD_TYPE=None In the same spirit of commit ce1cadd35a, (Tests/ConfigSources: fix for non main stream CMAKE_BUILD_TYPE, 2021-04-01). Allow distributions' check to pass seemlessly. Issue: #22470 --- Tests/CompileOptions/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt index 96bafeadd51..1bedac0192e 100644 --- a/Tests/CompileOptions/CMakeLists.txt +++ b/Tests/CompileOptions/CMakeLists.txt @@ -65,6 +65,10 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|AppleClang|MSVC)$") string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DFLAG_A=2 -DFLAG_C=1") string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DFLAG_A=2 -DFLAG_C=1") string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DFLAG_A=2 -DFLAG_C=1") + string(TOUPPER "${CMAKE_BUILD_TYPE}" _xbuild_type) + if(NOT _xbuild_type MATCHES "^(DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL)$") + string(APPEND CMAKE_CXX_FLAGS_${_xbuild_type} " -DFLAG_A=2 -DFLAG_C=1") + endif() set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS "-DFLAG_B=2" "-DFLAG_C=2" "-DFLAG_D=1") set_property(TARGET testlib APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-DFLAG_D=2") if(NOT CMAKE_GENERATOR MATCHES "^Visual Studio 9") From 7fc3f7001a3fcc3dbab90834c6bc2b389b3b38c9 Mon Sep 17 00:00:00 2001 From: KWSys Upstream <kwrobot@kitware.com> Date: Mon, 26 Jul 2021 10:16:56 -0400 Subject: [PATCH 0990/1519] KWSys 2021-07-26 (d5fd6ca2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit d5fd6ca2ba5b4ca04d7ac346ceb87f7d2b0ad8aa (master). Upstream Shortlog ----------------- Dženan Zukić (1): 7079df74 SystemTools: Fix GetOperatingSystemNameAndVersion empty string return Đoàn Trần Công Danh (1): 4e69b791 SystemInformation: Add option to explicitly avoid using execinfo --- CMakeLists.txt | 4 +++- SystemTools.cxx | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef615b3fee1..7da597121fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,8 @@ # Set to empty string to use no default value. # KWSYS_CXX_COMPILE_FEATURES = target_compile_features arguments for KWSys. # +# KWSYS_NO_EXECINFO = Do not use execinfo. +# # Optional settings to setup install rules are as follows: # # KWSYS_INSTALL_BIN_DIR = The installation target directories into @@ -526,7 +528,7 @@ if(KWSYS_USE_SystemInformation) set_property(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS_RLIMIT64=1) endif() - if(UNIX) + if(UNIX AND NOT KWSYS_NO_EXECINFO) include(CheckIncludeFileCXX) # check for simple stack trace # usually it's in libc but on FreeBSD diff --git a/SystemTools.cxx b/SystemTools.cxx index 006495d3cc7..7c26974ef8c 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -4360,7 +4360,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() # endif bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi); if (!bOsVersionInfoEx) { - return 0; + return ""; } # ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # ifdef __clang__ @@ -4499,14 +4499,14 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey); if (lRet != ERROR_SUCCESS) { - return 0; + return ""; } lRet = RegQueryValueExW(hKey, L"ProductType", nullptr, nullptr, (LPBYTE)szProductType, &dwBufLen); if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE)) { - return 0; + return ""; } RegCloseKey(hKey); From 8fb349a80e3feef7d139dd4ade2a2e64e6652e55 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 26 Jul 2021 09:44:55 -0400 Subject: [PATCH 0991/1519] VS: Remove cl /FS entry from flag table for v142 and v143 The `ForceSynchronousPDBWrites` entry in a `.vcxproj` file does not actually cause the `/FS` flag to be added to the command line. Fixes: #22476 --- Templates/MSBuild/FlagTables/v142_CL.json | 7 ------- Templates/MSBuild/FlagTables/v143_CL.json | 7 ------- 2 files changed, 14 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index b3637186ce1..08b645925f9 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -786,13 +786,6 @@ "Continue" ] }, - { - "name": "ForceSynchronousPDBWrites", - "switch": "FS", - "comment": "Force Synchronous PDB Writes", - "value": "true", - "flags": [] - }, { "name": "IntrinsicFunctions", "switch": "Oi", diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 9d8ddb02561..ad7194b8fce 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -788,13 +788,6 @@ "Continue" ] }, - { - "name": "ForceSynchronousPDBWrites", - "switch": "FS", - "comment": "Force Synchronous PDB Writes", - "value": "true", - "flags": [] - }, { "name": "IntrinsicFunctions", "switch": "Oi", From 937f454fb9a8bc962a94f050e5b632d92d5db1b0 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 26 Jul 2021 10:46:14 -0400 Subject: [PATCH 0992/1519] VS: Remove C++ module CompileAs flag table entries for v142 and v143 The `CompileAs` entry in a `.vcxproj` file with values: * `CompileAsCppModule` for `-interface` * `CompileAsCppModuleInternalPartition` for `-internalPartition` * `CompileAsHeaderUnit` for `-exportHeader` does not cause the corresponding flag to be added to the command line. Drop the flag table entries so that the flags go to `AdditionalOptions`. Fixes: #22477 --- Templates/MSBuild/FlagTables/v142_CL.json | 21 --------------------- Templates/MSBuild/FlagTables/v143_CL.json | 21 --------------------- 2 files changed, 42 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 08b645925f9..64eeac4ab3f 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -663,27 +663,6 @@ "value": "CompileAsCpp", "flags": [] }, - { - "name": "CompileAs", - "switch": "interface", - "comment": "Compile as C++ Module Code", - "value": "CompileAsCppModule", - "flags": [] - }, - { - "name": "CompileAs", - "switch": "internalPartition", - "comment": "Compile as C++ Module Internal Partition", - "value": "CompileAsCppModuleInternalPartition", - "flags": [] - }, - { - "name": "CompileAs", - "switch": "exportHeader", - "comment": "Compile as C++ Header Unit", - "value": "CompileAsHeaderUnit", - "flags": [] - }, { "name": "ErrorReporting", "switch": "errorReport:none", diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index ad7194b8fce..8b700aafb3e 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -658,27 +658,6 @@ "value": "CompileAsCpp", "flags": [] }, - { - "name": "CompileAs", - "switch": "interface", - "comment": "Compile as C++ Module Code", - "value": "CompileAsCppModule", - "flags": [] - }, - { - "name": "CompileAs", - "switch": "internalPartition", - "comment": "Compile as C++ Module Internal Partition", - "value": "CompileAsCppModuleInternalPartition", - "flags": [] - }, - { - "name": "CompileAs", - "switch": "exportHeader", - "comment": "Compile as C++ Header Unit", - "value": "CompileAsHeaderUnit", - "flags": [] - }, { "name": "ErrorReporting", "switch": "errorReport:none", From aa4c30182b0c258cddfb0582e7cfc2561b69a378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= <congdanhqx@gmail.com> Date: Sun, 18 Jul 2021 16:32:38 +0700 Subject: [PATCH 0993/1519] Add option to explicitly avoid using execinfo for backtraces backtrace(3) from libexecinfo in musl will run into crash [1]. Provide an option to disable it explicitly even if libexecinfo is present. 1: https://www.openwall.com/lists/musl/2021/07/17/1 --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44b433ac8f2..9944ea4ce37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,6 +361,9 @@ macro (CMAKE_BUILD_UTILITIES) if(CMake_NO_CXX_STANDARD) set(KWSYS_CXX_STANDARD "") endif() + if(CMake_NO_SELF_BACKTRACE) + set(KWSYS_NO_EXECINFO 1) + endif() if(WIN32) # FIXME: Teach KWSys to hard-code these checks on Windows. set(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC_COMPILED 0) From 0b5301a778cb22b1179dd21d709494dfe74add41 Mon Sep 17 00:00:00 2001 From: Yauheni Khnykin <yauheni.khnykin@here.com> Date: Thu, 22 Jul 2021 10:40:50 +0200 Subject: [PATCH 0994/1519] FindXCTest: Fix output directory for test bundle with Xcode 12.5 The fix from commit eafe740ead (FindXCTest: Fix output directory for test bundle with new build system, 2021-02-09, v3.19.5~5^2) is not necessary with Xcode 12.5, which seems to have changed/fixed the behaviour again. Fixes: #22462 --- Modules/FindXCTest.cmake | 3 ++- Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 11 ++++++++--- .../XcodeProject/XCTestAddBundle.cmake | 9 +++++++-- Tests/RunCMake/XcodeProject/dummy_main.swift | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/XcodeProject/dummy_main.swift diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake index 48371e620b9..00729bc273f 100644 --- a/Modules/FindXCTest.cmake +++ b/Modules/FindXCTest.cmake @@ -156,8 +156,9 @@ function(xctest_add_bundle target testee) XCODE_ATTRIBUTE_BUNDLE_LOADER "$(TEST_HOST)" XCODE_ATTRIBUTE_TEST_HOST "$<TARGET_FILE:${testee}>") if(XCODE_VERSION VERSION_GREATER_EQUAL 7.3) - # CMAKE_XCODE_BUILD_SYSTEM equals 12 means that at least Xcode 11.x is used. + # The Xcode "new build system" used a different path until Xcode 12.5. if(CMAKE_XCODE_BUILD_SYSTEM EQUAL 12 AND + XCODE_VERSION VERSION_LESS 12.5 AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(_output_directory "$<TARGET_BUNDLE_CONTENT_DIR:${testee}>") else() diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 26714c47f1e..ed8e7258f86 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -407,11 +407,16 @@ if (XCODE_VERSION VERSION_GREATER_EQUAL 7.3) if(XCODE_VERSION VERSION_GREATER_EQUAL 12) xctest_add_bundle_test(Darwin macosx "1" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") xctest_add_bundle_test(Darwin macosx "12" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") - xctest_add_bundle_test(iOS iphoneos "1" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") - xctest_add_bundle_test(iOS iphoneos "12" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>") + xctest_add_bundle_test(iOS iphonesimulator "1" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") + if (XCODE_VERSION VERSION_LESS 12.5) + xctest_add_bundle_test(iOS iphonesimulator "12" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>") + else() + xctest_add_bundle_test(iOS iphonesimulator "12" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") + endif() else() xctest_add_bundle_test(Darwin macosx "" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") - xctest_add_bundle_test(iOS iphoneos "" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") + xctest_add_bundle_test(iOS iphonesimulator "" "$<TARGET_BUNDLE_CONTENT_DIR:TestedApp>/PlugIns") endif() endif() + # Please add macOS-only tests above before the device-specific tests. diff --git a/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake b/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake index 444c730bbe6..9114feea538 100644 --- a/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake +++ b/Tests/RunCMake/XcodeProject/XCTestAddBundle.cmake @@ -1,9 +1,14 @@ enable_language(Swift) + +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED NO) +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + find_package(XCTest REQUIRED) -add_executable(TestedApp MACOSX_BUNDLE EXCLUDE_FROM_ALL foo.swift) +add_executable(TestedApp MACOSX_BUNDLE dummy_main.swift) -xctest_add_bundle(TestingAppBundle TestedApp foo.swift) +xctest_add_bundle(TestingAppBundle TestedApp dummy_main.swift) get_target_property(_lib_output_dir TestingAppBundle LIBRARY_OUTPUT_DIRECTORY) diff --git a/Tests/RunCMake/XcodeProject/dummy_main.swift b/Tests/RunCMake/XcodeProject/dummy_main.swift new file mode 100644 index 00000000000..1aaee42c88c --- /dev/null +++ b/Tests/RunCMake/XcodeProject/dummy_main.swift @@ -0,0 +1,18 @@ +#if os(iOS) +import UIKit + +@UIApplicationMain +class MyApp: UIResponder, UIApplicationDelegate { +} + +#elseif os(macOS) +import SwiftUI + +@main +struct MyApp: App { + var body: some Scene { + WindowGroup { + } + } +} +#endif From bebb3a1f5ac05cf8ec9b7702019e700ed14887e3 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 03:29:00 +0300 Subject: [PATCH 0995/1519] Refactor: Use anonymous namespace instead of `static` keyword for consts Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 66 +++++++++++++++++---------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index f99592cc092..9936d4cea00 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -22,38 +22,40 @@ class cmTest; -static std::string const keyAND = "AND"; -static std::string const keyCOMMAND = "COMMAND"; -static std::string const keyDEFINED = "DEFINED"; -static std::string const keyEQUAL = "EQUAL"; -static std::string const keyEXISTS = "EXISTS"; -static std::string const keyGREATER = "GREATER"; -static std::string const keyGREATER_EQUAL = "GREATER_EQUAL"; -static std::string const keyIN_LIST = "IN_LIST"; -static std::string const keyIS_ABSOLUTE = "IS_ABSOLUTE"; -static std::string const keyIS_DIRECTORY = "IS_DIRECTORY"; -static std::string const keyIS_NEWER_THAN = "IS_NEWER_THAN"; -static std::string const keyIS_SYMLINK = "IS_SYMLINK"; -static std::string const keyLESS = "LESS"; -static std::string const keyLESS_EQUAL = "LESS_EQUAL"; -static std::string const keyMATCHES = "MATCHES"; -static std::string const keyNOT = "NOT"; -static std::string const keyOR = "OR"; -static std::string const keyParenL = "("; -static std::string const keyParenR = ")"; -static std::string const keyPOLICY = "POLICY"; -static std::string const keySTREQUAL = "STREQUAL"; -static std::string const keySTRGREATER = "STRGREATER"; -static std::string const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"; -static std::string const keySTRLESS = "STRLESS"; -static std::string const keySTRLESS_EQUAL = "STRLESS_EQUAL"; -static std::string const keyTARGET = "TARGET"; -static std::string const keyTEST = "TEST"; -static std::string const keyVERSION_EQUAL = "VERSION_EQUAL"; -static std::string const keyVERSION_GREATER = "VERSION_GREATER"; -static std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"; -static std::string const keyVERSION_LESS = "VERSION_LESS"; -static std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"; +namespace { +std::string const keyAND = "AND"; +std::string const keyCOMMAND = "COMMAND"; +std::string const keyDEFINED = "DEFINED"; +std::string const keyEQUAL = "EQUAL"; +std::string const keyEXISTS = "EXISTS"; +std::string const keyGREATER = "GREATER"; +std::string const keyGREATER_EQUAL = "GREATER_EQUAL"; +std::string const keyIN_LIST = "IN_LIST"; +std::string const keyIS_ABSOLUTE = "IS_ABSOLUTE"; +std::string const keyIS_DIRECTORY = "IS_DIRECTORY"; +std::string const keyIS_NEWER_THAN = "IS_NEWER_THAN"; +std::string const keyIS_SYMLINK = "IS_SYMLINK"; +std::string const keyLESS = "LESS"; +std::string const keyLESS_EQUAL = "LESS_EQUAL"; +std::string const keyMATCHES = "MATCHES"; +std::string const keyNOT = "NOT"; +std::string const keyOR = "OR"; +std::string const keyParenL = "("; +std::string const keyParenR = ")"; +std::string const keyPOLICY = "POLICY"; +std::string const keySTREQUAL = "STREQUAL"; +std::string const keySTRGREATER = "STRGREATER"; +std::string const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"; +std::string const keySTRLESS = "STRLESS"; +std::string const keySTRLESS_EQUAL = "STRLESS_EQUAL"; +std::string const keyTARGET = "TARGET"; +std::string const keyTEST = "TEST"; +std::string const keyVERSION_EQUAL = "VERSION_EQUAL"; +std::string const keyVERSION_GREATER = "VERSION_GREATER"; +std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"; +std::string const keyVERSION_LESS = "VERSION_LESS"; +std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"; +} // anonymous namespace cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, cmListFileBacktrace bt) From 4b4e603075d61b33fac595ed29ac6dd694927927 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 03:34:08 +0300 Subject: [PATCH 0996/1519] Refactor: Add constness Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 9936d4cea00..530f8bc33dc 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -229,7 +229,7 @@ bool cmConditionEvaluator::GetBooleanValue( // Check for numbers. if (!arg.empty()) { char* end; - double d = strtod(arg.GetValue().c_str(), &end); + const double d = std::strtod(arg.GetValue().c_str(), &end); if (*end == '\0') { // The whole string is a number. Use C conversion to bool. return static_cast<bool>(d); @@ -280,8 +280,8 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( } // Check policy only if old and new results differ. - bool newResult = this->GetBooleanValue(newArg); - bool oldResult = this->GetBooleanValueOld(newArg, oneArg); + const bool newResult = this->GetBooleanValue(newArg); + const bool oldResult = this->GetBooleanValueOld(newArg, oneArg); if (newResult != oldResult) { switch (this->Policy12Status) { case cmPolicies::WARN: @@ -323,7 +323,7 @@ void cmConditionEvaluator::IncrementArguments( //========================================================================= // helper function to reduce code duplication void cmConditionEvaluator::HandlePredicate( - bool value, int& reducible, cmArgumentList::iterator& arg, + const bool value, int& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2) const { @@ -340,7 +340,7 @@ void cmConditionEvaluator::HandlePredicate( //========================================================================= // helper function to reduce code duplication -void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible, +void cmConditionEvaluator::HandleBinaryOp(const bool value, int& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, @@ -491,7 +491,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } // is a variable defined if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) { - size_t argP1len = argP1->GetValue().size(); + const size_t argP1len = argP1->GetValue().size(); bool bdef = false; if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && argP1->GetValue().operator[](argP1len - 1) == '}') { @@ -585,8 +585,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, double lhs; double rhs; bool result; - if (sscanf(def->c_str(), "%lg", &lhs) != 1 || - sscanf(def2->c_str(), "%lg", &rhs) != 1) { + if (std::sscanf(def->c_str(), "%lg", &lhs) != 1 || + std::sscanf(def2->c_str(), "%lg", &rhs) != 1) { result = false; } else if (*(argP1) == keyLESS) { result = (lhs < rhs); @@ -610,7 +610,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keySTREQUAL, *argP1))) { def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); - int val = (*def).compare(*def2); + const int val = (*def).compare(*def2); bool result; if (*(argP1) == keySTRLESS) { result = (val < 0); @@ -647,7 +647,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else { // version_equal op = cmSystemTools::OP_EQUAL; } - bool result = + const bool result = cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } From fab389002543f9a7c46522956dd8ce6bfe1752a4 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 03:36:44 +0300 Subject: [PATCH 0997/1519] Refactor: Opt-out `if` stataments to select 1st param ... for some calls to `cmExpandedCommandArgument`. Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 530f8bc33dc..4a9f95f2b21 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmConditionEvaluator.h" +#include <array> #include <cstdio> #include <cstdlib> #include <functional> @@ -55,6 +56,9 @@ std::string const keyVERSION_GREATER = "VERSION_GREATER"; std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"; std::string const keyVERSION_LESS = "VERSION_LESS"; std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"; + +std::array<const char* const, 2> const ZERO_ONE_XLAT = { "0", "1" }; + } // anonymous namespace cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, @@ -312,10 +316,10 @@ void cmConditionEvaluator::IncrementArguments( cmArgumentList::iterator& argP2) const { if (argP1 != newArgs.end()) { - argP1++; + ++argP1; argP2 = argP1; if (argP1 != newArgs.end()) { - argP2++; + ++argP2; } } } @@ -327,11 +331,7 @@ void cmConditionEvaluator::HandlePredicate( cmArgumentList& newArgs, cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2) const { - if (value) { - *arg = cmExpandedCommandArgument("1", true); - } else { - *arg = cmExpandedCommandArgument("0", true); - } + *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); newArgs.erase(argP1); argP1 = arg; this->IncrementArguments(newArgs, argP1, argP2); @@ -346,11 +346,7 @@ void cmConditionEvaluator::HandleBinaryOp(const bool value, int& reducible, cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2) { - if (value) { - *arg = cmExpandedCommandArgument("1", true); - } else { - *arg = cmExpandedCommandArgument("0", true); - } + *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); newArgs.erase(argP2); newArgs.erase(argP1); argP1 = arg; @@ -399,12 +395,8 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, newArgs2.pop_back(); // now recursively invoke IsTrue to handle the values inside the // parenthetical expression - bool value = this->IsTrue(newArgs2, errorString, status); - if (value) { - *arg = cmExpandedCommandArgument("1", true); - } else { - *arg = cmExpandedCommandArgument("0", true); - } + const bool value = this->IsTrue(newArgs2, errorString, status); + *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); argP1 = arg; argP1++; // remove the now evaluated parenthetical expression From c26f15c66dcf45c2245315251b31b8f0b671321b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 04:38:40 +0300 Subject: [PATCH 0998/1519] Refactor: Use `cm::string_view` for static const literals Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 93 +++++++++++++++++---------------- Source/cmConditionEvaluator.h | 4 +- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 4a9f95f2b21..29d7108fd8e 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -9,6 +9,7 @@ #include <sstream> #include <utility> +#include <cm/string_view> #include <cmext/algorithm> #include "cmsys/RegularExpression.hxx" @@ -24,38 +25,38 @@ class cmTest; namespace { -std::string const keyAND = "AND"; -std::string const keyCOMMAND = "COMMAND"; -std::string const keyDEFINED = "DEFINED"; -std::string const keyEQUAL = "EQUAL"; -std::string const keyEXISTS = "EXISTS"; -std::string const keyGREATER = "GREATER"; -std::string const keyGREATER_EQUAL = "GREATER_EQUAL"; -std::string const keyIN_LIST = "IN_LIST"; -std::string const keyIS_ABSOLUTE = "IS_ABSOLUTE"; -std::string const keyIS_DIRECTORY = "IS_DIRECTORY"; -std::string const keyIS_NEWER_THAN = "IS_NEWER_THAN"; -std::string const keyIS_SYMLINK = "IS_SYMLINK"; -std::string const keyLESS = "LESS"; -std::string const keyLESS_EQUAL = "LESS_EQUAL"; -std::string const keyMATCHES = "MATCHES"; -std::string const keyNOT = "NOT"; -std::string const keyOR = "OR"; -std::string const keyParenL = "("; -std::string const keyParenR = ")"; -std::string const keyPOLICY = "POLICY"; -std::string const keySTREQUAL = "STREQUAL"; -std::string const keySTRGREATER = "STRGREATER"; -std::string const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"; -std::string const keySTRLESS = "STRLESS"; -std::string const keySTRLESS_EQUAL = "STRLESS_EQUAL"; -std::string const keyTARGET = "TARGET"; -std::string const keyTEST = "TEST"; -std::string const keyVERSION_EQUAL = "VERSION_EQUAL"; -std::string const keyVERSION_GREATER = "VERSION_GREATER"; -std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"; -std::string const keyVERSION_LESS = "VERSION_LESS"; -std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"; +auto const keyAND = "AND"_s; +auto const keyCOMMAND = "COMMAND"_s; +auto const keyDEFINED = "DEFINED"_s; +auto const keyEQUAL = "EQUAL"_s; +auto const keyEXISTS = "EXISTS"_s; +auto const keyGREATER = "GREATER"_s; +auto const keyGREATER_EQUAL = "GREATER_EQUAL"_s; +auto const keyIN_LIST = "IN_LIST"_s; +auto const keyIS_ABSOLUTE = "IS_ABSOLUTE"_s; +auto const keyIS_DIRECTORY = "IS_DIRECTORY"_s; +auto const keyIS_NEWER_THAN = "IS_NEWER_THAN"_s; +auto const keyIS_SYMLINK = "IS_SYMLINK"_s; +auto const keyLESS = "LESS"_s; +auto const keyLESS_EQUAL = "LESS_EQUAL"_s; +auto const keyMATCHES = "MATCHES"_s; +auto const keyNOT = "NOT"_s; +auto const keyOR = "OR"_s; +auto const keyParenL = "("_s; +auto const keyParenR = ")"_s; +auto const keyPOLICY = "POLICY"_s; +auto const keySTREQUAL = "STREQUAL"_s; +auto const keySTRGREATER = "STRGREATER"_s; +auto const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"_s; +auto const keySTRLESS = "STRLESS"_s; +auto const keySTRLESS_EQUAL = "STRLESS_EQUAL"_s; +auto const keyTARGET = "TARGET"_s; +auto const keyTEST = "TEST"_s; +auto const keyVERSION_EQUAL = "VERSION_EQUAL"_s; +auto const keyVERSION_GREATER = "VERSION_GREATER"_s; +auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s; +auto const keyVERSION_LESS = "VERSION_LESS"_s; +auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; std::array<const char* const, 2> const ZERO_ONE_XLAT = { "0", "1" }; @@ -181,7 +182,7 @@ cmProp cmConditionEvaluator::GetVariableOrString( } //========================================================================= -bool cmConditionEvaluator::IsKeyword(std::string const& keyword, +bool cmConditionEvaluator::IsKeyword(cm::string_view keyword, cmExpandedCommandArgument& argument) const { if ((this->Policy54Status != cmPolicies::WARN && @@ -190,7 +191,7 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword, return false; } - bool isKeyword = argument.GetValue() == keyword; + const bool isKeyword = argument.GetValue() == keyword; if (isKeyword && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { @@ -580,13 +581,13 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (std::sscanf(def->c_str(), "%lg", &lhs) != 1 || std::sscanf(def2->c_str(), "%lg", &rhs) != 1) { result = false; - } else if (*(argP1) == keyLESS) { + } else if (argP1->GetValue() == keyLESS) { result = (lhs < rhs); - } else if (*(argP1) == keyLESS_EQUAL) { + } else if (argP1->GetValue() == keyLESS_EQUAL) { result = (lhs <= rhs); - } else if (*(argP1) == keyGREATER) { + } else if (argP1->GetValue() == keyGREATER) { result = (lhs > rhs); - } else if (*(argP1) == keyGREATER_EQUAL) { + } else if (argP1->GetValue() == keyGREATER_EQUAL) { result = (lhs >= rhs); } else { result = (lhs == rhs); @@ -604,13 +605,13 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def2 = this->GetVariableOrString(*argP2); const int val = (*def).compare(*def2); bool result; - if (*(argP1) == keySTRLESS) { + if (argP1->GetValue() == keySTRLESS) { result = (val < 0); - } else if (*(argP1) == keySTRLESS_EQUAL) { + } else if (argP1->GetValue() == keySTRLESS_EQUAL) { result = (val <= 0); - } else if (*(argP1) == keySTRGREATER) { + } else if (argP1->GetValue() == keySTRGREATER) { result = (val > 0); - } else if (*(argP1) == keySTRGREATER_EQUAL) { + } else if (argP1->GetValue() == keySTRGREATER_EQUAL) { result = (val >= 0); } else // strequal { @@ -628,13 +629,13 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); cmSystemTools::CompareOp op; - if (*argP1 == keyVERSION_LESS) { + if (argP1->GetValue() == keyVERSION_LESS) { op = cmSystemTools::OP_LESS; - } else if (*argP1 == keyVERSION_LESS_EQUAL) { + } else if (argP1->GetValue() == keyVERSION_LESS_EQUAL) { op = cmSystemTools::OP_LESS_EQUAL; - } else if (*argP1 == keyVERSION_GREATER) { + } else if (argP1->GetValue() == keyVERSION_GREATER) { op = cmSystemTools::OP_GREATER; - } else if (*argP1 == keyVERSION_GREATER_EQUAL) { + } else if (argP1->GetValue() == keyVERSION_GREATER_EQUAL) { op = cmSystemTools::OP_GREATER_EQUAL; } else { // version_equal op = cmSystemTools::OP_EQUAL; diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index cf00ede35c2..ce255192591 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include <cmext/string_view> + #include "cmExpandedCommandArgument.h" #include "cmListFileCache.h" #include "cmMessageType.h" @@ -36,7 +38,7 @@ class cmConditionEvaluator cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const; - bool IsKeyword(std::string const& keyword, + bool IsKeyword(cm::string_view keyword, cmExpandedCommandArgument& argument) const; bool GetBooleanValue(cmExpandedCommandArgument& arg) const; From 24cbfb8d964564711c764658a295abba560e837a Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 20:30:12 +0300 Subject: [PATCH 0999/1519] Refactor: Turn `reducible` flag into boolean Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 32 ++++++++++++++++---------------- Source/cmConditionEvaluator.h | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 29d7108fd8e..a6e814775d2 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -328,7 +328,7 @@ void cmConditionEvaluator::IncrementArguments( //========================================================================= // helper function to reduce code duplication void cmConditionEvaluator::HandlePredicate( - const bool value, int& reducible, cmArgumentList::iterator& arg, + const bool value, bool& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2) const { @@ -336,12 +336,12 @@ void cmConditionEvaluator::HandlePredicate( newArgs.erase(argP1); argP1 = arg; this->IncrementArguments(newArgs, argP1, argP2); - reducible = 1; + reducible = true; } //========================================================================= // helper function to reduce code duplication -void cmConditionEvaluator::HandleBinaryOp(const bool value, int& reducible, +void cmConditionEvaluator::HandleBinaryOp(const bool value, bool& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, @@ -352,7 +352,7 @@ void cmConditionEvaluator::HandleBinaryOp(const bool value, int& reducible, newArgs.erase(argP1); argP1 = arg; this->IncrementArguments(newArgs, argP1, argP2); - reducible = 1; + reducible = true; } //========================================================================= @@ -361,9 +361,9 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - int reducible; + bool reducible; do { - reducible = 0; + reducible = false; auto arg = newArgs.begin(); while (arg != newArgs.end()) { if (this->IsKeyword(keyParenL, *arg)) { @@ -414,9 +414,9 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, MessageType&) { - int reducible; + bool reducible; do { - reducible = 0; + reducible = false; auto arg = newArgs.begin(); cmArgumentList::iterator argP1; cmArgumentList::iterator argP2; @@ -513,12 +513,12 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - int reducible; + bool reducible; std::string def_buf; cmProp def; cmProp def2; do { - reducible = 0; + reducible = false; auto arg = newArgs.begin(); cmArgumentList::iterator argP1; cmArgumentList::iterator argP2; @@ -556,7 +556,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, newArgs.erase(argP1); argP1 = arg; this->IncrementArguments(newArgs, argP1, argP2); - reducible = 1; + reducible = true; } if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { @@ -564,7 +564,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, newArgs.erase(argP1); argP1 = arg; this->IncrementArguments(newArgs, argP1, argP2); - reducible = 1; + reducible = true; } if (argP1 != newArgs.end() && argP2 != newArgs.end() && @@ -694,9 +694,9 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - int reducible; + bool reducible; do { - reducible = 0; + reducible = false; auto arg = newArgs.begin(); cmArgumentList::iterator argP1; cmArgumentList::iterator argP2; @@ -720,11 +720,11 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - int reducible; + bool reducible; bool lhs; bool rhs; do { - reducible = 0; + reducible = false; auto arg = newArgs.begin(); cmArgumentList::iterator argP1; cmArgumentList::iterator argP2; diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index ce255192591..5d48ee81b10 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -55,12 +55,12 @@ class cmConditionEvaluator cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2) const; - void HandlePredicate(bool value, int& reducible, + void HandlePredicate(bool value, bool& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2) const; - void HandleBinaryOp(bool value, int& reducible, + void HandleBinaryOp(bool value, bool& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, cmArgumentList::iterator& argP2); From 0f65d0cd837c2c12f04e8e10cec6c49eade08f1d Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 20:54:29 +0300 Subject: [PATCH 1000/1519] Refactor: Turn the innter `while` loop in `HandleLevelN()` into `for` Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 40 +++++++++------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index a6e814775d2..ef51729cffa 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -317,8 +317,7 @@ void cmConditionEvaluator::IncrementArguments( cmArgumentList::iterator& argP2) const { if (argP1 != newArgs.end()) { - ++argP1; - argP2 = argP1; + argP2 = ++argP1; if (argP1 != newArgs.end()) { ++argP2; } @@ -364,8 +363,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, bool reducible; do { reducible = false; - auto arg = newArgs.begin(); - while (arg != newArgs.end()) { + for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) { if (this->IsKeyword(keyParenL, *arg)) { // search for the closing paren for this opening one cmArgumentList::iterator argClose; @@ -403,7 +401,6 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, // remove the now evaluated parenthetical expression newArgs.erase(argP1, argClose); } - ++arg; } } while (reducible); return true; @@ -417,11 +414,8 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, bool reducible; do { reducible = false; - auto arg = newArgs.begin(); - cmArgumentList::iterator argP1; - cmArgumentList::iterator argP2; - while (arg != newArgs.end()) { - argP1 = arg; + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; + arg != newArgs.end(); argP1 = ++arg) { this->IncrementArguments(newArgs, argP1, argP2); // does a file exist if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) { @@ -501,7 +495,6 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); } - ++arg; } } while (reducible); return true; @@ -519,11 +512,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, cmProp def2; do { reducible = false; - auto arg = newArgs.begin(); - cmArgumentList::iterator argP1; - cmArgumentList::iterator argP2; - while (arg != newArgs.end()) { - argP1 = arg; + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; + arg != newArgs.end(); argP1 = ++arg) { this->IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyMATCHES, *argP1)) { @@ -681,8 +671,6 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } } - - ++arg; } } while (reducible); return true; @@ -697,18 +685,14 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, bool reducible; do { reducible = false; - auto arg = newArgs.begin(); - cmArgumentList::iterator argP1; - cmArgumentList::iterator argP2; - while (arg != newArgs.end()) { - argP1 = arg; + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; + arg != newArgs.end(); argP1 = ++arg) { this->IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { bool rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); } - ++arg; } } while (reducible); return true; @@ -725,11 +709,8 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, bool rhs; do { reducible = false; - auto arg = newArgs.begin(); - cmArgumentList::iterator argP1; - cmArgumentList::iterator argP2; - while (arg != newArgs.end()) { - argP1 = arg; + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; + arg != newArgs.end(); argP1 = ++arg) { this->IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && this->IsKeyword(keyAND, *argP1) && argP2 != newArgs.end()) { @@ -750,7 +731,6 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, this->HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1, argP2); } - ++arg; } } while (reducible); return true; From 961df6cde60763dc77cafe6bf3a2704b52394a20 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 21:10:06 +0300 Subject: [PATCH 1001/1519] Refactor: Make `IncrementArguments()` the free function Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 43 +++++++++++++++++---------------- Source/cmConditionEvaluator.h | 4 --- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index ef51729cffa..50e7655b2b7 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -6,6 +6,7 @@ #include <cstdio> #include <cstdlib> #include <functional> +#include <iterator> #include <sstream> #include <utility> @@ -60,6 +61,19 @@ auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; std::array<const char* const, 2> const ZERO_ONE_XLAT = { "0", "1" }; +inline void IncrementArguments( + cmConditionEvaluator::cmArgumentList& newArgs, + cmConditionEvaluator::cmArgumentList::iterator& argP1, + cmConditionEvaluator::cmArgumentList::iterator& argP2) +{ + if (argP1 != newArgs.end()) { + argP2 = ++argP1; + using difference_type = + cmConditionEvaluator::cmArgumentList::difference_type; + std::advance(argP2, difference_type(argP1 != newArgs.end())); + } +} + } // anonymous namespace cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, @@ -311,19 +325,6 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( return newResult; } -//========================================================================= -void cmConditionEvaluator::IncrementArguments( - cmArgumentList& newArgs, cmArgumentList::iterator& argP1, - cmArgumentList::iterator& argP2) const -{ - if (argP1 != newArgs.end()) { - argP2 = ++argP1; - if (argP1 != newArgs.end()) { - ++argP2; - } - } -} - //========================================================================= // helper function to reduce code duplication void cmConditionEvaluator::HandlePredicate( @@ -334,7 +335,7 @@ void cmConditionEvaluator::HandlePredicate( *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); newArgs.erase(argP1); argP1 = arg; - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); reducible = true; } @@ -350,7 +351,7 @@ void cmConditionEvaluator::HandleBinaryOp(const bool value, bool& reducible, newArgs.erase(argP2); newArgs.erase(argP1); argP1 = arg; - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); reducible = true; } @@ -416,7 +417,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); // does a file exist if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) { this->HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), @@ -514,7 +515,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyMATCHES, *argP1)) { def = this->GetDefinitionIfUnquoted(*arg); @@ -545,7 +546,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, newArgs.erase(argP2); newArgs.erase(argP1); argP1 = arg; - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); reducible = true; } @@ -553,7 +554,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, *arg = cmExpandedCommandArgument("0", true); newArgs.erase(argP1); argP1 = arg; - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); reducible = true; } @@ -687,7 +688,7 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { bool rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); @@ -711,7 +712,7 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { - this->IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && this->IsKeyword(keyAND, *argP1) && argP2 != newArgs.end()) { lhs = diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 5d48ee81b10..74652a0e28b 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -51,10 +51,6 @@ class cmConditionEvaluator MessageType& status, bool oneArg = false) const; - void IncrementArguments(cmArgumentList& newArgs, - cmArgumentList::iterator& argP1, - cmArgumentList::iterator& argP2) const; - void HandlePredicate(bool value, bool& reducible, cmArgumentList::iterator& arg, cmArgumentList& newArgs, cmArgumentList::iterator& argP1, From 498c8c77732acf71e9a2f21afe37ee3f815b8801 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sat, 24 Jul 2021 22:45:09 +0300 Subject: [PATCH 1002/1519] Refactor: More `auto` and constness Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 60 +++++++++++++++------------------ 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 50e7655b2b7..ad1680455d2 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -23,8 +23,6 @@ #include "cmSystemTools.h" #include "cmake.h" -class cmTest; - namespace { auto const keyAND = "AND"_s; auto const keyCOMMAND = "COMMAND"_s; @@ -205,7 +203,7 @@ bool cmConditionEvaluator::IsKeyword(cm::string_view keyword, return false; } - const bool isKeyword = argument.GetValue() == keyword; + const auto isKeyword = argument.GetValue() == keyword; if (isKeyword && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { @@ -263,7 +261,7 @@ bool cmConditionEvaluator::GetBooleanValue( //========================================================================= // Boolean value behavior from CMake 2.6.4 and below. bool cmConditionEvaluator::GetBooleanValueOld( - cmExpandedCommandArgument const& arg, bool one) const + cmExpandedCommandArgument const& arg, bool const one) const { if (one) { // Old IsTrue behavior for single argument. @@ -278,7 +276,7 @@ bool cmConditionEvaluator::GetBooleanValueOld( } // Old GetVariableOrNumber behavior. cmProp def = this->GetDefinitionIfUnquoted(arg); - if (!def && atoi(arg.GetValue().c_str())) { + if (!def && std::atoi(arg.GetValue().c_str())) { def = &arg.GetValue(); } return !cmIsOff(def); @@ -288,7 +286,7 @@ bool cmConditionEvaluator::GetBooleanValueOld( // returns the resulting boolean value bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( cmExpandedCommandArgument& newArg, std::string& errorString, - MessageType& status, bool oneArg) const + MessageType& status, bool const oneArg) const { // Use the policy if it is set. if (this->Policy12Status == cmPolicies::NEW) { @@ -299,8 +297,8 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( } // Check policy only if old and new results differ. - const bool newResult = this->GetBooleanValue(newArg); - const bool oldResult = this->GetBooleanValueOld(newArg, oneArg); + const auto newResult = this->GetBooleanValue(newArg); + const auto oldResult = this->GetBooleanValueOld(newArg, oneArg); if (newResult != oldResult) { switch (this->Policy12Status) { case cmPolicies::WARN: @@ -370,7 +368,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, cmArgumentList::iterator argClose; argClose = arg; argClose++; - unsigned int depth = 1; + auto depth = 1u; while (argClose != newArgs.end() && depth) { if (this->IsKeyword(keyParenL, *argClose)) { depth++; @@ -389,16 +387,14 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, std::vector<cmExpandedCommandArgument> newArgs2; // copy to the list structure - auto argP1 = arg; - argP1++; + auto argP1 = std::next(arg); cm::append(newArgs2, argP1, argClose); newArgs2.pop_back(); // now recursively invoke IsTrue to handle the values inside the // parenthetical expression - const bool value = this->IsTrue(newArgs2, errorString, status); + const auto value = this->IsTrue(newArgs2, errorString, status); *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); - argP1 = arg; - argP1++; + argP1 = std::next(arg); // remove the now evaluated parenthetical expression newArgs.erase(argP1, argClose); } @@ -441,10 +437,9 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } // does a command exist if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) { - cmState::Command command = - this->Makefile.GetState()->GetCommand(argP1->GetValue()); - this->HandlePredicate(command != nullptr, reducible, arg, newArgs, - argP1, argP2); + this->HandlePredicate( + this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, + reducible, arg, newArgs, argP1, argP2); } // does a policy exist if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) { @@ -463,9 +458,9 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, if (this->Policy64Status != cmPolicies::OLD && this->Policy64Status != cmPolicies::WARN) { if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) { - const cmTest* haveTest = this->Makefile.GetTest(argP1->GetValue()); - this->HandlePredicate(haveTest != nullptr, reducible, arg, newArgs, - argP1, argP2); + this->HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != + nullptr, + reducible, arg, newArgs, argP1, argP2); } } else if (this->Policy64Status == cmPolicies::WARN && this->IsKeyword(keyTEST, *arg)) { @@ -479,16 +474,16 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } // is a variable defined if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) { - const size_t argP1len = argP1->GetValue().size(); - bool bdef = false; + const auto argP1len = argP1->GetValue().size(); + auto bdef = false; if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && argP1->GetValue().operator[](argP1len - 1) == '}') { - std::string env = argP1->GetValue().substr(4, argP1len - 5); + const auto env = argP1->GetValue().substr(4, argP1len - 5); bdef = cmSystemTools::HasEnv(env); } else if (argP1len > 6 && cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") && argP1->GetValue().operator[](argP1len - 1) == '}') { - std::string cache = argP1->GetValue().substr(6, argP1len - 7); + const auto cache = argP1->GetValue().substr(6, argP1len - 7); bdef = this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr; } else { @@ -527,7 +522,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def_buf = *def; def = &def_buf; } - const std::string& rex = argP2->GetValue(); + const auto& rex = argP2->GetValue(); this->Makefile.ClearMatches(); cmsys::RegularExpression regEntry; if (!regEntry.compile(rex)) { @@ -631,7 +626,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else { // version_equal op = cmSystemTools::OP_EQUAL; } - const bool result = + const auto result = cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } @@ -639,9 +634,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, // is file A newer than file B if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { - int fileIsNewer = 0; + auto fileIsNewer = 0; cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( - arg->GetValue(), (argP2)->GetValue(), &fileIsNewer); + arg->GetValue(), argP2->GetValue(), &fileIsNewer); this->HandleBinaryOp( (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg, newArgs, argP1, argP2); @@ -651,14 +646,13 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keyIN_LIST, *argP1)) { if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { - bool result = false; + auto result = false; def = this->GetVariableOrString(*arg); def2 = this->Makefile.GetDefinition(argP2->GetValue()); if (def2) { - std::vector<std::string> list = cmExpandedList(*def2, true); - result = cm::contains(list, *def); + result = cm::contains(cmExpandedList(*def2, true), *def); } this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); @@ -690,7 +684,7 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, arg != newArgs.end(); argP1 = ++arg) { IncrementArguments(newArgs, argP1, argP2); if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { - bool rhs = this->GetBooleanValueWithAutoDereference( + const auto rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); } From 135c37bdd73a8de5a2da43e652f26948481dd936 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 21:27:56 +0300 Subject: [PATCH 1003/1519] Refactor: Make `HandleBinaryOp` and `HandlePredicate` free functions --- Source/cmConditionEvaluator.cxx | 112 +++++++++++++++----------------- Source/cmConditionEvaluator.h | 10 --- 2 files changed, 52 insertions(+), 70 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index ad1680455d2..be7ae88260b 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -72,6 +72,33 @@ inline void IncrementArguments( } } +void HandlePredicate(const bool value, bool& reducible, + cmConditionEvaluator::cmArgumentList::iterator& arg, + cmConditionEvaluator::cmArgumentList& newArgs, + cmConditionEvaluator::cmArgumentList::iterator& argP1, + cmConditionEvaluator::cmArgumentList::iterator& argP2) +{ + *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs, argP1, argP2); + reducible = true; +} + +void HandleBinaryOp(const bool value, bool& reducible, + cmConditionEvaluator::cmArgumentList::iterator& arg, + cmConditionEvaluator::cmArgumentList& newArgs, + cmConditionEvaluator::cmArgumentList::iterator& argP1, + cmConditionEvaluator::cmArgumentList::iterator& argP2) +{ + *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); + newArgs.erase(argP2); + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs, argP1, argP2); + reducible = true; +} + } // anonymous namespace cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, @@ -323,36 +350,6 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( return newResult; } -//========================================================================= -// helper function to reduce code duplication -void cmConditionEvaluator::HandlePredicate( - const bool value, bool& reducible, cmArgumentList::iterator& arg, - cmArgumentList& newArgs, cmArgumentList::iterator& argP1, - cmArgumentList::iterator& argP2) const -{ - *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); - reducible = true; -} - -//========================================================================= -// helper function to reduce code duplication -void cmConditionEvaluator::HandleBinaryOp(const bool value, bool& reducible, - cmArgumentList::iterator& arg, - cmArgumentList& newArgs, - cmArgumentList::iterator& argP1, - cmArgumentList::iterator& argP2) -{ - *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); - newArgs.erase(argP2); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); - reducible = true; -} - //========================================================================= // level 0 processes parenthetical expressions bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, @@ -416,51 +413,49 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, IncrementArguments(newArgs, argP1, argP2); // does a file exist if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), + reducible, arg, newArgs, argP1, argP2); } // does a directory with this name exist if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate( - cmSystemTools::FileIsDirectory(argP1->GetValue()), reducible, arg, - newArgs, argP1, argP2); + HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), + reducible, arg, newArgs, argP1, argP2); } // does a symlink with this name exist if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), + reducible, arg, newArgs, argP1, argP2); } // is the given path an absolute path ? if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), + reducible, arg, newArgs, argP1, argP2); } // does a command exist if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate( + HandlePredicate( this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, reducible, arg, newArgs, argP1, argP2); } // does a policy exist if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) { cmPolicies::PolicyID pid; - this->HandlePredicate( + HandlePredicate( cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible, arg, newArgs, argP1, argP2); } // does a target exist if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate( - this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1, argP2); + HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != + nullptr, + reducible, arg, newArgs, argP1, argP2); } // does a test exist if (this->Policy64Status != cmPolicies::OLD && this->Policy64Status != cmPolicies::WARN) { if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) { - this->HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != - nullptr, - reducible, arg, newArgs, argP1, argP2); + HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, + reducible, arg, newArgs, argP1, argP2); } } else if (this->Policy64Status == cmPolicies::WARN && this->IsKeyword(keyTEST, *arg)) { @@ -489,7 +484,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } else { bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); } - this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); + HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); } } } while (reducible); @@ -578,7 +573,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else { result = (lhs == rhs); } - this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } if (argP1 != newArgs.end() && argP2 != newArgs.end() && @@ -603,7 +598,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, { result = (val == 0); } - this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } if (argP1 != newArgs.end() && argP2 != newArgs.end() && @@ -628,7 +623,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } const auto result = cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); - this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } // is file A newer than file B @@ -637,9 +632,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, auto fileIsNewer = 0; cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( arg->GetValue(), argP2->GetValue(), &fileIsNewer); - this->HandleBinaryOp( - (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg, - newArgs, argP1, argP2); + HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), + reducible, arg, newArgs, argP1, argP2); } if (argP1 != newArgs.end() && argP2 != newArgs.end() && @@ -655,7 +649,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, result = cm::contains(cmExpandedList(*def2, true), *def); } - this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n"; @@ -686,7 +680,7 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { const auto rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); - this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); + HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); } } } while (reducible); @@ -713,8 +707,7 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, this->GetBooleanValueWithAutoDereference(*arg, errorString, status); rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString, status); - this->HandleBinaryOp((lhs && rhs), reducible, arg, newArgs, argP1, - argP2); + HandleBinaryOp((lhs && rhs), reducible, arg, newArgs, argP1, argP2); } if (argP1 != newArgs.end() && this->IsKeyword(keyOR, *argP1) && @@ -723,8 +716,7 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, this->GetBooleanValueWithAutoDereference(*arg, errorString, status); rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString, status); - this->HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1, - argP2); + HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1, argP2); } } } while (reducible); diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 74652a0e28b..af0dc5cb403 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -51,16 +51,6 @@ class cmConditionEvaluator MessageType& status, bool oneArg = false) const; - void HandlePredicate(bool value, bool& reducible, - cmArgumentList::iterator& arg, cmArgumentList& newArgs, - cmArgumentList::iterator& argP1, - cmArgumentList::iterator& argP2) const; - - void HandleBinaryOp(bool value, bool& reducible, - cmArgumentList::iterator& arg, cmArgumentList& newArgs, - cmArgumentList::iterator& argP1, - cmArgumentList::iterator& argP2); - bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString, MessageType& status); From 95fc27cedde069c884d151644bf1e7ef105dc7da Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sun, 25 Jul 2021 03:41:26 +0300 Subject: [PATCH 1004/1519] Refactor: Rewrite parenthesis scanner to avoid `if`s Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index be7ae88260b..ef055605f1b 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -362,18 +362,11 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) { if (this->IsKeyword(keyParenL, *arg)) { // search for the closing paren for this opening one - cmArgumentList::iterator argClose; - argClose = arg; - argClose++; - auto depth = 1u; - while (argClose != newArgs.end() && depth) { - if (this->IsKeyword(keyParenL, *argClose)) { - depth++; - } - if (this->IsKeyword(keyParenR, *argClose)) { - depth--; - } - argClose++; + auto depth = 1; + auto argClose = std::next(arg); + for (; argClose != newArgs.end() && depth; ++argClose) { + depth += int(this->IsKeyword(keyParenL, *argClose)) - + int(this->IsKeyword(keyParenR, *argClose)); } if (depth) { errorString = "mismatched parenthesis in condition"; From 314538703a4c70a45dc7679af6eb0c46f39ee3e4 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sun, 25 Jul 2021 03:50:52 +0300 Subject: [PATCH 1005/1519] Refactor: Deduplicate code for `AND` and `OR` handling in `if()` command Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index ef055605f1b..3def347f81e 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -687,29 +687,22 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, MessageType& status) { bool reducible; - bool lhs; - bool rhs; do { reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { IncrementArguments(newArgs, argP1, argP2); - if (argP1 != newArgs.end() && this->IsKeyword(keyAND, *argP1) && + if (argP1 != newArgs.end() && + (this->IsKeyword(keyAND, *argP1) || + this->IsKeyword(keyOR, *argP1)) && argP2 != newArgs.end()) { - lhs = + const auto lhs = this->GetBooleanValueWithAutoDereference(*arg, errorString, status); - rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString, - status); - HandleBinaryOp((lhs && rhs), reducible, arg, newArgs, argP1, argP2); - } - - if (argP1 != newArgs.end() && this->IsKeyword(keyOR, *argP1) && - argP2 != newArgs.end()) { - lhs = - this->GetBooleanValueWithAutoDereference(*arg, errorString, status); - rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString, - status); - HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1, argP2); + const auto rhs = this->GetBooleanValueWithAutoDereference( + *argP2, errorString, status); + HandleBinaryOp(this->IsKeyword(keyAND, *argP1) ? (lhs && rhs) + : (lhs || rhs), + reducible, arg, newArgs, argP1, argP2); } } } while (reducible); From 7bec39dc10e821571785e503a1c14f09db8004a9 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sun, 25 Jul 2021 03:54:44 +0300 Subject: [PATCH 1006/1519] Style: Add empty lines to increase readability Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 3def347f81e..9183a44e73b 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -403,7 +403,9 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { + IncrementArguments(newArgs, argP1, argP2); + // does a file exist if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) { HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), @@ -498,10 +500,14 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { + IncrementArguments(newArgs, argP1, argP2); + if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyMATCHES, *argP1)) { + def = this->GetDefinitionIfUnquoted(*arg); + if (!def) { def = &arg->GetValue(); } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { @@ -510,6 +516,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def_buf = *def; def = &def_buf; } + const auto& rex = argP2->GetValue(); this->Makefile.ClearMatches(); cmsys::RegularExpression regEntry; @@ -520,12 +527,14 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, status = MessageType::FATAL_ERROR; return false; } + if (regEntry.find(*def)) { this->Makefile.StoreMatches(regEntry); *arg = cmExpandedCommandArgument("1", true); } else { *arg = cmExpandedCommandArgument("0", true); } + newArgs.erase(argP2); newArgs.erase(argP1); argP1 = arg; @@ -547,8 +556,10 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keyGREATER, *argP1) || this->IsKeyword(keyGREATER_EQUAL, *argP1) || this->IsKeyword(keyEQUAL, *argP1))) { + def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); + double lhs; double rhs; bool result; @@ -575,9 +586,11 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keySTRGREATER, *argP1) || this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || this->IsKeyword(keySTREQUAL, *argP1))) { + def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); const int val = (*def).compare(*def2); + bool result; if (argP1->GetValue() == keySTRLESS) { result = (val < 0); @@ -600,8 +613,10 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keyVERSION_GREATER, *argP1) || this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || this->IsKeyword(keyVERSION_EQUAL, *argP1))) { + def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); + cmSystemTools::CompareOp op; if (argP1->GetValue() == keyVERSION_LESS) { op = cmSystemTools::OP_LESS; @@ -631,6 +646,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyIN_LIST, *argP1)) { + if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { auto result = false; @@ -669,7 +685,9 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { + IncrementArguments(newArgs, argP1, argP2); + if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { const auto rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); @@ -691,7 +709,9 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, reducible = false; for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { + IncrementArguments(newArgs, argP1, argP2); + if (argP1 != newArgs.end() && (this->IsKeyword(keyAND, *argP1) || this->IsKeyword(keyOR, *argP1)) && From bf2fe903728a56755d045c768fc6cc0d46845cc5 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 21:45:03 +0300 Subject: [PATCH 1007/1519] Refactor: Speedup predicates and binary operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before predicates and binary ops reducers use series of `if ()` blocks to match the keywords. However, if matched the currect `arg` get replaced with evaluation result, so further `if (<match-another-keyword>)` is just wasting time/resources. This patch introduce a chain of `if` → `else if` → ..., so after first match the loop restarts w/ the next argument. --- Source/cmConditionEvaluator.cxx | 109 ++++++++++++++++++-------------- Source/cmConditionEvaluator.h | 2 +- 2 files changed, 61 insertions(+), 50 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 9183a44e73b..059378659f5 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -221,7 +221,7 @@ cmProp cmConditionEvaluator::GetVariableOrString( } //========================================================================= -bool cmConditionEvaluator::IsKeyword(cm::string_view keyword, +bool cmConditionEvaluator::IsKeyword(cm::static_string_view keyword, cmExpandedCommandArgument& argument) const { if ((this->Policy54Status != cmPolicies::WARN && @@ -406,64 +406,67 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, IncrementArguments(newArgs, argP1, argP2); + // NOTE This is the only predicate that dones't need the next argument... + // Check it first! + // does a test exist (CMP0064 == WARN case) + if (this->Policy64Status == cmPolicies::WARN && + this->IsKeyword(keyTEST, *arg)) { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n"; + e << "TEST will be interpreted as an operator " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; + + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + } + + // NOTE Fail fast: All the predicates below require the next arg to be + // valid + if (argP1 == newArgs.end()) { + continue; + } + // does a file exist - if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) { + if (this->IsKeyword(keyEXISTS, *arg)) { HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // does a directory with this name exist - if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // does a symlink with this name exist - if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // is the given path an absolute path ? - if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), reducible, arg, newArgs, argP1, argP2); } // does a command exist - if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyCOMMAND, *arg)) { HandlePredicate( this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, reducible, arg, newArgs, argP1, argP2); } // does a policy exist - if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyPOLICY, *arg)) { cmPolicies::PolicyID pid; HandlePredicate( cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible, arg, newArgs, argP1, argP2); } // does a target exist - if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyTARGET, *arg)) { HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr, reducible, arg, newArgs, argP1, argP2); } - // does a test exist - if (this->Policy64Status != cmPolicies::OLD && - this->Policy64Status != cmPolicies::WARN) { - if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) { - HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1, argP2); - } - } else if (this->Policy64Status == cmPolicies::WARN && - this->IsKeyword(keyTEST, *arg)) { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n"; - e << "TEST will be interpreted as an operator " - "when the policy is set to NEW. " - "Since the policy is not set the OLD behavior will be used."; - - this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); - } // is a variable defined - if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) { + else if (this->IsKeyword(keyDEFINED, *arg)) { const auto argP1len = argP1->GetValue().size(); auto bdef = false; if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && @@ -481,6 +484,14 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); } + // does a test exist + else if (this->Policy64Status != cmPolicies::OLD && + this->Policy64Status != cmPolicies::WARN) { + if (this->IsKeyword(keyTEST, *arg)) { + HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, + reducible, arg, newArgs, argP1, argP2); + } + } } } while (reducible); return true; @@ -542,7 +553,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, reducible = true; } - if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { + else if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { *arg = cmExpandedCommandArgument("0", true); newArgs.erase(argP1); argP1 = arg; @@ -550,12 +561,16 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, reducible = true; } - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (this->IsKeyword(keyLESS, *argP1) || - this->IsKeyword(keyLESS_EQUAL, *argP1) || - this->IsKeyword(keyGREATER, *argP1) || - this->IsKeyword(keyGREATER_EQUAL, *argP1) || - this->IsKeyword(keyEQUAL, *argP1))) { + // NOTE Fail fast: All the binary ops below require 2 arguments. + else if (argP1 == newArgs.end() || argP2 == newArgs.end()) { + continue; + } + + else if (this->IsKeyword(keyLESS, *argP1) || + this->IsKeyword(keyLESS_EQUAL, *argP1) || + this->IsKeyword(keyGREATER, *argP1) || + this->IsKeyword(keyGREATER_EQUAL, *argP1) || + this->IsKeyword(keyEQUAL, *argP1)) { def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); @@ -580,12 +595,11 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (this->IsKeyword(keySTRLESS, *argP1) || - this->IsKeyword(keySTRLESS_EQUAL, *argP1) || - this->IsKeyword(keySTRGREATER, *argP1) || - this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || - this->IsKeyword(keySTREQUAL, *argP1))) { + else if (this->IsKeyword(keySTRLESS, *argP1) || + this->IsKeyword(keySTRLESS_EQUAL, *argP1) || + this->IsKeyword(keySTRGREATER, *argP1) || + this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || + this->IsKeyword(keySTREQUAL, *argP1)) { def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); @@ -607,12 +621,11 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (this->IsKeyword(keyVERSION_LESS, *argP1) || - this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) || - this->IsKeyword(keyVERSION_GREATER, *argP1) || - this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || - this->IsKeyword(keyVERSION_EQUAL, *argP1))) { + else if (this->IsKeyword(keyVERSION_LESS, *argP1) || + this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) || + this->IsKeyword(keyVERSION_GREATER, *argP1) || + this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || + this->IsKeyword(keyVERSION_EQUAL, *argP1)) { def = this->GetVariableOrString(*arg); def2 = this->GetVariableOrString(*argP2); @@ -635,8 +648,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } // is file A newer than file B - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { + else if (this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { auto fileIsNewer = 0; cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( arg->GetValue(), argP2->GetValue(), &fileIsNewer); @@ -644,8 +656,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, reducible, arg, newArgs, argP1, argP2); } - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - this->IsKeyword(keyIN_LIST, *argP1)) { + else if (this->IsKeyword(keyIN_LIST, *argP1)) { if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index af0dc5cb403..a7e3ce87ac8 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -38,7 +38,7 @@ class cmConditionEvaluator cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const; - bool IsKeyword(cm::string_view keyword, + bool IsKeyword(cm::static_string_view keyword, cmExpandedCommandArgument& argument) const; bool GetBooleanValue(cmExpandedCommandArgument& arg) const; From 9946ff68481a1d02a75b646f3b275f98ca616d64 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Sun, 25 Jul 2021 19:07:36 +0300 Subject: [PATCH 1008/1519] Refactor: Initialize args vector from iterators instead of copy Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 059378659f5..871acd16371 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -374,12 +374,10 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, return false; } // store the reduced args in this vector - std::vector<cmExpandedCommandArgument> newArgs2; - - // copy to the list structure auto argP1 = std::next(arg); - cm::append(newArgs2, argP1, argClose); + std::vector<cmExpandedCommandArgument> newArgs2{ argP1, argClose }; newArgs2.pop_back(); + // now recursively invoke IsTrue to handle the values inside the // parenthetical expression const auto value = this->IsTrue(newArgs2, errorString, status); From 8bc4a740d648e59d6712bbaea0cae8e03fc97a25 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 21:52:24 +0300 Subject: [PATCH 1009/1519] Refactor: When handle predicates, there is no need to check 2nd arg Introduce an overload for `IncrementArguments()` w/ one iterator and use it in the handler level 1. --- Source/cmConditionEvaluator.cxx | 64 +++++++++++++++++---------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 871acd16371..c4d945bd150 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -59,29 +59,34 @@ auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; std::array<const char* const, 2> const ZERO_ONE_XLAT = { "0", "1" }; -inline void IncrementArguments( - cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator& argP1, - cmConditionEvaluator::cmArgumentList::iterator& argP2) +void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, + cmConditionEvaluator::cmArgumentList::iterator& argP1) { - if (argP1 != newArgs.end()) { - argP2 = ++argP1; - using difference_type = - cmConditionEvaluator::cmArgumentList::difference_type; - std::advance(argP2, difference_type(argP1 != newArgs.end())); - } + using difference_type = + cmConditionEvaluator::cmArgumentList::difference_type; + std::advance(argP1, difference_type(argP1 != newArgs.end())); +} + +void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, + cmConditionEvaluator::cmArgumentList::iterator& argP1, + cmConditionEvaluator::cmArgumentList::iterator& argP2) +{ + IncrementArguments(newArgs, argP1); + argP2 = argP1; + using difference_type = + cmConditionEvaluator::cmArgumentList::difference_type; + std::advance(argP2, difference_type(argP1 != newArgs.end())); } void HandlePredicate(const bool value, bool& reducible, cmConditionEvaluator::cmArgumentList::iterator& arg, cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator& argP1, - cmConditionEvaluator::cmArgumentList::iterator& argP2) + cmConditionEvaluator::cmArgumentList::iterator& argP1) { *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); newArgs.erase(argP1); argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1); reducible = true; } @@ -98,7 +103,6 @@ void HandleBinaryOp(const bool value, bool& reducible, IncrementArguments(newArgs, argP1, argP2); reducible = true; } - } // anonymous namespace cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, @@ -399,10 +403,10 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, bool reducible; do { reducible = false; - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; - arg != newArgs.end(); argP1 = ++arg) { + for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); + argP1 = ++arg) { - IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1); // NOTE This is the only predicate that dones't need the next argument... // Check it first! @@ -427,41 +431,41 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, // does a file exist if (this->IsKeyword(keyEXISTS, *arg)) { HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } // does a directory with this name exist else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } // does a symlink with this name exist else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } // is the given path an absolute path ? else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } // does a command exist else if (this->IsKeyword(keyCOMMAND, *arg)) { HandlePredicate( this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } // does a policy exist else if (this->IsKeyword(keyPOLICY, *arg)) { cmPolicies::PolicyID pid; HandlePredicate( cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible, - arg, newArgs, argP1, argP2); + arg, newArgs, argP1); } // does a target exist else if (this->IsKeyword(keyTARGET, *arg)) { HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } // is a variable defined else if (this->IsKeyword(keyDEFINED, *arg)) { @@ -480,14 +484,14 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } else { bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); } - HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); + HandlePredicate(bdef, reducible, arg, newArgs, argP1); } // does a test exist else if (this->Policy64Status != cmPolicies::OLD && this->Policy64Status != cmPolicies::WARN) { if (this->IsKeyword(keyTEST, *arg)) { HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1, argP2); + reducible, arg, newArgs, argP1); } } } @@ -692,15 +696,15 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, bool reducible; do { reducible = false; - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; - arg != newArgs.end(); argP1 = ++arg) { + for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); + argP1 = ++arg) { - IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1); if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { const auto rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); - HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); + HandlePredicate(!rhs, reducible, arg, newArgs, argP1); } } } while (reducible); From 18bd6c98ea70adf3067539266fdb782e910fb3cc Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 21:56:52 +0300 Subject: [PATCH 1010/1519] Refactor: Generalize policy checking in `HandleLevel1` Also, move OLD policy checking out of the loop to evaluate it once. --- Source/cmConditionEvaluator.cxx | 43 +++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index c4d945bd150..99927d7db2c 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -400,6 +400,9 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, MessageType&) { + const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD || + this->Policy64Status == cmPolicies::WARN; + bool reducible; do { reducible = false; @@ -407,20 +410,24 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, argP1 = ++arg) { IncrementArguments(newArgs, argP1); + auto policyCheck = [&, this](const cmPolicies::PolicyID id, + const cmPolicies::PolicyStatus status, + const cm::static_string_view kw) { + if (status == cmPolicies::WARN && this->IsKeyword(kw, *arg)) { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(id) << "\n" + << kw + << " will be interpreted as an operator " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; - // NOTE This is the only predicate that dones't need the next argument... - // Check it first! - // does a test exist (CMP0064 == WARN case) - if (this->Policy64Status == cmPolicies::WARN && - this->IsKeyword(keyTEST, *arg)) { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n"; - e << "TEST will be interpreted as an operator " - "when the policy is set to NEW. " - "Since the policy is not set the OLD behavior will be used."; - - this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); - } + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + } + }; + + // NOTE Checking policies for warnings are not require an access to the + // next arg. Check them first! + policyCheck(cmPolicies::CMP0064, this->Policy64Status, keyTEST); // NOTE Fail fast: All the predicates below require the next arg to be // valid @@ -487,12 +494,12 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, HandlePredicate(bdef, reducible, arg, newArgs, argP1); } // does a test exist - else if (this->Policy64Status != cmPolicies::OLD && - this->Policy64Status != cmPolicies::WARN) { - if (this->IsKeyword(keyTEST, *arg)) { - HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1); + else if (this->IsKeyword(keyTEST, *arg)) { + if (policy64IsOld) { + continue; } + HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, + reducible, arg, newArgs, argP1); } } } while (reducible); From c15bb6f8b8c2eac691138e35d96570d537cc6d69 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 27 Jul 2021 00:01:08 -0400 Subject: [PATCH 1011/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7345e44242e..ee3ffb769bf 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210726) +set(CMake_VERSION_PATCH 20210727) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f7cf69e34a1607e8ea2b6d10fef6a6058377c24e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 27 Jul 2021 09:29:13 -0400 Subject: [PATCH 1012/1519] CMake 3.21.1 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 590cf9cac54..88263e06899 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_PATCH 1) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 92edd7376bf18f3cf467cfd28a88b7372b5e0f50 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Tue, 27 Jul 2021 16:26:27 +0300 Subject: [PATCH 1013/1519] FindBLAS: Fix regression in finding EML_mt after recent refactoring Fix a variable referenced missed by commit 76487b04b1 (Find{BLAS,LAPACK}: clean variables, 2021-07-13). --- Modules/FindBLAS.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 0898240edf1..29150c1e526 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -1094,7 +1094,7 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") # Check for OpenMP support, VIA BLA_VENDOR of eml_mt if(BLA_VENDOR MATCHES "_mt") - set(_blas_eml_lib "${BLAS_EML_LIB}_mt") + set(_blas_eml_lib "${_blas_eml_lib}_mt") endif() if(NOT BLAS_LIBRARIES) From a7f6e5dbf90f94cd2bdb4576650bf662755e8d9c Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Tue, 27 Jul 2021 16:30:08 +0300 Subject: [PATCH 1014/1519] FindBLAS: use unset instead of set for empty variables --- Modules/FindBLAS.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 29150c1e526..799d1795959 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -759,7 +759,7 @@ if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All") "" ) endif() - set(_blas_armpl_lib) + unset(_blas_armpl_lib) endif() # FLAME's blis library? (https://github.com/flame/blis) @@ -1109,7 +1109,7 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") "" ) endif() - set(_blas_eml_lib) + unset(_blas_eml_lib) endif() # Fujitsu SSL2 Library? From 3e42bf3e0575d8e203405d95fd24065ea6b70495 Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Tue, 27 Jul 2021 11:45:57 -0400 Subject: [PATCH 1015/1519] CMakePresets: Check presets with their own file version 06e6981 added support for optional binaryDir and generator, but use the dependent preset's file version instead of the current preset's file version. Check presets with their own file version instead of their dependent's file version. Fixes: #22428 --- Source/cmCMakePresetsFile.cxx | 10 +++++----- Tests/RunCMake/CMakePresets/RunCMakeTest.cmake | 1 + Tests/RunCMake/CMakePresets/V2InheritV3Optional.cmake | 0 .../RunCMake/CMakePresets/V2InheritV3Optional.json.in | 8 ++++++++ .../CMakePresets/V2InheritV3OptionalUser.json.in | 11 +++++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 Tests/RunCMake/CMakePresets/V2InheritV3Optional.cmake create mode 100644 Tests/RunCMake/CMakePresets/V2InheritV3Optional.json.in create mode 100644 Tests/RunCMake/CMakePresets/V2InheritV3OptionalUser.json.in diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx index fd578faef79..538b668059d 100644 --- a/Source/cmCMakePresetsFile.cxx +++ b/Source/cmCMakePresetsFile.cxx @@ -78,7 +78,8 @@ void InheritVector(std::vector<T>& child, const std::vector<T>& parent) template <class T> ReadFileResult VisitPreset( T& preset, std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets, - std::map<std::string, CycleStatus> cycleStatus, int version) + std::map<std::string, CycleStatus> cycleStatus, + const cmCMakePresetsFile& file) { switch (cycleStatus[preset.Name]) { case CycleStatus::InProgress: @@ -108,7 +109,7 @@ ReadFileResult VisitPreset( return ReadFileResult::USER_PRESET_INHERITANCE; } - auto result = VisitPreset(parentPreset, presets, cycleStatus, version); + auto result = VisitPreset(parentPreset, presets, cycleStatus, file); if (result != ReadFileResult::READ_OK) { return result; } @@ -128,7 +129,7 @@ ReadFileResult VisitPreset( preset.ConditionEvaluator.reset(); } - CHECK_OK(preset.VisitPresetAfterInherit(version)) + CHECK_OK(preset.VisitPresetAfterInherit(file.GetVersion(preset))) cycleStatus[preset.Name] = CycleStatus::Verified; return ReadFileResult::READ_OK; @@ -146,8 +147,7 @@ ReadFileResult ComputePresetInheritance( for (auto& it : presets) { auto& preset = it.second.Unexpanded; - auto result = - VisitPreset<T>(preset, presets, cycleStatus, file.GetVersion(preset)); + auto result = VisitPreset<T>(preset, presets, cycleStatus, file); if (result != ReadFileResult::READ_OK) { return result; } diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 31bd8a44536..c31a645bcaf 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -260,6 +260,7 @@ unset(CMakePresets_FILE) run_cmake_presets(GoodUserOnly) run_cmake_presets(GoodUserFromMain) run_cmake_presets(GoodUserFromUser) +run_cmake_presets(V2InheritV3Optional) # Test CMakeUserPresets.json errors run_cmake_presets(UserDuplicateInUser) diff --git a/Tests/RunCMake/CMakePresets/V2InheritV3Optional.cmake b/Tests/RunCMake/CMakePresets/V2InheritV3Optional.cmake new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/CMakePresets/V2InheritV3Optional.json.in b/Tests/RunCMake/CMakePresets/V2InheritV3Optional.json.in new file mode 100644 index 00000000000..957b157dea8 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/V2InheritV3Optional.json.in @@ -0,0 +1,8 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/V2InheritV3OptionalUser.json.in b/Tests/RunCMake/CMakePresets/V2InheritV3OptionalUser.json.in new file mode 100644 index 00000000000..f18c1b957e4 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/V2InheritV3OptionalUser.json.in @@ -0,0 +1,11 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "V2InheritV3Optional", + "inherits": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ] +} From 73e452eb98ecea915164444a417b9c18a0a84e82 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Tue, 27 Jul 2021 20:15:10 +0300 Subject: [PATCH 1016/1519] FindBLAS: IBM ESSL 6.1 does not required BLAS lib --- Modules/FindBLAS.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 799d1795959..0d95723f412 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -893,7 +893,7 @@ if(BLA_VENDOR STREQUAL "SGIMATH" OR BLA_VENDOR STREQUAL "All") endif() endif() -# BLAS in IBM ESSL library? (requires generic BLAS lib, too) +# BLAS in IBM ESSL library? if(BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) check_blas_libraries( @@ -901,7 +901,7 @@ if(BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All") BLAS sgemm "" - "essl;blas" + "essl" "" "" "" From ccb85f8943746fefac9f9e6f6e69e9074d243484 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Tue, 27 Jul 2021 20:22:30 +0300 Subject: [PATCH 1017/1519] FindBLAS: Add possibility to find OMP parallelized version of ESSL --- Modules/FindBLAS.cmake | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 0d95723f412..2ea6d984e16 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -109,7 +109,8 @@ BLAS/LAPACK Vendors ``Goto`` GotoBLAS -``IBMESSL`` +``IBMESSL``, ``IBMESSL_SMP`` + IBM Engineering and Scientific Subroutine Library ``Intel`` @@ -894,19 +895,26 @@ if(BLA_VENDOR STREQUAL "SGIMATH" OR BLA_VENDOR STREQUAL "All") endif() # BLAS in IBM ESSL library? -if(BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All") +if(BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All") + set(_blas_essl_lib "essl") + + if(BLA_VENDOR MATCHES "_SMP") + set(_blas_essl_lib "${_blas_essl_lib}smp") + endif() if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS sgemm "" - "essl" + "${_blas_essl_lib}" "" "" "" ) endif() + + unset(_blas_essl_lib) endif() # BLAS in acml library? From d6299d9941644e1bb36d274597e53a4c9e12f3bf Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Wed, 28 Jul 2021 01:53:22 +0300 Subject: [PATCH 1018/1519] Refactor: Run CPU/OS/Memory tests once on first run --- Source/cmCMakeHostSystemInformationCommand.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 05505688764..10c07146f9f 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -45,10 +45,14 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, return false; } - cmsys::SystemInformation info; - info.RunCPUCheck(); - info.RunOSCheck(); - info.RunMemoryCheck(); + static cmsys::SystemInformation info; + static auto initialized = false; + if (!initialized) { + info.RunCPUCheck(); + info.RunOSCheck(); + info.RunMemoryCheck(); + initialized = true; + } std::string result_list; for (size_t i = current_index + 1; i < args.size(); ++i) { From d6b4982697d74a0077f7f3c57f5078449b41e8ef Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Wed, 28 Jul 2021 04:38:26 +0300 Subject: [PATCH 1019/1519] Refactor: Move module private functions on top --- .../cmCMakeHostSystemInformationCommand.cxx | 116 ++++++++---------- 1 file changed, 54 insertions(+), 62 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 10c07146f9f..2a0b0b86682 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -9,7 +9,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#if defined(_WIN32) +#ifdef _WIN32 # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" # include "cmGlobalVisualStudioVersionedGenerator.h" @@ -19,60 +19,21 @@ #endif namespace { -bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, - std::string const& key, std::string& value); -std::string ValueToString(size_t value); -std::string ValueToString(const char* value); -std::string ValueToString(std::string const& value); +// BEGIN Private functions +std::string ValueToString(std::size_t const value) +{ + return std::to_string(value); } -// cmCMakeHostSystemInformation -bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, - cmExecutionStatus& status) +std::string ValueToString(const char* const value) { - size_t current_index = 0; - - if (args.size() < (current_index + 2) || args[current_index] != "RESULT") { - status.SetError("missing RESULT specification."); - return false; - } - - std::string const& variable = args[current_index + 1]; - current_index += 2; - - if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { - status.SetError("missing QUERY specification"); - return false; - } - - static cmsys::SystemInformation info; - static auto initialized = false; - if (!initialized) { - info.RunCPUCheck(); - info.RunOSCheck(); - info.RunMemoryCheck(); - initialized = true; - } - - std::string result_list; - for (size_t i = current_index + 1; i < args.size(); ++i) { - std::string const& key = args[i]; - if (i != current_index + 1) { - result_list += ";"; - } - std::string value; - if (!GetValue(status, info, key, value)) { - return false; - } - result_list += value; - } - - status.GetMakefile().AddDefinition(variable, result_list); - - return true; + return value ? value : std::string{}; } -namespace { +std::string ValueToString(std::string const& value) +{ + return value; +} bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, std::string const& key, std::string& value) @@ -200,20 +161,51 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, return true; } +// END Private functions +} // anonymous namespace -std::string ValueToString(size_t value) +// cmCMakeHostSystemInformation +bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - return std::to_string(value); -} + std::size_t current_index = 0; -std::string ValueToString(const char* value) -{ - std::string safe_string = value ? value : ""; - return safe_string; -} + if (args.size() < (current_index + 2) || args[current_index] != "RESULT") { + status.SetError("missing RESULT specification."); + return false; + } -std::string ValueToString(std::string const& value) -{ - return value; -} + std::string const& variable = args[current_index + 1]; + current_index += 2; + + if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { + status.SetError("missing QUERY specification"); + return false; + } + + static cmsys::SystemInformation info; + static auto initialized = false; + if (!initialized) { + info.RunCPUCheck(); + info.RunOSCheck(); + info.RunMemoryCheck(); + initialized = true; + } + + std::string result_list; + for (auto i = current_index + 1; i < args.size(); ++i) { + std::string const& key = args[i]; + if (i != current_index + 1) { + result_list += ";"; + } + std::string value; + if (!GetValue(status, info, key, value)) { + return false; + } + result_list += value; + } + + status.GetMakefile().AddDefinition(variable, result_list); + + return true; } From 986caf9b86de75bef071af098435451f0e20645a Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 28 Jul 2021 00:01:13 -0400 Subject: [PATCH 1020/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ee3ffb769bf..3a96d7e0696 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210727) +set(CMake_VERSION_PATCH 20210728) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From dbcc5eaa05337a12655e11bcf34259c0bdac3589 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Wed, 28 Jul 2021 15:56:34 +0300 Subject: [PATCH 1021/1519] FindBLAS: Update SCSL library --- Modules/FindBLAS.cmake | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 799d1795959..5d5a362055b 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -150,7 +150,7 @@ BLAS/LAPACK Vendors ``PhiPACK`` Portable High Performance ANSI C (PHiPAC) -``SCSL`` +``SCSL``, ``SCSL_mp`` Scientific Computing Software Library ``SGIMATH`` @@ -862,19 +862,27 @@ if(BLA_VENDOR STREQUAL "SunPerf" OR BLA_VENDOR STREQUAL "All") endif() # BLAS in SCSL library? (SGI/Cray Scientific Library) -if(BLA_VENDOR STREQUAL "SCSL" OR BLA_VENDOR STREQUAL "All") +if(BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All") + set(_blas_scsl_lib "scs") + + if(BLA_VENDOR MATCHES "_mp") + set(_blas_scsl_lib "${_blas_scsl_lib}_mp") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS sgemm "" - "scsl" + "${_blas_scsl_lib}" "" "" "" ) endif() + + unset(_blas_scsl_lib) endif() # BLAS in SGIMATH library? From 069a5c3188e76aa26a22bbf1ec9d27a803813124 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Wed, 28 Jul 2021 16:01:14 +0300 Subject: [PATCH 1022/1519] FindLAPACK: SCSL also has LAPACK routines --- Modules/FindLAPACK.cmake | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index aa5423a434c..a97d7f7431c 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -491,6 +491,30 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) ) endif() + # LAPACK in SCSL library? (SGI/Cray Scientific Library) + if(NOT LAPACK_LIBRARIES + AND (BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All")) + set(_lapack_scsl_lib "scs") + + # Check for OpenMP support, VIA BLA_VENDOR of scs_mp + if(BLA_VENDOR MATCHES "_mp") + set(_lapack_scsl_lib "${_lapack_scsl_lib}_mp") + endif() + + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "${_lapack_scsl_lib}" + "" + "" + "" + "${BLAS_LIBRARIES}" + ) + unset(_lapack_scsl_lib) + endif() + # BLAS in acml library? if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All") if(BLAS_LIBRARIES MATCHES ".+acml.+") From 03913b12cb9ae48d81ec773a1c6b93ba5fd2ad5d Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Tue, 27 Jul 2021 20:40:51 +0300 Subject: [PATCH 1023/1519] FindLAPACK: IBM ESSL 6.1 also has LAPACK routines --- Modules/FindLAPACK.cmake | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index aa5423a434c..d70453be026 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -586,6 +586,30 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) unset(_ssl2_suffix) endif() + # LAPACK in IBM ESSL library? + if(NOT LAPACK_LIBRARIES + AND (BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All")) + set(_lapack_essl_lib "essl") + + # Check for OpenMP support, VIA BLA_VENDOR of esslsmp + if(BLA_VENDOR MATCHES "_SMP") + set(_lapack_essl_lib "${_lapack_essl_lib}smp") + endif() + + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "${_lapack_essl_lib}" + "" + "" + "" + "${BLAS_LIBRARIES}" + ) + unset(_lapack_essl_lib) + endif() + # NVHPC Library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All")) From 26170ea3069238bfb287d6304cd2f65e1c3a7387 Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Wed, 28 Jul 2021 09:43:04 -0400 Subject: [PATCH 1024/1519] CTest: Reset multi-options to persistent multi-options 44ad3f0b added multi-options to CTest, but didn't reset them, causing ctest_test() to fail if it was run multiple times with different label arguments. Reset the multi-options. Fixes: #22485 --- Source/CTest/cmCTestGenericHandler.cxx | 6 ++---- Tests/RunCMake/ctest_test/RunCMakeTest.cmake | 13 +++++++++++++ Tests/RunCMake/ctest_test/test.cmake.in | 7 ++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index cc756d7dc48..48cc0e45007 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -68,10 +68,8 @@ void cmCTestGenericHandler::Initialize() { this->AppendXML = false; this->TestLoad = 0; - this->Options.clear(); - for (auto const& po : this->PersistentOptions) { - this->Options[po.first] = po.second; - } + this->Options = this->PersistentOptions; + this->MultiOptions = this->PersistentMultiOptions; } const char* cmCTestGenericHandler::GetOption(const std::string& op) diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index f07a12b7739..5f9b32d9725 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -181,3 +181,16 @@ add_test( run_ctest(TestCompletionStatus) endfunction() run_completion_status() + +# Verify that running ctest_test() multiple times with different label arguments +# doesn't break. +function(run_changing_labels) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME a COMMAND ${CMAKE_COMMAND} -E true) +set_property(TEST a PROPERTY LABELS a) +add_test(NAME b COMMAND ${CMAKE_COMMAND} -E true) +set_property(TEST b PROPERTY LABELS b) + ]]) + run_ctest(TestChangingLabels) +endfunction() +run_changing_labels() diff --git a/Tests/RunCMake/ctest_test/test.cmake.in b/Tests/RunCMake/ctest_test/test.cmake.in index 50b936d311e..36b1dbdf034 100644 --- a/Tests/RunCMake/ctest_test/test.cmake.in +++ b/Tests/RunCMake/ctest_test/test.cmake.in @@ -15,4 +15,9 @@ set(ctest_test_args "@CASE_CTEST_TEST_ARGS@") ctest_start(Experimental) ctest_configure() ctest_build() -ctest_test(${ctest_test_args}) +if("@CASE_NAME@" STREQUAL "TestChangingLabels") + ctest_test(${ctest_test_args} INCLUDE_LABEL "^a$") + ctest_test(${ctest_test_args} INCLUDE_LABEL "^b$") +else() + ctest_test(${ctest_test_args}) +endif() From 283e8d8d0475dd38e7ee52093fd033225f858d07 Mon Sep 17 00:00:00 2001 From: Alexey Edelev <semlanik@gmail.com> Date: Wed, 28 Jul 2021 16:32:27 +0200 Subject: [PATCH 1025/1519] AUTOUIC: Add test for cyclic dependency between UI headers and timestamp Follow up test for the commit 9cebdbec. --- Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt | 13 +++++++++++++ .../UicOnFileChange/CMakeLists.txt.in | 8 ++++++-- .../RerunUicOnFileChange/UicOnFileChange/main.cpp | 1 + .../UicOnFileChange/mainwindow.h | 13 +++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt index a9ccece5d5c..a3ba9fbd40d 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt @@ -26,6 +26,7 @@ macro(rebuild buildName) endmacro() configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY) +configure_file("${testProjectTemplateDir}/mainwindow.h" "${testProjectSrc}/mainwindow.h" COPYONLY) configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY) configure_file("${testProjectTemplateDir}/subdir/subdircheck.cpp" "${testProjectSrc}/subdir/subdircheck.cpp" COPYONLY) configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY) @@ -103,3 +104,15 @@ execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" if(NOT result EQUAL "0") message(FATAL_ERROR "Rebuild of UicOnFileChange test result is: ${result}") endif() + +# Check if the generated ui_mainwindow.h rules introduce circular dependency between the generated +# ui_mainwinow.h and timestamp. +# +# The first rebuild updates a timestamp dependency file after "touching" mainwindow.h. +sleep() +execute_process(COMMAND ${CMAKE_COMMAND} -E touch "${testProjectSrc}/mainwindow.h") +rebuild(3) + +# The second rebuild detects if cycling dependency is introduced by deps file. +sleep() +rebuild(4) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in index 2a1998d10fe..c77075ca1e3 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in @@ -5,9 +5,13 @@ include("@CMAKE_CURRENT_LIST_DIR@/../AutogenGuiTest.cmake") # Enable CMAKE_AUTOUIC for all targets set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) -add_executable(UicOnFileChange main.cpp mainwindow.ui +add_executable(UicOnFileChange main.cpp mainwindow.ui mainwindow.h subdir/subdircheck.cpp subdir/mainwindowsubdir.ui ) -target_include_directories(UicOnFileChange PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(UicOnFileChange PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}/UicOnFileChange_autogen/include" +) target_link_libraries(UicOnFileChange ${QT_QTCORE_TARGET} ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp index 39812688463..99de13dccf2 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp @@ -1,3 +1,4 @@ +#include "mainwindow.h" #include "ui_mainwindow.h" extern bool subdircheck(); diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h new file mode 100644 index 00000000000..24621ffb01e --- /dev/null +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h @@ -0,0 +1,13 @@ +#include <QObject> + +#include "ui_mainwindow.h" + +class MainWindow : public QObject +{ + Q_OBJECT +public: + MainWindow() { mwUi.setupUi(&mw); } + + MocWidget mw; + Ui::Widget mwUi; +}; From d856aaa37d35a23b1d5da3aa3cc34201b76b8bde Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Mon, 3 May 2021 10:59:23 -0400 Subject: [PATCH 1026/1519] FindCUDAToolkit: Understand NVHPC versioned math library layout The NVHPC packages bundle the CUDA math libraries in a sibling directory (`math_libs`) instead of in with the rest of the cuda libraries. Depending on the NVHPC package the math_libs folder can have versioned subdirectories, therefore we prefer finding the same versions as the CUDA Toolkit and falling back to the latest when not possible. --- Modules/FindCUDAToolkit.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index e45310995ab..92042d23c42 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -844,6 +844,9 @@ if(CUDAToolkit_FOUND) HINTS ${CUDAToolkit_LIBRARY_DIR} ENV CUDA_PATH PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs + # Support NVHPC splayed math library layout + ../../math_libs/${CUDAToolkit_VERSION_MAJOR}.${CUDAToolkit_VERSION_MINOR}/lib64 + ../../math_libs/lib64 ) mark_as_advanced(CUDA_${lib_name}_LIBRARY) From 172475b2c57963a9cc0ac5bac90084b21054e900 Mon Sep 17 00:00:00 2001 From: Lawrence A <38889-lawadr@users.noreply.gitlab.kitware.com> Date: Wed, 28 Jul 2021 18:24:42 +0100 Subject: [PATCH 1027/1519] GHS: Remove bashism from custom command shell scripts --- Source/cmGhsMultiTargetGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 32238e4bd32..12fd9c4526b 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -376,7 +376,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( #ifdef _WIN32 std::string check_error = "if %errorlevel% neq 0 exit /b %errorlevel%"; #else - std::string check_error = "if [[ $? -ne 0 ]]; then exit 1; fi"; + std::string check_error = "if [ $? -ne 0 ]; then exit 1; fi"; #endif #ifdef _WIN32 From 824bab99e90337c62a837756eb55fb29c131da8f Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 29 Jul 2021 00:01:09 -0400 Subject: [PATCH 1028/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3a96d7e0696..9d87d6fd73e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210728) +set(CMake_VERSION_PATCH 20210729) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0b1cea66cd1f80458f0da579d0182d908874939d Mon Sep 17 00:00:00 2001 From: root <raul@tambre.ee> Date: Tue, 27 Jul 2021 22:58:03 +0300 Subject: [PATCH 1029/1519] CUDA/Clang: Fix separable compilation in non-root directories with Makefiles Seems the relative paths were wrong basically all around such that only compiling files in the top-level directory would work. I've modified CudaOnly.SeparateCompilation to cover this. Fixes #22482. --- Help/release/3.21.rst | 6 +++++ Source/cmMakefileTargetGenerator.cxx | 24 +++++++++++-------- Tests/CudaOnly/CMakeLists.txt | 2 +- .../SeparateCompilation/CMakeLists.txt | 19 +-------------- .../SeparateCompilation/main/CMakeLists.txt | 18 ++++++++++++++ .../SeparateCompilation/{ => main}/main.cu | 4 ++-- 6 files changed, 42 insertions(+), 31 deletions(-) create mode 100644 Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt rename Tests/CudaOnly/SeparateCompilation/{ => main}/main.cu (97%) diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 3e705529fe1..fc5d6ace2ff 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -304,3 +304,9 @@ Changes made since CMake 3.21.0 include the following. * The :generator:`Visual Studio 17 2022` generator is now based on "Visual Studio 2022 Preview 2". Previously it was based on "Preview 1.1". + +3.21.2 +------ + +* ``CUDA`` targets with :prop_tgt:`CUDA_SEPARABLE_COMPILATION` enabled are now + correctly generated in non-root directories. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 6d8376c6788..6324b2ef83b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1484,14 +1484,18 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( } std::vector<std::string> architectures = cmExpandedList(architecturesStr); + std::string const& relPath = + this->LocalGenerator->GetHomeRelativeOutputPath(); // Ensure there are no duplicates. const std::vector<std::string> linkDeps = [&]() -> std::vector<std::string> { std::vector<std::string> deps; this->AppendTargetDepends(deps, true); this->GeneratorTarget->GetLinkDepends(deps, this->GetConfigName(), "CUDA"); - std::copy(this->Objects.begin(), this->Objects.end(), - std::back_inserter(deps)); + + for (std::string const& obj : this->Objects) { + deps.emplace_back(cmStrCat(relPath, obj)); + } std::unordered_set<std::string> depsSet(deps.begin(), deps.end()); deps.clear(); @@ -1510,7 +1514,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( std::string profiles; std::vector<std::string> fatbinaryDepends; - std::string registerFile = cmStrCat(objectDir, "cmake_cuda_register.h"); + std::string const registerFile = + cmStrCat(objectDir, "cmake_cuda_register.h"); // Link device code for each architecture. for (const std::string& architectureKind : architectures) { @@ -1518,7 +1523,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( const std::string architecture = architectureKind.substr(0, architectureKind.find('-')); const std::string cubin = - cmStrCat(relObjectDir, "sm_", architecture, ".cubin"); + cmStrCat(objectDir, "sm_", architecture, ".cubin"); profiles += cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin); fatbinaryDepends.emplace_back(cubin); @@ -1530,8 +1535,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( // all architectures the register file will be the same too. Thus // generate it only on the first invocation to reduce overhead. if (fatbinaryDepends.size() == 1) { - std::string registerFileRel = - this->LocalGenerator->MaybeRelativeToCurBinDir(registerFile); + std::string const registerFileRel = + cmStrCat(relPath, relObjectDir, "cmake_cuda_register.h"); registerFileCmd = cmStrCat(" --register-link-binaries=", registerFileRel); cleanFiles.push_back(registerFileRel); @@ -1555,7 +1560,7 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( const std::string fatbinaryOutput = cmStrCat(objectDir, "cmake_cuda_fatbin.h"); const std::string fatbinaryOutputRel = - this->LocalGenerator->MaybeRelativeToCurBinDir(fatbinaryOutput); + cmStrCat(relPath, relObjectDir, "cmake_cuda_fatbin.h"); this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, fatbinaryOutputRel, fatbinaryDepends, @@ -1583,9 +1588,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( compileCmd, vars); commands.emplace_back(compileCmd); - this->LocalGenerator->WriteMakeRule( - *this->BuildFileStream, nullptr, output, - { cmStrCat(relObjectDir, "cmake_cuda_fatbin.h") }, commands, false); + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, output, + { fatbinaryOutputRel }, commands, false); // Clean all the possible executable names and symlinks. this->CleanFiles.insert(cleanFiles.begin(), cleanFiles.end()); diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt index fdb7a6eda82..a3fb409b918 100644 --- a/Tests/CudaOnly/CMakeLists.txt +++ b/Tests/CudaOnly/CMakeLists.txt @@ -15,7 +15,7 @@ add_cuda_test_macro(CudaOnly.ToolkitBeforeLang CudaOnlyToolkitBeforeLang) add_cuda_test_macro(CudaOnly.WithDefs CudaOnlyWithDefs) add_cuda_test_macro(CudaOnly.CircularLinkLine CudaOnlyCircularLinkLine) add_cuda_test_macro(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols) -add_cuda_test_macro(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation) +add_cuda_test_macro(CudaOnly.SeparateCompilation main/CudaOnlySeparateCompilation) if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang") # Clang doesn't have flags for selecting the runtime. diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index 864ecbfb5dc..17069e3107d 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -34,26 +34,9 @@ add_library(CUDASeparateLibB STATIC file4.cu file5.cu) target_compile_features(CUDASeparateLibB PRIVATE cuda_std_11) target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA) -add_executable(CudaOnlySeparateCompilation main.cu) -target_link_libraries(CudaOnlySeparateCompilation - PRIVATE CUDASeparateLibB) -set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD 11) -set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD_REQUIRED TRUE) - set_target_properties(CUDASeparateLibA CUDASeparateLibB PROPERTIES CUDA_SEPARABLE_COMPILATION ON POSITION_INDEPENDENT_CODE ON) -if (CMAKE_GENERATOR MATCHES "^Visual Studio") - #Visual Studio CUDA integration will not perform device linking - #on a target that itself does not have GenerateRelocatableDeviceCode - #enabled. - set_target_properties(CudaOnlySeparateCompilation - PROPERTIES CUDA_SEPARABLE_COMPILATION ON) -endif() - -if(APPLE) - # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. - set_property(TARGET CudaOnlySeparateCompilation PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) -endif() +add_subdirectory(main) diff --git a/Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt new file mode 100644 index 00000000000..c1810786c93 --- /dev/null +++ b/Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt @@ -0,0 +1,18 @@ +add_executable(CudaOnlySeparateCompilation main.cu) +target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASeparateLibB) +set_target_properties(CudaOnlySeparateCompilation PROPERTIES + CUDA_STANDARD 11 + CUDA_STANDARD_REQUIRED TRUE +) + +if(CMAKE_GENERATOR MATCHES "^Visual Studio") + # Visual Studio CUDA integration will not perform device linking + # on a target that itself does not have GenerateRelocatableDeviceCode + # enabled. + set_property(TARGET CudaOnlySeparateCompilation PROPERTY CUDA_SEPARABLE_COMPILATION ON) +endif() + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET CudaOnlySeparateCompilation PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main/main.cu similarity index 97% rename from Tests/CudaOnly/SeparateCompilation/main.cu rename to Tests/CudaOnly/SeparateCompilation/main/main.cu index 40dbe5d7e2d..2b6e8f4cb84 100644 --- a/Tests/CudaOnly/SeparateCompilation/main.cu +++ b/Tests/CudaOnly/SeparateCompilation/main/main.cu @@ -1,8 +1,8 @@ #include <iostream> -#include "file1.h" -#include "file2.h" +#include "../file1.h" +#include "../file2.h" int file4_launch_kernel(int x); int file5_launch_kernel(int x); From 3975678fcc3928f2a7dcd79fe9b9e9ebf3abe2b2 Mon Sep 17 00:00:00 2001 From: root <raul@tambre.ee> Date: Tue, 27 Jul 2021 23:38:36 +0300 Subject: [PATCH 1030/1519] CUDA/Clang: Simplify --register-link-binaries logic Move the logic for appending cubin afterwards, so the check can simply be empty(). With the Makefile generator the option is now at the front instead of being intermixed with the actual bins. --- Source/cmMakefileTargetGenerator.cxx | 20 ++++++++++---------- Source/cmNinjaNormalTargetGenerator.cxx | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 6324b2ef83b..98c61fe8be5 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1519,22 +1519,13 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( // Link device code for each architecture. for (const std::string& architectureKind : architectures) { - // Clang always generates real code, so strip the specifier. - const std::string architecture = - architectureKind.substr(0, architectureKind.find('-')); - const std::string cubin = - cmStrCat(objectDir, "sm_", architecture, ".cubin"); - - profiles += cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin); - fatbinaryDepends.emplace_back(cubin); - std::string registerFileCmd; // The generated register file contains macros that when expanded // register the device routines. Because the routines are the same for // all architectures the register file will be the same too. Thus // generate it only on the first invocation to reduce overhead. - if (fatbinaryDepends.size() == 1) { + if (fatbinaryDepends.empty()) { std::string const registerFileRel = cmStrCat(relPath, relObjectDir, "cmake_cuda_register.h"); registerFileCmd = @@ -1542,6 +1533,15 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( cleanFiles.push_back(registerFileRel); } + // Clang always generates real code, so strip the specifier. + const std::string architecture = + architectureKind.substr(0, architectureKind.find('-')); + const std::string cubin = + cmStrCat(objectDir, "sm_", architecture, ".cubin"); + + profiles += cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin); + fatbinaryDepends.emplace_back(cubin); + std::string command = cmStrCat( this->Makefile->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"), " -arch=sm_", architecture, registerFileCmd, " -o=$@ ", diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 5a4c6521d84..493bd4ac85d 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -753,10 +753,6 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements( const std::string cubin = cmStrCat(ninjaOutputDir, "/sm_", architecture, ".cubin"); - fatbinary.Variables["PROFILES"] += - cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin); - fatbinary.ExplicitDeps.emplace_back(cubin); - cmNinjaBuild dlink(this->LanguageLinkerCudaDeviceRule(config)); dlink.ExplicitDeps = explicitDeps; dlink.Outputs = { cubin }; @@ -766,11 +762,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements( // the device routines. Because the routines are the same for all // architectures the register file will be the same too. Thus generate it // only on the first invocation to reduce overhead. - if (fatbinary.ExplicitDeps.size() == 1) { + if (fatbinary.ExplicitDeps.empty()) { dlink.Variables["REGISTER"] = cmStrCat( "--register-link-binaries=", ninjaOutputDir, "/cmake_cuda_register.h"); } + fatbinary.Variables["PROFILES"] += + cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin); + fatbinary.ExplicitDeps.emplace_back(cubin); + this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), dlink); } From a1261ce91769449505433e7ecd4288a39738a6f3 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton <jessica.l.hamilton@gmail.com> Date: Wed, 28 Jul 2021 05:48:03 -0400 Subject: [PATCH 1031/1519] Platform/Haiku: Remove the include-once behavior The behavior was added by commit 7ebc1cb2ff (Haiku: Several fixes to platform module, 2013-10-05, v3.0.0-rc1~541^2~3), but was not explained in its commit message. No other platform modules do this. The include-once behavior results in incorrect variables set in some larger projects, e.g. .NET Core, particularly when cross-compiling, `CMAKE_DL_LIBS` being one of these. Remove it. --- Modules/Platform/Haiku.cmake | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Modules/Platform/Haiku.cmake b/Modules/Platform/Haiku.cmake index 7e0af6166f4..b8e3ba6280e 100644 --- a/Modules/Platform/Haiku.cmake +++ b/Modules/Platform/Haiku.cmake @@ -1,8 +1,3 @@ -# process only once -if(HAIKU) - return() -endif() - set(HAIKU 1) set(UNIX 1) From 7ce718376cb6853793a75ee9a6e22ecff04e75fe Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 28 Jul 2021 13:47:19 -0400 Subject: [PATCH 1032/1519] NVHPC: Support 21.07 change to '-MD' where it behaves like gcc --- Modules/Compiler/NVHPC-C.cmake | 5 ----- Modules/Compiler/NVHPC-CXX.cmake | 5 ----- Modules/Compiler/NVHPC.cmake | 12 ++++++++++++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake index a734edf1988..72c26563f47 100644 --- a/Modules/Compiler/NVHPC-C.cmake +++ b/Modules/Compiler/NVHPC-C.cmake @@ -4,9 +4,4 @@ include(Compiler/NVHPC) # Needed so that we support `LANGUAGE` property correctly set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c) -# Required since as of NVHPC 21.03 the `-MD` flag implicitly -# implies `-E` and therefore compilation and dependency generation -# can't occur in the same invocation -set(CMAKE_C_DEPENDS_EXTRA_COMMANDS "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>") - __compiler_nvhpc(C) diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake index 98d00225764..ac75b53a409 100644 --- a/Modules/Compiler/NVHPC-CXX.cmake +++ b/Modules/Compiler/NVHPC-CXX.cmake @@ -4,9 +4,4 @@ include(Compiler/NVHPC) # Needed so that we support `LANGUAGE` property correctly set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++) -# Required since as of NVHPC 21.03 the `-MD` flag implicitly -# implies `-E` and therefore compilation and dependency generation -# can't occur in the same invocation -set(CMAKE_CXX_DEPENDS_EXTRA_COMMANDS "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c++ -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>") - __compiler_nvhpc(CXX) diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake index 70486705c1c..a85df711e6d 100644 --- a/Modules/Compiler/NVHPC.cmake +++ b/Modules/Compiler/NVHPC.cmake @@ -12,4 +12,16 @@ include(Compiler/PGI) macro(__compiler_nvhpc lang) # Logic specific to NVHPC. + + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 21.07) + set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") + set(CMAKE_${lang}_DEPFILE_FORMAT gcc) + set(CMAKE_${lang}_DEPENDS_USE_COMPILER TRUE) + else() + # Before NVHPC 21.07 the `-MD` flag implicitly + # implies `-E` and therefore compilation and dependency generation + # can't occur in the same invocation + set(CMAKE_${lang}_DEPENDS_EXTRA_COMMANDS "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${CMAKE_${lang}_COMPILE_OPTIONS_EXPLICIT_LANGUAGE} -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>") + endif() + endmacro() From 53aabe9817dfad76869c41c2eeb46fb874bf188b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 29 Jul 2021 11:21:13 -0400 Subject: [PATCH 1033/1519] VS: Fix assertion failure on INCLUDE_DIRECTORIES in INTERFACE libraries Since commit 4391913133 (Add INTERFACE libraries to generated buildsystem if they have SOURCES, 2020-07-20, v3.19.0-rc1~346^2~1), the VS generator may process INTERFACE libraries. Avoid code paths in the generator that process include directories because they should not be used by INTERFACE libraries since they do not compile anything. Fixes: #22494 --- Source/cmVisualStudio10TargetGenerator.cxx | 3 +++ Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake | 7 +++++++ Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake | 1 + 3 files changed, 11 insertions(+) create mode 100644 Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 11a8b1f3e70..bda2f914d21 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -4093,6 +4093,9 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions( if (this->ProjectType == csproj) { return; } + if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) { + return; + } // This processes *any* of the .idl files specified in the project's file // list (and passed as the item metadata %(Filename) expressing the rule diff --git a/Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake b/Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake new file mode 100644 index 00000000000..b94eac0bb90 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake @@ -0,0 +1,7 @@ +cmake_policy(SET CMP0076 NEW) +include_directories(Inc1 Inc2) +add_library(iface INTERFACE) +target_sources(iface PRIVATE iface.c) +# Ensure the INCLUDE_DIRECTORIES property is populated. +# Since interface libraries do not actually compile anything, this should be ignored. +set_property(TARGET iface APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Inc3 ${CMAKE_CURRENT_SOURCE_DIR}/Inc4) diff --git a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake index 834b3c8fe5b..10a2d511b96 100644 --- a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake @@ -34,3 +34,4 @@ run_WithSources(ConfigSources "build1:iface") run_WithSources(EmptySources "build1:iface" "build2:iface2,merge") run_WithSources(ExcludeFromAll "build1" "build2:iface" "build3:iface2,merge") run_WithSources(PublicSources "build1" "build2:iface" "build3:iface2,merge") +run_WithSources(IncludeDirectories "build1:iface") From 008d55df7677ec69254cd480329dd713d103b20f Mon Sep 17 00:00:00 2001 From: Russell Greene <russell@churchillnavigation.com> Date: Mon, 26 Jul 2021 14:31:26 -0400 Subject: [PATCH 1034/1519] CPack/DEB+RPM: Update documentation on debug symbol package creation Update documentation to elaborate on the behavior between `.ddeb` creation, CPACK_STRIP_FILES, and if the files are actually stripped. Closes: #22438 --- Help/cpack_gen/deb.rst | 9 +++++++++ Help/cpack_gen/rpm.rst | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst index d8d53ece362..c0d9c3dd495 100644 --- a/Help/cpack_gen/deb.rst +++ b/Help/cpack_gen/deb.rst @@ -650,11 +650,20 @@ Dbgsym packaging has its own set of variables: * Mandatory : NO * Default : OFF +.. note:: + + Setting this also strips the ELF files in the generated non-dbgsym package, + which results in debuginfo only being available in the dbgsym package. + .. note:: Binaries must contain debug symbols before packaging so use either ``Debug`` or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value. + Additionally, if :variable:`CPACK_STRIP_FILES` is set, the files will be stripped before + they get to the DEB generator, so will not contain debug symbols and + a dbgsym package will not get built. Do not use with :variable:`CPACK_STRIP_FILES`. + Building Debian packages on Windows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst index f6274f9dc93..823594abf1b 100644 --- a/Help/cpack_gen/rpm.rst +++ b/Help/cpack_gen/rpm.rst @@ -840,6 +840,10 @@ Debuginfo RPM packaging has its own set of variables: Binaries must contain debug symbols before packaging so use either ``Debug`` or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value. + Additionally, if :variable:`CPACK_STRIP_FILES` is set, the files will be stripped before + they get to the RPM generator, so will not contain debug symbols and + a debuginfo package will not get built. Do not use with :variable:`CPACK_STRIP_FILES`. + .. note:: Packages generated from packages without binary files, with binary files but From 051da997da6344a33145e7c370e336dfc1e8fb09 Mon Sep 17 00:00:00 2001 From: Russell Greene <russell@churchillnavigation.com> Date: Mon, 26 Jul 2021 14:36:04 -0400 Subject: [PATCH 1035/1519] CPack/DEB: Add zstd compression for deb packages --- Help/cpack_gen/deb.rst | 21 +++++++++++++++---- .../dev/cpack-deb-add-zstd-compression.rst | 6 ++++++ Source/CPack/cmCPackDebGenerator.cxx | 3 +++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/cpack-deb-add-zstd-compression.rst diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst index d8d53ece362..3b341c2730f 100644 --- a/Help/cpack_gen/deb.rst +++ b/Help/cpack_gen/deb.rst @@ -274,10 +274,23 @@ List of CPack DEB generator specific variables: Possible values are: - - lzma - - xz - - bzip2 - - gzip + ``lzma`` + Lempel–Ziv–Markov chain algorithm + + ``xz`` + XZ Utils compression + + ``bzip2`` + bzip2 Burrows–Wheeler algorithm + + ``gzip`` + GNU Gzip compression + + ``zstd`` + .. versionadded:: 3.22 + + Zstandard compression + .. variable:: CPACK_DEBIAN_PACKAGE_PRIORITY CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY diff --git a/Help/release/dev/cpack-deb-add-zstd-compression.rst b/Help/release/dev/cpack-deb-add-zstd-compression.rst new file mode 100644 index 00000000000..a138455f0cb --- /dev/null +++ b/Help/release/dev/cpack-deb-add-zstd-compression.rst @@ -0,0 +1,6 @@ +cpack-deb-add-zstd-compression +------------------------------ + +* The :cpack_gen:`CPack DEB Generator` gained the + option to set :variable:`CPACK_DEBIAN_COMPRESSION_TYPE` to zstd, + which enables Zstandard compression for deb packages. diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 5b031857ee3..5f0f153b3e7 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -111,6 +111,9 @@ DebGenerator::DebGenerator( } else if (!std::strcmp(debianCompressionType, "gzip")) { this->CompressionSuffix = ".gz"; this->TarCompressionType = cmArchiveWrite::CompressGZip; + } else if (!std::strcmp(debianCompressionType, "zstd")) { + this->CompressionSuffix = ".zst"; + this->TarCompressionType = cmArchiveWrite::CompressZstd; } else if (!std::strcmp(debianCompressionType, "none")) { this->CompressionSuffix.clear(); this->TarCompressionType = cmArchiveWrite::CompressNone; From 22dab6eb96438b8563079c44d00c520df5b04a6e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 29 Jul 2021 11:49:27 -0400 Subject: [PATCH 1036/1519] Deprecate Visual Studio 10 2010 generator Update documentation to mark the generator deprecated. Add a warning at the end of generation plus an option to turn off the warning. --- Help/generator/Visual Studio 10 2010.rst | 9 ++++++++- Help/release/dev/vs10-deprecate.rst | 5 +++++ Source/cmGlobalVisualStudio10Generator.cxx | 2 +- Source/cmGlobalVisualStudio7Generator.cxx | 19 +++++++++++++++++++ Tests/CMakeLists.txt | 7 +++++++ Tests/EnforceConfig.cmake.in | 1 + .../CommandLine/DeprecateVS10-WARN-OFF.cmake | 0 .../DeprecateVS10-WARN-ON-stderr.txt | 5 +++++ .../CommandLine/DeprecateVS10-WARN-ON.cmake | 0 Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 7 +++++++ 10 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/vs10-deprecate.rst create mode 100644 Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake create mode 100644 Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst index c065550361d..9ec33c3549e 100644 --- a/Help/generator/Visual Studio 10 2010.rst +++ b/Help/generator/Visual Studio 10 2010.rst @@ -1,7 +1,14 @@ Visual Studio 10 2010 --------------------- -Generates Visual Studio 10 (VS 2010) project files. +Deprecated. Generates Visual Studio 10 (VS 2010) project files. + +.. note:: + This generator is deprecated and will be removed in a future version + of CMake. It will still be possible to build with VS 10 2010 tools + using the :generator:`Visual Studio 11 2012` (or above) generator + with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v100``, or by + using the :generator:`NMake Makefiles` generator. For compatibility with CMake versions prior to 3.0, one may specify this generator using the name ``Visual Studio 10`` without the year component. diff --git a/Help/release/dev/vs10-deprecate.rst b/Help/release/dev/vs10-deprecate.rst new file mode 100644 index 00000000000..7bec3911545 --- /dev/null +++ b/Help/release/dev/vs10-deprecate.rst @@ -0,0 +1,5 @@ +vs10-deprecate +-------------- + +* The :generator:`Visual Studio 10 2010` generator is now deprecated + and will be removed in a future version of CMake. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index fdb71554ce1..488ff2e9c7a 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -88,7 +88,7 @@ class cmGlobalVisualStudio10Generator::Factory void GetDocumentation(cmDocumentationEntry& entry) const override { entry.Name = std::string(vs10generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2010 project files. " + entry.Brief = "Deprecated. Generates Visual Studio 2010 project files. " "Optional [arch] can be \"Win64\" or \"IA64\"."; } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index f8aa1729e4c..34dba1eb5c2 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -296,6 +296,25 @@ void cmGlobalVisualStudio7Generator::Generate() this->CallVisualStudioMacro(MacroReload, GetSLNFile(this->LocalGenerators[0].get())); } + + if (this->Version == VS10 && !this->CMakeInstance->GetIsInTryCompile()) { + std::string cmakeWarnVS10; + if (cmProp cached = this->CMakeInstance->GetState()->GetCacheEntryValue( + "CMAKE_WARN_VS10")) { + this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS10"); + cmakeWarnVS10 = *cached; + } else { + cmSystemTools::GetEnv("CMAKE_WARN_VS10", cmakeWarnVS10); + } + if (cmakeWarnVS10.empty() || !cmIsOff(cmakeWarnVS10)) { + this->CMakeInstance->IssueMessage( + MessageType::WARNING, + "The \"Visual Studio 10 2010\" generator is deprecated " + "and will be removed in a future version of CMake." + "\n" + "Add CMAKE_WARN_VS10=OFF to the cache to disable this warning."); + } + } } void cmGlobalVisualStudio7Generator::OutputSLNFile( diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 388ff207a81..ef8c84648c5 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -39,6 +39,13 @@ set(ENV{HOME} \"${TEST_HOME}\") ") endif() +# Suppress generator deprecation warnings in test suite. +if(CMAKE_GENERATOR MATCHES "^Visual Studio 10 2010") + set(TEST_WARN_VS10_CODE "set(ENV{CMAKE_WARN_VS10} OFF)") +else() + set(TEST_WARN_VS10_CODE "") +endif() + # 3.9 or later provides a definitive answer to whether we are multi-config # through a global property. Prior to 3.9, CMAKE_CONFIGURATION_TYPES being set # is assumed to mean multi-config, but developers might modify it so it is diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in index 7781ded84a7..7c6f76a24a7 100644 --- a/Tests/EnforceConfig.cmake.in +++ b/Tests/EnforceConfig.cmake.in @@ -36,3 +36,4 @@ unset(ENV{CMAKE_GENERATOR_TOOLSET}) unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS}) @TEST_HOME_ENV_CODE@ +@TEST_WARN_VS10_CODE@ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt new file mode 100644 index 00000000000..202ef80b61a --- /dev/null +++ b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt @@ -0,0 +1,5 @@ +^CMake Warning: + The "Visual Studio 10 2010" generator is deprecated and will be removed in + a future version of CMake. + + Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.$ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 0b26b890124..cea5b1b1f73 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -918,3 +918,10 @@ set(ProfilingTestOutput ${RunCMake_TEST_BINARY_DIR}/output.json) set(RunCMake_TEST_OPTIONS --profiling-format=google-trace --profiling-output=${ProfilingTestOutput}) run_cmake(ProfilingTest) unset(RunCMake_TEST_OPTIONS) + +if(RunCMake_GENERATOR MATCHES "^Visual Studio 10 2010") + run_cmake_with_options(DeprecateVS10-WARN-ON -DCMAKE_WARN_VS10=ON) + unset(ENV{CMAKE_WARN_VS10}) + run_cmake(DeprecateVS10-WARN-ON) + run_cmake_with_options(DeprecateVS10-WARN-OFF -DCMAKE_WARN_VS10=OFF) +endif() From 69d3fcf2c866e83480730b6a3b3589edc5ba96ae Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Wed, 28 Jul 2021 16:22:54 +0300 Subject: [PATCH 1037/1519] =?UTF-8?q?Refactor:=20`bool=20GetValue(...,=20s?= =?UTF-8?q?tring&)`=20=E2=86=92=20`optional<string>=20GetValue(...)`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, split `GetValue()` into 2 overloads: - one used to get documented keys - the other (different signature) to get `VS_nn_DIR` keys --- .../cmCMakeHostSystemInformationCommand.cxx | 184 +++++++++++------- 1 file changed, 114 insertions(+), 70 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 2a0b0b86682..4465a6d26fe 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -4,6 +4,8 @@ #include <cstddef> +#include <cm/optional> + #include "cmsys/SystemInformation.hxx" #include "cmExecutionStatus.h" @@ -35,83 +37,117 @@ std::string ValueToString(std::string const& value) return value; } -bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, - std::string const& key, std::string& value) +cm::optional<std::string> GetValue(cmsys::SystemInformation& info, + std::string const& key) { if (key == "NUMBER_OF_LOGICAL_CORES") { - value = ValueToString(info.GetNumberOfLogicalCPU()); - } else if (key == "NUMBER_OF_PHYSICAL_CORES") { - value = ValueToString(info.GetNumberOfPhysicalCPU()); - } else if (key == "HOSTNAME") { - value = ValueToString(info.GetHostname()); - } else if (key == "FQDN") { - value = ValueToString(info.GetFullyQualifiedDomainName()); - } else if (key == "TOTAL_VIRTUAL_MEMORY") { - value = ValueToString(info.GetTotalVirtualMemory()); - } else if (key == "AVAILABLE_VIRTUAL_MEMORY") { - value = ValueToString(info.GetAvailableVirtualMemory()); - } else if (key == "TOTAL_PHYSICAL_MEMORY") { - value = ValueToString(info.GetTotalPhysicalMemory()); - } else if (key == "AVAILABLE_PHYSICAL_MEMORY") { - value = ValueToString(info.GetAvailablePhysicalMemory()); - } else if (key == "IS_64BIT") { - value = ValueToString(info.Is64Bits()); - } else if (key == "HAS_FPU") { - value = ValueToString( + return ValueToString(info.GetNumberOfLogicalCPU()); + } + if (key == "NUMBER_OF_PHYSICAL_CORES") { + return ValueToString(info.GetNumberOfPhysicalCPU()); + } + if (key == "HOSTNAME") { + return ValueToString(info.GetHostname()); + } + if (key == "FQDN") { + return ValueToString(info.GetFullyQualifiedDomainName()); + } + if (key == "TOTAL_VIRTUAL_MEMORY") { + return ValueToString(info.GetTotalVirtualMemory()); + } + if (key == "AVAILABLE_VIRTUAL_MEMORY") { + return ValueToString(info.GetAvailableVirtualMemory()); + } + if (key == "TOTAL_PHYSICAL_MEMORY") { + return ValueToString(info.GetTotalPhysicalMemory()); + } + if (key == "AVAILABLE_PHYSICAL_MEMORY") { + return ValueToString(info.GetAvailablePhysicalMemory()); + } + if (key == "IS_64BIT") { + return ValueToString(info.Is64Bits()); + } + if (key == "HAS_FPU") { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU)); - } else if (key == "HAS_MMX") { - value = ValueToString( + } + if (key == "HAS_MMX") { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX)); - } else if (key == "HAS_MMX_PLUS") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_MMX_PLUS") { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS)); - } else if (key == "HAS_SSE") { - value = ValueToString( + } + if (key == "HAS_SSE") { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE)); - } else if (key == "HAS_SSE2") { - value = ValueToString( + } + if (key == "HAS_SSE2") { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2)); - } else if (key == "HAS_SSE_FP") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_SSE_FP") { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_FP)); - } else if (key == "HAS_SSE_MMX") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_SSE_MMX") { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_MMX)); - } else if (key == "HAS_AMD_3DNOW") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_AMD_3DNOW") { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW)); - } else if (key == "HAS_AMD_3DNOW_PLUS") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_AMD_3DNOW_PLUS") { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS)); - } else if (key == "HAS_IA64") { - value = ValueToString( + } + if (key == "HAS_IA64") { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64)); - } else if (key == "HAS_SERIAL_NUMBER") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_SERIAL_NUMBER") { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER)); - } else if (key == "PROCESSOR_NAME") { - value = ValueToString(info.GetExtendedProcessorName()); - } else if (key == "PROCESSOR_DESCRIPTION") { - value = info.GetCPUDescription(); - } else if (key == "PROCESSOR_SERIAL_NUMBER") { - value = ValueToString(info.GetProcessorSerialNumber()); - } else if (key == "OS_NAME") { - value = ValueToString(info.GetOSName()); - } else if (key == "OS_RELEASE") { - value = ValueToString(info.GetOSRelease()); - } else if (key == "OS_VERSION") { - value = ValueToString(info.GetOSVersion()); - } else if (key == "OS_PLATFORM") { - value = ValueToString(info.GetOSPlatform()); + } + if (key == "PROCESSOR_NAME") { + return ValueToString(info.GetExtendedProcessorName()); + } + if (key == "PROCESSOR_DESCRIPTION") { + return info.GetCPUDescription(); + } + if (key == "PROCESSOR_SERIAL_NUMBER") { + return ValueToString(info.GetProcessorSerialNumber()); + } + if (key == "OS_NAME") { + return ValueToString(info.GetOSName()); + } + if (key == "OS_RELEASE") { + return ValueToString(info.GetOSRelease()); + } + if (key == "OS_VERSION") { + return ValueToString(info.GetOSVersion()); + } + if (key == "OS_PLATFORM") { + return ValueToString(info.GetOSPlatform()); + } + return {}; +} + #ifdef HAVE_VS_SETUP_HELPER - } else if (key == "VS_15_DIR") { +cm::optional<std::string> GetValue(cmExecutionStatus& status, + std::string const& key) +{ + std::string value; + if (key == "VS_15_DIR") { // If generating for the VS 15 IDE, use the same instance. cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { cmGlobalVisualStudioVersionedGenerator* vs15gen = static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); if (vs15gen->GetVSInstance(value)) { - return true; + return value; } } @@ -120,6 +156,7 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } + return value; } else if (key == "VS_16_DIR") { // If generating for the VS 16 IDE, use the same instance. cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); @@ -127,7 +164,7 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, cmGlobalVisualStudioVersionedGenerator* vs16gen = static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); if (vs16gen->GetVSInstance(value)) { - return true; + return value; } } @@ -136,6 +173,7 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } + return value; } else if (key == "VS_17_DIR") { // If generating for the VS 17 IDE, use the same instance. cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); @@ -143,7 +181,7 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, cmGlobalVisualStudioVersionedGenerator* vs17gen = static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); if (vs17gen->GetVSInstance(value)) { - return true; + return value; } } @@ -152,15 +190,12 @@ bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); } -#endif - } else { - std::string e = "does not recognize <key> " + key; - status.SetError(e); - return false; + return value; } - return true; + return {}; } +#endif // END Private functions } // anonymous namespace @@ -175,7 +210,7 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, return false; } - std::string const& variable = args[current_index + 1]; + auto const& variable = args[current_index + 1]; current_index += 2; if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { @@ -194,15 +229,24 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, std::string result_list; for (auto i = current_index + 1; i < args.size(); ++i) { - std::string const& key = args[i]; + auto const& key = args[i]; if (i != current_index + 1) { result_list += ";"; } - std::string value; - if (!GetValue(status, info, key, value)) { + auto value = GetValue(info, key); + if (!value) { +#ifdef HAVE_VS_SETUP_HELPER + value = GetValue(status, key); + if (!value) { + status.SetError("does not recognize <key> " + key); + return false; + } +#else + status.SetError("does not recognize <key> " + key); return false; +#endif } - result_list += value; + result_list += value.value(); } status.GetMakefile().AddDefinition(variable, result_list); From f9947ec9e384d12d1abc74aa5ccc8e81327580c5 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Thu, 29 Jul 2021 17:22:39 +0300 Subject: [PATCH 1038/1519] Refactor: Use string view --- .../cmCMakeHostSystemInformationCommand.cxx | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 4465a6d26fe..2bc981692e4 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -5,6 +5,8 @@ #include <cstddef> #include <cm/optional> +#include <cm/string_view> +#include <cmext/string_view> #include "cmsys/SystemInformation.hxx" @@ -40,96 +42,96 @@ std::string ValueToString(std::string const& value) cm::optional<std::string> GetValue(cmsys::SystemInformation& info, std::string const& key) { - if (key == "NUMBER_OF_LOGICAL_CORES") { + if (key == "NUMBER_OF_LOGICAL_CORES"_s) { return ValueToString(info.GetNumberOfLogicalCPU()); } - if (key == "NUMBER_OF_PHYSICAL_CORES") { + if (key == "NUMBER_OF_PHYSICAL_CORES"_s) { return ValueToString(info.GetNumberOfPhysicalCPU()); } - if (key == "HOSTNAME") { + if (key == "HOSTNAME"_s) { return ValueToString(info.GetHostname()); } - if (key == "FQDN") { + if (key == "FQDN"_s) { return ValueToString(info.GetFullyQualifiedDomainName()); } - if (key == "TOTAL_VIRTUAL_MEMORY") { + if (key == "TOTAL_VIRTUAL_MEMORY"_s) { return ValueToString(info.GetTotalVirtualMemory()); } - if (key == "AVAILABLE_VIRTUAL_MEMORY") { + if (key == "AVAILABLE_VIRTUAL_MEMORY"_s) { return ValueToString(info.GetAvailableVirtualMemory()); } - if (key == "TOTAL_PHYSICAL_MEMORY") { + if (key == "TOTAL_PHYSICAL_MEMORY"_s) { return ValueToString(info.GetTotalPhysicalMemory()); } - if (key == "AVAILABLE_PHYSICAL_MEMORY") { + if (key == "AVAILABLE_PHYSICAL_MEMORY"_s) { return ValueToString(info.GetAvailablePhysicalMemory()); } - if (key == "IS_64BIT") { + if (key == "IS_64BIT"_s) { return ValueToString(info.Is64Bits()); } - if (key == "HAS_FPU") { + if (key == "HAS_FPU"_s) { return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU)); } - if (key == "HAS_MMX") { + if (key == "HAS_MMX"_s) { return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX)); } - if (key == "HAS_MMX_PLUS") { + if (key == "HAS_MMX_PLUS"_s) { return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS)); } - if (key == "HAS_SSE") { + if (key == "HAS_SSE"_s) { return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE)); } - if (key == "HAS_SSE2") { + if (key == "HAS_SSE2"_s) { return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2)); } - if (key == "HAS_SSE_FP") { + if (key == "HAS_SSE_FP"_s) { return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_FP)); } - if (key == "HAS_SSE_MMX") { + if (key == "HAS_SSE_MMX"_s) { return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_MMX)); } - if (key == "HAS_AMD_3DNOW") { + if (key == "HAS_AMD_3DNOW"_s) { return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW)); } - if (key == "HAS_AMD_3DNOW_PLUS") { + if (key == "HAS_AMD_3DNOW_PLUS"_s) { return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS)); } - if (key == "HAS_IA64") { + if (key == "HAS_IA64"_s) { return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64)); } - if (key == "HAS_SERIAL_NUMBER") { + if (key == "HAS_SERIAL_NUMBER"_s) { return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER)); } - if (key == "PROCESSOR_NAME") { + if (key == "PROCESSOR_NAME"_s) { return ValueToString(info.GetExtendedProcessorName()); } - if (key == "PROCESSOR_DESCRIPTION") { + if (key == "PROCESSOR_DESCRIPTION"_s) { return info.GetCPUDescription(); } - if (key == "PROCESSOR_SERIAL_NUMBER") { + if (key == "PROCESSOR_SERIAL_NUMBER"_s) { return ValueToString(info.GetProcessorSerialNumber()); } - if (key == "OS_NAME") { + if (key == "OS_NAME"_s) { return ValueToString(info.GetOSName()); } - if (key == "OS_RELEASE") { + if (key == "OS_RELEASE"_s) { return ValueToString(info.GetOSRelease()); } - if (key == "OS_VERSION") { + if (key == "OS_VERSION"_s) { return ValueToString(info.GetOSVersion()); } - if (key == "OS_PLATFORM") { + if (key == "OS_PLATFORM"_s) { return ValueToString(info.GetOSPlatform()); } return {}; @@ -205,7 +207,7 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, { std::size_t current_index = 0; - if (args.size() < (current_index + 2) || args[current_index] != "RESULT") { + if (args.size() < (current_index + 2) || args[current_index] != "RESULT"_s) { status.SetError("missing RESULT specification."); return false; } @@ -213,7 +215,7 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, auto const& variable = args[current_index + 1]; current_index += 2; - if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { + if (args.size() < (current_index + 2) || args[current_index] != "QUERY"_s) { status.SetError("missing QUERY specification"); return false; } From 346f3de005722070986861450014796f84990043 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Thu, 29 Jul 2021 17:23:51 +0300 Subject: [PATCH 1039/1519] Refactor: Deduplicate code for `VS_nn_DIR` keys processing --- .../cmCMakeHostSystemInformationCommand.cxx | 66 +++++-------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 2bc981692e4..9e21208f92b 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -17,6 +17,7 @@ # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" # include "cmGlobalVisualStudioVersionedGenerator.h" +# include "cmStringAlgorithms.h" # include "cmSystemTools.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER @@ -141,58 +142,27 @@ cm::optional<std::string> GetValue(cmsys::SystemInformation& info, cm::optional<std::string> GetValue(cmExecutionStatus& status, std::string const& key) { - std::string value; - if (key == "VS_15_DIR") { - // If generating for the VS 15 IDE, use the same instance. - cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); - if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { - cmGlobalVisualStudioVersionedGenerator* vs15gen = - static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); - if (vs15gen->GetVSInstance(value)) { - return value; + auto* const gg = status.GetMakefile().GetGlobalGenerator(); + for (auto vs : { 15, 16, 17 }) { + if (key == cmStrCat("VS_"_s, vs, "_DIR"_s)) { + std::string value; + // If generating for the VS nn IDE, use the same instance. + + if (cmHasPrefix(gg->GetName(), cmStrCat("Visual Studio "_s, vs, ' '))) { + cmGlobalVisualStudioVersionedGenerator* vsNNgen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); + if (vsNNgen->GetVSInstance(value)) { + return value; + } } - } - - // Otherwise, find a VS 15 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper(15); - if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { - cmSystemTools::ConvertToUnixSlashes(value); - } - return value; - } else if (key == "VS_16_DIR") { - // If generating for the VS 16 IDE, use the same instance. - cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); - if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) { - cmGlobalVisualStudioVersionedGenerator* vs16gen = - static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); - if (vs16gen->GetVSInstance(value)) { - return value; - } - } - // Otherwise, find a VS 16 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper(16); - if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { - cmSystemTools::ConvertToUnixSlashes(value); - } - return value; - } else if (key == "VS_17_DIR") { - // If generating for the VS 17 IDE, use the same instance. - cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); - if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 17 ")) { - cmGlobalVisualStudioVersionedGenerator* vs17gen = - static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); - if (vs17gen->GetVSInstance(value)) { - return value; + // Otherwise, find a VS nn instance ourselves. + cmVSSetupAPIHelper vsSetupAPIHelper(vs); + if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { + cmSystemTools::ConvertToUnixSlashes(value); } + return value; } - - // Otherwise, find a VS 17 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper(17); - if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { - cmSystemTools::ConvertToUnixSlashes(value); - } - return value; } return {}; From 9e831284e5373002067754dfe7206e91075fa635 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Thu, 29 Jul 2021 17:40:01 +0300 Subject: [PATCH 1040/1519] Documentation: Use definition list instead of tables Transform tables into definition list for `cmake_host_system_information` command manual. --- .../command/cmake_host_system_information.rst | 158 +++++++++++++----- 1 file changed, 119 insertions(+), 39 deletions(-) diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index 2b902a9159f..ac6a0080227 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -13,45 +13,125 @@ queried. The list of queried values is stored in ``<variable>``. ``<key>`` can be one of the following values: -============================= ================================================ -Key Description -============================= ================================================ -``NUMBER_OF_LOGICAL_CORES`` Number of logical cores -``NUMBER_OF_PHYSICAL_CORES`` Number of physical cores -``HOSTNAME`` Hostname -``FQDN`` Fully qualified domain name -``TOTAL_VIRTUAL_MEMORY`` Total virtual memory in MiB [#mebibytes]_ -``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in MiB [#mebibytes]_ -``TOTAL_PHYSICAL_MEMORY`` Total physical memory in MiB [#mebibytes]_ -``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in MiB [#mebibytes]_ -============================= ================================================ - -.. versionadded:: 3.10 - Additional ``<key>`` values are available: - -============================= ================================================ -Key Description -============================= ================================================ -``IS_64BIT`` One if processor is 64Bit -``HAS_FPU`` One if processor has floating point unit -``HAS_MMX`` One if processor supports MMX instructions -``HAS_MMX_PLUS`` One if processor supports Ext. MMX instructions -``HAS_SSE`` One if processor supports SSE instructions -``HAS_SSE2`` One if processor supports SSE2 instructions -``HAS_SSE_FP`` One if processor supports SSE FP instructions -``HAS_SSE_MMX`` One if processor supports SSE MMX instructions -``HAS_AMD_3DNOW`` One if processor supports 3DNow instructions -``HAS_AMD_3DNOW_PLUS`` One if processor supports 3DNow+ instructions -``HAS_IA64`` One if IA64 processor emulating x86 -``HAS_SERIAL_NUMBER`` One if processor has serial number -``PROCESSOR_SERIAL_NUMBER`` Processor serial number -``PROCESSOR_NAME`` Human readable processor name -``PROCESSOR_DESCRIPTION`` Human readable full processor description -``OS_NAME`` See :variable:`CMAKE_HOST_SYSTEM_NAME` -``OS_RELEASE`` The OS sub-type e.g. on Windows ``Professional`` -``OS_VERSION`` The OS build ID -``OS_PLATFORM`` See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` -============================= ================================================ +``NUMBER_OF_LOGICAL_CORES`` + Number of logical cores + +``NUMBER_OF_PHYSICAL_CORES`` + Number of physical cores + +``HOSTNAME`` + Hostname + +``FQDN`` + Fully qualified domain name + +``TOTAL_VIRTUAL_MEMORY`` + Total virtual memory in MiB [#mebibytes]_ + +``AVAILABLE_VIRTUAL_MEMORY`` + Available virtual memory in MiB [#mebibytes]_ + +``TOTAL_PHYSICAL_MEMORY`` + Total physical memory in MiB [#mebibytes]_ + +``AVAILABLE_PHYSICAL_MEMORY`` + Available physical memory in MiB [#mebibytes]_ + +``IS_64BIT`` + .. versionadded:: 3.10 + + One if processor is 64Bit + +``HAS_FPU`` + .. versionadded:: 3.10 + + One if processor has floating point unit + +``HAS_MMX`` + .. versionadded:: 3.10 + + One if processor supports MMX instructions + +``HAS_MMX_PLUS`` + .. versionadded:: 3.10 + + One if processor supports Ext. MMX instructions + +``HAS_SSE`` + .. versionadded:: 3.10 + + One if processor supports SSE instructions + +``HAS_SSE2`` + .. versionadded:: 3.10 + + One if processor supports SSE2 instructions + +``HAS_SSE_FP`` + .. versionadded:: 3.10 + + One if processor supports SSE FP instructions + +``HAS_SSE_MMX`` + .. versionadded:: 3.10 + + One if processor supports SSE MMX instructions + +``HAS_AMD_3DNOW`` + .. versionadded:: 3.10 + + One if processor supports 3DNow instructions + +``HAS_AMD_3DNOW_PLUS`` + .. versionadded:: 3.10 + + One if processor supports 3DNow+ instructions + +``HAS_IA64`` + .. versionadded:: 3.10 + + One if IA64 processor emulating x86 + +``HAS_SERIAL_NUMBER`` + .. versionadded:: 3.10 + + One if processor has serial number + +``PROCESSOR_SERIAL_NUMBER`` + .. versionadded:: 3.10 + + Processor serial number + +``PROCESSOR_NAME`` + .. versionadded:: 3.10 + + Human readable processor name + +``PROCESSOR_DESCRIPTION`` + .. versionadded:: 3.10 + + Human readable full processor description + +``OS_NAME`` + .. versionadded:: 3.10 + + See :variable:`CMAKE_HOST_SYSTEM_NAME` + +``OS_RELEASE`` + .. versionadded:: 3.10 + + The OS sub-type e.g. on Windows ``Professional`` + +``OS_VERSION`` + .. versionadded:: 3.10 + + The OS build ID + +``OS_PLATFORM`` + .. versionadded:: 3.10 + + See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` + .. rubric:: Footnotes From 8e77f495b577b38676aaf274611bc3fb146e51a4 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 30 Jul 2021 00:01:09 -0400 Subject: [PATCH 1041/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9d87d6fd73e..ca43e1bcdd6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210729) +set(CMake_VERSION_PATCH 20210730) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 03ddaf1763f1651bb718e3c109f4f29acaaa8028 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 31 Jul 2021 11:14:26 +1000 Subject: [PATCH 1042/1519] Help: Add missing versionadded annotation for CPACK_DMG_FILESYSTEM --- Help/cpack_gen/dmg.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst index 64e97699814..1f05618cc7c 100644 --- a/Help/cpack_gen/dmg.rst +++ b/Help/cpack_gen/dmg.rst @@ -105,6 +105,8 @@ on macOS: .. variable:: CPACK_DMG_FILESYSTEM + .. versionadded:: 3.21 + The filesystem format. Common values are ``APFS`` and ``HFS+``. See ``man hdiutil`` for a full list of supported formats. Defaults to ``HFS+``. From 16398b8130a534420ca5289f86afe10c1971a710 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 31 Jul 2021 00:01:07 -0400 Subject: [PATCH 1043/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ca43e1bcdd6..34baf3c3d15 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210730) +set(CMake_VERSION_PATCH 20210731) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ca371d3a144ea761485e0f1846b8c215e7db19fa Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 31 Jul 2021 17:08:42 +1000 Subject: [PATCH 1044/1519] Help: Fix unlinked mention of CMAKE_TOOLCHAIN_FILE --- Help/manual/cmake-presets.7.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index db26b5a40fc..74e9faea9d2 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -187,8 +187,9 @@ that may contain the following fields: 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. Takes precedence over any `CMAKE_TOOLCHAIN_FILE` - value. This is allowed in preset files specifying version ``3`` or above. + 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. ``binaryDir`` From 8d5052fdc422733ce876ad9aac9554a6d76945e1 Mon Sep 17 00:00:00 2001 From: Jaak Ristioja <jaak@ristioja.ee> Date: Sat, 31 Jul 2021 15:06:03 +0300 Subject: [PATCH 1045/1519] cmStandardLevelResolver: Fixed typo in struct name + clang-format --- Source/cmStandardLevelResolver.cxx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 74b9d6fd547..da36ed6b203 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -57,10 +57,10 @@ int ParseStd(std::string const& level) return -1; } -struct StanardLevelComputer +struct StandardLevelComputer { - explicit StanardLevelComputer(std::string lang, std::vector<int> levels, - std::vector<std::string> levelsStr) + explicit StandardLevelComputer(std::string lang, std::vector<int> levels, + std::vector<std::string> levelsStr) : Language(std::move(lang)) , Levels(std::move(levels)) , LevelsAsStrings(std::move(levelsStr)) @@ -308,31 +308,33 @@ struct StanardLevelComputer std::vector<std::string> LevelsAsStrings; }; -std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping = - { { "C", - StanardLevelComputer{ +std::unordered_map<std::string, StandardLevelComputer> + StandardComputerMapping = { + { "C", + StandardLevelComputer{ "C", std::vector<int>{ 90, 99, 11, 17, 23 }, std::vector<std::string>{ "90", "99", "11", "17", "23" } } }, { "CXX", - StanardLevelComputer{ + StandardLevelComputer{ "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }, { "CUDA", - StanardLevelComputer{ + StandardLevelComputer{ "CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 }, std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } }, { "OBJC", - StanardLevelComputer{ + StandardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11, 17, 23 }, std::vector<std::string>{ "90", "99", "11", "17", "23" } } }, { "OBJCXX", - StanardLevelComputer{ + StandardLevelComputer{ "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }, { "HIP", - StanardLevelComputer{ + StandardLevelComputer{ "HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, - std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } }; + std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } + }; } std::string cmStandardLevelResolver::GetCompileOptionDef( From 0a6415ea1fa286346f119809323938a7cfca8565 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 1 Aug 2021 00:02:11 -0400 Subject: [PATCH 1046/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 34baf3c3d15..38570b5da52 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210731) +set(CMake_VERSION_PATCH 20210801) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 213fec4908a13bb0f414533eddfd72481bc50694 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sun, 1 Aug 2021 11:46:20 +0200 Subject: [PATCH 1047/1519] add_custom_command(DEPFILE) independent from CMAKE_DEPENDS_USE_COMPILER Fixes: #22486 --- Source/cmMakefileTargetGenerator.cxx | 22 +++++++++++++++++-- ...andDependencies-compiler-deps-legacy.cmake | 9 ++++++++ .../RunCMake/BuildDepends/RunCMakeTest.cmake | 4 ++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/BuildDepends/CustomCommandDependencies-compiler-deps-legacy.cmake diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 98c61fe8be5..a3e5553d747 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -324,9 +324,25 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() this->LocalGenerator->MaybeRelativeToTopBinDir(dependFileNameFull)) << "\n"; + // Scan any custom commands to check if DEPFILE option is specified + bool ccGenerateDeps = false; + std::vector<cmSourceFile const*> customCommands; + this->GeneratorTarget->GetCustomCommands(customCommands, + this->GetConfigName()); + for (cmSourceFile const* sf : customCommands) { + if (!sf->GetCustomCommand()->GetDepfile().empty()) { + ccGenerateDeps = true; + break; + } + } + std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER"; - if (!this->Makefile->IsDefinitionSet(depsUseCompiler) || - this->Makefile->IsOn(depsUseCompiler)) { + bool compilerGenerateDeps = + this->GlobalGenerator->SupportsCompilerDependencies() && + (!this->Makefile->IsDefinitionSet(depsUseCompiler) || + this->Makefile->IsOn(depsUseCompiler)); + + if (compilerGenerateDeps || ccGenerateDeps) { std::string compilerDependFile = cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make"); *this->BuildFileStream << "# Include any dependencies generated by the " @@ -361,7 +377,9 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() "management for " << this->GeneratorTarget->GetName() << ".\n"; } + } + if (compilerGenerateDeps) { // deactivate no longer needed legacy dependency files // Write an empty dependency file. cmGeneratedFileStream legacyDepFileStream( diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies-compiler-deps-legacy.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-compiler-deps-legacy.cmake new file mode 100644 index 00000000000..e13efb3023f --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-compiler-deps-legacy.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +add_custom_command(OUTPUT main.c + DEPFILE main.c.d + COMMAND "${CMAKE_COMMAND}" -DINFILE=${CMAKE_CURRENT_SOURCE_DIR}/main.c -DOUTFILE=main.c -DDEPFILE=main.c.d + -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + +add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index f8c20c2ea1e..27bbff69b89 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -170,6 +170,10 @@ endif() if (RunCMake_GENERATOR MATCHES "Makefiles") run_cmake(CustomCommandDependencies-BadArgs) + run_cmake_with_options(CustomCommandDependencies-compiler-deps-legacy -DCMAKE_DEPENDS_USE_COMPILER=FALSE) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(CustomCommandDependencies-compiler-deps-legacy ${CMAKE_COMMAND} --build . --config Debug) + unset(RunCMake_TEST_NO_CLEAN) endif() if(RunCMake_GENERATOR MATCHES "Make|Ninja|Visual Studio|Xcode" AND From 795e406e3bbd99024652f44fc121f36cd291c269 Mon Sep 17 00:00:00 2001 From: Johnny Jazeix <jazeix@gmail.com> Date: Sun, 1 Aug 2021 18:27:49 +0200 Subject: [PATCH 1048/1519] CPack/NSIS: Add option to not display license page Fixes: #22215 --- Help/cpack_gen/nsis.rst | 6 ++++++ Help/release/dev/nsis_ignore_install_page.rst | 6 ++++++ Modules/Internal/CPack/NSIS.template.in | 2 +- Source/CPack/cmCPackNSISGenerator.cxx | 7 +++++++ Tests/CPackNSISGenerator/CMakeLists.txt | 1 + Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake | 9 +++++++++ 6 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/nsis_ignore_install_page.rst diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst index 02e33ba30eb..05c57c20084 100644 --- a/Help/cpack_gen/nsis.rst +++ b/Help/cpack_gen/nsis.rst @@ -201,3 +201,9 @@ on Windows Nullsoft Scriptable Install System. .. versionadded:: 3.21 If set, specify the name of the NSIS executable. Default is ``makensis``. + +.. variable:: CPACK_NSIS_IGNORE_LICENSE_PAGE + + .. versionadded:: 3.22 + + If set, do not display the page containing the license during installation. diff --git a/Help/release/dev/nsis_ignore_install_page.rst b/Help/release/dev/nsis_ignore_install_page.rst new file mode 100644 index 00000000000..2d8a8d05f9b --- /dev/null +++ b/Help/release/dev/nsis_ignore_install_page.rst @@ -0,0 +1,6 @@ +nsis_ignore_install_page +------------------------ + +* The :cpack_gen:`CPack NSIS Generator` gained a new variable + :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` to ignore the + license page in the installer. diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index 848691f4410..1df8a5885f6 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -540,7 +540,7 @@ FunctionEnd @CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE@ !insertmacro MUI_PAGE_WELCOME - !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" + @CPACK_NSIS_LICENSE_PAGE@ Page custom InstallOptionsPage !insertmacro MUI_PAGE_DIRECTORY diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 6bd0d1b2a89..4a494e14ac9 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -235,6 +235,13 @@ int cmCPackNSISGenerator::PackageFiles() brandingTextCode.c_str()); } + if (!this->IsSet("CPACK_NSIS_IGNORE_LICENSE_PAGE")) { + std::string licenceCode = + cmStrCat("!insertmacro MUI_PAGE_LICENSE \"", + this->GetOption("CPACK_RESOURCE_FILE_LICENSE"), "\"\n"); + this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode.c_str()); + } + // Setup all of the component sections if (this->Components.empty()) { this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", ""); diff --git a/Tests/CPackNSISGenerator/CMakeLists.txt b/Tests/CPackNSISGenerator/CMakeLists.txt index 64a8ef6a5e6..5d6320b8b17 100644 --- a/Tests/CPackNSISGenerator/CMakeLists.txt +++ b/Tests/CPackNSISGenerator/CMakeLists.txt @@ -19,5 +19,6 @@ set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) set(CPACK_NSIS_MANIFEST_DPI_AWARE ON) set(CPACK_NSIS_BRANDING_TEXT "CMake branding text") set(CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION "RIGHT") +set(CPACK_NSIS_IGNORE_LICENSE_PAGE ON) include(CPack) diff --git a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake index 8bfcf26f5bb..31a2560e1f7 100644 --- a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake +++ b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake @@ -60,3 +60,12 @@ if("${output_index}" EQUAL "-1") else() message(STATUS "Found BrandingText") endif() + +# license page should not be present +file(STRINGS "${project_file}" line REGEX "!insertmacro MUI_PAGE_LICENSE") +string(FIND "${line}" "MUI_PAGE_LICENSE" output_index) +if("${output_index}" EQUAL "-1") + message(STATUS "License not found in the project") +else() + message(FATAL_ERROR "License found in the project") +endif() From 09217f2779f688779cde33a81d7167acf14ed3ee Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 2 Aug 2021 00:01:15 -0400 Subject: [PATCH 1049/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 38570b5da52..2b24fba7831 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210801) +set(CMake_VERSION_PATCH 20210802) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 8b28fe567040303581d7e343e95a73bae8b80b52 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 2 Aug 2021 11:12:46 +0200 Subject: [PATCH 1050/1519] Help: get_filename_component: fix version info for cmake_path Fixes: #22505 --- Help/command/get_filename_component.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/command/get_filename_component.rst b/Help/command/get_filename_component.rst index be9d00af30a..4bdd3885dc6 100644 --- a/Help/command/get_filename_component.rst +++ b/Help/command/get_filename_component.rst @@ -3,7 +3,7 @@ get_filename_component Get a specific component of a full filename. -.. versionchanged:: 3.19 +.. versionchanged:: 3.20 This command been superseded by :command:`cmake_path` command, except ``REALPATH`` now offered by :ref:`file(REAL_PATH) <REAL_PATH>` command and ``PROGRAM`` now available in :command:`separate_arguments(PROGRAM)` command. From aafa392c12f6fe04893bc5327af429f5321fbb9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antons=20Je=C4=BCkins?= <Antons.Jelkins@bmw.de> Date: Wed, 21 Jul 2021 15:52:45 +0200 Subject: [PATCH 1051/1519] string(TIMESTAMP): Add %V specifier for ISO 8601 week number In ISO 8601 weeks begin with Monday. The first week of the year is the week which contains the first Thursday of the year. --- Help/command/string.rst | 5 ++++ .../dev/string-TIMESTAMP-specifier-V.rst | 5 ++++ Source/cmTimestamp.cxx | 23 +++++++++++++++++++ Tests/RunCMake/string/Timestamp-stderr.txt | 2 +- Tests/RunCMake/string/Timestamp.cmake | 2 +- 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/string-TIMESTAMP-specifier-V.rst diff --git a/Help/command/string.rst b/Help/command/string.rst index 6fac0e65f8a..29ad082a905 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -493,6 +493,11 @@ specifiers: ``%U`` The week number of the current year (00-53). +``%V`` + .. versionadded:: 3.22 + + The ISO 8601 week number of the current year (01-53). + ``%w`` The day of the current week. 0 is Sunday. (0-6) diff --git a/Help/release/dev/string-TIMESTAMP-specifier-V.rst b/Help/release/dev/string-TIMESTAMP-specifier-V.rst new file mode 100644 index 00000000000..afd3f036955 --- /dev/null +++ b/Help/release/dev/string-TIMESTAMP-specifier-V.rst @@ -0,0 +1,5 @@ +string-TIMESTAMP-specifier-V +---------------------------- + +* The :command:`string(TIMESTAMP)` command now supports the ``%V`` + specifier for ISO 8601 week numbers. diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 056696d4b17..cfea4cff2f9 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -18,6 +18,10 @@ #include <cstring> #include <sstream> +#ifdef __MINGW32__ +# include <libloaderapi.h> +#endif + #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -159,6 +163,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag, case 'M': case 'S': case 'U': + case 'V': case 'w': case 'y': case 'Y': @@ -187,6 +192,24 @@ std::string cmTimestamp::AddTimestampComponent(char flag, } } +#ifdef __MINGW32__ + /* See a bug in MinGW: https://sourceforge.net/p/mingw-w64/bugs/793/. A work + * around is to try to use strftime() from ucrtbase.dll. */ + using T = size_t(WINAPI*)(char*, size_t, const char*, const struct tm*); + auto loadStrftime = [] { + auto handle = + LoadLibraryExA("ucrtbase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (handle) { +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-function-type" + return reinterpret_cast<T>(GetProcAddress(handle, "strftime")); +# pragma GCC diagnostic pop + } + return strftime; + }; + static T strftime = loadStrftime(); +#endif + char buffer[16]; size_t size = diff --git a/Tests/RunCMake/string/Timestamp-stderr.txt b/Tests/RunCMake/string/Timestamp-stderr.txt index cd4dcb37e68..d54777bd71f 100644 --- a/Tests/RunCMake/string/Timestamp-stderr.txt +++ b/Tests/RunCMake/string/Timestamp-stderr.txt @@ -1 +1 @@ -RESULT=2005-08-07 23:19:49 Sunday=Sun August=Aug 05 day=219 wd=0 week=32 %I=11 epoch=1123456789 +RESULT=2005-08-07 23:19:49 Sunday=Sun August=Aug 05 day=219 wd=0 week=32 w_iso=31 %I=11 epoch=1123456789 diff --git a/Tests/RunCMake/string/Timestamp.cmake b/Tests/RunCMake/string/Timestamp.cmake index cba258d12bf..7fd6d72b0d8 100644 --- a/Tests/RunCMake/string/Timestamp.cmake +++ b/Tests/RunCMake/string/Timestamp.cmake @@ -1,3 +1,3 @@ set(ENV{SOURCE_DATE_EPOCH} "1123456789") -string(TIMESTAMP RESULT "%Y-%m-%d %H:%M:%S %A=%a %B=%b %y day=%j wd=%w week=%U %%I=%I epoch=%s" UTC) +string(TIMESTAMP RESULT "%Y-%m-%d %H:%M:%S %A=%a %B=%b %y day=%j wd=%w week=%U w_iso=%V %%I=%I epoch=%s" UTC) message("RESULT=${RESULT}") From 076d0a1710722bf88b1e3a70caa7b0f5c0a05915 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Mon, 2 Aug 2021 10:40:57 -0400 Subject: [PATCH 1052/1519] FindX11: mark more xcb variables as advanced --- Modules/FindX11.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake index d480fc48033..fd5ee53954e 100644 --- a/Modules/FindX11.cmake +++ b/Modules/FindX11.cmake @@ -828,6 +828,12 @@ if (UNIX) X11_Xau_INCLUDE_PATH X11_xcb_LIB X11_xcb_INCLUDE_PATH + X11_xcb_icccm_LIB + X11_xcb_icccm_INCLUDE_PATH + X11_xcb_util_LIB + X11_xcb_util_INCLUDE_PATH + X11_xcb_xfixes_LIB + X11_xcb_xfixes_INCLUDE_PATH X11_xcb_xkb_LIB X11_X11_xcb_LIB X11_X11_xcb_INCLUDE_PATH From 7391363302d36da3ed8c421210c15dbaa69ad896 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Thu, 29 Jul 2021 20:45:01 -0400 Subject: [PATCH 1053/1519] VTKCompatibility: ignore for "modern" VTK Modern versions which use the module system really don't need any of the hacks needed here. --- Modules/VTKCompatibility.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/VTKCompatibility.cmake b/Modules/VTKCompatibility.cmake index 1b0815e853d..4ee7643c208 100644 --- a/Modules/VTKCompatibility.cmake +++ b/Modules/VTKCompatibility.cmake @@ -1,6 +1,10 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. +# Not needed for "modern" VTK. +if (EXISTS "${VTK_SOURCE_DIR}/CMake/vtkModule.cmake") + return () +endif () if(APPLE) set(CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}") From 58d10cf6f13493db124af18e3cac127b2164ea59 Mon Sep 17 00:00:00 2001 From: Felix Lelchuk <felix.lelchuk@gmx.de> Date: Mon, 2 Aug 2021 19:42:26 +0200 Subject: [PATCH 1054/1519] Alternative symlink-creating mode for file(INSTALL ...) An new environment variable 'CMAKE_INSTALL_MODE' is introduced, which can be used to ask CMake to create symbolic links instead of copying files during a file(INSTALL ...). The operation is at the file level only, directory trees are still created using actual directories, not links. Signed-off-by: Felix Lelchuk <felix.lelchuk@gmx.de> --- Help/command/file.rst | 5 + Help/command/install.rst | 4 + Help/envvar/CMAKE_INSTALL_MODE.rst | 37 ++++++ Help/manual/cmake-env-variables.7.rst | 1 + .../dev/cmake-install-mode-symlink.rst | 16 +++ Source/cmFileCopier.h | 5 +- Source/cmFileInstaller.cxx | 118 +++++++++++++++++ Source/cmFileInstaller.h | 5 +- Source/cmInstallMode.h | 17 +++ Tests/CMakeLists.txt | 48 +++++++ Tests/InstallMode/CMakeLists.txt | 124 ++++++++++++++++++ Tests/InstallMode/README.txt | 43 ++++++ Tests/InstallMode/Subproject.cmake | 76 +++++++++++ Tests/InstallMode/Test.cmake | 38 ++++++ .../subpro_a_static_lib/CMakeLists.txt | 60 +++++++++ .../cmake/PackageConfig.cmake.in | 8 ++ .../subpro_a_static_lib/include/static_lib.h | 3 + .../subpro_a_static_lib/src/static_lib.cpp | 10 ++ .../subpro_b_shared_lib/CMakeLists.txt | 66 ++++++++++ .../cmake/PackageConfig.cmake.in | 8 ++ .../subpro_b_shared_lib/include/shared_lib.h | 3 + .../subpro_b_shared_lib/src/shared_lib.cpp | 10 ++ .../subpro_c_nested_lib/CMakeLists.txt | 10 ++ .../subsubpro_c1_lib/CMakeLists.txt | 61 +++++++++ .../cmake/PackageConfig.cmake.in | 8 ++ .../subsubpro_c1_lib/include/c1_lib.h | 3 + .../subsubpro_c1_lib/src/c1_lib.cpp | 10 ++ .../subsubpro_c2_lib/CMakeLists.txt | 68 ++++++++++ .../cmake/PackageConfig.cmake.in | 11 ++ .../subsubpro_c2_lib/include/c2_lib.h | 3 + .../subsubpro_c2_lib/src/c2_lib.cpp | 12 ++ .../subpro_d_executable/CMakeLists.txt | 24 ++++ .../subpro_d_executable/src/main.cpp | 13 ++ Tests/InstallMode/superpro/CMakeLists.txt | 29 ++++ Tests/InstallMode/superpro/file_copy.txt | 1 + Tests/InstallMode/superpro/file_copy_file.txt | 1 + .../superpro/file_create_link_symbolic.txt | 2 + Tests/InstallMode/superpro/file_install.txt | 6 + 38 files changed, 964 insertions(+), 3 deletions(-) create mode 100644 Help/envvar/CMAKE_INSTALL_MODE.rst create mode 100644 Help/release/dev/cmake-install-mode-symlink.rst create mode 100644 Source/cmInstallMode.h create mode 100644 Tests/InstallMode/CMakeLists.txt create mode 100644 Tests/InstallMode/README.txt create mode 100644 Tests/InstallMode/Subproject.cmake create mode 100644 Tests/InstallMode/Test.cmake create mode 100644 Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt create mode 100644 Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in create mode 100644 Tests/InstallMode/subpro_a_static_lib/include/static_lib.h create mode 100644 Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp create mode 100644 Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt create mode 100644 Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in create mode 100644 Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h create mode 100644 Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp create mode 100644 Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h create mode 100644 Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp create mode 100644 Tests/InstallMode/subpro_d_executable/CMakeLists.txt create mode 100644 Tests/InstallMode/subpro_d_executable/src/main.cpp create mode 100644 Tests/InstallMode/superpro/CMakeLists.txt create mode 100644 Tests/InstallMode/superpro/file_copy.txt create mode 100644 Tests/InstallMode/superpro/file_copy_file.txt create mode 100644 Tests/InstallMode/superpro/file_create_link_symbolic.txt create mode 100644 Tests/InstallMode/superpro/file_install.txt diff --git a/Help/command/file.rst b/Help/command/file.rst index f038871b7b2..96a55ee8018 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -843,6 +843,11 @@ and ``NO_SOURCE_PERMISSIONS`` is default. Installation scripts generated by the :command:`install` command use this signature (with some undocumented options for internal use). +.. versionchanged:: 3.22 + + The environment variable :envvar:`CMAKE_INSTALL_MODE` can override the + default copying behavior of :command:`file(INSTALL)`. + .. _SIZE: .. code-block:: cmake diff --git a/Help/command/install.rst b/Help/command/install.rst index c6af4897e0f..1236f1d32b7 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -30,6 +30,10 @@ are executed in order during installation. with those in the parent directory to run in the order declared (see policy :policy:`CMP0082`). +.. versionchanged:: 3.22 + The environment variable :envvar:`CMAKE_INSTALL_MODE` can override the + default copying behavior of :command:`install()`. + There are multiple signatures for this command. Some of them define installation options for files and targets. Options common to multiple signatures are covered here but they are valid only for diff --git a/Help/envvar/CMAKE_INSTALL_MODE.rst b/Help/envvar/CMAKE_INSTALL_MODE.rst new file mode 100644 index 00000000000..37db0d71404 --- /dev/null +++ b/Help/envvar/CMAKE_INSTALL_MODE.rst @@ -0,0 +1,37 @@ +CMAKE_INSTALL_MODE +------------------ + +.. versionadded:: 3.22 + +.. include:: ENV_VAR.txt + +The ``CMAKE_INSTALL_MODE`` environment variable allows users to operate +CMake in an alternate mode of :command:`file(INSTALL)` and :command:`install()`. + +The default behavior for an installation is to copy a source file from a +source directory into a destination directory. This environment variable +however allows the user to override this behavior, causing CMake to create +symbolic links instead. + +.. note:: + A symbolic link consists of a reference file path rather than contents of its own, + hence there are two ways to express the relation, either by a relative or an absolute path. + +The following values are allowed for ``CMAKE_INSTALL_MODE``: + +* empty, unset or ``COPY``: default behavior, duplicate the file at its destination +* ``ABS_SYMLINK``: create an *absolute* symbolic link to the source file at the destination *or fail* +* ``ABS_SYMLINK_OR_COPY``: like ``ABS_SYMLINK`` but silently copy on error +* ``REL_SYMLINK``: create an *relative* symbolic link to the source file at the destination *or fail* +* ``REL_SYMLINK_OR_COPY``: like ``REL_SYMLINK`` but silently copy on error +* ``SYMLINK``: try as if through ``REL_SYMLINK`` and fall back to ``ABS_SYMLINK`` if the referenced + file cannot be expressed using a relative path. Fail on error. +* ``SYMLINK_OR_COPY``: like ``SYMLINK`` but silently copy on error + +Installing symbolic links rather than copying files can help conserve storage space because files do +not have to be duplicated on disk. However, modifications applied to the source immediately affects +the symbolic link and vice versa. *Use with caution*. + +.. note:: ``CMAKE_INSTALL_MODE`` only affects files, *not* directories. + +.. note:: Symbolic links are not available on all platforms. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index 3db189efffd..0799fddb67a 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -38,6 +38,7 @@ Environment Variables that Control the Build /envvar/CMAKE_GENERATOR_INSTANCE /envvar/CMAKE_GENERATOR_PLATFORM /envvar/CMAKE_GENERATOR_TOOLSET + /envvar/CMAKE_INSTALL_MODE /envvar/CMAKE_LANG_COMPILER_LAUNCHER /envvar/CMAKE_LANG_LINKER_LAUNCHER /envvar/CMAKE_MSVCIDE_RUN_PATH diff --git a/Help/release/dev/cmake-install-mode-symlink.rst b/Help/release/dev/cmake-install-mode-symlink.rst new file mode 100644 index 00000000000..a5f75ca2b0f --- /dev/null +++ b/Help/release/dev/cmake-install-mode-symlink.rst @@ -0,0 +1,16 @@ +cmake-install-mode-symlink +-------------------------- + +* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to + allow users to override the default file-copying behavior of + :command:`install` and :command:`file(INSTALL)` into creating + symbolic links. This can aid in lowering storage space requirements + and avoiding redundancy. + +* The :command:`file(INSTALL)` can now be affected / modified by the + :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation + of symbolic links instead of copying of files. + +* The :command:`install` can now be affected / modified by the + :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation + of symbolic links instead of copying of files. diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h index 217d58d28db..ee9872d9d19 100644 --- a/Source/cmFileCopier.h +++ b/Source/cmFileCopier.h @@ -67,8 +67,9 @@ struct cmFileCopier bool InstallSymlinkChain(std::string& fromFile, std::string& toFile); bool InstallSymlink(const std::string& fromFile, const std::string& toFile); - bool InstallFile(const std::string& fromFile, const std::string& toFile, - MatchProperties match_properties); + virtual bool InstallFile(const std::string& fromFile, + const std::string& toFile, + MatchProperties match_properties); bool InstallDirectory(const std::string& source, const std::string& destination, MatchProperties match_properties); diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx index c89be9628e7..0d8ba2d2662 100644 --- a/Source/cmFileInstaller.cxx +++ b/Source/cmFileInstaller.cxx @@ -3,7 +3,12 @@ #include "cmFileInstaller.h" +#include <map> #include <sstream> +#include <utility> + +#include <cm/string_view> +#include <cmext/string_view> #include "cm_sys_stat.h" @@ -18,6 +23,7 @@ using namespace cmFSPermissions; cmFileInstaller::cmFileInstaller(cmExecutionStatus& status) : cmFileCopier(status, "INSTALL") , InstallType(cmInstallType_FILES) + , InstallMode(cmInstallMode::COPY) , Optional(false) , MessageAlways(false) , MessageLazy(false) @@ -82,6 +88,93 @@ bool cmFileInstaller::Install(const std::string& fromFile, return this->cmFileCopier::Install(fromFile, toFile); } +bool cmFileInstaller::InstallFile(const std::string& fromFile, + const std::string& toFile, + MatchProperties match_properties) +{ + if (this->InstallMode == cmInstallMode::COPY) { + return this->cmFileCopier::InstallFile(fromFile, toFile, match_properties); + } + + std::string newFromFile; + + if (this->InstallMode == cmInstallMode::REL_SYMLINK || + this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY || + this->InstallMode == cmInstallMode::SYMLINK || + this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) { + // Try to get a relative path. + std::string toDir = cmSystemTools::GetParentDirectory(toFile); + newFromFile = cmSystemTools::ForceToRelativePath(toDir, fromFile); + + // Double check that we can restore the original path. + std::string reassembled = + cmSystemTools::CollapseFullPath(newFromFile, toDir); + if (!cmSystemTools::ComparePath(reassembled, fromFile)) { + if (this->InstallMode == cmInstallMode::SYMLINK || + this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) { + // User does not mind, silently proceed with absolute path. + newFromFile = fromFile; + } else if (this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY) { + // User expects a relative symbolic link or a copy. + // Since an absolute symlink won't do, copy instead. + return this->cmFileCopier::InstallFile(fromFile, toFile, + match_properties); + } else { + // We cannot meet user's expectation (REL_SYMLINK) + auto e = cmStrCat(this->Name, + " cannot determine relative path for symlink to \"", + newFromFile, "\" at \"", toFile, "\"."); + this->Status.SetError(e); + return false; + } + } + } else { + newFromFile = fromFile; // stick with absolute path + } + + // Compare the symlink value to that at the destination if not + // always installing. + bool copy = true; + if (!this->Always) { + std::string oldSymlinkTarget; + if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) { + if (newFromFile == oldSymlinkTarget) { + copy = false; + } + } + } + + // Inform the user about this file installation. + this->ReportCopy(toFile, TypeLink, copy); + + if (copy) { + // Remove the destination file so we can always create the symlink. + cmSystemTools::RemoveFile(toFile); + + // Create destination directory if it doesn't exist + cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile)); + + // Create the symlink. + if (!cmSystemTools::CreateSymlink(newFromFile, toFile)) { + if (this->InstallMode == cmInstallMode::ABS_SYMLINK_OR_COPY || + this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY || + this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) { + // Failed to create a symbolic link, fall back to copying. + return this->cmFileCopier::InstallFile(newFromFile, toFile, + match_properties); + } + + auto e = cmStrCat(this->Name, " cannot create symlink to \"", + newFromFile, "\" at \"", toFile, + "\": ", cmSystemTools::GetLastSystemError(), "\"."); + this->Status.SetError(e); + return false; + } + } + + return true; +} + void cmFileInstaller::DefaultFilePermissions() { this->cmFileCopier::DefaultFilePermissions(); @@ -141,6 +234,31 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args) return false; } + static const std::map<cm::string_view, cmInstallMode> install_mode_dict{ + { "ABS_SYMLINK"_s, cmInstallMode::ABS_SYMLINK }, + { "ABS_SYMLINK_OR_COPY"_s, cmInstallMode::ABS_SYMLINK_OR_COPY }, + { "REL_SYMLINK"_s, cmInstallMode::REL_SYMLINK }, + { "REL_SYMLINK_OR_COPY"_s, cmInstallMode::REL_SYMLINK_OR_COPY }, + { "SYMLINK"_s, cmInstallMode::SYMLINK }, + { "SYMLINK_OR_COPY"_s, cmInstallMode::SYMLINK_OR_COPY } + }; + + std::string install_mode; + cmSystemTools::GetEnv("CMAKE_INSTALL_MODE", install_mode); + if (install_mode.empty() || install_mode == "COPY"_s) { + this->InstallMode = cmInstallMode::COPY; + } else { + auto it = install_mode_dict.find(install_mode); + if (it != install_mode_dict.end()) { + this->InstallMode = it->second; + } else { + auto e = cmStrCat("Unrecognized value '", install_mode, + "' for environment variable CMAKE_INSTALL_MODE"); + this->Status.SetError(e); + return false; + } + } + return true; } diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h index 3a905d320d8..3f6bd454224 100644 --- a/Source/cmFileInstaller.h +++ b/Source/cmFileInstaller.h @@ -8,6 +8,7 @@ #include <vector> #include "cmFileCopier.h" +#include "cmInstallMode.h" #include "cmInstallType.h" class cmExecutionStatus; @@ -19,6 +20,7 @@ struct cmFileInstaller : public cmFileCopier protected: cmInstallType InstallType; + cmInstallMode InstallMode; bool Optional; bool MessageAlways; bool MessageLazy; @@ -35,7 +37,8 @@ struct cmFileInstaller : public cmFileCopier bool ReportMissing(const std::string& fromFile) override; bool Install(const std::string& fromFile, const std::string& toFile) override; - + bool InstallFile(const std::string& fromFile, const std::string& toFile, + MatchProperties match_properties) override; bool Parse(std::vector<std::string> const& args) override; enum { diff --git a/Source/cmInstallMode.h b/Source/cmInstallMode.h new file mode 100644 index 00000000000..5343d34a4e7 --- /dev/null +++ b/Source/cmInstallMode.h @@ -0,0 +1,17 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +/** + * Enumerate types known to file(INSTALL). + */ +enum class cmInstallMode +{ + COPY, + ABS_SYMLINK, + ABS_SYMLINK_OR_COPY, + REL_SYMLINK, + REL_SYMLINK_OR_COPY, + SYMLINK, + SYMLINK_OR_COPY +}; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 388ff207a81..e59cdfb52c8 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1641,6 +1641,54 @@ if(BUILD_TESTING) WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate DEPENDS ExternalProjectUpdateSetup ) + execute_process( + COMMAND ${CMAKE_CMAKE_COMMAND} + "-E" create_symlink + "${CMake_SOURCE_DIR}/Tests/CMakeLists.txt" # random source file that exists + "${CMake_BINARY_DIR}/Tests/try_to_create_symlink" # random target file in existing directory + RESULT_VARIABLE _failed + ) + if(_failed) + message("Failed to create a simple symlink on this machine. Skipping InstallMode tests.") + else() + function(add_installmode_test _mode) + set(ENV{CMAKE_INSTALL_MODE} _mode) + set(_maybe_InstallMode_CTEST_OPTIONS) + set(_maybe_BUILD_OPTIONS) + if(_isMultiConfig) + set(_maybe_CTEST_OPTIONS -C $<CONFIGURATION>) + else() + set(_maybe_BUILD_OPTIONS "-DCMAKE_BUILD_TYPE=$<CONFIGURATION>") + endif() + add_test( + NAME "InstallMode-${_mode}" + COMMAND + ${CMAKE_CTEST_COMMAND} -V ${_maybe_CTEST_OPTIONS} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/InstallMode" + "${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}" + ${build_generator_args} + --build-project superpro + --build-exe-dir "${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}" + --force-new-ctest-process + --build-options + ${_maybe_BUILD_OPTIONS} + "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}/install" + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}") + unset(ENV{CMAKE_INSTALL_MODE}) + endfunction() + + add_installmode_test(COPY) + add_installmode_test(REL_SYMLINK) + add_installmode_test(REL_SYMLINK_OR_COPY) + add_installmode_test(ABS_SYMLINK) + add_installmode_test(ABS_SYMLINK_OR_COPY) + add_installmode_test(SYMLINK) + add_installmode_test(SYMLINK_OR_COPY) + endif() + + # do each of the tutorial steps function(add_tutorial_test step_name use_mymath tutorial_arg pass_regex) set(tutorial_test_name Tutorial${step_name}) diff --git a/Tests/InstallMode/CMakeLists.txt b/Tests/InstallMode/CMakeLists.txt new file mode 100644 index 00000000000..96c83a05d5f --- /dev/null +++ b/Tests/InstallMode/CMakeLists.txt @@ -0,0 +1,124 @@ +cmake_minimum_required(VERSION 3.20.0) + +project(superpro LANGUAGES NONE) + +add_subdirectory(superpro) + +include(Subproject.cmake) +add_subproject(static_lib DIR subpro_a_static_lib) +add_subproject(shared_lib DIR subpro_b_shared_lib) +add_subproject(nested_lib DIR subpro_c_nested_lib NO_INSTALL) +add_subproject(executable DIR subpro_d_executable + DEPENDS + static_lib + shared_lib + nested_lib +) + +include(CTest) +if(BUILD_TESTING) + enable_language(CXX) # required by GNUInstallDirs + include(GNUInstallDirs) + + macro(testme _name _path _symlink) + add_test( + NAME "${_name}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMAND + "${CMAKE_COMMAND}" + "-DFILE_PATH=${CMAKE_INSTALL_PREFIX}/${_path}" + "-DEXPECT_SYMLINK:BOOL=${_symlink}" + "-DEXPECT_ABSOLUTE:BOOL=${ARGN}" + "-P" "${CMAKE_SOURCE_DIR}/Test.cmake" + ) + endmacro() + + set(_mode $ENV{CMAKE_INSTALL_MODE}) + if(NOT "${_mode}" OR "${_mode}" STREQUAL "COPY") + set(expect_symlink NO) + elseif("${_mode}" MATCHES "(REL_)?SYMLINK(_OR_COPY)?") + set(expect_symlink YES) + set(expect_absolute NO) + elseif("${_mode}" MATCHES "ABS_SYMLINK(_OR_COPY)?") + set(expect_symlink YES) + set(expect_absolute YES) + endif() + + # toplevel project should respect CMAKE_INSTALL_MODE + + testme(superproj_file_copy + "file_copy.txt" NO) + testme(superproj_file_copy_file + "file_copy_file.txt" NO) + testme(superproj_file_install + "file_install.txt" + ${expect_symlink} + ${expect_absolute}) + testme(superproj_file_create_link_symbolic + "file_create_link_symbolic.txt" YES YES) + + # subprojects should receive and respect CMAKE_INSTALL_MODE too + + testme(subpro_a_static_lib_header + "${CMAKE_INSTALL_INCLUDEDIR}/static_lib.h" + ${expect_symlink} + ${expect_absolute} + ) + testme(subpro_a_static_lib_libfile + "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}the_static_lib${CMAKE_STATIC_LIBRARY_SUFFIX}" + ${expect_symlink} + ${expect_absolute} + ) + + testme(subpro_b_shared_lib_header + "${CMAKE_INSTALL_INCLUDEDIR}/shared_lib.h" + ${expect_symlink} + ${expect_absolute} + ) + + if(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG AND + "${CMAKE_CXX_CREATE_SHARED_MODULE}" MATCHES "SONAME_FLAG") + # due to semver, this is always a link + testme(subpro_b_shared_lib_libfile + "${CMAKE_INSTALL_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}the_shared_lib${CMAKE_SHARED_LIBRARY_SUFFIX}" + YES + ${expect_absolute} + ) + # this is the actual shared lib, so should follow CMAKE_INSTALL_MODE rules + testme(subpro_b_shared_lib_libfile_versuffix + "${CMAKE_INSTALL_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}the_shared_lib${CMAKE_SHARED_LIBRARY_SUFFIX}.2.3.4" + ${expect_symlink} + ${expect_absolute} + ) + endif() + + testme(subpro_d_executable_exefile + "${CMAKE_INSTALL_BINDIR}/the_executable${CMAKE_EXECUTABLE_SUFFIX}" + ${expect_symlink} + ${expect_absolute} + ) + + # nested subprojects should receive and respect CMAKE_INSTALL_MODE too + + testme(subsubpro_c1_header + "${CMAKE_INSTALL_INCLUDEDIR}/c1_lib.h" + ${expect_symlink} + ${expect_absolute} + ) + testme(subsubpro_c1_libfile + "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}the_c1_lib${CMAKE_STATIC_LIBRARY_SUFFIX}" + ${expect_symlink} + ${expect_absolute} + ) + + testme(subsubpro_c2_header + "${CMAKE_INSTALL_INCLUDEDIR}/c2_lib.h" + ${expect_symlink} + ${expect_absolute} + ) + testme(subsubpro_c2_libfile + "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}the_c2_lib${CMAKE_STATIC_LIBRARY_SUFFIX}" + ${expect_symlink} + ${expect_absolute} + ) +endif() diff --git a/Tests/InstallMode/README.txt b/Tests/InstallMode/README.txt new file mode 100644 index 00000000000..a4316ebb530 --- /dev/null +++ b/Tests/InstallMode/README.txt @@ -0,0 +1,43 @@ +This is an example superbuild project to demonstrate the use of the +CMAKE_INSTALL_MODE environment variable on. + +The project hierarchy is like (B = Builds / D = Link Dependency): + ++---------------------------------------------------------------------+ +| Superbuild (Top) | ++---------------------------------------------------------------------+ + | | | | + | | | | + (B) (B) (B) (B) + | | | | + v v v v ++---------------+ +---------------+ +---------------+ +---------------+ +| A: Static Lib | | B: Shared Lib | | C: Nested | | D: Executable | +| Project | | Project | | Superbuild | | Project | ++---------------+ +---------------+ +---------------+ +---------------+ + ^ ^ | | | | | + | | (B) (B) | | | + | | | | | | | + | | v | | | | + | | +----------------+ | | | | + | | | C1: Static Lib | | | | | + | | | Project | | (D) (D) (D) + | | +----------------+ | | | | + | | ^ | | | | + | | | v | | | + | | (D) +----------------+ | | | + | | | | C2: Static Lib |<---+ | | + | | +--| Project | | | + | | +----------------+ | | + | | | | + | +------------------------------------+ | + | | + +--------------------------------------------------------+ + +The superbuild system is built on top of ExternalProject_Add(). + +NOTE that the subprojects will configure, build and install +during the build phase ('make') of the top-level project. +There is no install target in the top-level project! +The CMAKE_INSTALL_PREFIX is therefore populated during the build +phase already. diff --git a/Tests/InstallMode/Subproject.cmake b/Tests/InstallMode/Subproject.cmake new file mode 100644 index 00000000000..e4354d67ee7 --- /dev/null +++ b/Tests/InstallMode/Subproject.cmake @@ -0,0 +1,76 @@ +include(ExternalProject) + +# add_subproject(<name> [NO_INSTALL] [DIR <dirname>] [DEPENDS [subpro_dep ...]]) +function(add_subproject _name) + cmake_parse_arguments(_arg "NO_INSTALL" "DIR" "DEPENDS" ${ARGN}) + + if(_arg_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "There are unparsed arguments") + endif() + + set(_maybe_NO_INSTALL) + if(_arg_NO_INSTALL) + set(_maybe_NO_INSTALL "INSTALL_COMMAND") + else() + # This is a trick to get a valid call. + # Since we set UPDATE_COMMAND to "" + # explicitly below, this won't harm. + set(_maybe_NO_INSTALL "UPDATE_COMMAND") + endif() + + if(CMAKE_GENERATOR MATCHES "Ninja Multi-Config") + # Replace list separator before passing on to ExternalProject_Add + string(REPLACE ";" "|" _CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}") + string(REPLACE ";" "|" _CROSS_CONFIGS "${CMAKE_CROSS_CONFIGS}") + string(REPLACE ";" "|" _DEFAULT_CONFIGS "${CMAKE_DEFAULT_CONFIGS}") + + set(_maybe_NINJA_MULTICONFIG_ARGS + "-DCMAKE_CONFIGURATION_TYPES:STRINGS=${_CONFIGURATION_TYPES}" + "-DCMAKE_CROSS_CONFIGS:STRINGS=${_CROSS_CONFIGS}" + "-DCMAKE_DEFAULT_BUILD_TYPE:STRING=${CMAKE_DEFAULT_BUILD_TYPE}" + "-DCMAKE_DEFAULT_CONFIGS:STRINGS=${_DEFAULT_CONFIGS}" + ) + endif() + + ExternalProject_Add("${_name}" + DOWNLOAD_COMMAND "" + UPDATE_COMMAND "" + ${_maybe_NO_INSTALL} "" + + BUILD_ALWAYS ON + + LOG_DOWNLOAD OFF + LOG_UPDATE OFF + LOG_PATCH OFF + LOG_CONFIGURE OFF + LOG_BUILD OFF + LOG_INSTALL OFF + + SOURCE_DIR "${PROJECT_SOURCE_DIR}/${_arg_DIR}" + + # Private build directory per subproject + BINARY_DIR "${PROJECT_BINARY_DIR}/subproject/${_arg_DIR}" + + # Common install directory, populated immediately + # during build (during build - not install - of superproject) + INSTALL_DIR "${CMAKE_INSTALL_PREFIX}" + + DEPENDS + ${_arg_DEPENDS} + + LIST_SEPARATOR "|" + CMAKE_ARGS + "-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>" + + # We can rely on ExternalProject to pick the right + # generator (and architecture/toolset where applicable), + # however, we need to explicitly inherit other parent + # project's build settings. + "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}" + ${_maybe_NINJA_MULTICONFIG_ARGS} + + # Subproject progress reports clutter up the output, disable + "-DCMAKE_TARGET_MESSAGES:BOOL=OFF" + "-DCMAKE_RULE_MESSAGES:BOOL=OFF" + ) +endfunction() diff --git a/Tests/InstallMode/Test.cmake b/Tests/InstallMode/Test.cmake new file mode 100644 index 00000000000..46c8fa1daeb --- /dev/null +++ b/Tests/InstallMode/Test.cmake @@ -0,0 +1,38 @@ +message("Testing...") +message("FILE_PATH = ${FILE_PATH}") +message("EXPECT_SYMLINK = ${EXPECT_SYMLINK}") +message("EXPECT_ABSOLUTE = ${EXPECT_ABSOLUTE}") + +if(NOT DEFINED FILE_PATH) + message(FATAL_ERROR "FILE_PATH variable must be defined") +endif() + +if(NOT EXISTS "${FILE_PATH}") + message(FATAL_ERROR "File ${FILE_PATH} does not exist") +endif() + +if(NOT DEFINED EXPECT_SYMLINK) + message(FATAL_ERROR "EXPECT_SYMLINK must be defined") +endif() + +if(EXPECT_SYMLINK) + if(NOT DEFINED EXPECT_ABSOLUTE) + message(FATAL_ERROR "EXPECT_ABSOLUTE variable must be defined") + endif() + + if(NOT IS_SYMLINK "${FILE_PATH}") + message(FATAL_ERROR "${FILE_PATH} must be a symlink") + endif() + + file(READ_SYMLINK "${FILE_PATH}" TARGET_PATH) + + if(EXPECT_ABSOLUTE AND NOT IS_ABSOLUTE "${TARGET_PATH}") + message(FATAL_ERROR "${FILE_PATH} must be an absolute symlink") + elseif(NOT EXPECT_ABSOLUTE AND IS_ABSOLUTE "${TARGET_PATH}") + message(FATAL_ERROR "${FILE_PATH} must be a relative symlink") + endif() +else() + if(IS_SYMLINK "${FILE_PATH}") + message(FATAL_ERROR "${FILE_PATH} must NOT be a symlink") + endif() +endif() diff --git a/Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt b/Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt new file mode 100644 index 00000000000..7cd32cc6ef7 --- /dev/null +++ b/Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt @@ -0,0 +1,60 @@ +# This CMakeLists.txt is part of the subproject A (ExternalProject_Add). + +cmake_minimum_required(VERSION 3.20) +project(static_lib_project VERSION 1.2.3 LANGUAGES CXX) + +include(GNUInstallDirs) + +add_library(the_static_lib STATIC + "include/static_lib.h" + "src/static_lib.cpp" +) + +target_include_directories(the_static_lib PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> +) + +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + TARGETS + the_static_lib + EXPORT main + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) + +set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + +include(CMakePackageConfigHelpers) + +configure_package_config_file( + "cmake/PackageConfig.cmake.in" + "${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}" + PATH_VARS + CMAKE_INSTALL_INCLUDEDIR + CMAKE_INSTALL_LIBDIR +) + +write_basic_package_version_file("${PROJECT_NAME}Version.cmake" + VERSION "${PROJECT_VERSION}" + COMPATIBILITY SameMajorVersion +) + +install( + EXPORT main + FILE "${PROJECT_NAME}Targets.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) diff --git a/Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in new file mode 100644 index 00000000000..0fe72c91f51 --- /dev/null +++ b/Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in @@ -0,0 +1,8 @@ +set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@) + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@") diff --git a/Tests/InstallMode/subpro_a_static_lib/include/static_lib.h b/Tests/InstallMode/subpro_a_static_lib/include/static_lib.h new file mode 100644 index 00000000000..bd82d2eea5b --- /dev/null +++ b/Tests/InstallMode/subpro_a_static_lib/include/static_lib.h @@ -0,0 +1,3 @@ +#pragma once + +void static_hello(); diff --git a/Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp b/Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp new file mode 100644 index 00000000000..fe1cd854a7d --- /dev/null +++ b/Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp @@ -0,0 +1,10 @@ +#include <iostream> + +#include <static_lib.h> + +using namespace std; + +void static_hello() +{ + cout << "Hello from static_lib" << endl; +} diff --git a/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt b/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt new file mode 100644 index 00000000000..eb118c9a1b5 --- /dev/null +++ b/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt @@ -0,0 +1,66 @@ +# This CMakeLists.txt is part of the subproject B (ExternalProject_Add). + +cmake_minimum_required(VERSION 3.20) +project(shared_lib_project VERSION 2.3.4 LANGUAGES CXX) + +include(GNUInstallDirs) + +add_library(the_shared_lib SHARED + "include/shared_lib.h" + "src/shared_lib.cpp" +) + +set_target_properties(the_shared_lib + PROPERTIES + VERSION "${PROJECT_VERSION}" + SOVERSION "${PROJECT_VERSION}" +) + +target_include_directories(the_shared_lib PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> +) + +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + TARGETS + the_shared_lib + EXPORT main + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) + +set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + +include(CMakePackageConfigHelpers) + +configure_package_config_file( + "cmake/PackageConfig.cmake.in" + "${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}" + PATH_VARS + CMAKE_INSTALL_INCLUDEDIR + CMAKE_INSTALL_LIBDIR +) + +write_basic_package_version_file("${PROJECT_NAME}Version.cmake" + VERSION "${PROJECT_VERSION}" + COMPATIBILITY SameMajorVersion +) + +install( + EXPORT main + FILE "${PROJECT_NAME}Targets.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) diff --git a/Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in new file mode 100644 index 00000000000..0fe72c91f51 --- /dev/null +++ b/Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in @@ -0,0 +1,8 @@ +set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@) + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@") diff --git a/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h b/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h new file mode 100644 index 00000000000..fd960db019e --- /dev/null +++ b/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h @@ -0,0 +1,3 @@ +#pragma once + +void shared_hello(); diff --git a/Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp b/Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp new file mode 100644 index 00000000000..2820d5d02f6 --- /dev/null +++ b/Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp @@ -0,0 +1,10 @@ +#include <iostream> + +#include <shared_lib.h> + +using namespace std; + +void shared_hello() +{ + cout << "Hello from shared_lib" << endl; +} diff --git a/Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt new file mode 100644 index 00000000000..e397c02e191 --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20.0) + +project(subpro_c_nested_lib LANGUAGES NONE) + +include(../Subproject.cmake) +add_subproject(c1_lib DIR subsubpro_c1_lib) +add_subproject(c2_lib DIR subsubpro_c2_lib + DEPENDS + c1_lib +) diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt new file mode 100644 index 00000000000..89f3755598c --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt @@ -0,0 +1,61 @@ +# This CMakeLists.txt is a nested subproject of the +# subproject C (ExternalProject_Add). + +cmake_minimum_required(VERSION 3.20) +project(c1_lib_project VERSION 1.2.3 LANGUAGES CXX) + +include(GNUInstallDirs) + +add_library(the_c1_lib STATIC + "include/c1_lib.h" + "src/c1_lib.cpp" +) + +target_include_directories(the_c1_lib PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> +) + +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + TARGETS + the_c1_lib + EXPORT main + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) + +set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + +include(CMakePackageConfigHelpers) + +configure_package_config_file( + "cmake/PackageConfig.cmake.in" + "${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}" + PATH_VARS + CMAKE_INSTALL_INCLUDEDIR + CMAKE_INSTALL_LIBDIR +) + +write_basic_package_version_file("${PROJECT_NAME}Version.cmake" + VERSION "${PROJECT_VERSION}" + COMPATIBILITY SameMajorVersion +) + +install( + EXPORT main + FILE "${PROJECT_NAME}Targets.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in new file mode 100644 index 00000000000..0fe72c91f51 --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in @@ -0,0 +1,8 @@ +set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@) + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@") diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h new file mode 100644 index 00000000000..245f9d48c7f --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h @@ -0,0 +1,3 @@ +#pragma once + +void c1_hello(); diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp new file mode 100644 index 00000000000..c405056eb71 --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp @@ -0,0 +1,10 @@ +#include <iostream> + +#include <c1_lib.h> + +using namespace std; + +void c1_hello() +{ + cout << "Hello from c1_lib" << endl; +} diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt new file mode 100644 index 00000000000..e139446edca --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt @@ -0,0 +1,68 @@ +# This CMakeLists.txt is a nested subproject of the +# subproject C (ExternalProject_Add). + +cmake_minimum_required(VERSION 3.20) +project(c2_lib_project VERSION 1.2.3 LANGUAGES CXX) + +find_package(c1_lib_project REQUIRED) + +include(GNUInstallDirs) + +add_library(the_c2_lib STATIC + "include/c2_lib.h" + "src/c2_lib.cpp" +) + +target_link_libraries(the_c2_lib + PUBLIC + the_c1_lib +) + +target_include_directories(the_c2_lib PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> +) + +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + TARGETS + the_c2_lib + EXPORT main + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) + +set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + +include(CMakePackageConfigHelpers) + +configure_package_config_file( + "cmake/PackageConfig.cmake.in" + "${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}" + PATH_VARS + CMAKE_INSTALL_INCLUDEDIR + CMAKE_INSTALL_LIBDIR +) + +write_basic_package_version_file("${PROJECT_NAME}Version.cmake" + VERSION "${PROJECT_VERSION}" + COMPATIBILITY SameMajorVersion +) + +install( + EXPORT main + FILE "${PROJECT_NAME}Targets.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" +) diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in new file mode 100644 index 00000000000..45a177a5312 --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in @@ -0,0 +1,11 @@ +set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@) + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@") + +include(CMakeFindDependencyMacro) +find_dependency(c1_lib_project REQUIRED) diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h new file mode 100644 index 00000000000..5056814f401 --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h @@ -0,0 +1,3 @@ +#pragma once + +void c2_hello(); diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp new file mode 100644 index 00000000000..cd2c9321ea5 --- /dev/null +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp @@ -0,0 +1,12 @@ +#include <iostream> + +#include <c1_lib.h> +#include <c2_lib.h> + +using namespace std; + +void c2_hello() +{ + cout << "Hello from c2_lib and also..." << endl; + c1_hello(); +} diff --git a/Tests/InstallMode/subpro_d_executable/CMakeLists.txt b/Tests/InstallMode/subpro_d_executable/CMakeLists.txt new file mode 100644 index 00000000000..98472275736 --- /dev/null +++ b/Tests/InstallMode/subpro_d_executable/CMakeLists.txt @@ -0,0 +1,24 @@ +# This CMakeLists.txt is part of the subproject B (ExternalProject_Add). + +cmake_minimum_required(VERSION 3.20) +project(subpro_d_executable LANGUAGES CXX) + +find_package(static_lib_project REQUIRED) +find_package(shared_lib_project REQUIRED) +find_package(c2_lib_project REQUIRED) + +add_executable(the_executable + "src/main.cpp" +) + +target_link_libraries(the_executable PRIVATE + the_static_lib + the_shared_lib + the_c2_lib +) + +install( + TARGETS + the_executable + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) diff --git a/Tests/InstallMode/subpro_d_executable/src/main.cpp b/Tests/InstallMode/subpro_d_executable/src/main.cpp new file mode 100644 index 00000000000..ec12004af4f --- /dev/null +++ b/Tests/InstallMode/subpro_d_executable/src/main.cpp @@ -0,0 +1,13 @@ +#include <cstdlib> + +#include <c2_lib.h> +#include <shared_lib.h> +#include <static_lib.h> + +int main() +{ + static_hello(); + shared_hello(); + c2_hello(); + return EXIT_SUCCESS; +} diff --git a/Tests/InstallMode/superpro/CMakeLists.txt b/Tests/InstallMode/superpro/CMakeLists.txt new file mode 100644 index 00000000000..ae4d25c1f39 --- /dev/null +++ b/Tests/InstallMode/superpro/CMakeLists.txt @@ -0,0 +1,29 @@ +# This CMakeLists.txt is part of the superproject (add_subdirectory). + +# Below file transfers are executed at configuration time! + +file( + COPY + "file_copy.txt" + DESTINATION + "${CMAKE_INSTALL_PREFIX}" +) + +file(COPY_FILE + "${CMAKE_CURRENT_SOURCE_DIR}/file_copy_file.txt" + "${CMAKE_INSTALL_PREFIX}/file_copy_file.txt" +) + +file( + INSTALL + "file_install.txt" + DESTINATION + "${CMAKE_INSTALL_PREFIX}" +) + +file( + CREATE_LINK + "${CMAKE_CURRENT_SOURCE_DIR}/file_create_link_symbolic.txt" + "${CMAKE_INSTALL_PREFIX}/file_create_link_symbolic.txt" + SYMBOLIC +) diff --git a/Tests/InstallMode/superpro/file_copy.txt b/Tests/InstallMode/superpro/file_copy.txt new file mode 100644 index 00000000000..aacbb964426 --- /dev/null +++ b/Tests/InstallMode/superpro/file_copy.txt @@ -0,0 +1 @@ +This file should always be copied into CMAKE_INSTALL_PREFIX. diff --git a/Tests/InstallMode/superpro/file_copy_file.txt b/Tests/InstallMode/superpro/file_copy_file.txt new file mode 100644 index 00000000000..aacbb964426 --- /dev/null +++ b/Tests/InstallMode/superpro/file_copy_file.txt @@ -0,0 +1 @@ +This file should always be copied into CMAKE_INSTALL_PREFIX. diff --git a/Tests/InstallMode/superpro/file_create_link_symbolic.txt b/Tests/InstallMode/superpro/file_create_link_symbolic.txt new file mode 100644 index 00000000000..16a481ba180 --- /dev/null +++ b/Tests/InstallMode/superpro/file_create_link_symbolic.txt @@ -0,0 +1,2 @@ +This file should always be installed into CMAKE_INSTALL_PREFIX +as a symbolic link to the original file. diff --git a/Tests/InstallMode/superpro/file_install.txt b/Tests/InstallMode/superpro/file_install.txt new file mode 100644 index 00000000000..eac97823b18 --- /dev/null +++ b/Tests/InstallMode/superpro/file_install.txt @@ -0,0 +1,6 @@ +This file should be placed in CMAKE_INSTALL_PREFIX +as a copy if the CMAKE_INSTALL_MODE environment variable +is unset or equals "COPY". +If the variable's value is "SYMLINK" or "SYMLINK_OR_COPY", +the CMAKE_INSTALL_PREFIX should rather receive a symbolic +link to this file. From 3cdf23985fc4578b719546a0e76bdcf82457477a Mon Sep 17 00:00:00 2001 From: Artur Samarin <39006-asamarin97@users.noreply.gitlab.kitware.com> Date: Fri, 30 Jul 2021 19:38:56 +0300 Subject: [PATCH 1055/1519] CPackRPM: avoid a spurious `;` in the `%pre` and other sections with scripts This was accidentally added by commit 34c8a23044 (CPackRPM: add scriplets tags only if scripts exist, 2021-04-01, v3.21.0-rc1~387^2). Fixes: #22501 --- Modules/Internal/CPack/CPackRPM.cmake | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index 47d2a5c7fee..cbd748b2c7e 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -11,9 +11,7 @@ function(set_spec_script_if_enabled TYPE PACKAGE_NAME VAR) if(PACKAGE_NAME) set(PACKAGE_NAME " -n ${PACKAGE_NAME}") endif() - set(${TYPE}_ - "%${TYPE}${PACKAGE_NAME}\n" - "${VAR}\n" PARENT_SCOPE) + set(${TYPE}_ "%${TYPE}${PACKAGE_NAME}\n${VAR}\n" PARENT_SCOPE) else() set(${TYPE} "" PARENT_SCOPE) endif() From c0572a15d6c6a2e643b13e21823f6fe7cd402a41 Mon Sep 17 00:00:00 2001 From: Johnny Jazeix <jazeix@gmail.com> Date: Mon, 2 Aug 2021 21:25:20 +0200 Subject: [PATCH 1056/1519] CPack/NSIS: Bump minimal version of NSIS to 3.03 Fixes: #22508 --- Help/cpack_gen/nsis.rst | 4 ++-- Help/release/dev/nsis-minimal-version.rst | 4 ++++ Source/CPack/cmCPackNSISGenerator.cxx | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 Help/release/dev/nsis-minimal-version.rst diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst index 02e33ba30eb..983df77da37 100644 --- a/Help/cpack_gen/nsis.rst +++ b/Help/cpack_gen/nsis.rst @@ -3,8 +3,8 @@ CPack NSIS Generator CPack Nullsoft Scriptable Install System (NSIS) generator specific options. -.. versionchanged:: 3.17 - The NSIS generator requires NSIS 3.0 or newer. +.. versionchanged:: 3.22 + The NSIS generator requires NSIS 3.03 or newer. Variables specific to CPack NSIS generator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/nsis-minimal-version.rst b/Help/release/dev/nsis-minimal-version.rst new file mode 100644 index 00000000000..b19597a13f6 --- /dev/null +++ b/Help/release/dev/nsis-minimal-version.rst @@ -0,0 +1,4 @@ +nsis-minimal-version.rst +------------------------ + +* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 6bd0d1b2a89..0379232089e 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -487,12 +487,12 @@ int cmCPackNSISGenerator::InitializeInternal() } if (versionRex.find(output)) { double nsisVersion = atof(versionRex.match(1).c_str()); - double minNSISVersion = 3.0; + double minNSISVersion = 3.03; cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: " << nsisVersion << std::endl); if (nsisVersion < minNSISVersion) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "CPack requires NSIS Version 3.0 or greater. " + "CPack requires NSIS Version 3.03 or greater. " "NSIS found on the system was: " << nsisVersion << std::endl); return 0; From 2adc45c7f68d6b0904109bd16bf45105dcee5992 Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Fri, 30 Jul 2021 16:05:01 +0200 Subject: [PATCH 1057/1519] IRSL: Fix check of path to Intel redistdir Fix a cut-n-paste error from commit fd4406f33e (IRSL: Add Intel compiler support, 2017-08-16, v3.10.0-rc1~187^2). Make the checked and used paths match. --- Modules/InstallRequiredSystemLibraries.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index fa7b125f904..348b3a9c122 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -87,7 +87,7 @@ foreach(LANG IN ITEMS C CXX Fortran) elseif(APPLE) get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib" ABSOLUTE) else() - if(EXISTS "${_Intel_basedir}/../lib/${_Intel_archdir}_lin") + if(EXISTS "${_Intel_basedir}/../lib/${_Intel_archdir}") get_filename_component(_Intel_redistdir "${_Intel_basedir}/../lib/${_Intel_archdir}" ABSOLUTE) else() get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin" ABSOLUTE) From f4c194398d079ab5be3e693eae73774431d232f2 Mon Sep 17 00:00:00 2001 From: Alexander Grund <Flamefire@users.noreply.github.com> Date: Fri, 30 Jul 2021 16:24:53 +0200 Subject: [PATCH 1058/1519] IRSL: Avoid duplication of Intel redist lib folder paths --- Modules/InstallRequiredSystemLibraries.cmake | 33 ++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index 348b3a9c122..b2af6c95bee 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -80,19 +80,34 @@ foreach(LANG IN ITEMS C CXX Fortran) set(_Intel_archdir ia32) endif() set(_Intel_compiler_ver ${CMAKE_${LANG}_COMPILER_VERSION}) - if(WIN32 AND EXISTS "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler") - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler" ABSOLUTE) - elseif(WIN32) - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" ABSOLUTE) + if(WIN32) + set(_Intel_possible_redistdirs + "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler" + "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" + ) elseif(APPLE) - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib" ABSOLUTE) + set(_Intel_possible_redistdirs + "${_Intel_basedir}/../../compiler/lib" + ) else() - if(EXISTS "${_Intel_basedir}/../lib/${_Intel_archdir}") - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../lib/${_Intel_archdir}" ABSOLUTE) - else() - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin" ABSOLUTE) + set(_Intel_possible_redistdirs + "${_Intel_basedir}/../lib/${_Intel_archdir}" + "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin" + ) + endif() + + set(_Intel_redistdir NOT-FOUND) + foreach(dir IN LISTS _Intel_possible_redistdirs) + if(EXISTS "${dir}") + set(_Intel_redistdir "${dir}") + break() endif() + endforeach() + # Fall back to last dir + if(NOT _Intel_redistdir) + list(POP_BACK _Intel_possible_redistdirs _Intel_redistdir) endif() + unset(_Intel_possible_redistdirs) set(_IRSL_HAVE_Intel TRUE) endif() elseif("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "MSVC") From 1af23c4de2c7d58c06171d70b37794b5c860d5f4 Mon Sep 17 00:00:00 2001 From: Evan Miller <emmiller@gmail.com> Date: Mon, 2 Aug 2021 15:38:02 -0400 Subject: [PATCH 1059/1519] macOS: Restore support for Mac OS X 10.4 (Tiger) Since commit 4aed96e230 (Apple: Set CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG on non-macOS too, 2021-04-06, v3.20.1~5^2) we always enable support for linking with `-rpath`. The intention of the change was to enable using the flag on iOS, tvOS and watchOS by avoiding a Darwin-specific version check. However, removing the check broke support for OS X 10.4 because the flag is not supported on that version. Restore a form of the check that disables the flag on OS X < 10.5 while still allowing it for the other Apple platforms. Since no one is doing iOS/tvOS/etc development on 10.4, this change should have no unintended side effects. Fixes: #22490 --- Modules/Platform/Darwin.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index d9a789475ce..839dc814ec0 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -47,7 +47,9 @@ set(CMAKE_SHARED_MODULE_PREFIX "lib") set(CMAKE_SHARED_MODULE_SUFFIX ".so") set(CMAKE_MODULE_EXISTS 1) set(CMAKE_DL_LIBS "") -set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") +if(NOT "${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5") + set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") +endif() foreach(lang C CXX OBJC OBJCXX) set(CMAKE_${lang}_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") From e808cbb1dd9bf594e2f2c8ea2c0b82b9a6590d29 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Thu, 29 Jul 2021 18:12:03 +0300 Subject: [PATCH 1060/1519] Testing: Convert `cmake_host_system_information` tests into `RunCMake` --- Tests/CMakeTests/CMakeLists.txt | 1 - Tests/RunCMake/CMakeLists.txt | 1 + .../BadArg1-result.txt | 1 + .../BadArg1-stderr.txt | 4 +++ .../BadArg1.cmake} | 0 .../BadArg2-result.txt | 1 + .../BadArg2-stderr.txt | 4 +++ .../BadArg2.cmake} | 0 .../BadArg3-result.txt | 1 + .../BadArg3-stderr.txt | 4 +++ .../BadArg3.cmake} | 0 .../CMakeLists.txt | 7 +++++ .../QueryKeys-stdout.txt | 27 +++++++++++++++++++ .../QueryKeys.cmake} | 24 ++--------------- .../QueryList-stdout.txt | 1 + .../QueryList.cmake} | 2 +- .../RunCMakeTest.cmake | 8 ++++++ 17 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt rename Tests/{CMakeTests/CMakeHostSystemInformation-BadArg1.cmake => RunCMake/cmake_host_system_information/BadArg1.cmake} (100%) create mode 100644 Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt rename Tests/{CMakeTests/CMakeHostSystemInformation-BadArg2.cmake => RunCMake/cmake_host_system_information/BadArg2.cmake} (100%) create mode 100644 Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt rename Tests/{CMakeTests/CMakeHostSystemInformation-BadArg3.cmake => RunCMake/cmake_host_system_information/BadArg3.cmake} (100%) create mode 100644 Tests/RunCMake/cmake_host_system_information/CMakeLists.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt rename Tests/{CMakeTests/CMakeHostSystemInformationTest.cmake.in => RunCMake/cmake_host_system_information/QueryKeys.cmake} (58%) create mode 100644 Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt rename Tests/{CMakeTests/CMakeHostSystemInformation-QueryList.cmake => RunCMake/cmake_host_system_information/QueryList.cmake} (77%) create mode 100644 Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 52959e62eb3..9e0b89101df 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -31,7 +31,6 @@ AddCMakeTest(CompilerIdVendor "") AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>") AddCMakeTest(PushCheckState "") AddCMakeTest(While "") -AddCMakeTest(CMakeHostSystemInformation "") AddCMakeTest(FileDownload "") set_tests_properties(CMake.FileDownload PROPERTIES diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index ef797f73079..eb2c2d94ae1 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -349,6 +349,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() add_RunCMake_test(execute_process) add_RunCMake_test(export) +add_RunCMake_test(cmake_host_system_information) add_RunCMake_test(cmake_language) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(cmake_parse_arguments) diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt new file mode 100644 index 00000000000..ed995e6a63f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadArg1\.cmake:1 \(cmake_host_system_information\): + cmake_host_system_information missing RESULT specification. +Call Stack \(most recent call first\): + CMakeLists\.txt:7 \(include\) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake similarity index 100% rename from Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake rename to Tests/RunCMake/cmake_host_system_information/BadArg1.cmake diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt new file mode 100644 index 00000000000..b78c927f1f3 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadArg2\.cmake:1 \(cmake_host_system_information\): + cmake_host_system_information missing QUERY specification +Call Stack \(most recent call first\): + CMakeLists\.txt:7 \(include\) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake similarity index 100% rename from Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake rename to Tests/RunCMake/cmake_host_system_information/BadArg2.cmake diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt new file mode 100644 index 00000000000..c3f13140ab1 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadArg3\.cmake:1 \(cmake_host_system_information\): + cmake_host_system_information does not recognize <key> FOOBAR +Call Stack \(most recent call first\): + CMakeLists\.txt:7 \(include\) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake similarity index 100% rename from Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake rename to Tests/RunCMake/cmake_host_system_information/BadArg3.cmake diff --git a/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt new file mode 100644 index 00000000000..0198f9be0af --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.21) + +project(${RunCMake_TEST} NONE) + +set(CMAKE_SYSROOT ${PROJECT_SOURCE_DIR}/${RunCMake_TEST}) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt new file mode 100644 index 00000000000..f583deb62ec --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt @@ -0,0 +1,27 @@ +-- NUMBER_OF_LOGICAL_CORES=`[0-9]+` +-- NUMBER_OF_PHYSICAL_CORES=`[0-9]+` +-- HOSTNAME=`.*` +-- FQDN=`.*` +-- TOTAL_VIRTUAL_MEMORY=`[0-9]+` +-- AVAILABLE_VIRTUAL_MEMORY=`[0-9]+` +-- TOTAL_PHYSICAL_MEMORY=`[0-9]+` +-- AVAILABLE_PHYSICAL_MEMORY=`[0-9]+` +-- IS_64BIT=`[01]` +-- HAS_FPU=`[01]` +-- HAS_MMX=`[01]` +-- HAS_MMX_PLUS=`[01]` +-- HAS_SSE=`[01]` +-- HAS_SSE2=`[01]` +-- HAS_SSE_FP=`[01]` +-- HAS_SSE_MMX=`[01]` +-- HAS_AMD_3DNOW=`[01]` +-- HAS_AMD_3DNOW_PLUS=`[01]` +-- HAS_IA64=`[01]` +-- HAS_SERIAL_NUMBER=`[01]` +-- PROCESSOR_SERIAL_NUMBER=`.*` +-- PROCESSOR_NAME=`.*` +-- PROCESSOR_DESCRIPTION=`.*` +-- OS_NAME=`.*` +-- OS_RELEASE=`.*` +-- OS_VERSION=`.*` +-- OS_PLATFORM=`.*` diff --git a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake similarity index 58% rename from Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in rename to Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake index a3c2b055ac1..f22a0ae70bb 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in +++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake @@ -1,19 +1,8 @@ -set(BadArg1-RESULT 1) -set(BadArg1-STDERR "missing RESULT specification") -set(BadArg2-RESULT 1) -set(BadArg2-STDERR "missing QUERY specification") -set(BadArg3-RESULT 1) -set(BadArg3-STDERR "does not recognize <key> FOOBAR") -set(QueryList-RESULT 0) -set(QueryList-STDERR "\\[[0-9]+;[0-9]+\\]") - function(try_and_print key) - cmake_host_system_information(RESULT RESULT QUERY ${key}) - message(STATUS "[${key}] [${RESULT}]") + cmake_host_system_information(RESULT RESULT QUERY ${key}) + message(STATUS "${key}=`${RESULT}`") endfunction() -message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") - try_and_print(NUMBER_OF_LOGICAL_CORES) try_and_print(NUMBER_OF_PHYSICAL_CORES) try_and_print(HOSTNAME) @@ -41,12 +30,3 @@ try_and_print(OS_NAME) try_and_print(OS_RELEASE) try_and_print(OS_VERSION) try_and_print(OS_PLATFORM) - -include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") - -check_cmake_test(CMakeHostSystemInformation - BadArg1 - BadArg2 - BadArg3 - QueryList -) diff --git a/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt new file mode 100644 index 00000000000..eebe0d40e36 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt @@ -0,0 +1 @@ +-- \[[0-9]+;[0-9]+\] diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake similarity index 77% rename from Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake rename to Tests/RunCMake/cmake_host_system_information/QueryList.cmake index 1c3156d23c4..f24aa2bdf57 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake +++ b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake @@ -2,4 +2,4 @@ cmake_host_system_information(RESULT RESULT QUERY NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES ) -message("[${RESULT}]") +message(STATUS "[${RESULT}]") diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake new file mode 100644 index 00000000000..be74ade0e59 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -0,0 +1,8 @@ +include(RunCMake) + +run_cmake(BadArg1) +run_cmake(BadArg2) +run_cmake(BadArg3) + +run_cmake(QueryList) +run_cmake(QueryKeys) From 4deb7c250b85984f5e69191cc50ac7f5d98371dd Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 3 Aug 2021 00:01:12 -0400 Subject: [PATCH 1061/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2b24fba7831..9a3e312e1a7 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210802) +set(CMake_VERSION_PATCH 20210803) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b0d65963992d85349487a3fdf51cfced6910384d Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 01:54:24 +0300 Subject: [PATCH 1062/1519] Refactor: Make `cmConditionEvaluator::IsTrue` a bit more compact Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 99927d7db2c..7ea0dafd855 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -149,25 +149,19 @@ bool cmConditionEvaluator::IsTrue( // now loop through the arguments and see if we can reduce any of them // we do this multiple times. Once for each level of precedence // parens - if (!this->HandleLevel0(newArgs, errorString, status)) { - return false; - } - // predicates - if (!this->HandleLevel1(newArgs, errorString, status)) { - return false; - } - // binary ops - if (!this->HandleLevel2(newArgs, errorString, status)) { - return false; - } - - // NOT - if (!this->HandleLevel3(newArgs, errorString, status)) { - return false; - } - // AND OR - if (!this->HandleLevel4(newArgs, errorString, status)) { - return false; + using handlerFn_t = bool (cmConditionEvaluator::*)( + cmArgumentList&, std::string&, MessageType&); + const std::array<handlerFn_t, 5> handlers = { { + &cmConditionEvaluator::HandleLevel0, // parenthesis + &cmConditionEvaluator::HandleLevel1, // predicates + &cmConditionEvaluator::HandleLevel2, // binary ops + &cmConditionEvaluator::HandleLevel3, // NOT + &cmConditionEvaluator::HandleLevel4 // AND OR + } }; + for (auto fn : handlers) { + if (!(this->*fn)(newArgs, errorString, status)) { + return false; + } } // now at the end there should only be one argument left From 78fcbb20cdd6f33423e8b503a4b55de4abfa52f6 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 02:51:43 +0300 Subject: [PATCH 1063/1519] Refactor: Remove `reducible` flag from `handleLevelN()` functions The indicator that smth has been done is the `newArgs` size get differ after an iteration. Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 90 ++++++++++++++++----------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 7ea0dafd855..c19338b6145 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -78,7 +78,7 @@ void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, std::advance(argP2, difference_type(argP1 != newArgs.end())); } -void HandlePredicate(const bool value, bool& reducible, +void HandlePredicate(const bool value, cmConditionEvaluator::cmArgumentList::iterator& arg, cmConditionEvaluator::cmArgumentList& newArgs, cmConditionEvaluator::cmArgumentList::iterator& argP1) @@ -87,10 +87,9 @@ void HandlePredicate(const bool value, bool& reducible, newArgs.erase(argP1); argP1 = arg; IncrementArguments(newArgs, argP1); - reducible = true; } -void HandleBinaryOp(const bool value, bool& reducible, +void HandleBinaryOp(const bool value, cmConditionEvaluator::cmArgumentList::iterator& arg, cmConditionEvaluator::cmArgumentList& newArgs, cmConditionEvaluator::cmArgumentList::iterator& argP1, @@ -101,7 +100,6 @@ void HandleBinaryOp(const bool value, bool& reducible, newArgs.erase(argP1); argP1 = arg; IncrementArguments(newArgs, argP1, argP2); - reducible = true; } } // anonymous namespace @@ -354,9 +352,10 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - bool reducible; + std::size_t beginSize; do { - reducible = false; + beginSize = newArgs.size(); + for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) { if (this->IsKeyword(keyParenL, *arg)) { // search for the closing paren for this opening one @@ -385,7 +384,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, newArgs.erase(argP1, argClose); } } - } while (reducible); + } while (beginSize != newArgs.size()); return true; } @@ -397,9 +396,10 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD || this->Policy64Status == cmPolicies::WARN; - bool reducible; + std::size_t beginSize; do { - reducible = false; + beginSize = newArgs.size(); + for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); argP1 = ++arg) { @@ -431,42 +431,42 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, // does a file exist if (this->IsKeyword(keyEXISTS, *arg)) { - HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), - reducible, arg, newArgs, argP1); + HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), arg, + newArgs, argP1); } // does a directory with this name exist else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { - HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), - reducible, arg, newArgs, argP1); + HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), arg, + newArgs, argP1); } // does a symlink with this name exist else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { - HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), - reducible, arg, newArgs, argP1); + HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), arg, + newArgs, argP1); } // is the given path an absolute path ? else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { - HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), - reducible, arg, newArgs, argP1); + HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), arg, + newArgs, argP1); } // does a command exist else if (this->IsKeyword(keyCOMMAND, *arg)) { HandlePredicate( this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1); + arg, newArgs, argP1); } // does a policy exist else if (this->IsKeyword(keyPOLICY, *arg)) { cmPolicies::PolicyID pid; HandlePredicate( - cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible, - arg, newArgs, argP1); + cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), arg, + newArgs, argP1); } // does a target exist else if (this->IsKeyword(keyTARGET, *arg)) { HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1); + arg, newArgs, argP1); } // is a variable defined else if (this->IsKeyword(keyDEFINED, *arg)) { @@ -485,7 +485,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } else { bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); } - HandlePredicate(bdef, reducible, arg, newArgs, argP1); + HandlePredicate(bdef, arg, newArgs, argP1); } // does a test exist else if (this->IsKeyword(keyTEST, *arg)) { @@ -493,10 +493,10 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, continue; } HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - reducible, arg, newArgs, argP1); + arg, newArgs, argP1); } } - } while (reducible); + } while (beginSize != newArgs.size()); return true; } @@ -506,12 +506,13 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - bool reducible; std::string def_buf; cmProp def; cmProp def2; + std::size_t beginSize; do { - reducible = false; + beginSize = newArgs.size(); + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { @@ -553,7 +554,6 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, newArgs.erase(argP1); argP1 = arg; IncrementArguments(newArgs, argP1, argP2); - reducible = true; } else if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { @@ -561,7 +561,6 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, newArgs.erase(argP1); argP1 = arg; IncrementArguments(newArgs, argP1, argP2); - reducible = true; } // NOTE Fail fast: All the binary ops below require 2 arguments. @@ -595,7 +594,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else { result = (lhs == rhs); } - HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, arg, newArgs, argP1, argP2); } else if (this->IsKeyword(keySTRLESS, *argP1) || @@ -621,7 +620,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, { result = (val == 0); } - HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, arg, newArgs, argP1, argP2); } else if (this->IsKeyword(keyVERSION_LESS, *argP1) || @@ -647,7 +646,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } const auto result = cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); - HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, arg, newArgs, argP1, argP2); } // is file A newer than file B @@ -656,7 +655,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( arg->GetValue(), argP2->GetValue(), &fileIsNewer); HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), - reducible, arg, newArgs, argP1, argP2); + arg, newArgs, argP1, argP2); } else if (this->IsKeyword(keyIN_LIST, *argP1)) { @@ -672,7 +671,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, result = cm::contains(cmExpandedList(*def2, true), *def); } - HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, arg, newArgs, argP1, argP2); } else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n"; @@ -684,7 +683,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } } } - } while (reducible); + } while (beginSize != newArgs.size()); return true; } @@ -694,9 +693,10 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - bool reducible; + std::size_t beginSize; do { - reducible = false; + beginSize = newArgs.size(); + for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); argP1 = ++arg) { @@ -705,10 +705,10 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { const auto rhs = this->GetBooleanValueWithAutoDereference( *argP1, errorString, status); - HandlePredicate(!rhs, reducible, arg, newArgs, argP1); + HandlePredicate(!rhs, arg, newArgs, argP1); } } - } while (reducible); + } while (beginSize != newArgs.size()); return true; } @@ -718,27 +718,27 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - bool reducible; + std::size_t beginSize; do { - reducible = false; + beginSize = newArgs.size(); + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { IncrementArguments(newArgs, argP1, argP2); - if (argP1 != newArgs.end() && + if (argP1 != newArgs.end() && argP2 != newArgs.end() && (this->IsKeyword(keyAND, *argP1) || - this->IsKeyword(keyOR, *argP1)) && - argP2 != newArgs.end()) { + this->IsKeyword(keyOR, *argP1))) { const auto lhs = this->GetBooleanValueWithAutoDereference(*arg, errorString, status); const auto rhs = this->GetBooleanValueWithAutoDereference( *argP2, errorString, status); HandleBinaryOp(this->IsKeyword(keyAND, *argP1) ? (lhs && rhs) : (lhs || rhs), - reducible, arg, newArgs, argP1, argP2); + arg, newArgs, argP1, argP2); } } - } while (reducible); + } while (beginSize != newArgs.size()); return true; } From 4de2a4a46dcddd3e86c6da8be8a3fe2008b093cf Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 04:02:04 +0300 Subject: [PATCH 1064/1519] Refactor: Opt-out do+while loops and reduce nesting level in handlers Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 596 +++++++++++++++----------------- 1 file changed, 287 insertions(+), 309 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index c19338b6145..5f66dbfcc0e 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -157,8 +157,12 @@ bool cmConditionEvaluator::IsTrue( &cmConditionEvaluator::HandleLevel4 // AND OR } }; for (auto fn : handlers) { - if (!(this->*fn)(newArgs, errorString, status)) { - return false; + // Call the reducer 'till there is anything to reduce... + // (i.e., if after an iteration the size becomes smaller) + for (auto beginSize = newArgs.size(); + (this->*fn)(newArgs, errorString, status) && + newArgs.size() < beginSize; + beginSize = newArgs.size()) { } } @@ -352,39 +356,34 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - std::size_t beginSize; - do { - beginSize = newArgs.size(); - - for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) { - if (this->IsKeyword(keyParenL, *arg)) { - // search for the closing paren for this opening one - auto depth = 1; - auto argClose = std::next(arg); - for (; argClose != newArgs.end() && depth; ++argClose) { - depth += int(this->IsKeyword(keyParenL, *argClose)) - - int(this->IsKeyword(keyParenR, *argClose)); - } - if (depth) { - errorString = "mismatched parenthesis in condition"; - status = MessageType::FATAL_ERROR; - return false; - } - // store the reduced args in this vector - auto argP1 = std::next(arg); - std::vector<cmExpandedCommandArgument> newArgs2{ argP1, argClose }; - newArgs2.pop_back(); - - // now recursively invoke IsTrue to handle the values inside the - // parenthetical expression - const auto value = this->IsTrue(newArgs2, errorString, status); - *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); - argP1 = std::next(arg); - // remove the now evaluated parenthetical expression - newArgs.erase(argP1, argClose); + for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) { + if (this->IsKeyword(keyParenL, *arg)) { + // search for the closing paren for this opening one + auto depth = 1; + auto argClose = std::next(arg); + for (; argClose != newArgs.end() && depth; ++argClose) { + depth += int(this->IsKeyword(keyParenL, *argClose)) - + int(this->IsKeyword(keyParenR, *argClose)); + } + if (depth) { + errorString = "mismatched parenthesis in condition"; + status = MessageType::FATAL_ERROR; + return false; } + // store the reduced args in this vector + auto argP1 = std::next(arg); + std::vector<cmExpandedCommandArgument> newArgs2{ argP1, argClose }; + newArgs2.pop_back(); + + // now recursively invoke IsTrue to handle the values inside the + // parenthetical expression + const auto value = this->IsTrue(newArgs2, errorString, status); + *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); + argP1 = std::next(arg); + // remove the now evaluated parenthetical expression + newArgs.erase(argP1, argClose); } - } while (beginSize != newArgs.size()); + } return true; } @@ -396,107 +395,101 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD || this->Policy64Status == cmPolicies::WARN; - std::size_t beginSize; - do { - beginSize = newArgs.size(); - - for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); - argP1 = ++arg) { - - IncrementArguments(newArgs, argP1); - auto policyCheck = [&, this](const cmPolicies::PolicyID id, - const cmPolicies::PolicyStatus status, - const cm::static_string_view kw) { - if (status == cmPolicies::WARN && this->IsKeyword(kw, *arg)) { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(id) << "\n" - << kw - << " will be interpreted as an operator " - "when the policy is set to NEW. " - "Since the policy is not set the OLD behavior will be used."; - - this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); - } - }; + for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); + argP1 = ++arg) { - // NOTE Checking policies for warnings are not require an access to the - // next arg. Check them first! - policyCheck(cmPolicies::CMP0064, this->Policy64Status, keyTEST); + IncrementArguments(newArgs, argP1); - // NOTE Fail fast: All the predicates below require the next arg to be - // valid - if (argP1 == newArgs.end()) { - continue; - } + auto policyCheck = [&, this](const cmPolicies::PolicyID id, + const cmPolicies::PolicyStatus status, + const cm::static_string_view kw) { + if (status == cmPolicies::WARN && this->IsKeyword(kw, *arg)) { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(id) << "\n" + << kw + << " will be interpreted as an operator " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; - // does a file exist - if (this->IsKeyword(keyEXISTS, *arg)) { - HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), arg, - newArgs, argP1); - } - // does a directory with this name exist - else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { - HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), arg, - newArgs, argP1); + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } - // does a symlink with this name exist - else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { - HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), arg, - newArgs, argP1); - } - // is the given path an absolute path ? - else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { - HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), arg, - newArgs, argP1); - } - // does a command exist - else if (this->IsKeyword(keyCOMMAND, *arg)) { - HandlePredicate( - this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, - arg, newArgs, argP1); - } - // does a policy exist - else if (this->IsKeyword(keyPOLICY, *arg)) { - cmPolicies::PolicyID pid; - HandlePredicate( - cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), arg, - newArgs, argP1); - } - // does a target exist - else if (this->IsKeyword(keyTARGET, *arg)) { - HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != - nullptr, - arg, newArgs, argP1); - } - // is a variable defined - else if (this->IsKeyword(keyDEFINED, *arg)) { - const auto argP1len = argP1->GetValue().size(); - auto bdef = false; - if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && - argP1->GetValue().operator[](argP1len - 1) == '}') { - const auto env = argP1->GetValue().substr(4, argP1len - 5); - bdef = cmSystemTools::HasEnv(env); - } else if (argP1len > 6 && - cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") && - argP1->GetValue().operator[](argP1len - 1) == '}') { - const auto cache = argP1->GetValue().substr(6, argP1len - 7); - bdef = - this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr; - } else { - bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); - } - HandlePredicate(bdef, arg, newArgs, argP1); + }; + + // NOTE Checking policies for warnings are not require an access to the + // next arg. Check them first! + policyCheck(cmPolicies::CMP0064, this->Policy64Status, keyTEST); + + // NOTE Fail fast: All the predicates below require the next arg to be + // valid + if (argP1 == newArgs.end()) { + continue; + } + + // does a file exist + if (this->IsKeyword(keyEXISTS, *arg)) { + HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), arg, + newArgs, argP1); + } + // does a directory with this name exist + else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { + HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), arg, + newArgs, argP1); + } + // does a symlink with this name exist + else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { + HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), arg, + newArgs, argP1); + } + // is the given path an absolute path ? + else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { + HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), arg, + newArgs, argP1); + } + // does a command exist + else if (this->IsKeyword(keyCOMMAND, *arg)) { + HandlePredicate( + this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, + arg, newArgs, argP1); + } + // does a policy exist + else if (this->IsKeyword(keyPOLICY, *arg)) { + cmPolicies::PolicyID pid; + HandlePredicate(cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), + arg, newArgs, argP1); + } + // does a target exist + else if (this->IsKeyword(keyTARGET, *arg)) { + HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != + nullptr, + arg, newArgs, argP1); + } + // is a variable defined + else if (this->IsKeyword(keyDEFINED, *arg)) { + const auto argP1len = argP1->GetValue().size(); + auto bdef = false; + if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && + argP1->GetValue().operator[](argP1len - 1) == '}') { + const auto env = argP1->GetValue().substr(4, argP1len - 5); + bdef = cmSystemTools::HasEnv(env); + } else if (argP1len > 6 && + cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") && + argP1->GetValue().operator[](argP1len - 1) == '}') { + const auto cache = argP1->GetValue().substr(6, argP1len - 7); + bdef = this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr; + } else { + bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); } - // does a test exist - else if (this->IsKeyword(keyTEST, *arg)) { - if (policy64IsOld) { - continue; - } - HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - arg, newArgs, argP1); + HandlePredicate(bdef, arg, newArgs, argP1); + } + // does a test exist + else if (this->IsKeyword(keyTEST, *arg)) { + if (policy64IsOld) { + continue; } + HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, + arg, newArgs, argP1); } - } while (beginSize != newArgs.size()); + } return true; } @@ -509,181 +502,177 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string def_buf; cmProp def; cmProp def2; - std::size_t beginSize; - do { - beginSize = newArgs.size(); - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; - arg != newArgs.end(); argP1 = ++arg) { + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; + arg != newArgs.end(); argP1 = ++arg) { - IncrementArguments(newArgs, argP1, argP2); + IncrementArguments(newArgs, argP1, argP2); - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - this->IsKeyword(keyMATCHES, *argP1)) { + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + this->IsKeyword(keyMATCHES, *argP1)) { - def = this->GetDefinitionIfUnquoted(*arg); - - if (!def) { - def = &arg->GetValue(); - } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { - // The string to match is owned by our match result variables. - // Move it to our own buffer before clearing them. - def_buf = *def; - def = &def_buf; - } - - const auto& rex = argP2->GetValue(); - this->Makefile.ClearMatches(); - cmsys::RegularExpression regEntry; - if (!regEntry.compile(rex)) { - std::ostringstream error; - error << "Regular expression \"" << rex << "\" cannot compile"; - errorString = error.str(); - status = MessageType::FATAL_ERROR; - return false; - } - - if (regEntry.find(*def)) { - this->Makefile.StoreMatches(regEntry); - *arg = cmExpandedCommandArgument("1", true); - } else { - *arg = cmExpandedCommandArgument("0", true); - } + def = this->GetDefinitionIfUnquoted(*arg); - newArgs.erase(argP2); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); + if (!def) { + def = &arg->GetValue(); + } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { + // The string to match is owned by our match result variables. + // Move it to our own buffer before clearing them. + def_buf = *def; + def = &def_buf; } - else if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { - *arg = cmExpandedCommandArgument("0", true); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); + const auto& rex = argP2->GetValue(); + this->Makefile.ClearMatches(); + cmsys::RegularExpression regEntry; + if (!regEntry.compile(rex)) { + std::ostringstream error; + error << "Regular expression \"" << rex << "\" cannot compile"; + errorString = error.str(); + status = MessageType::FATAL_ERROR; + return false; } - // NOTE Fail fast: All the binary ops below require 2 arguments. - else if (argP1 == newArgs.end() || argP2 == newArgs.end()) { - continue; + if (regEntry.find(*def)) { + this->Makefile.StoreMatches(regEntry); + *arg = cmExpandedCommandArgument("1", true); + } else { + *arg = cmExpandedCommandArgument("0", true); } - else if (this->IsKeyword(keyLESS, *argP1) || - this->IsKeyword(keyLESS_EQUAL, *argP1) || - this->IsKeyword(keyGREATER, *argP1) || - this->IsKeyword(keyGREATER_EQUAL, *argP1) || - this->IsKeyword(keyEQUAL, *argP1)) { + newArgs.erase(argP2); + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs, argP1, argP2); + } - def = this->GetVariableOrString(*arg); - def2 = this->GetVariableOrString(*argP2); - - double lhs; - double rhs; - bool result; - if (std::sscanf(def->c_str(), "%lg", &lhs) != 1 || - std::sscanf(def2->c_str(), "%lg", &rhs) != 1) { - result = false; - } else if (argP1->GetValue() == keyLESS) { - result = (lhs < rhs); - } else if (argP1->GetValue() == keyLESS_EQUAL) { - result = (lhs <= rhs); - } else if (argP1->GetValue() == keyGREATER) { - result = (lhs > rhs); - } else if (argP1->GetValue() == keyGREATER_EQUAL) { - result = (lhs >= rhs); - } else { - result = (lhs == rhs); - } - HandleBinaryOp(result, arg, newArgs, argP1, argP2); - } + else if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { + *arg = cmExpandedCommandArgument("0", true); + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs, argP1, argP2); + } - else if (this->IsKeyword(keySTRLESS, *argP1) || - this->IsKeyword(keySTRLESS_EQUAL, *argP1) || - this->IsKeyword(keySTRGREATER, *argP1) || - this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || - this->IsKeyword(keySTREQUAL, *argP1)) { + // NOTE Fail fast: All the binary ops below require 2 arguments. + else if (argP1 == newArgs.end() || argP2 == newArgs.end()) { + continue; + } - def = this->GetVariableOrString(*arg); - def2 = this->GetVariableOrString(*argP2); - const int val = (*def).compare(*def2); - - bool result; - if (argP1->GetValue() == keySTRLESS) { - result = (val < 0); - } else if (argP1->GetValue() == keySTRLESS_EQUAL) { - result = (val <= 0); - } else if (argP1->GetValue() == keySTRGREATER) { - result = (val > 0); - } else if (argP1->GetValue() == keySTRGREATER_EQUAL) { - result = (val >= 0); - } else // strequal - { - result = (val == 0); - } - HandleBinaryOp(result, arg, newArgs, argP1, argP2); + else if (this->IsKeyword(keyLESS, *argP1) || + this->IsKeyword(keyLESS_EQUAL, *argP1) || + this->IsKeyword(keyGREATER, *argP1) || + this->IsKeyword(keyGREATER_EQUAL, *argP1) || + this->IsKeyword(keyEQUAL, *argP1)) { + + def = this->GetVariableOrString(*arg); + def2 = this->GetVariableOrString(*argP2); + + double lhs; + double rhs; + bool result; + if (std::sscanf(def->c_str(), "%lg", &lhs) != 1 || + std::sscanf(def2->c_str(), "%lg", &rhs) != 1) { + result = false; + } else if (argP1->GetValue() == keyLESS) { + result = (lhs < rhs); + } else if (argP1->GetValue() == keyLESS_EQUAL) { + result = (lhs <= rhs); + } else if (argP1->GetValue() == keyGREATER) { + result = (lhs > rhs); + } else if (argP1->GetValue() == keyGREATER_EQUAL) { + result = (lhs >= rhs); + } else { + result = (lhs == rhs); } + HandleBinaryOp(result, arg, newArgs, argP1, argP2); + } - else if (this->IsKeyword(keyVERSION_LESS, *argP1) || - this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) || - this->IsKeyword(keyVERSION_GREATER, *argP1) || - this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || - this->IsKeyword(keyVERSION_EQUAL, *argP1)) { - - def = this->GetVariableOrString(*arg); - def2 = this->GetVariableOrString(*argP2); - - cmSystemTools::CompareOp op; - if (argP1->GetValue() == keyVERSION_LESS) { - op = cmSystemTools::OP_LESS; - } else if (argP1->GetValue() == keyVERSION_LESS_EQUAL) { - op = cmSystemTools::OP_LESS_EQUAL; - } else if (argP1->GetValue() == keyVERSION_GREATER) { - op = cmSystemTools::OP_GREATER; - } else if (argP1->GetValue() == keyVERSION_GREATER_EQUAL) { - op = cmSystemTools::OP_GREATER_EQUAL; - } else { // version_equal - op = cmSystemTools::OP_EQUAL; - } - const auto result = - cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); - HandleBinaryOp(result, arg, newArgs, argP1, argP2); + else if (this->IsKeyword(keySTRLESS, *argP1) || + this->IsKeyword(keySTRLESS_EQUAL, *argP1) || + this->IsKeyword(keySTRGREATER, *argP1) || + this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || + this->IsKeyword(keySTREQUAL, *argP1)) { + + def = this->GetVariableOrString(*arg); + def2 = this->GetVariableOrString(*argP2); + const int val = (*def).compare(*def2); + + bool result; + if (argP1->GetValue() == keySTRLESS) { + result = (val < 0); + } else if (argP1->GetValue() == keySTRLESS_EQUAL) { + result = (val <= 0); + } else if (argP1->GetValue() == keySTRGREATER) { + result = (val > 0); + } else if (argP1->GetValue() == keySTRGREATER_EQUAL) { + result = (val >= 0); + } else // strequal + { + result = (val == 0); } + HandleBinaryOp(result, arg, newArgs, argP1, argP2); + } - // is file A newer than file B - else if (this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { - auto fileIsNewer = 0; - cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( - arg->GetValue(), argP2->GetValue(), &fileIsNewer); - HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), - arg, newArgs, argP1, argP2); + else if (this->IsKeyword(keyVERSION_LESS, *argP1) || + this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) || + this->IsKeyword(keyVERSION_GREATER, *argP1) || + this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || + this->IsKeyword(keyVERSION_EQUAL, *argP1)) { + + def = this->GetVariableOrString(*arg); + def2 = this->GetVariableOrString(*argP2); + + cmSystemTools::CompareOp op; + if (argP1->GetValue() == keyVERSION_LESS) { + op = cmSystemTools::OP_LESS; + } else if (argP1->GetValue() == keyVERSION_LESS_EQUAL) { + op = cmSystemTools::OP_LESS_EQUAL; + } else if (argP1->GetValue() == keyVERSION_GREATER) { + op = cmSystemTools::OP_GREATER; + } else if (argP1->GetValue() == keyVERSION_GREATER_EQUAL) { + op = cmSystemTools::OP_GREATER_EQUAL; + } else { // version_equal + op = cmSystemTools::OP_EQUAL; } + const auto result = + cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); + HandleBinaryOp(result, arg, newArgs, argP1, argP2); + } - else if (this->IsKeyword(keyIN_LIST, *argP1)) { - - if (this->Policy57Status != cmPolicies::OLD && - this->Policy57Status != cmPolicies::WARN) { - auto result = false; + // is file A newer than file B + else if (this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { + auto fileIsNewer = 0; + cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( + arg->GetValue(), argP2->GetValue(), &fileIsNewer); + HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), arg, + newArgs, argP1, argP2); + } - def = this->GetVariableOrString(*arg); - def2 = this->Makefile.GetDefinition(argP2->GetValue()); + else if (this->IsKeyword(keyIN_LIST, *argP1)) { - if (def2) { - result = cm::contains(cmExpandedList(*def2, true), *def); - } + if (this->Policy57Status != cmPolicies::OLD && + this->Policy57Status != cmPolicies::WARN) { + auto result = false; - HandleBinaryOp(result, arg, newArgs, argP1, argP2); - } else if (this->Policy57Status == cmPolicies::WARN) { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n"; - e << "IN_LIST will be interpreted as an operator " - "when the policy is set to NEW. " - "Since the policy is not set the OLD behavior will be used."; + def = this->GetVariableOrString(*arg); + def2 = this->Makefile.GetDefinition(argP2->GetValue()); - this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + if (def2) { + result = cm::contains(cmExpandedList(*def2, true), *def); } + + HandleBinaryOp(result, arg, newArgs, argP1, argP2); + } else if (this->Policy57Status == cmPolicies::WARN) { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n"; + e << "IN_LIST will be interpreted as an operator " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; + + this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } } - } while (beginSize != newArgs.size()); + } return true; } @@ -693,22 +682,17 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - std::size_t beginSize; - do { - beginSize = newArgs.size(); + for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); + argP1 = ++arg) { - for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); - argP1 = ++arg) { + IncrementArguments(newArgs, argP1); - IncrementArguments(newArgs, argP1); - - if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { - const auto rhs = this->GetBooleanValueWithAutoDereference( - *argP1, errorString, status); - HandlePredicate(!rhs, arg, newArgs, argP1); - } + if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { + const auto rhs = + this->GetBooleanValueWithAutoDereference(*argP1, errorString, status); + HandlePredicate(!rhs, arg, newArgs, argP1); } - } while (beginSize != newArgs.size()); + } return true; } @@ -718,27 +702,21 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - std::size_t beginSize; - do { - beginSize = newArgs.size(); - - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; - arg != newArgs.end(); argP1 = ++arg) { - - IncrementArguments(newArgs, argP1, argP2); - - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (this->IsKeyword(keyAND, *argP1) || - this->IsKeyword(keyOR, *argP1))) { - const auto lhs = - this->GetBooleanValueWithAutoDereference(*arg, errorString, status); - const auto rhs = this->GetBooleanValueWithAutoDereference( - *argP2, errorString, status); - HandleBinaryOp(this->IsKeyword(keyAND, *argP1) ? (lhs && rhs) - : (lhs || rhs), - arg, newArgs, argP1, argP2); - } + for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; + arg != newArgs.end(); argP1 = ++arg) { + + IncrementArguments(newArgs, argP1, argP2); + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (this->IsKeyword(keyAND, *argP1) || this->IsKeyword(keyOR, *argP1))) { + const auto lhs = + this->GetBooleanValueWithAutoDereference(*arg, errorString, status); + const auto rhs = + this->GetBooleanValueWithAutoDereference(*argP2, errorString, status); + HandleBinaryOp(this->IsKeyword(keyAND, *argP1) ? (lhs && rhs) + : (lhs || rhs), + arg, newArgs, argP1, argP2); } - } while (beginSize != newArgs.size()); + } return true; } From 047f8321a0923d16b97f70e0b3dcfd1eadeddf6f Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 04:13:13 +0300 Subject: [PATCH 1065/1519] Refactor: Avoid redundant `operator<<` on printing messages Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 5f66dbfcc0e..5d8dc70f327 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -193,11 +193,13 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted( this->Policy54Status == cmPolicies::WARN) { if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) { std::ostringstream e; - e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) << "\n"; - e << "Quoted variables like \"" << argument.GetValue() - << "\" will no longer be dereferenced " - "when the policy is set to NEW. " + // clang-format off + e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) + << "\n" + "Quoted variables like \"" << argument.GetValue() << "\" " + "will no longer be dereferenced when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; + // clang-format on this->Makefile.GetCMakeInstance()->IssueMessage( MessageType::AUTHOR_WARNING, e.str(), this->Backtrace); @@ -236,11 +238,14 @@ bool cmConditionEvaluator::IsKeyword(cm::static_string_view keyword, this->Policy54Status == cmPolicies::WARN) { if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) { std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) << "\n"; - e << "Quoted keywords like \"" << argument.GetValue() - << "\" will no longer be interpreted as keywords " + // clang-format off + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) + << "\n" + "Quoted keywords like \"" << argument.GetValue() << "\" " + "will no longer be interpreted as keywords " "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; + // clang-format on this->Makefile.GetCMakeInstance()->IssueMessage( MessageType::AUTHOR_WARNING, e.str(), this->Backtrace); @@ -664,8 +669,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, HandleBinaryOp(result, arg, newArgs, argP1, argP2); } else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n"; - e << "IN_LIST will be interpreted as an operator " + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) + << "\n" + "IN_LIST will be interpreted as an operator " "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; From e3c1dbe18b41752f9e042c6a42170887af6af651 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 05:08:20 +0300 Subject: [PATCH 1066/1519] Refactor: Replace `if` block w/ boolean expression Signed-off-by: Alex Turbov <i.zaufi@gmail.com> --- Source/cmConditionEvaluator.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 5d8dc70f327..3673200a444 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -657,16 +657,12 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { - auto result = false; def = this->GetVariableOrString(*arg); def2 = this->Makefile.GetDefinition(argP2->GetValue()); - if (def2) { - result = cm::contains(cmExpandedList(*def2, true), *def); - } - - HandleBinaryOp(result, arg, newArgs, argP1, argP2); + HandleBinaryOp(def2 && cm::contains(cmExpandedList(*def2, true), *def), + arg, newArgs, argP1, argP2); } else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) From cc6cdacc1860ab14a2980332626b0de826f1eb2b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 22:12:51 +0300 Subject: [PATCH 1067/1519] Refactor: Simplify boolean to string result assignments --- Source/cmConditionEvaluator.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 3673200a444..ad2ba3f31d4 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -8,6 +8,7 @@ #include <functional> #include <iterator> #include <sstream> +#include <string> #include <utility> #include <cm/string_view> @@ -57,8 +58,6 @@ auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s; auto const keyVERSION_LESS = "VERSION_LESS"_s; auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; -std::array<const char* const, 2> const ZERO_ONE_XLAT = { "0", "1" }; - void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, cmConditionEvaluator::cmArgumentList::iterator& argP1) { @@ -83,7 +82,7 @@ void HandlePredicate(const bool value, cmConditionEvaluator::cmArgumentList& newArgs, cmConditionEvaluator::cmArgumentList::iterator& argP1) { - *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); + *arg = cmExpandedCommandArgument(std::to_string(int(value)), true); newArgs.erase(argP1); argP1 = arg; IncrementArguments(newArgs, argP1); @@ -95,7 +94,7 @@ void HandleBinaryOp(const bool value, cmConditionEvaluator::cmArgumentList::iterator& argP1, cmConditionEvaluator::cmArgumentList::iterator& argP2) { - *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); + *arg = cmExpandedCommandArgument(std::to_string(int(value)), true); newArgs.erase(argP2); newArgs.erase(argP1); argP1 = arg; @@ -383,7 +382,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, // now recursively invoke IsTrue to handle the values inside the // parenthetical expression const auto value = this->IsTrue(newArgs2, errorString, status); - *arg = cmExpandedCommandArgument(ZERO_ONE_XLAT[value], true); + *arg = cmExpandedCommandArgument(std::to_string(int(value)), true); argP1 = std::next(arg); // remove the now evaluated parenthetical expression newArgs.erase(argP1, argClose); From d4d44e86f6a144bc849ffd1439a51a87cbb0cc12 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 22:49:06 +0300 Subject: [PATCH 1068/1519] Refactor: Reduce variables scope in `HandleLevel2` --- Source/cmConditionEvaluator.cxx | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index ad2ba3f31d4..eea7bde4d8e 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -503,10 +503,6 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - std::string def_buf; - cmProp def; - cmProp def2; - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; arg != newArgs.end(); argP1 = ++arg) { @@ -515,8 +511,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (argP1 != newArgs.end() && argP2 != newArgs.end() && this->IsKeyword(keyMATCHES, *argP1)) { - def = this->GetDefinitionIfUnquoted(*arg); + cmProp def = this->GetDefinitionIfUnquoted(*arg); + std::string def_buf; if (!def) { def = &arg->GetValue(); } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { @@ -526,8 +523,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def = &def_buf; } - const auto& rex = argP2->GetValue(); this->Makefile.ClearMatches(); + + const auto& rex = argP2->GetValue(); cmsys::RegularExpression regEntry; if (!regEntry.compile(rex)) { std::ostringstream error; @@ -568,8 +566,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keyGREATER_EQUAL, *argP1) || this->IsKeyword(keyEQUAL, *argP1)) { - def = this->GetVariableOrString(*arg); - def2 = this->GetVariableOrString(*argP2); + cmProp def = this->GetVariableOrString(*arg); + cmProp def2 = this->GetVariableOrString(*argP2); double lhs; double rhs; @@ -597,8 +595,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || this->IsKeyword(keySTREQUAL, *argP1)) { - def = this->GetVariableOrString(*arg); - def2 = this->GetVariableOrString(*argP2); + cmProp def = this->GetVariableOrString(*arg); + cmProp def2 = this->GetVariableOrString(*argP2); const int val = (*def).compare(*def2); bool result; @@ -623,8 +621,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || this->IsKeyword(keyVERSION_EQUAL, *argP1)) { - def = this->GetVariableOrString(*arg); - def2 = this->GetVariableOrString(*argP2); + cmProp def = this->GetVariableOrString(*arg); + cmProp def2 = this->GetVariableOrString(*argP2); cmSystemTools::CompareOp op; if (argP1->GetValue() == keyVERSION_LESS) { @@ -657,8 +655,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { - def = this->GetVariableOrString(*arg); - def2 = this->Makefile.GetDefinition(argP2->GetValue()); + cmProp def = this->GetVariableOrString(*arg); + cmProp def2 = this->Makefile.GetDefinition(argP2->GetValue()); HandleBinaryOp(def2 && cm::contains(cmExpandedList(*def2, true), *def), arg, newArgs, argP1, argP2); From 9721ab416f65edd969b756a501b5748d21d4f242 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 23:07:12 +0300 Subject: [PATCH 1069/1519] Refactor: Reorder `MATCHES` handler from top below to the fail-fast --- Source/cmConditionEvaluator.cxx | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index eea7bde4d8e..67556efe0ba 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -508,9 +508,22 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, IncrementArguments(newArgs, argP1, argP2); - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - this->IsKeyword(keyMATCHES, *argP1)) { + // NOTE Handle special case `if(... BLAH_BAH MATCHES)` + // (i.e., w/o regex to match which is possibly result of + // variable expansion to an empty string) + if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { + *arg = cmExpandedCommandArgument("0", true); + newArgs.erase(argP1); + argP1 = arg; + IncrementArguments(newArgs, argP1, argP2); + } + // NOTE Fail fast: All the binary ops below require 2 arguments. + else if (argP1 == newArgs.end() || argP2 == newArgs.end()) { + continue; + } + + else if (this->IsKeyword(keyMATCHES, *argP1)) { cmProp def = this->GetDefinitionIfUnquoted(*arg); std::string def_buf; @@ -535,12 +548,11 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, return false; } - if (regEntry.find(*def)) { + const auto match = regEntry.find(*def); + if (match) { this->Makefile.StoreMatches(regEntry); - *arg = cmExpandedCommandArgument("1", true); - } else { - *arg = cmExpandedCommandArgument("0", true); } + *arg = cmExpandedCommandArgument(std::to_string(int(match)), true); newArgs.erase(argP2); newArgs.erase(argP1); @@ -548,18 +560,6 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, IncrementArguments(newArgs, argP1, argP2); } - else if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { - *arg = cmExpandedCommandArgument("0", true); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); - } - - // NOTE Fail fast: All the binary ops below require 2 arguments. - else if (argP1 == newArgs.end() || argP2 == newArgs.end()) { - continue; - } - else if (this->IsKeyword(keyLESS, *argP1) || this->IsKeyword(keyLESS_EQUAL, *argP1) || this->IsKeyword(keyGREATER, *argP1) || From 97d6bbcc01f9e7580ae556d62ee4ceefffbabe3b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 26 Jul 2021 23:11:56 +0300 Subject: [PATCH 1070/1519] Refactor: Replace `std::to_string` w/ more specialized `bool2string` --- Source/cmConditionEvaluator.cxx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 67556efe0ba..46affaa377c 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -8,7 +8,6 @@ #include <functional> #include <iterator> #include <sstream> -#include <string> #include <utility> #include <cm/string_view> @@ -58,6 +57,11 @@ auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s; auto const keyVERSION_LESS = "VERSION_LESS"_s; auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; +std::string bool2string(bool const value) +{ + return std::string(std::size_t(1), static_cast<char>('0' + int(value))); +} + void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, cmConditionEvaluator::cmArgumentList::iterator& argP1) { @@ -82,7 +86,7 @@ void HandlePredicate(const bool value, cmConditionEvaluator::cmArgumentList& newArgs, cmConditionEvaluator::cmArgumentList::iterator& argP1) { - *arg = cmExpandedCommandArgument(std::to_string(int(value)), true); + *arg = cmExpandedCommandArgument(bool2string(value), true); newArgs.erase(argP1); argP1 = arg; IncrementArguments(newArgs, argP1); @@ -94,7 +98,7 @@ void HandleBinaryOp(const bool value, cmConditionEvaluator::cmArgumentList::iterator& argP1, cmConditionEvaluator::cmArgumentList::iterator& argP2) { - *arg = cmExpandedCommandArgument(std::to_string(int(value)), true); + *arg = cmExpandedCommandArgument(bool2string(value), true); newArgs.erase(argP2); newArgs.erase(argP1); argP1 = arg; @@ -382,7 +386,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, // now recursively invoke IsTrue to handle the values inside the // parenthetical expression const auto value = this->IsTrue(newArgs2, errorString, status); - *arg = cmExpandedCommandArgument(std::to_string(int(value)), true); + *arg = cmExpandedCommandArgument(bool2string(value), true); argP1 = std::next(arg); // remove the now evaluated parenthetical expression newArgs.erase(argP1, argClose); @@ -552,7 +556,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (match) { this->Makefile.StoreMatches(regEntry); } - *arg = cmExpandedCommandArgument(std::to_string(int(match)), true); + *arg = cmExpandedCommandArgument(bool2string(match), true); newArgs.erase(argP2); newArgs.erase(argP1); From 2b916606c5c3f1145edd5f0464b139d03b79ae44 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 00:13:21 +0300 Subject: [PATCH 1071/1519] Refactor: No need to move iterators after match A handler's loop of all levels gonna restart after calls to `HandlePredcate` or `HandleBinaryOp`... And the first action in the loop is to setup iterators. So, no need to move 'em inside the functions. Also, no need to pass iterators by reference. Also, reorder parameters of both functions so iterators followed after a reference to the newArgs container. --- Source/cmConditionEvaluator.cxx | 68 ++++++++++++++------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 46affaa377c..38dfca5c63b 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -82,27 +82,23 @@ void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, } void HandlePredicate(const bool value, - cmConditionEvaluator::cmArgumentList::iterator& arg, cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator& argP1) + cmConditionEvaluator::cmArgumentList::iterator arg, + cmConditionEvaluator::cmArgumentList::iterator argP1) { *arg = cmExpandedCommandArgument(bool2string(value), true); newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1); } void HandleBinaryOp(const bool value, - cmConditionEvaluator::cmArgumentList::iterator& arg, cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator& argP1, - cmConditionEvaluator::cmArgumentList::iterator& argP2) + cmConditionEvaluator::cmArgumentList::iterator arg, + cmConditionEvaluator::cmArgumentList::iterator argP1, + cmConditionEvaluator::cmArgumentList::iterator argP2) { *arg = cmExpandedCommandArgument(bool2string(value), true); newArgs.erase(argP2); newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); } } // anonymous namespace @@ -435,41 +431,41 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, // does a file exist if (this->IsKeyword(keyEXISTS, *arg)) { - HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), arg, - newArgs, argP1); + HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), newArgs, + arg, argP1); } // does a directory with this name exist else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { - HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), arg, - newArgs, argP1); + HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), + newArgs, arg, argP1); } // does a symlink with this name exist else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { - HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), arg, - newArgs, argP1); + HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), newArgs, + arg, argP1); } // is the given path an absolute path ? else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { - HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), arg, - newArgs, argP1); + HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), + newArgs, arg, argP1); } // does a command exist else if (this->IsKeyword(keyCOMMAND, *arg)) { HandlePredicate( this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, - arg, newArgs, argP1); + newArgs, arg, argP1); } // does a policy exist else if (this->IsKeyword(keyPOLICY, *arg)) { cmPolicies::PolicyID pid; HandlePredicate(cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), - arg, newArgs, argP1); + newArgs, arg, argP1); } // does a target exist else if (this->IsKeyword(keyTARGET, *arg)) { HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr, - arg, newArgs, argP1); + newArgs, arg, argP1); } // is a variable defined else if (this->IsKeyword(keyDEFINED, *arg)) { @@ -487,7 +483,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } else { bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); } - HandlePredicate(bdef, arg, newArgs, argP1); + HandlePredicate(bdef, newArgs, arg, argP1); } // does a test exist else if (this->IsKeyword(keyTEST, *arg)) { @@ -495,7 +491,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, continue; } HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - arg, newArgs, argP1); + newArgs, arg, argP1); } } return true; @@ -516,10 +512,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, // (i.e., w/o regex to match which is possibly result of // variable expansion to an empty string) if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { - *arg = cmExpandedCommandArgument("0", true); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); + HandlePredicate(false, newArgs, arg, argP1); } // NOTE Fail fast: All the binary ops below require 2 arguments. @@ -556,12 +549,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (match) { this->Makefile.StoreMatches(regEntry); } - *arg = cmExpandedCommandArgument(bool2string(match), true); - - newArgs.erase(argP2); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs, argP1, argP2); + HandleBinaryOp(match, newArgs, arg, argP1, argP2); } else if (this->IsKeyword(keyLESS, *argP1) || @@ -590,7 +578,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else { result = (lhs == rhs); } - HandleBinaryOp(result, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, newArgs, arg, argP1, argP2); } else if (this->IsKeyword(keySTRLESS, *argP1) || @@ -616,7 +604,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, { result = (val == 0); } - HandleBinaryOp(result, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, newArgs, arg, argP1, argP2); } else if (this->IsKeyword(keyVERSION_LESS, *argP1) || @@ -642,7 +630,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } const auto result = cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); - HandleBinaryOp(result, arg, newArgs, argP1, argP2); + HandleBinaryOp(result, newArgs, arg, argP1, argP2); } // is file A newer than file B @@ -650,8 +638,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, auto fileIsNewer = 0; cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( arg->GetValue(), argP2->GetValue(), &fileIsNewer); - HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), arg, - newArgs, argP1, argP2); + HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), + newArgs, arg, argP1, argP2); } else if (this->IsKeyword(keyIN_LIST, *argP1)) { @@ -663,7 +651,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, cmProp def2 = this->Makefile.GetDefinition(argP2->GetValue()); HandleBinaryOp(def2 && cm::contains(cmExpandedList(*def2, true), *def), - arg, newArgs, argP1, argP2); + newArgs, arg, argP1, argP2); } else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) @@ -693,7 +681,7 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { const auto rhs = this->GetBooleanValueWithAutoDereference(*argP1, errorString, status); - HandlePredicate(!rhs, arg, newArgs, argP1); + HandlePredicate(!rhs, newArgs, arg, argP1); } } return true; @@ -718,7 +706,7 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, this->GetBooleanValueWithAutoDereference(*argP2, errorString, status); HandleBinaryOp(this->IsKeyword(keyAND, *argP1) ? (lhs && rhs) : (lhs || rhs), - arg, newArgs, argP1, argP2); + newArgs, arg, argP1, argP2); } } return true; From 17af3baddd7b7056114748f16e63b8de6b3f67e8 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 05:33:53 +0300 Subject: [PATCH 1072/1519] Refactor: Set `const` to `cmConditionEvaluator::IsKeyword` parameters --- Source/cmConditionEvaluator.cxx | 5 +++-- Source/cmConditionEvaluator.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 38dfca5c63b..cec96915460 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -222,8 +222,9 @@ cmProp cmConditionEvaluator::GetVariableOrString( } //========================================================================= -bool cmConditionEvaluator::IsKeyword(cm::static_string_view keyword, - cmExpandedCommandArgument& argument) const +bool cmConditionEvaluator::IsKeyword( + cm::static_string_view keyword, + const cmExpandedCommandArgument& argument) const { if ((this->Policy54Status != cmPolicies::WARN && this->Policy54Status != cmPolicies::OLD) && diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index a7e3ce87ac8..d74e28b4b2a 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -39,7 +39,7 @@ class cmConditionEvaluator cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const; bool IsKeyword(cm::static_string_view keyword, - cmExpandedCommandArgument& argument) const; + const cmExpandedCommandArgument& argument) const; bool GetBooleanValue(cmExpandedCommandArgument& arg) const; From 46810235e3a8420b3379b352dd6b19d7a0439acd Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 06:35:54 +0300 Subject: [PATCH 1073/1519] =?UTF-8?q?Refactor:=20Avoid=20`if`=20=E2=86=92?= =?UTF-8?q?=20`else=20if`=20=E2=86=92=20=E2=80=A6=20for=20compare=20operat?= =?UTF-8?q?ors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to match one of compare operator key inside `if()` condition, remember the index of matched operator. Later this index used to select the operation to perform instead of strings compare again. --- Source/cmConditionEvaluator.cxx | 157 +++++++++++++++++++------------- Source/cmConditionEvaluator.h | 9 ++ 2 files changed, 104 insertions(+), 62 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index cec96915460..570bb4a4460 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -57,6 +57,34 @@ auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s; auto const keyVERSION_LESS = "VERSION_LESS"_s; auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; +// Run-Time to Compile-Time template selector +template <template <typename> class Comp, template <typename> class... Ops> +struct cmRt2CtSelector +{ + template <typename T> + static bool eval(int r, T lhs, T rhs) + { + switch (r) { + case 0: + return false; + case 1: + return Comp<T>()(lhs, rhs); + default: + return cmRt2CtSelector<Ops...>::eval(r - 1, lhs, rhs); + } + } +}; + +template <template <typename> class Comp> +struct cmRt2CtSelector<Comp> +{ + template <typename T> + static bool eval(int r, T lhs, T rhs) + { + return r == 1 && Comp<T>()(lhs, rhs); + } +}; + std::string bool2string(bool const value) { return std::string(std::size_t(1), static_cast<char>('0' + int(value))); @@ -355,6 +383,33 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( return newResult; } +template <int N> +inline int cmConditionEvaluator::matchKeysImpl( + const cmExpandedCommandArgument&) +{ + // Zero means "not found" + return 0; +} + +template <int N, typename T, typename... Keys> +inline int cmConditionEvaluator::matchKeysImpl( + const cmExpandedCommandArgument& arg, T current, Keys... key) +{ + if (this->IsKeyword(current, arg)) { + // Stop searching as soon as smth has found + return N; + } + return matchKeysImpl<N + 1>(arg, key...); +} + +template <typename... Keys> +inline int cmConditionEvaluator::matchKeys( + const cmExpandedCommandArgument& arg, Keys... key) +{ + // Get index of the matched key (1-based) + return matchKeysImpl<1>(arg, key...); +} + //========================================================================= // level 0 processes parenthetical expressions bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, @@ -509,6 +564,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, IncrementArguments(newArgs, argP1, argP2); + int matchNo; + // NOTE Handle special case `if(... BLAH_BAH MATCHES)` // (i.e., w/o regex to match which is possibly result of // variable expansion to an empty string) @@ -553,84 +610,60 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, HandleBinaryOp(match, newArgs, arg, argP1, argP2); } - else if (this->IsKeyword(keyLESS, *argP1) || - this->IsKeyword(keyLESS_EQUAL, *argP1) || - this->IsKeyword(keyGREATER, *argP1) || - this->IsKeyword(keyGREATER_EQUAL, *argP1) || - this->IsKeyword(keyEQUAL, *argP1)) { + else if ((matchNo = + this->matchKeys(*argP1, keyLESS, keyLESS_EQUAL, keyGREATER, + keyGREATER_EQUAL, keyEQUAL))) { - cmProp def = this->GetVariableOrString(*arg); - cmProp def2 = this->GetVariableOrString(*argP2); + cmProp ldef = this->GetVariableOrString(*arg); + cmProp rdef = this->GetVariableOrString(*argP2); double lhs; double rhs; bool result; - if (std::sscanf(def->c_str(), "%lg", &lhs) != 1 || - std::sscanf(def2->c_str(), "%lg", &rhs) != 1) { + if (std::sscanf(ldef->c_str(), "%lg", &lhs) != 1 || + std::sscanf(rdef->c_str(), "%lg", &rhs) != 1) { result = false; - } else if (argP1->GetValue() == keyLESS) { - result = (lhs < rhs); - } else if (argP1->GetValue() == keyLESS_EQUAL) { - result = (lhs <= rhs); - } else if (argP1->GetValue() == keyGREATER) { - result = (lhs > rhs); - } else if (argP1->GetValue() == keyGREATER_EQUAL) { - result = (lhs >= rhs); } else { - result = (lhs == rhs); + // clang-format off + result = cmRt2CtSelector< + std::less, std::less_equal, std::greater, + std::greater_equal, std::equal_to + >::eval(matchNo, lhs, rhs); + // clang-format on } HandleBinaryOp(result, newArgs, arg, argP1, argP2); } - else if (this->IsKeyword(keySTRLESS, *argP1) || - this->IsKeyword(keySTRLESS_EQUAL, *argP1) || - this->IsKeyword(keySTRGREATER, *argP1) || - this->IsKeyword(keySTRGREATER_EQUAL, *argP1) || - this->IsKeyword(keySTREQUAL, *argP1)) { + else if ((matchNo = this->matchKeys(*argP1, keySTRLESS, keySTRLESS_EQUAL, + keySTRGREATER, keySTRGREATER_EQUAL, + keySTREQUAL))) { - cmProp def = this->GetVariableOrString(*arg); - cmProp def2 = this->GetVariableOrString(*argP2); - const int val = (*def).compare(*def2); - - bool result; - if (argP1->GetValue() == keySTRLESS) { - result = (val < 0); - } else if (argP1->GetValue() == keySTRLESS_EQUAL) { - result = (val <= 0); - } else if (argP1->GetValue() == keySTRGREATER) { - result = (val > 0); - } else if (argP1->GetValue() == keySTRGREATER_EQUAL) { - result = (val >= 0); - } else // strequal - { - result = (val == 0); - } + const cmProp lhs = this->GetVariableOrString(*arg); + const cmProp rhs = this->GetVariableOrString(*argP2); + const auto val = (*lhs).compare(*rhs); + // clang-format off + const auto result = cmRt2CtSelector< + std::less, std::less_equal, std::greater, + std::greater_equal, std::equal_to + >::eval(matchNo, val, 0); + // clang-format on HandleBinaryOp(result, newArgs, arg, argP1, argP2); } - else if (this->IsKeyword(keyVERSION_LESS, *argP1) || - this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) || - this->IsKeyword(keyVERSION_GREATER, *argP1) || - this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) || - this->IsKeyword(keyVERSION_EQUAL, *argP1)) { - - cmProp def = this->GetVariableOrString(*arg); - cmProp def2 = this->GetVariableOrString(*argP2); - - cmSystemTools::CompareOp op; - if (argP1->GetValue() == keyVERSION_LESS) { - op = cmSystemTools::OP_LESS; - } else if (argP1->GetValue() == keyVERSION_LESS_EQUAL) { - op = cmSystemTools::OP_LESS_EQUAL; - } else if (argP1->GetValue() == keyVERSION_GREATER) { - op = cmSystemTools::OP_GREATER; - } else if (argP1->GetValue() == keyVERSION_GREATER_EQUAL) { - op = cmSystemTools::OP_GREATER_EQUAL; - } else { // version_equal - op = cmSystemTools::OP_EQUAL; - } + else if ((matchNo = + this->matchKeys(*argP1, keyVERSION_LESS, keyVERSION_LESS_EQUAL, + keyVERSION_GREATER, keyVERSION_GREATER_EQUAL, + keyVERSION_EQUAL))) { + const cmSystemTools::CompareOp xlat[5] = { + cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL, + cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL, + cmSystemTools::OP_EQUAL + }; + const auto op = xlat[matchNo - 1]; + const cmProp lhs = this->GetVariableOrString(*arg); + const cmProp rhs = this->GetVariableOrString(*argP2); const auto result = - cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str()); + cmSystemTools::VersionCompare(op, lhs->c_str(), rhs->c_str()); HandleBinaryOp(result, newArgs, arg, argP1, argP2); } diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index d74e28b4b2a..83670071c47 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -65,6 +65,15 @@ class cmConditionEvaluator bool HandleLevel4(cmArgumentList& newArgs, std::string& errorString, MessageType& status); + template <int N> + int matchKeysImpl(const cmExpandedCommandArgument&); + + template <int N, typename T, typename... Keys> + int matchKeysImpl(const cmExpandedCommandArgument&, T, Keys...); + + template <typename... Keys> + int matchKeys(const cmExpandedCommandArgument&, Keys...); + cmMakefile& Makefile; cmListFileBacktrace Backtrace; cmPolicies::PolicyStatus Policy12Status; From 51d9194a96df4cb8cd144afce4edc6e2122fab2d Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 18:36:18 +0300 Subject: [PATCH 1074/1519] Refactor: Reduce one more condition checking on handling math compare --- Source/cmConditionEvaluator.cxx | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 570bb4a4460..8224121c1bd 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -619,18 +619,18 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, double lhs; double rhs; - bool result; - if (std::sscanf(ldef->c_str(), "%lg", &lhs) != 1 || - std::sscanf(rdef->c_str(), "%lg", &rhs) != 1) { - result = false; - } else { + auto parseDoubles = [&]() { + return std::sscanf(ldef->c_str(), "%lg", &lhs) == 1 && + std::sscanf(rdef->c_str(), "%lg", &rhs) == 1; + }; + const auto result = parseDoubles() && // clang-format off - result = cmRt2CtSelector< - std::less, std::less_equal, std::greater, - std::greater_equal, std::equal_to + cmRt2CtSelector< + std::less, std::less_equal, + std::greater, std::greater_equal, + std::equal_to >::eval(matchNo, lhs, rhs); - // clang-format on - } + // clang-format on HandleBinaryOp(result, newArgs, arg, argP1, argP2); } @@ -643,8 +643,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, const auto val = (*lhs).compare(*rhs); // clang-format off const auto result = cmRt2CtSelector< - std::less, std::less_equal, std::greater, - std::greater_equal, std::equal_to + std::less, std::less_equal, + std::greater, std::greater_equal, + std::equal_to >::eval(matchNo, val, 0); // clang-format on HandleBinaryOp(result, newArgs, arg, argP1, argP2); From 866b0595f6f3e26542148984e22f508fb1b3eb1e Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 22:47:06 +0300 Subject: [PATCH 1075/1519] Refactor: Introduce `cmArgumentList` container class The `cmArgumentList` has been turned into a class (forward declared in the header). It inherits from the `std::list` (yeah, but we don't intend to store polymorphic classes in it). In addition to the standard methods, now it's possible to move `HandlePredicate` (renamed to `ReduceOneArg`) and `HandleBinaryOp` (renamed to `ReduceTwoArgs`) as its members. Additionally, iterators managements (`IncrementArguments`) have been refactored into two separate classes mimicking iterators. This also allows having a uniform `for` loop and concentrates the logic of iterators advancing in it instead of the loop's body. The arguments processing algorithms operate with "windows" over a collection of arguments. Hence there are two kinds of "iteration windows" -- allowing to observe 2 or 3 elements per loop iteration. These iteration "windows" also passed to reducers. --- Source/cmConditionEvaluator.cxx | 338 ++++++++++-------- Source/cmConditionEvaluator.h | 25 +- .../RunCMake/if/IncompleteMatches-stdout.txt | 6 + Tests/RunCMake/if/IncompleteMatches.cmake | 36 ++ .../if/IncompleteMatchesFail-result.txt | 1 + .../if/IncompleteMatchesFail-stderr.txt | 6 + Tests/RunCMake/if/IncompleteMatchesFail.cmake | 2 + Tests/RunCMake/if/RunCMakeTest.cmake | 2 + 8 files changed, 262 insertions(+), 154 deletions(-) create mode 100644 Tests/RunCMake/if/IncompleteMatches-stdout.txt create mode 100644 Tests/RunCMake/if/IncompleteMatches.cmake create mode 100644 Tests/RunCMake/if/IncompleteMatchesFail-result.txt create mode 100644 Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt create mode 100644 Tests/RunCMake/if/IncompleteMatchesFail.cmake diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 8224121c1bd..444d029926f 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -7,6 +7,7 @@ #include <cstdlib> #include <functional> #include <iterator> +#include <list> #include <sstream> #include <utility> @@ -15,6 +16,7 @@ #include "cmsys/RegularExpression.hxx" +#include "cmExpandedCommandArgument.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmProperty.h" @@ -89,46 +91,102 @@ std::string bool2string(bool const value) { return std::string(std::size_t(1), static_cast<char>('0' + int(value))); } +} // anonymous namespace -void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator& argP1) -{ - using difference_type = - cmConditionEvaluator::cmArgumentList::difference_type; - std::advance(argP1, difference_type(argP1 != newArgs.end())); -} +#if defined(__SUNPRO_CC) +# define CM_INHERIT_CTOR(Class, Base, Tpl) \ + template <typename... Args> \ + Class(Args&&... args) \ + : Base Tpl(std::forward<Args>(args)...) \ + { \ + } +#else +# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base; +#endif -void IncrementArguments(cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator& argP1, - cmConditionEvaluator::cmArgumentList::iterator& argP2) +// BEGIN cmConditionEvaluator::cmArgumentList +class cmConditionEvaluator::cmArgumentList + : public std::list<cmExpandedCommandArgument> { - IncrementArguments(newArgs, argP1); - argP2 = argP1; - using difference_type = - cmConditionEvaluator::cmArgumentList::difference_type; - std::advance(argP2, difference_type(argP1 != newArgs.end())); -} + using base_t = std::list<cmExpandedCommandArgument>; -void HandlePredicate(const bool value, - cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator arg, - cmConditionEvaluator::cmArgumentList::iterator argP1) -{ - *arg = cmExpandedCommandArgument(bool2string(value), true); - newArgs.erase(argP1); -} +public: + CM_INHERIT_CTOR(cmArgumentList, list, <cmExpandedCommandArgument>); -void HandleBinaryOp(const bool value, - cmConditionEvaluator::cmArgumentList& newArgs, - cmConditionEvaluator::cmArgumentList::iterator arg, - cmConditionEvaluator::cmArgumentList::iterator argP1, - cmConditionEvaluator::cmArgumentList::iterator argP2) -{ - *arg = cmExpandedCommandArgument(bool2string(value), true); - newArgs.erase(argP2); - newArgs.erase(argP1); -} -} // anonymous namespace + class CurrentAndNextIter + { + friend class cmConditionEvaluator::cmArgumentList; + + public: + base_t::iterator current; + base_t::iterator next; + + CurrentAndNextIter advance(base_t& args) + { + this->current = std::next(this->current); + this->next = + std::next(this->current, difference_type(this->current != args.end())); + return *this; + } + + private: + CurrentAndNextIter(base_t& args) + : current(args.begin()) + , next(std::next(this->current, + difference_type(this->current != args.end()))) + { + } + }; + + class CurrentAndTwoMoreIter + { + friend class cmConditionEvaluator::cmArgumentList; + + public: + base_t::iterator current; + base_t::iterator next; + base_t::iterator nextnext; + + CurrentAndTwoMoreIter advance(base_t& args) + { + this->current = std::next(this->current); + this->next = + std::next(this->current, difference_type(this->current != args.end())); + this->nextnext = + std::next(this->next, difference_type(this->next != args.end())); + return *this; + } + + private: + CurrentAndTwoMoreIter(base_t& args) + : current(args.begin()) + , next(std::next(this->current, + difference_type(this->current != args.end()))) + , nextnext( + std::next(this->next, difference_type(this->next != args.end()))) + { + } + }; + + CurrentAndNextIter make2ArgsIterator() { return *this; } + CurrentAndTwoMoreIter make3ArgsIterator() { return *this; } + + template <typename Iter> + void ReduceOneArg(const bool value, Iter args) + { + *args.current = cmExpandedCommandArgument(bool2string(value), true); + this->erase(args.next); + } + + void ReduceTwoArgs(const bool value, CurrentAndTwoMoreIter args) + { + *args.current = cmExpandedCommandArgument(bool2string(value), true); + this->erase(args.nextnext); + this->erase(args.next); + } +}; + +// END cmConditionEvaluator::cmArgumentList cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, cmListFileBacktrace bt) @@ -455,15 +513,13 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD || this->Policy64Status == cmPolicies::WARN; - for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); - argP1 = ++arg) { - - IncrementArguments(newArgs, argP1); + for (auto args = newArgs.make2ArgsIterator(); args.current != newArgs.end(); + args.advance(newArgs)) { auto policyCheck = [&, this](const cmPolicies::PolicyID id, const cmPolicies::PolicyStatus status, const cm::static_string_view kw) { - if (status == cmPolicies::WARN && this->IsKeyword(kw, *arg)) { + if (status == cmPolicies::WARN && this->IsKeyword(kw, *args.current)) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(id) << "\n" << kw @@ -481,73 +537,72 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, // NOTE Fail fast: All the predicates below require the next arg to be // valid - if (argP1 == newArgs.end()) { + if (args.next == newArgs.end()) { continue; } // does a file exist - if (this->IsKeyword(keyEXISTS, *arg)) { - HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()), newArgs, - arg, argP1); + if (this->IsKeyword(keyEXISTS, *args.current)) { + newArgs.ReduceOneArg(cmSystemTools::FileExists(args.next->GetValue()), + args); } // does a directory with this name exist - else if (this->IsKeyword(keyIS_DIRECTORY, *arg)) { - HandlePredicate(cmSystemTools::FileIsDirectory(argP1->GetValue()), - newArgs, arg, argP1); + else if (this->IsKeyword(keyIS_DIRECTORY, *args.current)) { + newArgs.ReduceOneArg( + cmSystemTools::FileIsDirectory(args.next->GetValue()), args); } // does a symlink with this name exist - else if (this->IsKeyword(keyIS_SYMLINK, *arg)) { - HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()), newArgs, - arg, argP1); + else if (this->IsKeyword(keyIS_SYMLINK, *args.current)) { + newArgs.ReduceOneArg(cmSystemTools::FileIsSymlink(args.next->GetValue()), + args); } // is the given path an absolute path ? - else if (this->IsKeyword(keyIS_ABSOLUTE, *arg)) { - HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()), - newArgs, arg, argP1); + else if (this->IsKeyword(keyIS_ABSOLUTE, *args.current)) { + newArgs.ReduceOneArg( + cmSystemTools::FileIsFullPath(args.next->GetValue()), args); } // does a command exist - else if (this->IsKeyword(keyCOMMAND, *arg)) { - HandlePredicate( - this->Makefile.GetState()->GetCommand(argP1->GetValue()) != nullptr, - newArgs, arg, argP1); + else if (this->IsKeyword(keyCOMMAND, *args.current)) { + newArgs.ReduceOneArg( + bool(this->Makefile.GetState()->GetCommand(args.next->GetValue())), + args); } // does a policy exist - else if (this->IsKeyword(keyPOLICY, *arg)) { + else if (this->IsKeyword(keyPOLICY, *args.current)) { cmPolicies::PolicyID pid; - HandlePredicate(cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), - newArgs, arg, argP1); + newArgs.ReduceOneArg( + cmPolicies::GetPolicyID(args.next->GetValue().c_str(), pid), args); } // does a target exist - else if (this->IsKeyword(keyTARGET, *arg)) { - HandlePredicate(this->Makefile.FindTargetToUse(argP1->GetValue()) != - nullptr, - newArgs, arg, argP1); + else if (this->IsKeyword(keyTARGET, *args.current)) { + newArgs.ReduceOneArg( + bool(this->Makefile.FindTargetToUse(args.next->GetValue())), args); } // is a variable defined - else if (this->IsKeyword(keyDEFINED, *arg)) { - const auto argP1len = argP1->GetValue().size(); + else if (this->IsKeyword(keyDEFINED, *args.current)) { + const auto argP1len = args.next->GetValue().size(); auto bdef = false; - if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") && - argP1->GetValue().operator[](argP1len - 1) == '}') { - const auto env = argP1->GetValue().substr(4, argP1len - 5); + if (argP1len > 4 && cmHasLiteralPrefix(args.next->GetValue(), "ENV{") && + args.next->GetValue().operator[](argP1len - 1) == '}') { + const auto env = args.next->GetValue().substr(4, argP1len - 5); bdef = cmSystemTools::HasEnv(env); } else if (argP1len > 6 && - cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") && - argP1->GetValue().operator[](argP1len - 1) == '}') { - const auto cache = argP1->GetValue().substr(6, argP1len - 7); - bdef = this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr; + cmHasLiteralPrefix(args.next->GetValue(), "CACHE{") && + args.next->GetValue().operator[](argP1len - 1) == '}') { + const auto cache = args.next->GetValue().substr(6, argP1len - 7); + bdef = bool(this->Makefile.GetState()->GetCacheEntryValue(cache)); } else { - bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); + bdef = this->Makefile.IsDefinitionSet(args.next->GetValue()); } - HandlePredicate(bdef, newArgs, arg, argP1); + newArgs.ReduceOneArg(bdef, args); } // does a test exist - else if (this->IsKeyword(keyTEST, *arg)) { + else if (this->IsKeyword(keyTEST, *args.current)) { if (policy64IsOld) { continue; } - HandlePredicate(this->Makefile.GetTest(argP1->GetValue()) != nullptr, - newArgs, arg, argP1); + newArgs.ReduceOneArg(bool(this->Makefile.GetTest(args.next->GetValue())), + args); } } return true; @@ -559,32 +614,32 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; - arg != newArgs.end(); argP1 = ++arg) { - - IncrementArguments(newArgs, argP1, argP2); + for (auto args = newArgs.make3ArgsIterator(); args.current != newArgs.end(); + args.advance(newArgs)) { int matchNo; - // NOTE Handle special case `if(... BLAH_BAH MATCHES)` + // NOTE Handle special case `if(... BLAH_BLAH MATCHES)` // (i.e., w/o regex to match which is possibly result of // variable expansion to an empty string) - if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) { - HandlePredicate(false, newArgs, arg, argP1); + if (args.next != newArgs.end() && + this->IsKeyword(keyMATCHES, *args.current)) { + newArgs.ReduceOneArg(false, args); } // NOTE Fail fast: All the binary ops below require 2 arguments. - else if (argP1 == newArgs.end() || argP2 == newArgs.end()) { + else if (args.next == newArgs.end() || args.nextnext == newArgs.end()) { continue; } - else if (this->IsKeyword(keyMATCHES, *argP1)) { - cmProp def = this->GetDefinitionIfUnquoted(*arg); + else if (this->IsKeyword(keyMATCHES, *args.next)) { + cmProp def = this->GetDefinitionIfUnquoted(*args.current); std::string def_buf; if (!def) { - def = &arg->GetValue(); - } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) { + def = &args.current->GetValue(); + } else if (cmHasLiteralPrefix(args.current->GetValue(), + "CMAKE_MATCH_")) { // The string to match is owned by our match result variables. // Move it to our own buffer before clearing them. def_buf = *def; @@ -593,7 +648,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->Makefile.ClearMatches(); - const auto& rex = argP2->GetValue(); + const auto& rex = args.nextnext->GetValue(); cmsys::RegularExpression regEntry; if (!regEntry.compile(rex)) { std::ostringstream error; @@ -607,15 +662,15 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (match) { this->Makefile.StoreMatches(regEntry); } - HandleBinaryOp(match, newArgs, arg, argP1, argP2); + newArgs.ReduceTwoArgs(match, args); } else if ((matchNo = - this->matchKeys(*argP1, keyLESS, keyLESS_EQUAL, keyGREATER, + this->matchKeys(*args.next, keyLESS, keyLESS_EQUAL, keyGREATER, keyGREATER_EQUAL, keyEQUAL))) { - cmProp ldef = this->GetVariableOrString(*arg); - cmProp rdef = this->GetVariableOrString(*argP2); + cmProp ldef = this->GetVariableOrString(*args.current); + cmProp rdef = this->GetVariableOrString(*args.nextnext); double lhs; double rhs; @@ -623,23 +678,23 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, return std::sscanf(ldef->c_str(), "%lg", &lhs) == 1 && std::sscanf(rdef->c_str(), "%lg", &rhs) == 1; }; + // clang-format off const auto result = parseDoubles() && - // clang-format off cmRt2CtSelector< std::less, std::less_equal, std::greater, std::greater_equal, std::equal_to >::eval(matchNo, lhs, rhs); // clang-format on - HandleBinaryOp(result, newArgs, arg, argP1, argP2); + newArgs.ReduceTwoArgs(result, args); } - else if ((matchNo = this->matchKeys(*argP1, keySTRLESS, keySTRLESS_EQUAL, - keySTRGREATER, keySTRGREATER_EQUAL, - keySTREQUAL))) { + else if ((matchNo = this->matchKeys(*args.next, keySTRLESS, + keySTRLESS_EQUAL, keySTRGREATER, + keySTRGREATER_EQUAL, keySTREQUAL))) { - const cmProp lhs = this->GetVariableOrString(*arg); - const cmProp rhs = this->GetVariableOrString(*argP2); + const cmProp lhs = this->GetVariableOrString(*args.current); + const cmProp rhs = this->GetVariableOrString(*args.nextnext); const auto val = (*lhs).compare(*rhs); // clang-format off const auto result = cmRt2CtSelector< @@ -648,45 +703,46 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::equal_to >::eval(matchNo, val, 0); // clang-format on - HandleBinaryOp(result, newArgs, arg, argP1, argP2); + newArgs.ReduceTwoArgs(result, args); } else if ((matchNo = - this->matchKeys(*argP1, keyVERSION_LESS, keyVERSION_LESS_EQUAL, - keyVERSION_GREATER, keyVERSION_GREATER_EQUAL, - keyVERSION_EQUAL))) { + this->matchKeys(*args.next, keyVERSION_LESS, + keyVERSION_LESS_EQUAL, keyVERSION_GREATER, + keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) { + const cmSystemTools::CompareOp xlat[5] = { cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL, cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL, cmSystemTools::OP_EQUAL }; const auto op = xlat[matchNo - 1]; - const cmProp lhs = this->GetVariableOrString(*arg); - const cmProp rhs = this->GetVariableOrString(*argP2); + const cmProp lhs = this->GetVariableOrString(*args.current); + const cmProp rhs = this->GetVariableOrString(*args.nextnext); const auto result = cmSystemTools::VersionCompare(op, lhs->c_str(), rhs->c_str()); - HandleBinaryOp(result, newArgs, arg, argP1, argP2); + newArgs.ReduceTwoArgs(result, args); } // is file A newer than file B - else if (this->IsKeyword(keyIS_NEWER_THAN, *argP1)) { + else if (this->IsKeyword(keyIS_NEWER_THAN, *args.next)) { auto fileIsNewer = 0; cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare( - arg->GetValue(), argP2->GetValue(), &fileIsNewer); - HandleBinaryOp((!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), - newArgs, arg, argP1, argP2); + args.current->GetValue(), args.nextnext->GetValue(), &fileIsNewer); + newArgs.ReduceTwoArgs( + (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), args); } - else if (this->IsKeyword(keyIN_LIST, *argP1)) { + else if (this->IsKeyword(keyIN_LIST, *args.next)) { if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { - cmProp def = this->GetVariableOrString(*arg); - cmProp def2 = this->Makefile.GetDefinition(argP2->GetValue()); + cmProp def = this->GetVariableOrString(*args.current); + cmProp def2 = this->Makefile.GetDefinition(args.nextnext->GetValue()); - HandleBinaryOp(def2 && cm::contains(cmExpandedList(*def2, true), *def), - newArgs, arg, argP1, argP2); + newArgs.ReduceTwoArgs( + def2 && cm::contains(cmExpandedList(*def2, true), *def), args); } else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) @@ -708,15 +764,12 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - for (auto arg = newArgs.begin(), argP1 = arg; arg != newArgs.end(); - argP1 = ++arg) { - - IncrementArguments(newArgs, argP1); - - if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) { - const auto rhs = - this->GetBooleanValueWithAutoDereference(*argP1, errorString, status); - HandlePredicate(!rhs, newArgs, arg, argP1); + for (auto args = newArgs.make2ArgsIterator(); args.next != newArgs.end(); + args.advance(newArgs)) { + if (this->IsKeyword(keyNOT, *args.current)) { + const auto rhs = this->GetBooleanValueWithAutoDereference( + *args.next, errorString, status); + newArgs.ReduceOneArg(!rhs, args); } } return true; @@ -728,20 +781,23 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs, std::string& errorString, MessageType& status) { - for (auto arg = newArgs.begin(), argP1 = arg, argP2 = arg; - arg != newArgs.end(); argP1 = ++arg) { - - IncrementArguments(newArgs, argP1, argP2); - - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (this->IsKeyword(keyAND, *argP1) || this->IsKeyword(keyOR, *argP1))) { - const auto lhs = - this->GetBooleanValueWithAutoDereference(*arg, errorString, status); - const auto rhs = - this->GetBooleanValueWithAutoDereference(*argP2, errorString, status); - HandleBinaryOp(this->IsKeyword(keyAND, *argP1) ? (lhs && rhs) - : (lhs || rhs), - newArgs, arg, argP1, argP2); + for (auto args = newArgs.make3ArgsIterator(); args.nextnext != newArgs.end(); + args.advance(newArgs)) { + + int matchNo; + + if ((matchNo = this->matchKeys(*args.next, keyAND, keyOR))) { + const auto lhs = this->GetBooleanValueWithAutoDereference( + *args.current, errorString, status); + const auto rhs = this->GetBooleanValueWithAutoDereference( + *args.nextnext, errorString, status); + // clang-format off + const auto result = + cmRt2CtSelector< + std::logical_and, std::logical_or + >::eval(matchNo, lhs, rhs); + // clang-format on + newArgs.ReduceTwoArgs(result, args); } } return true; diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 83670071c47..00d896b82e2 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -4,25 +4,22 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <list> #include <string> #include <vector> #include <cmext/string_view> -#include "cmExpandedCommandArgument.h" #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmProperty.h" +class cmExpandedCommandArgument; class cmMakefile; class cmConditionEvaluator { public: - using cmArgumentList = std::list<cmExpandedCommandArgument>; - cmConditionEvaluator(cmMakefile& makefile, cmListFileBacktrace bt); // this is a shared function for both If and Else to determine if the @@ -32,6 +29,8 @@ class cmConditionEvaluator std::string& errorString, MessageType& status); private: + class cmArgumentList; + // Filter the given variable definition based on policy CMP0054. cmProp GetDefinitionIfUnquoted( const cmExpandedCommandArgument& argument) const; @@ -51,6 +50,15 @@ class cmConditionEvaluator MessageType& status, bool oneArg = false) const; + template <int N> + int matchKeysImpl(const cmExpandedCommandArgument&); + + template <int N, typename T, typename... Keys> + int matchKeysImpl(const cmExpandedCommandArgument&, T, Keys...); + + template <typename... Keys> + int matchKeys(const cmExpandedCommandArgument&, Keys...); + bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString, MessageType& status); @@ -65,15 +73,6 @@ class cmConditionEvaluator bool HandleLevel4(cmArgumentList& newArgs, std::string& errorString, MessageType& status); - template <int N> - int matchKeysImpl(const cmExpandedCommandArgument&); - - template <int N, typename T, typename... Keys> - int matchKeysImpl(const cmExpandedCommandArgument&, T, Keys...); - - template <typename... Keys> - int matchKeys(const cmExpandedCommandArgument&, Keys...); - cmMakefile& Makefile; cmListFileBacktrace Backtrace; cmPolicies::PolicyStatus Policy12Status; diff --git a/Tests/RunCMake/if/IncompleteMatches-stdout.txt b/Tests/RunCMake/if/IncompleteMatches-stdout.txt new file mode 100644 index 00000000000..634d9884911 --- /dev/null +++ b/Tests/RunCMake/if/IncompleteMatches-stdout.txt @@ -0,0 +1,6 @@ +-- Test #1 passed +-- Test #2 passed +-- Test #3 passed +-- Test #4 passed +-- Test #5 passed +-- Test #6 passed diff --git a/Tests/RunCMake/if/IncompleteMatches.cmake b/Tests/RunCMake/if/IncompleteMatches.cmake new file mode 100644 index 00000000000..7142cfc3271 --- /dev/null +++ b/Tests/RunCMake/if/IncompleteMatches.cmake @@ -0,0 +1,36 @@ +if(MATCHES) + message(SEND_ERROR "Test #1 failed") +else() + message(STATUS "Test #1 passed") +endif() + +if("" MATCHES "") + message(STATUS "Test #2 passed") +else() + message(SEND_ERROR "Test #2 failed") +endif() + +if(MATCHES RHS) + message(SEND_ERROR "Test #3 failed") +else() + message(STATUS "Test #3 passed") +endif() + +set(RHS "") +if(MATCHES RHS) + message(SEND_ERROR "Test #4 failed") +else() + message(STATUS "Test #4 passed") +endif() + +if(MATCHES "^$") + message(SEND_ERROR "Test #5 failed") +else() + message(STATUS "Test #5 passed") +endif() + +if("" MATCHES "^$") + message(STATUS "Test #6 passed") +else() + message(SEND_ERROR "Test #6 failed") +endif() diff --git a/Tests/RunCMake/if/IncompleteMatchesFail-result.txt b/Tests/RunCMake/if/IncompleteMatchesFail-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/if/IncompleteMatchesFail-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt b/Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt new file mode 100644 index 00000000000..6e8ac80be3d --- /dev/null +++ b/Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at IncompleteMatchesFail\.cmake:1 \(if\): + if given arguments: + + "LHS" "MATCHES" + + Unknown arguments specified diff --git a/Tests/RunCMake/if/IncompleteMatchesFail.cmake b/Tests/RunCMake/if/IncompleteMatchesFail.cmake new file mode 100644 index 00000000000..a3ef2b8ae41 --- /dev/null +++ b/Tests/RunCMake/if/IncompleteMatchesFail.cmake @@ -0,0 +1,2 @@ +if(LHS MATCHES) +endif() diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake index f54edf7edd1..239c167139f 100644 --- a/Tests/RunCMake/if/RunCMakeTest.cmake +++ b/Tests/RunCMake/if/RunCMakeTest.cmake @@ -10,6 +10,8 @@ run_cmake(elseif-message) run_cmake(misplaced-elseif) run_cmake(MatchesSelf) +run_cmake(IncompleteMatches) +run_cmake(IncompleteMatchesFail) run_cmake(TestNameThatExists) run_cmake(TestNameThatDoesNotExist) From 0dd77957063f07d5ab8dc8ddb7a56930c688d523 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 23:05:08 +0300 Subject: [PATCH 1076/1519] Refactor: Extract the logic of testing for special variable to func Introduce `looksLikeSpecialVariable`. It makes `if()` blocks readable. --- Source/cmConditionEvaluator.cxx | 41 ++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 444d029926f..a239fcc8559 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -91,6 +91,16 @@ std::string bool2string(bool const value) { return std::string(std::size_t(1), static_cast<char>('0' + int(value))); } + +bool looksLikeSpecialVariable(const std::string& var, + cm::static_string_view prefix, + const std::size_t varNameLen) +{ + // NOTE Expecting a variable name at least 1 char length: + // <prefix> + `{` + <varname> + `}` + return ((prefix.size() + 3) <= varNameLen) && + cmHasPrefix(var, cmStrCat(prefix, '{')) && var[varNameLen - 1] == '}'; +} } // anonymous namespace #if defined(__SUNPRO_CC) @@ -580,21 +590,24 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } // is a variable defined else if (this->IsKeyword(keyDEFINED, *args.current)) { - const auto argP1len = args.next->GetValue().size(); - auto bdef = false; - if (argP1len > 4 && cmHasLiteralPrefix(args.next->GetValue(), "ENV{") && - args.next->GetValue().operator[](argP1len - 1) == '}') { - const auto env = args.next->GetValue().substr(4, argP1len - 5); - bdef = cmSystemTools::HasEnv(env); - } else if (argP1len > 6 && - cmHasLiteralPrefix(args.next->GetValue(), "CACHE{") && - args.next->GetValue().operator[](argP1len - 1) == '}') { - const auto cache = args.next->GetValue().substr(6, argP1len - 7); - bdef = bool(this->Makefile.GetState()->GetCacheEntryValue(cache)); - } else { - bdef = this->Makefile.IsDefinitionSet(args.next->GetValue()); + const auto& var = args.next->GetValue(); + const auto varNameLen = var.size(); + + auto result = false; + if (looksLikeSpecialVariable(var, "ENV"_s, varNameLen)) { + const auto env = args.next->GetValue().substr(4, varNameLen - 5); + result = cmSystemTools::HasEnv(env); + } + + else if (looksLikeSpecialVariable(var, "CACHE"_s, varNameLen)) { + const auto cache = args.next->GetValue().substr(6, varNameLen - 7); + result = bool(this->Makefile.GetState()->GetCacheEntryValue(cache)); + } + + else { + result = this->Makefile.IsDefinitionSet(args.next->GetValue()); } - newArgs.ReduceOneArg(bdef, args); + newArgs.ReduceOneArg(result, args); } // does a test exist else if (this->IsKeyword(keyTEST, *args.current)) { From 2a72cad9bec2e9bf2fafcde4e0affcf0a6afc96e Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 23:09:18 +0300 Subject: [PATCH 1077/1519] Style: Better names of local vars for `IN_LIST` handler --- Source/cmConditionEvaluator.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index a239fcc8559..d55a89c8ef2 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -751,12 +751,14 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { - cmProp def = this->GetVariableOrString(*args.current); - cmProp def2 = this->Makefile.GetDefinition(args.nextnext->GetValue()); + cmProp lhs = this->GetVariableOrString(*args.current); + cmProp rhs = this->Makefile.GetDefinition(args.nextnext->GetValue()); newArgs.ReduceTwoArgs( - def2 && cm::contains(cmExpandedList(*def2, true), *def), args); - } else if (this->Policy57Status == cmPolicies::WARN) { + rhs && cm::contains(cmExpandedList(*rhs, true), *lhs), args); + } + + else if (this->Policy57Status == cmPolicies::WARN) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n" From 00961a4782d9b22adce4d75ea61eb2f1d16ad0e5 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 27 Jul 2021 23:22:10 +0300 Subject: [PATCH 1078/1519] Refactor: Copy exactly required count of args and avoid `pop_back()` --- Source/cmConditionEvaluator.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index d55a89c8ef2..ea5dce5eb12 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -498,18 +498,19 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, status = MessageType::FATAL_ERROR; return false; } + // store the reduced args in this vector - auto argP1 = std::next(arg); - std::vector<cmExpandedCommandArgument> newArgs2{ argP1, argClose }; - newArgs2.pop_back(); + auto argOpen = std::next(arg); + const std::vector<cmExpandedCommandArgument> subExpr( + argOpen, std::prev(argClose)); // now recursively invoke IsTrue to handle the values inside the // parenthetical expression - const auto value = this->IsTrue(newArgs2, errorString, status); + const auto value = this->IsTrue(subExpr, errorString, status); *arg = cmExpandedCommandArgument(bool2string(value), true); - argP1 = std::next(arg); + argOpen = std::next(arg); // remove the now evaluated parenthetical expression - newArgs.erase(argP1, argClose); + newArgs.erase(argOpen, argClose); } } return true; From f37d6a31703bd74dddfbc82b41f3d97633edb70b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 2 Aug 2021 19:22:07 +0300 Subject: [PATCH 1079/1519] Refactor: Remove redundant checks for `0` and `1` literals They are gonna be checked by `cmIsOn()` anyway. --- Source/cmConditionEvaluator.cxx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index ea5dce5eb12..9485d04c2a5 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -355,15 +355,7 @@ bool cmConditionEvaluator::IsKeyword( bool cmConditionEvaluator::GetBooleanValue( cmExpandedCommandArgument& arg) const { - // Check basic constants. - if (arg == "0") { - return false; - } - if (arg == "1") { - return true; - } - - // Check named constants. + // Check basic and named constants. if (cmIsOn(arg.GetValue())) { return true; } From 54a70b3988d756cccf92773d86b38e3b2574758c Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 3 Aug 2021 17:14:04 +0300 Subject: [PATCH 1080/1519] Refactor: Move version compare op table out of the function It's static data and never changed. --- Source/cmConditionEvaluator.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 9485d04c2a5..415f667c61c 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -59,6 +59,12 @@ auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s; auto const keyVERSION_LESS = "VERSION_LESS"_s; auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s; +cmSystemTools::CompareOp const MATCH2CMPOP[5] = { + cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL, + cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL, + cmSystemTools::OP_EQUAL +}; + // Run-Time to Compile-Time template selector template <template <typename> class Comp, template <typename> class... Ops> struct cmRt2CtSelector @@ -716,13 +722,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->matchKeys(*args.next, keyVERSION_LESS, keyVERSION_LESS_EQUAL, keyVERSION_GREATER, keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) { - - const cmSystemTools::CompareOp xlat[5] = { - cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL, - cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL, - cmSystemTools::OP_EQUAL - }; - const auto op = xlat[matchNo - 1]; + const auto op = MATCH2CMPOP[matchNo - 1]; const cmProp lhs = this->GetVariableOrString(*args.current); const cmProp rhs = this->GetVariableOrString(*args.nextnext); const auto result = From 93eb4a7bd17f0da02a5ea71426bed5c2056e9ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= <congdanhqx@gmail.com> Date: Sat, 31 Jul 2021 14:17:35 +0700 Subject: [PATCH 1081/1519] Ninja: Revert accidental LINK_WHAT_YOU_USE impl for static libraries In commit d7159f9591, (Ninja: Fix LINK_WHAT_YOU_USE link flag placement, 2021-06-24), we fixed usage of -Wl,--no-as-needed to override -Wl,--as-needed from LDFLAGS. However, that change also passes -Wl,--no-as-needed to `ar`, which is incorrect flag for `ar`. Let's check the target type before passing down the flags. Fixes: #22487 --- Source/cmNinjaNormalTargetGenerator.cxx | 5 ++++- Tests/RunCMake/LinkWhatYouUse/C.cmake | 1 + Tests/RunCMake/LinkWhatYouUse/CXX.cmake | 1 + Tests/RunCMake/LinkWhatYouUse/foo.c | 4 ++++ Tests/RunCMake/LinkWhatYouUse/foo.cxx | 4 ++++ 5 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/LinkWhatYouUse/foo.c create mode 100644 Tests/RunCMake/LinkWhatYouUse/foo.cxx diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 5a4c6521d84..61cfa11f787 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -1156,7 +1156,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], config); - if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { + if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE") && + (gt->GetType() == cmStateEnums::TargetType::EXECUTABLE || + gt->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY || + gt->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY)) { vars["LINK_FLAGS"] += " -Wl,--no-as-needed"; } vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); diff --git a/Tests/RunCMake/LinkWhatYouUse/C.cmake b/Tests/RunCMake/LinkWhatYouUse/C.cmake index 4c3f428284d..f00db305720 100644 --- a/Tests/RunCMake/LinkWhatYouUse/C.cmake +++ b/Tests/RunCMake/LinkWhatYouUse/C.cmake @@ -2,3 +2,4 @@ enable_language(C) set(CMAKE_LINK_WHAT_YOU_USE TRUE) add_executable(main main.c) target_link_libraries(main m) +add_library(foo STATIC foo.c) diff --git a/Tests/RunCMake/LinkWhatYouUse/CXX.cmake b/Tests/RunCMake/LinkWhatYouUse/CXX.cmake index 95558327e3d..5762e94112d 100644 --- a/Tests/RunCMake/LinkWhatYouUse/CXX.cmake +++ b/Tests/RunCMake/LinkWhatYouUse/CXX.cmake @@ -2,3 +2,4 @@ enable_language(CXX) set(CMAKE_LINK_WHAT_YOU_USE TRUE) add_executable(main main.cxx) target_link_libraries(main m) +add_library(foo STATIC foo.cxx) diff --git a/Tests/RunCMake/LinkWhatYouUse/foo.c b/Tests/RunCMake/LinkWhatYouUse/foo.c new file mode 100644 index 00000000000..c83d85699cc --- /dev/null +++ b/Tests/RunCMake/LinkWhatYouUse/foo.c @@ -0,0 +1,4 @@ +int foo(void) +{ + return 0; +} diff --git a/Tests/RunCMake/LinkWhatYouUse/foo.cxx b/Tests/RunCMake/LinkWhatYouUse/foo.cxx new file mode 100644 index 00000000000..e05eb7e694a --- /dev/null +++ b/Tests/RunCMake/LinkWhatYouUse/foo.cxx @@ -0,0 +1,4 @@ +int foo() +{ + return 0; +} From 85b5e6a458cfdf78005dcab64587e0ced5f490ba Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 4 Aug 2021 00:01:14 -0400 Subject: [PATCH 1082/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9a3e312e1a7..14a64597cf5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210803) +set(CMake_VERSION_PATCH 20210804) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6c0f476505166c3aed414c7707b92c68e278f9b3 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 5 Aug 2021 00:01:12 -0400 Subject: [PATCH 1083/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 14a64597cf5..11282c623fe 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210804) +set(CMake_VERSION_PATCH 20210805) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ea6a7dd1c2e76533d6aa4725e04acc3d8e1ed912 Mon Sep 17 00:00:00 2001 From: Ashish Sadanandan <ashish.sadanandan@gmail.com> Date: Mon, 26 Jul 2021 10:44:21 -0600 Subject: [PATCH 1084/1519] GoogleTest: Add TEST_FILTER arg to gtest_discover_tests The `TEST_FILTER` argument can be used to filter tests during the discovery phase. It combines `--gtest_filter=<expr>` with the `--gtest_list_tests` argument when invoking the test excutable for listing defined tests. Fixes: #17493 --- Help/release/dev/GoogleTest-gtest-filter.rst | 6 ++ Modules/GoogleTest.cmake | 11 +++- Modules/GoogleTestAddTests.cmake | 11 +++- .../GoogleTest/GoogleTest-test3-stdout.txt | 16 ++++++ .../GoogleTest/GoogleTest-test4-stdout.txt | 9 +++ Tests/RunCMake/GoogleTest/GoogleTest.cmake | 18 ++++++ Tests/RunCMake/GoogleTest/RunCMakeTest.cmake | 14 +++++ Tests/RunCMake/GoogleTest/fake_gtest.cpp | 55 ++++++++++++------- 8 files changed, 117 insertions(+), 23 deletions(-) create mode 100644 Help/release/dev/GoogleTest-gtest-filter.rst create mode 100644 Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt create mode 100644 Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt diff --git a/Help/release/dev/GoogleTest-gtest-filter.rst b/Help/release/dev/GoogleTest-gtest-filter.rst new file mode 100644 index 00000000000..48b97a72500 --- /dev/null +++ b/Help/release/dev/GoogleTest-gtest-filter.rst @@ -0,0 +1,6 @@ +GoogleTest-gtest-filter +----------------------- + +* The :module:`GoogleTest` module :command:`gtest_discover_tests` + function gained a ``TEST_FILTER`` option to filter tests using + ``--gtest_filter`` during test discovery. diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index 80d8e239715..a483c0356db 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -151,6 +151,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also [WORKING_DIRECTORY dir] [TEST_PREFIX prefix] [TEST_SUFFIX suffix] + [TEST_FILTER expr] [NO_PRETTY_TYPES] [NO_PRETTY_VALUES] [PROPERTIES name1 value1...] [TEST_LIST var] @@ -204,6 +205,12 @@ same as the Google Test name (i.e. ``suite.testcase``); see also every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may be specified. + ``TEST_FILTER expr`` + .. versionadded:: 3.22 + + Filter expression to pass to ``--gtest_filter`` argument during test + discovery. + ``NO_PRETTY_TYPES`` By default, the type index of type-parameterized tests is replaced by the actual type name in the CTest test name. If this behavior is undesirable @@ -411,7 +418,7 @@ function(gtest_discover_tests TARGET) "" "NO_PRETTY_TYPES;NO_PRETTY_VALUES" "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;DISCOVERY_TIMEOUT;XML_OUTPUT_DIR;DISCOVERY_MODE" - "EXTRA_ARGS;PROPERTIES" + "EXTRA_ARGS;PROPERTIES;TEST_FILTER" ${ARGN} ) @@ -475,6 +482,7 @@ function(gtest_discover_tests TARGET) -D "TEST_PROPERTIES=${_PROPERTIES}" -D "TEST_PREFIX=${_TEST_PREFIX}" -D "TEST_SUFFIX=${_TEST_SUFFIX}" + -D "TEST_FILTER=${_TEST_FILTER}" -D "NO_PRETTY_TYPES=${_NO_PRETTY_TYPES}" -D "NO_PRETTY_VALUES=${_NO_PRETTY_VALUES}" -D "TEST_LIST=${_TEST_LIST}" @@ -515,6 +523,7 @@ function(gtest_discover_tests TARGET) " TEST_PROPERTIES" " [==[" "${_PROPERTIES}" "]==]" "\n" " TEST_PREFIX" " [==[" "${_TEST_PREFIX}" "]==]" "\n" " TEST_SUFFIX" " [==[" "${_TEST_SUFFIX}" "]==]" "\n" + " TEST_FILTER" " [==[" "${_TEST_FILTER}" "]==]" "\n" " NO_PRETTY_TYPES" " [==[" "${_NO_PRETTY_TYPES}" "]==]" "\n" " NO_PRETTY_VALUES" " [==[" "${_NO_PRETTY_VALUES}" "]==]" "\n" " TEST_LIST" " [==[" "${_TEST_LIST}" "]==]" "\n" diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake index 0f79c9afc0e..6b3bf34ee87 100644 --- a/Modules/GoogleTestAddTests.cmake +++ b/Modules/GoogleTestAddTests.cmake @@ -44,7 +44,7 @@ function(gtest_discover_tests_impl) cmake_parse_arguments( "" "" - "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR" + "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR;TEST_FILTER" "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR" ${ARGN} ) @@ -58,6 +58,12 @@ function(gtest_discover_tests_impl) set(tests) set(tests_buffer) + if(_TEST_FILTER) + set(filter "--gtest_filter=${_TEST_FILTER}") + else() + set(filter) + endif() + # Run test executable to get list of available tests if(NOT EXISTS "${_TEST_EXECUTABLE}") message(FATAL_ERROR @@ -66,7 +72,7 @@ function(gtest_discover_tests_impl) ) endif() execute_process( - COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests + COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests ${filter} WORKING_DIRECTORY "${_TEST_WORKING_DIR}" TIMEOUT ${_TEST_DISCOVERY_TIMEOUT} OUTPUT_VARIABLE output @@ -178,6 +184,7 @@ if(CMAKE_SCRIPT_MODE_FILE) TEST_WORKING_DIR ${TEST_WORKING_DIR} TEST_PREFIX ${TEST_PREFIX} TEST_SUFFIX ${TEST_SUFFIX} + TEST_FILTER ${TEST_FILTER} TEST_LIST ${TEST_LIST} CTEST_FILE ${CTEST_FILE} TEST_DISCOVERY_TIMEOUT ${TEST_DISCOVERY_TIMEOUT} diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt new file mode 100644 index 00000000000..cf082670f73 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt @@ -0,0 +1,16 @@ +Test project .* + Start 27: TEST:basic\.case_foo!3 +1/4 Test #27: TEST:basic\.case_foo!3 \.+ +Passed +[0-9.]+ sec + Start 28: TEST:basic\.case_bar!3 +2/4 Test #28: TEST:basic\.case_bar!3 \.+ +Passed +[0-9.]+ sec + Start 29: TEST:basic\.disabled_case!3 +3/4 Test #29: TEST:basic\.disabled_case!3 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec + Start 30: TEST:basic\.DISABLEDnot_really_case!3 +4/4 Test #30: TEST:basic\.DISABLEDnot_really_case!3 \.+ +Passed +[0-9.]+ sec + +100% tests passed, 0 tests failed out of 3 + +Total Test time \(real\) = +[0-9.]+ sec + +The following tests did not run: +.*29 - TEST:basic.disabled_case!3 \(Disabled\) diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt new file mode 100644 index 00000000000..4a9d75b7871 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt @@ -0,0 +1,9 @@ +Test project .* + Start 31: TEST:typed/short\.case!4 +1/2 Test #31: TEST:typed/short\.case!4 \.+ +Passed +[0-9.]+ sec + Start 32: TEST:typed/float\.case!4 +2/2 Test #32: TEST:typed/float\.case!4 \.+ +Passed +[0-9.]+ sec + +100% tests passed, 0 tests failed out of 2 + +Total Test time \(real\) = +[0-9.]+ sec diff --git a/Tests/RunCMake/GoogleTest/GoogleTest.cmake b/Tests/RunCMake/GoogleTest/GoogleTest.cmake index 8efd1171de3..221d6adac49 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest.cmake +++ b/Tests/RunCMake/GoogleTest/GoogleTest.cmake @@ -24,6 +24,24 @@ gtest_discover_tests( PROPERTIES LABELS TEST2 ) +gtest_discover_tests( + fake_gtest + TEST_PREFIX TEST: + TEST_SUFFIX !3 + TEST_FILTER basic* + EXTRA_ARGS how now "\"brown\" cow" + PROPERTIES LABELS TEST3 +) + +gtest_discover_tests( + fake_gtest + TEST_PREFIX TEST: + TEST_SUFFIX !4 + TEST_FILTER typed* + EXTRA_ARGS how now "\"brown\" cow" + PROPERTIES LABELS TEST4 +) + add_executable(no_tests_defined no_tests_defined.cpp) xcode_sign_adhoc(no_tests_defined) diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake index 530c8abe5a5..c5c592507f2 100644 --- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake @@ -40,6 +40,20 @@ function(run_GoogleTest DISCOVERY_MODE) --no-label-summary ) + run_cmake_command(GoogleTest-test3 + ${CMAKE_CTEST_COMMAND} + -C Debug + -L TEST3 + --no-label-summary + ) + + run_cmake_command(GoogleTest-test4 + ${CMAKE_CTEST_COMMAND} + -C Debug + -L TEST4 + --no-label-summary + ) + run_cmake_command(GoogleTest-test-missing ${CMAKE_CTEST_COMMAND} -C Debug diff --git a/Tests/RunCMake/GoogleTest/fake_gtest.cpp b/Tests/RunCMake/GoogleTest/fake_gtest.cpp index 1956c37fe87..b2a5cb443f6 100644 --- a/Tests/RunCMake/GoogleTest/fake_gtest.cpp +++ b/Tests/RunCMake/GoogleTest/fake_gtest.cpp @@ -7,27 +7,42 @@ int main(int argc, char** argv) // it only requires that we produces output in the expected format when // invoked with --gtest_list_tests. Thus, we fake that here. This allows us // to test the module without actually needing Google Test. + bool is_filtered = + argc > 2 && std::string(argv[2]).find("--gtest_filter=") == 0; + bool is_basic_only = + is_filtered && std::string(argv[2]).find("basic*") != std::string::npos; + bool is_typed_only = + is_filtered && std::string(argv[2]).find("typed*") != std::string::npos; + if (argc > 1 && std::string(argv[1]) == "--gtest_list_tests") { - std::cout << "basic." << std::endl; - std::cout << " case_foo" << std::endl; - std::cout << " case_bar" << std::endl; - std::cout << " DISABLED_disabled_case" << std::endl; - std::cout << " DISABLEDnot_really_case" << std::endl; - std::cout << "DISABLED_disabled." << std::endl; - std::cout << " case" << std::endl; - std::cout << "DISABLEDnotreally." << std::endl; - std::cout << " case" << std::endl; - std::cout << "typed/0. # TypeParam = short" << std::endl; - std::cout << " case" << std::endl; - std::cout << "typed/1. # TypeParam = float" << std::endl; - std::cout << " case" << std::endl; - std::cout << "value/test." << std::endl; - std::cout << " case/0 # GetParam() = 1" << std::endl; - std::cout << " case/1 # GetParam() = \"foo\"" << std::endl; - std::cout << "param/special." << std::endl; - std::cout << " case/0 # GetParam() = \"semicolon;\"" << std::endl; - std::cout << " case/1 # GetParam() = \"backslash\\\"" << std::endl; - std::cout << " case/2 # GetParam() = \"${var}\"" << std::endl; + if (!is_typed_only) { + std::cout << "basic." << std::endl; + std::cout << " case_foo" << std::endl; + std::cout << " case_bar" << std::endl; + std::cout << " DISABLED_disabled_case" << std::endl; + std::cout << " DISABLEDnot_really_case" << std::endl; + } + if (!is_basic_only && !is_typed_only) { + std::cout << "DISABLED_disabled." << std::endl; + std::cout << " case" << std::endl; + std::cout << "DISABLEDnotreally." << std::endl; + std::cout << " case" << std::endl; + } + if (!is_basic_only) { + std::cout << "typed/0. # TypeParam = short" << std::endl; + std::cout << " case" << std::endl; + std::cout << "typed/1. # TypeParam = float" << std::endl; + std::cout << " case" << std::endl; + } + if (!is_basic_only && !is_typed_only) { + std::cout << "value/test." << std::endl; + std::cout << " case/0 # GetParam() = 1" << std::endl; + std::cout << " case/1 # GetParam() = \"foo\"" << std::endl; + std::cout << "param/special." << std::endl; + std::cout << " case/0 # GetParam() = \"semicolon;\"" << std::endl; + std::cout << " case/1 # GetParam() = \"backslash\\\"" << std::endl; + std::cout << " case/2 # GetParam() = \"${var}\"" << std::endl; + } return 0; } From f5dbc27c27a09a3d62d619e9859b3b8c3cb7699a Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Thu, 5 Aug 2021 09:11:40 -0400 Subject: [PATCH 1085/1519] NVHPC-CXX: Add support for C++20 --- Modules/Compiler/NVHPC-CXX.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake index ac75b53a409..534e822325f 100644 --- a/Modules/Compiler/NVHPC-CXX.cmake +++ b/Modules/Compiler/NVHPC-CXX.cmake @@ -4,4 +4,9 @@ include(Compiler/NVHPC) # Needed so that we support `LANGUAGE` property correctly set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++) +if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20.11) + set(CMAKE_CXX20_STANDARD_COMPILE_OPTION -std=c++20) + set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION -std=gnu++20) +endif() + __compiler_nvhpc(CXX) From 9ac426e46075871a283e6b2afdeb3792a70e5744 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Thu, 5 Aug 2021 16:19:23 -0400 Subject: [PATCH 1086/1519] NVHPC-C: Add support for C17 --- Modules/Compiler/NVHPC-C.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake index 72c26563f47..e37aad562c4 100644 --- a/Modules/Compiler/NVHPC-C.cmake +++ b/Modules/Compiler/NVHPC-C.cmake @@ -4,4 +4,9 @@ include(Compiler/NVHPC) # Needed so that we support `LANGUAGE` property correctly set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c) +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 20.11) + set(CMAKE_C17_STANDARD_COMPILE_OPTION -std=c17) + set(CMAKE_C17_EXTENSION_COMPILE_OPTION -std=gnu17) +endif() + __compiler_nvhpc(C) From 1df8c88ea2d93c7dd41c759dc8eb30a42f8c0ef9 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 6 Aug 2021 00:01:10 -0400 Subject: [PATCH 1087/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 11282c623fe..be42a28cb2c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210805) +set(CMake_VERSION_PATCH 20210806) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 7ef5255e1efdcbf48a62a3711b9f75ea69671c6e Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 6 Aug 2021 14:01:02 +0200 Subject: [PATCH 1088/1519] armclang: activate compiler dependencies generation --- Modules/Compiler/ARMClang-C.cmake | 8 ++++++++ Modules/Compiler/ARMClang-CXX.cmake | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/Modules/Compiler/ARMClang-C.cmake b/Modules/Compiler/ARMClang-C.cmake index 0a64a8a4f1a..01c4cea08e5 100644 --- a/Modules/Compiler/ARMClang-C.cmake +++ b/Modules/Compiler/ARMClang-C.cmake @@ -2,6 +2,14 @@ include(Compiler/Clang-C) include(Compiler/ARMClang) __compiler_armclang(C) +if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_C) + # dependencies are computed by the compiler itself + set(CMAKE_C_DEPFILE_FORMAT gcc) + set(CMAKE_C_DEPENDS_USE_COMPILER TRUE) +endif() + set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) diff --git a/Modules/Compiler/ARMClang-CXX.cmake b/Modules/Compiler/ARMClang-CXX.cmake index 5dfb4011e29..045b7831183 100644 --- a/Modules/Compiler/ARMClang-CXX.cmake +++ b/Modules/Compiler/ARMClang-CXX.cmake @@ -1,3 +1,11 @@ include(Compiler/Clang-CXX) include(Compiler/ARMClang) __compiler_armclang(CXX) + +if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_CXX) + # dependencies are computed by the compiler itself + set(CMAKE_CXX_DEPFILE_FORMAT gcc) + set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE) +endif() From bb19af546bd3cc31f449d98ebed4412f504a98b9 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Fri, 6 Aug 2021 03:57:19 -0400 Subject: [PATCH 1089/1519] Help: cmake_path: add missing parameter for cmake_path(`CONVERT` ... [NORMALIZE]) was missing in top summary --- Help/command/cmake_path.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst index 565a37b6a85..454c8605c7c 100644 --- a/Help/command/cmake_path.rst +++ b/Help/command/cmake_path.rst @@ -69,8 +69,8 @@ Synopsis `Native Conversion`_ cmake_path(`NATIVE_PATH`_ <path-var> [NORMALIZE] <out-var>) - cmake_path(`CONVERT`_ <input> `TO_CMAKE_PATH_LIST`_ <out-var>) - cmake_path(`CONVERT`_ <input> `TO_NATIVE_PATH_LIST`_ <out-var>) + cmake_path(`CONVERT`_ <input> `TO_CMAKE_PATH_LIST`_ <out-var> [NORMALIZE]) + cmake_path(`CONVERT`_ <input> `TO_NATIVE_PATH_LIST`_ <out-var> [NORMALIZE]) `Hashing`_ cmake_path(`HASH`_ <path-var> <out-var>) From cc94429c61fcdff73ff78430692ff12ed1fff29b Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 7 Aug 2021 00:01:15 -0400 Subject: [PATCH 1090/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index be42a28cb2c..b2abd3dc7e5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210806) +set(CMake_VERSION_PATCH 20210807) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d1b2916bbb42ffbf8cd418fe867ec8d7cf36d4a4 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 8 Aug 2021 00:01:10 -0400 Subject: [PATCH 1091/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b2abd3dc7e5..001ac78c031 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210807) +set(CMake_VERSION_PATCH 20210808) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e5cd39ca80c8c234118ded33a1576c1be281aa9e Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Wed, 4 Aug 2021 15:08:17 +0200 Subject: [PATCH 1092/1519] cmProp: refactoring: transform alias in class To handle safely the values used by CMake variables and properties, introduce the class cmProp as a replacement from the simple pointer to std::string instance. --- Source/CMakeLists.txt | 1 + Source/CTest/cmCTestStartCommand.cxx | 8 +- Source/CTest/cmCTestSubmitCommand.cxx | 4 +- Source/QtDialog/QCMake.cxx | 6 +- Source/cmCMakePolicyCommand.cxx | 1 + Source/cmCacheManager.cxx | 6 +- Source/cmCacheManager.h | 2 +- Source/cmCommandArgumentParserHelper.cxx | 2 +- Source/cmConditionEvaluator.cxx | 8 +- Source/cmCoreTryCompile.cxx | 10 +- Source/cmDefinitions.cxx | 6 +- Source/cmDefinitions.h | 4 +- Source/cmExportBuildFileGenerator.cxx | 1 + Source/cmExportInstallFileGenerator.cxx | 1 + Source/cmFileAPICodemodel.cxx | 3 +- Source/cmFileCommand.cxx | 4 +- Source/cmFindBase.cxx | 4 +- Source/cmForEachCommand.cxx | 1 + Source/cmGeneratorTarget.cxx | 27 ++- Source/cmGlobalGenerator.cxx | 4 +- Source/cmGlobalGhsMultiGenerator.cxx | 3 +- Source/cmIncludeGuardCommand.cxx | 1 + Source/cmMakefile.cxx | 11 +- Source/cmMarkAsAdvancedCommand.cxx | 1 + Source/cmOptionCommand.cxx | 4 +- Source/cmPolicies.cxx | 1 + Source/cmProperty.cxx | 113 +++++++++++ Source/cmProperty.h | 210 ++++++++++++++++++++- Source/cmPropertyMap.cxx | 2 +- Source/cmSourceFile.cxx | 14 +- Source/cmState.cxx | 18 +- Source/cmStateDirectory.cxx | 30 +-- Source/cmStateSnapshot.cxx | 3 +- Source/cmStateSnapshot.h | 3 +- Source/cmStringAlgorithms.cxx | 70 ------- Source/cmStringAlgorithms.h | 64 ++++--- Source/cmTarget.cxx | 43 ++--- Source/cmTargetPropertyComputer.h | 6 +- Source/cmVisualStudio10TargetGenerator.cxx | 5 +- bootstrap | 1 + 40 files changed, 482 insertions(+), 224 deletions(-) create mode 100644 Source/cmProperty.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6775acbe262..791871e12c5 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -381,6 +381,7 @@ set(SRCS cmProcessOutput.h cmProcessTools.cxx cmProcessTools.h + cmProperty.cxx cmProperty.h cmPropertyDefinition.cxx cmPropertyDefinition.h diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index 53e1b2f96f0..a8c24037316 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -30,8 +30,8 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, size_t cnt = 0; const char* smodel = nullptr; - const std::string* src_dir = nullptr; - const std::string* bld_dir = nullptr; + cmProp src_dir; + cmProp bld_dir; while (cnt < args.size()) { if (args[cnt] == "GROUP" || args[cnt] == "TRACK") { @@ -55,10 +55,10 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, smodel = args[cnt].c_str(); cnt++; } else if (!src_dir) { - src_dir = &args[cnt]; + src_dir = cmProp(args[cnt]); cnt++; } else if (!bld_dir) { - bld_dir = &args[cnt]; + bld_dir = cmProp(args[cnt]); cnt++; } else { this->SetError("Too many arguments"); diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index bdba0e5d293..7aeb288435f 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -36,8 +36,8 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone() cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() { - const std::string* submitURL = !this->SubmitURL.empty() - ? &this->SubmitURL + cmProp submitURL = !this->SubmitURL.empty() + ? cmProp(this->SubmitURL) : this->Makefile->GetDefinition("CTEST_SUBMIT_URL"); if (submitURL) { diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 859c18dad30..41e8a559451 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -128,11 +128,11 @@ void QCMake::setBinaryDirectory(const QString& _dir) } cmProp gen = state->GetCacheEntryValue("CMAKE_GENERATOR"); if (gen) { - const std::string* extraGen = + cmProp extraGen = state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string curGen = - cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - *gen, extraGen ? *extraGen : ""); + cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*gen, + *extraGen); this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); } diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 1f99043647e..b2830e2c33d 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -6,6 +6,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 1a950dfb0f7..8fefaa6b657 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -500,7 +500,7 @@ cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const { if (const auto* entry = this->GetCacheEntry(key)) { if (entry->Initialized) { - return &entry->GetValue(); + return cmProp(entry->GetValue()); } } return nullptr; @@ -568,10 +568,10 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const { if (prop == "TYPE") { - return &cmState::CacheEntryTypeToString(this->Type); + return cmProp(cmState::CacheEntryTypeToString(this->Type)); } if (prop == "VALUE") { - return &this->Value; + return cmProp(this->Value); } return this->Properties.GetPropertyValue(prop); } diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index 7a9a7dc4158..0238fb8e0cd 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -75,7 +75,7 @@ class cmCacheManager cmProp GetCacheEntryValue(const std::string& key) const { if (const auto* entry = this->GetCacheEntry(key)) { - return &entry->GetValue(); + return cmProp(entry->GetValue()); } return nullptr; } diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index deddba8ef04..415f0c0c4d7 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -113,7 +113,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) if (this->EscapeQuotes && value) { return this->AddString(cmEscapeQuotes(*value)); } - return this->AddString(cmToCStrSafe(value)); + return this->AddString(value); } const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var) diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 415f667c61c..49189d8b1e0 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -317,7 +317,7 @@ cmProp cmConditionEvaluator::GetVariableOrString( cmProp def = this->GetDefinitionIfUnquoted(argument); if (!def) { - def = &argument.GetValue(); + def = cmProp(argument.GetValue()); } return def; @@ -403,7 +403,7 @@ bool cmConditionEvaluator::GetBooleanValueOld( // Old GetVariableOrNumber behavior. cmProp def = this->GetDefinitionIfUnquoted(arg); if (!def && std::atoi(arg.GetValue().c_str())) { - def = &arg.GetValue(); + def = cmProp(arg.GetValue()); } return !cmIsOff(def); } @@ -649,13 +649,13 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, std::string def_buf; if (!def) { - def = &args.current->GetValue(); + def = cmProp(args.current->GetValue()); } else if (cmHasLiteralPrefix(args.current->GetValue(), "CMAKE_MATCH_")) { // The string to match is owned by our match result variables. // Move it to our own buffer before clearing them. def_buf = *def; - def = &def_buf; + def = cmProp(def_buf); } this->Makefile.ClearMatches(); diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index bf181433bd3..0fd48f0b8f9 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -606,7 +606,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string langFlags = "CMAKE_" + li + "_FLAGS"; cmProp flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(), - cmOutputConverter::EscapeForCMake(cmToCStrSafe(flags)).c_str()); + cmOutputConverter::EscapeForCMake(flags).c_str()); fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" " ${COMPILE_DEFINITIONS}\")\n", @@ -644,9 +644,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string const langFlagsCfg = cmStrCat("CMAKE_", li, "_FLAGS_", cfg); cmProp flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); - fprintf( - fout, "set(%s %s)\n", langFlagsCfg.c_str(), - cmOutputConverter::EscapeForCMake(cmToCStrSafe(flagsCfg)).c_str()); + fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(), + cmOutputConverter::EscapeForCMake(flagsCfg).c_str()); } } break; } @@ -679,8 +678,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmProp exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", - cmOutputConverter::EscapeForCMake(cmToCStrSafe(exeLinkFlags)) - .c_str()); + cmOutputConverter::EscapeForCMake(exeLinkFlags).c_str()); } break; } diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 4a4f87d8b23..9e2d7b9e03c 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -34,11 +34,11 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, return begin->Map.emplace(key, def).first->second; } -const std::string* cmDefinitions::Get(const std::string& key, StackIter begin, - StackIter end) +cmProp cmDefinitions::Get(const std::string& key, StackIter begin, + StackIter end) { Def const& def = cmDefinitions::GetInternal(key, begin, end, false); - return def.Value ? def.Value.str_if_stable() : nullptr; + return def.Value ? cmProp(def.Value.str_if_stable()) : nullptr; } void cmDefinitions::Raise(const std::string& key, StackIter begin, diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index b650aa8604c..ee1db7ada2e 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -12,6 +12,7 @@ #include <cm/string_view> #include "cmLinkedTree.h" +#include "cmProperty.h" #include "cmString.hxx" /** \class cmDefinitions @@ -28,8 +29,7 @@ class cmDefinitions public: // -- Static member functions - static const std::string* Get(const std::string& key, StackIter begin, - StackIter end); + static cmProp Get(const std::string& key, StackIter begin, StackIter end); static void Raise(const std::string& key, StackIter begin, StackIter end); diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 4a9bf28dabb..6e3f918d6c0 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -18,6 +18,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 4249cfe2dbf..46d2d31cff5 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -16,6 +16,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index a2b5460c169..adeba74895d 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -813,8 +813,7 @@ Json::Value CodemodelConfig::DumpProject(Project& p) Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) { Json::Value minimumCMakeVersion; - if (std::string const* def = - s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { + if (cmProp def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { minimumCMakeVersion = Json::objectValue; minimumCMakeVersion["string"] = *def; } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1e3076f88dc..2730a076e4b 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1850,7 +1850,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } else if (*i == "TLS_CAINFO") { ++i; if (i != args.end()) { - cainfo = &(*i); + cainfo = cmProp(*i); } else { status.SetError("DOWNLOAD missing file value for TLS_CAINFO."); return false; @@ -2236,7 +2236,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, } else if (*i == "TLS_CAINFO") { ++i; if (i != args.end()) { - cainfo = &(*i); + cainfo = cmProp(*i); } else { status.SetError("UPLOAD missing file value for TLS_CAINFO."); return false; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 1038ac29e15..f4e1763e7fc 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -311,7 +311,7 @@ bool cmFindBase::CheckForVariableDefined() if (cached && cacheType != cmStateEnums::UNINITIALIZED) { this->VariableType = cacheType; - if (const auto* hs = + if (const auto& hs = state->GetCacheEntryProperty(this->VariableName, "HELPSTRING")) { this->VariableDocumentation = *hs; } @@ -336,7 +336,7 @@ void cmFindBase::NormalizeFindResult() if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) == cmPolicies::NEW) { // ensure the path returned by find_* command is absolute - const auto* existingValue = + const auto& existingValue = this->Makefile->GetDefinition(this->VariableName); std::string value; if (!existingValue->empty()) { diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 4845a6d0912..b44f79716c4 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -27,6 +27,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 17237bb5069..6bd41bd560b 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -62,7 +62,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, cmListFileBacktrace const& /* context */) { - return &tgt->GetSourcesProperty(); + return cmProp(tgt->GetSourcesProperty()); } template <> @@ -396,13 +396,7 @@ cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const std::string const& cmGeneratorTarget::GetSafeProperty( std::string const& prop) const { - cmProp ret = this->GetProperty(prop); - if (ret) { - return *ret; - } - - static std::string const s_empty; - return s_empty; + return this->GetProperty(prop); } const char* cmGeneratorTarget::GetOutputTargetType( @@ -564,7 +558,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const // framework postfix. frameworkPostfix = this->GetFrameworkMultiConfigPostfix(config); if (!frameworkPostfix.empty()) { - postfix = &frameworkPostfix; + postfix = cmProp(frameworkPostfix); } } return postfix ? *postfix : std::string(); @@ -966,7 +960,7 @@ cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, this->GetLanguageStandardProperty(lang, config); if (languageStandard) { - return &(languageStandard->Value); + return cmProp(languageStandard->Value); } return nullptr; @@ -5121,13 +5115,13 @@ void cmGeneratorTarget::GetFullNameInternal( if (this->IsFrameworkOnApple()) { fw_prefix = cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/'); - targetPrefix = &fw_prefix; + targetPrefix = cmProp(fw_prefix); targetSuffix = nullptr; } if (this->IsCFBundleOnApple()) { fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/'); - targetPrefix = &fw_prefix; + targetPrefix = cmProp(fw_prefix); targetSuffix = nullptr; } @@ -5143,7 +5137,7 @@ void cmGeneratorTarget::GetFullNameInternal( // EXECUTABLE_SUFFIX attribute. if (this->IsFrameworkOnApple() && this->GetGlobalGenerator()->GetName() == "Xcode") { - targetSuffix = &configPostfix; + targetSuffix = cmProp(configPostfix); } else { outBase += configPostfix; } @@ -5674,6 +5668,11 @@ std::string valueAsString<std::string>(std::string value) return value; } template <> +std::string valueAsString<cmProp>(cmProp value) +{ + return value ? value : std::string("(unset)"); +} +template <> std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/) { return "(unset)"; @@ -5749,7 +5748,7 @@ std::string getTypedProperty<std::string>( cmProp value = tgt->GetProperty(prop); if (genexInterpreter == nullptr) { - return valueAsString(cmToCStr(value)); + return valueAsString(value); } return genexInterpreter->Evaluate(value ? *value : "", prop); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 15a73045b65..aae6e35bda2 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -242,7 +242,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, std::vector<std::string> cnameArgVec; if (cname && !cname->empty()) { cmExpandList(*cname, cnameArgVec); - cname = &cnameArgVec.front(); + cname = cmProp(cnameArgVec.front()); } std::string changeVars; @@ -2749,7 +2749,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( singleLine.push_back(cfgArg); cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)"; } else { - cfgArg += cmToCStr(mf->GetDefinition("CMAKE_CFG_INTDIR")); + cfgArg += *mf->GetDefinition("CMAKE_CFG_INTDIR"); } singleLine.push_back(cfgArg); } diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 7cf3e9363a7..b81f82ec086 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -186,8 +186,7 @@ void cmGlobalGhsMultiGenerator::EnableLanguage( mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files - const char* tgtPlatform = - cmToCStrSafe(mf->GetDefinition("GHS_TARGET_PLATFORM")); + const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM")->c_str(); if (!tgtPlatform) { cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not " "specified; defaulting to \"integrity\""); diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx index aefd0985fd4..d48c823973b 100644 --- a/Source/cmIncludeGuardCommand.cxx +++ b/Source/cmIncludeGuardCommand.cxx @@ -4,6 +4,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 6d477a7660b..0b8778f9e83 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2579,12 +2579,7 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const { - static std::string const empty; - cmProp def = this->GetDefinition(name); - if (!def) { - return empty; - } - return *def; + return this->GetDefinition(name); } bool cmMakefile::GetDefExpandList(const std::string& name, @@ -2967,7 +2962,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( break; case ENVIRONMENT: if (cmSystemTools::GetEnv(lookup, svalue)) { - value = &svalue; + value = cmProp(svalue); } break; case CACHE: @@ -4012,7 +4007,7 @@ cmProp cmMakefile::GetProperty(const std::string& prop) const return pair.first; }); output = cmJoin(keys, ";"); - return &output; + return cmProp(output); } return this->StateSnapshot.GetDirectory().GetProperty(prop); diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx index 45043faa5d3..5908f7472d6 100644 --- a/Source/cmMarkAsAdvancedCommand.cxx +++ b/Source/cmMarkAsAdvancedCommand.cxx @@ -6,6 +6,7 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index bae67e04d18..014da4d2f24 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -29,7 +29,7 @@ bool cmOptionCommand(std::vector<std::string> const& args, { auto policyStatus = status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077); - const auto* existsBeforeSet = + const auto& existsBeforeSet = status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]); switch (policyStatus) { case cmPolicies::WARN: @@ -77,7 +77,7 @@ bool cmOptionCommand(std::vector<std::string> const& args, } if (checkAndWarn) { - const auto* existsAfterSet = + const auto& existsAfterSet = status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]); if (!existsAfterSet) { status.GetMakefile().IssueMessage( diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 01e8c047a03..fc839c537ec 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -10,6 +10,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx new file mode 100644 index 00000000000..d012630de31 --- /dev/null +++ b/Source/cmProperty.cxx @@ -0,0 +1,113 @@ + +#include "cmProperty.h" + +#include <string> + +#include <cmext/string_view> + +#include "cmStringAlgorithms.h" + +std::string cmProp::Empty; + +bool cmProp::IsOn(cm::string_view value) noexcept +{ + switch (value.size()) { + case 1: + return value[0] == '1' || value[0] == 'Y' || value[0] == 'y'; + case 2: + return // + (value[0] == 'O' || value[0] == 'o') && // + (value[1] == 'N' || value[1] == 'n'); + case 3: + return // + (value[0] == 'Y' || value[0] == 'y') && // + (value[1] == 'E' || value[1] == 'e') && // + (value[2] == 'S' || value[2] == 's'); + case 4: + return // + (value[0] == 'T' || value[0] == 't') && // + (value[1] == 'R' || value[1] == 'r') && // + (value[2] == 'U' || value[2] == 'u') && // + (value[3] == 'E' || value[3] == 'e'); + default: + break; + } + + return false; +} + +bool cmProp::IsOff(cm::string_view value) noexcept +{ + switch (value.size()) { + case 0: + return true; + case 1: + return value[0] == '0' || value[0] == 'N' || value[0] == 'n'; + case 2: + return // + (value[0] == 'N' || value[0] == 'n') && // + (value[1] == 'O' || value[1] == 'o'); + case 3: + return // + (value[0] == 'O' || value[0] == 'o') && // + (value[1] == 'F' || value[1] == 'f') && // + (value[2] == 'F' || value[2] == 'f'); + case 5: + return // + (value[0] == 'F' || value[0] == 'f') && // + (value[1] == 'A' || value[1] == 'a') && // + (value[2] == 'L' || value[2] == 'l') && // + (value[3] == 'S' || value[3] == 's') && // + (value[4] == 'E' || value[4] == 'e'); + case 6: + return // + (value[0] == 'I' || value[0] == 'i') && // + (value[1] == 'G' || value[1] == 'g') && // + (value[2] == 'N' || value[2] == 'n') && // + (value[3] == 'O' || value[3] == 'o') && // + (value[4] == 'R' || value[4] == 'r') && // + (value[5] == 'E' || value[5] == 'e'); + default: + break; + } + + return IsNOTFOUND(value); +} +bool cmProp::IsNOTFOUND(cm::string_view value) noexcept +{ + return (value == "NOTFOUND"_s) || cmHasSuffix(value, "-NOTFOUND"_s); +} + +int cmProp::Compare(cmProp value) const noexcept +{ + if (this->Value == nullptr && !value) { + return 0; + } + if (this->Value == nullptr) { + return -1; + } + if (!value) { + return 1; + } + return this->Value->compare(*value); +} + +int cmProp::Compare(cm::string_view value) const noexcept +{ + if (this->Value == nullptr && value.data() == nullptr) { + return 0; + } + if (this->Value == nullptr) { + return -1; + } + if (value.data() == nullptr) { + return 1; + } + return cm::string_view(*this->Value).compare(value); +} + +std::ostream& operator<<(std::ostream& o, cmProp v) +{ + o << *v; + return o; +} diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 1e03c3f0f5c..3a0a5be25c4 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -4,8 +4,12 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> +#include <iosfwd> #include <string> +#include <cm/string_view> + class cmProperty { public: @@ -23,14 +27,210 @@ class cmProperty }; }; -using cmProp = const std::string*; +class cmProp +{ +public: + cmProp() noexcept = default; + cmProp(std::nullptr_t) noexcept {} + explicit cmProp(const std::string* value) noexcept + : Value(value) + { + } + explicit cmProp(const std::string& value) noexcept + : Value(&value) + { + } + cmProp(const cmProp& other) noexcept = default; -inline const char* cmToCStr(cmProp p) + cmProp& operator=(const cmProp& other) noexcept = default; + cmProp& operator=(std::nullptr_t) noexcept + { + this->Value = nullptr; + return *this; + } + + const std::string* Get() const noexcept { return this->Value; } + const char* GetCStr() const noexcept + { + return this->Value == nullptr ? nullptr : this->Value->c_str(); + } + + const std::string* operator->() const noexcept + { + return this->Value == nullptr ? &cmProp::Empty : this->Value; + } + const std::string& operator*() const noexcept + { + return this->Value == nullptr ? cmProp::Empty : *this->Value; + } + + explicit operator bool() const noexcept { return this->Value != nullptr; } + operator const std::string&() const noexcept { return this->operator*(); } + operator cm::string_view() const noexcept { return this->operator*(); } + + /** + * Does the value indicate a true or ON value? + */ + bool IsOn() const noexcept + { + return this->Value != nullptr && + cmProp::IsOn(cm::string_view(*this->Value)); + } + /** + * Does the value indicate a false or off value ? Note that this is + * not the same as !IsOn(...) because there are a number of + * ambiguous values such as "/usr/local/bin" a path will result in + * IsOn and IsOff both returning false. Note that the special path + * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. + */ + bool IsOff() const noexcept + { + return this->Value == nullptr || + cmProp::IsOff(cm::string_view(*this->Value)); + } + /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ + bool IsNOTFOUND() const noexcept + { + return this->Value != nullptr && + cmProp::IsNOTFOUND(cm::string_view(*this->Value)); + } + bool IsEmpty() const noexcept + { + return this->Value == nullptr || this->Value->empty(); + } + + bool IsSet() const noexcept + { + return !this->IsEmpty() && !this->IsNOTFOUND(); + } + + /** + * Does a string indicate a true or ON value? + */ + static bool IsOn(const char* value) noexcept + { + return value != nullptr && IsOn(cm::string_view(value)); + } + static bool IsOn(cm::string_view) noexcept; + + /** + * Compare method has same semantic as std::optional::compare + */ + int Compare(cmProp value) const noexcept; + int Compare(cm::string_view value) const noexcept; + + /** + * Does a string indicate a false or off value ? Note that this is + * not the same as !IsOn(...) because there are a number of + * ambiguous values such as "/usr/local/bin" a path will result in + * IsOn and IsOff both returning false. Note that the special path + * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. + */ + static bool IsOff(const char* value) noexcept + { + return value == nullptr || IsOff(cm::string_view(value)); + } + static bool IsOff(cm::string_view) noexcept; + + /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ + static bool IsNOTFOUND(const char* value) noexcept + { + return value == nullptr || IsNOTFOUND(cm::string_view(value)); + } + static bool IsNOTFOUND(cm::string_view) noexcept; + + static bool IsEmpty(const char* value) noexcept + { + return value == nullptr || *value == '\0'; + } + static bool IsEmpty(cm::string_view value) noexcept { return value.empty(); } + +private: + static std::string Empty; + const std::string* Value = nullptr; +}; + +std::ostream& operator<<(std::ostream& o, cmProp v); + +inline bool operator==(cmProp l, cmProp r) noexcept +{ + return l.Compare(r) == 0; +} +inline bool operator!=(cmProp l, cmProp r) noexcept { - return p ? p->c_str() : nullptr; + return l.Compare(r) != 0; +} +inline bool operator<(cmProp l, cmProp r) noexcept +{ + return l.Compare(r) < 0; +} +inline bool operator<=(cmProp l, cmProp r) noexcept +{ + return l.Compare(r) <= 0; +} +inline bool operator>(cmProp l, cmProp r) noexcept +{ + return l.Compare(r) > 0; +} +inline bool operator>=(cmProp l, cmProp r) noexcept +{ + return l.Compare(r) >= 0; } -inline const char* cmToCStrSafe(cmProp p) +inline bool operator==(cmProp l, cm::string_view r) noexcept +{ + return l.Compare(r) == 0; +} +inline bool operator!=(cmProp l, cm::string_view r) noexcept +{ + return l.Compare(r) != 0; +} +inline bool operator<(cmProp l, cm::string_view r) noexcept +{ + return l.Compare(r) < 0; +} +inline bool operator<=(cmProp l, cm::string_view r) noexcept +{ + return l.Compare(r) <= 0; +} +inline bool operator>(cmProp l, cm::string_view r) noexcept +{ + return l.Compare(r) > 0; +} +inline bool operator>=(cmProp l, cm::string_view r) noexcept +{ + return l.Compare(r) >= 0; +} + +inline bool operator==(cmProp l, std::nullptr_t) noexcept +{ + return l.Compare(cmProp{}) == 0; +} +inline bool operator!=(cmProp l, std::nullptr_t) noexcept +{ + return l.Compare(cmProp{}) != 0; +} +inline bool operator<(cmProp l, std::nullptr_t) noexcept +{ + return l.Compare(cmProp{}) < 0; +} +inline bool operator<=(cmProp l, std::nullptr_t) noexcept +{ + return l.Compare(cmProp{}) <= 0; +} +inline bool operator>(cmProp l, std::nullptr_t) noexcept +{ + return l.Compare(cmProp{}) > 0; +} +inline bool operator>=(cmProp l, std::nullptr_t) noexcept +{ + return l.Compare(cmProp{}) >= 0; +} + +/** + * Temporary wrapper + */ +inline const char* cmToCStr(cmProp p) { - return p ? p->c_str() : ""; + return p.GetCStr(); } diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index 06e151ab6f2..3e3a44bd0bf 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -46,7 +46,7 @@ cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const { auto it = this->Map_.find(name); if (it != this->Map_.end()) { - return &it->second; + return cmProp(it->second); } return nullptr; } diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 3f3c8d501f2..f2b5cc42783 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -342,7 +342,7 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop) // if it is requested by the user. if (prop == propLANGUAGE) { // The pointer is valid until `this->Language` is modified. - return &this->GetOrDetermineLanguage(); + return cmProp(this->GetOrDetermineLanguage()); } // Special handling for GENERATED property. @@ -355,9 +355,9 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop) (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD) ? CheckScope::GlobalAndLocal : CheckScope::Global)) { - return &propTRUE; + return cmProp(propTRUE); } - return &propFALSE; + return cmProp(propFALSE); } // Perform the normal property lookup. @@ -371,7 +371,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const if (this->FullPath.empty()) { return nullptr; } - return &this->FullPath; + return cmProp(this->FullPath); } // Check for the properties with backtraces. @@ -382,7 +382,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->IncludeDirectories, ";"); - return &output; + return cmProp(output); } if (prop == propCOMPILE_OPTIONS) { @@ -392,7 +392,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->CompileOptions, ";"); - return &output; + return cmProp(output); } if (prop == propCOMPILE_DEFINITIONS) { @@ -402,7 +402,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->CompileDefinitions, ";"); - return &output; + return cmProp(output); } cmProp retVal = this->Properties.GetPropertyValue(prop); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index bdb5bda1939..bde3e2e6f93 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -603,47 +603,47 @@ cmProp cmState::GetGlobalProperty(const std::string& prop) if (prop == "CMAKE_C_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_C90_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_C99_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_C11_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_CXX_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_CXX98_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_CXX11_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_CXX14_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } if (prop == "CMAKE_CUDA_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]); - return &s_out; + return cmProp(s_out); } #undef STRING_LIST_ELEMENT diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index c898dd47517..b90cf7ecefe 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -450,17 +450,17 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const if (prop == "PARENT_DIRECTORY") { cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent(); if (parent.IsValid()) { - return &parent.GetDirectory().GetCurrentSource(); + return cmProp(parent.GetDirectory().GetCurrentSource()); } - return &output; + return cmProp(output); } if (prop == kBINARY_DIR) { output = this->GetCurrentBinary(); - return &output; + return cmProp(output); } if (prop == kSOURCE_DIR) { output = this->GetCurrentSource(); - return &output; + return cmProp(output); } if (prop == kSUBDIRECTORIES) { std::vector<std::string> child_dirs; @@ -471,15 +471,15 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const child_dirs.push_back(ci.GetDirectory().GetCurrentSource()); } output = cmJoin(child_dirs, ";"); - return &output; + return cmProp(output); } if (prop == kBUILDSYSTEM_TARGETS) { output = cmJoin(this->DirectoryState->NormalTargetNames, ";"); - return &output; + return cmProp(output); } if (prop == "IMPORTED_TARGETS"_s) { output = cmJoin(this->DirectoryState->ImportedTargetNames, ";"); - return &output; + return cmProp(output); } if (prop == "LISTFILE_STACK") { @@ -491,38 +491,38 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const } std::reverse(listFiles.begin(), listFiles.end()); output = cmJoin(listFiles, ";"); - return &output; + return cmProp(output); } if (prop == "CACHE_VARIABLES") { output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";"); - return &output; + return cmProp(output); } if (prop == "VARIABLES") { std::vector<std::string> res = this->Snapshot_.ClosureKeys(); cm::append(res, this->Snapshot_.State->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); output = cmJoin(res, ";"); - return &output; + return cmProp(output); } if (prop == "INCLUDE_DIRECTORIES") { output = cmJoin(this->GetIncludeDirectoriesEntries(), ";"); - return &output; + return cmProp(output); } if (prop == "COMPILE_OPTIONS") { output = cmJoin(this->GetCompileOptionsEntries(), ";"); - return &output; + return cmProp(output); } if (prop == "COMPILE_DEFINITIONS") { output = cmJoin(this->GetCompileDefinitionsEntries(), ";"); - return &output; + return cmProp(output); } if (prop == "LINK_OPTIONS") { output = cmJoin(this->GetLinkOptionsEntries(), ";"); - return &output; + return cmProp(output); } if (prop == "LINK_DIRECTORIES") { output = cmJoin(this->GetLinkDirectoriesEntries(), ";"); - return &output; + return cmProp(output); } cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop); diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index fbf47ef68c3..6f13d89acb5 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -201,8 +201,7 @@ bool cmStateSnapshot::HasDefinedPolicyCMP0011() return !this->Position->Policies->IsEmpty(); } -std::string const* cmStateSnapshot::GetDefinition( - std::string const& name) const +cmProp cmStateSnapshot::GetDefinition(std::string const& name) const { assert(this->Position->Vars.IsValid()); return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root); diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index d06cba37a80..a5fe7e20cc6 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -12,6 +12,7 @@ #include "cmLinkedTree.h" #include "cmPolicies.h" +#include "cmProperty.h" #include "cmStateTypes.h" class cmState; @@ -23,7 +24,7 @@ class cmStateSnapshot cmStateSnapshot(cmState* state = nullptr); cmStateSnapshot(cmState* state, cmStateDetail::PositionType position); - std::string const* GetDefinition(std::string const& name) const; + cmProp GetDefinition(std::string const& name) const; bool IsInitialized(std::string const& name) const; void SetDefinition(std::string const& name, cm::string_view value); void RemoveDefinition(std::string const& name); diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx index 5bb6e7bc578..acb5e5be5bf 100644 --- a/Source/cmStringAlgorithms.cxx +++ b/Source/cmStringAlgorithms.cxx @@ -227,76 +227,6 @@ bool cmIsInternallyOn(cm::string_view val) (val[3] == 'N' || val[3] == 'n'); } -bool cmIsNOTFOUND(cm::string_view val) -{ - return (val == "NOTFOUND") || cmHasLiteralSuffix(val, "-NOTFOUND"); -} - -bool cmIsOn(cm::string_view val) -{ - switch (val.size()) { - case 1: - return val[0] == '1' || val[0] == 'Y' || val[0] == 'y'; - case 2: - return // - (val[0] == 'O' || val[0] == 'o') && // - (val[1] == 'N' || val[1] == 'n'); - case 3: - return // - (val[0] == 'Y' || val[0] == 'y') && // - (val[1] == 'E' || val[1] == 'e') && // - (val[2] == 'S' || val[2] == 's'); - case 4: - return // - (val[0] == 'T' || val[0] == 't') && // - (val[1] == 'R' || val[1] == 'r') && // - (val[2] == 'U' || val[2] == 'u') && // - (val[3] == 'E' || val[3] == 'e'); - default: - break; - } - - return false; -} - -bool cmIsOff(cm::string_view val) -{ - switch (val.size()) { - case 0: - return true; - case 1: - return val[0] == '0' || val[0] == 'N' || val[0] == 'n'; - case 2: - return // - (val[0] == 'N' || val[0] == 'n') && // - (val[1] == 'O' || val[1] == 'o'); - case 3: - return // - (val[0] == 'O' || val[0] == 'o') && // - (val[1] == 'F' || val[1] == 'f') && // - (val[2] == 'F' || val[2] == 'f'); - case 5: - return // - (val[0] == 'F' || val[0] == 'f') && // - (val[1] == 'A' || val[1] == 'a') && // - (val[2] == 'L' || val[2] == 'l') && // - (val[3] == 'S' || val[3] == 's') && // - (val[4] == 'E' || val[4] == 'e'); - case 6: - return // - (val[0] == 'I' || val[0] == 'i') && // - (val[1] == 'G' || val[1] == 'g') && // - (val[2] == 'N' || val[2] == 'n') && // - (val[3] == 'O' || val[3] == 'o') && // - (val[4] == 'R' || val[4] == 'r') && // - (val[5] == 'E' || val[5] == 'e'); - default: - break; - } - - return cmIsNOTFOUND(val); -} - bool cmStrToLong(const char* str, long* value) { errno = 0; diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 6b458ec52cd..531678ad226 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -14,25 +14,12 @@ #include <cm/string_view> +#include "cmProperty.h" #include "cmRange.h" /** String range type. */ using cmStringRange = cmRange<std::vector<std::string>::const_iterator>; -/** Check for non-empty string. */ -inline bool cmNonempty(const char* str) -{ - return str && *str; -} -inline bool cmNonempty(cm::string_view str) -{ - return !str.empty(); -} -inline bool cmNonempty(std::string const* str) -{ - return str && !str->empty(); -} - /** Returns length of a literal string. */ template <size_t N> constexpr size_t cmStrLen(const char (&/*str*/)[N]) @@ -175,6 +162,10 @@ class cmAlphaNum cmAlphaNum(unsigned long long int val); cmAlphaNum(float val); cmAlphaNum(double val); + cmAlphaNum(cmProp value) + : View_(*value) + { + } cm::string_view View() const { return this->View_; } @@ -227,20 +218,44 @@ inline bool cmIsInternallyOn(const char* val) return cmIsInternallyOn(cm::string_view(val)); } +/** Check for non-empty Property/Variable value. */ +inline bool cmNonempty(cm::string_view val) +{ + return !cmProp::IsEmpty(val); +} +inline bool cmNonempty(const char* val) +{ + return !cmProp::IsEmpty(val); +} +inline bool cmNonempty(cmProp val) +{ + return !val.IsEmpty(); +} + /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ -bool cmIsNOTFOUND(cm::string_view val); +inline bool cmIsNOTFOUND(cm::string_view val) +{ + return cmProp::IsNOTFOUND(val); +} +inline bool cmIsNOTFOUND(cmProp val) +{ + return val.IsNOTFOUND(); +} /** * Does a string indicate a true or ON value? This is not the same as ifdef. */ -bool cmIsOn(cm::string_view val); +inline bool cmIsOn(cm::string_view val) +{ + return cmProp::IsOn(val); +} inline bool cmIsOn(const char* val) { - return val && cmIsOn(cm::string_view(val)); + return cmProp::IsOn(val); } -inline bool cmIsOn(std::string const* val) +inline bool cmIsOn(cmProp val) { - return val && cmIsOn(*val); + return val.IsOn(); } /** @@ -250,14 +265,17 @@ inline bool cmIsOn(std::string const* val) * IsON and IsOff both returning false. Note that the special path * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. */ -bool cmIsOff(cm::string_view val); +inline bool cmIsOff(cm::string_view val) +{ + return cmProp::IsOff(val); +} inline bool cmIsOff(const char* val) { - return !val || cmIsOff(cm::string_view(val)); + return cmProp::IsOff(val); } -inline bool cmIsOff(std::string const* val) +inline bool cmIsOff(cmProp val) { - return !val || cmIsOff(*val); + return val.IsOff(); } /** Returns true if string @a str starts with the character @a prefix. */ diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 70e11a2d016..656afc63ab5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -157,7 +157,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>( } static std::string srcs; srcs = ss.str(); - return &srcs; + return cmProp(srcs); } class cmTargetInternals @@ -1749,7 +1749,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const if (propertyIter == this->impl->LanguageStandardProperties.end()) { return nullptr; } - return &(propertyIter->second.Value); + return cmProp(propertyIter->second.Value); } if (prop == propLINK_LIBRARIES) { if (this->impl->LinkImplementationPropertyEntries.empty()) { @@ -1758,11 +1758,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";"); - return &output; + return cmProp(output); } // the type property returns what type the target is if (prop == propTYPE) { - return &cmState::GetTargetTypeName(this->GetType()); + return cmProp(cmState::GetTargetTypeName(this->GetType())); } if (prop == propINCLUDE_DIRECTORIES) { if (this->impl->IncludeDirectoriesEntries.empty()) { @@ -1771,7 +1771,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->IncludeDirectoriesEntries, ";"); - return &output; + return cmProp(output); } if (prop == propCOMPILE_FEATURES) { if (this->impl->CompileFeaturesEntries.empty()) { @@ -1780,7 +1780,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->CompileFeaturesEntries, ";"); - return &output; + return cmProp(output); } if (prop == propCOMPILE_OPTIONS) { if (this->impl->CompileOptionsEntries.empty()) { @@ -1789,7 +1789,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->CompileOptionsEntries, ";"); - return &output; + return cmProp(output); } if (prop == propCOMPILE_DEFINITIONS) { if (this->impl->CompileDefinitionsEntries.empty()) { @@ -1798,7 +1798,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->CompileDefinitionsEntries, ";"); - return &output; + return cmProp(output); } if (prop == propLINK_OPTIONS) { if (this->impl->LinkOptionsEntries.empty()) { @@ -1807,7 +1807,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->LinkOptionsEntries, ";"); - return &output; + return cmProp(output); } if (prop == propLINK_DIRECTORIES) { if (this->impl->LinkDirectoriesEntries.empty()) { @@ -1817,7 +1817,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->LinkDirectoriesEntries, ";"); - return &output; + return cmProp(output); } if (prop == propMANUALLY_ADDED_DEPENDENCIES) { if (this->impl->Utilities.empty()) { @@ -1834,7 +1834,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const return item.Value.first; }); output = cmJoin(utilities, ";"); - return &output; + return cmProp(output); } if (prop == propPRECOMPILE_HEADERS) { if (this->impl->PrecompileHeadersEntries.empty()) { @@ -1843,26 +1843,27 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->PrecompileHeadersEntries, ";"); - return &output; + return cmProp(output); } if (prop == propIMPORTED) { - return this->IsImported() ? &propTRUE : &propFALSE; + return this->IsImported() ? cmProp(propTRUE) : cmProp(propFALSE); } if (prop == propIMPORTED_GLOBAL) { - return this->IsImportedGloballyVisible() ? &propTRUE : &propFALSE; + return this->IsImportedGloballyVisible() ? cmProp(propTRUE) + : cmProp(propFALSE); } if (prop == propNAME) { - return &this->GetName(); + return cmProp(this->GetName()); } if (prop == propBINARY_DIR) { - return &this->impl->Makefile->GetStateSnapshot() - .GetDirectory() - .GetCurrentBinary(); + return cmProp(this->impl->Makefile->GetStateSnapshot() + .GetDirectory() + .GetCurrentBinary()); } if (prop == propSOURCE_DIR) { - return &this->impl->Makefile->GetStateSnapshot() - .GetDirectory() - .GetCurrentSource(); + return cmProp(this->impl->Makefile->GetStateSnapshot() + .GetDirectory() + .GetCurrentSource()); } } diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index f2be318b81c..a749b537e8b 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -65,7 +65,7 @@ class cmTargetPropertyComputer context)) { return nullptr; } - return &ComputeLocationForBuild(tgt); + return cmProp(ComputeLocationForBuild(tgt)); } // Support "LOCATION_<CONFIG>". @@ -76,7 +76,7 @@ class cmTargetPropertyComputer return nullptr; } std::string configName = prop.substr(9); - return &ComputeLocation(tgt, configName); + return cmProp(ComputeLocation(tgt, configName)); } // Support "<CONFIG>_LOCATION". @@ -89,7 +89,7 @@ class cmTargetPropertyComputer context)) { return nullptr; } - return &ComputeLocation(tgt, configName); + return cmProp(ComputeLocation(tgt, configName)); } } } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 065601b791f..03d1bbbc6d4 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -490,10 +490,7 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("Platform", this->Platform); cmProp projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL"); - if (!projLabel) { - projLabel = &this->Name; - } - e1.Element("ProjectName", *projLabel); + e1.Element("ProjectName", projLabel ? projLabel : this->Name); { cmProp targetFramework = this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK"); diff --git a/bootstrap b/bootstrap index 4ef0fe551f9..d0329fbf706 100755 --- a/bootstrap +++ b/bootstrap @@ -426,6 +426,7 @@ CMAKE_CXX_SOURCES="\ cmPolicies \ cmProcessOutput \ cmProjectCommand \ + cmProperty \ cmPropertyDefinition \ cmPropertyMap \ cmGccDepfileLexerHelper \ From b7d45677691cda2defdccd9272e595973f766162 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 8 Aug 2021 15:04:23 +1000 Subject: [PATCH 1093/1519] Help: Clarify find_package() component handling Fixes: #22513 --- Help/command/find_package.rst | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 7febd5d0a55..bd2601007e6 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -28,11 +28,26 @@ that the package cannot be found if it is not ``REQUIRED``. The ``REQUIRED`` option stops processing with an error message if the package cannot be found. A package-specific list of required components may be listed after the -``COMPONENTS`` option (or after the ``REQUIRED`` option if present). +``COMPONENTS`` keyword. If any of these components are not able to be +satisfied, the package overall is considered to be not found. If the +``REQUIRED`` option is also present, this is treated as a fatal error, +otherwise execution still continues. As a form of shorthand, if the +``REQUIRED`` option is present, the ``COMPONENTS`` keyword can be omitted +and the required components can be listed directly after ``REQUIRED``. + Additional optional components may be listed after -``OPTIONAL_COMPONENTS``. Available components and their influence on -whether a package is considered to be found are defined by the target -package. +``OPTIONAL_COMPONENTS``. If these cannot be satisfied, the package overall +can still be considered found, as long as all required components are +satisfied. + +The set of available components and their meaning are defined by the +target package. Formally, it is up to the target package how to +interpret the component information given to it, but it should follow +the expectations stated above. For calls where no components are specified, +there is no single expected behavior and target packages should clearly +define what occurs in such cases. Common arrangements include assuming it +should find all components, no components or some well-defined subset of the +available components. .. _FIND_PACKAGE_VERSION_FORMAT: @@ -486,7 +501,7 @@ restores their original state before returning): ``<PackageName>_FIND_VERSION_EXACT`` True if ``EXACT`` option was given ``<PackageName>_FIND_COMPONENTS`` - List of requested components + List of specified components (required and optional) ``<PackageName>_FIND_REQUIRED_<c>`` True if component ``<c>`` is required, false if component ``<c>`` is optional From ec686f4c8a875f85e44491f7e4387e0fa201a0cc Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 9 Aug 2021 00:01:33 -0400 Subject: [PATCH 1094/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 001ac78c031..d53fb1d5f8e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210808) +set(CMake_VERSION_PATCH 20210809) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From fc1f733cc7b312cd156b4d2aa6e8190e7def33b9 Mon Sep 17 00:00:00 2001 From: Cristian Adam <cristian.adam@gmail.com> Date: Sat, 7 Aug 2021 14:12:22 +0200 Subject: [PATCH 1095/1519] BinUtils: Avoid searching CMAKE_PREFIX_PATH Our `find_program` calls specify `HINTS` to look in the toolchain's directory first, and then in `PATH`. `CMAKE_PREFIX_PATH` may be specified by the user to help find packages for project dependencies, but this should not override the binutils. Fixes: #22512 --- Modules/CMakeFindBinUtils.cmake | 6 +++--- Modules/Compiler/Clang-FindBinUtils.cmake | 2 ++ Modules/Compiler/GNU-FindBinUtils.cmake | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index f139ff48267..d0beac61437 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -33,7 +33,7 @@ function(__resolve_tool_path CMAKE_TOOL SEARCH_PATH DOCSTRING) 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}) + find_program(_CMAKE_TOOL_WITH_PATH 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. @@ -202,7 +202,7 @@ foreach(_CMAKE_TOOL IN LISTS _CMAKE_TOOL_VARS) endforeach() list(REMOVE_DUPLICATES _CMAKE_${_CMAKE_TOOL}_FIND_NAMES) - find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_FIND_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_${_CMAKE_TOOL} NAMES ${_CMAKE_${_CMAKE_TOOL}_FIND_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH) unset(_CMAKE_${_CMAKE_TOOL}_FIND_NAMES) endforeach() @@ -212,7 +212,7 @@ endif() if(CMAKE_PLATFORM_HAS_INSTALLNAME) - find_program(CMAKE_INSTALL_NAME_TOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}install_name_tool HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_INSTALL_NAME_TOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}install_name_tool HINTS ${_CMAKE_TOOLCHAIN_LOCATION} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH) if(NOT CMAKE_INSTALL_NAME_TOOL) message(FATAL_ERROR "Could not find install_name_tool, please check your installation.") diff --git a/Modules/Compiler/Clang-FindBinUtils.cmake b/Modules/Compiler/Clang-FindBinUtils.cmake index e6c469a10e9..125ae7884fb 100644 --- a/Modules/Compiler/Clang-FindBinUtils.cmake +++ b/Modules/Compiler/Clang-FindBinUtils.cmake @@ -28,6 +28,7 @@ find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x}" "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar" HINTS ${__clang_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH DOC "LLVM archiver" ) mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) @@ -38,6 +39,7 @@ find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x}" "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib" HINTS ${__clang_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH DOC "Generate index for LLVM archive" ) mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB) diff --git a/Modules/Compiler/GNU-FindBinUtils.cmake b/Modules/Compiler/GNU-FindBinUtils.cmake index 097fbf3ac97..4dcdd5377e7 100644 --- a/Modules/Compiler/GNU-FindBinUtils.cmake +++ b/Modules/Compiler/GNU-FindBinUtils.cmake @@ -20,6 +20,7 @@ find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x}" "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar${_CMAKE_COMPILER_SUFFIX}" HINTS ${__gcc_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler" ) mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) @@ -30,6 +31,7 @@ find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x}" "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib${_CMAKE_COMPILER_SUFFIX}" HINTS ${__gcc_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler" ) mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB) From 97ed474431426a50e6080a1cef8098fce297a940 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 9 Aug 2021 16:37:14 +0200 Subject: [PATCH 1096/1519] Refactor: cmTest::GetProperty returns cmProp --- Source/cmGetPropertyCommand.cxx | 19 +++++++++++-------- Source/cmGetTestPropertyCommand.cxx | 5 +++-- Source/cmTest.cxx | 6 +++--- Source/cmTest.h | 3 ++- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index cb657f9ee03..bb3a40bac6e 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -268,6 +268,11 @@ bool StoreResult(OutType infoType, cmMakefile& makefile, } return true; } +bool StoreResult(OutType infoType, cmMakefile& makefile, + const std::string& variable, cmProp value) +{ + return StoreResult(infoType, makefile, variable, value.GetCStr()); +} bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, OutType infoType, const std::string& variable, @@ -280,9 +285,8 @@ bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, // Get the property. cmake* cm = status.GetMakefile().GetCMakeInstance(); - return StoreResult( - infoType, status.GetMakefile(), variable, - cmToCStr(cm->GetState()->GetGlobalProperty(propertyName))); + return StoreResult(infoType, status.GetMakefile(), variable, + cm->GetState()->GetGlobalProperty(propertyName)); } bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, @@ -329,7 +333,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, // Get the property. return StoreResult(infoType, status.GetMakefile(), variable, - cmToCStr(mf->GetProperty(propertyName))); + mf->GetProperty(propertyName)); } bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, @@ -365,8 +369,7 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, if (!prop) { prop = target->GetProperty(propertyName); } - return StoreResult(infoType, status.GetMakefile(), variable, - cmToCStr(prop)); + return StoreResult(infoType, status.GetMakefile(), variable, prop); } status.SetError(cmStrCat("could not find TARGET ", name, ". Perhaps it has not yet been created.")); @@ -391,7 +394,7 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, if (cmSourceFile* sf = directory_makefile.GetOrCreateSource(source_file_absolute_path)) { return StoreResult(infoType, status.GetMakefile(), variable, - cmToCStr(sf->GetPropertyForUser(propertyName))); + sf->GetPropertyForUser(propertyName)); } status.SetError( cmStrCat("given SOURCE name that could not be found or created: ", @@ -447,7 +450,7 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, value = status.GetMakefile().GetState()->GetCacheEntryProperty( name, propertyName); } - StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(value)); + StoreResult(infoType, status.GetMakefile(), variable, value); return true; } diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx index cf8c1d5faa3..077353e3f09 100644 --- a/Source/cmGetTestPropertyCommand.cxx +++ b/Source/cmGetTestPropertyCommand.cxx @@ -4,6 +4,7 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmTest.h" bool cmGetTestPropertyCommand(std::vector<std::string> const& args, @@ -19,12 +20,12 @@ bool cmGetTestPropertyCommand(std::vector<std::string> const& args, cmMakefile& mf = status.GetMakefile(); cmTest* test = mf.GetTest(testName); if (test) { - const char* prop = nullptr; + cmProp prop; if (!args[1].empty()) { prop = test->GetProperty(args[1]); } if (prop) { - mf.AddDefinition(var, prop); + mf.AddDefinition(var, prop->c_str()); return true; } } diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index a26bef3dbc7..5bc10c22ce5 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -32,7 +32,7 @@ void cmTest::SetCommand(std::vector<std::string> const& command) this->Command = command; } -const char* cmTest::GetProperty(const std::string& prop) const +cmProp cmTest::GetProperty(const std::string& prop) const { cmProp retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { @@ -40,12 +40,12 @@ const char* cmTest::GetProperty(const std::string& prop) const this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST); if (chain) { if (cmProp p = this->Makefile->GetProperty(prop, chain)) { - return p->c_str(); + return p; } } return nullptr; } - return retVal->c_str(); + return retVal; } bool cmTest::GetPropertyAsBool(const std::string& prop) const diff --git a/Source/cmTest.h b/Source/cmTest.h index f33b7e286d0..63e5e8782da 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -8,6 +8,7 @@ #include <vector> #include "cmListFileCache.h" +#include "cmProperty.h" #include "cmPropertyMap.h" class cmMakefile; @@ -36,7 +37,7 @@ class cmTest void SetProperty(const std::string& prop, const char* value); void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); - const char* GetProperty(const std::string& prop) const; + cmProp GetProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; cmPropertyMap& GetProperties() { return this->Properties; } From e5421168143dda5f72088a6ff451785ec137e8c4 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 9 Aug 2021 16:56:41 +0200 Subject: [PATCH 1097/1519] Refactor: cmGeneratorTarget::GetSourcesProperty returns cmProp --- Source/cmGeneratorTarget.cxx | 6 +++--- Source/cmGeneratorTarget.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6bd41bd560b..42086894b96 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -62,7 +62,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, cmListFileBacktrace const& /* context */) { - return cmProp(tgt->GetSourcesProperty()); + return tgt->GetSourcesProperty(); } template <> @@ -332,7 +332,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) cmGeneratorTarget::~cmGeneratorTarget() = default; -const std::string& cmGeneratorTarget::GetSourcesProperty() const +cmProp cmGeneratorTarget::GetSourcesProperty() const { std::vector<std::string> values; for (auto const& se : this->SourceEntries) { @@ -341,7 +341,7 @@ const std::string& cmGeneratorTarget::GetSourcesProperty() const static std::string value; value.clear(); value = cmJoin(values, ";"); - return value; + return cmProp(value); } cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index bd4e08fc59f..fb1b2e62074 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -837,7 +837,7 @@ class cmGeneratorTarget std::string GetFortranModuleDirectory(std::string const& working_dir) const; bool IsFortranBuildingInstrinsicModules() const; - const std::string& GetSourcesProperty() const; + cmProp GetSourcesProperty() const; void AddISPCGeneratedHeader(std::string const& header, std::string const& config); From 791337f18124d745dd08a8f141cc258656dc052b Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 9 Aug 2021 17:28:31 +0200 Subject: [PATCH 1098/1519] Refactor: cmCommonTargetGenerator::GetFeature returns cmProp --- Source/cmCommonTargetGenerator.cxx | 6 +++--- Source/cmCommonTargetGenerator.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 7c2e20c0164..59e41419e55 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -39,10 +39,10 @@ std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const return this->ConfigNames; } -const char* cmCommonTargetGenerator::GetFeature(const std::string& feature, - const std::string& config) +cmProp cmCommonTargetGenerator::GetFeature(const std::string& feature, + const std::string& config) { - return this->GeneratorTarget->GetFeature(feature, config)->c_str(); + return this->GeneratorTarget->GetFeature(feature, config); } void cmCommonTargetGenerator::AddModuleDefinitionFlag( diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index e1a4f8bb5bf..463a445a275 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cmProperty.h" + class cmGeneratorTarget; class cmGlobalCommonGenerator; class cmLinkLineComputer; @@ -28,8 +30,7 @@ class cmCommonTargetGenerator protected: // Feature query methods. - const char* GetFeature(const std::string& feature, - const std::string& config); + cmProp GetFeature(const std::string& feature, const std::string& config); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, From 3941b74de4043a1a8a173a61c4f5efe0a8a55d33 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 9 Aug 2021 18:52:35 +0200 Subject: [PATCH 1099/1519] Refactor: cmGlobalGenerator::GetGlobalSetting returns cmProp --- Source/cmGlobalGenerator.cxx | 6 +++--- Source/cmGlobalGenerator.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index aae6e35bda2..3561deb8800 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1179,10 +1179,10 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, } } -const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const +cmProp cmGlobalGenerator::GetGlobalSetting(std::string const& name) const { assert(!this->Makefiles.empty()); - return cmToCStr(this->Makefiles[0]->GetDefinition(name)); + return this->Makefiles[0]->GetDefinition(name); } bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const @@ -1195,7 +1195,7 @@ std::string cmGlobalGenerator::GetSafeGlobalSetting( std::string const& name) const { assert(!this->Makefiles.empty()); - return this->Makefiles[0]->GetSafeDefinition(name); + return this->Makefiles[0]->GetDefinition(name); } bool cmGlobalGenerator::IgnoreFile(const char* ext) const diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index f0b59bf25df..34646d9f969 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -23,6 +23,7 @@ #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmExportSet.h" +#include "cmProperty.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -308,7 +309,7 @@ class cmGlobalGenerator cmExportSetMap& GetExportSets() { return this->ExportSets; } - const char* GetGlobalSetting(std::string const& name) const; + cmProp GetGlobalSetting(std::string const& name) const; bool GlobalSettingIsOn(std::string const& name) const; std::string GetSafeGlobalSetting(std::string const& name) const; From 61b33c3f4eae3ce81df36c79ec69630cd9fcefdc Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 9 Aug 2021 20:35:56 +0300 Subject: [PATCH 1100/1519] Fix: Regression in the `cmConditionEvaluator::HandleLevel0` As reported in the BUG #22524, mismatched parenthesis reported differently for `while()` and `if()`. The problem was in the double loop (over "handlers" and the arguments), where the outer loop didn't check the result of the running handler. --- Source/cmConditionEvaluator.cxx | 8 +++++++- Tests/RunCMake/if/RunCMakeTest.cmake | 2 ++ Tests/RunCMake/if/unbalanced-parenthesis-result.txt | 1 + Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt | 8 ++++++++ Tests/RunCMake/if/unbalanced-parenthesis.cmake | 8 ++++++++ Tests/RunCMake/while/RunCMakeTest.cmake | 2 ++ Tests/RunCMake/while/unbalanced-parenthesis.cmake | 8 ++++++++ 7 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/if/unbalanced-parenthesis-result.txt create mode 100644 Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt create mode 100644 Tests/RunCMake/if/unbalanced-parenthesis.cmake create mode 100644 Tests/RunCMake/while/unbalanced-parenthesis.cmake diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 49189d8b1e0..68bc4d81fe5 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -260,11 +260,17 @@ bool cmConditionEvaluator::IsTrue( for (auto fn : handlers) { // Call the reducer 'till there is anything to reduce... // (i.e., if after an iteration the size becomes smaller) + auto levelResult = true; for (auto beginSize = newArgs.size(); - (this->*fn)(newArgs, errorString, status) && + (levelResult = (this->*fn)(newArgs, errorString, status)) && newArgs.size() < beginSize; beginSize = newArgs.size()) { } + + if (!levelResult) { + // NOTE `errorString` supposed to be set already + return false; + } } // now at the end there should only be one argument left diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake index 239c167139f..6baa8405928 100644 --- a/Tests/RunCMake/if/RunCMakeTest.cmake +++ b/Tests/RunCMake/if/RunCMakeTest.cmake @@ -9,6 +9,8 @@ run_cmake(duplicate-else-after-elseif) run_cmake(elseif-message) run_cmake(misplaced-elseif) +run_cmake(unbalanced-parenthesis) + run_cmake(MatchesSelf) run_cmake(IncompleteMatches) run_cmake(IncompleteMatchesFail) diff --git a/Tests/RunCMake/if/unbalanced-parenthesis-result.txt b/Tests/RunCMake/if/unbalanced-parenthesis-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/if/unbalanced-parenthesis-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt b/Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt new file mode 100644 index 00000000000..770ccb8f187 --- /dev/null +++ b/Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at unbalanced-parenthesis\.cmake:[0-9]+ \(if\): + if given arguments: + + "NOT" "\(" "IN_LIST" "some_list" + + mismatched parenthesis in condition +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/if/unbalanced-parenthesis.cmake b/Tests/RunCMake/if/unbalanced-parenthesis.cmake new file mode 100644 index 00000000000..c51c7557f80 --- /dev/null +++ b/Tests/RunCMake/if/unbalanced-parenthesis.cmake @@ -0,0 +1,8 @@ +set(var_with_paren "(") +set(some_list "") + +if(NOT ${var_with_paren} IN_LIST some_list) + message(STATUS "Never prints") +else() + message(STATUS "Never prints") +endif() diff --git a/Tests/RunCMake/while/RunCMakeTest.cmake b/Tests/RunCMake/while/RunCMakeTest.cmake index 7da80ace308..bb9b9910140 100644 --- a/Tests/RunCMake/while/RunCMakeTest.cmake +++ b/Tests/RunCMake/while/RunCMakeTest.cmake @@ -5,3 +5,5 @@ run_cmake(EndMissing) run_cmake(EndMismatch) run_cmake(EndAlone) run_cmake(EndAloneArgs) + +run_cmake(unbalanced-parenthesis) diff --git a/Tests/RunCMake/while/unbalanced-parenthesis.cmake b/Tests/RunCMake/while/unbalanced-parenthesis.cmake new file mode 100644 index 00000000000..4b6a5cdda1a --- /dev/null +++ b/Tests/RunCMake/while/unbalanced-parenthesis.cmake @@ -0,0 +1,8 @@ +set(var_with_paren "(") +set(some_list "") + +while(NOT ${var_with_paren} IN_LIST some_list) + message(STATUS "Never prints") +endwhile() + +message(STATUS "It prints but in fact `while()` have to fail") From 880ca66b51551d5ee732c7b81349c1a5f724d093 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 9 Aug 2021 20:58:27 +0300 Subject: [PATCH 1101/1519] Fix: `while()` can silently ignore incorrect condition When `conditionEvaluator.IsTrue(...)` returns `false` it just didn't print the error occured. --- Source/cmWhileCommand.cxx | 36 +++++++++---------- .../while/unbalanced-parenthesis-result.txt | 1 + .../while/unbalanced-parenthesis-stderr.txt | 5 +++ .../while/unbalanced-parenthesis.cmake | 2 +- 4 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 Tests/RunCMake/while/unbalanced-parenthesis-result.txt create mode 100644 Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 327c1c7bafa..13633860522 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -75,24 +75,6 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); while (isTrue) { - if (!errorString.empty()) { - std::string err = "had incorrect arguments: "; - for (cmListFileArgument const& arg : this->Args) { - err += (arg.Delim ? "\"" : ""); - err += arg.Value; - err += (arg.Delim ? "\"" : ""); - err += " "; - } - err += "("; - err += errorString; - err += ")."; - mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT); - if (messageType == MessageType::FATAL_ERROR) { - cmSystemTools::SetFatalErrorOccured(); - return true; - } - } - // Invoke all the functions that were collected in the block. for (cmListFileFunction const& fn : functions) { cmExecutionStatus status(mf); @@ -116,6 +98,24 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); } + + if (!isTrue && !errorString.empty()) { + std::string err = "had incorrect arguments: "; + for (cmListFileArgument const& arg : this->Args) { + err += (arg.Delim ? "\"" : ""); + err += arg.Value; + err += (arg.Delim ? "\"" : ""); + err += " "; + } + err += "("; + err += errorString; + err += ")."; + mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT); + if (messageType == MessageType::FATAL_ERROR) { + cmSystemTools::SetFatalErrorOccured(); + } + } + return true; } diff --git a/Tests/RunCMake/while/unbalanced-parenthesis-result.txt b/Tests/RunCMake/while/unbalanced-parenthesis-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/while/unbalanced-parenthesis-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt b/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt new file mode 100644 index 00000000000..33ac54aac79 --- /dev/null +++ b/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at unbalanced-parenthesis.cmake:[0-9]+ \(while\): + had incorrect arguments: NOT \$\{var_with_paren\} IN_LIST some_list + \(mismatched parenthesis in condition\). +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/while/unbalanced-parenthesis.cmake b/Tests/RunCMake/while/unbalanced-parenthesis.cmake index 4b6a5cdda1a..7a12701e6c3 100644 --- a/Tests/RunCMake/while/unbalanced-parenthesis.cmake +++ b/Tests/RunCMake/while/unbalanced-parenthesis.cmake @@ -5,4 +5,4 @@ while(NOT ${var_with_paren} IN_LIST some_list) message(STATUS "Never prints") endwhile() -message(STATUS "It prints but in fact `while()` have to fail") +message(STATUS "Never prints") From e97e714f0d59809fcefdc94feaadedb319d252c6 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 9 Aug 2021 21:48:24 +0300 Subject: [PATCH 1102/1519] Fix: `while()` reports an error the same way as `if()` With arguments list expanded. --- Source/cmWhileCommand.cxx | 12 +++++------- .../RunCMake/while/unbalanced-parenthesis-stderr.txt | 7 +++++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 13633860522..89386635bac 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -16,6 +16,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmOutputConverter.h" #include "cmSystemTools.h" #include "cmake.h" @@ -100,16 +101,13 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, } if (!isTrue && !errorString.empty()) { - std::string err = "had incorrect arguments: "; - for (cmListFileArgument const& arg : this->Args) { - err += (arg.Delim ? "\"" : ""); - err += arg.Value; - err += (arg.Delim ? "\"" : ""); + std::string err = "had incorrect arguments:\n "; + for (cmExpandedCommandArgument const& i : expandedArguments) { err += " "; + err += cmOutputConverter::EscapeForCMake(i.GetValue()); } - err += "("; + err += "\n"; err += errorString; - err += ")."; mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT); if (messageType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); diff --git a/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt b/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt index 33ac54aac79..9d4132c5a34 100644 --- a/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt +++ b/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt @@ -1,5 +1,8 @@ CMake Error at unbalanced-parenthesis.cmake:[0-9]+ \(while\): - had incorrect arguments: NOT \$\{var_with_paren\} IN_LIST some_list - \(mismatched parenthesis in condition\). + had incorrect arguments: + + "NOT" "\(" "IN_LIST" "some_list" + + mismatched parenthesis in condition Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) From 438005a6e0a4a9c82b06395d1dc4792f24cb8c32 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 10 Aug 2021 00:01:15 -0400 Subject: [PATCH 1103/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d53fb1d5f8e..1cb8bc6f076 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210809) +set(CMake_VERSION_PATCH 20210810) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3f9ef3703aff5879f56d7e77c0d301f4acd15ca5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 10 Aug 2021 10:37:57 -0400 Subject: [PATCH 1104/1519] VS: Fix /reference and /headerUnit flag table entries for v142 and v143 These flags accept values in following arguments, not immediately appended. Fixes: #22530 --- Templates/MSBuild/FlagTables/v142_CL.json | 4 ++-- Templates/MSBuild/FlagTables/v143_CL.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Templates/MSBuild/FlagTables/v142_CL.json b/Templates/MSBuild/FlagTables/v142_CL.json index 64eeac4ab3f..4c65ad9bd77 100644 --- a/Templates/MSBuild/FlagTables/v142_CL.json +++ b/Templates/MSBuild/FlagTables/v142_CL.json @@ -1214,7 +1214,7 @@ "comment": "Additional Module Dependencies", "value": "", "flags": [ - "UserValue", + "UserFollowing", "SemicolonAppendable" ] }, @@ -1224,7 +1224,7 @@ "comment": "Additional Header Unit Dependencies", "value": "", "flags": [ - "UserValue", + "UserFollowing", "SemicolonAppendable" ] }, diff --git a/Templates/MSBuild/FlagTables/v143_CL.json b/Templates/MSBuild/FlagTables/v143_CL.json index 8b700aafb3e..96f74b1f2b5 100644 --- a/Templates/MSBuild/FlagTables/v143_CL.json +++ b/Templates/MSBuild/FlagTables/v143_CL.json @@ -1214,7 +1214,7 @@ "comment": "Additional Module Dependencies", "value": "", "flags": [ - "UserValue", + "UserFollowing", "SemicolonAppendable" ] }, @@ -1224,7 +1224,7 @@ "comment": "Additional Header Unit Dependencies", "value": "", "flags": [ - "UserValue", + "UserFollowing", "SemicolonAppendable" ] }, From e0c40018b337457db8c127724b9c7e9726649949 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 11 Aug 2021 00:01:14 -0400 Subject: [PATCH 1105/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1cb8bc6f076..ed32434e124 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210810) +set(CMake_VERSION_PATCH 20210811) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d22f68d01998ff3cbbdebaec2f1071148b82d588 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 10 Aug 2021 00:41:55 +0300 Subject: [PATCH 1106/1519] Refactor: Transform `while` loop into `for` And reduce scope for some variables + use some more `auto`. --- Source/cmWhileCommand.cxx | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 89386635bac..1285baf3b6e 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -61,21 +61,31 @@ bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) { - cmMakefile& mf = inStatus.GetMakefile(); - std::string errorString; - - std::vector<cmExpandedCommandArgument> expandedArguments; - mf.ExpandArguments(this->Args, expandedArguments); - MessageType messageType; + auto& mf = inStatus.GetMakefile(); cmListFileBacktrace whileBT = mf.GetBacktrace().Push(this->GetStartingContext()); - cmConditionEvaluator conditionEvaluator(mf, whileBT); - bool isTrue = - conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); + std::vector<cmExpandedCommandArgument> expandedArguments; + // At least same size expected for `expandedArguments` as `Args` + expandedArguments.reserve(this->Args.size()); + + auto expandArgs = [&mf](std::vector<cmListFileArgument> const& args, + std::vector<cmExpandedCommandArgument>& out) + -> std::vector<cmExpandedCommandArgument>& { + out.clear(); + mf.ExpandArguments(args, out); + return out; + }; + + std::string errorString; + MessageType messageType; + auto isTrue = true; - while (isTrue) { + for (cmConditionEvaluator conditionEvaluator(mf, whileBT); + (isTrue = + conditionEvaluator.IsTrue(expandArgs(this->Args, expandedArguments), + errorString, messageType));) { // Invoke all the functions that were collected in the block. for (cmListFileFunction const& fn : functions) { cmExecutionStatus status(mf); @@ -94,15 +104,11 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, return true; } } - expandedArguments.clear(); - mf.ExpandArguments(this->Args, expandedArguments); - isTrue = - conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); } if (!isTrue && !errorString.empty()) { std::string err = "had incorrect arguments:\n "; - for (cmExpandedCommandArgument const& i : expandedArguments) { + for (auto const& i : expandedArguments) { err += " "; err += cmOutputConverter::EscapeForCMake(i.GetValue()); } @@ -127,7 +133,7 @@ bool cmWhileCommand(std::vector<cmListFileArgument> const& args, // create a function blocker { - cmMakefile& makefile = status.GetMakefile(); + auto& makefile = status.GetMakefile(); auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile); fb->Args = args; makefile.AddFunctionBlocker(std::move(fb)); From 4c1cdfd8f09182d8a6c87772b7fc0946c691e18b Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 10 Aug 2021 01:04:32 +0300 Subject: [PATCH 1107/1519] Refactor: Keep `cmWhileFunctionBlocker` members private Particularly `Args`. --- Source/cmWhileCommand.cxx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 1285baf3b6e..7d9eec0ff87 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -23,7 +23,7 @@ class cmWhileFunctionBlocker : public cmFunctionBlocker { public: - cmWhileFunctionBlocker(cmMakefile* mf); + cmWhileFunctionBlocker(cmMakefile* mf, std::vector<cmListFileArgument> args); ~cmWhileFunctionBlocker() override; cm::string_view StartCommandName() const override { return "while"_s; } @@ -35,14 +35,15 @@ class cmWhileFunctionBlocker : public cmFunctionBlocker bool Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) override; - std::vector<cmListFileArgument> Args; - private: cmMakefile* Makefile; + std::vector<cmListFileArgument> Args; }; -cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf) - : Makefile(mf) +cmWhileFunctionBlocker::cmWhileFunctionBlocker( + cmMakefile* const mf, std::vector<cmListFileArgument> args) + : Makefile{ mf } + , Args{ std::move(args) } { this->Makefile->PushLoopBlock(); } @@ -132,11 +133,9 @@ bool cmWhileCommand(std::vector<cmListFileArgument> const& args, } // create a function blocker - { - auto& makefile = status.GetMakefile(); - auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile); - fb->Args = args; - makefile.AddFunctionBlocker(std::move(fb)); - } + auto& makefile = status.GetMakefile(); + makefile.AddFunctionBlocker( + cm::make_unique<cmWhileFunctionBlocker>(&makefile, args)); + return true; } From eae125ace54bd82ed5be14cfee50f41a07b10619 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 10 Aug 2021 01:19:56 +0300 Subject: [PATCH 1108/1519] Refactor: Get rid of `isTrue` variable in the `while` block execution --- Source/cmWhileCommand.cxx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 7d9eec0ff87..b8297ce2125 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -81,12 +81,10 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, std::string errorString; MessageType messageType; - auto isTrue = true; for (cmConditionEvaluator conditionEvaluator(mf, whileBT); - (isTrue = - conditionEvaluator.IsTrue(expandArgs(this->Args, expandedArguments), - errorString, messageType));) { + conditionEvaluator.IsTrue(expandArgs(this->Args, expandedArguments), + errorString, messageType);) { // Invoke all the functions that were collected in the block. for (cmListFileFunction const& fn : functions) { cmExecutionStatus status(mf); @@ -107,7 +105,7 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, } } - if (!isTrue && !errorString.empty()) { + if (!errorString.empty()) { std::string err = "had incorrect arguments:\n "; for (auto const& i : expandedArguments) { err += " "; From 8fddc2bb2fe3d3e7debc32f1e6f8f6e376a303b8 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Wed, 11 Aug 2021 13:39:44 -0400 Subject: [PATCH 1109/1519] Help: refer to CheckSourceCompiles instead of older --- Modules/CheckCXXSymbolExists.cmake | 2 +- Modules/CheckSymbolExists.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake index b4da4fac88d..7b13c3aa342 100644 --- a/Modules/CheckCXXSymbolExists.cmake +++ b/Modules/CheckCXXSymbolExists.cmake @@ -25,7 +25,7 @@ Check if a symbol exists as a function, variable, or macro in ``C++``. as a function or variable then the symbol must also be available for linking. If the symbol is a type, enum value, or C++ template it will not be recognized: consider using the :module:`CheckTypeSize` - or :module:`CheckCXXSourceCompiles` module instead. + or :module:`CheckSourceCompiles` module instead. .. note:: diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index f8ca584026f..48ee3c47794 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -24,7 +24,7 @@ available and assumed to work. If the header files declare the symbol as a function or variable then the symbol must also be available for linking (so intrinsics may not be detected). If the symbol is a type, enum value, or intrinsic it will not be recognized -(consider using :module:`CheckTypeSize` or :module:`CheckCSourceCompiles`). +(consider using :module:`CheckTypeSize` or :module:`CheckSourceCompiles`). If the check needs to be done in C++, consider using :module:`CheckCXXSymbolExists` instead. From d62d0f048fdb073bab6bdb9b0055d97d0f9c8569 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Wed, 11 Aug 2021 13:40:14 -0400 Subject: [PATCH 1110/1519] Help: CheckFortranFunctionExists: recommend more general CheckSourceCompiles CheckFortranFunctionExists is really only relevant to Fortran 77 code. Fortran 90 and newer users should use CheckSourceCompiles instead. --- Modules/CheckFortranFunctionExists.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake index ad72e2f09e1..8f1ca9dd33a 100644 --- a/Modules/CheckFortranFunctionExists.cmake +++ b/Modules/CheckFortranFunctionExists.cmake @@ -20,6 +20,12 @@ Check if a Fortran function exists. ``<result>`` variable to store the result; will be created as an internal cache variable. +.. note:: + + This command does not detect functions in Fortran modules. In general it is + recommended to use :module:`CheckSourceCompiles` instead to determine if a + Fortran function or subroutine is available. + The following variables may be set before calling this macro to modify the way the check is run: From 3fc3b43933d0b486aa4eb5d63fc257475feff348 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 12 Aug 2021 00:01:15 -0400 Subject: [PATCH 1111/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ed32434e124..16d1c49396f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210811) +set(CMake_VERSION_PATCH 20210812) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 361b1ea4c76fab3f22e99de6bbd926a8956714fa Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Thu, 12 Aug 2021 19:17:35 +0200 Subject: [PATCH 1112/1519] Refactor: cmStandardLevelResolver::ComputeFeaturesAvailable returns cmProp --- Source/cmGeneratorExpressionNode.cxx | 2 +- Source/cmStandardLevelResolver.cxx | 6 +++--- Source/cmStandardLevelResolver.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 217ebe5f9dc..3e90eaded89 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1777,7 +1777,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode testedFeatures[lang].push_back(p); if (availableFeatures.find(lang) == availableFeatures.end()) { - const char* featuresKnown = + cmProp featuresKnown = standardResolver.CompileFeaturesAvailable(lang, &error); if (!featuresKnown) { reportError(context, content->GetOriginalExpression(), error); diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index da36ed6b203..499317d2d60 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -393,7 +393,7 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( return true; } - const char* features = this->CompileFeaturesAvailable(lang, error); + cmProp features = this->CompileFeaturesAvailable(lang, error); if (!features) { return false; } @@ -471,7 +471,7 @@ bool cmStandardLevelResolver::CompileFeatureKnown( return false; } -const char* cmStandardLevelResolver::CompileFeaturesAvailable( +cmProp cmStandardLevelResolver::CompileFeaturesAvailable( const std::string& lang, std::string* error) const { if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) { @@ -513,7 +513,7 @@ const char* cmStandardLevelResolver::CompileFeaturesAvailable( } return nullptr; } - return cmToCStr(featuresKnown); + return featuresKnown; } bool cmStandardLevelResolver::GetNewRequiredStandard( diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index d84fbcbe19c..c01a3b13279 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -30,8 +30,8 @@ class cmStandardLevelResolver const std::string& feature, std::string& lang, std::string* error) const; - const char* CompileFeaturesAvailable(const std::string& lang, - std::string* error) const; + cmProp CompileFeaturesAvailable(const std::string& lang, + std::string* error) const; bool GetNewRequiredStandard(const std::string& targetName, const std::string& feature, From 74d062969066ecacad8ca3de1c923c253310b26a Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 13 Aug 2021 00:01:26 -0400 Subject: [PATCH 1113/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 16d1c49396f..a668fdbc1bf 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210812) +set(CMake_VERSION_PATCH 20210813) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d1599c3f7fc7200894c95a47ee41265d9c8b9c2d Mon Sep 17 00:00:00 2001 From: leha-bot <leha-bot@users.noreply.github.com> Date: Fri, 13 Aug 2021 17:05:01 +0300 Subject: [PATCH 1114/1519] Fix build on Android (host) --- Source/cmake.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index ab8309d6824..7f8f6547b8f 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -114,7 +114,9 @@ # include "cmExtraSublimeTextGenerator.h" #endif -#if defined(__linux__) || defined(_WIN32) +// NOTE: the __linux__ macro is predefined on Android host too, but +// main CMakeLists.txt filters out this generator by host name. +#if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32) # include "cmGlobalGhsMultiGenerator.h" #endif @@ -2528,7 +2530,7 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory()); #endif #if !defined(CMAKE_BOOTSTRAP) -# if defined(__linux__) || defined(_WIN32) +# if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32) this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory()); From e06c1e84aaf9d5a87187cb7226264c69efe8847d Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 14 Aug 2021 00:01:10 -0400 Subject: [PATCH 1115/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a668fdbc1bf..941490936ba 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210813) +set(CMake_VERSION_PATCH 20210814) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a3ea775aeabf1fe014ab0fa8883ff62543740ea0 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 15 Aug 2021 00:01:14 -0400 Subject: [PATCH 1116/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 941490936ba..4ec8896dbd9 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210814) +set(CMake_VERSION_PATCH 20210815) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0aa514297e251c9c9f9cf9ad3dad5f74fd7798f3 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 16 Aug 2021 00:01:24 -0400 Subject: [PATCH 1117/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4ec8896dbd9..1fe8819aee8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210815) +set(CMake_VERSION_PATCH 20210816) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 35e38ef97a056e44926ad0991627a71b5d7ed2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= <marcus@hostalia.de> Date: Mon, 16 Aug 2021 20:24:03 +0200 Subject: [PATCH 1118/1519] Config File Gen: When requiring >= 2.6, don't check < 2.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This seems to be a clear-cut case. Signed-off-by: Marcus Müller <marcus@hostalia.de> --- Source/cmExportFileGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ebdbe38f57e..8b06a158149 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -917,7 +917,7 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Protect that file against use with older CMake versions. /* clang-format off */ os << "# Generated by CMake\n\n"; - os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n" + os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.6)\n" << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n" << "endif()\n"; /* clang-format on */ From fa68fef6a719fcc150eac1eb8040d884f693d3dd Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 17 Aug 2021 00:01:21 -0400 Subject: [PATCH 1119/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1fe8819aee8..10c68c28b16 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210816) +set(CMake_VERSION_PATCH 20210817) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 881e76e7c51c2aa8958252c4bc1166a8b00f24a7 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 18 Aug 2021 00:01:09 -0400 Subject: [PATCH 1120/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 10c68c28b16..b78d7d24abf 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210817) +set(CMake_VERSION_PATCH 20210818) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 164643fc3994f7fca09d4974cb097ec3d418cd53 Mon Sep 17 00:00:00 2001 From: WangBin <wbsecg1@gmail.com> Date: Wed, 11 Aug 2021 23:14:22 -0400 Subject: [PATCH 1121/1519] Android: Fix NDK toolchain dir on arm64 mac --- Modules/Platform/Android-Determine.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index 2d2cd5c72bc..7b67f839ecc 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -267,7 +267,7 @@ endif() if(CMAKE_ANDROID_NDK) # Identify the host platform. if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64") set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86_64") else() set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86") From 788b7afff20a59bada4dbb21418d9f83290996c6 Mon Sep 17 00:00:00 2001 From: Thomas Bernard <thomas@famillebernardgouriou.fr> Date: Mon, 16 Aug 2021 23:48:41 +0200 Subject: [PATCH 1122/1519] FindBinUtils: Fall back to ld for Clang without lld If `lld` is not available, Clang can still use `ld`. Fixes: #22500 --- Modules/CMakeFindBinUtils.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index d0beac61437..bb97f4a2253 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -165,9 +165,9 @@ else() # Prepend toolchain-specific names. if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang) if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC") - set(_CMAKE_LINKER_NAMES "lld-link") + list(PREPEND _CMAKE_LINKER_NAMES "lld-link") else() - set(_CMAKE_LINKER_NAMES "ld.lld") + list(PREPEND _CMAKE_LINKER_NAMES "ld.lld") endif() list(PREPEND _CMAKE_AR_NAMES "llvm-ar") list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") From 17e4934dbfa6df048e201bf0f0b46ad8d0e279ef Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sat, 14 Aug 2021 16:48:22 +0200 Subject: [PATCH 1123/1519] FindPkgConfig: Restore legacy behavior when CMP0126 is set to NEW Module behavior must be independent from `CMP0126` policy. Fixes: #22526 --- Modules/FindPkgConfig.cmake | 8 +++ .../FindPkgConfig_CMP0126_NEW.cmake | 64 +++++++++++++++++++ .../RunCMake/FindPkgConfig/RunCMakeTest.cmake | 1 + 3 files changed, 73 insertions(+) create mode 100644 Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 3bc9dba167a..01ad5ac6bf6 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -79,10 +79,18 @@ set(PKG_CONFIG_FOUND "${PKGCONFIG_FOUND}") # Unsets the given variables macro(_pkgconfig_unset var) + # Clear normal variable (possibly set by project code). + unset(${var}) + # Store as cache variable. + # FIXME: Add a policy to switch to a normal variable. set(${var} "" CACHE INTERNAL "") endmacro() macro(_pkgconfig_set var value) + # Clear normal variable (possibly set by project code). + unset(${var}) + # Store as cache variable. + # FIXME: Add a policy to switch to a normal variable. set(${var} ${value} CACHE INTERNAL "") endmacro() diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake new file mode 100644 index 00000000000..a419ab323d7 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake @@ -0,0 +1,64 @@ + +cmake_policy(SET CMP0126 NEW) + +# Needed for CMAKE_SYSTEM_NAME, CMAKE_LIBRARY_ARCHITECTURE, FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS +enable_language(C) + +# Prepare environment and variables +set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH TRUE) +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pc-foo") +if(WIN32) + set(PKG_CONFIG_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}\\dummy-pkg-config.bat") + set(ENV{CMAKE_PREFIX_PATH} "${CMAKE_CURRENT_SOURCE_DIR}\\pc-bar;X:\\this\\directory\\should\\not\\exist\\in\\the\\filesystem") + set(ENV{PKG_CONFIG_PATH} "C:\\baz") +else() + set(PKG_CONFIG_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/dummy-pkg-config.sh") + set(ENV{CMAKE_PREFIX_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/pc-bar:/this/directory/should/not/exist/in/the/filesystem") + set(ENV{PKG_CONFIG_PATH} "/baz") +endif() + + +find_package(PkgConfig) + + +if(NOT DEFINED CMAKE_SYSTEM_NAME + OR (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" + AND NOT CMAKE_CROSSCOMPILING)) + if(EXISTS "/etc/debian_version") # is this a debian system ? + if(CMAKE_LIBRARY_ARCHITECTURE MATCHES "^(i386-linux-gnu|x86_64-linux-gnu)$") + # Cannot create directories for all the existing architectures... + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + else() + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + endif() + else() + # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) + get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) + get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + else() + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + endif() + endif() +else() + if(WIN32) + set(expected_path "C:\\baz;${CMAKE_CURRENT_SOURCE_DIR}\\pc-foo\\lib\\pkgconfig;${CMAKE_CURRENT_SOURCE_DIR}\\pc-bar\\lib\\pkgconfig") + else() + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + endif() +endif() + + +set(FOO_FOUND FALSE) + +pkg_check_modules(FOO "${expected_path}") + +if(NOT FOO_FOUND) + message(FATAL_ERROR "Expected FOO_FOUND == 1.") +endif() diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index e7f008ca530..78ccd962f08 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -7,6 +7,7 @@ set(ENV{CMAKE_FRAMEWORK_PATH} "") run_cmake(PkgConfigDoesNotExist) +run_cmake(FindPkgConfig_CMP0126_NEW) run_cmake(FindPkgConfig_NO_PKGCONFIG_PATH) run_cmake(FindPkgConfig_PKGCONFIG_PATH) run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH) From 89ed11ae6f98319bbba2c34e7c0e1d1a5c8dd547 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 18 Aug 2021 15:24:30 -0400 Subject: [PATCH 1124/1519] CheckLanguage: Avoid CMP0126 warning The macro's implementation converts a normal variable into a cache variable intentionally, so both are set. Explicitly set CMP0126 to NEW to avoid a warning in trace mode. This won't affect the module behavior because the code path does not activate if a normal variable is already defined anyway. Fixes: #22548 --- Modules/CheckLanguage.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake index 928881cab1f..559c103e8b7 100644 --- a/Modules/CheckLanguage.cmake +++ b/Modules/CheckLanguage.cmake @@ -36,6 +36,9 @@ Example: include_guard(GLOBAL) +cmake_policy(PUSH) +cmake_policy(SET CMP0126 NEW) + macro(check_language lang) if(NOT DEFINED CMAKE_${lang}_COMPILER) set(_desc "Looking for a ${lang} compiler") @@ -110,3 +113,5 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" endif() endmacro() + +cmake_policy(POP) From 5917b6277fc171fc61d0b277af9bf5950915f863 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 19 Aug 2021 00:01:17 -0400 Subject: [PATCH 1125/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b78d7d24abf..d13d28570a6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210818) +set(CMake_VERSION_PATCH 20210819) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2984df91002fe3e3db0d38f364e9842024a8ab2e Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sun, 15 Aug 2021 15:27:47 +0200 Subject: [PATCH 1126/1519] Refactor: cmHasPrefix and cmHasSuffix accept now cmProp --- Source/cmStringAlgorithms.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 531678ad226..20061e9af1b 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -290,6 +290,16 @@ inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix) return str.compare(0, prefix.size(), prefix) == 0; } +/** Returns true if string @a str starts with string @a prefix. */ +inline bool cmHasPrefix(cm::string_view str, cmProp prefix) +{ + if (!prefix) { + return false; + } + + return str.compare(0, prefix->size(), prefix) == 0; +} + /** Returns true if string @a str starts with string @a prefix. */ template <size_t N> inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N]) @@ -310,6 +320,17 @@ inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix) str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } +/** Returns true if string @a str ends with string @a suffix. */ +inline bool cmHasSuffix(cm::string_view str, cmProp suffix) +{ + if (!suffix) { + return false; + } + + return str.size() >= suffix->size() && + str.compare(str.size() - suffix->size(), suffix->size(), suffix) == 0; +} + /** Returns true if string @a str ends with string @a suffix. */ template <size_t N> inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N]) From 5a2a275bb41e04891c2541a8e185b6daed259b0b Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 13 Aug 2021 15:57:23 +0200 Subject: [PATCH 1127/1519] Refactor: reduce cmToCStr usage --- Source/cmComputeLinkInformation.cxx | 7 ++--- Source/cmComputeLinkInformation.h | 3 +- Source/cmGeneratorTarget.cxx | 21 ++++++------- Source/cmGeneratorTarget.h | 3 +- Source/cmGetDirectoryPropertyCommand.cxx | 11 +++++-- Source/cmGetPropertyCommand.cxx | 5 ++- Source/cmGlobalVisualStudio71Generator.cxx | 6 ++-- Source/cmGlobalVisualStudio71Generator.h | 2 +- Source/cmGlobalVisualStudio7Generator.cxx | 7 ++--- Source/cmGlobalVisualStudio7Generator.h | 3 +- Source/cmIncludeRegularExpressionCommand.cxx | 2 +- Source/cmLocalGenerator.cxx | 32 +++++++++----------- Source/cmLocalGenerator.h | 2 +- Source/cmMakefile.h | 8 ++--- Source/cmMakefileTargetGenerator.cxx | 7 ++--- Source/cmNinjaTargetGenerator.cxx | 6 ++-- Source/cmVisualStudio10TargetGenerator.cxx | 6 ++-- 17 files changed, 62 insertions(+), 69 deletions(-) diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d15da0c968f..eda0722d0a7 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -278,13 +278,11 @@ cmComputeLinkInformation::cmComputeLinkInformation( // On platforms without import libraries there may be a special flag // to use when creating a plugin (module) that obtains symbols from // the program that will load it. - this->LoaderFlag = nullptr; if (!this->Target->IsDLLPlatform() && this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) { std::string loader_flag_var = cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG"); - this->LoaderFlag = - cmToCStr(this->Makefile->GetDefinition(loader_flag_var)); + this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var); } // Get options needed to link libraries. @@ -660,8 +658,7 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item, // This link item is an executable that may provide symbols // used by this target. A special flag is needed on this // platform. Add it now. - std::string linkItem; - linkItem = this->LoaderFlag; + std::string linkItem = this->LoaderFlag; cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 7fe30b3bb61..c3ae3452564 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -14,6 +14,7 @@ #include "cmsys/RegularExpression.hxx" #include "cmListFileCache.h" +#include "cmProperty.h" class cmGeneratorTarget; class cmGlobalGenerator; @@ -137,7 +138,7 @@ class cmComputeLinkInformation SharedDepModeLink // List file on link line }; - const char* LoaderFlag; + cmProp LoaderFlag; std::string LibLinkFlag; std::string LibLinkFileFlag; std::string ObjLinkFileFlag; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 42086894b96..3201ae38a6f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4962,11 +4962,11 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames( // The library's soname. this->ComputeVersionedName(targetNames.SharedObject, prefix, targetNames.Base, suffix, targetNames.Output, - cmToCStr(soversion)); + soversion); // The library's real name on disk. this->ComputeVersionedName(targetNames.Real, prefix, targetNames.Base, - suffix, targetNames.Output, cmToCStr(version)); + suffix, targetNames.Output, version); } // The import library name. @@ -4999,10 +4999,10 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames( // This versioning is supported only for executables and then only // when the platform supports symbolic links. #if defined(_WIN32) && !defined(__CYGWIN__) - const char* version = nullptr; + cmProp version; #else // Check for executable version properties. - const char* version = cmToCStr(this->GetProperty("VERSION")); + cmProp version = this->GetProperty("VERSION"); if (this->GetType() != cmStateEnums::EXECUTABLE || this->Makefile->IsOn("XCODE")) { version = nullptr; @@ -5026,7 +5026,7 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames( #endif if (version) { targetNames.Real += "-"; - targetNames.Real += version; + targetNames.Real += *version; } #if defined(__CYGWIN__) targetNames.Real += suffix; @@ -6290,17 +6290,14 @@ std::string cmGeneratorTarget::GetFrameworkVersion() const return "A"; } -void cmGeneratorTarget::ComputeVersionedName(std::string& vName, - std::string const& prefix, - std::string const& base, - std::string const& suffix, - std::string const& name, - const char* version) const +void cmGeneratorTarget::ComputeVersionedName( + std::string& vName, std::string const& prefix, std::string const& base, + std::string const& suffix, std::string const& name, cmProp version) const { vName = this->Makefile->IsOn("APPLE") ? (prefix + base) : name; if (version) { vName += "."; - vName += version; + vName += *version; } vName += this->Makefile->IsOn("APPLE") ? suffix : std::string(); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index fb1b2e62074..bb4621198ba 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -905,8 +905,7 @@ class cmGeneratorTarget void ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, std::string const& suffix, - std::string const& name, - const char* version) const; + std::string const& name, cmProp version) const; struct CompatibleInterfacesBase { diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 7fbd479ac7c..d98f95cd0d0 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -13,6 +13,8 @@ namespace { void StoreResult(cmMakefile& makefile, std::string const& variable, const char* prop); +void StoreResult(cmMakefile& makefile, std::string const& variable, + cmProp prop); } // cmGetDirectoryPropertyCommand @@ -76,7 +78,6 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, return false; } - const char* prop = nullptr; if (*i == "DEFINITIONS") { switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: @@ -94,8 +95,7 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, break; } } - prop = cmToCStr(dir->GetProperty(*i)); - StoreResult(status.GetMakefile(), variable, prop); + StoreResult(status.GetMakefile(), variable, dir->GetProperty(*i)); return true; } @@ -105,4 +105,9 @@ void StoreResult(cmMakefile& makefile, std::string const& variable, { makefile.AddDefinition(variable, prop ? prop : ""); } +void StoreResult(cmMakefile& makefile, std::string const& variable, + cmProp prop) +{ + makefile.AddDefinition(variable, prop); +} } diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index bb3a40bac6e..4b380c05b85 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -431,9 +431,8 @@ bool HandleVariableMode(cmExecutionStatus& status, const std::string& name, return false; } - return StoreResult( - infoType, status.GetMakefile(), variable, - cmToCStr(status.GetMakefile().GetDefinition(propertyName))); + return StoreResult(infoType, status.GetMakefile(), variable, + status.GetMakefile().GetDefinition(propertyName)); } bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 0083c407d58..21ea7e6c2b2 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -157,11 +157,11 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteExternalProject( std::ostream& fout, const std::string& name, const std::string& location, - const char* typeGuid, - const std::set<BT<std::pair<std::string, bool>>>& depends) + cmProp typeGuid, const std::set<BT<std::pair<std::string, bool>>>& depends) { fout << "Project(\"{" - << (typeGuid ? typeGuid : this->ExternalProjectType(location)) + << (typeGuid ? typeGuid + : std::string(this->ExternalProjectType(location))) << "}\") = \"" << name << "\", \"" << this->ConvertToSolutionPath(location) << "\", \"{" << this->GetGUID(name) << "}\"\n"; diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 7d381996615..30ebf08e01f 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -33,7 +33,7 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator const std::string& platformMapping = "") override; void WriteExternalProject( std::ostream& fout, const std::string& name, const std::string& path, - const char* typeGuid, + cmProp typeGuid, const std::set<BT<std::pair<std::string, bool>>>& depends) override; // Folders are not supported by VS 7.1. diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 34dba1eb5c2..2a142aef238 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -391,10 +391,9 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( std::string project = target->GetName(); std::string location = *expath; - this->WriteExternalProject( - fout, project, location, - cmToCStr(target->GetProperty("VS_PROJECT_TYPE")), - target->GetUtilities()); + this->WriteExternalProject(fout, project, location, + target->GetProperty("VS_PROJECT_TYPE"), + target->GetUtilities()); written = true; } else { cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 148762eacd8..1e34792ed3a 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -6,6 +6,7 @@ #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" +#include "cmProperty.h" class cmTarget; struct cmIDEFlagTable; @@ -142,7 +143,7 @@ class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator virtual void WriteExternalProject( std::ostream& fout, const std::string& name, const std::string& path, - const char* typeGuid, + cmProp typeGuid, const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0; std::string ConvertToSolutionPath(const std::string& path); diff --git a/Source/cmIncludeRegularExpressionCommand.cxx b/Source/cmIncludeRegularExpressionCommand.cxx index 655ebd6e404..cdcc7df71fa 100644 --- a/Source/cmIncludeRegularExpressionCommand.cxx +++ b/Source/cmIncludeRegularExpressionCommand.cxx @@ -14,7 +14,7 @@ bool cmIncludeRegularExpressionCommand(std::vector<std::string> const& args, } cmMakefile& mf = status.GetMakefile(); - mf.SetIncludeRegularExpression(args[0].c_str()); + mf.SetIncludeRegularExpression(args[0]); if (args.size() > 1) { mf.SetComplainRegularExpression(args[1]); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 028952a9c00..74130dd0719 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -425,27 +425,25 @@ void cmLocalGenerator::ProcessEvaluationFiles( void cmLocalGenerator::GenerateInstallRules() { // Compute the install prefix. - const char* prefix = - cmToCStr(this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX")); + cmProp installPrefix = this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX"); + std::string prefix = installPrefix; #if defined(_WIN32) && !defined(__CYGWIN__) - std::string prefix_win32; - if (!prefix) { - if (!cmSystemTools::GetEnv("SystemDrive", prefix_win32)) { - prefix_win32 = "C:"; + if (!installPrefix) { + if (!cmSystemTools::GetEnv("SystemDrive", prefix)) { + prefix = "C:"; } cmProp project_name = this->Makefile->GetDefinition("PROJECT_NAME"); if (cmNonempty(project_name)) { - prefix_win32 += "/Program Files/"; - prefix_win32 += *project_name; + prefix += "/Program Files/"; + prefix += *project_name; } else { - prefix_win32 += "/InstalledCMakeProject"; + prefix += "/InstalledCMakeProject"; } - prefix = prefix_win32.c_str(); } #elif defined(__HAIKU__) char dir[B_PATH_NAME_LENGTH]; - if (!prefix) { + if (!installPrefix) { if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) == B_OK) { prefix = dir; @@ -454,13 +452,13 @@ void cmLocalGenerator::GenerateInstallRules() } } #else - if (!prefix) { + if (!installPrefix) { prefix = "/usr/local"; } #endif if (cmProp stagingPrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) { - prefix = stagingPrefix->c_str(); + prefix = *stagingPrefix; } // Compute the set of configurations. @@ -1869,17 +1867,17 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( } bool cmLocalGenerator::AllAppleArchSysrootsAreTheSame( - const std::vector<std::string>& archs, const char* sysroot) + const std::vector<std::string>& archs, cmProp sysroot) { if (!sysroot) { return false; } return std::all_of(archs.begin(), archs.end(), - [this, &sysroot](std::string const& arch) -> bool { + [this, sysroot](std::string const& arch) -> bool { std::string const& archSysroot = this->AppleArchSysroots[arch]; - return cmIsOff(archSysroot) || archSysroot == sysroot; + return cmIsOff(archSysroot) || sysroot == archSysroot; }); } @@ -1912,7 +1910,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, cmProp sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); if (cmNonempty(sysrootFlag)) { if (!this->AppleArchSysroots.empty() && - !this->AllAppleArchSysrootsAreTheSame(archs, cmToCStr(sysroot))) { + !this->AllAppleArchSysrootsAreTheSame(archs, sysroot)) { for (std::string const& arch : archs) { std::string const& archSysroot = this->AppleArchSysroots[arch]; if (cmIsOff(archSysroot)) { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1e09b23f291..678ef8c9c0d 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -651,7 +651,7 @@ class cmLocalGenerator : public cmOutputConverter void ComputeObjectMaxPath(); bool AllAppleArchSysrootsAreTheSame(const std::vector<std::string>& archs, - const char* sysroot); + cmProp sysroot); void CopyPchCompilePdb(const std::string& config, cmGeneratorTarget* target, const std::string& ReuseFrom, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 5886c86ef4a..a3d2a8195f6 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -399,13 +399,13 @@ class cmMakefile * Set a regular expression that include files must match * in order to be considered as part of the depend information. */ - void SetIncludeRegularExpression(const char* regex) + void SetIncludeRegularExpression(const std::string& regex) { - this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex); + this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex.c_str()); } - const char* GetIncludeRegularExpression() const + const std::string& GetIncludeRegularExpression() const { - return cmToCStr(this->GetProperty("INCLUDE_REGULAR_EXPRESSION")); + return this->GetProperty("INCLUDE_REGULAR_EXPRESSION"); } /** diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 626453ffd42..c83a7ab3da4 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -293,8 +293,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GetConfigName()); for (cmSourceFile const* sf : externalObjects) { auto const& objectFileName = sf->GetFullPath(); - if (!cmSystemTools::StringEndsWith(objectFileName, - cmToCStr(pchExtension))) { + if (!cmHasSuffix(objectFileName, pchExtension)) { this->ExternalObjects.push_back(objectFileName); } } @@ -1732,7 +1731,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); for (std::string const& obj : this->Objects) { - if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) { + if (cmHasSuffix(obj, pchExtension)) { continue; } *this->BuildFileStream << " " << lineContinue; @@ -1822,7 +1821,7 @@ void cmMakefileTargetGenerator::WriteObjectsStrings( objStrings, this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit); for (std::string const& obj : this->Objects) { - if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) { + if (cmHasSuffix(obj, pchExtension)) { continue; } helper.Feed(obj); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 609848b433b..1b6b834e5db 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -994,8 +994,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( for (cmSourceFile const* sf : externalObjects) { auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir( this->ConvertToNinjaPath(sf->GetFullPath()), config); - if (!cmSystemTools::StringEndsWith(objectFileName, - cmToCStr(pchExtension))) { + if (!cmHasSuffix(objectFileName, pchExtension)) { this->Configs[config].Objects.push_back(objectFileName); } } @@ -1260,8 +1259,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( if (firstForConfig) { cmProp pchExtension = this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); - if (!cmSystemTools::StringEndsWith(objectFileName, - cmToCStr(pchExtension))) { + if (!cmHasSuffix(objectFileName, pchExtension)) { // Add this object to the list of object files. this->Configs[config].Objects.push_back(objectFileName); } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 03d1bbbc6d4..94072286d08 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -508,15 +508,15 @@ void cmVisualStudio10TargetGenerator::Generate() p = this->GeneratorTarget->GetProperty( "DOTNET_TARGET_FRAMEWORK_VERSION"); } - const char* targetFrameworkVersion = cmToCStr(p); - if (!targetFrameworkVersion && this->ProjectType == csproj && + std::string targetFrameworkVersion = p; + if (targetFrameworkVersion.empty() && this->ProjectType == csproj && this->GlobalGenerator->TargetsWindowsCE() && this->GlobalGenerator->GetVersion() == cmGlobalVisualStudioGenerator::VS12) { // VS12 .NETCF default to .NET framework 3.9 targetFrameworkVersion = "v3.9"; } - if (targetFrameworkVersion) { + if (!targetFrameworkVersion.empty()) { e1.Element("TargetFrameworkVersion", targetFrameworkVersion); } } From d2a6e160aa74479fc623918b084423739a9b80c7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 19 Aug 2021 12:22:47 -0400 Subject: [PATCH 1128/1519] AUTOUIC: Revert "Fix generating of dependency rules for UI header files" Revert commit e5ec0e52f4 (AUTOUIC: Fix generating of dependency rules for UI header files, 2021-07-22, v3.21.1~8^2) because it caused regressions. For example, changing one C++ source can now cause many others to rebuild. Revert the change pending further investigation. Fixes: #22531 Issue: #16776 --- Source/CMakeLists.txt | 2 - Source/cmQtAutoGen.cxx | 36 ------------- Source/cmQtAutoGen.h | 3 -- Source/cmQtAutoGenInitializer.cxx | 53 +++++++++---------- Source/cmQtAutoGenInitializer.h | 2 - Source/cmQtAutoGenerator.cxx | 37 +++++++++++++ Source/cmQtAutoGenerator.h | 2 + Source/cmQtAutoMocUic.cxx | 20 +++++-- Source/cmQtAutoUicHelpers.cxx | 25 --------- Source/cmQtAutoUicHelpers.h | 20 ------- .../RerunUicOnFileChange/CMakeLists.txt | 3 -- .../UicOnFileChange/CMakeLists.txt.in | 1 - .../UicOnFileChange/main.cpp | 4 +- .../subdir/mainwindowsubdir.ui.in | 7 --- .../UicOnFileChange/subdir/subdircheck.cpp | 9 ---- 15 files changed, 82 insertions(+), 142 deletions(-) delete mode 100644 Source/cmQtAutoUicHelpers.cxx delete mode 100644 Source/cmQtAutoUicHelpers.h delete mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in delete mode 100644 Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 0142c07ecb3..9a18184fd3b 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -432,8 +432,6 @@ set(SRCS cmQtAutoMocUic.h cmQtAutoRcc.cxx cmQtAutoRcc.h - cmQtAutoUicHelpers.cxx - cmQtAutoUicHelpers.h cmRST.cxx cmRST.h cmRuntimeDependencyArchive.cxx diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 898d862221f..57fcd2da768 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -384,39 +384,3 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, } return true; } - -bool cmQtAutoGen::FileRead(std::string& content, std::string const& filename, - std::string* error) -{ - content.clear(); - if (!cmSystemTools::FileExists(filename, true)) { - if (error != nullptr) { - *error = "Not a file."; - } - return false; - } - - unsigned long const length = cmSystemTools::FileLength(filename); - cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); - - // Use lambda to save destructor calls of ifs - return [&ifs, length, &content, error]() -> bool { - if (!ifs) { - if (error != nullptr) { - *error = "Opening the file for reading failed."; - } - return false; - } - content.reserve(length); - using IsIt = std::istreambuf_iterator<char>; - content.assign(IsIt{ ifs }, IsIt{}); - if (!ifs) { - content.clear(); - if (error != nullptr) { - *error = "Reading from the file failed."; - } - return false; - } - return true; - }(); -} diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index b9ae360291e..466a954a981 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -100,9 +100,6 @@ class cmQtAutoGen std::vector<std::string> const& newOpts, bool isQt5); - static bool FileRead(std::string& content, std::string const& filename, - std::string* error = nullptr); - /** @class RccLister * @brief Lists files in qrc resource files */ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6cc83289100..4dd78e514f5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -902,13 +902,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() // The reason is that their file names might be discovered from source files // at generation time. if (this->MocOrUicEnabled()) { - std::set<std::string> uicIncludes; - auto collectUicIncludes = [&](std::unique_ptr<cmSourceFile> const& sf) { - std::string content; - FileRead(content, sf->GetFullPath()); - this->AutoUicHelpers.CollectUicIncludes(uicIncludes, content); - }; - for (const auto& sf : this->Makefile->GetSourceFiles()) { // sf->GetExtension() is only valid after sf->ResolveFullPath() ... // Since we're iterating over source files that might be not in the @@ -921,10 +914,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const& extLower = cmSystemTools::LowerCase(sf->GetExtension()); - bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); - bool const skipUic = - (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC) || - !this->Uic.Enabled); if (cm->IsAHeaderExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Headers, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, {}, false); @@ -932,9 +921,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() addMUHeader(std::move(muf), extLower); } } - if (!skipUic && !sf->GetIsGenerated()) { - collectUicIncludes(sf); - } } else if (cm->IsACLikeSourceExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Sources, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, {}, false); @@ -942,11 +928,11 @@ bool cmQtAutoGenInitializer::InitScanFiles() addMUSource(std::move(muf)); } } - if (!skipUic && !sf->GetIsGenerated()) { - collectUicIncludes(sf); - } } else if (this->Uic.Enabled && (extLower == kw.ui)) { // .ui file + bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); + bool const skipUic = + (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC)); if (!skipUic) { // Check if the .ui file has uic options std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); @@ -956,22 +942,35 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->Uic.UiFilesWithOptions.emplace_back(fullPath, cmExpandedList(uicOpts)); } + + auto uiHeaderRelativePath = cmSystemTools::RelativePath( + this->LocalGen->GetCurrentSourceDirectory(), + cmSystemTools::GetFilenamePath(fullPath)); + + // Avoid creating a path containing adjacent slashes + if (!uiHeaderRelativePath.empty() && + uiHeaderRelativePath.back() != '/') { + uiHeaderRelativePath += '/'; + } + + auto uiHeaderFilePath = cmStrCat( + '/', uiHeaderRelativePath, "ui_"_s, + cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); + + ConfigString uiHeader; + std::string uiHeaderGenex; + this->ConfigFileNamesAndGenex( + uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s), + uiHeaderFilePath); + + this->Uic.UiHeaders.emplace_back( + std::make_pair(uiHeader, uiHeaderGenex)); } else { // Register skipped .ui file this->Uic.SkipUi.insert(fullPath); } } } - - for (const auto& include : uicIncludes) { - ConfigString uiHeader; - std::string uiHeaderGenex; - this->ConfigFileNamesAndGenex(uiHeader, uiHeaderGenex, - cmStrCat(this->Dir.Build, "/include"_s), - cmStrCat("/"_s, include)); - this->Uic.UiHeaders.emplace_back( - std::make_pair(uiHeader, uiHeaderGenex)); - } } // Process GENERATED sources and headers diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 3ec87d212d4..e76817b9c43 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -17,7 +17,6 @@ #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" -#include "cmQtAutoUicHelpers.h" class cmGeneratorTarget; class cmGlobalGenerator; @@ -171,7 +170,6 @@ class cmQtAutoGenInitializer : public cmQtAutoGen std::string ConfigDefault; std::vector<std::string> ConfigsList; std::string TargetsFolder; - cmQtAutoUicHelpers AutoUicHelpers; /** Common directories. */ struct diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 0c6b5e6dc53..568926e3c5d 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -121,6 +121,43 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename) return success; } +bool cmQtAutoGenerator::FileRead(std::string& content, + std::string const& filename, + std::string* error) +{ + content.clear(); + if (!cmSystemTools::FileExists(filename, true)) { + if (error != nullptr) { + *error = "Not a file."; + } + return false; + } + + unsigned long const length = cmSystemTools::FileLength(filename); + cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); + + // Use lambda to save destructor calls of ifs + return [&ifs, length, &content, error]() -> bool { + if (!ifs) { + if (error != nullptr) { + *error = "Opening the file for reading failed."; + } + return false; + } + content.reserve(length); + using IsIt = std::istreambuf_iterator<char>; + content.assign(IsIt{ ifs }, IsIt{}); + if (!ifs) { + content.clear(); + if (error != nullptr) { + *error = "Reading from the file failed."; + } + return false; + } + return true; + }(); +} + bool cmQtAutoGenerator::FileWrite(std::string const& filename, std::string const& content, std::string* error) diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 66399d7e8ae..5c3a8adccb4 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -70,6 +70,8 @@ class cmQtAutoGenerator : public cmQtAutoGen // -- File system methods static bool MakeParentDirectory(std::string const& filename); + static bool FileRead(std::string& content, std::string const& filename, + std::string* error = nullptr); static bool FileWrite(std::string const& filename, std::string const& content, std::string* error = nullptr); diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 86d54f9e1a7..2753fd57c02 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -30,7 +30,6 @@ #include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" -#include "cmQtAutoUicHelpers.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkerPool.h" @@ -282,7 +281,7 @@ class cmQtAutoMocUicT : public cmQtAutoGenerator std::vector<std::string> Options; std::unordered_map<std::string, UiFile> UiFiles; std::vector<std::string> SearchPaths; - cmQtAutoUicHelpers AutoUicHelpers; + cmsys::RegularExpression RegExpInclude; }; /** Uic shared variables. */ @@ -762,7 +761,11 @@ std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const return res; } -cmQtAutoMocUicT::UicSettingsT::UicSettingsT() = default; +cmQtAutoMocUicT::UicSettingsT::UicSettingsT() +{ + this->RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" + "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); +} cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default; @@ -1053,7 +1056,16 @@ void cmQtAutoMocUicT::JobParseT::UicIncludes() } std::set<std::string> includes; - this->UicConst().AutoUicHelpers.CollectUicIncludes(includes, this->Content); + { + const char* contentChars = this->Content.c_str(); + cmsys::RegularExpression const& regExp = this->UicConst().RegExpInclude; + cmsys::RegularExpressionMatch match; + while (regExp.find(contentChars, match)) { + includes.emplace(match.match(2)); + // Forward content pointer + contentChars += match.end(); + } + } this->CreateKeys(this->FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength); } diff --git a/Source/cmQtAutoUicHelpers.cxx b/Source/cmQtAutoUicHelpers.cxx deleted file mode 100644 index 751ae08575a..00000000000 --- a/Source/cmQtAutoUicHelpers.cxx +++ /dev/null @@ -1,25 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmQtAutoUicHelpers.h" - -cmQtAutoUicHelpers::cmQtAutoUicHelpers() -{ - RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" - "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); -} - -void cmQtAutoUicHelpers::CollectUicIncludes(std::set<std::string>& includes, - const std::string& content) const -{ - if (content.find("ui_") == std::string::npos) { - return; - } - - const char* contentChars = content.c_str(); - cmsys::RegularExpressionMatch match; - while (this->RegExpInclude.find(contentChars, match)) { - includes.emplace(match.match(2)); - // Forward content pointer - contentChars += match.end(); - } -} diff --git a/Source/cmQtAutoUicHelpers.h b/Source/cmQtAutoUicHelpers.h deleted file mode 100644 index 6b09a31daaa..00000000000 --- a/Source/cmQtAutoUicHelpers.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#pragma once - -#include <set> -#include <string> - -#include "cmsys/RegularExpression.hxx" - -class cmQtAutoUicHelpers -{ -public: - cmQtAutoUicHelpers(); - virtual ~cmQtAutoUicHelpers() = default; - void CollectUicIncludes(std::set<std::string>& includes, - const std::string& content) const; - -private: - cmsys::RegularExpression RegExpInclude; -}; diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt index a3ba9fbd40d..9b114e9be20 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt @@ -28,12 +28,10 @@ endmacro() configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY) configure_file("${testProjectTemplateDir}/mainwindow.h" "${testProjectSrc}/mainwindow.h" COPYONLY) configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY) -configure_file("${testProjectTemplateDir}/subdir/subdircheck.cpp" "${testProjectSrc}/subdir/subdircheck.cpp" COPYONLY) configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY) set(Num 1) configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) -configure_file("${testProjectTemplateDir}/subdir/mainwindowsubdir.ui.in" "${testProjectSrc}/subdir/mainwindowsubdir.ui" @ONLY) if(CMAKE_GENERATOR_INSTANCE) set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}") @@ -97,7 +95,6 @@ sleep() set(Num 2) configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) -configure_file("${testProjectTemplateDir}/subdir/mainwindowsubdir.ui.in" "${testProjectSrc}/subdir/mainwindowsubdir.ui" @ONLY) rebuild(2) execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in index c77075ca1e3..c787db1d561 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in @@ -8,7 +8,6 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) add_executable(UicOnFileChange main.cpp mainwindow.ui mainwindow.h - subdir/subdircheck.cpp subdir/mainwindowsubdir.ui ) target_include_directories(UicOnFileChange PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp index 99de13dccf2..4aab2ad4a2c 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp @@ -1,12 +1,10 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -extern bool subdircheck(); - int main(int argc, char* argv[]) { MocWidget mw; Ui::Widget mwUi; mwUi.setupUi(&mw); - return mw.objectName() == "Widget2" && subdircheck() ? 0 : 1; + return mw.objectName() == "Widget2" ? 0 : 1; } diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in deleted file mode 100644 index a6a31f6d428..00000000000 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>WidgetSubdir</class> - <widget class="MocWidget" name="WidgetSubdir@Num@"/> - <resources/> - <connections/> -</ui> diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp deleted file mode 100644 index 3b36a10df8a..00000000000 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "ui_mainwindowsubdir.h" - -bool subdircheck() -{ - MocWidget mw; - Ui::WidgetSubdir mwUi; - mwUi.setupUi(&mw); - return mw.objectName() == "WidgetSubdir2"; -} From f64e8036aa1498edc34b1624df9dc8633467e7ef Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 19 Aug 2021 13:01:46 -0400 Subject: [PATCH 1129/1519] Tests: Fix check to add InstallMode tests The check added by commit 58d10cf6f1 (Alternative symlink-creating mode for file(INSTALL ...), 2021-08-02) only works when re-running CMake in a build tree after building `cmake`. Use the driving CMake to check instead. Remove the stray link after creation. Also remove the message on failure: we do not use that convention. --- Tests/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 9dab5b9f778..76c6c05cdef 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1649,15 +1649,14 @@ if(BUILD_TESTING) DEPENDS ExternalProjectUpdateSetup ) execute_process( - COMMAND ${CMAKE_CMAKE_COMMAND} + COMMAND ${CMAKE_COMMAND} "-E" create_symlink "${CMake_SOURCE_DIR}/Tests/CMakeLists.txt" # random source file that exists "${CMake_BINARY_DIR}/Tests/try_to_create_symlink" # random target file in existing directory - RESULT_VARIABLE _failed + RESULT_VARIABLE _symlink_result ) - if(_failed) - message("Failed to create a simple symlink on this machine. Skipping InstallMode tests.") - else() + if(_symlink_result EQUAL 0) + file(REMOVE "${CMake_BINARY_DIR}/Tests/try_to_create_symlink") function(add_installmode_test _mode) set(ENV{CMAKE_INSTALL_MODE} _mode) set(_maybe_InstallMode_CTEST_OPTIONS) From 2b2a6a7170c2253c1f97647a03c190aa906e194a Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Thu, 19 Aug 2021 13:09:39 -0400 Subject: [PATCH 1130/1519] FindMPI: do not detect `-framework` as a compile flag MPICH 3.4.2 now reports `-framework OpenCL` as one of its compilation flag. The compile flag extraction is seeing it as a generic `-f` flag and misses its argument. This ends up with a compile option of `-framework` which eats the next flag (and may be very important). It does not seem that passing `-framework` as a link flag is necessary at this time, so that is being actively ignored for now. Fixes: #22555 --- Modules/FindMPI.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index c48decbb9fb..d8f0334081c 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -624,7 +624,8 @@ function (_MPI_interrogate_compiler LANG) # we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore # produce inconsistent results with the regularly flags. # Similarly, aliasing flags do not belong into our flag array. - if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce])") + # Also strip out `-framework` flags. + if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)") list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") endif() endforeach() From 25c5ebba7edc6b871a29617ab2d7a459d81dfd58 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 27 May 2021 16:50:55 -0400 Subject: [PATCH 1131/1519] VS: Add special case for '-T version=14.29.16.11' under VS 16.11 Extend the table of special cases from commit 58a50a3a0a (VS: Fix '-T version=14.28' under VS 16.9, 2021-03-11, v3.19.7~1^2~1) and updated by commit a60141feaa (VS: Add special case for '-T version=14.29.16.10' under VS 16.10, 2021-05-27, v3.20.4~11^2). Add a special case for the name VS 17 will use for VS 16.11's default toolset, so that it can be used with VS 16.11 too. Issue: #21922 --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 79c06d6a154..d0ad53e984a 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -618,6 +618,9 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset( if (version == "14.29.16.10" && vcToolsetVersion == "14.29.30037") { return AuxToolset::Default; } + if (version == "14.29.16.11" && vcToolsetVersion == "14.29.30133") { + return AuxToolset::Default; + } // The first two components of the default toolset version typically // match the name used by later VS versions for the SxS props files. From c8c257206b1e4f5d083c7da5ac269bb4fef5cedf Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 20 Aug 2021 00:01:13 -0400 Subject: [PATCH 1132/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d13d28570a6..591bc0c5231 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210819) +set(CMake_VERSION_PATCH 20210820) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1e65e4a6e5c4870960b998b6f5d6f70965cc9344 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Fri, 30 Jul 2021 03:49:04 +0300 Subject: [PATCH 1133/1519] cmake_host_system_information: Can read `/etc/os-release` file --- .../command/cmake_host_system_information.rst | 45 ++++ Help/release/dev/os-release.rst | 6 + .../cmCMakeHostSystemInformationCommand.cxx | 197 +++++++++++++++++- Tests/RunCMake/CMakeLists.txt | 2 +- .../Exherbo-stdout.txt | 9 + .../Exherbo.cmake | 11 + .../Exherbo/etc/os-release | 7 + .../RunCMakeTest.cmake | 8 + .../Ubuntu-stdout.txt | 14 ++ .../Ubuntu.cmake | 11 + .../Ubuntu/etc/os-release | 12 ++ .../UnitTest-stdout.txt | 7 + .../UnitTest.cmake | 5 + .../UnitTest/etc/os-release | 9 + 14 files changed, 336 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/os-release.rst create mode 100644 Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/Exherbo.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release create mode 100644 Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release create mode 100644 Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/UnitTest.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index ac6a0080227..ae24b0390e4 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -132,7 +132,52 @@ queried. The list of queried values is stored in ``<variable>``. See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` +For Linux distributions additional ``<key>`` values are available to get operating +system identification as described in the `man 5 os-release`_. + +``DISTRIB_INFO`` + .. versionadded:: 3.22 + + Read :file:`/etc/os-release` file and define the given ``<variable>`` + into a list of read variables + +``DISTRIB_<name>`` + .. versionadded:: 3.22 + + Get the ``<name>`` variable if it exists in the :file:`/etc/os-release` file + + Example: + + .. code-block:: cmake + + cmake_host_system_information(RESULT PRETTY_NAME QUERY DISTRIB_PRETTY_NAME) + message(STATUS "${PRETTY_NAME}") + + cmake_host_system_information(RESULT DISTRO QUERY DISTRIB_INFO) + + foreach(VAR IN LISTS DISTRO) + message(STATUS "${VAR}=`${${VAR}}`") + endforeach() + + + Output:: + + -- Ubuntu 20.04.2 LTS + -- DISTRO_BUG_REPORT_URL=`https://bugs.launchpad.net/ubuntu/` + -- DISTRO_HOME_URL=`https://www.ubuntu.com/` + -- DISTRO_ID=`ubuntu` + -- DISTRO_ID_LIKE=`debian` + -- DISTRO_NAME=`Ubuntu` + -- DISTRO_PRETTY_NAME=`Ubuntu 20.04.2 LTS` + -- DISTRO_PRIVACY_POLICY_URL=`https://www.ubuntu.com/legal/terms-and-policies/privacy-policy` + -- DISTRO_SUPPORT_URL=`https://help.ubuntu.com/` + -- DISTRO_UBUNTU_CODENAME=`focal` + -- DISTRO_VERSION=`20.04.2 LTS (Focal Fossa)` + -- DISTRO_VERSION_CODENAME=`focal` + -- DISTRO_VERSION_ID=`20.04` .. rubric:: Footnotes .. [#mebibytes] One MiB (mebibyte) is equal to 1024x1024 bytes. + +.. _man 5 os-release: https://www.freedesktop.org/software/systemd/man/os-release.html diff --git a/Help/release/dev/os-release.rst b/Help/release/dev/os-release.rst new file mode 100644 index 00000000000..cce6aee8239 --- /dev/null +++ b/Help/release/dev/os-release.rst @@ -0,0 +1,6 @@ +os-release +---------- + +* The :command:`cmake_host_system_information` command query operating system + identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ + from the :file:`/etc/os-release` file. diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 9e21208f92b..cdd6b4c3288 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -2,28 +2,37 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeHostSystemInformationCommand.h" -#include <cstddef> +#include <cassert> +#include <cctype> +#include <initializer_list> +#include <map> +#include <string> +#include <type_traits> +#include <utility> #include <cm/optional> #include <cm/string_view> #include <cmext/string_view> +#include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #ifdef _WIN32 # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" # include "cmGlobalVisualStudioVersionedGenerator.h" -# include "cmStringAlgorithms.h" -# include "cmSystemTools.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER #endif namespace { +std::string const DELIM[2] = { {}, ";" }; + // BEGIN Private functions std::string ValueToString(std::size_t const value) { @@ -138,6 +147,177 @@ cm::optional<std::string> GetValue(cmsys::SystemInformation& info, return {}; } +#ifdef __linux__ +cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine( + std::string const& line) +{ + std::string key; + std::string value; + + char prev = 0; + enum ParserState + { + PARSE_KEY_1ST, + PARSE_KEY, + FOUND_EQ, + PARSE_SINGLE_QUOTE_VALUE, + PARSE_DBL_QUOTE_VALUE, + PARSE_VALUE, + IGNORE_REST + } state = PARSE_KEY_1ST; + + for (auto ch : line) { + switch (state) { + case PARSE_KEY_1ST: + if (std::isalpha(ch) || ch == '_') { + key += ch; + state = PARSE_KEY; + } else if (!std::isspace(ch)) { + state = IGNORE_REST; + } + break; + + case PARSE_KEY: + if (ch == '=') { + state = FOUND_EQ; + } else if (std::isalnum(ch) || ch == '_') { + key += ch; + } else { + state = IGNORE_REST; + } + break; + + case FOUND_EQ: + switch (ch) { + case '\'': + state = PARSE_SINGLE_QUOTE_VALUE; + break; + case '"': + state = PARSE_DBL_QUOTE_VALUE; + break; + case '#': + case '\\': + state = IGNORE_REST; + break; + default: + value += ch; + state = PARSE_VALUE; + } + break; + + case PARSE_SINGLE_QUOTE_VALUE: + if (ch == '\'') { + if (prev != '\\') { + state = IGNORE_REST; + } else { + assert(!value.empty()); + value[value.size() - 1] = ch; + } + } else { + value += ch; + } + break; + + case PARSE_DBL_QUOTE_VALUE: + if (ch == '"') { + if (prev != '\\') { + state = IGNORE_REST; + } else { + assert(!value.empty()); + value[value.size() - 1] = ch; + } + } else { + value += ch; + } + break; + + case PARSE_VALUE: + if (ch == '#' || std::isspace(ch)) { + state = IGNORE_REST; + } else { + value += ch; + } + break; + + default: + // Unexpected os-release parser state! + state = IGNORE_REST; + break; + } + + if (state == IGNORE_REST) { + break; + } + prev = ch; + } + if (!(key.empty() || value.empty())) { + return std::make_pair(key, value); + } + return {}; +} + +std::map<std::string, std::string> GetOSReleaseVariables( + cmExecutionStatus& status) +{ + const auto& sysroot = + status.GetMakefile().GetSafeDefinition("CMAKE_SYSROOT"); + + std::map<std::string, std::string> data; + // Based on + // https://www.freedesktop.org/software/systemd/man/os-release.html + for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) { + const auto& filename = cmStrCat(sysroot, name); + if (cmSystemTools::FileExists(filename)) { + cmsys::ifstream fin(filename.c_str()); + for (std::string line; !std::getline(fin, line).fail();) { + auto kv = ParseOSReleaseLine(line); + if (kv.has_value()) { + data.emplace(kv.value()); + } + } + break; + } + } + return data; +} + +cm::optional<std::string> GetValue(cmExecutionStatus& status, + std::string const& key, + std::string const& variable) +{ + const auto prefix = "DISTRIB_"_s; + if (!cmHasPrefix(key, prefix)) { + return {}; + } + + static const std::map<std::string, std::string> s_os_release = + GetOSReleaseVariables(status); + + auto& makefile = status.GetMakefile(); + + const std::string subkey = + key.substr(prefix.size(), key.size() - prefix.size()); + if (subkey == "INFO"_s) { + std::string vars; + for (const auto& kv : s_os_release) { + auto cmake_var_name = cmStrCat(variable, '_', kv.first); + vars += DELIM[!vars.empty()] + cmake_var_name; + makefile.AddDefinition(cmake_var_name, kv.second); + } + return cm::optional<std::string>(std::move(vars)); + } + + // Query individual variable + const auto it = s_os_release.find(subkey); + if (it != s_os_release.cend()) { + return it->second; + } + + // NOTE Empty string means requested variable not set + return std::string{}; +} +#endif + #ifdef HAVE_VS_SETUP_HELPER cm::optional<std::string> GetValue(cmExecutionStatus& status, std::string const& key) @@ -201,10 +381,9 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, std::string result_list; for (auto i = current_index + 1; i < args.size(); ++i) { + result_list += DELIM[!result_list.empty()]; + auto const& key = args[i]; - if (i != current_index + 1) { - result_list += ";"; - } auto value = GetValue(info, key); if (!value) { #ifdef HAVE_VS_SETUP_HELPER @@ -213,6 +392,12 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, status.SetError("does not recognize <key> " + key); return false; } +#elif defined(__linux__) + value = GetValue(status, key, variable); + if (!value) { + status.SetError("does not recognize <key> " + key); + return false; + } #else status.SetError("does not recognize <key> " + key); return false; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index eb2c2d94ae1..543ad1d77b5 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -349,7 +349,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() add_RunCMake_test(execute_process) add_RunCMake_test(export) -add_RunCMake_test(cmake_host_system_information) +add_RunCMake_test(cmake_host_system_information -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(cmake_language) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(cmake_parse_arguments) diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt new file mode 100644 index 00000000000..11ae71f42b0 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt @@ -0,0 +1,9 @@ +-- TEST1_ANSI_COLOR=`0;32` +-- TEST1_BUG_REPORT_URL=`https://bugs.exherbo.org/` +-- TEST1_HOME_URL=`https://www.exherbo.org/` +-- TEST1_ID=`exherbo` +-- TEST1_NAME=`Exherbo` +-- TEST1_PRETTY_NAME=`Exherbo Linux` +-- TEST1_SUPPORT_URL=`irc://irc.freenode.net/#exherbo` +-- TEST2_ID=`exherbo` +-- TEST2_VERSION=`` diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake new file mode 100644 index 00000000000..7fc26d812a6 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake @@ -0,0 +1,11 @@ +cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS TEST1) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() + +# Query individual variables +cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION) +list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION) +message(STATUS "TEST2_ID=`${TEST2_ID}`") +message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`") diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release new file mode 100644 index 00000000000..944c9b44efc --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release @@ -0,0 +1,7 @@ +NAME="Exherbo" +PRETTY_NAME="Exherbo Linux" +ID="exherbo" +ANSI_COLOR="0;32" +HOME_URL="https://www.exherbo.org/" +SUPPORT_URL="irc://irc.freenode.net/#exherbo" +BUG_REPORT_URL="https://bugs.exherbo.org/" diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index be74ade0e59..6cbb7fd39b4 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -6,3 +6,11 @@ run_cmake(BadArg3) run_cmake(QueryList) run_cmake(QueryKeys) + +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + + run_cmake_with_options(UnitTest) + run_cmake_with_options(Exherbo) + run_cmake_with_options(Ubuntu) + +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt new file mode 100644 index 00000000000..d1a18da234f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt @@ -0,0 +1,14 @@ +-- TEST1_BUG_REPORT_URL=`https://bugs\.launchpad\.net/ubuntu/` +-- TEST1_HOME_URL=`https://www\.ubuntu\.com/` +-- TEST1_ID=`ubuntu` +-- TEST1_ID_LIKE=`debian` +-- TEST1_NAME=`Ubuntu` +-- TEST1_PRETTY_NAME=`Ubuntu 20\.04\.2 LTS` +-- TEST1_PRIVACY_POLICY_URL=`https://www\.ubuntu\.com/legal/terms-and-policies/privacy-policy` +-- TEST1_SUPPORT_URL=`https://help\.ubuntu\.com/` +-- TEST1_UBUNTU_CODENAME=`focal` +-- TEST1_VERSION=`20\.04\.2 LTS \(Focal Fossa\)` +-- TEST1_VERSION_CODENAME=`focal` +-- TEST1_VERSION_ID=`20\.04` +-- TEST2_ID=`ubuntu` +-- TEST2_VERSION=`20\.04\.2 LTS \(Focal Fossa\)` diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake new file mode 100644 index 00000000000..7fc26d812a6 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake @@ -0,0 +1,11 @@ +cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS TEST1) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() + +# Query individual variables +cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION) +list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION) +message(STATUS "TEST2_ID=`${TEST2_ID}`") +message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`") diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release new file mode 100644 index 00000000000..f228f222644 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release @@ -0,0 +1,12 @@ +NAME="Ubuntu" +VERSION="20.04.2 LTS (Focal Fossa)" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu 20.04.2 LTS" +VERSION_ID="20.04" +HOME_URL="https://www.ubuntu.com/" +SUPPORT_URL="https://help.ubuntu.com/" +BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" +PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" +VERSION_CODENAME=focal +UBUNTU_CODENAME=focal diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt new file mode 100644 index 00000000000..db6f48760cb --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt @@ -0,0 +1,7 @@ +-- UNIT_TEST_A_LIST_LIKE_VARIABLE=`satu;dua;tiga` +-- UNIT_TEST_DBL_QUOTED_VALUE=`"The" value in double "quotes"` +-- UNIT_TEST_DBL_QUOTED_VALUE_STIPPED_COMMENT=`Blah blah blah` +-- UNIT_TEST_NON_SPACE_VALUE=`Blah-blah-blah` +-- UNIT_TEST_QUOTED_VALUE=`'The' value in single 'quotes'` +-- UNIT_TEST_QUOTED_VALUE_STIPPED_COMMENT=`The value in single quotes` +-- UNIT_TEST_THE_URL_WITH_ANCHOR_TEST=`https://blah.blah/resource#anchor` diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake new file mode 100644 index 00000000000..d9a0acae84a --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT UNIT_TEST QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS UNIT_TEST) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release new file mode 100644 index 00000000000..66c33b5992e --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release @@ -0,0 +1,9 @@ +# Comment string gonna be ignored +NON_SPACE_VALUE=Blah-blah-blah +QUOTED_VALUE='\'The\' value in single \'quotes\'' +QUOTED_VALUE_STIPPED_COMMENT='The value in single quotes'# The comment right after `'` +DBL_QUOTED_VALUE="\"The\" value in double \"quotes\"" +DBL_QUOTED_VALUE_STIPPED_COMMENT="Blah blah blah"# The comment right after `'` +THE_URL_WITH_ANCHOR_TEST="https://blah.blah/resource#anchor" # And a comment after +A_LIST_LIKE_VARIABLE='satu;dua;tiga' +INCORRECT_ESCAPE_IGNORED=\'This line gonna be ignored' From efe139d1b835d126d7280d5bf615fe8149f923e5 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 3 Aug 2021 16:49:02 +0300 Subject: [PATCH 1134/1519] cmake_host_system_information: Can run fallback scripts --- .../command/cmake_host_system_information.rst | 67 ++++++++++++++ .../Internal/OSRelease/010-TryOldCentOS.cmake | 41 +++++++++ .../OSRelease/020-TryDebianVersion.cmake | 38 ++++++++ .../cmCMakeHostSystemInformationCommand.cxx | 92 ++++++++++++++++++- .../000-FirstFallbackScript.cmake | 1 + .../999-LastFallbackScript.cmake | 21 +++++ .../CentOS6-stdout.txt | 6 ++ .../CentOS6.cmake | 5 + .../CentOS6/etc/centos-release | 1 + .../Debian6-stdout.txt | 4 + .../Debian6.cmake | 5 + .../Debian6/etc/debian_version | 1 + .../RunCMakeTest.cmake | 5 + .../UserFallbackScript-stderr.txt | 5 + .../UserFallbackScript-stdout.txt | 6 ++ .../UserFallbackScript.cmake | 12 +++ 16 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 Modules/Internal/OSRelease/010-TryOldCentOS.cmake create mode 100644 Modules/Internal/OSRelease/020-TryDebianVersion.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/CentOS6.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release create mode 100644 Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/Debian6.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version create mode 100644 Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index ae24b0390e4..66249adedf2 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -176,8 +176,75 @@ system identification as described in the `man 5 os-release`_. -- DISTRO_VERSION_CODENAME=`focal` -- DISTRO_VERSION_ID=`20.04` +If :file:`/etc/os-release` file is not found, the command tries to gather OS +identification via fallback scripts. The fallback script can use `various +distribution-specific files`_ to collect OS identification data and map it +into `man 5 os-release`_ variables. + +Fallback Interface Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS + + In addition to the scripts shipped with CMake, a user may append full + paths to his script(s) to the this list. The script filename has the + following format: ``NNN-<name>.cmake``, where ``NNN`` is three digits + used to apply collected scripts in a specific order. + +.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname> + + Variables collected by the user provided fallback script + ought to be assigned to CMake variables using this naming + convention. Example, the ``ID`` variable from the manual becomes + ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID``. + +.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + + The fallback script ought to store names of all assigned + ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname>`` variables in this list. + +Example: + +.. code-block:: cmake + + # Try to detect some old distribution + # See also + # - http://linuxmafia.com/faq/Admin/release-files.html + # + if(NOT EXISTS "${CMAKE_SYSROOT}/etc/foobar-release") + return() + endif() + # Get the first string only + file( + STRINGS "${CMAKE_SYSROOT}/etc/foobar-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT + LIMIT_COUNT 1 + ) + # + # Example: + # + # Foobar distribution release 1.2.3 (server) + # + if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "Foobar distribution release ([0-9\.]+) .*") + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Foobar) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}") + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID foobar) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1}) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1}) + list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) + endif() + unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT) + + .. rubric:: Footnotes .. [#mebibytes] One MiB (mebibyte) is equal to 1024x1024 bytes. .. _man 5 os-release: https://www.freedesktop.org/software/systemd/man/os-release.html +.. _various distribution-specific files: http://linuxmafia.com/faq/Admin/release-files.html diff --git a/Modules/Internal/OSRelease/010-TryOldCentOS.cmake b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake new file mode 100644 index 00000000000..ff358977f14 --- /dev/null +++ b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake @@ -0,0 +1,41 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Author: Alex Turbov + +if(NOT EXISTS "${CMAKE_SYSROOT}/etc/centos-release") + return() +endif() + +# Get the first string only +file( + STRINGS "${CMAKE_SYSROOT}/etc/centos-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT + LIMIT_COUNT 1 + ) + +# +# Example: +# CentOS release 6.10 (Final) +# +if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "CentOS release ([0-9\.]+) .*") + + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME CentOS) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}") + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID centos) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE rhel) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1}) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1}) + + list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) + +endif() + +unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT) diff --git a/Modules/Internal/OSRelease/020-TryDebianVersion.cmake b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake new file mode 100644 index 00000000000..8ebe19a725c --- /dev/null +++ b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake @@ -0,0 +1,38 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Author: Alex Turbov + +if(NOT EXISTS "${CMAKE_SYSROOT}/etc/debian_version") + return() +endif() + +# Get the first string only +file( + STRINGS "${CMAKE_SYSROOT}/etc/debian_version" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT + LIMIT_COUNT 1 + ) + +# +# Example: +# 6.0.10 # Old debian +# wheezy/sid # Ubuntu +# +if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "[0-9]+(\.[0-9]+)*") + + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Debian) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID debian) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}) + + list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) + +endif() + +unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index cdd6b4c3288..90240a1b6c4 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeHostSystemInformationCommand.h" +#include <algorithm> #include <cassert> #include <cctype> #include <initializer_list> @@ -15,6 +16,7 @@ #include <cmext/string_view> #include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include "cmsys/SystemInformation.hxx" #include "cmExecutionStatus.h" @@ -259,8 +261,8 @@ cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine( std::map<std::string, std::string> GetOSReleaseVariables( cmExecutionStatus& status) { - const auto& sysroot = - status.GetMakefile().GetSafeDefinition("CMAKE_SYSROOT"); + auto& makefile = status.GetMakefile(); + const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT"); std::map<std::string, std::string> data; // Based on @@ -278,6 +280,92 @@ std::map<std::string, std::string> GetOSReleaseVariables( break; } } + // Got smth? + if (!data.empty()) { + return data; + } + + // Ugh, it could be some pre-os-release distro. + // Lets try some fallback getters. + + // 1. CMake provided + cmsys::Glob gl; + std::vector<std::string> scripts; + auto const findExpr = cmStrCat(cmSystemTools::GetCMakeRoot(), + "/Modules/Internal/OSRelease/*.cmake"); + if (gl.FindFiles(findExpr)) { + scripts = gl.GetFiles(); + } + + // 2. User provided (append to the CMake prvided) + makefile.GetDefExpandList("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS", scripts); + + // Filter out files that are not in format `NNN-name.cmake` + auto checkName = [](std::string const& filepath) -> bool { + auto const& filename = cmSystemTools::GetFilenameName(filepath); + // NOTE Minimum filename length expected: + // NNN-<at-least-one-char-name>.cmake --> 11 + return (filename.size() < 11) || !std::isdigit(filename[0]) || + !std::isdigit(filename[1]) || !std::isdigit(filename[2]) || + filename[3] != '-'; + }; + scripts.erase(std::remove_if(scripts.begin(), scripts.end(), checkName), + scripts.end()); + + // Make sure scripts are running in desired order + std::sort(scripts.begin(), scripts.end(), + [](std::string const& lhs, std::string const& rhs) -> bool { + long lhs_order; + cmStrToLong(cmSystemTools::GetFilenameName(lhs).substr(0u, 3u), + &lhs_order); + long rhs_order; + cmStrToLong(cmSystemTools::GetFilenameName(rhs).substr(0u, 3u), + &rhs_order); + return lhs_order < rhs_order; + }); + + // Name of the variable to put the results + auto const result_variable = "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT"_s; + + for (auto const& script : scripts) { + // Unset the result variable + makefile.RemoveDefinition(result_variable.data()); + + // include FATAL_ERROR and ERROR in the return status + if (!makefile.ReadListFile(script) || + cmSystemTools::GetErrorOccuredFlag()) { + // Ok, no worries... go try the next script. + continue; + } + + std::vector<std::string> variables; + if (!makefile.GetDefExpandList(result_variable.data(), variables)) { + // Heh, this script didn't found anything... go try the next one. + continue; + } + + for (auto const& variable : variables) { + auto value = makefile.GetSafeDefinition(variable); + makefile.RemoveDefinition(variable); + + if (!cmHasPrefix(variable, cmStrCat(result_variable, '_'))) { + // Ignore unknown variable set by the script + continue; + } + + auto key = variable.substr(result_variable.size() + 1, + variable.size() - result_variable.size() - 1); + data.emplace(std::move(key), std::move(value)); + } + + if (!data.empty()) { + // Try 'till some script can get anything + break; + } + } + + makefile.RemoveDefinition(result_variable.data()); + return data; } diff --git a/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake new file mode 100644 index 00000000000..ad873eb2939 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake @@ -0,0 +1 @@ +message(WARNING "The warning text to match just to make sure the script get executed") diff --git a/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake new file mode 100644 index 00000000000..08d8da80d43 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake @@ -0,0 +1,21 @@ +if(DEFINED CMAKE_GET_OS_RELEASE_FALLBACK_RESULT) + message(FATAL_ERROR "The `CMAKE_GET_OS_RELEASE_FALLBACK_RESULT` expected to be unset at this moment") +endif() + +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME UnitTest) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "Just a Unit Test") +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID unittest) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE nothing) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION 0.0.1) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID 0.0.1) + +list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME + IGNORED_VARIABLE_NAME_WHICH_IS_NOT_STARTED_WITH_EXPECTED_PREFIX + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt new file mode 100644 index 00000000000..803ee086894 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt @@ -0,0 +1,6 @@ +-- CENTOS6_ID=`centos` +-- CENTOS6_ID_LIKE=`rhel` +-- CENTOS6_NAME=`CentOS` +-- CENTOS6_PRETTY_NAME=`CentOS release 6\.10 \(Final\)` +-- CENTOS6_VERSION=`6\.10` +-- CENTOS6_VERSION_ID=`6\.10` diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake new file mode 100644 index 00000000000..3bc632b9b9e --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT CENTOS6 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS CENTOS6) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release new file mode 100644 index 00000000000..294ccc9f806 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release @@ -0,0 +1 @@ +CentOS release 6.10 (Final) diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt new file mode 100644 index 00000000000..60d64254396 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt @@ -0,0 +1,4 @@ +-- DEBIAN6_ID=`debian` +-- DEBIAN6_NAME=`Debian` +-- DEBIAN6_VERSION=`6\.0\.10` +-- DEBIAN6_VERSION_ID=`6\.0\.10` diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6.cmake b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake new file mode 100644 index 00000000000..cbf83a9f1f6 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT DEBIAN6 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS DEBIAN6) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version new file mode 100644 index 00000000000..c7d48f048d3 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version @@ -0,0 +1 @@ +6.0.10 diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index 6cbb7fd39b4..7462f7a060b 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -13,4 +13,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") run_cmake_with_options(Exherbo) run_cmake_with_options(Ubuntu) + run_cmake_with_options(CentOS6) + run_cmake_with_options(Debian6) + + run_cmake_with_options(UserFallbackScript) + endif() diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt new file mode 100644 index 00000000000..78acea2b40b --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning at 000-FirstFallbackScript\.cmake:[0-9]+ \(message\): + The warning text to match just to make sure the script get executed +Call Stack \(most recent call first\): + UserFallbackScript\.cmake:[0-9]+ \(cmake_host_system_information\) + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt new file mode 100644 index 00000000000..afcc000bb1f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt @@ -0,0 +1,6 @@ +-- UFS_ID=`unittest` +-- UFS_ID_LIKE=`nothing` +-- UFS_NAME=`UnitTest` +-- UFS_PRETTY_NAME=`Just a Unit Test` +-- UFS_VERSION=`0\.0\.1` +-- UFS_VERSION_ID=`0\.0\.1` diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake new file mode 100644 index 00000000000..660aa1ca313 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake @@ -0,0 +1,12 @@ +list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS + ${CMAKE_CURRENT_SOURCE_DIR}/000-FirstFallbackScript.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/Ignored-Script.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/999-LastFallbackScript.cmake + ) + +cmake_host_system_information(RESULT UFS QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS UFS) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() From 6c92f80f2ecb106916534d4b88704432476b9006 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Thu, 29 Jul 2021 21:32:26 +0300 Subject: [PATCH 1135/1519] cmake_host_system_information: Also set `USED_FALLBACK_SCRIPT` If the OS identification was obtained via fallback script. --- Source/cmCMakeHostSystemInformationCommand.cxx | 5 ++++- .../cmake_host_system_information/CentOS6-stdout.txt | 1 + .../cmake_host_system_information/Debian6-stdout.txt | 1 + .../UserFallbackScript-stdout.txt | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 90240a1b6c4..146422087df 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -287,6 +287,8 @@ std::map<std::string, std::string> GetOSReleaseVariables( // Ugh, it could be some pre-os-release distro. // Lets try some fallback getters. + // See also: + // - http://linuxmafia.com/faq/Admin/release-files.html // 1. CMake provided cmsys::Glob gl; @@ -358,8 +360,9 @@ std::map<std::string, std::string> GetOSReleaseVariables( data.emplace(std::move(key), std::move(value)); } + // Try 'till some script can get anything if (!data.empty()) { - // Try 'till some script can get anything + data.emplace("USED_FALLBACK_SCRIPT", script); break; } } diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt index 803ee086894..50dbb087615 100644 --- a/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt @@ -2,5 +2,6 @@ -- CENTOS6_ID_LIKE=`rhel` -- CENTOS6_NAME=`CentOS` -- CENTOS6_PRETTY_NAME=`CentOS release 6\.10 \(Final\)` +-- CENTOS6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/010-TryOldCentOS.cmake` -- CENTOS6_VERSION=`6\.10` -- CENTOS6_VERSION_ID=`6\.10` diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt index 60d64254396..4193d6f5e4f 100644 --- a/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt +++ b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt @@ -1,4 +1,5 @@ -- DEBIAN6_ID=`debian` -- DEBIAN6_NAME=`Debian` +-- DEBIAN6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/020-TryDebianVersion.cmake` -- DEBIAN6_VERSION=`6\.0\.10` -- DEBIAN6_VERSION_ID=`6\.0\.10` diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt index afcc000bb1f..acaf47e6955 100644 --- a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt @@ -2,5 +2,6 @@ -- UFS_ID_LIKE=`nothing` -- UFS_NAME=`UnitTest` -- UFS_PRETTY_NAME=`Just a Unit Test` +-- UFS_USED_FALLBACK_SCRIPT=`.*/999-LastFallbackScript\.cmake` -- UFS_VERSION=`0\.0\.1` -- UFS_VERSION_ID=`0\.0\.1` From 5469c71a824880eb646a0003cb001c58f24f9cce Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Fri, 30 Jul 2021 03:49:56 +0300 Subject: [PATCH 1136/1519] Refactor: Simplify `GetValue()` function calls --- .../cmCMakeHostSystemInformationCommand.cxx | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 146422087df..b2c45343881 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -439,6 +439,21 @@ cm::optional<std::string> GetValue(cmExecutionStatus& status, return {}; } #endif + +cm::optional<std::string> GetValueChained() +{ + return {}; +} + +template <typename GetterFn, typename... Next> +cm::optional<std::string> GetValueChained(GetterFn current, Next... chain) +{ + auto value = current(); + if (value.has_value()) { + return value; + } + return GetValueChained(chain...); +} // END Private functions } // anonymous namespace @@ -475,24 +490,21 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, result_list += DELIM[!result_list.empty()]; auto const& key = args[i]; - auto value = GetValue(info, key); - if (!value) { + // clang-format off + auto value = + GetValueChained( + [&]() { return GetValue(info, key); } +#ifdef __linux__ + , [&]() { return GetValue(status, key, variable); } +#endif #ifdef HAVE_VS_SETUP_HELPER - value = GetValue(status, key); - if (!value) { - status.SetError("does not recognize <key> " + key); - return false; - } -#elif defined(__linux__) - value = GetValue(status, key, variable); - if (!value) { - status.SetError("does not recognize <key> " + key); - return false; - } -#else + , [&]() { return GetValue(status, key); } +#endif + ); + // clang-format on + if (!value) { status.SetError("does not recognize <key> " + key); return false; -#endif } result_list += value.value(); } From b9698f89df275a33b01cfc7b4f88a510ad9d8bbe Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Tue, 3 Aug 2021 20:24:59 +0300 Subject: [PATCH 1137/1519] cmake_host_system_information: Make it available for all systems Before it was Linux only. --- Help/command/cmake_host_system_information.rst | 6 ++---- Source/cmCMakeHostSystemInformationCommand.cxx | 4 ---- Tests/RunCMake/CMakeLists.txt | 2 +- .../RunCMakeTest.cmake | 16 ++++++---------- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index 66249adedf2..998e1467429 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -132,9 +132,6 @@ queried. The list of queried values is stored in ``<variable>``. See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` -For Linux distributions additional ``<key>`` values are available to get operating -system identification as described in the `man 5 os-release`_. - ``DISTRIB_INFO`` .. versionadded:: 3.22 @@ -144,7 +141,8 @@ system identification as described in the `man 5 os-release`_. ``DISTRIB_<name>`` .. versionadded:: 3.22 - Get the ``<name>`` variable if it exists in the :file:`/etc/os-release` file + Get the ``<name>`` variable (see `man 5 os-release`_) if it exists in the + :file:`/etc/os-release` file Example: diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index b2c45343881..74071ff4f29 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -149,7 +149,6 @@ cm::optional<std::string> GetValue(cmsys::SystemInformation& info, return {}; } -#ifdef __linux__ cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine( std::string const& line) { @@ -407,7 +406,6 @@ cm::optional<std::string> GetValue(cmExecutionStatus& status, // NOTE Empty string means requested variable not set return std::string{}; } -#endif #ifdef HAVE_VS_SETUP_HELPER cm::optional<std::string> GetValue(cmExecutionStatus& status, @@ -494,9 +492,7 @@ bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, auto value = GetValueChained( [&]() { return GetValue(info, key); } -#ifdef __linux__ , [&]() { return GetValue(status, key, variable); } -#endif #ifdef HAVE_VS_SETUP_HELPER , [&]() { return GetValue(status, key); } #endif diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 543ad1d77b5..eb2c2d94ae1 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -349,7 +349,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() add_RunCMake_test(execute_process) add_RunCMake_test(export) -add_RunCMake_test(cmake_host_system_information -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) +add_RunCMake_test(cmake_host_system_information) add_RunCMake_test(cmake_language) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(cmake_parse_arguments) diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index 7462f7a060b..189013f84f6 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -7,15 +7,11 @@ run_cmake(BadArg3) run_cmake(QueryList) run_cmake(QueryKeys) -if (CMAKE_SYSTEM_NAME MATCHES "Linux") +run_cmake(UnitTest) +run_cmake(Exherbo) +run_cmake(Ubuntu) - run_cmake_with_options(UnitTest) - run_cmake_with_options(Exherbo) - run_cmake_with_options(Ubuntu) +run_cmake(CentOS6) +run_cmake(Debian6) - run_cmake_with_options(CentOS6) - run_cmake_with_options(Debian6) - - run_cmake_with_options(UserFallbackScript) - -endif() +run_cmake(UserFallbackScript) From e2c06736e54d9160e49d5a67f5c10ca601ab31ed Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 19 Aug 2021 10:49:43 -0400 Subject: [PATCH 1138/1519] libarchive: Add missing cm3p prefixes on includes Issue: #20666 --- .../cmlibarchive/libarchive/archive_read_support_format_xar.c | 2 +- .../cmlibarchive/libarchive/archive_read_support_format_zip.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c index 9489e510603..bcb67fe9814 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #elif HAVE_BSDXML_H #include <bsdxml.h> #elif HAVE_EXPAT_H -#include <expat.h> +#include <cm3p/expat.h> #endif #ifdef HAVE_BZLIB_H #include <cm3p/bzlib.h> diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index 4d71f985a2d..62f98a4fd98 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@ -53,10 +53,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 #include <cm3p/zlib.h> #endif #ifdef HAVE_BZLIB_H -#include <bzlib.h> +#include <cm3p/bzlib.h> #endif #ifdef HAVE_LZMA_H -#include <lzma.h> +#include <cm3p/lzma.h> #endif #include "archive.h" From 20fec1520458cdfb71bf1099cfc3648154d57d8f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 20 Aug 2021 11:23:20 -0400 Subject: [PATCH 1139/1519] cmArchiveWrite: Check for construction errors on Open Also update call sites to report the error. Issue: #19666 --- Source/CPack/cmCPackDebGenerator.cxx | 24 +++++++++++++++++++++--- Source/cmArchiveWrite.cxx | 3 +++ Source/cmSystemTools.cxx | 5 ++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 5f0f153b3e7..829cef4ec4d 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -192,7 +192,13 @@ bool DebGenerator::generateDataTar() const cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType, this->DebianArchiveType, 0, static_cast<int>(this->NumThreads)); - data_tar.Open(); + if (!data_tar.Open()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the archive \"" + << filename_data_tar + << "\", ERROR = " << data_tar.GetError() << std::endl); + return false; + } // uid/gid should be the one of the root user, and this root user has // always uid/gid equal to 0. @@ -317,7 +323,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const cmArchiveWrite control_tar(fileStream_control_tar, cmArchiveWrite::CompressGZip, this->DebianArchiveType); - control_tar.Open(); + if (!control_tar.Open()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the archive \"" + << filename_control_tar + << "\", ERROR = " << control_tar.GetError() << std::endl); + return false; + } // sets permissions and uid/gid for the files control_tar.SetUIDAndGID(0u, 0u); @@ -457,7 +469,13 @@ bool DebGenerator::generateDeb() const cmGeneratedFileStream debStream; debStream.Open(outputPath, false, true); cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd"); - deb.Open(); + if (!deb.Open()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the archive \"" + << outputPath << "\", ERROR = " << deb.GetError() + << std::endl); + return false; + } // uid/gid should be the one of the root user, and this root user has // always uid/gid equal to 0. diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 54b29982468..9e0d80c0942 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -250,6 +250,9 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, bool cmArchiveWrite::Open() { + if (!this->Error.empty()) { + return false; + } if (archive_write_open( this->Archive, this, nullptr, reinterpret_cast<archive_write_callback*>(&Callback::Write), diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index f082ae84bbf..54fe7a14a5e 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1629,7 +1629,10 @@ bool cmSystemTools::CreateTar(const std::string& outFileName, cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format, compressionLevel); - a.Open(); + if (!a.Open()) { + cmSystemTools::Error(a.GetError()); + return false; + } a.SetMTime(mtime); a.SetVerbose(verbose); bool tarCreatedSuccessfully = true; From 78f758a463516a78a9ec8d472080c6e61cb89c7f Mon Sep 17 00:00:00 2001 From: Bradley Bell <bradleyb@uw.edu> Date: Fri, 20 Aug 2021 20:20:01 -0700 Subject: [PATCH 1140/1519] Use dashes for MASM flags Microsoft's tools traditionally uses slashes, but accept dashes as well. If we use dashes, it becomes possible to use an alternative MASM-compatible assembler such as JWasm. --- Modules/CMakeASM_MASMInformation.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeASM_MASMInformation.cmake b/Modules/CMakeASM_MASMInformation.cmake index 6d1e174e38c..656b75e7d99 100644 --- a/Modules/CMakeASM_MASMInformation.cmake +++ b/Modules/CMakeASM_MASMInformation.cmake @@ -8,7 +8,7 @@ set(ASM_DIALECT "_MASM") set(CMAKE_ASM${ASM_DIALECT}_SOURCE_FILE_EXTENSIONS asm) -set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> /c /Fo <OBJECT> <SOURCE>") +set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -c -Fo <OBJECT> <SOURCE>") # The ASM_MASM compiler id for this compiler is "MSVC", so fill out the runtime library table. set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "") From bf09145eb0cfc80068441631d0b106cc7948cff3 Mon Sep 17 00:00:00 2001 From: Bradley Bell <bradleyb@uw.edu> Date: Fri, 20 Aug 2021 20:20:37 -0700 Subject: [PATCH 1141/1519] Enable Watcom WMake generator on Darwin Open Watcom v2 runs on Mac OS and is useful there for doing cross-compilation. --- Source/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 791871e12c5..2e57a16a5f6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -803,7 +803,7 @@ if (WIN32) endif () # Watcom support -if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux") +if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") set_property(SOURCE cmake.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_USE_WMAKE) list(APPEND SRCS cmGlobalWatcomWMakeGenerator.cxx From b76bf671d00653b46747d5317af251ceeb180b83 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 21 Aug 2021 00:01:12 -0400 Subject: [PATCH 1142/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 591bc0c5231..090a193dcf4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210820) +set(CMake_VERSION_PATCH 20210821) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f28889ace73280f987a69259a07755103758a2a9 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 22 Aug 2021 00:01:10 -0400 Subject: [PATCH 1143/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 090a193dcf4..fd70311be2a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210821) +set(CMake_VERSION_PATCH 20210822) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 49a5dbcaff57da133aadd7a31abdd65515b426e6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Sun, 22 Aug 2021 12:35:56 -0400 Subject: [PATCH 1144/1519] GNUInstallDirs: avoid unwanted variable dereference In some situations, it seems that the variable `0` is defined. In the case found, it was set to `1`. This makes the detection of the missing third argument bogus and unnecessarily triggers a warning. This oversight was introduced in 229b5ee994 (GNUInstallDirs: Add dir argument to GNUInstallDirs_get_absolute_install_dir, 2020-10-31) prior to CMake 3.20's release cycle. --- Modules/GNUInstallDirs.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index e149f4c5aa5..4016a64888f 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -349,7 +349,7 @@ mark_as_advanced( macro(GNUInstallDirs_get_absolute_install_dir absvar var) set(GGAID_extra_args ${ARGN}) list(LENGTH GGAID_extra_args GGAID_extra_arg_count) - if(GGAID_extra_arg_count GREATER 0) + if(GGAID_extra_arg_count GREATER "0") list(GET GGAID_extra_args 0 GGAID_dir) else() # Historical behaviour: use ${dir} from caller's scope From 670e4bd9e9d963a90f30661672efe30dd708be22 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 23 Aug 2021 00:01:20 -0400 Subject: [PATCH 1145/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fd70311be2a..57f0d65e01f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210822) +set(CMake_VERSION_PATCH 20210823) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e802193a34210d1d8c7d8b4201c2afa9f125ff74 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 23 Aug 2021 00:18:46 +1000 Subject: [PATCH 1146/1519] Help: Rework docs to prioritize FetchContent_MakeAvailable() FetchContent_MakeAvailable() should be strongly preferred over the direct use of FetchContent_Populate(). The latter was the only method available before CMake 3.14, but the former is simpler and offers more functionality. Restructure the docs and improve the wording to steer the reader toward `FetchContent_MakeAvailable()` as the preferred approach. Also take the opportunity to pull out the variables that influence behavior into their own section. They were easily missed when buried in the docs for the FetchContent_Populate() command. --- Modules/FetchContent.cmake | 452 +++++++++++++++++++++---------------- 1 file changed, 252 insertions(+), 200 deletions(-) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index bd82a90e1d9..5ea8b2a92cc 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -21,13 +21,14 @@ supported by the :module:`ExternalProject` module. Whereas configure step to use the content in commands like :command:`add_subdirectory`, :command:`include` or :command:`file` operations. -Content population details would normally be defined separately from the -command that performs the actual population. This separation ensures that -all of the dependency details are defined before anything may try to use those -details to populate content. This is particularly important in more complex -project hierarchies where dependencies may be shared between multiple projects. +Content population details should be defined separately from the command that +performs the actual population. This separation ensures that all the +dependency details are defined before anything might try to use them to +populate content. This is particularly important in more complex project +hierarchies where dependencies may be shared between multiple projects. -The following shows a typical example of declaring content details: +The following shows a typical example of declaring content details for some +dependencies and then ensuring they are populated with a separate call: .. code-block:: cmake @@ -36,57 +37,67 @@ The following shows a typical example of declaring content details: GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 ) + FetchContent_Declare( + myCompanyIcons + URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz + URL_HASH MD5=5588a7b18261c20068beabfb4f530b87 + ) + + FetchContent_MakeAvailable(googletest secret_sauce) + +The :command:`FetchContent_MakeAvailable` command ensures the named +dependencies have been populated, either by an earlier call or by populating +them itself. When performing the population, it will also add them to the +main build, if possible, so that the main build can use the populated +projects' targets, etc. See the command's documentation for how these steps +are performed. + +When using a hierarchical project arrangement, projects at higher levels in +the hierarchy are able to override the declared details of content specified +anywhere lower in the project hierarchy. The first details to be declared +for a given dependency take precedence, regardless of where in the project +hierarchy that occurs. Similarly, the first call that tries to populate a +dependency "wins", with subsequent populations reusing the result of the +first instead of repeating the population again. +See the :ref:`Examples <fetch-content-examples>` which demonstrate +this scenario. -For most typical cases, populating the content can then be done with a single -command like so: +In some cases, the main project may need to have more precise control over +the population, or it may be required to explicitly define the population +steps in a way that cannot be captured by the declared details alone. +For such situations, the lower level :command:`FetchContent_GetProperties` and +:command:`FetchContent_Populate` commands can be used. These lack the richer +features provided by :command:`FetchContent_MakeAvailable` though, so their +direct use should be considered a last resort. The typical pattern of such +custom steps looks like this: .. code-block:: cmake - FetchContent_MakeAvailable(googletest) + # NOTE: Where possible, prefer to use FetchContent_MakeAvailable() + # instead of custom logic like this -The above command not only populates the content, it also adds it to the main -build (if possible) so that the main build can use the populated project's -targets, etc. In some cases, the main project may need to have more precise -control over the population or may be required to explicitly define the -population steps (e.g. if CMake versions earlier than 3.14 need to be -supported). The typical pattern of such custom steps looks like this: + # Check if population has already been performed + FetchContent_GetProperties(depname) + if(NOT depname_POPULATED) + # Fetch the content using previously declared details + FetchContent_Populate(depname) -.. code-block:: cmake + # Set custom variables, policies, etc. + # ... - FetchContent_GetProperties(googletest) - if(NOT googletest_POPULATED) - FetchContent_Populate(googletest) - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + # Bring the populated content into the build + add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR}) endif() -Regardless of which population method is used, when using the -declare-populate pattern with a hierarchical project arrangement, projects at -higher levels in the hierarchy are able to override the population details of -content specified anywhere lower in the project hierarchy. The ability to -detect whether content has already been populated ensures that even if -multiple child projects want certain content to be available, the first one -to populate it wins. The other child project can simply make use of the -already available content instead of repeating the population for itself. -See the :ref:`Examples <fetch-content-examples>` section which demonstrates -this scenario. - The ``FetchContent`` module also supports defining and populating content in a single call, with no check for whether the content has been -populated elsewhere in the project already. This is a more low level -operation and would not normally be the way the module is used, but it is -sometimes useful as part of implementing some higher level feature or to -populate some content in CMake's script mode. - -.. versionchanged:: 3.14 - ``FetchContent`` commands can access the terminal. This is necessary - for password prompts and real-time progress displays to work. +populated elsewhere already. This should not be done in projects, but may +be appropriate for populating content in CMake's script mode. +See :command:`FetchContent_Populate` for details. Commands ^^^^^^^^ -Declaring Content Details -""""""""""""""""""""""""" - .. command:: FetchContent_Declare .. code-block:: cmake @@ -94,7 +105,7 @@ Declaring Content Details FetchContent_Declare(<name> <contentOptions>...) The ``FetchContent_Declare()`` function records the options that describe - how to populate the specified content, but if such details have already + how to populate the specified content. If such details have already been recorded earlier in this project (regardless of where in the project hierarchy), this and all later calls for the same content ``<name>`` are ignored. This "first to record, wins" approach is what allows hierarchical @@ -110,7 +121,7 @@ Declaring Content Details projects needing that same content will use the same name, leading to the content being populated multiple times. - The ``<contentOptions>`` can be any of the download or update/patch options + The ``<contentOptions>`` can be any of the download, update or patch options that the :command:`ExternalProject_Add` command understands. The configure, build, install and test steps are explicitly disabled and therefore options related to them will be ignored. The ``SOURCE_SUBDIR`` option is an @@ -146,47 +157,88 @@ Declaring Content Details than a branch or tag name. A commit hash is more secure and helps to confirm that the downloaded contents are what you expected. -Populating The Content -"""""""""""""""""""""" + .. versionchanged:: 3.14 + Commands for the download, update or patch steps can access the terminal. + This may be needed for things like password prompts or real-time display + of command progress. -For most common scenarios, population means making content available to the -main build according to previously declared details for that dependency. -There are two main patterns for populating content, one based on calling -:command:`FetchContent_GetProperties` and -:command:`FetchContent_Populate` for more precise control and the other on -calling :command:`FetchContent_MakeAvailable` for a simpler, more automated -approach. The former generally follows this canonical pattern: +.. command:: FetchContent_MakeAvailable -.. _`fetch-content-canonical-pattern`: + .. versionadded:: 3.14 -.. code-block:: cmake + .. code-block:: cmake - # Check if population has already been performed - FetchContent_GetProperties(<name>) - string(TOLOWER "<name>" lcName) - if(NOT ${lcName}_POPULATED) - # Fetch the content using previously declared details - FetchContent_Populate(<name>) + FetchContent_MakeAvailable(<name1> [<name2>...]) + + This command ensures that each of the named dependencies are populated and + potentially added to the build by the time it returns. It iterates over + the list, and for each dependency, the following logic is applied: + + * If the dependency has already been populated earlier in this run, set + the ``<lowercaseName>_POPULATED``, ``<lowercaseName>_SOURCE_DIR`` and + ``<lowercaseName>_BINARY_DIR`` variables in the same way as a call to + :command:`FetchContent_GetProperties`, then skip the remaining steps + below and move on to the next dependency in the list. + + * Call :command:`FetchContent_Populate` to populate the dependency using + the details recorded by an earlier call to :command:`FetchContent_Declare`. + Halt with a fatal error if no such details have been recorded. + :variable:`FETCHCONTENT_SOURCE_DIR_<uppercaseName>` can be used to override + the declared details and use content provided at the specified location + instead. + + * If the top directory of the populated content contains a ``CMakeLists.txt`` + file, call :command:`add_subdirectory` to add it to the main build. + It is not an error for there to be no ``CMakeLists.txt`` file, which + allows the command to be used for dependencies that make downloaded + content available at a known location, but which do not need or support + being added directly to the build. + + .. versionadded:: 3.18 + The ``SOURCE_SUBDIR`` option can be given in the declared details to + look somewhere below the top directory instead (i.e. the same way that + ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add` + command). The path provided with ``SOURCE_SUBDIR`` must be relative + and will be treated as relative to the top directory. It can also + point to a directory that does not contain a ``CMakeLists.txt`` file + or even to a directory that doesn't exist. This can be used to avoid + adding a project that contains a ``CMakeLists.txt`` file in its top + directory. + + Projects should aim to declare the details of all dependencies they might + use before they call ``FetchContent_MakeAvailable()`` for any of them. + This ensures that if any of the dependencies are also sub-dependencies of + one or more of the others, the main project still controls the details + that will be used (because it will declare them first before the + dependencies get a chance to). In the following code samples, assume that + the ``uses_other`` dependency also uses ``FetchContent`` to add the ``other`` + dependency internally: - # Set custom variables, policies, etc. - # ... + .. code-block:: cmake - # Bring the populated content into the build - add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR}) - endif() + # WRONG: Should declare all details first + FetchContent_Declare(uses_other ...) + FetchContent_MakeAvailable(uses_other) + + FetchContent_Declare(other ...) # Will be ignored, uses_other beat us to it + FetchContent_MakeAvailable(other) # Would use details declared by uses_other -The above is such a common pattern that, where no custom steps are needed -between the calls to :command:`FetchContent_Populate` and -:command:`add_subdirectory`, equivalent logic can be obtained by calling -:command:`FetchContent_MakeAvailable` instead. Where it meets the needs of -the project, :command:`FetchContent_MakeAvailable` should be preferred, as it -is simpler and provides additional features over the pattern above. + .. code-block:: cmake + + # CORRECT: All details declared first, so they will take priority + FetchContent_Declare(uses_other ...) + FetchContent_Declare(other ...) + FetchContent_MakeAvailable(uses_other other) .. command:: FetchContent_Populate + .. note:: + Where possible, prefer to use :command:`FetchContent_MakeAvailable` + instead of implementing population manually with this command. + .. code-block:: cmake - FetchContent_Populate( <name> ) + FetchContent_Populate(<name>) In most cases, the only argument given to ``FetchContent_Populate()`` is the ``<name>``. When used this way, the command assumes the content details have @@ -211,88 +263,29 @@ is simpler and provides additional features over the pattern above. ``FetchContent_Populate()``. ``FetchContent_Populate()`` will set three variables in the scope of the - caller; ``<lcName>_POPULATED``, ``<lcName>_SOURCE_DIR`` and - ``<lcName>_BINARY_DIR``, where ``<lcName>`` is the lowercased ``<name>``. - ``<lcName>_POPULATED`` will always be set to ``True`` by the call. - ``<lcName>_SOURCE_DIR`` is the location where the - content can be found upon return (it will have already been populated), while - ``<lcName>_BINARY_DIR`` is a directory intended for use as a corresponding - build directory. The main use case for the two directory variables is to - call :command:`add_subdirectory` immediately after population, i.e.: + caller: + + ``<lowercaseName>_POPULATED`` + This will always be set to ``TRUE`` by the call. + + ``<lowercaseName>_SOURCE_DIR`` + The location where the populated content can be found upon return. + + ``<lowercaseName>_BINARY_DIR`` + A directory intended for use as a corresponding build directory. + + The main use case for the ``<lowercaseName>_SOURCE_DIR`` and + ``<lowercaseName>_BINARY_DIR`` variables is to call + :command:`add_subdirectory` immediately after population: .. code-block:: cmake - FetchContent_Populate(FooBar ...) + FetchContent_Populate(FooBar) add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) The values of the three variables can also be retrieved from anywhere in the project hierarchy using the :command:`FetchContent_GetProperties` command. - A number of cache variables influence the behavior of all content population - performed using details saved from a :command:`FetchContent_Declare` call: - - ``FETCHCONTENT_BASE_DIR`` - In most cases, the saved details do not specify any options relating to the - directories to use for the internal sub-build, final source and build areas. - It is generally best to leave these decisions up to the ``FetchContent`` - module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` - cache variable controls the point under which all content population - directories are collected, but in most cases developers would not need to - change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if - developers change this value, they should aim to keep the path short and - just below the top level of the build tree to avoid running into path - length problems on Windows. - - ``FETCHCONTENT_QUIET`` - The logging output during population can be quite verbose, making the - configure stage quite noisy. This cache option (``ON`` by default) hides - all population output unless an error is encountered. If experiencing - problems with hung downloads, temporarily switching this option off may - help diagnose which content population is causing the issue. - - ``FETCHCONTENT_FULLY_DISCONNECTED`` - When this option is enabled, no attempt is made to download or update - any content. It is assumed that all content has already been populated in - a previous run or the source directories have been pointed at existing - contents the developer has provided manually (using options described - further below). When the developer knows that no changes have been made to - any content details, turning this option ``ON`` can significantly speed up - the configure stage. It is ``OFF`` by default. - - ``FETCHCONTENT_UPDATES_DISCONNECTED`` - This is a less severe download/update control compared to - ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and - update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the - update stage. Therefore, if content has not been downloaded previously, - it will still be downloaded when this option is enabled. This can speed up - the configure stage, but not as much as - ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default. - - In addition to the above cache variables, the following cache variables are - also defined for each content name (``<ucName>`` is the uppercased value of - ``<name>``): - - ``FETCHCONTENT_SOURCE_DIR_<ucName>`` - If this is set, no download or update steps are performed for the specified - content and the ``<lcName>_SOURCE_DIR`` variable returned to the caller is - pointed at this location. This gives developers a way to have a separate - checkout of the content that they can modify freely without interference - from the build. The build simply uses that existing source, but it still - defines ``<lcName>_BINARY_DIR`` to point inside its own build area. - Developers are strongly encouraged to use this mechanism rather than - editing the sources populated in the default location, as changes to - sources in the default location can be lost when content population details - are changed by the project. - - ``FETCHCONTENT_UPDATES_DISCONNECTED_<ucName>`` - This is the per-content equivalent of - ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option - is ``ON``, then updates will be disabled for the named content. - Disabling updates for individual content can be useful for content whose - details rarely change, while still leaving other frequently changing - content with updates enabled. - - The ``FetchContent_Populate()`` command also supports a syntax allowing the content details to be specified directly rather than using any saved details. This is more low-level and use of this form is generally to be @@ -303,7 +296,8 @@ is simpler and provides additional features over the pattern above. .. code-block:: cmake - FetchContent_Populate( <name> + FetchContent_Populate( + <name> [QUIET] [SUBBUILD_DIR <subBuildDir>] [SOURCE_DIR <srcDir>] @@ -325,16 +319,17 @@ is simpler and provides additional features over the pattern above. - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored. - The ``<lcName>_SOURCE_DIR`` and ``<lcName>_BINARY_DIR`` variables are still - returned to the caller, but since these locations are not stored as global - properties when this form is used, they are only available to the calling - scope and below rather than the entire project hierarchy. No - ``<lcName>_POPULATED`` variable is set in the caller's scope with this form. + The ``<lowercaseName>_SOURCE_DIR`` and ``<lowercaseName>_BINARY_DIR`` + variables are still returned to the caller, but since these locations are + not stored as global properties when this form is used, they are only + available to the calling scope and below rather than the entire project + hierarchy. No ``<lowercaseName>_POPULATED`` variable is set in the caller's + scope with this form. The supported options for ``FetchContent_Populate()`` are the same as those for :command:`FetchContent_Declare()`. Those few options shown just above are either specific to ``FetchContent_Populate()`` or their behavior is - slightly modified from how :command:`ExternalProject_Add` treats them. + slightly modified from how :command:`ExternalProject_Add` treats them: ``QUIET`` The ``QUIET`` option can be given to hide the output associated with @@ -347,9 +342,9 @@ is simpler and provides additional features over the pattern above. ``SUBBUILD_DIR`` The ``SUBBUILD_DIR`` argument can be provided to change the location of the sub-build created to perform the population. The default value is - ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual - to need to override this default. If a relative path is specified, it will - be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. + ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-subbuild`` and it would be + unusual to need to override this default. If a relative path is specified, + it will be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. This option should not be confused with the ``SOURCE_SUBDIR`` option which only affects the :command:`FetchContent_MakeAvailable` command. @@ -357,9 +352,9 @@ is simpler and provides additional features over the pattern above. The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by :command:`ExternalProject_Add`, but different default values are used by ``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to - ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-src`` and ``BINARY_DIR`` defaults to - ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build``. If a relative path is - specified, it will be interpreted as relative to + ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-src`` and ``BINARY_DIR`` + defaults to ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-build``. + If a relative path is specified, it will be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. In addition to the above explicit options, any other unrecognized options are @@ -380,11 +375,12 @@ is simpler and provides additional features over the pattern above. on the command line invoking the script. .. versionadded:: 3.18 - Added support for ``DOWNLOAD_NO_EXTRACT`` and ``SOURCE_SUBDIR`` options. + Added support for the ``DOWNLOAD_NO_EXTRACT`` option. .. command:: FetchContent_GetProperties - When using saved content details, a call to :command:`FetchContent_Populate` + When using saved content details, a call to + :command:`FetchContent_MakeAvailable` or :command:`FetchContent_Populate` records information in global properties which can be queried at any time. This information includes the source and binary directories associated with the content and also whether or not the content population has been processed @@ -392,7 +388,8 @@ is simpler and provides additional features over the pattern above. .. code-block:: cmake - FetchContent_GetProperties( <name> + FetchContent_GetProperties( + <name> [SOURCE_DIR <srcDirVar>] [BINARY_DIR <binDirVar>] [POPULATED <doneVar>] @@ -403,49 +400,104 @@ is simpler and provides additional features over the pattern above. which is the name of the variable in which to store that property. Most of the time though, only ``<name>`` is given, in which case the call will then set the same variables as a call to - :command:`FetchContent_Populate(name) <FetchContent_Populate>`. This allows - the following canonical pattern to be used, which ensures that the relevant - variables will always be defined regardless of whether or not the population - has been performed elsewhere in the project already: - - .. code-block:: cmake - - FetchContent_GetProperties(foobar) - if(NOT foobar_POPULATED) - FetchContent_Populate(foobar) - ... - endif() + :command:`FetchContent_MakeAvailable(name) <FetchContent_MakeAvailable>` or + :command:`FetchContent_Populate(name) <FetchContent_Populate>`. - The above pattern allows other parts of the overall project hierarchy to - re-use the same content and ensure that it is only populated once. - - -.. command:: FetchContent_MakeAvailable + This command is rarely needed when using + :command:`FetchContent_MakeAvailable`. It is more commonly used as part of + implementing the following pattern with :command:`FetchContent_Populate`, + which ensures that the relevant variables will always be defined regardless + of whether or not the population has been performed elsewhere in the project + already: .. code-block:: cmake - FetchContent_MakeAvailable( <name1> [<name2>...] ) + # Check if population has already been performed + FetchContent_GetProperties(depname) + if(NOT depname_POPULATED) + # Fetch the content using previously declared details + FetchContent_Populate(depname) - .. versionadded:: 3.14 + # Set custom variables, policies, etc. + # ... - This command implements the common pattern typically needed for most - dependencies. It iterates over each of the named dependencies in turn - and for each one it loosely follows the - :ref:`canonical pattern <fetch-content-canonical-pattern>` as - presented at the beginning of this section. An important difference is - that :command:`add_subdirectory` will only be called on the - populated content if there is a ``CMakeLists.txt`` file in its top level - source directory. This allows the command to be used for dependencies - that make downloaded content available at a known location but which do - not need or support being added directly to the build. - - The ``SOURCE_SUBDIR`` option can be given in the declared details to - instruct ``FetchContent_MakeAvailable()`` to look for a ``CMakeLists.txt`` - file in a subdirectory below the top level (i.e. the same way that - ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add` command). - ``SOURCE_SUBDIR`` must always be a relative path. See the next section - for an example of this option. + # Bring the populated content into the build + add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR}) + endif() +Variables +^^^^^^^^^ + +A number of cache variables can influence the behavior where details from a +:command:`FetchContent_Declare` call are used to populate content. +The variables are all intended for the developer to customize behavior and +should not normally be set by the project. + +.. variable:: FETCHCONTENT_BASE_DIR + + In most cases, the saved details do not specify any options relating to the + directories to use for the internal sub-build, final source and build areas. + It is generally best to leave these decisions up to the ``FetchContent`` + module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` + cache variable controls the point under which all content population + directories are collected, but in most cases, developers would not need to + change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if + developers change this value, they should aim to keep the path short and + just below the top level of the build tree to avoid running into path + length problems on Windows. + +.. variable:: FETCHCONTENT_QUIET + + The logging output during population can be quite verbose, making the + configure stage quite noisy. This cache option (``ON`` by default) hides + all population output unless an error is encountered. If experiencing + problems with hung downloads, temporarily switching this option off may + help diagnose which content population is causing the issue. + +.. variable:: FETCHCONTENT_FULLY_DISCONNECTED + + When this option is enabled, no attempt is made to download or update + any content. It is assumed that all content has already been populated in + a previous run or the source directories have been pointed at existing + contents the developer has provided manually (using options described + further below). When the developer knows that no changes have been made to + any content details, turning this option ``ON`` can significantly speed up + the configure stage. It is ``OFF`` by default. + +.. variable:: FETCHCONTENT_UPDATES_DISCONNECTED + + This is a less severe download/update control compared to + :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. Instead of bypassing all + download and update logic, ``FETCHCONTENT_UPDATES_DISCONNECTED`` only + disables the update stage. Therefore, if content has not been downloaded + previously, it will still be downloaded when this option is enabled. + This can speed up the configure stage, but not as much as + :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. It is ``OFF`` by default. + +In addition to the above cache variables, the following cache variables are +also defined for each content name: + +.. variable:: FETCHCONTENT_SOURCE_DIR_<uppercaseName> + + If this is set, no download or update steps are performed for the specified + content and the ``<lowercaseName>_SOURCE_DIR`` variable returned to the + caller is pointed at this location. This gives developers a way to have a + separate checkout of the content that they can modify freely without + interference from the build. The build simply uses that existing source, + but it still defines ``<lowercaseName>_BINARY_DIR`` to point inside its own + build area. Developers are strongly encouraged to use this mechanism rather + than editing the sources populated in the default location, as changes to + sources in the default location can be lost when content population details + are changed by the project. + +.. variable:: FETCHCONTENT_UPDATES_DISCONNECTED_<uppercaseName> + + This is the per-content equivalent of + :variable:`FETCHCONTENT_UPDATES_DISCONNECTED`. If the global option or + this option is ``ON``, then updates will be disabled for the named content. + Disabling updates for individual content can be useful for content whose + details rarely change, while still leaving other frequently changing content + with updates enabled. .. _`fetch-content-examples`: @@ -470,7 +522,7 @@ frameworks are available to the main build: ) # After the following call, the CMake targets defined by googletest and - # Catch2 will be defined and available to the rest of the build + # Catch2 will be available to the rest of the build FetchContent_MakeAvailable(googletest Catch2) If the sub-project's ``CMakeLists.txt`` file is not at the top level of its From 0c0ba17493e11b409498b368156b0c6ab5e641cb Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" <ferdnyc@gmail.com> Date: Mon, 23 Aug 2021 17:26:43 -0400 Subject: [PATCH 1147/1519] Help: get/set_property: Fix SOURCE grammars --- Help/command/get_property.rst | 2 +- Help/command/set_property.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/command/get_property.rst b/Help/command/get_property.rst index f77d8af7858..46da2853b2c 100644 --- a/Help/command/get_property.rst +++ b/Help/command/get_property.rst @@ -9,7 +9,7 @@ Get a property. <GLOBAL | DIRECTORY [<dir>] | TARGET <target> | - SOURCE <source> | + SOURCE <source> [DIRECTORY <dir> | TARGET_DIRECTORY <target>] | INSTALL <file> | TEST <test> | diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst index bf437b43473..555520d227c 100644 --- a/Help/command/set_property.rst +++ b/Help/command/set_property.rst @@ -9,8 +9,8 @@ Set a named property in a given scope. DIRECTORY [<dir>] | TARGET [<target1> ...] | SOURCE [<src1> ...] - [DIRECTORY <dirs> ...] | - [TARGET_DIRECTORY <targets> ...] + [DIRECTORY <dirs> ...] + [TARGET_DIRECTORY <targets> ...] | INSTALL [<file1> ...] | TEST [<test1> ...] | CACHE [<entry1> ...] > From d7e521bcd325359a258492f8147b433a698de9a7 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" <ferdnyc@gmail.com> Date: Mon, 23 Aug 2021 20:02:08 -0400 Subject: [PATCH 1148/1519] Help: find_package: Tweak change description --- Help/command/find_package.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index bd2601007e6..490a5c74591 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -447,7 +447,7 @@ enabled. hard-coded guesses. .. versionadded:: 3.16 - Added the ``CMAKE_FIND_USE_<CATEGORY>_PATH`` variables to globally disable + Added the ``CMAKE_FIND_USE_<CATEGORY>`` variables to globally disable various search locations. .. |FIND_XXX| replace:: find_package From bf969eb4556fa767df83a2efad21ec5957463968 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 24 Aug 2021 00:01:10 -0400 Subject: [PATCH 1149/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 57f0d65e01f..d10822f4f33 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210823) +set(CMake_VERSION_PATCH 20210824) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1b8fefb50547713a1a8d1a7cd418469861714ec9 Mon Sep 17 00:00:00 2001 From: KWIML Upstream <kwrobot@kitware.com> Date: Fri, 20 Aug 2021 12:30:45 -0400 Subject: [PATCH 1150/1519] KWIML 2021-08-20 (9c534d2c) Code extracted from: https://gitlab.kitware.com/utils/kwiml.git at commit 9c534d2cc5c3fece4184e8eaeda6f30d419db601 (master). Upstream Shortlog ----------------- Brad King (1): 9c534d2c int.h: Record that MSVC provides inttypes.h since VS 2013 --- include/kwiml/int.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/kwiml/int.h b/include/kwiml/int.h index b2e14d5f28a..25a063aafde 100644 --- a/include/kwiml/int.h +++ b/include/kwiml/int.h @@ -162,7 +162,11 @@ An includer may test the following macros after inclusion: #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # define KWIML_INT_HAVE_INTTYPES_H 1 #elif defined(_MSC_VER) /* MSVC */ -# define KWIML_INT_NO_INTTYPES_H 1 +# if _MSC_VER >= 1800 +# define KWIML_INT_HAVE_INTTYPES_H 1 +# else +# define KWIML_INT_NO_INTTYPES_H 1 +# endif #elif defined(__BORLANDC__) /* Borland */ # define KWIML_INT_NO_INTTYPES_H 1 #elif defined(__WATCOMC__) /* Watcom */ @@ -272,6 +276,15 @@ An includer may test the following macros after inclusion: # define KWIML_INT_BROKEN_PRIXPTR 1 #endif +#if defined(_MSC_VER) && _MSC_VER < 1900 + /* MSVC scanf seems broken on 8-bit sizes until 19.00 */ +# define KWIML_INT_BROKEN_SCNd8 1 +# define KWIML_INT_BROKEN_SCNi8 1 +# define KWIML_INT_BROKEN_SCNo8 1 +# define KWIML_INT_BROKEN_SCNu8 1 +# define KWIML_INT_BROKEN_SCNx8 1 +#endif + #if (defined(__SUNPRO_C)||defined(__SUNPRO_CC)) && defined(_CHAR_IS_UNSIGNED) # define KWIML_INT_BROKEN_INT8_T 1 /* system type defined incorrectly */ #elif defined(__BORLANDC__) && defined(_CHAR_UNSIGNED) @@ -303,7 +316,7 @@ An includer may test the following macros after inclusion: #elif defined(__BORLANDC__) # define KWIML_INT_private_NO_SCN8 # define KWIML_INT_private_NO_SCN64 -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) && _MSC_VER < 1900 # define KWIML_INT_private_NO_SCN8 #elif defined(__WATCOMC__) # define KWIML_INT_private_NO_SCN8 From 3d05964b0293a0bb9eb9f1f3b6d3cff1d86aa85a Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 19 Aug 2021 10:36:39 -0400 Subject: [PATCH 1151/1519] libarchive: Update script to get 3.5.1 --- Utilities/Scripts/update-libarchive.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash index 3db89ff73a4..3a24e2b3ef5 100755 --- a/Utilities/Scripts/update-libarchive.bash +++ b/Utilities/Scripts/update-libarchive.bash @@ -8,7 +8,7 @@ readonly name="LibArchive" readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>" readonly subtree="Utilities/cmlibarchive" readonly repo="https://github.com/libarchive/libarchive.git" -readonly tag="v3.4.2" +readonly tag="v3.5.1" readonly shortlog=false readonly paths=" CMakeLists.txt From dadea0e5ce7dd04c7a2c1d22f3fd12affdbd6a89 Mon Sep 17 00:00:00 2001 From: LibArchive Upstream <libarchive-discuss@googlegroups.com> Date: Sat, 26 Dec 2020 00:34:39 +0100 Subject: [PATCH 1152/1519] LibArchive 2020-12-26 (227a4b97) Code extracted from: https://github.com/libarchive/libarchive.git at commit 227a4b9719a7fbeba6ba46e377ff7d953f405cd5 (v3.5.1). --- CMakeLists.txt | 28 +- COPYING | 1 - build/cmake/CreatePkgConfigFile.cmake | 4 +- build/cmake/config.h.in | 4 + build/version | 2 +- libarchive/archive.h | 11 +- libarchive/archive_acl.c | 10 +- libarchive/archive_check_magic.c | 2 +- libarchive/archive_cryptor.c | 23 + libarchive/archive_cryptor_private.h | 9 + libarchive/archive_digest.c | 534 ++++++------------ libarchive/archive_digest_private.h | 4 + libarchive/archive_entry.c | 85 ++- libarchive/archive_entry.h | 15 +- libarchive/archive_entry_private.h | 16 + libarchive/archive_entry_stat.3 | 4 +- libarchive/archive_ppmd7.c | 2 +- libarchive/archive_read.c | 17 +- libarchive/archive_read_add_passphrase.c | 4 + .../archive_read_disk_entry_from_file.c | 48 +- libarchive/archive_read_disk_posix.c | 46 +- libarchive/archive_read_filter.3 | 12 +- libarchive/archive_read_open_filename.c | 4 + libarchive/archive_read_set_format.c | 9 + .../archive_read_support_filter_by_code.c | 83 +++ .../archive_read_support_filter_program.c | 23 +- libarchive/archive_read_support_filter_zstd.c | 4 + .../archive_read_support_format_by_code.c | 15 + libarchive/archive_read_support_format_cab.c | 2 +- .../archive_read_support_format_empty.c | 2 +- .../archive_read_support_format_mtree.c | 137 ++++- libarchive/archive_read_support_format_rar.c | 14 +- libarchive/archive_read_support_format_rar5.c | 13 +- libarchive/archive_read_support_format_tar.c | 18 + libarchive/archive_read_support_format_warc.c | 20 +- libarchive/archive_read_support_format_xar.c | 17 +- libarchive/archive_read_support_format_zip.c | 131 ++++- libarchive/archive_string.c | 52 +- libarchive/archive_string.h | 2 +- libarchive/archive_util.c | 6 + libarchive/archive_write.c | 42 +- libarchive/archive_write_add_filter_program.c | 26 +- libarchive/archive_write_add_filter_xz.c | 4 +- libarchive/archive_write_add_filter_zstd.c | 79 ++- libarchive/archive_write_disk_posix.c | 52 +- libarchive/archive_write_disk_windows.c | 19 +- libarchive/archive_write_open.3 | 37 +- libarchive/archive_write_open_fd.c | 10 +- libarchive/archive_write_open_file.c | 10 +- libarchive/archive_write_open_filename.c | 21 +- libarchive/archive_write_open_memory.c | 10 +- libarchive/archive_write_private.h | 1 + libarchive/archive_write_set_format.c | 2 +- libarchive/archive_write_set_format_7zip.c | 4 +- libarchive/archive_write_set_format_cpio.c | 4 +- .../archive_write_set_format_cpio_newc.c | 2 +- libarchive/archive_write_set_format_iso9660.c | 3 +- libarchive/archive_write_set_format_mtree.c | 49 +- libarchive/archive_write_set_format_xar.c | 7 +- libarchive/archive_write_set_format_zip.c | 5 + libarchive/archive_write_set_options.3 | 3 +- libarchive/config_freebsd.h | 2 + libarchive/cpio.5 | 2 +- libarchive/filter_fork.h | 9 +- libarchive/filter_fork_posix.c | 10 +- libarchive/filter_fork_windows.c | 17 +- 66 files changed, 1237 insertions(+), 626 deletions(-) create mode 100644 libarchive/archive_read_support_filter_by_code.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a9b3250443..58b4c8d9862 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,32 +157,32 @@ IF (MSVC) # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" # Enable level 4 C4062: The enumerate has no associated handler in a switch # statement and there is no default that can catch it. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4062") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14062") # Enable level 4 C4254: A larger bit field was assigned to a smaller bit # field. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4254") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14254") # Enable level 4 C4295: An array was initialized but the last character in # the array is not a null; accessing the array may # produce unexpected results. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4295") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14295") # Enable level 4 C4296: An unsigned variable was used in a comparison # operation with zero. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4296") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14296") # Enable level 4 C4389: An operation involved signed and unsigned variables. # This could result in a loss of data. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4389") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14389") # Enable level 4 C4505: The given function is local and not referenced in # the body of the module; therefore, the function is # dead code. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4505") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14505") # Enable level 4 C4514: The optimizer removed an inline function that is not # called. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4514") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14514") # Enable level 4 C4702: Unreachable code. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4702") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14702") # Enable level 4 C4706: The test value in a conditional expression was the # result of an assignment. - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4706") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14706") # /Oi option enables built-in functions. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Oi") ################################################################# @@ -1378,6 +1378,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR) CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP) CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR) CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S) +CHECK_FUNCTION_EXISTS_GLIBC(strnlen HAVE_STRNLEN) CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR) CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK) CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM) @@ -1449,9 +1450,13 @@ CHECK_C_SOURCE_COMPILES( "#include <sys/sysmacros.h>\nint main() { return major(256); }" MAJOR_IN_SYSMACROS) +IF(ENABLE_LZMA) CHECK_C_SOURCE_COMPILES( "#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}" HAVE_LZMA_STREAM_ENCODER_MT) +ELSE() + SET(HAVE_LZMA_STREAM_ENCODER_MT 0) +ENDIF(ENABLE_LZMA) IF(HAVE_STRERROR_R) SET(HAVE_DECL_STRERROR_R 1) @@ -2036,6 +2041,11 @@ IF(MSVC) ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) ENDIF(MSVC) +IF(APPLE) + # CC_MD5_Init() functions are deprecated on macOS 10.15, but we want to use them + ADD_DEFINITIONS(-Wno-deprecated-declarations) +ENDIF(APPLE) + IF(ENABLE_TEST) ADD_CUSTOM_TARGET(run_all_tests) ENDIF(ENABLE_TEST) diff --git a/COPYING b/COPYING index 14bbefa0d5a..1b9723574a7 100644 --- a/COPYING +++ b/COPYING @@ -15,7 +15,6 @@ the actual statements in the files are controlling. * The following source files are also subject in whole or in part to a 3-clause UC Regents copyright; please read the individual source files for details: - libarchive/archive_entry.c libarchive/archive_read_support_filter_compress.c libarchive/archive_write_add_filter_compress.c libarchive/mtree.5 diff --git a/build/cmake/CreatePkgConfigFile.cmake b/build/cmake/CreatePkgConfigFile.cmake index fc8529a571f..bc5a43f72af 100644 --- a/build/cmake/CreatePkgConfigFile.cmake +++ b/build/cmake/CreatePkgConfigFile.cmake @@ -24,10 +24,10 @@ ENDFOREACH() # thus there's a good chance it'll make some binutils versions unhappy... # This only affects Libs.private (looked up for static builds) though. CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in - ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc + ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc @ONLY) # And install it, of course ;). IF(ENABLE_INSTALL) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc DESTINATION "lib/pkgconfig") ENDIF() diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index fcbd80c5a17..ff629f9ceb4 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -1,4 +1,5 @@ /* config.h. Generated from build/cmake/config.h.in by cmake configure */ +#define __LIBARCHIVE_CONFIG_H_INCLUDED 1 /* * Ensure we have C99-style int64_t, etc, all defined. @@ -958,6 +959,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `strchr' function. */ #cmakedefine HAVE_STRCHR 1 +/* Define to 1 if you have the `strnlen' function. */ +#cmakedefine HAVE_STRNLEN 1 + /* Define to 1 if you have the `strdup' function. */ #cmakedefine HAVE_STRDUP 1 diff --git a/build/version b/build/version index 78be3ab7e34..205791c6d99 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3004002 +3005001 diff --git a/libarchive/archive.h b/libarchive/archive.h index 55818eac8e6..52f4d782953 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3004002 +#define ARCHIVE_VERSION_NUMBER 3005001 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.4.2" +#define ARCHIVE_VERSION_ONLY_STRING "3.5.1" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -246,6 +246,8 @@ typedef int archive_open_callback(struct archive *, void *_client_data); typedef int archive_close_callback(struct archive *, void *_client_data); +typedef int archive_free_callback(struct archive *, void *_client_data); + /* Switches from one client data object to the next/prev client data object. * This is useful for reading from different data blocks such as a set of files * that make up one large file. @@ -418,6 +420,7 @@ __LA_DECL int archive_read_support_compression_xz(struct archive *) #endif __LA_DECL int archive_read_support_filter_all(struct archive *); +__LA_DECL int archive_read_support_filter_by_code(struct archive *, int); __LA_DECL int archive_read_support_filter_bzip2(struct archive *); __LA_DECL int archive_read_support_filter_compress(struct archive *); __LA_DECL int archive_read_support_filter_gzip(struct archive *); @@ -817,9 +820,13 @@ __LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const ch __LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext); __LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); __LA_DECL int archive_write_zip_set_compression_store(struct archive *); +/* Deprecated; use archive_write_open2 instead */ __LA_DECL int archive_write_open(struct archive *, void *, archive_open_callback *, archive_write_callback *, archive_close_callback *); +__LA_DECL int archive_write_open2(struct archive *, void *, + archive_open_callback *, archive_write_callback *, + archive_close_callback *, archive_free_callback *); __LA_DECL int archive_write_open_fd(struct archive *, int _fd); __LA_DECL int archive_write_open_filename(struct archive *, const char *_file); __LA_DECL int archive_write_open_filename_w(struct archive *, diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c index 952e20df4dc..ead7e36e49e 100644 --- a/libarchive/archive_acl.c +++ b/libarchive/archive_acl.c @@ -595,7 +595,7 @@ archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, else length += sizeof(uid_t) * 3 + 1; } else { - r = archive_mstring_get_mbs_l(&ap->name, &name, + r = archive_mstring_get_mbs_l(a, &ap->name, &name, &len, sc); if (r != 0) return (0); @@ -968,7 +968,7 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, else prefix = NULL; r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); + NULL, &ap->name, &name, &len, sc); if (r != 0) { free(s); return (NULL); @@ -1402,14 +1402,14 @@ isint_w(const wchar_t *start, const wchar_t *end, int *result) if (start >= end) return (0); while (start < end) { - if (*start < '0' || *start > '9') + if (*start < L'0' || *start > L'9') return (0); if (n > (INT_MAX / 10) || - (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) { + (n == INT_MAX / 10 && (*start - L'0') > INT_MAX % 10)) { n = INT_MAX; } else { n *= 10; - n += *start - '0'; + n += *start - L'0'; } start++; } diff --git a/libarchive/archive_check_magic.c b/libarchive/archive_check_magic.c index 288ce233855..1f40072f81d 100644 --- a/libarchive/archive_check_magic.c +++ b/libarchive/archive_check_magic.c @@ -54,7 +54,7 @@ errmsg(const char *m) ssize_t written; while (s > 0) { - written = write(2, m, strlen(m)); + written = write(2, m, s); if (written <= 0) return; m += written; diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c index 8ab2b097967..d4bca906b6e 100644 --- a/libarchive/archive_cryptor.c +++ b/libarchive/archive_cryptor.c @@ -347,8 +347,31 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) static int aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) { +#if NETTLE_VERSION_MAJOR < 3 aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key); aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce); +#else + switch(ctx->key_len) { + case AES128_KEY_SIZE: + aes128_set_encrypt_key(&ctx->ctx.c128, ctx->key); + aes128_encrypt(&ctx->ctx.c128, AES_BLOCK_SIZE, ctx->encr_buf, + ctx->nonce); + break; + case AES192_KEY_SIZE: + aes192_set_encrypt_key(&ctx->ctx.c192, ctx->key); + aes192_encrypt(&ctx->ctx.c192, AES_BLOCK_SIZE, ctx->encr_buf, + ctx->nonce); + break; + case AES256_KEY_SIZE: + aes256_set_encrypt_key(&ctx->ctx.c256, ctx->key); + aes256_encrypt(&ctx->ctx.c256, AES_BLOCK_SIZE, ctx->encr_buf, + ctx->nonce); + break; + default: + return -1; + break; + } +#endif return 0; } diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h index 64a20556a39..16b6d16ff23 100644 --- a/libarchive/archive_cryptor_private.h +++ b/libarchive/archive_cryptor_private.h @@ -104,9 +104,18 @@ typedef struct { #include <nettle/pbkdf2.h> #endif #include <nettle/aes.h> +#include <nettle/version.h> typedef struct { +#if NETTLE_VERSION_MAJOR < 3 struct aes_ctx ctx; +#else + union { + struct aes128_ctx c128; + struct aes192_ctx c192; + struct aes256_ctx c256; + } ctx; +#endif uint8_t key[AES_MAX_KEY_SIZE]; unsigned key_len; uint8_t nonce[AES_BLOCK_SIZE]; diff --git a/libarchive/archive_digest.c b/libarchive/archive_digest.c index 34c58ac9494..410df01563d 100644 --- a/libarchive/archive_digest.c +++ b/libarchive/archive_digest.c @@ -109,14 +109,14 @@ win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx) #if defined(ARCHIVE_CRYPTO_MD5_LIBC) static int -__archive_libc_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { MD5Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { MD5Update(ctx, indata, insize); @@ -124,7 +124,7 @@ __archive_libc_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_libc_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { MD5Final(md, ctx); return (ARCHIVE_OK); @@ -133,14 +133,14 @@ __archive_libc_md5final(archive_md5_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_MD5_LIBMD) static int -__archive_libmd_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { MD5Init(ctx); return (ARCHIVE_OK); } static int -__archive_libmd_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { MD5Update(ctx, indata, insize); @@ -148,7 +148,7 @@ __archive_libmd_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_libmd_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { MD5Final(md, ctx); return (ARCHIVE_OK); @@ -157,14 +157,14 @@ __archive_libmd_md5final(archive_md5_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) static int -__archive_libsystem_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { CC_MD5_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libsystem_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { CC_MD5_Update(ctx, indata, insize); @@ -172,7 +172,7 @@ __archive_libsystem_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_libsystem_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { CC_MD5_Final(md, ctx); return (ARCHIVE_OK); @@ -181,7 +181,7 @@ __archive_libsystem_md5final(archive_md5_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) static int -__archive_mbedtls_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { mbedtls_md5_init(ctx); if (mbedtls_md5_starts_ret(ctx) == 0) @@ -191,7 +191,7 @@ __archive_mbedtls_md5init(archive_md5_ctx *ctx) } static int -__archive_mbedtls_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { if (mbedtls_md5_update_ret(ctx, indata, insize) == 0) @@ -201,7 +201,7 @@ __archive_mbedtls_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_mbedtls_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { if (mbedtls_md5_finish_ret(ctx, md) == 0) { mbedtls_md5_free(ctx); @@ -215,14 +215,14 @@ __archive_mbedtls_md5final(archive_md5_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_MD5_NETTLE) static int -__archive_nettle_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { md5_init(ctx); return (ARCHIVE_OK); } static int -__archive_nettle_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { md5_update(ctx, insize, indata); @@ -230,7 +230,7 @@ __archive_nettle_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_nettle_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { md5_digest(ctx, MD5_DIGEST_SIZE, md); return (ARCHIVE_OK); @@ -239,7 +239,7 @@ __archive_nettle_md5final(archive_md5_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL) static int -__archive_openssl_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); @@ -248,7 +248,7 @@ __archive_openssl_md5init(archive_md5_ctx *ctx) } static int -__archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { EVP_DigestUpdate(*ctx, indata, insize); @@ -256,7 +256,7 @@ __archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_openssl_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so * this is meant to cope with that. Real fix is probably to fix @@ -273,20 +273,20 @@ __archive_openssl_md5final(archive_md5_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_MD5_WIN) static int -__archive_windowsapi_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { return (win_crypto_init(ctx, CALG_MD5)); } static int -__archive_windowsapi_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { return (win_crypto_Update(ctx, indata, insize)); } static int -__archive_windowsapi_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { return (win_crypto_Final(md, 16, ctx)); } @@ -294,14 +294,14 @@ __archive_windowsapi_md5final(archive_md5_ctx *ctx, void *md) #else static int -__archive_stub_md5init(archive_md5_ctx *ctx) +__archive_md5init(archive_md5_ctx *ctx) { (void)ctx; /* UNUSED */ return (ARCHIVE_FAILED); } static int -__archive_stub_md5update(archive_md5_ctx *ctx, const void *indata, +__archive_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { (void)ctx; /* UNUSED */ @@ -311,7 +311,7 @@ __archive_stub_md5update(archive_md5_ctx *ctx, const void *indata, } static int -__archive_stub_md5final(archive_md5_ctx *ctx, void *md) +__archive_md5final(archive_md5_ctx *ctx, void *md) { (void)ctx; /* UNUSED */ (void)md; /* UNUSED */ @@ -324,14 +324,14 @@ __archive_stub_md5final(archive_md5_ctx *ctx, void *md) #if defined(ARCHIVE_CRYPTO_RMD160_LIBC) static int -__archive_libc_ripemd160init(archive_rmd160_ctx *ctx) +__archive_ripemd160init(archive_rmd160_ctx *ctx) { RMD160Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, +__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { RMD160Update(ctx, indata, insize); @@ -339,7 +339,7 @@ __archive_libc_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, } static int -__archive_libc_ripemd160final(archive_rmd160_ctx *ctx, void *md) +__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md) { RMD160Final(md, ctx); return (ARCHIVE_OK); @@ -348,14 +348,14 @@ __archive_libc_ripemd160final(archive_rmd160_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD) static int -__archive_libmd_ripemd160init(archive_rmd160_ctx *ctx) +__archive_ripemd160init(archive_rmd160_ctx *ctx) { RIPEMD160_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libmd_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, +__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { RIPEMD160_Update(ctx, indata, insize); @@ -363,7 +363,7 @@ __archive_libmd_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, } static int -__archive_libmd_ripemd160final(archive_rmd160_ctx *ctx, void *md) +__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md) { RIPEMD160_Final(md, ctx); return (ARCHIVE_OK); @@ -372,7 +372,7 @@ __archive_libmd_ripemd160final(archive_rmd160_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) static int -__archive_mbedtls_ripemd160init(archive_rmd160_ctx *ctx) +__archive_ripemd160init(archive_rmd160_ctx *ctx) { mbedtls_ripemd160_init(ctx); if (mbedtls_ripemd160_starts_ret(ctx) == 0) @@ -382,7 +382,7 @@ __archive_mbedtls_ripemd160init(archive_rmd160_ctx *ctx) } static int -__archive_mbedtls_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, +__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0) @@ -392,7 +392,7 @@ __archive_mbedtls_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, } static int -__archive_mbedtls_ripemd160final(archive_rmd160_ctx *ctx, void *md) +__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md) { if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) { mbedtls_ripemd160_free(ctx); @@ -406,14 +406,14 @@ __archive_mbedtls_ripemd160final(archive_rmd160_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE) static int -__archive_nettle_ripemd160init(archive_rmd160_ctx *ctx) +__archive_ripemd160init(archive_rmd160_ctx *ctx) { ripemd160_init(ctx); return (ARCHIVE_OK); } static int -__archive_nettle_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, +__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { ripemd160_update(ctx, insize, indata); @@ -421,7 +421,7 @@ __archive_nettle_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, } static int -__archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md) +__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md) { ripemd160_digest(ctx, RIPEMD160_DIGEST_SIZE, md); return (ARCHIVE_OK); @@ -430,7 +430,7 @@ __archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) static int -__archive_openssl_ripemd160init(archive_rmd160_ctx *ctx) +__archive_ripemd160init(archive_rmd160_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); @@ -439,7 +439,7 @@ __archive_openssl_ripemd160init(archive_rmd160_ctx *ctx) } static int -__archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, +__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { EVP_DigestUpdate(*ctx, indata, insize); @@ -447,7 +447,7 @@ __archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, } static int -__archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md) +__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md) { if (*ctx) { EVP_DigestFinal(*ctx, md, NULL); @@ -460,14 +460,14 @@ __archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md) #else static int -__archive_stub_ripemd160init(archive_rmd160_ctx *ctx) +__archive_ripemd160init(archive_rmd160_ctx *ctx) { (void)ctx; /* UNUSED */ return (ARCHIVE_FAILED); } static int -__archive_stub_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, +__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { (void)ctx; /* UNUSED */ @@ -477,7 +477,7 @@ __archive_stub_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, } static int -__archive_stub_ripemd160final(archive_rmd160_ctx *ctx, void *md) +__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md) { (void)ctx; /* UNUSED */ (void)md; /* UNUSED */ @@ -490,14 +490,14 @@ __archive_stub_ripemd160final(archive_rmd160_ctx *ctx, void *md) #if defined(ARCHIVE_CRYPTO_SHA1_LIBC) static int -__archive_libc_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { SHA1Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { SHA1Update(ctx, indata, insize); @@ -505,7 +505,7 @@ __archive_libc_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_libc_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { SHA1Final(md, ctx); return (ARCHIVE_OK); @@ -514,14 +514,14 @@ __archive_libc_sha1final(archive_sha1_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD) static int -__archive_libmd_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { SHA1_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libmd_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { SHA1_Update(ctx, indata, insize); @@ -529,7 +529,7 @@ __archive_libmd_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_libmd_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { SHA1_Final(md, ctx); return (ARCHIVE_OK); @@ -538,14 +538,14 @@ __archive_libmd_sha1final(archive_sha1_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) static int -__archive_libsystem_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { CC_SHA1_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libsystem_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { CC_SHA1_Update(ctx, indata, insize); @@ -553,7 +553,7 @@ __archive_libsystem_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_libsystem_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { CC_SHA1_Final(md, ctx); return (ARCHIVE_OK); @@ -562,7 +562,7 @@ __archive_libsystem_sha1final(archive_sha1_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) static int -__archive_mbedtls_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { mbedtls_sha1_init(ctx); if (mbedtls_sha1_starts_ret(ctx) == 0) @@ -572,7 +572,7 @@ __archive_mbedtls_sha1init(archive_sha1_ctx *ctx) } static int -__archive_mbedtls_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0) @@ -582,7 +582,7 @@ __archive_mbedtls_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_mbedtls_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { if (mbedtls_sha1_finish_ret(ctx, md) == 0) { mbedtls_sha1_free(ctx); @@ -596,14 +596,14 @@ __archive_mbedtls_sha1final(archive_sha1_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE) static int -__archive_nettle_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { sha1_init(ctx); return (ARCHIVE_OK); } static int -__archive_nettle_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { sha1_update(ctx, insize, indata); @@ -611,7 +611,7 @@ __archive_nettle_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { sha1_digest(ctx, SHA1_DIGEST_SIZE, md); return (ARCHIVE_OK); @@ -620,7 +620,7 @@ __archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) static int -__archive_openssl_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); @@ -629,7 +629,7 @@ __archive_openssl_sha1init(archive_sha1_ctx *ctx) } static int -__archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { EVP_DigestUpdate(*ctx, indata, insize); @@ -637,7 +637,7 @@ __archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { /* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so * this is meant to cope with that. Real fix is probably to fix @@ -654,20 +654,20 @@ __archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA1_WIN) static int -__archive_windowsapi_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { return (win_crypto_init(ctx, CALG_SHA1)); } static int -__archive_windowsapi_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { return (win_crypto_Update(ctx, indata, insize)); } static int -__archive_windowsapi_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { return (win_crypto_Final(md, 20, ctx)); } @@ -675,14 +675,14 @@ __archive_windowsapi_sha1final(archive_sha1_ctx *ctx, void *md) #else static int -__archive_stub_sha1init(archive_sha1_ctx *ctx) +__archive_sha1init(archive_sha1_ctx *ctx) { (void)ctx; /* UNUSED */ return (ARCHIVE_FAILED); } static int -__archive_stub_sha1update(archive_sha1_ctx *ctx, const void *indata, +__archive_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { (void)ctx; /* UNUSED */ @@ -692,7 +692,7 @@ __archive_stub_sha1update(archive_sha1_ctx *ctx, const void *indata, } static int -__archive_stub_sha1final(archive_sha1_ctx *ctx, void *md) +__archive_sha1final(archive_sha1_ctx *ctx, void *md) { (void)ctx; /* UNUSED */ (void)md; /* UNUSED */ @@ -705,14 +705,14 @@ __archive_stub_sha1final(archive_sha1_ctx *ctx, void *md) #if defined(ARCHIVE_CRYPTO_SHA256_LIBC) static int -__archive_libc_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { SHA256_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { SHA256_Update(ctx, indata, insize); @@ -720,7 +720,7 @@ __archive_libc_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_libc_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { SHA256_Final(md, ctx); return (ARCHIVE_OK); @@ -729,14 +729,14 @@ __archive_libc_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2) static int -__archive_libc2_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { SHA256Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc2_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { SHA256Update(ctx, indata, insize); @@ -744,7 +744,7 @@ __archive_libc2_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_libc2_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { SHA256Final(md, ctx); return (ARCHIVE_OK); @@ -753,14 +753,14 @@ __archive_libc2_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3) static int -__archive_libc3_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { SHA256Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc3_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { SHA256Update(ctx, indata, insize); @@ -768,7 +768,7 @@ __archive_libc3_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_libc3_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { SHA256Final(md, ctx); return (ARCHIVE_OK); @@ -777,14 +777,14 @@ __archive_libc3_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD) static int -__archive_libmd_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { SHA256_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libmd_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { SHA256_Update(ctx, indata, insize); @@ -792,7 +792,7 @@ __archive_libmd_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_libmd_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { SHA256_Final(md, ctx); return (ARCHIVE_OK); @@ -801,14 +801,14 @@ __archive_libmd_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) static int -__archive_libsystem_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { CC_SHA256_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libsystem_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { CC_SHA256_Update(ctx, indata, insize); @@ -816,7 +816,7 @@ __archive_libsystem_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_libsystem_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { CC_SHA256_Final(md, ctx); return (ARCHIVE_OK); @@ -825,7 +825,7 @@ __archive_libsystem_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) static int -__archive_mbedtls_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { mbedtls_sha256_init(ctx); if (mbedtls_sha256_starts_ret(ctx, 0) == 0) @@ -835,7 +835,7 @@ __archive_mbedtls_sha256init(archive_sha256_ctx *ctx) } static int -__archive_mbedtls_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0) @@ -845,7 +845,7 @@ __archive_mbedtls_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_mbedtls_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { if (mbedtls_sha256_finish_ret(ctx, md) == 0) { mbedtls_sha256_free(ctx); @@ -859,14 +859,14 @@ __archive_mbedtls_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE) static int -__archive_nettle_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { sha256_init(ctx); return (ARCHIVE_OK); } static int -__archive_nettle_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { sha256_update(ctx, insize, indata); @@ -874,7 +874,7 @@ __archive_nettle_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { sha256_digest(ctx, SHA256_DIGEST_SIZE, md); return (ARCHIVE_OK); @@ -883,7 +883,7 @@ __archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) static int -__archive_openssl_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); @@ -892,7 +892,7 @@ __archive_openssl_sha256init(archive_sha256_ctx *ctx) } static int -__archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { EVP_DigestUpdate(*ctx, indata, insize); @@ -900,7 +900,7 @@ __archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { if (*ctx) { EVP_DigestFinal(*ctx, md, NULL); @@ -913,20 +913,20 @@ __archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA256_WIN) static int -__archive_windowsapi_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { return (win_crypto_init(ctx, CALG_SHA_256)); } static int -__archive_windowsapi_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { return (win_crypto_Update(ctx, indata, insize)); } static int -__archive_windowsapi_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { return (win_crypto_Final(md, 32, ctx)); } @@ -934,14 +934,14 @@ __archive_windowsapi_sha256final(archive_sha256_ctx *ctx, void *md) #else static int -__archive_stub_sha256init(archive_sha256_ctx *ctx) +__archive_sha256init(archive_sha256_ctx *ctx) { (void)ctx; /* UNUSED */ return (ARCHIVE_FAILED); } static int -__archive_stub_sha256update(archive_sha256_ctx *ctx, const void *indata, +__archive_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { (void)ctx; /* UNUSED */ @@ -951,7 +951,7 @@ __archive_stub_sha256update(archive_sha256_ctx *ctx, const void *indata, } static int -__archive_stub_sha256final(archive_sha256_ctx *ctx, void *md) +__archive_sha256final(archive_sha256_ctx *ctx, void *md) { (void)ctx; /* UNUSED */ (void)md; /* UNUSED */ @@ -964,14 +964,14 @@ __archive_stub_sha256final(archive_sha256_ctx *ctx, void *md) #if defined(ARCHIVE_CRYPTO_SHA384_LIBC) static int -__archive_libc_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { SHA384_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { SHA384_Update(ctx, indata, insize); @@ -979,7 +979,7 @@ __archive_libc_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_libc_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { SHA384_Final(md, ctx); return (ARCHIVE_OK); @@ -988,14 +988,14 @@ __archive_libc_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2) static int -__archive_libc2_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { SHA384Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc2_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { SHA384Update(ctx, indata, insize); @@ -1003,7 +1003,7 @@ __archive_libc2_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_libc2_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { SHA384Final(md, ctx); return (ARCHIVE_OK); @@ -1012,14 +1012,14 @@ __archive_libc2_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3) static int -__archive_libc3_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { SHA384Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc3_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { SHA384Update(ctx, indata, insize); @@ -1027,7 +1027,7 @@ __archive_libc3_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_libc3_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { SHA384Final(md, ctx); return (ARCHIVE_OK); @@ -1036,14 +1036,14 @@ __archive_libc3_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) static int -__archive_libsystem_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { CC_SHA384_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libsystem_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { CC_SHA384_Update(ctx, indata, insize); @@ -1051,7 +1051,7 @@ __archive_libsystem_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_libsystem_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { CC_SHA384_Final(md, ctx); return (ARCHIVE_OK); @@ -1060,7 +1060,7 @@ __archive_libsystem_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) static int -__archive_mbedtls_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { mbedtls_sha512_init(ctx); if (mbedtls_sha512_starts_ret(ctx, 1) == 0) @@ -1070,7 +1070,7 @@ __archive_mbedtls_sha384init(archive_sha384_ctx *ctx) } static int -__archive_mbedtls_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0) @@ -1080,7 +1080,7 @@ __archive_mbedtls_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_mbedtls_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { if (mbedtls_sha512_finish_ret(ctx, md) == 0) { mbedtls_sha512_free(ctx); @@ -1094,14 +1094,14 @@ __archive_mbedtls_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE) static int -__archive_nettle_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { sha384_init(ctx); return (ARCHIVE_OK); } static int -__archive_nettle_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { sha384_update(ctx, insize, indata); @@ -1109,7 +1109,7 @@ __archive_nettle_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { sha384_digest(ctx, SHA384_DIGEST_SIZE, md); return (ARCHIVE_OK); @@ -1118,7 +1118,7 @@ __archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) static int -__archive_openssl_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); @@ -1127,7 +1127,7 @@ __archive_openssl_sha384init(archive_sha384_ctx *ctx) } static int -__archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { EVP_DigestUpdate(*ctx, indata, insize); @@ -1135,7 +1135,7 @@ __archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { if (*ctx) { EVP_DigestFinal(*ctx, md, NULL); @@ -1148,20 +1148,20 @@ __archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA384_WIN) static int -__archive_windowsapi_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { return (win_crypto_init(ctx, CALG_SHA_384)); } static int -__archive_windowsapi_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { return (win_crypto_Update(ctx, indata, insize)); } static int -__archive_windowsapi_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { return (win_crypto_Final(md, 48, ctx)); } @@ -1169,14 +1169,14 @@ __archive_windowsapi_sha384final(archive_sha384_ctx *ctx, void *md) #else static int -__archive_stub_sha384init(archive_sha384_ctx *ctx) +__archive_sha384init(archive_sha384_ctx *ctx) { (void)ctx; /* UNUSED */ return (ARCHIVE_FAILED); } static int -__archive_stub_sha384update(archive_sha384_ctx *ctx, const void *indata, +__archive_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { (void)ctx; /* UNUSED */ @@ -1186,7 +1186,7 @@ __archive_stub_sha384update(archive_sha384_ctx *ctx, const void *indata, } static int -__archive_stub_sha384final(archive_sha384_ctx *ctx, void *md) +__archive_sha384final(archive_sha384_ctx *ctx, void *md) { (void)ctx; /* UNUSED */ (void)md; /* UNUSED */ @@ -1199,14 +1199,14 @@ __archive_stub_sha384final(archive_sha384_ctx *ctx, void *md) #if defined(ARCHIVE_CRYPTO_SHA512_LIBC) static int -__archive_libc_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { SHA512_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { SHA512_Update(ctx, indata, insize); @@ -1214,7 +1214,7 @@ __archive_libc_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_libc_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { SHA512_Final(md, ctx); return (ARCHIVE_OK); @@ -1223,14 +1223,14 @@ __archive_libc_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2) static int -__archive_libc2_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { SHA512Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc2_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { SHA512Update(ctx, indata, insize); @@ -1238,7 +1238,7 @@ __archive_libc2_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_libc2_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { SHA512Final(md, ctx); return (ARCHIVE_OK); @@ -1247,14 +1247,14 @@ __archive_libc2_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3) static int -__archive_libc3_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { SHA512Init(ctx); return (ARCHIVE_OK); } static int -__archive_libc3_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { SHA512Update(ctx, indata, insize); @@ -1262,7 +1262,7 @@ __archive_libc3_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_libc3_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { SHA512Final(md, ctx); return (ARCHIVE_OK); @@ -1271,14 +1271,14 @@ __archive_libc3_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD) static int -__archive_libmd_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { SHA512_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libmd_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { SHA512_Update(ctx, indata, insize); @@ -1286,7 +1286,7 @@ __archive_libmd_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_libmd_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { SHA512_Final(md, ctx); return (ARCHIVE_OK); @@ -1295,14 +1295,14 @@ __archive_libmd_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) static int -__archive_libsystem_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { CC_SHA512_Init(ctx); return (ARCHIVE_OK); } static int -__archive_libsystem_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { CC_SHA512_Update(ctx, indata, insize); @@ -1310,7 +1310,7 @@ __archive_libsystem_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_libsystem_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { CC_SHA512_Final(md, ctx); return (ARCHIVE_OK); @@ -1319,7 +1319,7 @@ __archive_libsystem_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) static int -__archive_mbedtls_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { mbedtls_sha512_init(ctx); if (mbedtls_sha512_starts_ret(ctx, 0) == 0) @@ -1329,7 +1329,7 @@ __archive_mbedtls_sha512init(archive_sha512_ctx *ctx) } static int -__archive_mbedtls_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0) @@ -1339,7 +1339,7 @@ __archive_mbedtls_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_mbedtls_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { if (mbedtls_sha512_finish_ret(ctx, md) == 0) { mbedtls_sha512_free(ctx); @@ -1353,14 +1353,14 @@ __archive_mbedtls_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) static int -__archive_nettle_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { sha512_init(ctx); return (ARCHIVE_OK); } static int -__archive_nettle_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { sha512_update(ctx, insize, indata); @@ -1368,7 +1368,7 @@ __archive_nettle_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { sha512_digest(ctx, SHA512_DIGEST_SIZE, md); return (ARCHIVE_OK); @@ -1377,7 +1377,7 @@ __archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) static int -__archive_openssl_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { if ((*ctx = EVP_MD_CTX_new()) == NULL) return (ARCHIVE_FAILED); @@ -1386,7 +1386,7 @@ __archive_openssl_sha512init(archive_sha512_ctx *ctx) } static int -__archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { EVP_DigestUpdate(*ctx, indata, insize); @@ -1394,7 +1394,7 @@ __archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { if (*ctx) { EVP_DigestFinal(*ctx, md, NULL); @@ -1407,20 +1407,20 @@ __archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md) #elif defined(ARCHIVE_CRYPTO_SHA512_WIN) static int -__archive_windowsapi_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { return (win_crypto_init(ctx, CALG_SHA_512)); } static int -__archive_windowsapi_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { return (win_crypto_Update(ctx, indata, insize)); } static int -__archive_windowsapi_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { return (win_crypto_Final(md, 64, ctx)); } @@ -1428,14 +1428,14 @@ __archive_windowsapi_sha512final(archive_sha512_ctx *ctx, void *md) #else static int -__archive_stub_sha512init(archive_sha512_ctx *ctx) +__archive_sha512init(archive_sha512_ctx *ctx) { (void)ctx; /* UNUSED */ return (ARCHIVE_FAILED); } static int -__archive_stub_sha512update(archive_sha512_ctx *ctx, const void *indata, +__archive_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { (void)ctx; /* UNUSED */ @@ -1445,7 +1445,7 @@ __archive_stub_sha512update(archive_sha512_ctx *ctx, const void *indata, } static int -__archive_stub_sha512final(archive_sha512_ctx *ctx, void *md) +__archive_sha512final(archive_sha512_ctx *ctx, void *md) { (void)ctx; /* UNUSED */ (void)md; /* UNUSED */ @@ -1468,224 +1468,32 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md) const struct archive_digest __archive_digest = { /* MD5 */ -#if defined(ARCHIVE_CRYPTO_MD5_LIBC) - &__archive_libc_md5init, - &__archive_libc_md5update, - &__archive_libc_md5final, -#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD) - &__archive_libmd_md5init, - &__archive_libmd_md5update, - &__archive_libmd_md5final, -#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) - &__archive_libsystem_md5init, - &__archive_libsystem_md5update, - &__archive_libsystem_md5final, -#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS) - &__archive_mbedtls_md5init, - &__archive_mbedtls_md5update, - &__archive_mbedtls_md5final, -#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE) - &__archive_nettle_md5init, - &__archive_nettle_md5update, - &__archive_nettle_md5final, -#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL) - &__archive_openssl_md5init, - &__archive_openssl_md5update, - &__archive_openssl_md5final, -#elif defined(ARCHIVE_CRYPTO_MD5_WIN) - &__archive_windowsapi_md5init, - &__archive_windowsapi_md5update, - &__archive_windowsapi_md5final, -#elif !defined(ARCHIVE_MD5_COMPILE_TEST) - &__archive_stub_md5init, - &__archive_stub_md5update, - &__archive_stub_md5final, -#endif + &__archive_md5init, + &__archive_md5update, + &__archive_md5final, /* RIPEMD160 */ -#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) - &__archive_libc_ripemd160init, - &__archive_libc_ripemd160update, - &__archive_libc_ripemd160final, -#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD) - &__archive_libmd_ripemd160init, - &__archive_libmd_ripemd160update, - &__archive_libmd_ripemd160final, -#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS) - &__archive_mbedtls_ripemd160init, - &__archive_mbedtls_ripemd160update, - &__archive_mbedtls_ripemd160final, -#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE) - &__archive_nettle_ripemd160init, - &__archive_nettle_ripemd160update, - &__archive_nettle_ripemd160final, -#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) - &__archive_openssl_ripemd160init, - &__archive_openssl_ripemd160update, - &__archive_openssl_ripemd160final, -#elif !defined(ARCHIVE_RMD160_COMPILE_TEST) - &__archive_stub_ripemd160init, - &__archive_stub_ripemd160update, - &__archive_stub_ripemd160final, -#endif + &__archive_ripemd160init, + &__archive_ripemd160update, + &__archive_ripemd160final, /* SHA1 */ -#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) - &__archive_libc_sha1init, - &__archive_libc_sha1update, - &__archive_libc_sha1final, -#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD) - &__archive_libmd_sha1init, - &__archive_libmd_sha1update, - &__archive_libmd_sha1final, -#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) - &__archive_libsystem_sha1init, - &__archive_libsystem_sha1update, - &__archive_libsystem_sha1final, -#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS) - &__archive_mbedtls_sha1init, - &__archive_mbedtls_sha1update, - &__archive_mbedtls_sha1final, -#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE) - &__archive_nettle_sha1init, - &__archive_nettle_sha1update, - &__archive_nettle_sha1final, -#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) - &__archive_openssl_sha1init, - &__archive_openssl_sha1update, - &__archive_openssl_sha1final, -#elif defined(ARCHIVE_CRYPTO_SHA1_WIN) - &__archive_windowsapi_sha1init, - &__archive_windowsapi_sha1update, - &__archive_windowsapi_sha1final, -#elif !defined(ARCHIVE_SHA1_COMPILE_TEST) - &__archive_stub_sha1init, - &__archive_stub_sha1update, - &__archive_stub_sha1final, -#endif + &__archive_sha1init, + &__archive_sha1update, + &__archive_sha1final, /* SHA256 */ -#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) - &__archive_libc_sha256init, - &__archive_libc_sha256update, - &__archive_libc_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2) - &__archive_libc2_sha256init, - &__archive_libc2_sha256update, - &__archive_libc2_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3) - &__archive_libc3_sha256init, - &__archive_libc3_sha256update, - &__archive_libc3_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD) - &__archive_libmd_sha256init, - &__archive_libmd_sha256update, - &__archive_libmd_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) - &__archive_libsystem_sha256init, - &__archive_libsystem_sha256update, - &__archive_libsystem_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS) - &__archive_mbedtls_sha256init, - &__archive_mbedtls_sha256update, - &__archive_mbedtls_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE) - &__archive_nettle_sha256init, - &__archive_nettle_sha256update, - &__archive_nettle_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) - &__archive_openssl_sha256init, - &__archive_openssl_sha256update, - &__archive_openssl_sha256final, -#elif defined(ARCHIVE_CRYPTO_SHA256_WIN) - &__archive_windowsapi_sha256init, - &__archive_windowsapi_sha256update, - &__archive_windowsapi_sha256final, -#elif !defined(ARCHIVE_SHA256_COMPILE_TEST) - &__archive_stub_sha256init, - &__archive_stub_sha256update, - &__archive_stub_sha256final, -#endif + &__archive_sha256init, + &__archive_sha256update, + &__archive_sha256final, /* SHA384 */ -#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) - &__archive_libc_sha384init, - &__archive_libc_sha384update, - &__archive_libc_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2) - &__archive_libc2_sha384init, - &__archive_libc2_sha384update, - &__archive_libc2_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3) - &__archive_libc3_sha384init, - &__archive_libc3_sha384update, - &__archive_libc3_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) - &__archive_libsystem_sha384init, - &__archive_libsystem_sha384update, - &__archive_libsystem_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS) - &__archive_mbedtls_sha384init, - &__archive_mbedtls_sha384update, - &__archive_mbedtls_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE) - &__archive_nettle_sha384init, - &__archive_nettle_sha384update, - &__archive_nettle_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) - &__archive_openssl_sha384init, - &__archive_openssl_sha384update, - &__archive_openssl_sha384final, -#elif defined(ARCHIVE_CRYPTO_SHA384_WIN) - &__archive_windowsapi_sha384init, - &__archive_windowsapi_sha384update, - &__archive_windowsapi_sha384final, -#elif !defined(ARCHIVE_SHA384_COMPILE_TEST) - &__archive_stub_sha384init, - &__archive_stub_sha384update, - &__archive_stub_sha384final, -#endif + &__archive_sha384init, + &__archive_sha384update, + &__archive_sha384final, /* SHA512 */ -#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) - &__archive_libc_sha512init, - &__archive_libc_sha512update, - &__archive_libc_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2) - &__archive_libc2_sha512init, - &__archive_libc2_sha512update, - &__archive_libc2_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3) - &__archive_libc3_sha512init, - &__archive_libc3_sha512update, - &__archive_libc3_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD) - &__archive_libmd_sha512init, - &__archive_libmd_sha512update, - &__archive_libmd_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) - &__archive_libsystem_sha512init, - &__archive_libsystem_sha512update, - &__archive_libsystem_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS) - &__archive_mbedtls_sha512init, - &__archive_mbedtls_sha512update, - &__archive_mbedtls_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) - &__archive_nettle_sha512init, - &__archive_nettle_sha512update, - &__archive_nettle_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) - &__archive_openssl_sha512init, - &__archive_openssl_sha512update, - &__archive_openssl_sha512final -#elif defined(ARCHIVE_CRYPTO_SHA512_WIN) - &__archive_windowsapi_sha512init, - &__archive_windowsapi_sha512update, - &__archive_windowsapi_sha512final -#elif !defined(ARCHIVE_SHA512_COMPILE_TEST) - &__archive_stub_sha512init, - &__archive_stub_sha512update, - &__archive_stub_sha512final -#endif + &__archive_sha512init, + &__archive_sha512update, + &__archive_sha512final }; diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h index 15312ee9a07..9b3bd6621bf 100644 --- a/libarchive/archive_digest_private.h +++ b/libarchive/archive_digest_private.h @@ -30,6 +30,10 @@ #ifndef __LIBARCHIVE_BUILD #error This header is only to be used internally to libarchive. #endif +#ifndef __LIBARCHIVE_CONFIG_H_INCLUDED +#error "Should have include config.h first!" +#endif + /* * Crypto support in various Operating Systems: * diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index a15e98c2842..ca7a4bdb50e 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -208,6 +208,19 @@ archive_entry_clone(struct archive_entry *entry) /* Copy encryption status */ entry2->encryption = entry->encryption; + + /* Copy digests */ +#define copy_digest(_e2, _e, _t) \ + memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t)) + + copy_digest(entry2, entry, md5); + copy_digest(entry2, entry, rmd160); + copy_digest(entry2, entry, sha1); + copy_digest(entry2, entry, sha256); + copy_digest(entry2, entry, sha384); + copy_digest(entry2, entry, sha512); + +#undef copy_digest /* Copy ACL data over. */ archive_acl_copy(&entry2->acl, &entry->acl); @@ -353,7 +366,7 @@ archive_entry_devminor(struct archive_entry *entry) return minor(entry->ae_stat.aest_dev); } -mode_t +__LA_MODE_T archive_entry_filetype(struct archive_entry *entry) { return (AE_IFMT & entry->acl.mode); @@ -450,7 +463,7 @@ int _archive_entry_gname_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { - return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc)); + return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc)); } const char * @@ -504,7 +517,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry, *len = 0; return (0); } - return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc)); + return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_hardlink, p, len, sc)); } la_int64_t @@ -525,7 +538,7 @@ archive_entry_ino64(struct archive_entry *entry) return (entry->ae_stat.aest_ino); } -mode_t +__LA_MODE_T archive_entry_mode(struct archive_entry *entry) { return (entry->acl.mode); @@ -595,10 +608,10 @@ int _archive_entry_pathname_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { - return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc)); + return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc)); } -mode_t +__LA_MODE_T archive_entry_perm(struct archive_entry *entry) { return (~AE_IFMT & entry->acl.mode); @@ -723,7 +736,7 @@ _archive_entry_symlink_l(struct archive_entry *entry, *len = 0; return (0); } - return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc)); + return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_symlink, p, len, sc)); } la_int64_t @@ -769,7 +782,7 @@ int _archive_entry_uname_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { - return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc)); + return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc)); } int @@ -1416,6 +1429,62 @@ archive_entry_copy_mac_metadata(struct archive_entry *entry, } } +/* Digest handling */ +const unsigned char * +archive_entry_digest(struct archive_entry *entry, int type) +{ + switch (type) { + case ARCHIVE_ENTRY_DIGEST_MD5: + return entry->digest.md5; + case ARCHIVE_ENTRY_DIGEST_RMD160: + return entry->digest.rmd160; + case ARCHIVE_ENTRY_DIGEST_SHA1: + return entry->digest.sha1; + case ARCHIVE_ENTRY_DIGEST_SHA256: + return entry->digest.sha256; + case ARCHIVE_ENTRY_DIGEST_SHA384: + return entry->digest.sha384; + case ARCHIVE_ENTRY_DIGEST_SHA512: + return entry->digest.sha512; + default: + return NULL; + } +} + +int +archive_entry_set_digest(struct archive_entry *entry, int type, + const unsigned char *digest) +{ +#define copy_digest(_e, _t, _d)\ + memcpy(_e->digest._t, _d, sizeof(_e->digest._t)) + + switch (type) { + case ARCHIVE_ENTRY_DIGEST_MD5: + copy_digest(entry, md5, digest); + break; + case ARCHIVE_ENTRY_DIGEST_RMD160: + copy_digest(entry, rmd160, digest); + break; + case ARCHIVE_ENTRY_DIGEST_SHA1: + copy_digest(entry, sha1, digest); + break; + case ARCHIVE_ENTRY_DIGEST_SHA256: + copy_digest(entry, sha256, digest); + break; + case ARCHIVE_ENTRY_DIGEST_SHA384: + copy_digest(entry, sha384, digest); + break; + case ARCHIVE_ENTRY_DIGEST_SHA512: + copy_digest(entry, sha512, digest); + break; + default: + return ARCHIVE_WARN; + } + + return ARCHIVE_OK; +#undef copy_digest +} + /* * ACL management. The following would, of course, be a lot simpler * if: 1) the last draft of POSIX.1e were a really thorough and diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 42af20864f7..c0e75bf9f10 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3004002 +#define ARCHIVE_VERSION_NUMBER 3005001 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -396,6 +396,19 @@ __LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat __LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); +/* + * Digest routine. This is used to query the raw hex digest for the + * given entry. The type of digest is provided as an argument. + */ +#define ARCHIVE_ENTRY_DIGEST_MD5 0x00000001 +#define ARCHIVE_ENTRY_DIGEST_RMD160 0x00000002 +#define ARCHIVE_ENTRY_DIGEST_SHA1 0x00000003 +#define ARCHIVE_ENTRY_DIGEST_SHA256 0x00000004 +#define ARCHIVE_ENTRY_DIGEST_SHA384 0x00000005 +#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006 + +__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */); + /* * ACL routines. This used to simply store and return text-format ACL * strings, but that proved insufficient for a number of reasons: diff --git a/libarchive/archive_entry_private.h b/libarchive/archive_entry_private.h index 2b9a084ca15..cf4deb24ec8 100644 --- a/libarchive/archive_entry_private.h +++ b/libarchive/archive_entry_private.h @@ -50,6 +50,15 @@ struct ae_sparse { int64_t length; }; +struct ae_digest { + unsigned char md5[16]; + unsigned char rmd160[20]; + unsigned char sha1[20]; + unsigned char sha256[32]; + unsigned char sha384[48]; + unsigned char sha512[64]; +}; + /* * Description of an archive entry. * @@ -162,6 +171,9 @@ struct archive_entry { void *mac_metadata; size_t mac_metadata_size; + /* Digest support. */ + struct ae_digest digest; + /* ACL support. */ struct archive_acl acl; @@ -181,4 +193,8 @@ struct archive_entry { int ae_symlink_type; }; +int +archive_entry_set_digest(struct archive_entry *entry, int type, + const unsigned char *digest); + #endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */ diff --git a/libarchive/archive_entry_stat.3 b/libarchive/archive_entry_stat.3 index aa5c8e03f9f..29a53f75607 100644 --- a/libarchive/archive_entry_stat.3 +++ b/libarchive/archive_entry_stat.3 @@ -215,9 +215,9 @@ and set and unset the size, respectively. .Pp The number of references (hardlinks) can be obtained by calling -.Fn archive_entry_nlinks +.Fn archive_entry_nlink and set with -.Fn archive_entry_set_nlinks . +.Fn archive_entry_set_nlink . .Ss Identifying unique files The functions .Fn archive_entry_dev diff --git a/libarchive/archive_ppmd7.c b/libarchive/archive_ppmd7.c index 4029395b4c7..cc3f778203f 100644 --- a/libarchive/archive_ppmd7.c +++ b/libarchive/archive_ppmd7.c @@ -4,7 +4,7 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "archive_platform.h" -#include <memory.h> +#include <stdlib.h> #include "archive_ppmd7_private.h" diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index 4a933b2fc08..c59f0515349 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -892,15 +892,16 @@ archive_read_data(struct archive *_a, void *buff, size_t s) len = a->read_data_remaining; if (len > s) len = s; - if (len) + if (len) { memcpy(dest, a->read_data_block, len); - s -= len; - a->read_data_block += len; - a->read_data_remaining -= len; - a->read_data_output_offset += len; - a->read_data_offset += len; - dest += len; - bytes_read += len; + s -= len; + a->read_data_block += len; + a->read_data_remaining -= len; + a->read_data_output_offset += len; + a->read_data_offset += len; + dest += len; + bytes_read += len; + } } } a->read_data_is_posix_read = 0; diff --git a/libarchive/archive_read_add_passphrase.c b/libarchive/archive_read_add_passphrase.c index cf821b5d483..f0b1ab93300 100644 --- a/libarchive/archive_read_add_passphrase.c +++ b/libarchive/archive_read_add_passphrase.c @@ -57,6 +57,10 @@ insert_passphrase_to_head(struct archive_read *a, { p->next = a->passphrases.first; a->passphrases.first = p; + if (&a->passphrases.first == a->passphrases.last) { + a->passphrases.last = &p->next; + p->next = NULL; + } } static struct archive_read_passphrase * diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index 2a8cec8d117..9c9cf38ee9f 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -103,6 +103,10 @@ __FBSDID("$FreeBSD"); static int setup_mac_metadata(struct archive_read_disk *, struct archive_entry *, int *fd); +#ifdef ARCHIVE_XATTR_FREEBSD +static int setup_xattrs_namespace(struct archive_read_disk *, + struct archive_entry *, int *, int); +#endif static int setup_xattrs(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_sparse(struct archive_read_disk *, @@ -701,14 +705,13 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, } static int -setup_xattrs(struct archive_read_disk *a, - struct archive_entry *entry, int *fd) +setup_xattrs_namespace(struct archive_read_disk *a, + struct archive_entry *entry, int *fd, int namespace) { char buff[512]; char *list, *p; ssize_t list_size; const char *path; - int namespace = EXTATTR_NAMESPACE_USER; path = NULL; @@ -727,6 +730,8 @@ setup_xattrs(struct archive_read_disk *a, if (list_size == -1 && errno == EOPNOTSUPP) return (ARCHIVE_OK); + if (list_size == -1 && errno == EPERM) + return (ARCHIVE_OK); if (list_size == -1) { archive_set_error(&a->archive, errno, "Couldn't list extended attributes"); @@ -760,7 +765,17 @@ setup_xattrs(struct archive_read_disk *a, size_t len = 255 & (int)*p; char *name; - strcpy(buff, "user."); + if (namespace == EXTATTR_NAMESPACE_SYSTEM) { + if (!strcmp(p + 1, "nfs4.acl") || + !strcmp(p + 1, "posix1e.acl_access") || + !strcmp(p + 1, "posix1e.acl_default")) { + p += 1 + len; + continue; + } + strcpy(buff, "system."); + } else { + strcpy(buff, "user."); + } name = buff + strlen(buff); memcpy(name, p + 1, len); name[len] = '\0'; @@ -772,6 +787,31 @@ setup_xattrs(struct archive_read_disk *a, return (ARCHIVE_OK); } +static int +setup_xattrs(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + int namespaces[2]; + int i, res; + + namespaces[0] = EXTATTR_NAMESPACE_USER; + namespaces[1] = EXTATTR_NAMESPACE_SYSTEM; + + for (i = 0; i < 2; i++) { + res = setup_xattrs_namespace(a, entry, fd, + namespaces[i]); + switch (res) { + case (ARCHIVE_OK): + case (ARCHIVE_WARN): + break; + default: + return (res); + } + } + + return (ARCHIVE_OK); +} + #else /* diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 52fec7bb42c..2898206951d 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -1658,7 +1658,7 @@ static int setup_current_filesystem(struct archive_read_disk *a) { struct tree *t = a->tree; - struct statvfs sfs; + struct statvfs svfs; int r, xr = 0; t->current_filesystem->synthetic = -1; @@ -1667,16 +1667,16 @@ setup_current_filesystem(struct archive_read_disk *a) return (ARCHIVE_FAILED); } if (tree_current_is_symblic_link_target(t)) { - r = statvfs(tree_current_access_path(t), &sfs); + r = statvfs(tree_current_access_path(t), &svfs); if (r == 0) xr = get_xfer_size(t, -1, tree_current_access_path(t)); } else { #ifdef HAVE_FSTATVFS - r = fstatvfs(tree_current_dir_fd(t), &sfs); + r = fstatvfs(tree_current_dir_fd(t), &svfs); if (r == 0) xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); #else - r = statvfs(".", &sfs); + r = statvfs(".", &svfs); if (r == 0) xr = get_xfer_size(t, -1, "."); #endif @@ -1688,30 +1688,30 @@ setup_current_filesystem(struct archive_read_disk *a) } else if (xr == 1) { /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN * for pathconf() function. */ - t->current_filesystem->xfer_align = sfs.f_frsize; + t->current_filesystem->xfer_align = svfs.f_frsize; t->current_filesystem->max_xfer_size = -1; #if defined(HAVE_STRUCT_STATVFS_F_IOSIZE) - t->current_filesystem->min_xfer_size = sfs.f_iosize; - t->current_filesystem->incr_xfer_size = sfs.f_iosize; + t->current_filesystem->min_xfer_size = svfs.f_iosize; + t->current_filesystem->incr_xfer_size = svfs.f_iosize; #else - t->current_filesystem->min_xfer_size = sfs.f_bsize; - t->current_filesystem->incr_xfer_size = sfs.f_bsize; + t->current_filesystem->min_xfer_size = svfs.f_bsize; + t->current_filesystem->incr_xfer_size = svfs.f_bsize; #endif } - if (sfs.f_flag & ST_LOCAL) + if (svfs.f_flag & ST_LOCAL) t->current_filesystem->remote = 0; else t->current_filesystem->remote = 1; #if defined(ST_NOATIME) - if (sfs.f_flag & ST_NOATIME) + if (svfs.f_flag & ST_NOATIME) t->current_filesystem->noatime = 1; else #endif t->current_filesystem->noatime = 0; /* Set maximum filename length. */ - t->current_filesystem->name_max = sfs.f_namemax; + t->current_filesystem->name_max = svfs.f_namemax; return (ARCHIVE_OK); } @@ -1840,7 +1840,7 @@ setup_current_filesystem(struct archive_read_disk *a) #if defined(HAVE_STATVFS) if (svfs.f_flag & ST_NOATIME) #else - if (sfs.f_flag & ST_NOATIME) + if (sfs.f_flags & ST_NOATIME) #endif t->current_filesystem->noatime = 1; else @@ -1864,7 +1864,7 @@ static int setup_current_filesystem(struct archive_read_disk *a) { struct tree *t = a->tree; - struct statvfs sfs; + struct statvfs svfs; int r, xr = 0; t->current_filesystem->synthetic = -1;/* Not supported */ @@ -1883,7 +1883,7 @@ setup_current_filesystem(struct archive_read_disk *a) "openat failed"); return (ARCHIVE_FAILED); } - r = fstatvfs(fd, &sfs); + r = fstatvfs(fd, &svfs); if (r == 0) xr = get_xfer_size(t, fd, NULL); close(fd); @@ -1892,13 +1892,13 @@ setup_current_filesystem(struct archive_read_disk *a) archive_set_error(&a->archive, errno, "fchdir failed"); return (ARCHIVE_FAILED); } - r = statvfs(tree_current_access_path(t), &sfs); + r = statvfs(tree_current_access_path(t), &svfs); if (r == 0) xr = get_xfer_size(t, -1, tree_current_access_path(t)); #endif } else { #ifdef HAVE_FSTATVFS - r = fstatvfs(tree_current_dir_fd(t), &sfs); + r = fstatvfs(tree_current_dir_fd(t), &svfs); if (r == 0) xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); #else @@ -1906,7 +1906,7 @@ setup_current_filesystem(struct archive_read_disk *a) archive_set_error(&a->archive, errno, "fchdir failed"); return (ARCHIVE_FAILED); } - r = statvfs(".", &sfs); + r = statvfs(".", &svfs); if (r == 0) xr = get_xfer_size(t, -1, "."); #endif @@ -1918,14 +1918,14 @@ setup_current_filesystem(struct archive_read_disk *a) return (ARCHIVE_FAILED); } else if (xr == 1) { /* pathconf(_PC_REX_*) operations are not supported. */ - t->current_filesystem->xfer_align = sfs.f_frsize; + t->current_filesystem->xfer_align = svfs.f_frsize; t->current_filesystem->max_xfer_size = -1; - t->current_filesystem->min_xfer_size = sfs.f_bsize; - t->current_filesystem->incr_xfer_size = sfs.f_bsize; + t->current_filesystem->min_xfer_size = svfs.f_bsize; + t->current_filesystem->incr_xfer_size = svfs.f_bsize; } #if defined(ST_NOATIME) - if (sfs.f_flag & ST_NOATIME) + if (svfs.f_flag & ST_NOATIME) t->current_filesystem->noatime = 1; else #endif @@ -1933,7 +1933,7 @@ setup_current_filesystem(struct archive_read_disk *a) #if defined(USE_READDIR_R) /* Set maximum filename length. */ - t->current_filesystem->name_max = sfs.f_namemax; + t->current_filesystem->name_max = svfs.f_namemax; #endif return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_filter.3 b/libarchive/archive_read_filter.3 index 1ba5fcbd6ef..4f5c3518a6c 100644 --- a/libarchive/archive_read_filter.3 +++ b/libarchive/archive_read_filter.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 14, 2014 +.Dd June 9, 2020 .Dt ARCHIVE_READ_FILTER 3 .Os .Sh NAME @@ -50,6 +50,8 @@ Streaming Archive Library (libarchive, -larchive) .Ft int .Fn archive_read_support_filter_all "struct archive *" .Ft int +.Fn archive_read_support_filter_by_code "struct archive *" "int" +.Ft int .Fn archive_read_support_filter_bzip2 "struct archive *" .Ft int .Fn archive_read_support_filter_compress "struct archive *" @@ -116,6 +118,14 @@ Note that is always enabled by default. .It Fn archive_read_support_filter_all Enables all available decompression filters. +.It Fn archive_read_support_filter_by_code +Enables a single filter specified by the filter code. +This function does not work with +.Cm ARCHIVE_FILTER_PROGRAM . +Note: In statically-linked executables, this will cause +your program to include support for every filter. +If executable size is a concern, you may wish to avoid +using this function. .It Fn archive_read_support_filter_program Data is fed through the specified external program before being dearchived. Note that this disables automatic detection of the compression format, diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c index 86635e21928..561289b694b 100644 --- a/libarchive/archive_read_open_filename.c +++ b/libarchive/archive_read_open_filename.c @@ -221,7 +221,9 @@ file_open(struct archive *a, void *client_data) struct read_file_data *mine = (struct read_file_data *)client_data; void *buffer; const char *filename = NULL; +#if defined(_WIN32) && !defined(__CYGWIN__) const wchar_t *wfilename = NULL; +#endif int fd = -1; int is_disk_like = 0; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -281,10 +283,12 @@ file_open(struct archive *a, void *client_data) #endif } if (fstat(fd, &st) != 0) { +#if defined(_WIN32) && !defined(__CYGWIN__) if (mine->filename_type == FNT_WCS) archive_set_error(a, errno, "Can't stat '%S'", wfilename); else +#endif archive_set_error(a, errno, "Can't stat '%s'", filename); goto fail; diff --git a/libarchive/archive_read_set_format.c b/libarchive/archive_read_set_format.c index 1d3e49d1647..796dcdcced1 100644 --- a/libarchive/archive_read_set_format.c +++ b/libarchive/archive_read_set_format.c @@ -61,6 +61,9 @@ archive_read_set_format(struct archive *_a, int code) case ARCHIVE_FORMAT_CPIO: strcpy(str, "cpio"); break; + case ARCHIVE_FORMAT_EMPTY: + strcpy(str, "empty"); + break; case ARCHIVE_FORMAT_ISO9660: strcpy(str, "iso9660"); break; @@ -76,9 +79,15 @@ archive_read_set_format(struct archive *_a, int code) case ARCHIVE_FORMAT_RAR_V5: strcpy(str, "rar5"); break; + case ARCHIVE_FORMAT_RAW: + strcpy(str, "raw"); + break; case ARCHIVE_FORMAT_TAR: strcpy(str, "tar"); break; + case ARCHIVE_FORMAT_WARC: + strcpy(str, "warc"); + break; case ARCHIVE_FORMAT_XAR: strcpy(str, "xar"); break; diff --git a/libarchive/archive_read_support_filter_by_code.c b/libarchive/archive_read_support_filter_by_code.c new file mode 100644 index 00000000000..94c4af695f4 --- /dev/null +++ b/libarchive/archive_read_support_filter_by_code.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2020 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#include "archive.h" +#include "archive_private.h" + +int +archive_read_support_filter_by_code(struct archive *a, int filter_code) +{ + archive_check_magic(a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_by_code"); + + switch (filter_code) { + case ARCHIVE_FILTER_NONE: + return archive_read_support_filter_none(a); + break; + case ARCHIVE_FILTER_GZIP: + return archive_read_support_filter_gzip(a); + break; + case ARCHIVE_FILTER_BZIP2: + return archive_read_support_filter_bzip2(a); + break; + case ARCHIVE_FILTER_COMPRESS: + return archive_read_support_filter_compress(a); + break; + case ARCHIVE_FILTER_LZMA: + return archive_read_support_filter_lzma(a); + break; + case ARCHIVE_FILTER_XZ: + return archive_read_support_filter_xz(a); + break; + case ARCHIVE_FILTER_UU: + return archive_read_support_filter_uu(a); + break; + case ARCHIVE_FILTER_RPM: + return archive_read_support_filter_rpm(a); + break; + case ARCHIVE_FILTER_LZIP: + return archive_read_support_filter_lzip(a); + break; + case ARCHIVE_FILTER_LRZIP: + return archive_read_support_filter_lrzip(a); + break; + case ARCHIVE_FILTER_LZOP: + return archive_read_support_filter_lzop(a); + break; + case ARCHIVE_FILTER_GRZIP: + return archive_read_support_filter_grzip(a); + break; + case ARCHIVE_FILTER_LZ4: + return archive_read_support_filter_lz4(a); + break; + case ARCHIVE_FILTER_ZSTD: + return archive_read_support_filter_zstd(a); + break; + } + return (ARCHIVE_FATAL); +} diff --git a/libarchive/archive_read_support_filter_program.c b/libarchive/archive_read_support_filter_program.c index b8bf12886f3..bf5b6f2b3c8 100644 --- a/libarchive/archive_read_support_filter_program.c +++ b/libarchive/archive_read_support_filter_program.c @@ -400,7 +400,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) static const size_t out_buf_len = 65536; char *out_buf; const char *prefix = "Program: "; - pid_t child; + int ret; size_t l; l = strlen(prefix) + strlen(cmd) + 1; @@ -426,9 +426,9 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) state->out_buf = out_buf; state->out_buf_len = out_buf_len; - child = __archive_create_child(cmd, &state->child_stdin, - &state->child_stdout); - if (child == -1) { + ret = __archive_create_child(cmd, &state->child_stdin, + &state->child_stdout, &state->child); + if (ret != ARCHIVE_OK) { free(state->out_buf); archive_string_free(&state->description); free(state); @@ -437,21 +437,6 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) cmd); return (ARCHIVE_FATAL); } -#if defined(_WIN32) && !defined(__CYGWIN__) - state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child); - if (state->child == NULL) { - child_stop(self, state); - free(state->out_buf); - archive_string_free(&state->description); - free(state); - archive_set_error(&self->archive->archive, EINVAL, - "Can't initialize filter; unable to run program \"%s\"", - cmd); - return (ARCHIVE_FATAL); - } -#else - state->child = child; -#endif self->data = state; self->read = program_filter_read; diff --git a/libarchive/archive_read_support_filter_zstd.c b/libarchive/archive_read_support_filter_zstd.c index c8bb36be703..af7eeb7c1e2 100644 --- a/libarchive/archive_read_support_filter_zstd.c +++ b/libarchive/archive_read_support_filter_zstd.c @@ -119,6 +119,8 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, /* Zstd frame magic values */ const unsigned zstd_magic = 0xFD2FB528U; + const unsigned zstd_magic_skippable_start = 0x184D2A50U; + const unsigned zstd_magic_skippable_mask = 0xFFFFFFF0; (void) self; /* UNUSED */ @@ -129,6 +131,8 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, prefix = archive_le32dec(buffer); if (prefix == zstd_magic) return (32); + if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start) + return (32); return (0); } diff --git a/libarchive/archive_read_support_format_by_code.c b/libarchive/archive_read_support_format_by_code.c index 034353d78f6..89e96f1f591 100644 --- a/libarchive/archive_read_support_format_by_code.c +++ b/libarchive/archive_read_support_format_by_code.c @@ -26,6 +26,10 @@ #include "archive_platform.h" __FBSDID("$FreeBSD$"); +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + #include "archive.h" #include "archive_private.h" @@ -48,6 +52,9 @@ archive_read_support_format_by_code(struct archive *a, int format_code) case ARCHIVE_FORMAT_CPIO: return archive_read_support_format_cpio(a); break; + case ARCHIVE_FORMAT_EMPTY: + return archive_read_support_format_empty(a); + break; case ARCHIVE_FORMAT_ISO9660: return archive_read_support_format_iso9660(a); break; @@ -63,9 +70,15 @@ archive_read_support_format_by_code(struct archive *a, int format_code) case ARCHIVE_FORMAT_RAR_V5: return archive_read_support_format_rar5(a); break; + case ARCHIVE_FORMAT_RAW: + return archive_read_support_format_raw(a); + break; case ARCHIVE_FORMAT_TAR: return archive_read_support_format_tar(a); break; + case ARCHIVE_FORMAT_WARC: + return archive_read_support_format_warc(a); + break; case ARCHIVE_FORMAT_XAR: return archive_read_support_format_xar(a); break; @@ -73,5 +86,7 @@ archive_read_support_format_by_code(struct archive *a, int format_code) return archive_read_support_format_zip(a); break; } + archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, + "Invalid format code specified"); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index a6475308e01..43738b53744 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -1172,7 +1172,7 @@ cab_checksum_finish(struct archive_read *a) cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); if (cfdata->sum_calculated != cfdata->sum) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Checksum error CFDATA[%d] %x:%x in %d bytes", + "Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes", cab->entry_cffolder->cfdata_index -1, cfdata->sum, cfdata->sum_calculated, cfdata->compressed_size); diff --git a/libarchive/archive_read_support_format_empty.c b/libarchive/archive_read_support_format_empty.c index c641eb9b150..53fb6cc4743 100644 --- a/libarchive/archive_read_support_format_empty.c +++ b/libarchive/archive_read_support_format_empty.c @@ -47,7 +47,7 @@ archive_read_support_format_empty(struct archive *_a) r = __archive_read_register_format(a, NULL, - NULL, + "empty", archive_read_format_empty_bid, NULL, archive_read_format_empty_read_header, diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index 332944ac51b..93ba2959a3c 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011 #include "archive.h" #include "archive_entry.h" +#include "archive_entry_private.h" #include "archive_private.h" #include "archive_rb.h" #include "archive_read_private.h" @@ -135,6 +136,9 @@ static int skip(struct archive_read *a); static int read_header(struct archive_read *, struct archive_entry *); static int64_t mtree_atol(char **, int base); +#ifndef HAVE_STRNLEN +static size_t mtree_strnlen(const char *, size_t); +#endif /* * There's no standard for TIME_T_MAX/TIME_T_MIN. So we compute them @@ -186,6 +190,24 @@ get_time_t_min(void) #endif } +#ifdef HAVE_STRNLEN +#define mtree_strnlen(a,b) strnlen(a,b) +#else +static size_t +mtree_strnlen(const char *p, size_t maxlen) +{ + size_t i; + + for (i = 0; i <= maxlen; i++) { + if (p[i] == 0) + break; + } + if (i > maxlen) + return (-1);/* invalid */ + return (i); +} +#endif + static int archive_read_format_mtree_options(struct archive_read *a, const char *key, const char *val) @@ -1482,6 +1504,84 @@ parse_device(dev_t *pdev, struct archive *a, char *val) #undef MAX_PACK_ARGS } +static int +parse_hex_nibble(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return 10 + c - 'a'; +#if 0 + /* XXX: Is uppercase something we should support? */ + if (c >= 'A' && c <= 'F') + return 10 + c - 'A'; +#endif + + return -1; +} + +static int +parse_digest(struct archive_read *a, struct archive_entry *entry, + const char *digest, int type) +{ + unsigned char digest_buf[64]; + int high, low; + size_t i, j, len; + + switch (type) { + case ARCHIVE_ENTRY_DIGEST_MD5: + len = sizeof(entry->digest.md5); + break; + case ARCHIVE_ENTRY_DIGEST_RMD160: + len = sizeof(entry->digest.rmd160); + break; + case ARCHIVE_ENTRY_DIGEST_SHA1: + len = sizeof(entry->digest.sha1); + break; + case ARCHIVE_ENTRY_DIGEST_SHA256: + len = sizeof(entry->digest.sha256); + break; + case ARCHIVE_ENTRY_DIGEST_SHA384: + len = sizeof(entry->digest.sha384); + break; + case ARCHIVE_ENTRY_DIGEST_SHA512: + len = sizeof(entry->digest.sha512); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unknown digest type"); + return ARCHIVE_FATAL; + } + + if (len > sizeof(digest_buf)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Digest storage too large"); + return ARCHIVE_FATAL; + } + + len *= 2; + + if (mtree_strnlen(digest, len+1) != len) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "incorrect digest length, ignoring"); + return ARCHIVE_WARN; + } + + for (i = 0, j = 0; i < len; i += 2, j++) { + high = parse_hex_nibble(digest[i]); + low = parse_hex_nibble(digest[i+1]); + if (high == -1 || low == -1) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "invalid digest data, ignoring"); + return ARCHIVE_WARN; + } + + digest_buf[j] = high << 4 | low; + } + + return archive_entry_set_digest(entry, type, digest_buf); +} + /* * Parse a single keyword and its value. */ @@ -1580,8 +1680,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, } __LA_FALLTHROUGH; case 'm': - if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) - break; + if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) { + return parse_digest(a, entry, val, + ARCHIVE_ENTRY_DIGEST_MD5); + } if (strcmp(key, "mode") == 0) { if (val[0] >= '0' && val[0] <= '7') { *parsed_kws |= MTREE_HAS_PERM; @@ -1617,21 +1719,32 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, return r; } if (strcmp(key, "rmd160") == 0 || - strcmp(key, "rmd160digest") == 0) - break; + strcmp(key, "rmd160digest") == 0) { + return parse_digest(a, entry, val, + ARCHIVE_ENTRY_DIGEST_RMD160); + } __LA_FALLTHROUGH; case 's': - if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0) - break; + if (strcmp(key, "sha1") == 0 || + strcmp(key, "sha1digest") == 0) { + return parse_digest(a, entry, val, + ARCHIVE_ENTRY_DIGEST_SHA1); + } if (strcmp(key, "sha256") == 0 || - strcmp(key, "sha256digest") == 0) - break; + strcmp(key, "sha256digest") == 0) { + return parse_digest(a, entry, val, + ARCHIVE_ENTRY_DIGEST_SHA256); + } if (strcmp(key, "sha384") == 0 || - strcmp(key, "sha384digest") == 0) - break; + strcmp(key, "sha384digest") == 0) { + return parse_digest(a, entry, val, + ARCHIVE_ENTRY_DIGEST_SHA384); + } if (strcmp(key, "sha512") == 0 || - strcmp(key, "sha512digest") == 0) - break; + strcmp(key, "sha512digest") == 0) { + return parse_digest(a, entry, val, + ARCHIVE_ENTRY_DIGEST_SHA512); + } if (strcmp(key, "size") == 0) { archive_entry_set_size(entry, mtree_atol(&val, 10)); break; diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 98efbb1a6c4..283a9604447 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -151,6 +151,9 @@ #undef minimum #define minimum(a, b) ((a)<(b)?(a):(b)) +/* Stack overflow check */ +#define MAX_COMPRESS_DEPTH 1024 + /* Fields common to all headers */ struct rar_header { @@ -340,7 +343,7 @@ static int read_symlink_stored(struct archive_read *, struct archive_entry *, static int read_data_stored(struct archive_read *, const void **, size_t *, int64_t *); static int read_data_compressed(struct archive_read *, const void **, size_t *, - int64_t *); + int64_t *, size_t); static int rar_br_preparation(struct archive_read *, struct rar_br *); static int parse_codes(struct archive_read *); static void free_codes(struct archive_read *); @@ -1026,7 +1029,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, case COMPRESS_METHOD_NORMAL: case COMPRESS_METHOD_GOOD: case COMPRESS_METHOD_BEST: - ret = read_data_compressed(a, buff, size, offset); + ret = read_data_compressed(a, buff, size, offset, 0); if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) { __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); rar->start_new_table = 1; @@ -1883,8 +1886,11 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, static int read_data_compressed(struct archive_read *a, const void **buff, size_t *size, - int64_t *offset) + int64_t *offset, size_t looper) { + if (looper++ > MAX_COMPRESS_DEPTH) + return (ARCHIVE_FATAL); + struct rar *rar; int64_t start, end, actualend; size_t bs; @@ -1982,7 +1988,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { case 0: rar->start_new_table = 1; - return read_data_compressed(a, buff, size, offset); + return read_data_compressed(a, buff, size, offset, looper); case 2: rar->ppmd_eod = 1;/* End Of ppmd Data. */ diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c index 82729bdcdb3..58a61d1bcb2 100644 --- a/libarchive/archive_read_support_format_rar5.c +++ b/libarchive/archive_read_support_format_rar5.c @@ -3084,12 +3084,6 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { continue; } - - /* The program counter shouldn't reach here. */ - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unsupported block code: 0x%x", num); - - return ARCHIVE_FATAL; } return ARCHIVE_OK; @@ -3837,7 +3831,7 @@ static int verify_checksums(struct archive_read* a) { DEBUG_CODE { printf("Checksum error: CRC32 " - "(was: %08x, expected: %08x)\n", + "(was: %08" PRIx32 ", expected: %08" PRIx32 ")\n", rar->file.calculated_crc32, rar->file.stored_crc32); } @@ -3851,7 +3845,7 @@ static int verify_checksums(struct archive_read* a) { } else { DEBUG_CODE { printf("Checksum OK: CRC32 " - "(%08x/%08x)\n", + "(%08" PRIx32 "/%08" PRIx32 ")\n", rar->file.stored_crc32, rar->file.calculated_crc32); } @@ -3912,6 +3906,9 @@ static int rar5_read_data(struct archive_read *a, const void **buff, int ret; struct rar5* rar = get_context(a); + if (size) + *size = 0; + if(rar->file.dir > 0) { /* Don't process any data if this file entry was declared * as a directory. This is needed, because entries marked as diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index c63d46fc0ce..96d8101844f 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -1796,6 +1796,16 @@ pax_attribute_schily_xattr(struct archive_entry *entry, return 0; } +static int +pax_attribute_rht_security_selinux(struct archive_entry *entry, + const char *value, size_t value_length) +{ + archive_entry_xattr_add_entry(entry, "security.selinux", + value, value_length); + + return 0; +} + static int pax_attribute_acl(struct archive_read *a, struct tar *tar, struct archive_entry *entry, const char *value, int type) @@ -1966,6 +1976,14 @@ pax_attribute(struct archive_read *a, struct tar *tar, if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0) pax_attribute_xattr(entry, key, value); break; + case 'R': + /* GNU tar uses RHT.security header to store SELinux xattrs + * SCHILY.xattr.security.selinux == RHT.security.selinux */ + if (strcmp(key, "RHT.security.selinux") == 0) { + pax_attribute_rht_security_selinux(entry, value, + value_length); + } + break; case 'S': /* We support some keys used by the "star" archiver */ if (strcmp(key, "SCHILY.acl.access") == 0) { diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c index 72977b8e073..27329962d6d 100644 --- a/libarchive/archive_read_support_format_warc.c +++ b/libarchive/archive_read_support_format_warc.c @@ -127,7 +127,7 @@ static int _warc_skip(struct archive_read *a); static int _warc_rdhdr(struct archive_read *a, struct archive_entry *e); /* private routines */ -static unsigned int _warc_rdver(const char buf[10], size_t bsz); +static unsigned int _warc_rdver(const char *buf, size_t bsz); static unsigned int _warc_rdtyp(const char *buf, size_t bsz); static warc_string_t _warc_rduri(const char *buf, size_t bsz); static ssize_t _warc_rdlen(const char *buf, size_t bsz); @@ -337,6 +337,14 @@ _warc_rdhdr(struct archive_read *a, struct archive_entry *entry) mtime = rtime; } break; + case WT_NONE: + case WT_INFO: + case WT_META: + case WT_REQ: + case WT_RVIS: + case WT_CONV: + case WT_CONT: + case LAST_WT: default: fnam.len = 0U; fnam.str = NULL; @@ -361,6 +369,14 @@ _warc_rdhdr(struct archive_read *a, struct archive_entry *entry) break; } /* FALLTHROUGH */ + case WT_NONE: + case WT_INFO: + case WT_META: + case WT_REQ: + case WT_RVIS: + case WT_CONV: + case WT_CONT: + case LAST_WT: default: /* consume the content and start over */ _warc_skip(a); @@ -427,7 +443,7 @@ _warc_skip(struct archive_read *a) static void* deconst(const void *c) { - return (char *)0x1 + (((const char *)c) - (const char *)0x1); + return (void *)(uintptr_t)c; } static char* diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c index 7f8be398c7a..503ff58b91d 100644 --- a/libarchive/archive_read_support_format_xar.c +++ b/libarchive/archive_read_support_format_xar.c @@ -458,6 +458,11 @@ archive_read_support_format_xar(struct archive *_a) return (ARCHIVE_FATAL); } + /* initialize xar->file_queue */ + xar->file_queue.allocated = 0; + xar->file_queue.used = 0; + xar->file_queue.files = NULL; + r = __archive_read_register_format(a, xar, "xar", @@ -1221,10 +1226,12 @@ heap_add_entry(struct archive_read *a, /* Expand our pending files list as necessary. */ if (heap->used >= heap->allocated) { struct xar_file **new_pending_files; - int new_size = heap->allocated * 2; + int new_size; if (heap->allocated < 1024) new_size = 1024; + else + new_size = heap->allocated * 2; /* Overflow might keep us from growing the list. */ if (new_size <= heap->allocated) { archive_set_error(&a->archive, @@ -1238,9 +1245,11 @@ heap_add_entry(struct archive_read *a, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - memcpy(new_pending_files, heap->files, - heap->allocated * sizeof(new_pending_files[0])); - free(heap->files); + if (heap->allocated) { + memcpy(new_pending_files, heap->files, + heap->allocated * sizeof(new_pending_files[0])); + free(heap->files); + } heap->files = new_pending_files; heap->allocated = new_size; } diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 6581ca0acf6..a64332c2818 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -899,6 +899,81 @@ process_extra(struct archive_read *a, struct archive_entry *entry, return ARCHIVE_OK; } +#if HAVE_LZMA_H && HAVE_LIBLZMA +/* + * Auxiliary function to uncompress data chunk from zipx archive + * (zip with lzma compression). + */ +static int +zipx_lzma_uncompress_buffer(const char *compressed_buffer, + size_t compressed_buffer_size, + char *uncompressed_buffer, + size_t uncompressed_buffer_size) +{ + int status = ARCHIVE_FATAL; + // length of 'lzma properties data' in lzma compressed + // data segment (stream) inside zip archive + const size_t lzma_params_length = 5; + // offset of 'lzma properties data' from the beginning of lzma stream + const size_t lzma_params_offset = 4; + // end position of 'lzma properties data' in lzma stream + const size_t lzma_params_end = lzma_params_offset + lzma_params_length; + if (compressed_buffer == NULL || + compressed_buffer_size < lzma_params_end || + uncompressed_buffer == NULL) + return status; + + // prepare header for lzma_alone_decoder to replace zipx header + // (see comments in 'zipx_lzma_alone_init' for justification) +#pragma pack(push) +#pragma pack(1) + struct _alone_header + { + uint8_t bytes[5]; // lzma_params_length + uint64_t uncompressed_size; + } alone_header; +#pragma pack(pop) + // copy 'lzma properties data' blob + memcpy(&alone_header.bytes[0], compressed_buffer + lzma_params_offset, + lzma_params_length); + alone_header.uncompressed_size = UINT64_MAX; + + // prepare new compressed buffer, see 'zipx_lzma_alone_init' for details + const size_t lzma_alone_buffer_size = + compressed_buffer_size - lzma_params_end + sizeof(alone_header); + unsigned char *lzma_alone_compressed_buffer = + (unsigned char*) malloc(lzma_alone_buffer_size); + if (lzma_alone_compressed_buffer == NULL) + return status; + // copy lzma_alone header into new buffer + memcpy(lzma_alone_compressed_buffer, (void*) &alone_header, + sizeof(alone_header)); + // copy compressed data into new buffer + memcpy(lzma_alone_compressed_buffer + sizeof(alone_header), + compressed_buffer + lzma_params_end, + compressed_buffer_size - lzma_params_end); + + // create and fill in lzma_alone_decoder stream + lzma_stream stream = LZMA_STREAM_INIT; + lzma_ret ret = lzma_alone_decoder(&stream, UINT64_MAX); + if (ret == LZMA_OK) + { + stream.next_in = lzma_alone_compressed_buffer; + stream.avail_in = lzma_alone_buffer_size; + stream.total_in = 0; + stream.next_out = (unsigned char*)uncompressed_buffer; + stream.avail_out = uncompressed_buffer_size; + stream.total_out = 0; + ret = lzma_code(&stream, LZMA_RUN); + if (ret == LZMA_OK || ret == LZMA_STREAM_END) + status = ARCHIVE_OK; + } + lzma_end(&stream); + free(lzma_alone_compressed_buffer); + return status; +} +#endif + /* * Assumes file pointer is at beginning of local file header. */ @@ -1173,18 +1248,64 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, "Truncated Zip file"); return ARCHIVE_FATAL; } + // take into account link compression if any + size_t linkname_full_length = linkname_length; + if (zip->entry->compression != 0) + { + // symlink target string appeared to be compressed + int status = ARCHIVE_FATAL; + char *uncompressed_buffer = + (char*) malloc(zip_entry->uncompressed_size); + if (uncompressed_buffer == NULL) + { + archive_set_error(&a->archive, ENOMEM, + "No memory for lzma decompression"); + return status; + } + + switch (zip->entry->compression) + { +#if HAVE_LZMA_H && HAVE_LIBLZMA + case 14: /* ZIPx LZMA compression. */ + /*(see zip file format specification, section 4.4.5)*/ + status = zipx_lzma_uncompress_buffer(p, + linkname_length, + uncompressed_buffer, + (size_t)zip_entry->uncompressed_size); + break; +#endif + default: /* Unsupported compression. */ + break; + } + if (status == ARCHIVE_OK) + { + p = uncompressed_buffer; + linkname_full_length = + (size_t)zip_entry->uncompressed_size; + } + else + { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported ZIP compression method " + "during decompression of link entry (%d: %s)", + zip->entry->compression, + compression_name(zip->entry->compression)); + return ARCHIVE_FAILED; + } + } sconv = zip->sconv; if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME)) sconv = zip->sconv_utf8; if (sconv == NULL) sconv = zip->sconv_default; - if (archive_entry_copy_symlink_l(entry, p, linkname_length, + if (archive_entry_copy_symlink_l(entry, p, linkname_full_length, sconv) != 0) { if (errno != ENOMEM && sconv == zip->sconv_utf8 && (zip->entry->zip_flags & ZIP_UTF8_NAME)) archive_entry_copy_symlink_l(entry, p, - linkname_length, NULL); + linkname_full_length, NULL); if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Symlink"); @@ -1901,15 +2022,15 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip) if(order < 2 || restore_method > 2) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Invalid parameter set in PPMd8 stream (order=%d, " - "restore=%d)", order, restore_method); + "Invalid parameter set in PPMd8 stream (order=%" PRId32 ", " + "restore=%" PRId32 ")", order, restore_method); return (ARCHIVE_FAILED); } /* Allocate the memory needed to properly decompress the file. */ if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) { archive_set_error(&a->archive, ENOMEM, - "Unable to allocate memory for PPMd8 stream: %d bytes", + "Unable to allocate memory for PPMd8 stream: %" PRId32 " bytes", mem << 20); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index c77dcf52c25..7460ded0023 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -3881,6 +3881,11 @@ archive_mstring_get_utf8(struct archive *a, struct archive_mstring *aes, } *p = NULL; + /* Try converting WCS to MBS first if MBS does not exist yet. */ + if ((aes->aes_set & AES_SET_MBS) == 0) { + const char *pm; /* unused */ + archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */ + } if (aes->aes_set & AES_SET_MBS) { sc = archive_string_conversion_to_charset(a, "UTF-8", 1); if (sc == NULL) @@ -3903,9 +3908,9 @@ int archive_mstring_get_mbs(struct archive *a, struct archive_mstring *aes, const char **p) { + struct archive_string_conv *sc; int r, ret = 0; - (void)a; /* UNUSED */ /* If we already have an MBS form, return that immediately. */ if (aes->aes_set & AES_SET_MBS) { *p = aes->aes_mbs.s; @@ -3926,10 +3931,23 @@ archive_mstring_get_mbs(struct archive *a, struct archive_mstring *aes, ret = -1; } - /* - * Only a UTF-8 form cannot avail because its conversion already - * failed at archive_mstring_update_utf8(). - */ + /* If there's a UTF-8 form, try converting with the native locale. */ + if (aes->aes_set & AES_SET_UTF8) { + archive_string_empty(&(aes->aes_mbs)); + sc = archive_string_conversion_from_charset(a, "UTF-8", 1); + if (sc == NULL) + return (-1);/* Couldn't allocate memory for sc. */ + r = archive_strncpy_l(&(aes->aes_mbs), + aes->aes_utf8.s, aes->aes_utf8.length, sc); + if (a == NULL) + free_sconv_object(sc); + *p = aes->aes_mbs.s; + if (r == 0) { + aes->aes_set |= AES_SET_MBS; + ret = 0;/* success; overwrite previous error. */ + } else + ret = -1;/* failure. */ + } return (ret); } @@ -3947,6 +3965,11 @@ archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes, } *wp = NULL; + /* Try converting UTF8 to MBS first if MBS does not exist yet. */ + if ((aes->aes_set & AES_SET_MBS) == 0) { + const char *p; /* unused */ + archive_mstring_get_mbs(a, aes, &p); /* ignore errors, we'll handle it later */ + } /* Try converting MBS to WCS using native locale. */ if (aes->aes_set & AES_SET_MBS) { archive_wstring_empty(&(aes->aes_wcs)); @@ -3962,11 +3985,12 @@ archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes, } int -archive_mstring_get_mbs_l(struct archive_mstring *aes, +archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes, const char **p, size_t *length, struct archive_string_conv *sc) { int r, ret = 0; + (void)r; /* UNUSED */ #if defined(_WIN32) && !defined(__CYGWIN__) /* * Internationalization programming on Windows must use Wide @@ -3989,20 +4013,12 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes, } #endif - /* If there is not an MBS form but is a WCS form, try converting + /* If there is not an MBS form but there is a WCS or UTF8 form, try converting * with the native locale to be used for translating it to specified * character-set. */ - if ((aes->aes_set & AES_SET_MBS) == 0 && - (aes->aes_set & AES_SET_WCS) != 0) { - archive_string_empty(&(aes->aes_mbs)); - r = archive_string_append_from_wcs(&(aes->aes_mbs), - aes->aes_wcs.s, aes->aes_wcs.length); - if (r == 0) - aes->aes_set |= AES_SET_MBS; - else if (errno == ENOMEM) - return (-1); - else - ret = -1; + if ((aes->aes_set & AES_SET_MBS) == 0) { + const char *pm; /* unused */ + archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */ } /* If we already have an MBS form, use it to be translated to * specified character-set. */ diff --git a/libarchive/archive_string.h b/libarchive/archive_string.h index 27e1ad69c56..49d7d3064a3 100644 --- a/libarchive/archive_string.h +++ b/libarchive/archive_string.h @@ -226,7 +226,7 @@ void archive_mstring_copy(struct archive_mstring *dest, struct archive_mstring * int archive_mstring_get_mbs(struct archive *, struct archive_mstring *, const char **); int archive_mstring_get_utf8(struct archive *, struct archive_mstring *, const char **); int archive_mstring_get_wcs(struct archive *, struct archive_mstring *, const wchar_t **); -int archive_mstring_get_mbs_l(struct archive_mstring *, const char **, +int archive_mstring_get_mbs_l(struct archive *, struct archive_mstring *, const char **, size_t *, struct archive_string_conv *); int archive_mstring_copy_mbs(struct archive_mstring *, const char *mbs); int archive_mstring_copy_mbs_len(struct archive_mstring *, const char *mbs, diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c index 288a44280dc..b1582edbe30 100644 --- a/libarchive/archive_util.c +++ b/libarchive/archive_util.c @@ -365,6 +365,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) } fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); if (fd == -1) { + la_dosmaperr(GetLastError()); CloseHandle(h); goto exit_tmpfile; } else @@ -432,6 +433,11 @@ __archive_mktemp(const char *tmpdir) if (temp_name.s[temp_name.length-1] != '/') archive_strappend_char(&temp_name, '/'); } +#ifdef O_TMPFILE + fd = open(temp_name.s, O_RDWR|O_CLOEXEC|O_TMPFILE|O_EXCL, 0600); + if(fd >= 0) + goto exit_tmpfile; +#endif archive_strcat(&temp_name, "libarchive_XXXXXX"); fd = mkstemp(temp_name.s); if (fd < 0) diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c index 98a55fb2aa0..8d70f51a6b5 100644 --- a/libarchive/archive_write.c +++ b/libarchive/archive_write.c @@ -455,6 +455,25 @@ archive_write_client_write(struct archive_write_filter *f, return (ARCHIVE_OK); } +static int +archive_write_client_free(struct archive_write_filter *f) +{ + struct archive_write *a = (struct archive_write *)f->archive; + + if (a->client_freer) + (*a->client_freer)(&a->archive, a->client_data); + a->client_data = NULL; + + /* Clear passphrase. */ + if (a->passphrase != NULL) { + memset(a->passphrase, 0, strlen(a->passphrase)); + free(a->passphrase); + a->passphrase = NULL; + } + + return (ARCHIVE_OK); +} + static int archive_write_client_close(struct archive_write_filter *f) { @@ -493,13 +512,7 @@ archive_write_client_close(struct archive_write_filter *f) (*a->client_closer)(&a->archive, a->client_data); free(state->buffer); free(state); - a->client_data = NULL; - /* Clear passphrase. */ - if (a->passphrase != NULL) { - memset(a->passphrase, 0, strlen(a->passphrase)); - free(a->passphrase); - a->passphrase = NULL; - } + /* Clear the close handler myself not to be called again. */ f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED; return (ret); @@ -509,9 +522,9 @@ archive_write_client_close(struct archive_write_filter *f) * Open the archive using the current settings. */ int -archive_write_open(struct archive *_a, void *client_data, +archive_write_open2(struct archive *_a, void *client_data, archive_open_callback *opener, archive_write_callback *writer, - archive_close_callback *closer) + archive_close_callback *closer, archive_free_callback *freer) { struct archive_write *a = (struct archive_write *)_a; struct archive_write_filter *client_filter; @@ -524,12 +537,14 @@ archive_write_open(struct archive *_a, void *client_data, a->client_writer = writer; a->client_opener = opener; a->client_closer = closer; + a->client_freer = freer; a->client_data = client_data; client_filter = __archive_write_allocate_filter(_a); client_filter->open = archive_write_client_open; client_filter->write = archive_write_client_write; client_filter->close = archive_write_client_close; + client_filter->free = archive_write_client_free; ret = __archive_write_filters_open(a); if (ret < ARCHIVE_WARN) { @@ -544,6 +559,15 @@ archive_write_open(struct archive *_a, void *client_data, return (ret); } +int +archive_write_open(struct archive *_a, void *client_data, + archive_open_callback *opener, archive_write_callback *writer, + archive_close_callback *closer) +{ + return archive_write_open2(_a, client_data, opener, writer, + closer, NULL); +} + /* * Close out the archive. */ diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c index a4bc1d90eda..c096e7227ba 100644 --- a/libarchive/archive_write_add_filter_program.c +++ b/libarchive/archive_write_add_filter_program.c @@ -196,10 +196,6 @@ __archive_write_program_free(struct archive_write_program_data *data) { if (data) { -#if defined(_WIN32) && !defined(__CYGWIN__) - if (data->child) - CloseHandle(data->child); -#endif free(data->program_name); free(data->child_buf); free(data); @@ -211,7 +207,7 @@ int __archive_write_program_open(struct archive_write_filter *f, struct archive_write_program_data *data, const char *cmd) { - pid_t child; + int ret; if (data->child_buf == NULL) { data->child_buf_len = 65536; @@ -225,27 +221,13 @@ __archive_write_program_open(struct archive_write_filter *f, } } - child = __archive_create_child(cmd, &data->child_stdin, - &data->child_stdout); - if (child == -1) { + ret = __archive_create_child(cmd, &data->child_stdin, + &data->child_stdout, &data->child); + if (ret != ARCHIVE_OK) { archive_set_error(f->archive, EINVAL, "Can't launch external program: %s", cmd); return (ARCHIVE_FATAL); } -#if defined(_WIN32) && !defined(__CYGWIN__) - data->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child); - if (data->child == NULL) { - close(data->child_stdin); - data->child_stdin = -1; - close(data->child_stdout); - data->child_stdout = -1; - archive_set_error(f->archive, EINVAL, - "Can't launch external program: %s", cmd); - return (ARCHIVE_FATAL); - } -#else - data->child = child; -#endif return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_xz.c b/libarchive/archive_write_add_filter_xz.c index 8c1ebb805b1..9dd2c30e5de 100644 --- a/libarchive/archive_write_add_filter_xz.c +++ b/libarchive/archive_write_add_filter_xz.c @@ -382,8 +382,8 @@ archive_compressor_xz_options(struct archive_write_filter *f, value[1] != '\0') return (ARCHIVE_WARN); data->compression_level = value[0] - '0'; - if (data->compression_level > 6) - data->compression_level = 6; + if (data->compression_level > 9) + data->compression_level = 9; return (ARCHIVE_OK); } else if (strcmp(key, "threads") == 0) { char *endptr; diff --git a/libarchive/archive_write_add_filter_zstd.c b/libarchive/archive_write_add_filter_zstd.c index 4c91551ed3e..c74a35cded2 100644 --- a/libarchive/archive_write_add_filter_zstd.c +++ b/libarchive/archive_write_add_filter_zstd.c @@ -59,6 +59,16 @@ struct private_data { #endif }; +/* If we don't have the library use default range values (zstdcli.c v1.4.0) */ +#define CLEVEL_MIN -99 +#define CLEVEL_STD_MIN 0 /* prior to 1.3.4 and more recent without using --fast */ +#define CLEVEL_DEFAULT 3 +#define CLEVEL_STD_MAX 19 /* without using --ultra */ +#define CLEVEL_MAX 22 + +#define MINVER_NEGCLEVEL 10304 +#define MINVER_MINCLEVEL 10306 + static int archive_compressor_zstd_options(struct archive_write_filter *, const char *, const char *); static int archive_compressor_zstd_open(struct archive_write_filter *); @@ -96,7 +106,7 @@ archive_write_add_filter_zstd(struct archive *_a) f->free = &archive_compressor_zstd_free; f->code = ARCHIVE_FILTER_ZSTD; f->name = "zstd"; - data->compression_level = 3; /* Default level used by the zstd CLI */ + data->compression_level = CLEVEL_DEFAULT; #if HAVE_ZSTD_H && HAVE_LIBZSTD data->cstream = ZSTD_createCStream(); if (data->cstream == NULL) { @@ -135,6 +145,31 @@ archive_compressor_zstd_free(struct archive_write_filter *f) return (ARCHIVE_OK); } +static int string_is_numeric (const char* value) +{ + size_t len = strlen(value); + size_t i; + + if (len == 0) { + return (ARCHIVE_WARN); + } + else if (len == 1 && !(value[0] >= '0' && value[0] <= '9')) { + return (ARCHIVE_WARN); + } + else if (!(value[0] >= '0' && value[0] <= '9') && + value[0] != '-' && value[0] != '+') { + return (ARCHIVE_WARN); + } + + for (i = 1; i < len; i++) { + if (!(value[i] >= '0' && value[i] <= '9')) { + return (ARCHIVE_WARN); + } + } + + return (ARCHIVE_OK); +} + /* * Set write options. */ @@ -146,12 +181,25 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key, if (strcmp(key, "compression-level") == 0) { int level = atoi(value); -#if HAVE_ZSTD_H && HAVE_LIBZSTD - if (level < 1 || level > ZSTD_maxCLevel()) { -#else /* If we don't have the library, hard-code the max level */ - if (level < 1 || level > 22) { + int minimum = CLEVEL_MIN; + int maximum = CLEVEL_MAX; + if (string_is_numeric(value) != ARCHIVE_OK) { + return (ARCHIVE_WARN); + } +#if HAVE_ZSTD_H && HAVE_LIBZSTD + maximum = ZSTD_maxCLevel(); +#if ZSTD_VERSION_NUMBER >= MINVER_MINCLEVEL + if (ZSTD_versionNumber() >= MINVER_MINCLEVEL) { + minimum = ZSTD_minCLevel(); + } + else +#endif + if (ZSTD_versionNumber() < MINVER_NEGCLEVEL) { + minimum = CLEVEL_STD_MIN; + } #endif + if (level < minimum || level > maximum) { return (ARCHIVE_WARN); } data->compression_level = level; @@ -297,7 +345,26 @@ archive_compressor_zstd_open(struct archive_write_filter *f) int r; archive_string_init(&as); - archive_string_sprintf(&as, "zstd -%d", data->compression_level); + /* --no-check matches library default */ + archive_strcpy(&as, "zstd --no-check"); + + if (data->compression_level < CLEVEL_STD_MIN) { + struct archive_string as2; + archive_string_init(&as2); + archive_string_sprintf(&as2, " --fast=%d", -data->compression_level); + archive_string_concat(&as, &as2); + archive_string_free(&as2); + } else { + struct archive_string as2; + archive_string_init(&as2); + archive_string_sprintf(&as2, " -%d", data->compression_level); + archive_string_concat(&as, &as2); + archive_string_free(&as2); + } + + if (data->compression_level > CLEVEL_STD_MAX) { + archive_strcat(&as, " --ultra"); + } f->write = archive_compressor_zstd_write; r = __archive_write_program_open(f, data->pdata, as.s); diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index cc53a3d318e..7e32fca9291 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -546,6 +546,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) { struct archive_write_disk *a = (struct archive_write_disk *)_a; struct fixup_entry *fe; + const char *linkname; int ret, r; archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, @@ -590,6 +591,17 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) if (ret != ARCHIVE_OK) return (ret); + /* + * Check if we have a hardlink that points to itself. + */ + linkname = archive_entry_hardlink(a->entry); + if (linkname != NULL && strcmp(a->name, linkname) == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Skipping hardlink pointing to itself: %s", + a->name); + return (ARCHIVE_WARN); + } + /* * Query the umask so we get predictable mode settings. * This gets done on every call to _write_header in case the @@ -1856,8 +1868,9 @@ _archive_write_disk_finish_entry(struct archive *_a) if (a->tmpname) { if (rename(a->tmpname, a->name) == -1) { archive_set_error(&a->archive, errno, - "rename failed"); - ret = ARCHIVE_FATAL; + "Failed to rename temporary file"); + ret = ARCHIVE_FAILED; + unlink(a->tmpname); } a->tmpname = NULL; } @@ -2144,8 +2157,11 @@ restore_entry(struct archive_write_disk *a) if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) && S_ISREG(a->st.st_mode)) { /* Use a temporary file to extract */ - if ((a->fd = la_mktemp(a)) == -1) + if ((a->fd = la_mktemp(a)) == -1) { + archive_set_error(&a->archive, errno, + "Can't create temporary file"); return ARCHIVE_FAILED; + } a->pst = NULL; en = 0; } else { @@ -4407,10 +4423,19 @@ set_xattrs(struct archive_write_disk *a) int e; int namespace; + namespace = EXTATTR_NAMESPACE_USER; + if (strncmp(name, "user.", 5) == 0) { /* "user." attributes go to user namespace */ name += 5; namespace = EXTATTR_NAMESPACE_USER; + } else if (strncmp(name, "system.", 7) == 0) { + name += 7; + namespace = EXTATTR_NAMESPACE_SYSTEM; + if (!strcmp(name, "nfs4.acl") || + !strcmp(name, "posix1e.acl_access") || + !strcmp(name, "posix1e.acl_default")) + continue; } else { /* Other namespaces are unsupported */ archive_strcat(&errlist, name); @@ -4421,8 +4446,29 @@ set_xattrs(struct archive_write_disk *a) } if (a->fd >= 0) { + /* + * On FreeBSD, extattr_set_fd does not + * return the same as + * extattr_set_file. It returns zero + * on success, non-zero on failure. + * + * We can detect the failure by + * manually setting errno prior to the + * call and checking after. + * + * If errno remains zero, fake the + * return value by setting e to size. + * + * This is a hack for now until I + * (Shawn Webb) get FreeBSD to fix the + * issue, if that's even possible. + */ + errno = 0; e = extattr_set_fd(a->fd, namespace, name, value, size); + if (e == 0 && errno == 0) { + e = size; + } } else { e = extattr_set_link( archive_entry_pathname(entry), namespace, diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 77e36c4a621..0c600176cd5 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -549,6 +549,8 @@ la_mktemp(struct archive_write_disk *a) a->tmpname = a->_tmpname_data.s; fd = __archive_mkstemp(a->tmpname); + if (fd == -1) + return -1; mode = a->mode & 0777 & ~a->user_umask; if (la_chmod(a->tmpname, mode) == -1) { @@ -1281,9 +1283,11 @@ _archive_write_disk_finish_entry(struct archive *_a) /* Windows does not support atomic rename */ disk_unlink(a->name); if (_wrename(a->tmpname, a->name) != 0) { + la_dosmaperr(GetLastError()); archive_set_error(&a->archive, errno, - "rename failed"); - ret = ARCHIVE_FATAL; + "Failed to rename temporary file"); + ret = ARCHIVE_FAILED; + disk_unlink(a->tmpname); } a->tmpname = NULL; } @@ -1573,12 +1577,17 @@ restore_entry(struct archive_write_disk *a) S_ISREG(st_mode)) { int fd = la_mktemp(a); - if (fd == -1) + if (fd == -1) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "Can't create temporary file"); return (ARCHIVE_FAILED); + } a->fh = (HANDLE)_get_osfhandle(fd); - if (a->fh == INVALID_HANDLE_VALUE) + if (a->fh == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); return (ARCHIVE_FAILED); - + } a->pst = NULL; en = 0; } else { diff --git a/libarchive/archive_write_open.3 b/libarchive/archive_write_open.3 index 0129d10b7f2..29bffe49eb9 100644 --- a/libarchive/archive_write_open.3 +++ b/libarchive/archive_write_open.3 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd November 12, 2020 .Dt ARCHIVE_WRITE_OPEN 3 .Os .Sh NAME .Nm archive_write_open , +.Nm archive_write_open2 , .Nm archive_write_open_fd , .Nm archive_write_open_FILE , .Nm archive_write_open_filename , @@ -47,6 +48,15 @@ Streaming Archive Library (libarchive, -larchive) .Fa "archive_close_callback *" .Fc .Ft int +.Fo archive_write_open2 +.Fa "struct archive *" +.Fa "void *client_data" +.Fa "archive_open_callback *" +.Fa "archive_write_callback *" +.Fa "archive_close_callback *" +.Fa "archive_free_callback *" +.Fc +.Ft int .Fn archive_write_open_fd "struct archive *" "int fd" .Ft int .Fn archive_write_open_FILE "struct archive *" "FILE *file" @@ -67,6 +77,11 @@ This is the most generic form of this function, which accepts pointers to three callback functions which will be invoked by the compression layer to write the constructed archive. This does not alter the default archive padding. +.It Fn archive_write_open2 +Same as +.Fn archive_write_open +with an additional fourth free callback. This function should be preferred to +.Fn archive_write_open . .It Fn archive_write_open_fd A convenience form of .Fn archive_write_open @@ -106,14 +121,14 @@ to a character or block device node, it will disable padding otherwise. You can override this by manually invoking .Fn archive_write_set_bytes_in_last_block before calling -.Fn archive_write_open . +.Fn archive_write_open2 . The .Fn archive_write_open_filename function is safe for use with tape drives or other block-oriented devices. .It Fn archive_write_open_memory A convenience form of -.Fn archive_write_open +.Fn archive_write_open2 that accepts a pointer to a block of memory that will receive the archive. The final @@ -145,7 +160,7 @@ To use this library, you will need to define and register callback functions that will be invoked to write data to the resulting archive. These functions are registered by calling -.Fn archive_write_open : +.Fn archive_write_open2 : .Bl -item -offset indent .It .Ft typedef int @@ -162,6 +177,8 @@ If the open fails, it should call .Fn archive_set_error to register an error code and message and return .Cm ARCHIVE_FATAL . +Please note that if open fails, close is not called and resources must be +freed inside the open callback or with the free callback. .Bl -item -offset indent .It .Ft typedef la_ssize_t @@ -192,7 +209,8 @@ to register an error code and message and return -1. .El .Pp The close callback is invoked by archive_close when -the archive processing is complete. +the archive processing is complete. If the open callback fails, the close +callback is not invoked. The callback should return .Cm ARCHIVE_OK on success. @@ -200,7 +218,14 @@ On failure, the callback should invoke .Fn archive_set_error to register an error code and message and return -.Cm ARCHIVE_FATAL . +.Bl -item -offset indent +.It +.Ft typedef int +.Fn archive_free_callback "struct archive *" "void *client_data" +.El +.Pp +The free callback is always invoked on archive_free. +The return code of this callback is not processed. .Pp Note that if the client-provided write callback function returns a non-zero value, that error will be propagated back to the caller diff --git a/libarchive/archive_write_open_fd.c b/libarchive/archive_write_open_fd.c index d5c426cf978..b8d491faa27 100644 --- a/libarchive/archive_write_open_fd.c +++ b/libarchive/archive_write_open_fd.c @@ -54,7 +54,7 @@ struct write_fd_data { int fd; }; -static int file_close(struct archive *, void *); +static int file_free(struct archive *, void *); static int file_open(struct archive *, void *); static ssize_t file_write(struct archive *, void *, const void *buff, size_t); @@ -72,8 +72,8 @@ archive_write_open_fd(struct archive *a, int fd) #if defined(__CYGWIN__) || defined(_WIN32) setmode(mine->fd, O_BINARY); #endif - return (archive_write_open(a, mine, - file_open, file_write, file_close)); + return (archive_write_open2(a, mine, + file_open, file_write, NULL, file_free)); } static int @@ -134,11 +134,13 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length } static int -file_close(struct archive *a, void *client_data) +file_free(struct archive *a, void *client_data) { struct write_fd_data *mine = (struct write_fd_data *)client_data; (void)a; /* UNUSED */ + if (mine == NULL) + return (ARCHIVE_OK); free(mine); return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_open_file.c b/libarchive/archive_write_open_file.c index f6b141239ff..bf5b55a672e 100644 --- a/libarchive/archive_write_open_file.c +++ b/libarchive/archive_write_open_file.c @@ -51,7 +51,7 @@ struct write_FILE_data { FILE *f; }; -static int file_close(struct archive *, void *); +static int file_free(struct archive *, void *); static int file_open(struct archive *, void *); static ssize_t file_write(struct archive *, void *, const void *buff, size_t); @@ -66,8 +66,8 @@ archive_write_open_FILE(struct archive *a, FILE *f) return (ARCHIVE_FATAL); } mine->f = f; - return (archive_write_open(a, mine, - file_open, file_write, file_close)); + return (archive_write_open2(a, mine, file_open, file_write, + NULL, file_free)); } static int @@ -99,11 +99,13 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length } static int -file_close(struct archive *a, void *client_data) +file_free(struct archive *a, void *client_data) { struct write_FILE_data *mine = client_data; (void)a; /* UNUSED */ + if (mine == NULL) + return (ARCHIVE_OK); free(mine); return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_open_filename.c b/libarchive/archive_write_open_filename.c index 66e0dfee9f3..9ceefb19bc9 100644 --- a/libarchive/archive_write_open_filename.c +++ b/libarchive/archive_write_open_filename.c @@ -62,6 +62,7 @@ struct write_file_data { }; static int file_close(struct archive *, void *); +static int file_free(struct archive *, void *); static int file_open(struct archive *, void *); static ssize_t file_write(struct archive *, void *, const void *buff, size_t); static int open_filename(struct archive *, int, const void *); @@ -123,8 +124,8 @@ open_filename(struct archive *a, int mbs_fn, const void *filename) return (ARCHIVE_FAILED); } mine->fd = -1; - return (archive_write_open(a, mine, - file_open, file_write, file_close)); + return (archive_write_open2(a, mine, + file_open, file_write, file_close, file_free)); } static int @@ -244,9 +245,25 @@ file_close(struct archive *a, void *client_data) (void)a; /* UNUSED */ + if (mine == NULL) + return (ARCHIVE_FATAL); + if (mine->fd >= 0) close(mine->fd); + return (ARCHIVE_OK); +} + +static int +file_free(struct archive *a, void *client_data) +{ + struct write_file_data *mine = (struct write_file_data *)client_data; + + (void)a; /* UNUSED */ + + if (mine == NULL) + return (ARCHIVE_OK); + archive_mstring_clean(&mine->filename); free(mine); return (ARCHIVE_OK); diff --git a/libarchive/archive_write_open_memory.c b/libarchive/archive_write_open_memory.c index ea6ae0ac524..a8a0b817fc2 100644 --- a/libarchive/archive_write_open_memory.c +++ b/libarchive/archive_write_open_memory.c @@ -39,7 +39,7 @@ struct write_memory_data { unsigned char * buff; }; -static int memory_write_close(struct archive *, void *); +static int memory_write_free(struct archive *, void *); static int memory_write_open(struct archive *, void *); static ssize_t memory_write(struct archive *, void *, const void *buff, size_t); @@ -61,8 +61,8 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t mine->buff = buff; mine->size = buffSize; mine->client_size = used; - return (archive_write_open(a, mine, - memory_write_open, memory_write, memory_write_close)); + return (archive_write_open2(a, mine, + memory_write_open, memory_write, NULL, memory_write_free)); } static int @@ -103,11 +103,13 @@ memory_write(struct archive *a, void *client_data, const void *buff, size_t leng } static int -memory_write_close(struct archive *a, void *client_data) +memory_write_free(struct archive *a, void *client_data) { struct write_memory_data *mine; (void)a; /* UNUSED */ mine = client_data; + if (mine == NULL) + return (ARCHIVE_OK); free(mine); return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h index 27cba0392ce..155fdd73488 100644 --- a/libarchive/archive_write_private.h +++ b/libarchive/archive_write_private.h @@ -89,6 +89,7 @@ struct archive_write { archive_open_callback *client_opener; archive_write_callback *client_writer; archive_close_callback *client_closer; + archive_free_callback *client_freer; void *client_data; /* diff --git a/libarchive/archive_write_set_format.c b/libarchive/archive_write_set_format.c index 12de0807753..7dbe7b9a2c1 100644 --- a/libarchive/archive_write_set_format.c +++ b/libarchive/archive_write_set_format.c @@ -82,7 +82,7 @@ void __archive_write_entry_filetype_unsupported(struct archive *a, struct archive_entry *entry, const char *format) { - char *name = NULL; + const char *name = NULL; switch (archive_entry_filetype(entry)) { /* diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index fb7697f659c..f3a7446a0a0 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -1927,8 +1927,8 @@ compression_init_encoder_lzma(struct archive *a, return (ARCHIVE_FATAL); } lzmafilters = (lzma_filter *)(strm+1); - if (level > 6) - level = 6; + if (level > 9) + level = 9; if (lzma_lzma_preset(&lzma_opt, level)) { free(strm); lastrm->real_stream = NULL; diff --git a/libarchive/archive_write_set_format_cpio.c b/libarchive/archive_write_set_format_cpio.c index 729f9c77559..e06673352b6 100644 --- a/libarchive/archive_write_set_format_cpio.c +++ b/libarchive/archive_write_set_format_cpio.c @@ -250,7 +250,7 @@ archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry) const char *path; size_t len; - if (archive_entry_filetype(entry) == 0) { + if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) { archive_set_error(&a->archive, -1, "Filetype required"); return (ARCHIVE_FAILED); } @@ -348,7 +348,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size); if (archive_entry_filetype(entry) == AE_IFBLK || archive_entry_filetype(entry) == AE_IFCHR) - format_octal(archive_entry_dev(entry), h + c_rdev_offset, c_rdev_size); + format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size); else format_octal(0, h + c_rdev_offset, c_rdev_size); format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c index 172fda62f0b..f0f39809dad 100644 --- a/libarchive/archive_write_set_format_cpio_newc.c +++ b/libarchive/archive_write_set_format_cpio_newc.c @@ -190,7 +190,7 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) const char *path; size_t len; - if (archive_entry_filetype(entry) == 0) { + if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) { archive_set_error(&a->archive, -1, "Filetype required"); return (ARCHIVE_FAILED); } diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index 7cde44c34f7..faabd28ea64 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -2178,7 +2178,8 @@ get_system_identitier(char *system_id, size_t size) strncpy(system_id, "Windows", size-1); system_id[size-1] = '\0'; #else -#error no way to get the system identifier on your platform. + strncpy(system_id, "Unknown", size-1); + system_id[size-1] = '\0'; #endif } diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index aa41e9acc22..619b7714eeb 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 #include "archive.h" #include "archive_digest_private.h" #include "archive_entry.h" +#include "archive_entry_private.h" #include "archive_private.h" #include "archive_rb.h" #include "archive_string.h" @@ -82,24 +83,7 @@ struct dir_info { struct reg_info { int compute_sum; uint32_t crc; -#ifdef ARCHIVE_HAS_MD5 - unsigned char buf_md5[16]; -#endif -#ifdef ARCHIVE_HAS_RMD160 - unsigned char buf_rmd160[20]; -#endif -#ifdef ARCHIVE_HAS_SHA1 - unsigned char buf_sha1[20]; -#endif -#ifdef ARCHIVE_HAS_SHA256 - unsigned char buf_sha256[32]; -#endif -#ifdef ARCHIVE_HAS_SHA384 - unsigned char buf_sha384[48]; -#endif -#ifdef ARCHIVE_HAS_SHA512 - unsigned char buf_sha512[64]; -#endif + struct ae_digest digest; }; struct mtree_entry { @@ -1571,27 +1555,27 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg) } #ifdef ARCHIVE_HAS_MD5 if (mtree->compute_sum & F_MD5) - archive_md5_final(&mtree->md5ctx, reg->buf_md5); + archive_md5_final(&mtree->md5ctx, reg->digest.md5); #endif #ifdef ARCHIVE_HAS_RMD160 if (mtree->compute_sum & F_RMD160) - archive_rmd160_final(&mtree->rmd160ctx, reg->buf_rmd160); + archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160); #endif #ifdef ARCHIVE_HAS_SHA1 if (mtree->compute_sum & F_SHA1) - archive_sha1_final(&mtree->sha1ctx, reg->buf_sha1); + archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1); #endif #ifdef ARCHIVE_HAS_SHA256 if (mtree->compute_sum & F_SHA256) - archive_sha256_final(&mtree->sha256ctx, reg->buf_sha256); + archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256); #endif #ifdef ARCHIVE_HAS_SHA384 if (mtree->compute_sum & F_SHA384) - archive_sha384_final(&mtree->sha384ctx, reg->buf_sha384); + archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384); #endif #ifdef ARCHIVE_HAS_SHA512 if (mtree->compute_sum & F_SHA512) - archive_sha512_final(&mtree->sha512ctx, reg->buf_sha512); + archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512); #endif /* Save what types of sum are computed. */ reg->compute_sum = mtree->compute_sum; @@ -1621,42 +1605,47 @@ sum_write(struct archive_string *str, struct reg_info *reg) archive_string_sprintf(str, " cksum=%ju", (uintmax_t)reg->crc); } + +#define append_digest(_s, _r, _t) \ + strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t)) + #ifdef ARCHIVE_HAS_MD5 if (reg->compute_sum & F_MD5) { archive_strcat(str, " md5digest="); - strappend_bin(str, reg->buf_md5, sizeof(reg->buf_md5)); + append_digest(str, reg, md5); } #endif #ifdef ARCHIVE_HAS_RMD160 if (reg->compute_sum & F_RMD160) { archive_strcat(str, " rmd160digest="); - strappend_bin(str, reg->buf_rmd160, sizeof(reg->buf_rmd160)); + append_digest(str, reg, rmd160); } #endif #ifdef ARCHIVE_HAS_SHA1 if (reg->compute_sum & F_SHA1) { archive_strcat(str, " sha1digest="); - strappend_bin(str, reg->buf_sha1, sizeof(reg->buf_sha1)); + append_digest(str, reg, sha1); } #endif #ifdef ARCHIVE_HAS_SHA256 if (reg->compute_sum & F_SHA256) { archive_strcat(str, " sha256digest="); - strappend_bin(str, reg->buf_sha256, sizeof(reg->buf_sha256)); + append_digest(str, reg, sha256); } #endif #ifdef ARCHIVE_HAS_SHA384 if (reg->compute_sum & F_SHA384) { archive_strcat(str, " sha384digest="); - strappend_bin(str, reg->buf_sha384, sizeof(reg->buf_sha384)); + append_digest(str, reg, sha384); } #endif #ifdef ARCHIVE_HAS_SHA512 if (reg->compute_sum & F_SHA512) { archive_strcat(str, " sha512digest="); - strappend_bin(str, reg->buf_sha512, sizeof(reg->buf_sha512)); + append_digest(str, reg, sha512); } #endif +#undef append_digest } static int diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index d456cf8f8aa..d885f5c256d 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -681,7 +681,8 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s) { struct xar *xar; enum la_zaction run; - size_t size, rsize; + size_t size = 0; + size_t rsize; int r; xar = (struct xar *)a->format_data; @@ -2930,8 +2931,8 @@ compression_init_encoder_xz(struct archive *a, return (ARCHIVE_FATAL); } lzmafilters = (lzma_filter *)(strm+1); - if (level > 6) - level = 6; + if (level > 9) + level = 9; if (lzma_lzma_preset(&lzma_opt, level)) { free(strm); lastrm->real_stream = NULL; diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 6d485295d50..f4352d5a9f7 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -584,6 +584,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED; zip->entry_encryption = zip->encryption_type; break; + case ENCRYPTION_NONE: default: break; } @@ -710,6 +711,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) + AUTH_CODE_SIZE; version_needed = 20; break; + case ENCRYPTION_NONE: default: break; } @@ -762,6 +764,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) if (version_needed < 20) version_needed = 20; break; + case ENCRYPTION_NONE: default: break; } @@ -1029,6 +1032,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) zip->cctx_valid = zip->hctx_valid = 1; } break; + case ENCRYPTION_NONE: default: break; } @@ -1117,6 +1121,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) break; #endif + case COMPRESSION_UNSPECIFIED: default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid ZIP compression type"); diff --git a/libarchive/archive_write_set_options.3 b/libarchive/archive_write_set_options.3 index cffe571e90a..d4a52e322ea 100644 --- a/libarchive/archive_write_set_options.3 +++ b/libarchive/archive_write_set_options.3 @@ -255,7 +255,8 @@ If supported, the default value is read from .Bl -tag -compact -width indent .It Cm compression-level The value is interpreted as a decimal integer specifying the -compression level. Supported values are from 1 to 22. +compression level. Supported values depend on the library version, +common values are from 1 to 22. .El .It Format 7zip .Bl -tag -compact -width indent diff --git a/libarchive/config_freebsd.h b/libarchive/config_freebsd.h index f16fd3495ed..a484618b488 100644 --- a/libarchive/config_freebsd.h +++ b/libarchive/config_freebsd.h @@ -24,6 +24,7 @@ * * $FreeBSD$ */ +#define __LIBARCHIVE_CONFIG_H_INCLUDED 1 #include <osreldate.h> @@ -183,6 +184,7 @@ #define HAVE_STRFTIME 1 #define HAVE_STRINGS_H 1 #define HAVE_STRING_H 1 +#define HAVE_STRNLEN 1 #define HAVE_STRRCHR 1 #define HAVE_STRUCT_STATFS_F_NAMEMAX 1 #define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 diff --git a/libarchive/cpio.5 b/libarchive/cpio.5 index 1a2886f0867..a91f0c596d2 100644 --- a/libarchive/cpio.5 +++ b/libarchive/cpio.5 @@ -244,7 +244,7 @@ Note that this format supports only 4 gigabyte files (unlike the older ASCII format, which supports 8 gigabyte files). .Pp In this format, hardlinked files are handled by setting the -filesize to zero for each entry except the last one that +filesize to zero for each entry except the first one that appears in the archive. .Ss New CRC Format The CRC format is identical to the new ASCII format described diff --git a/libarchive/filter_fork.h b/libarchive/filter_fork.h index 908e7cdd4dd..2bf290c4d9e 100644 --- a/libarchive/filter_fork.h +++ b/libarchive/filter_fork.h @@ -32,8 +32,13 @@ #error This header is only to be used internally to libarchive. #endif -pid_t -__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout); +int +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE *out_child); +#else + pid_t *out_child); +#endif void __archive_check_child(int in, int out); diff --git a/libarchive/filter_fork_posix.c b/libarchive/filter_fork_posix.c index 02dbd4bb436..ac255c4f8b2 100644 --- a/libarchive/filter_fork_posix.c +++ b/libarchive/filter_fork_posix.c @@ -72,8 +72,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00 #include "filter_fork.h" -pid_t -__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) +int +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, + pid_t *out_child) { pid_t child; int stdin_pipe[2], stdout_pipe[2], tmp; @@ -177,7 +178,8 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) fcntl(*child_stdout, F_SETFL, O_NONBLOCK); __archive_cmdline_free(cmdline); - return child; + *out_child = child; + return ARCHIVE_OK; #if HAVE_POSIX_SPAWNP actions_inited: @@ -192,7 +194,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) close(stdin_pipe[1]); state_allocated: __archive_cmdline_free(cmdline); - return -1; + return ARCHIVE_FAILED; } void diff --git a/libarchive/filter_fork_windows.c b/libarchive/filter_fork_windows.c index ad271fe68a1..8d11179f307 100644 --- a/libarchive/filter_fork_windows.c +++ b/libarchive/filter_fork_windows.c @@ -31,8 +31,9 @@ #include "filter_fork.h" -pid_t -__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) +int +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, + HANDLE *out_child) { HANDLE childStdout[2], childStdin[2],childStderr; SECURITY_ATTRIBUTES secAtts; @@ -44,6 +45,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) char *arg0, *ext; int i, l; DWORD fl, fl_old; + HANDLE child; childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE; childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE; @@ -154,13 +156,20 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) *child_stdout = _open_osfhandle((intptr_t)childStdout[0], _O_RDONLY); *child_stdin = _open_osfhandle((intptr_t)childStdin[1], _O_WRONLY); + child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, + childInfo.dwProcessId); + if (child == NULL) // INVALID_HANDLE_VALUE ? + goto fail; + + *out_child = child; + CloseHandle(childStdout[1]); CloseHandle(childStdin[0]); archive_string_free(&cmdline); archive_string_free(&fullpath); __archive_cmdline_free(acmd); - return (childInfo.dwProcessId); + return ARCHIVE_OK; fail: if (childStdout[0] != INVALID_HANDLE_VALUE) @@ -176,7 +185,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) archive_string_free(&cmdline); archive_string_free(&fullpath); __archive_cmdline_free(acmd); - return (-1); + return ARCHIVE_FAILED; } void From 651ecdddfab8ba38decfa0b91333c8d27523c3ea Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 19 Aug 2021 10:55:23 -0400 Subject: [PATCH 1153/1519] Utilities: Add hard-coded try_compile result for libarchive strnlen check libarchive 3.5.1 checks for strnlen. It is available on all Windows platforms. --- Utilities/cmThirdPartyChecks.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake index bab30463f96..7e38df945f2 100644 --- a/Utilities/cmThirdPartyChecks.cmake +++ b/Utilities/cmThirdPartyChecks.cmake @@ -180,6 +180,7 @@ if(WIN32) set(HAVE_STRERROR_R 0) set(HAVE_STRNCMPI 0) set(HAVE_STRNCPY_S 1) + set(HAVE_STRNLEN 1) set(HAVE_STROPTS_H 0) set(HAVE__STRTOI64 1) set(HAVE_STRTOLL 1) From 6287b0214760f792192cfc075c7cf839b540b1de Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 24 Aug 2021 13:02:57 -0400 Subject: [PATCH 1154/1519] libarchive: Limit xz compression level to 6 on AIX Since libarchive commit `aff9809c` (Enable compression level up to 9 for xz, xar, 7zip, 2020-07-26, v3.5.0~19^2), libarchive fails to initialize xz compression on AIX with error Internal error initializing compression library: Cannot allocate memory Revert to the old limit of level 6 on AIX. Issue: #22553 --- .../cmlibarchive/libarchive/archive_write_add_filter_xz.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c index d3e58cefd05..00df8da5ad1 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c @@ -384,6 +384,10 @@ archive_compressor_xz_options(struct archive_write_filter *f, data->compression_level = value[0] - '0'; if (data->compression_level > 9) data->compression_level = 9; +#ifdef _AIX + if (data->compression_level > 6) + data->compression_level = 6; +#endif return (ARCHIVE_OK); } else if (strcmp(key, "threads") == 0) { char *endptr; From 047d46ebdbb87f0388fa1627a3c39810e0b08c69 Mon Sep 17 00:00:00 2001 From: Felix Lelchuk <felix.lelchuk@gmx.de> Date: Sat, 21 Aug 2021 13:52:49 +0200 Subject: [PATCH 1155/1519] Fix: InstallMode tests fail on some platforms 1) The ExternalProject_Add() command was called with UPDATE_COMMAND ";" which was not noticable on most platforms 2) On AIX/GCC, the executable did not link because symbols from imported libraries were assumed extern "C" (see commit 4fc47424) --- Tests/InstallMode/Subproject.cmake | 13 +++++-------- .../InstallMode/subpro_b_shared_lib/CMakeLists.txt | 11 ++++++++++- .../subpro_b_shared_lib/include/shared_lib.h | 4 +++- .../subsubpro_c2_lib/CMakeLists.txt | 3 +++ .../InstallMode/subpro_d_executable/CMakeLists.txt | 3 +++ 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Tests/InstallMode/Subproject.cmake b/Tests/InstallMode/Subproject.cmake index e4354d67ee7..826e61e02d1 100644 --- a/Tests/InstallMode/Subproject.cmake +++ b/Tests/InstallMode/Subproject.cmake @@ -10,12 +10,7 @@ function(add_subproject _name) set(_maybe_NO_INSTALL) if(_arg_NO_INSTALL) - set(_maybe_NO_INSTALL "INSTALL_COMMAND") - else() - # This is a trick to get a valid call. - # Since we set UPDATE_COMMAND to "" - # explicitly below, this won't harm. - set(_maybe_NO_INSTALL "UPDATE_COMMAND") + set(_maybe_NO_INSTALL INSTALL_COMMAND "") endif() if(CMAKE_GENERATOR MATCHES "Ninja Multi-Config") @@ -35,7 +30,9 @@ function(add_subproject _name) ExternalProject_Add("${_name}" DOWNLOAD_COMMAND "" UPDATE_COMMAND "" - ${_maybe_NO_INSTALL} "" + UPDATE_DISCONNECTED ON + + "${_maybe_NO_INSTALL}" BUILD_ALWAYS ON @@ -67,7 +64,7 @@ function(add_subproject _name) # however, we need to explicitly inherit other parent # project's build settings. "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}" - ${_maybe_NINJA_MULTICONFIG_ARGS} + "${_maybe_NINJA_MULTICONFIG_ARGS}" # Subproject progress reports clutter up the output, disable "-DCMAKE_TARGET_MESSAGES:BOOL=OFF" diff --git a/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt b/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt index eb118c9a1b5..b3d9cb2fe9f 100644 --- a/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt +++ b/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt @@ -4,12 +4,18 @@ cmake_minimum_required(VERSION 3.20) project(shared_lib_project VERSION 2.3.4 LANGUAGES CXX) include(GNUInstallDirs) +include(GenerateExportHeader) add_library(the_shared_lib SHARED "include/shared_lib.h" "src/shared_lib.cpp" ) +generate_export_header(the_shared_lib + BASE_NAME shared_lib + EXPORT_FILE_NAME include/shared_lib_export.h +) + set_target_properties(the_shared_lib PROPERTIES VERSION "${PROJECT_VERSION}" @@ -18,11 +24,14 @@ set_target_properties(the_shared_lib target_include_directories(the_shared_lib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> + $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ) install( - DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}/include/" + "${CMAKE_CURRENT_BINARY_DIR}/include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) diff --git a/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h b/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h index fd960db019e..550b2b44d55 100644 --- a/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h +++ b/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h @@ -1,3 +1,5 @@ #pragma once -void shared_hello(); +#include <shared_lib_export.h> + +void SHARED_LIB_EXPORT shared_hello(); diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt index e139446edca..7580c778c12 100644 --- a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt +++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt @@ -18,6 +18,9 @@ target_link_libraries(the_c2_lib the_c1_lib ) +# This is to fix an issue on AIX/GCC (see commit 4fc47424) +set_property(TARGET the_c2_lib PROPERTY NO_SYSTEM_FROM_IMPORTED 1) + target_include_directories(the_c2_lib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> diff --git a/Tests/InstallMode/subpro_d_executable/CMakeLists.txt b/Tests/InstallMode/subpro_d_executable/CMakeLists.txt index 98472275736..60189e228a8 100644 --- a/Tests/InstallMode/subpro_d_executable/CMakeLists.txt +++ b/Tests/InstallMode/subpro_d_executable/CMakeLists.txt @@ -17,6 +17,9 @@ target_link_libraries(the_executable PRIVATE the_c2_lib ) +# This is to fix an issue on AIX/GCC (see commit 4fc47424) +set_property(TARGET the_executable PROPERTY NO_SYSTEM_FROM_IMPORTED 1) + install( TARGETS the_executable From cb7edb1f4b46c391c9190ee24b850346dff2d83f Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 25 Aug 2021 00:01:13 -0400 Subject: [PATCH 1156/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d10822f4f33..e1d3e63a6ee 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210824) +set(CMake_VERSION_PATCH 20210825) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6dfa581babfb051461341ca92e0463481799361f Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sun, 15 Aug 2021 16:04:47 +0200 Subject: [PATCH 1157/1519] Enhancement: SetProperty accept cmProp or std::string Methods SetProperty of classes cmPropertyMap, cmStateDirectory and cmMakefile accept now cmProp or std::string as argument. --- Source/cmMakefile.cxx | 4 ++ Source/cmMakefile.h | 5 ++ Source/cmPropertyMap.cxx | 9 +++ Source/cmPropertyMap.h | 5 ++ Source/cmSourceFile.cxx | 12 +++- Source/cmSourceFile.h | 8 +++ Source/cmState.cxx | 4 ++ Source/cmState.h | 1 + Source/cmStateDirectory.cxx | 16 ++++- Source/cmStateDirectory.h | 6 ++ Source/cmTarget.cxx | 116 ++++++++++++++++++++---------------- Source/cmTarget.h | 6 +- Source/cmTest.cxx | 4 ++ Source/cmTest.h | 5 ++ Source/cmake.cxx | 4 ++ Source/cmake.h | 5 ++ 16 files changed, 154 insertions(+), 56 deletions(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 0b8778f9e83..5a62dda3fc0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3986,6 +3986,10 @@ void cmMakefile::SetProperty(const std::string& prop, const char* value) { this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace); } +void cmMakefile::SetProperty(const std::string& prop, cmProp value) +{ + this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace); +} void cmMakefile::AppendProperty(const std::string& prop, const std::string& value, bool asString) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index a3d2a8195f6..fd9a67974d9 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -769,6 +769,11 @@ class cmMakefile //! Set/Get a property of this directory void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, const std::string& value) + { + this->SetProperty(prop, cmProp(value)); + } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); cmProp GetProperty(const std::string& prop) const; diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index 3e3a44bd0bf..8ad3c6f1503 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -19,6 +19,15 @@ void cmPropertyMap::SetProperty(const std::string& name, const char* value) this->Map_[name] = value; } +void cmPropertyMap::SetProperty(const std::string& name, cmProp value) +{ + if (!value) { + this->Map_.erase(name); + return; + } + + this->Map_[name] = *value; +} void cmPropertyMap::AppendProperty(const std::string& name, const std::string& value, bool asString) diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index cda585a89f8..b28d3c9046a 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -26,6 +26,11 @@ class cmPropertyMap //! Set the property value void SetProperty(const std::string& name, const char* value); + void SetProperty(const std::string& name, cmProp value); + void SetProperty(const std::string& name, const std::string& value) + { + this->SetProperty(name, cmProp(value)); + } //! Append to the property value void AppendProperty(const std::string& name, const std::string& value, diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index f2b5cc42783..6caae3abca0 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -269,7 +269,8 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc) return this->Location.Matches(loc); } -void cmSourceFile::SetProperty(const std::string& prop, const char* value) +template <typename ValueType> +void cmSourceFile::StoreProperty(const std::string& prop, ValueType value) { if (prop == propINCLUDE_DIRECTORIES) { this->IncludeDirectories.clear(); @@ -294,6 +295,15 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value) } } +void cmSourceFile::SetProperty(const std::string& prop, const char* value) +{ + this->StoreProperty(prop, value); +} +void cmSourceFile::SetProperty(const std::string& prop, cmProp value) +{ + this->StoreProperty(prop, value); +} + void cmSourceFile::AppendProperty(const std::string& prop, const std::string& value, bool asString) { diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 32ed68715fe..78e0d271257 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -42,6 +42,11 @@ class cmSourceFile //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, const std::string& value) + { + this->SetProperty(prop, cmProp(value)); + } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); //! Might return a nullptr if the property is not set or invalid @@ -145,6 +150,9 @@ class cmSourceFile std::string GetObjectLibrary() const; private: + template <typename ValueType> + void StoreProperty(const std::string& prop, ValueType value); + cmSourceFileLocation Location; cmPropertyMap Properties; std::unique_ptr<cmCustomCommand> CustomCommand; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index bde3e2e6f93..a045545971f 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -569,6 +569,10 @@ void cmState::SetGlobalProperty(const std::string& prop, const char* value) { this->GlobalProperties.SetProperty(prop, value); } +void cmState::SetGlobalProperty(const std::string& prop, cmProp value) +{ + this->GlobalProperties.SetProperty(prop, value); +} void cmState::AppendGlobalProperty(const std::string& prop, const std::string& value, bool asString) diff --git a/Source/cmState.h b/Source/cmState.h index 8561fc0c4fd..0fd28d08950 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -178,6 +178,7 @@ class cmState std::vector<std::string> GetCommandNames() const; void SetGlobalProperty(const std::string& prop, const char* value); + void SetGlobalProperty(const std::string& prop, cmProp value); void AppendGlobalProperty(const std::string& prop, const std::string& value, bool asString = false); cmProp GetGlobalProperty(const std::string& prop); diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index b90cf7ecefe..ed5b5d85f53 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -361,8 +361,9 @@ void cmStateDirectory::ClearLinkDirectories() this->Snapshot_.Position->LinkDirectoriesPosition); } -void cmStateDirectory::SetProperty(const std::string& prop, const char* value, - cmListFileBacktrace const& lfbt) +template <typename ValueType> +void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, + cmListFileBacktrace const& lfbt) { if (prop == "INCLUDE_DIRECTORIES") { if (!value) { @@ -408,6 +409,17 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value, this->DirectoryState->Properties.SetProperty(prop, value); } +void cmStateDirectory::SetProperty(const std::string& prop, const char* value, + cmListFileBacktrace const& lfbt) +{ + this->StoreProperty(prop, value, lfbt); +} +void cmStateDirectory::SetProperty(const std::string& prop, cmProp value, + cmListFileBacktrace const& lfbt) +{ + this->StoreProperty(prop, value, lfbt); +} + void cmStateDirectory::AppendProperty(const std::string& prop, const std::string& value, bool asString, cmListFileBacktrace const& lfbt) diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index b8abccb81e8..65e2f306299 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -73,6 +73,8 @@ class cmStateDirectory void SetProperty(const std::string& prop, const char* value, cmListFileBacktrace const& lfbt); + void SetProperty(const std::string& prop, cmProp value, + cmListFileBacktrace const& lfbt); void AppendProperty(const std::string& prop, const std::string& value, bool asString, cmListFileBacktrace const& lfbt); cmProp GetProperty(const std::string& prop) const; @@ -84,6 +86,10 @@ class cmStateDirectory void AddImportedTargetName(std::string const& name); private: + template <typename ValueType> + void StoreProperty(const std::string& prop, ValueType value, + cmListFileBacktrace const& lfbt); + cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator DirectoryState; cmStateSnapshot Snapshot_; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 656afc63ab5..345efed5927 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1177,32 +1177,59 @@ cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const return cmMakeRange(this->impl->LinkImplementationPropertyBacktraces); } -void cmTarget::SetProperty(const std::string& prop, const char* value) +namespace { +#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP +MAKE_PROP(C_STANDARD); +MAKE_PROP(CXX_STANDARD); +MAKE_PROP(CUDA_STANDARD); +MAKE_PROP(HIP_STANDARD); +MAKE_PROP(OBJC_STANDARD); +MAKE_PROP(OBJCXX_STANDARD); +MAKE_PROP(COMPILE_DEFINITIONS); +MAKE_PROP(COMPILE_FEATURES); +MAKE_PROP(COMPILE_OPTIONS); +MAKE_PROP(PRECOMPILE_HEADERS); +MAKE_PROP(PRECOMPILE_HEADERS_REUSE_FROM); +MAKE_PROP(CUDA_PTX_COMPILATION); +MAKE_PROP(EXPORT_NAME); +MAKE_PROP(IMPORTED); +MAKE_PROP(IMPORTED_GLOBAL); +MAKE_PROP(INCLUDE_DIRECTORIES); +MAKE_PROP(LINK_OPTIONS); +MAKE_PROP(LINK_DIRECTORIES); +MAKE_PROP(LINK_LIBRARIES); +MAKE_PROP(MANUALLY_ADDED_DEPENDENCIES); +MAKE_PROP(NAME); +MAKE_PROP(SOURCES); +MAKE_PROP(TYPE); +MAKE_PROP(BINARY_DIR); +MAKE_PROP(SOURCE_DIR); +MAKE_PROP(FALSE); +MAKE_PROP(TRUE); +#undef MAKE_PROP +} + +namespace { +// to workaround bug on GCC/AIX +// Define a template to force conversion to std::string +template <typename ValueType> +std::string ConvertToString(ValueType value); + +template <> +std::string ConvertToString<const char*>(const char* value) +{ + return std::string(value); +} +template <> +std::string ConvertToString<cmProp>(cmProp value) +{ + return std::string(*value); +} +} + +template <typename ValueType> +void cmTarget::StoreProperty(const std::string& prop, ValueType value) { -#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP - MAKE_STATIC_PROP(C_STANDARD); - MAKE_STATIC_PROP(CXX_STANDARD); - MAKE_STATIC_PROP(CUDA_STANDARD); - MAKE_STATIC_PROP(HIP_STANDARD); - MAKE_STATIC_PROP(OBJC_STANDARD); - MAKE_STATIC_PROP(OBJCXX_STANDARD); - MAKE_STATIC_PROP(COMPILE_DEFINITIONS); - MAKE_STATIC_PROP(COMPILE_FEATURES); - MAKE_STATIC_PROP(COMPILE_OPTIONS); - MAKE_STATIC_PROP(PRECOMPILE_HEADERS); - MAKE_STATIC_PROP(PRECOMPILE_HEADERS_REUSE_FROM); - MAKE_STATIC_PROP(CUDA_PTX_COMPILATION); - MAKE_STATIC_PROP(EXPORT_NAME); - MAKE_STATIC_PROP(IMPORTED_GLOBAL); - MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); - MAKE_STATIC_PROP(LINK_OPTIONS); - MAKE_STATIC_PROP(LINK_DIRECTORIES); - MAKE_STATIC_PROP(LINK_LIBRARIES); - MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); - MAKE_STATIC_PROP(NAME); - MAKE_STATIC_PROP(SOURCES); - MAKE_STATIC_PROP(TYPE); -#undef MAKE_STATIC_PROP if (prop == propMANUALLY_ADDED_DEPENDENCIES) { this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, @@ -1327,7 +1354,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->GetGlobalGenerator()->IndexTarget(this); } } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && - !this->impl->CheckImportedLibName(prop, value ? value : "")) { + !this->impl->CheckImportedLibName( + prop, value ? value : std::string{})) { /* error was reported by check method */ } else if (prop == propCUDA_PTX_COMPILATION && this->GetType() != cmStateEnums::OBJECT_LIBRARY) { @@ -1357,7 +1385,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) std::string reusedFrom = reusedTarget->GetSafeProperty(prop); if (reusedFrom.empty()) { - reusedFrom = value; + reusedFrom = ConvertToString(value); } this->impl->Properties.SetProperty(prop, reusedFrom.c_str()); @@ -1486,6 +1514,15 @@ void cmTarget::AppendProperty(const std::string& prop, } } +void cmTarget::SetProperty(const std::string& prop, const char* value) +{ + this->StoreProperty(prop, value); +} +void cmTarget::SetProperty(const std::string& prop, cmProp value) +{ + this->StoreProperty(prop, value); +} + void cmTarget::AppendBuildInterfaceIncludes() { if (this->GetType() != cmStateEnums::SHARED_LIBRARY && @@ -1693,31 +1730,6 @@ cmProp cmTarget::GetComputedProperty(const std::string& prop, cmProp cmTarget::GetProperty(const std::string& prop) const { -#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP - MAKE_STATIC_PROP(C_STANDARD); - MAKE_STATIC_PROP(CXX_STANDARD); - MAKE_STATIC_PROP(CUDA_STANDARD); - MAKE_STATIC_PROP(OBJC_STANDARD); - MAKE_STATIC_PROP(OBJCXX_STANDARD); - MAKE_STATIC_PROP(LINK_LIBRARIES); - MAKE_STATIC_PROP(TYPE); - MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); - MAKE_STATIC_PROP(COMPILE_FEATURES); - MAKE_STATIC_PROP(COMPILE_OPTIONS); - MAKE_STATIC_PROP(COMPILE_DEFINITIONS); - MAKE_STATIC_PROP(LINK_OPTIONS); - MAKE_STATIC_PROP(LINK_DIRECTORIES); - MAKE_STATIC_PROP(PRECOMPILE_HEADERS); - MAKE_STATIC_PROP(IMPORTED); - MAKE_STATIC_PROP(IMPORTED_GLOBAL); - MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); - MAKE_STATIC_PROP(NAME); - MAKE_STATIC_PROP(BINARY_DIR); - MAKE_STATIC_PROP(SOURCE_DIR); - MAKE_STATIC_PROP(SOURCES); - MAKE_STATIC_PROP(FALSE); - MAKE_STATIC_PROP(TRUE); -#undef MAKE_STATIC_PROP static std::unordered_set<std::string> const specialProps{ propC_STANDARD, propCXX_STANDARD, diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 29130c7bf39..de0c4e3b693 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -170,9 +170,10 @@ class cmTarget //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, cmProp value); void SetProperty(const std::string& prop, const std::string& value) { - this->SetProperty(prop, value.c_str()); + this->SetProperty(prop, cmProp(value)); } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); @@ -283,6 +284,9 @@ class cmTarget }; private: + template <typename ValueType> + void StoreProperty(const std::string& prop, ValueType value); + // Internal representation details. friend class cmGeneratorTarget; diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 5bc10c22ce5..9d25ce9d971 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -57,6 +57,10 @@ void cmTest::SetProperty(const std::string& prop, const char* value) { this->Properties.SetProperty(prop, value); } +void cmTest::SetProperty(const std::string& prop, cmProp value) +{ + this->Properties.SetProperty(prop, value); +} void cmTest::AppendProperty(const std::string& prop, const std::string& value, bool asString) diff --git a/Source/cmTest.h b/Source/cmTest.h index 63e5e8782da..a7905011ffb 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -35,6 +35,11 @@ class cmTest //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, const std::string& value) + { + this->SetProperty(prop, cmProp(value)); + } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); cmProp GetProperty(const std::string& prop) const; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 7f8f6547b8f..beb5d1617f3 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2919,6 +2919,10 @@ void cmake::SetProperty(const std::string& prop, const char* value) { this->State->SetGlobalProperty(prop, value); } +void cmake::SetProperty(const std::string& prop, cmProp value) +{ + this->State->SetGlobalProperty(prop, value); +} void cmake::AppendProperty(const std::string& prop, const std::string& value, bool asString) diff --git a/Source/cmake.h b/Source/cmake.h index 12cce7e8ed0..32c75824228 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -396,6 +396,11 @@ class cmake //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, const std::string& value) + { + this->SetProperty(prop, cmProp(value)); + } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); cmProp GetProperty(const std::string& prop); From dc3aa4024eba3067d2cc81087aeccd4b31cf23f0 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 16 Aug 2021 16:46:53 +0200 Subject: [PATCH 1158/1519] Refactor: Use new SetProperty signatures --- Source/cmAddTestCommand.cxx | 2 +- Source/cmGlobalXCodeGenerator.cxx | 2 +- Source/cmLocalGenerator.cxx | 12 ++++++------ Source/cmMakefile.cxx | 15 +++++++-------- Source/cmQTWrapCPPCommand.cxx | 3 +-- Source/cmQtAutoGenGlobalInitializer.cxx | 2 +- Source/cmSetDirectoryPropertiesCommand.cxx | 2 +- Source/cmSetPropertyCommand.cxx | 10 +++++----- Source/cmSetSourceFilesPropertiesCommand.cxx | 2 +- Source/cmSetTestsPropertiesCommand.cxx | 2 +- Source/cmStateSnapshot.cxx | 2 +- Source/cmTarget.cxx | 8 ++++---- 12 files changed, 30 insertions(+), 32 deletions(-) diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index 205c1c7a511..a0d5732fdfb 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx @@ -140,7 +140,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args, test->SetOldStyle(false); test->SetCommand(command); if (!working_directory.empty()) { - test->SetProperty("WORKING_DIRECTORY", working_directory.c_str()); + test->SetProperty("WORKING_DIRECTORY", working_directory); } test->SetCommandExpandLists(command_expand_lists); mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test, configurations)); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3994816c54e..763f12a3a94 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1667,7 +1667,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) fout << "\n"; } if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) { - sf->SetProperty("LANGUAGE", llang.c_str()); + sf->SetProperty("LANGUAGE", llang); gtgt->AddSource(fname); } } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 74130dd0719..5fe5c756a50 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2553,10 +2553,10 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) continue; } - const std::string pchExtension = - this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = + this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); - if (pchExtension.empty()) { + if (pchExtension.IsEmpty()) { continue; } @@ -2647,7 +2647,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) } } } else { - pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); + pch_sf->SetProperty("PCH_EXTENSION", pchExtension); } // Add pchHeader to source files, which will @@ -2788,7 +2788,7 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, std::string const& filename) { target->AddSourceFileToUnityBatch(sf->ResolveFullPath()); - sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str()); + sf->SetProperty("UNITY_SOURCE_FILE", filename); } } @@ -2986,7 +2986,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) auto* unity = this->GetMakefile()->GetOrCreateSource(file); target->AddSource(file, true); unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON"); - unity->SetProperty("UNITY_SOURCE_FILE", file.c_str()); + unity->SetProperty("UNITY_SOURCE_FILE", file); } } } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5a62dda3fc0..7abbd319238 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1444,7 +1444,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) std::string ndefs = cmJoin(cmMakeRange(defBegin, defEnd), ";"); // Store the new list. - this->SetProperty("COMPILE_DEFINITIONS", ndefs.c_str()); + this->SetProperty("COMPILE_DEFINITIONS", ndefs); } } else { // Append the definition to the directory property. @@ -1465,30 +1465,29 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) // Include transform property. There is no per-config version. { const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"; - this->SetProperty(prop, cmToCStr(parent->GetProperty(prop))); + this->SetProperty(prop, parent->GetProperty(prop)); } // compile definitions property and per-config versions cmPolicies::PolicyStatus polSt = this->GetPolicyStatus(cmPolicies::CMP0043); if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { this->SetProperty("COMPILE_DEFINITIONS", - cmToCStr(parent->GetProperty("COMPILE_DEFINITIONS"))); + parent->GetProperty("COMPILE_DEFINITIONS")); std::vector<std::string> configs = this->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); for (std::string const& config : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); cmProp prop = parent->GetProperty(defPropName); - this->SetProperty(defPropName, cmToCStr(prop)); + this->SetProperty(defPropName, prop); } } // labels - this->SetProperty("LABELS", cmToCStr(parent->GetProperty("LABELS"))); + this->SetProperty("LABELS", parent->GetProperty("LABELS")); // link libraries - this->SetProperty("LINK_LIBRARIES", - cmToCStr(parent->GetProperty("LINK_LIBRARIES"))); + this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES")); // the initial project name this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName()); @@ -2308,7 +2307,7 @@ void cmMakefile::ExpandVariablesCMP0019() << " " << dirs << "\n"; /* clang-format on */ } - this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); + this->SetProperty("INCLUDE_DIRECTORIES", dirs); } // Also for each target's INCLUDE_DIRECTORIES property: diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index e9670f9c3a4..ca0b259dc5c 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -6,7 +6,6 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" @@ -41,7 +40,7 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args, cmStrCat(mf.GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx"); cmSourceFile* sf = mf.GetOrCreateSource(newName, true); if (curr) { - sf->SetProperty("ABSTRACT", cmToCStr(curr->GetProperty("ABSTRACT"))); + sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT")); } // Compute the name of the header from which to generate the file. diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 77fe87e4c31..f3ad5657d24 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -186,7 +186,7 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( cmProp folder = makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); if (folder) { - target->SetProperty("FOLDER", *folder); + target->SetProperty("FOLDER", folder); } } } diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx index 07ad24602e2..9adf5373b45 100644 --- a/Source/cmSetDirectoryPropertiesCommand.cxx +++ b/Source/cmSetDirectoryPropertiesCommand.cxx @@ -32,7 +32,7 @@ bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args, "Commands and macros cannot be set using SET_CMAKE_PROPERTIES"); return false; } - status.GetMakefile().SetProperty(prop, (iter + 1)->c_str()); + status.GetMakefile().SetProperty(prop, *(iter + 1)); } return true; diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index c8990537baa..59b44028db2 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -294,7 +294,7 @@ bool HandleAndValidateSourceFilePropertyGENERATED( sf->SetProperty("GENERATED", nullptr); break; case PropertyOp::Set: - sf->SetProperty("GENERATED", propertyValue.c_str()); + sf->SetProperty("GENERATED", propertyValue); break; } } else { @@ -474,7 +474,7 @@ bool HandleGlobalMode(cmExecutionStatus& status, if (remove) { cm->SetProperty(propertyName, nullptr); } else { - cm->SetProperty(propertyName, propertyValue.c_str()); + cm->SetProperty(propertyName, propertyValue); } } @@ -520,7 +520,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status, if (remove) { mf->SetProperty(propertyName, nullptr); } else { - mf->SetProperty(propertyName, propertyValue.c_str()); + mf->SetProperty(propertyName, propertyValue); } } @@ -631,7 +631,7 @@ bool HandleSource(cmSourceFile* sf, const std::string& propertyName, if (remove) { sf->SetProperty(propertyName, nullptr); } else { - sf->SetProperty(propertyName, propertyValue.c_str()); + sf->SetProperty(propertyName, propertyValue); } } return true; @@ -681,7 +681,7 @@ bool HandleTest(cmTest* test, const std::string& propertyName, if (remove) { test->SetProperty(propertyName, nullptr); } else { - test->SetProperty(propertyName, propertyValue.c_str()); + test->SetProperty(propertyName, propertyValue); } } diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 237b67fedb7..ab93ddb5493 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -173,7 +173,7 @@ static bool RunCommandForScope( SetPropertyCommand::HandleAndValidateSourceFilePropertyGENERATED( sf, *(k + 1)); } else { - sf->SetProperty(*k, (k + 1)->c_str()); + sf->SetProperty(*k, *(k + 1)); } } } diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index c4bff76f6f2..a17c9645188 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -37,7 +37,7 @@ bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args, // loop through all the props and set them for (auto k = propsIter + 1; k != args.end(); k += 2) { if (!k->empty()) { - test->SetProperty(*k, (k + 1)->c_str()); + test->SetProperty(*k, *(k + 1)); } } } else { diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 6f13d89acb5..66cbcca2c7c 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -395,7 +395,7 @@ void cmStateSnapshot::InitializeFromParent() parent->BuildSystemDirectory->Properties.GetPropertyValue( "INCLUDE_REGULAR_EXPRESSION"); this->Position->BuildSystemDirectory->Properties.SetProperty( - "INCLUDE_REGULAR_EXPRESSION", cmToCStr(include_regex)); + "INCLUDE_REGULAR_EXPRESSION", include_regex); } cmState* cmStateSnapshot::GetState() const diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 345efed5927..4f446d84ec2 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -267,7 +267,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // Replace everything after "CMAKE_" defKey.replace(defKey.begin() + 6, defKey.end(), property); if (cmProp value = mf->GetDefinition(defKey)) { - this->SetProperty(property, *value); + this->SetProperty(property, value); } }; auto initPropValue = [this, mf, &defKey](const std::string& property, @@ -275,7 +275,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // Replace everything after "CMAKE_" defKey.replace(defKey.begin() + 6, defKey.end(), property); if (cmProp value = mf->GetDefinition(defKey)) { - this->SetProperty(property, *value); + this->SetProperty(property, value); } else if (default_value) { this->SetProperty(property, default_value); } @@ -1388,14 +1388,14 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) reusedFrom = ConvertToString(value); } - this->impl->Properties.SetProperty(prop, reusedFrom.c_str()); + this->impl->Properties.SetProperty(prop, reusedFrom); reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom); reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", cmStrCat(reusedFrom, ".dir/")); cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); - this->SetProperty("COMPILE_PDB_NAME", cmToCStr(tmp)); + this->SetProperty("COMPILE_PDB_NAME", tmp); this->AddUtility(reusedFrom, false, this->impl->Makefile); } else if (prop == propC_STANDARD || prop == propCXX_STANDARD || prop == propCUDA_STANDARD || prop == propHIP_STANDARD || From c8ec137da762d52ae597c8cdb369e7f4958f126f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 19 Aug 2021 15:19:04 -0400 Subject: [PATCH 1159/1519] VS: Update Visual Studio 17 2022 generator for Preview 3.1 Issue: #22339 --- Help/generator/Visual Studio 17 2022.rst | 4 ++-- Help/release/3.21.rst | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index 60073658c63..8b97b9f52af 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -7,7 +7,7 @@ Generates Visual Studio 17 (VS 2022) project files. .. warning:: - This is experimental and based on "Visual Studio 2022 Preview 2". + This is experimental and based on "Visual Studio 2022 Preview 3.1". As of this version of CMake, VS 2022 has not been released. Project Types @@ -51,7 +51,7 @@ name (architecture). For example: Toolset Selection ^^^^^^^^^^^^^^^^^ -The ``v143`` toolset that comes with VS 17 2022 Preview 2 is selected by +The ``v143`` toolset that comes with VS 17 2022 Preview 3.1 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index fc5d6ace2ff..a5125ac0c50 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -27,7 +27,7 @@ Generators ---------- * The :generator:`Visual Studio 17 2022` generator was added. This is - experimental and based on "Visual Studio 2022 Preview 2" because this + experimental and based on "Visual Studio 2022 Preview 3.1" because this version of VS has not been released. * The :ref:`Makefile Generators` and the :generator:`Ninja` generator @@ -310,3 +310,6 @@ Changes made since CMake 3.21.0 include the following. * ``CUDA`` targets with :prop_tgt:`CUDA_SEPARABLE_COMPILATION` enabled are now correctly generated in non-root directories. + +* The :generator:`Visual Studio 17 2022` generator is now based on + "Visual Studio 2022 Preview 3.1". Previously it was based on "Preview 2". From 31c5700d4322ecfa169db2fccf385d6eced4e737 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 25 Aug 2021 10:17:05 -0400 Subject: [PATCH 1160/1519] CMake 3.21.2 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 88263e06899..3ed80c3c01d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 1) +set(CMake_VERSION_PATCH 2) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From aedfe6c9234a130596549332560c97d59deab71c Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 26 Aug 2021 00:01:13 -0400 Subject: [PATCH 1161/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e1d3e63a6ee..9951638f318 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210825) +set(CMake_VERSION_PATCH 20210826) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 33d4ec1282c240a81e253924ca04ff58c0626f1a Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 27 Aug 2021 00:01:10 -0400 Subject: [PATCH 1162/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9951638f318..3b89feafa87 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210826) +set(CMake_VERSION_PATCH 20210827) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From c6a6c008f4039c4fc6709cb7652434d66d0f4ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= <johelegp@gmail.com> Date: Fri, 27 Aug 2021 22:42:53 -0400 Subject: [PATCH 1163/1519] Help: Fix terminology for regular expression in if(MATCHES) This was wrongly changed in commit ba90611225 (Help: Make synopsis of if command more compact; add section headers, 2018-10-05). --- Help/command/if.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/command/if.rst b/Help/command/if.rst index fbf3e363f3a..6ff8852a381 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -171,7 +171,7 @@ Comparisons ``if(<variable|string> MATCHES regex)`` True if the given string or variable's value matches the given regular - condition. See :ref:`Regex Specification` for regex format. + expression. See :ref:`Regex Specification` for regex format. .. versionadded:: 3.9 ``()`` groups are captured in :variable:`CMAKE_MATCH_<n>` variables. From 9c8e25c5fdc3029020768116d01507bd84cbde42 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 28 Aug 2021 00:01:10 -0400 Subject: [PATCH 1164/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3b89feafa87..a1956119a4c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210827) +set(CMake_VERSION_PATCH 20210828) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d186797cf6d084ad8c198475757aaa6a33ddbcc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= <johelegp@gmail.com> Date: Sat, 28 Aug 2021 10:49:28 -0400 Subject: [PATCH 1165/1519] Help: Fix regex in example of cmake-packages(7) This change makes it work as intended as opposed to make the condition always true. This can be confirmed by running the following script: ``` [johel@sundown tmp]$ cat x.cmake function(f) set(valid_inputs abc 123) foreach(input ${ARGV}) if(";${valid_inputs};" MATCHES input) message("old valid: ${input}") endif() if(";${valid_inputs};" MATCHES ";${input};") message("new valid: ${input}") endif() endforeach() endfunction() f("0;z;123;12;abc;ab;13;ac") set(_supported_components Plot Table) set(ClimbingStats_FIND_COMPONENTS Plot Table P T) foreach(_comp ${ClimbingStats_FIND_COMPONENTS}) if(NOT ";${_supported_components};" MATCHES _comp) message("old invalid: set(ClimbingStats_NOT_FOUND_MESSAGE \"Unsupported component: ${_comp}\")") endif() if(NOT ";${_supported_components};" MATCHES ";${_comp};") message("new invalid: set(ClimbingStats_NOT_FOUND_MESSAGE \"Unsupported component: ${_comp}\")") endif() endforeach() [johel@sundown tmp]$ cmake -P x.cmake new valid: 123 new valid: abc old invalid: set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: Plot") old invalid: set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: Table") old invalid: set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: P") new invalid: set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: P") old invalid: set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: T") new invalid: set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: T") ``` --- Help/manual/cmake-packages.7.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst index 52621052b61..5c109ff6722 100644 --- a/Help/manual/cmake-packages.7.rst +++ b/Help/manual/cmake-packages.7.rst @@ -449,7 +449,7 @@ be true. This can be tested with logic in the package configuration file: set(_supported_components Plot Table) foreach(_comp ${ClimbingStats_FIND_COMPONENTS}) - if (NOT ";${_supported_components};" MATCHES _comp) + if (NOT ";${_supported_components};" MATCHES ";${_comp};") set(ClimbingStats_FOUND False) set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}") endif() From c9292f56fc7917dc55e8807d03ffadcd5cb45a0e Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 29 Aug 2021 00:01:09 -0400 Subject: [PATCH 1166/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a1956119a4c..0e8dfc7916d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210828) +set(CMake_VERSION_PATCH 20210829) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f3294e65237a1ac113a047960d3bd21cb68e3078 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 30 Aug 2021 00:01:36 -0400 Subject: [PATCH 1167/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0e8dfc7916d..8f2d1cc5640 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210829) +set(CMake_VERSION_PATCH 20210830) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f94e4b8bb3d5a3403d8612106c3d5fdbe616ca9f Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 31 Aug 2021 00:01:10 -0400 Subject: [PATCH 1168/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8f2d1cc5640..10f40546beb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210830) +set(CMake_VERSION_PATCH 20210831) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2458541fb6a91177a4f608ab1e7bfc4b59ac384e Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 1 Sep 2021 00:01:12 -0400 Subject: [PATCH 1169/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 10f40546beb..78b38d51b1f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210831) +set(CMake_VERSION_PATCH 20210901) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3078bf20637dd3fc6fbed75c04dc5797926dd5b4 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 2 Sep 2021 00:01:09 -0400 Subject: [PATCH 1170/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 78b38d51b1f..00cb1ced792 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210901) +set(CMake_VERSION_PATCH 20210902) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b6cf93472fe25d6c91d893cd1d243dc2d0e160bb Mon Sep 17 00:00:00 2001 From: Martin Kojtal <martin.kojtal@arm.com> Date: Wed, 25 Aug 2021 11:04:13 +0100 Subject: [PATCH 1171/1519] Ninja: fix ARMClang paths for Windows We need to escape paths for ARMClang on Windows, see the referenced issue for more details. Fixes: #21093 --- Source/cmGlobalNinjaGenerator.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 963118fd626..971a462a6c6 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -952,6 +952,8 @@ void cmGlobalNinjaGenerator::EnableLanguage( (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") || (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") || (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") || + (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "ARMClang") || + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "ARMClang") || (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") || (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) { this->UsingGCCOnWindows = true; From 1ad0c5ae53fc0c4f774166337f0e9c93c578cf9b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 2 Sep 2021 12:37:38 -0400 Subject: [PATCH 1172/1519] FindBoost: Add support for Boost 1.77 Update the list of known versions. Run the command cmake -DBOOST_DIR=/path/to/boost_1_77_0 \ -P Utilities/Scripts/BoostScanDeps.cmake to extract dependencies from the 1.77.0 source tree. The dependencies differ from those of 1.76: the `contract`, `thread`, and `wave` components no longer depend on `date_time`. The `math` component no longer depends on `atomic`. Fixes: #22588 --- Modules/FindBoost.cmake | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index f7605c4fd22..38faca24aaf 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -1335,7 +1335,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - else() + elseif(Boost_VERSION_STRING VERSION_LESS 1.77.0) set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) set(_Boost_COROUTINE_DEPENDENCIES context) set(_Boost_FIBER_DEPENDENCIES context) @@ -1350,7 +1350,22 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) + else() + set(_Boost_CONTRACT_DEPENDENCIES thread chrono) + set(_Boost_COROUTINE_DEPENDENCIES context) + set(_Boost_FIBER_DEPENDENCIES context) + set(_Boost_IOSTREAMS_DEPENDENCIES regex) + set(_Boost_JSON_DEPENDENCIES container) + set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) + set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) + set(_Boost_MPI_DEPENDENCIES serialization) + set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) + set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) + set(_Boost_THREAD_DEPENDENCIES chrono atomic) + set(_Boost_TIMER_DEPENDENCIES chrono) + set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic) + set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) + if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.78.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() endif() @@ -1623,7 +1638,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" + "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" From f01ea7e391a23622df2943dc0931a36c5c507bc5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Apr 2019 12:03:49 -0400 Subject: [PATCH 1173/1519] MSVC: Fix MSVC_TOOLSET_VERSION for VS 2022 v143 toolset This was forgotten in commit 0c7f918fb1 (VS: Update Visual Studio 17 2022 generator for Preview 2, 2021-07-14, v3.21.1~29^2) when the toolset was first renumbered to `v143`. Fixes: #22585 --- Modules/Platform/Windows-MSVC.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 4223bde8cfd..7d602c30eed 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -67,7 +67,10 @@ if(NOT MSVC_VERSION) message(FATAL_ERROR "MSVC compiler version not detected properly: ${_compiler_version}") endif() - if(MSVC_VERSION GREATER_EQUAL 1920) + if(MSVC_VERSION GREATER_EQUAL 1930) + # VS 2022 or greater + set(MSVC_TOOLSET_VERSION 143) + elseif(MSVC_VERSION GREATER_EQUAL 1920) # VS 2019 or greater set(MSVC_TOOLSET_VERSION 142) elseif(MSVC_VERSION GREATER_EQUAL 1910) From 38c8f2c4e3308eed56091162e781bd7a830cf8ef Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 2 Sep 2021 13:31:20 -0400 Subject: [PATCH 1174/1519] IRSL: Add discovery of VS 2022 v143 toolset redistributables Fixes: #22586 --- Modules/InstallRequiredSystemLibraries.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index fa7b125f904..331623fa449 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -222,8 +222,12 @@ if(MSVC) set(_MSVC_IDE_VERSION "") if(MSVC_VERSION GREATER_EQUAL 2000) message(WARNING "MSVC ${MSVC_VERSION} not yet supported.") - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 143) + elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 144) message(WARNING "MSVC toolset v${MSVC_TOOLSET_VERSION} not yet supported.") + elseif(MSVC_TOOLSET_VERSION EQUAL 143) + set(MSVC_REDIST_NAME VC142) + set(_MSVC_DLL_VERSION 140) + set(_MSVC_IDE_VERSION 17) elseif(MSVC_TOOLSET_VERSION EQUAL 142) set(MSVC_REDIST_NAME VC142) set(_MSVC_DLL_VERSION 140) @@ -264,7 +268,7 @@ if(MSVC) if(NOT vs VERSION_LESS 15) set(_vs_redist_paths "") # The toolset and its redistributables may come with any VS version 15 or newer. - set(_MSVC_IDE_VERSIONS 16 15) + set(_MSVC_IDE_VERSIONS 17 16 15) foreach(_vs_ver ${_MSVC_IDE_VERSIONS}) set(_vs_glob_redist_paths "") cmake_host_system_information(RESULT _vs_dir QUERY VS_${_vs_ver}_DIR) # undocumented query From 09c7c0a9c339bd95ac68809fe8e299eb09fbba88 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 2 Sep 2021 14:24:25 -0400 Subject: [PATCH 1175/1519] gitlab-ci: Update Windows builds to MSVC 19.29-16.11 toolset --- .gitlab/os-windows.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index 90ff0a8ff07..8037b33f5bd 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -38,7 +38,7 @@ CMAKE_CONFIGURATION: windows_vs2019_x64_ninja VCVARSALL: "${VS160COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat" VCVARSPLATFORM: "x64" - VCVARSVERSION: "14.29.30037" + VCVARSVERSION: "14.29.30133" ### External testing @@ -49,7 +49,7 @@ CMAKE_CONFIGURATION: windows_vs2019_x64 CMAKE_GENERATOR: "Visual Studio 16 2019" CMAKE_GENERATOR_PLATFORM: "x64" - CMAKE_GENERATOR_TOOLSET: "v142,version=14.29.30037" + CMAKE_GENERATOR_TOOLSET: "v142,version=14.29.30133" CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true" ## Tags @@ -60,7 +60,7 @@ - windows - shell - vs2019 - - msvc-19.29-16.10 + - msvc-19.29-16.11 - nonconcurrent .windows_builder_ext_tags: @@ -69,7 +69,7 @@ - windows - shell - vs2019 - - msvc-19.29-16.10 + - msvc-19.29-16.11 - concurrent ## Windows-specific scripts From 441691bc244977c7f645b809a0a873101ebabbcb Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 2 Sep 2021 14:49:40 -0400 Subject: [PATCH 1176/1519] Help: Document that toolchain files may set implicit link information Document in `CMAKE_<LANG>_IMPLICIT_LINK_{LIBRARIES,DIRECTORIES}` how their value is used and that a fallback value may be provided by a toolchain file. --- .../CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst | 18 +++++++++++++++-- .../CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst | 20 ++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst index e9e04be6ea9..081c4da6b52 100644 --- a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst +++ b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst @@ -6,8 +6,20 @@ Implicit linker search path detected for language ``<LANG>``. Compilers typically pass directories containing language runtime libraries and default library search paths when they invoke a linker. These paths are implicit linker search directories for the compiler's -language. CMake automatically detects these directories for each -language and reports the results in this variable. +language. For each language enabled by the :command:`project` or +:command:`enable_language` command, CMake automatically detects these +directories and reports the results in this variable. + +When linking to a static library, CMake adds the implicit link directories +from this variable for each language used in the static library (except +the language whose compiler is used to drive linking). In the case of an +imported static library, the :prop_tgt:`IMPORTED_LINK_INTERFACE_LANGUAGES` +target property lists the languages whose implicit link information is +needed. If any of the languages is not enabled, its value for the +``CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES`` variable may instead be provided +by the project. Or, a :variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` +may set the variable to a value known for the specified toolchain. It will +either be overridden when the language is enabled, or used as a fallback. Some toolchains read implicit directories from an environment variable such as ``LIBRARY_PATH``. If using such an environment variable, keep its value @@ -18,3 +30,5 @@ If policy :policy:`CMP0060` is not set to ``NEW``, then when a library in one of these directories is given by full path to :command:`target_link_libraries` CMake will generate the ``-l<name>`` form on link lines for historical purposes. + +See also the :variable:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES` variable. diff --git a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst index ec164774bd9..0c25489ca8a 100644 --- a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst +++ b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst @@ -5,6 +5,20 @@ Implicit link libraries and flags detected for language ``<LANG>``. Compilers typically pass language runtime library names and other flags when they invoke a linker. These flags are implicit link -options for the compiler's language. CMake automatically detects -these libraries and flags for each language and reports the results in -this variable. +options for the compiler's language. For each language enabled +by the :command:`project` or :command:`enable_language` command, +CMake automatically detects these libraries and flags and reports +the results in this variable. + +When linking to a static library, CMake adds the implicit link libraries and +flags from this variable for each language used in the static library (except +the language whose compiler is used to drive linking). In the case of an +imported static library, the :prop_tgt:`IMPORTED_LINK_INTERFACE_LANGUAGES` +target property lists the languages whose implicit link information is +needed. If any of the languages is not enabled, its value for the +``CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES`` variable may instead be provided +by the project. Or, a :variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` +may set the variable to a value known for the specified toolchain. It will +either be overridden when the language is enabled, or used as a fallback. + +See also the :variable:`CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES` variable. From a89ae726f4cd7cb3c3e9d318f478e6ef90b0df60 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 3 Sep 2021 00:01:17 -0400 Subject: [PATCH 1177/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 00cb1ced792..97b39484ec4 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210902) +set(CMake_VERSION_PATCH 20210903) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2636ad5045ecb413d82c5392a44460671b67916a Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 3 Sep 2021 14:58:03 +0200 Subject: [PATCH 1178/1519] FindPython: Ensure homebrew on Mac M1 is used Fixes: #22581 --- Modules/FindPython/Support.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 8e70e111b73..ce25cfc7093 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -98,6 +98,7 @@ macro (_PYTHON_FIND_FRAMEWORKS) ${_pff_CMAKE_FRAMEWORK_PATH} ~/Library/Frameworks /usr/local/Frameworks + /opt/homebrew/Frameworks ${CMAKE_SYSTEM_FRAMEWORK_PATH}) list (REMOVE_DUPLICATES _pff_frameworks) foreach (_pff_implementation IN LISTS _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS) From 6e2f4029c0e850a7420fba2ab953c0b6323e13fb Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 3 Sep 2021 09:36:40 -0400 Subject: [PATCH 1179/1519] cmAlgorithms: Preserve const-ness in cmRemoveDuplicates range signature The pattern `vec.erase(cmRemoveDuplicates(vec), vec.end())` fails to compile with GCC 4.8's libstdc++ if `cmRemoveDuplicates` returns a `const_iterator` because `end()` returns an `iterator`. Overload `cmRemoveDuplicates` to return an iterator type matching the const-ness of its argument. --- Source/cmAlgorithms.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index c192e2a7bcf..e0ba83d19f2 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -133,7 +133,13 @@ ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last) } template <typename Range> -typename Range::const_iterator cmRemoveDuplicates(Range& r) +typename Range::iterator cmRemoveDuplicates(Range& r) +{ + return cmRemoveDuplicates(r.begin(), r.end()); +} + +template <typename Range> +typename Range::const_iterator cmRemoveDuplicates(Range const& r) { return cmRemoveDuplicates(r.begin(), r.end()); } From 8ff0c2b1dd4b74a1e8e7a79adbfc5db55edff393 Mon Sep 17 00:00:00 2001 From: David Redondo <kde@david-redondo.de> Date: Wed, 18 Aug 2021 13:28:01 +0200 Subject: [PATCH 1180/1519] AutoMoc: Do not list moc macros multiple times When working on a project with a nested dependency tree, a macro can be added multiple times. For example in a project I am working on, in the warning "includes the moc file [... ] but does not contain a [...] macro" the macro list contains 127 entries but only 25 unique ones. --- Source/cmQtAutoGenInitializer.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6cc83289100..c7d38bb4dcb 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -24,6 +24,7 @@ #include "cmsys/SystemInformation.hxx" +#include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmGeneratedFileStream.h" @@ -522,6 +523,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Filters cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"), this->Moc.MacroNames); + this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames), + this->Moc.MacroNames.end()); { auto filterList = cmExpandedList( this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); From ab94c369c9f653d249e5a48ccc43f2dd2d95bc56 Mon Sep 17 00:00:00 2001 From: Kyle Edwards <kyle.edwards@kitware.com> Date: Fri, 27 Aug 2021 09:54:54 -0400 Subject: [PATCH 1181/1519] Refactor: Convert parallel string/backtrace vectors to BT vectors --- Source/cmAlgorithms.h | 4 + Source/cmCPluginAPI.cxx | 2 +- Source/cmComputeLinkDepends.cxx | 2 +- Source/cmComputeTargetDepends.cxx | 2 +- Source/cmGeneratorTarget.cxx | 103 ++++----- Source/cmGeneratorTarget.h | 6 +- Source/cmGlobalGenerator.cxx | 12 +- Source/cmMakefile.cxx | 48 +--- Source/cmMakefile.h | 16 +- Source/cmState.cxx | 5 - Source/cmStateDirectory.cxx | 186 ++++----------- Source/cmStateDirectory.h | 51 ++--- Source/cmStatePrivate.h | 15 +- Source/cmStateSnapshot.cxx | 27 +-- Source/cmTarget.cxx | 227 +++++-------------- Source/cmTarget.h | 45 ++-- Source/cmTargetCompileOptionsCommand.cxx | 3 +- Source/cmTargetIncludeDirectoriesCommand.cxx | 2 +- Source/cmTargetLinkDirectoriesCommand.cxx | 3 +- Source/cmTargetLinkOptionsCommand.cxx | 2 +- 20 files changed, 224 insertions(+), 537 deletions(-) diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index c192e2a7bcf..d00f420636d 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -60,6 +60,10 @@ class cmListFileBacktrace; using cmBacktraceRange = cmRange<std::vector<cmListFileBacktrace>::const_iterator>; +template <typename T> +class BT; +using cmBTStringRange = cmRange<std::vector<BT<std::string>>::const_iterator>; + template <typename Range> typename Range::const_iterator cmRemoveN(Range& r, size_t n) { diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index ace73825ab9..e922ee587fb 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -173,7 +173,7 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt, std::string(tgt) + " for directory " + std::string(d)); return; } - t->InsertLinkDirectory(d, mf->GetBacktrace()); + t->InsertLinkDirectory(BT<std::string>(d, mf->GetBacktrace())); } void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 0b27e34c2b7..15a12ba2438 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -607,7 +607,7 @@ cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, from = depender; } } - return from->ResolveLinkItem(name, cmListFileBacktrace()); + return from->ResolveLinkItem(BT<std::string>(name)); } void cmComputeLinkDepends::InferDependencies() diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 76712f4eb18..5d3e04f7923 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -323,7 +323,7 @@ void cmComputeTargetDepends::AddObjectDepends(int depender_index, } cmGeneratorTarget const* depender = this->Targets[depender_index]; cmLinkItem const& objItem = - depender->ResolveLinkItem(objLib, cmListFileBacktrace()); + depender->ResolveLinkItem(BT<std::string>(objLib)); if (emitted.insert(objItem).second) { if (depender->GetType() != cmStateEnums::EXECUTABLE && depender->GetType() != cmStateEnums::STATIC_LIBRARY && diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3201ae38a6f..648708a2248 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -145,12 +145,10 @@ class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry { public: - TargetPropertyEntryString(std::string propertyValue, - cmListFileBacktrace backtrace, + TargetPropertyEntryString(BT<std::string> propertyValue, cmLinkImplItem const& item = NoLinkImplItem) : cmGeneratorTarget::TargetPropertyEntry(item) , PropertyValue(std::move(propertyValue)) - , Backtrace(std::move(backtrace)) { } @@ -159,46 +157,46 @@ class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry cmGeneratorExpressionDAGChecker*, std::string const&) const override { - return this->PropertyValue; + return this->PropertyValue.Value; } - cmListFileBacktrace GetBacktrace() const override { return this->Backtrace; } - std::string const& GetInput() const override { return this->PropertyValue; } + cmListFileBacktrace GetBacktrace() const override + { + return this->PropertyValue.Backtrace; + } + std::string const& GetInput() const override + { + return this->PropertyValue.Value; + } private: - std::string PropertyValue; - cmListFileBacktrace Backtrace; + BT<std::string> PropertyValue; }; std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry> -CreateTargetPropertyEntry( - const std::string& propertyValue, - cmListFileBacktrace backtrace = cmListFileBacktrace(), - bool evaluateForBuildsystem = false) +CreateTargetPropertyEntry(const BT<std::string>& propertyValue, + bool evaluateForBuildsystem = false) { - if (cmGeneratorExpression::Find(propertyValue) != std::string::npos) { - cmGeneratorExpression ge(std::move(backtrace)); + if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) { + cmGeneratorExpression ge(propertyValue.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(propertyValue); + 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::move(backtrace))); + cm::make_unique<TargetPropertyEntryString>(propertyValue)); } void CreatePropertyGeneratorExpressions( - cmStringRange entries, cmBacktraceRange backtraces, + cmBTStringRange entries, std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items, bool evaluateForBuildsystem = false) { - auto btIt = backtraces.begin(); - for (auto it = entries.begin(); it != entries.end(); ++it, ++btIt) { - items.push_back( - CreateTargetPropertyEntry(*it, *btIt, evaluateForBuildsystem)); + for (auto const& entry : entries) { + items.push_back(CreateTargetPropertyEntry(entry, evaluateForBuildsystem)); } } @@ -289,35 +287,27 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->GlobalGenerator->ComputeTargetObjectDirectory(this); CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(), - t->GetIncludeDirectoriesBacktraces(), this->IncludeDirectoriesEntries); CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(), - t->GetCompileOptionsBacktraces(), this->CompileOptionsEntries); CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(), - t->GetCompileFeaturesBacktraces(), this->CompileFeaturesEntries); CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(), - t->GetCompileDefinitionsBacktraces(), this->CompileDefinitionsEntries); CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(), - t->GetLinkOptionsBacktraces(), this->LinkOptionsEntries); CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(), - t->GetLinkDirectoriesBacktraces(), this->LinkDirectoriesEntries); CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(), - t->GetPrecompileHeadersBacktraces(), this->PrecompileHeadersEntries); CreatePropertyGeneratorExpressions(t->GetSourceEntries(), - t->GetSourceBacktraces(), this->SourceEntries, true); this->PolicyMap = t->GetPolicyMap(); @@ -698,7 +688,8 @@ void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) { this->SourceEntries.insert( before ? this->SourceEntries.begin() : this->SourceEntries.end(), - CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true)); + CreateTargetPropertyEntry( + BT<std::string>(src, this->Makefile->GetBacktrace()), true)); this->ClearSourcesCache(); } @@ -719,11 +710,13 @@ void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs) void cmGeneratorTarget::AddIncludeDirectory(const std::string& src, bool before) { - this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before); + this->Target->InsertInclude( + BT<std::string>(src, this->Makefile->GetBacktrace()), before); this->IncludeDirectoriesEntries.insert( before ? this->IncludeDirectoriesEntries.begin() : this->IncludeDirectoriesEntries.end(), - CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true)); + CreateTargetPropertyEntry( + BT<std::string>(src, this->Makefile->GetBacktrace()), true)); } std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( @@ -1675,9 +1668,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( // for TARGET_OBJECTS instead for backwards compatibility with OLD // behavior of CMP0024 and CMP0026 only. - cmStringRange sourceEntries = this->Target->GetSourceEntries(); - for (std::string const& entry : sourceEntries) { - std::vector<std::string> items = cmExpandedList(entry); + cmBTStringRange sourceEntries = this->Target->GetSourceEntries(); + for (auto const& entry : sourceEntries) { + std::vector<std::string> items = cmExpandedList(entry.Value); for (std::string const& item : items) { if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") && item.back() == '>') { @@ -6364,7 +6357,7 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( if (name == this->GetName() || name.empty()) { return maybeItem; } - maybeItem = this->ResolveLinkItem(name, bt, scope->LG); + maybeItem = this->ResolveLinkItem(BT<std::string>(name, bt), scope->LG); return maybeItem; } @@ -7377,9 +7370,9 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026( // there is no cmGeneratorTarget at configure-time, so search the SOURCES // for TARGET_OBJECTS instead for backwards compatibility with OLD // behavior of CMP0024 and CMP0026 only. - cmStringRange rng = this->Target->GetSourceEntries(); - for (std::string const& entry : rng) { - std::vector<std::string> files = cmExpandedList(entry); + cmBTStringRange rng = this->Target->GetSourceEntries(); + for (auto const& entry : rng) { + std::vector<std::string> files = cmExpandedList(entry.Value); for (std::string const& li : files) { if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') { std::string objLibName = li.substr(17, li.size() - 18); @@ -7607,24 +7600,21 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( { cmLocalGenerator const* lg = this->LocalGenerator; cmMakefile const* mf = lg->GetMakefile(); - cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); - cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); - cmBacktraceRange::const_iterator btIt = btRange.begin(); + cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries(); // Collect libraries directly linked in this configuration. - for (cmStringRange::const_iterator le = entryRange.begin(), - end = entryRange.end(); - le != end; ++le, ++btIt) { + for (auto const& entry : entryRange) { std::vector<std::string> llibs; // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); - cmGeneratorExpression ge(*btIt); - std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); + cmGeneratorExpression ge(entry.Backtrace); + std::unique_ptr<cmCompiledGeneratorExpression> const cge = + ge.Parse(entry.Value); cge->SetEvaluateForBuildsystem(true); std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr, this->LinkerLanguage); - bool const fromGenex = evaluated != *le; + bool const fromGenex = evaluated != entry.Value; cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; @@ -7682,7 +7672,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg); + cmLinkItem item = + this->ResolveLinkItem(BT<std::string>(name, entry.Backtrace), lg); if (!item.Target) { // Report explicitly linked object files separately. std::string const& maybeObj = item.AsStr(); @@ -7724,7 +7715,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // Support OLD behavior for CMP0003. impl.WrongConfigLibraries.push_back( - this->ResolveLinkItem(name, cmListFileBacktrace())); + this->ResolveLinkItem(BT<std::string>(name))); } } } @@ -7750,16 +7741,16 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( } cmLinkItem cmGeneratorTarget::ResolveLinkItem( - std::string const& name, cmListFileBacktrace const& bt) const + BT<std::string> const& name) const { - return this->ResolveLinkItem(name, bt, this->LocalGenerator); + return this->ResolveLinkItem(name, this->LocalGenerator); } -cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name, - cmListFileBacktrace const& bt, +cmLinkItem cmGeneratorTarget::ResolveLinkItem(BT<std::string> const& name, cmLocalGenerator const* lg) const { - TargetOrString resolved = this->ResolveTargetReference(name, lg); + auto bt = name.Backtrace; + TargetOrString resolved = this->ResolveTargetReference(name.Value, lg); if (!resolved.Target) { return cmLinkItem(resolved.String, false, bt); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index bb4621198ba..007608552a7 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -409,10 +409,8 @@ class cmGeneratorTarget TargetOrString ResolveTargetReference(std::string const& name, cmLocalGenerator const* lg) const; - cmLinkItem ResolveLinkItem(std::string const& name, - cmListFileBacktrace const& bt) const; - cmLinkItem ResolveLinkItem(std::string const& name, - cmListFileBacktrace const& bt, + cmLinkItem ResolveLinkItem(BT<std::string> const& name) const; + cmLinkItem ResolveLinkItem(BT<std::string> const& name, cmLocalGenerator const* lg) const; // Compute the set of languages compiled by the target. This is diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 3561deb8800..17cd95e5620 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1718,10 +1718,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() // Construct per-target generator information. for (const auto& mf : this->Makefiles) { - const cmStringRange noconfig_compile_definitions = + const cmBTStringRange noconfig_compile_definitions = mf->GetCompileDefinitionsEntries(); - const cmBacktraceRange noconfig_compile_definitions_bts = - mf->GetCompileDefinitionsBacktraces(); for (auto& target : mf->GetTargets()) { cmTarget* t = &target.second; @@ -1735,12 +1733,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() continue; } - { - auto btIt = noconfig_compile_definitions_bts.begin(); - auto it = noconfig_compile_definitions.begin(); - for (; it != noconfig_compile_definitions.end(); ++it, ++btIt) { - t->InsertCompileDefinition(*it, *btIt); - } + for (auto const& def : noconfig_compile_definitions) { + t->InsertCompileDefinition(def); } cmPolicies::PolicyStatus polSt = diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 7abbd319238..9e7816fb01d 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -212,59 +212,31 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) } } -cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const +cmBTStringRange cmMakefile::GetIncludeDirectoriesEntries() const { return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries(); } -cmBacktraceRange cmMakefile::GetIncludeDirectoriesBacktraces() const -{ - return this->StateSnapshot.GetDirectory() - .GetIncludeDirectoriesEntryBacktraces(); -} - -cmStringRange cmMakefile::GetCompileOptionsEntries() const +cmBTStringRange cmMakefile::GetCompileOptionsEntries() const { return this->StateSnapshot.GetDirectory().GetCompileOptionsEntries(); } -cmBacktraceRange cmMakefile::GetCompileOptionsBacktraces() const -{ - return this->StateSnapshot.GetDirectory().GetCompileOptionsEntryBacktraces(); -} - -cmStringRange cmMakefile::GetCompileDefinitionsEntries() const +cmBTStringRange cmMakefile::GetCompileDefinitionsEntries() const { return this->StateSnapshot.GetDirectory().GetCompileDefinitionsEntries(); } -cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const -{ - return this->StateSnapshot.GetDirectory() - .GetCompileDefinitionsEntryBacktraces(); -} - -cmStringRange cmMakefile::GetLinkOptionsEntries() const +cmBTStringRange cmMakefile::GetLinkOptionsEntries() const { return this->StateSnapshot.GetDirectory().GetLinkOptionsEntries(); } -cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const -{ - return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces(); -} - -cmStringRange cmMakefile::GetLinkDirectoriesEntries() const +cmBTStringRange cmMakefile::GetLinkDirectoriesEntries() const { return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries(); } -cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const -{ - return this->StateSnapshot.GetDirectory() - .GetLinkDirectoriesEntryBacktraces(); -} - cmListFileBacktrace cmMakefile::GetBacktrace() const { return this->Backtrace; @@ -1386,10 +1358,10 @@ void cmMakefile::AddLinkDirectory(std::string const& directory, bool before) { if (before) { this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry( - directory, this->Backtrace); + BT<std::string>(directory, this->Backtrace)); } else { this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry( - directory, this->Backtrace); + BT<std::string>(directory, this->Backtrace)); } } @@ -1876,16 +1848,16 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs, std::string entryString = cmJoin(incs, ";"); if (before) { this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry( - entryString, this->Backtrace); + BT<std::string>(entryString, this->Backtrace)); } else { this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry( - entryString, this->Backtrace); + BT<std::string>(entryString, this->Backtrace)); } // Property on each target: for (auto& target : this->Targets) { cmTarget& t = target.second; - t.InsertInclude(entryString, this->Backtrace, before); + t.InsertInclude(BT<std::string>(entryString, this->Backtrace), before); } } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index fd9a67974d9..bdcab3b1676 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -33,7 +33,6 @@ #include "cmSourceFileLocationKind.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" // IWYU does not see that 'std::unordered_map<std::string, cmTarget>' // will not compile without the complete type. @@ -879,16 +878,11 @@ class cmMakefile bool CheckCMP0037(std::string const& targetName, cmStateEnums::TargetType targetType) const; - cmStringRange GetIncludeDirectoriesEntries() const; - cmBacktraceRange GetIncludeDirectoriesBacktraces() const; - cmStringRange GetCompileOptionsEntries() const; - cmBacktraceRange GetCompileOptionsBacktraces() const; - cmStringRange GetCompileDefinitionsEntries() const; - cmBacktraceRange GetCompileDefinitionsBacktraces() const; - cmStringRange GetLinkOptionsEntries() const; - cmBacktraceRange GetLinkOptionsBacktraces() const; - cmStringRange GetLinkDirectoriesEntries() const; - cmBacktraceRange GetLinkDirectoriesBacktraces() const; + cmBTStringRange GetIncludeDirectoriesEntries() const; + cmBTStringRange GetCompileOptionsEntries() const; + cmBTStringRange GetCompileDefinitionsEntries() const; + cmBTStringRange GetLinkOptionsEntries() const; + cmBTStringRange GetLinkDirectoriesEntries() const; std::set<std::string> const& GetSystemIncludeDirectories() const { diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a045545971f..cfd9ad0984a 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -277,15 +277,10 @@ cmStateSnapshot cmState::Reset() cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator it = this->BuildsystemDirectory.Truncate(); it->IncludeDirectories.clear(); - it->IncludeDirectoryBacktraces.clear(); it->CompileDefinitions.clear(); - it->CompileDefinitionsBacktraces.clear(); it->CompileOptions.clear(); - it->CompileOptionsBacktraces.clear(); it->LinkOptions.clear(); - it->LinkOptionsBacktraces.clear(); it->LinkDirectories.clear(); - it->LinkDirectoriesBacktraces.clear(); it->DirectoryEnd = pos; it->NormalTargetNames.clear(); it->ImportedTargetNames.clear(); diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index ed5b5d85f53..8f83b02fa9a 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -19,6 +19,7 @@ #include "cmState.h" #include "cmStatePrivate.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" static std::string const kBINARY_DIR = "BINARY_DIR"; @@ -63,7 +64,7 @@ cmStateDirectory::cmStateDirectory( } template <typename T, typename U> -cmStringRange GetPropertyContent(T const& content, U contentEndPosition) +cmBTStringRange GetPropertyContent(T const& content, U contentEndPosition) { auto end = content.begin() + contentEndPosition; @@ -73,88 +74,59 @@ cmStringRange GetPropertyContent(T const& content, U contentEndPosition) return cmMakeRange(rbegin.base(), end); } -template <typename T, typename U, typename V> -cmBacktraceRange GetPropertyBacktraces(T const& content, U const& backtraces, - V contentEndPosition) -{ - auto entryEnd = content.begin() + contentEndPosition; - - auto rbegin = cm::make_reverse_iterator(entryEnd); - rbegin = std::find(rbegin, content.rend(), cmPropertySentinal); - - auto it = backtraces.begin() + std::distance(content.begin(), rbegin.base()); - - auto end = backtraces.end(); - return cmMakeRange(it, end); -} - -template <typename T, typename U, typename V> -void AppendEntry(T& content, U& backtraces, V& endContentPosition, - const std::string& value, const cmListFileBacktrace& lfbt) +template <typename T, typename U> +void AppendEntry(T& content, U& endContentPosition, + const BT<std::string>& value) { - if (value.empty()) { + if (value.Value.empty()) { return; } assert(endContentPosition == content.size()); content.push_back(value); - backtraces.push_back(lfbt); endContentPosition = content.size(); } -template <typename T, typename U, typename V> -void SetContent(T& content, U& backtraces, V& endContentPosition, - const std::string& vec, const cmListFileBacktrace& lfbt) +template <typename T, typename U> +void SetContent(T& content, U& endContentPosition, const BT<std::string>& vec) { assert(endContentPosition == content.size()); content.resize(content.size() + 2); - backtraces.resize(backtraces.size() + 2); content.back() = vec; - backtraces.back() = lfbt; endContentPosition = content.size(); } -template <typename T, typename U, typename V> -void ClearContent(T& content, U& backtraces, V& endContentPosition) +template <typename T, typename U> +void ClearContent(T& content, U& endContentPosition) { assert(endContentPosition == content.size()); content.resize(content.size() + 1); - backtraces.resize(backtraces.size() + 1); endContentPosition = content.size(); } -cmStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const +cmBTStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const { return GetPropertyContent( this->DirectoryState->IncludeDirectories, this->Snapshot_.Position->IncludeDirectoryPosition); } -cmBacktraceRange cmStateDirectory::GetIncludeDirectoriesEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, - this->Snapshot_.Position->IncludeDirectoryPosition); -} - void cmStateDirectory::AppendIncludeDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) + const BT<std::string>& vec) { AppendEntry(this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, - this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt); + this->Snapshot_.Position->IncludeDirectoryPosition, vec); } void cmStateDirectory::PrependIncludeDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) + const BT<std::string>& vec) { auto entryEnd = this->DirectoryState->IncludeDirectories.begin() + this->Snapshot_.Position->IncludeDirectoryPosition; @@ -164,167 +136,111 @@ void cmStateDirectory::PrependIncludeDirectoriesEntry( rbegin = std::find(rbegin, rend, cmPropertySentinal); auto entryIt = rbegin.base(); - auto entryBegin = this->DirectoryState->IncludeDirectories.begin(); - - auto btIt = this->DirectoryState->IncludeDirectoryBacktraces.begin() + - std::distance(entryBegin, entryIt); this->DirectoryState->IncludeDirectories.insert(entryIt, vec); - this->DirectoryState->IncludeDirectoryBacktraces.insert(btIt, lfbt); this->Snapshot_.Position->IncludeDirectoryPosition = this->DirectoryState->IncludeDirectories.size(); } -void cmStateDirectory::SetIncludeDirectories(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetIncludeDirectories(const BT<std::string>& vec) { SetContent(this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, - this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt); + this->Snapshot_.Position->IncludeDirectoryPosition, vec); } void cmStateDirectory::ClearIncludeDirectories() { ClearContent(this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, this->Snapshot_.Position->IncludeDirectoryPosition); } -cmStringRange cmStateDirectory::GetCompileDefinitionsEntries() const +cmBTStringRange cmStateDirectory::GetCompileDefinitionsEntries() const { return GetPropertyContent( this->DirectoryState->CompileDefinitions, this->Snapshot_.Position->CompileDefinitionsPosition); } -cmBacktraceRange cmStateDirectory::GetCompileDefinitionsEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, - this->Snapshot_.Position->CompileDefinitionsPosition); -} - void cmStateDirectory::AppendCompileDefinitionsEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) + const BT<std::string>& vec) { AppendEntry(this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, - this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileDefinitionsPosition, vec); } -void cmStateDirectory::SetCompileDefinitions(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetCompileDefinitions(const BT<std::string>& vec) { SetContent(this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, - this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileDefinitionsPosition, vec); } void cmStateDirectory::ClearCompileDefinitions() { ClearContent(this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, this->Snapshot_.Position->CompileDefinitionsPosition); } -cmStringRange cmStateDirectory::GetCompileOptionsEntries() const +cmBTStringRange cmStateDirectory::GetCompileOptionsEntries() const { return GetPropertyContent(this->DirectoryState->CompileOptions, this->Snapshot_.Position->CompileOptionsPosition); } -cmBacktraceRange cmStateDirectory::GetCompileOptionsEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, - this->Snapshot_.Position->CompileOptionsPosition); -} - -void cmStateDirectory::AppendCompileOptionsEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) +void cmStateDirectory::AppendCompileOptionsEntry(const BT<std::string>& vec) { AppendEntry(this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, - this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileOptionsPosition, vec); } -void cmStateDirectory::SetCompileOptions(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetCompileOptions(const BT<std::string>& vec) { SetContent(this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, - this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileOptionsPosition, vec); } void cmStateDirectory::ClearCompileOptions() { ClearContent(this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, this->Snapshot_.Position->CompileOptionsPosition); } -cmStringRange cmStateDirectory::GetLinkOptionsEntries() const +cmBTStringRange cmStateDirectory::GetLinkOptionsEntries() const { return GetPropertyContent(this->DirectoryState->LinkOptions, this->Snapshot_.Position->LinkOptionsPosition); } -cmBacktraceRange cmStateDirectory::GetLinkOptionsEntryBacktraces() const -{ - return GetPropertyBacktraces(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, - this->Snapshot_.Position->LinkOptionsPosition); -} - -void cmStateDirectory::AppendLinkOptionsEntry(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::AppendLinkOptionsEntry(const BT<std::string>& vec) { AppendEntry(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, - this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt); + this->Snapshot_.Position->LinkOptionsPosition, vec); } -void cmStateDirectory::SetLinkOptions(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetLinkOptions(const BT<std::string>& vec) { SetContent(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, - this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt); + this->Snapshot_.Position->LinkOptionsPosition, vec); } void cmStateDirectory::ClearLinkOptions() { ClearContent(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, this->Snapshot_.Position->LinkOptionsPosition); } -cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const +cmBTStringRange cmStateDirectory::GetLinkDirectoriesEntries() const { return GetPropertyContent(this->DirectoryState->LinkDirectories, this->Snapshot_.Position->LinkDirectoriesPosition); } -cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, - this->Snapshot_.Position->LinkDirectoriesPosition); -} - -void cmStateDirectory::AppendLinkDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) +void cmStateDirectory::AppendLinkDirectoriesEntry(const BT<std::string>& vec) { AppendEntry(this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, - this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt); + this->Snapshot_.Position->LinkDirectoriesPosition, vec); } -void cmStateDirectory::PrependLinkDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) +void cmStateDirectory::PrependLinkDirectoriesEntry(const BT<std::string>& vec) { auto entryEnd = this->DirectoryState->LinkDirectories.begin() + this->Snapshot_.Position->LinkDirectoriesPosition; @@ -334,30 +250,22 @@ void cmStateDirectory::PrependLinkDirectoriesEntry( rbegin = std::find(rbegin, rend, cmPropertySentinal); auto entryIt = rbegin.base(); - auto entryBegin = this->DirectoryState->LinkDirectories.begin(); - - auto btIt = this->DirectoryState->LinkDirectoriesBacktraces.begin() + - std::distance(entryBegin, entryIt); this->DirectoryState->LinkDirectories.insert(entryIt, vec); - this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt); this->Snapshot_.Position->LinkDirectoriesPosition = this->DirectoryState->LinkDirectories.size(); } -void cmStateDirectory::SetLinkDirectories(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetLinkDirectories(const BT<std::string>& vec) { SetContent(this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, - this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt); + this->Snapshot_.Position->LinkDirectoriesPosition, vec); } void cmStateDirectory::ClearLinkDirectories() { ClearContent(this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, this->Snapshot_.Position->LinkDirectoriesPosition); } @@ -370,7 +278,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearIncludeDirectories(); return; } - this->SetIncludeDirectories(value, lfbt); + this->SetIncludeDirectories(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_OPTIONS") { @@ -378,7 +286,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearCompileOptions(); return; } - this->SetCompileOptions(value, lfbt); + this->SetCompileOptions(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_DEFINITIONS") { @@ -386,7 +294,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearCompileDefinitions(); return; } - this->SetCompileDefinitions(value, lfbt); + this->SetCompileDefinitions(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_OPTIONS") { @@ -394,7 +302,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearLinkOptions(); return; } - this->SetLinkOptions(value, lfbt); + this->SetLinkOptions(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_DIRECTORIES") { @@ -402,7 +310,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearLinkDirectories(); return; } - this->SetLinkDirectories(value, lfbt); + this->SetLinkDirectories(BT<std::string>(value, lfbt)); return; } @@ -425,23 +333,23 @@ void cmStateDirectory::AppendProperty(const std::string& prop, cmListFileBacktrace const& lfbt) { if (prop == "INCLUDE_DIRECTORIES") { - this->AppendIncludeDirectoriesEntry(value, lfbt); + this->AppendIncludeDirectoriesEntry(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_OPTIONS") { - this->AppendCompileOptionsEntry(value, lfbt); + this->AppendCompileOptionsEntry(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_DEFINITIONS") { - this->AppendCompileDefinitionsEntry(value, lfbt); + this->AppendCompileDefinitionsEntry(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_OPTIONS") { - this->AppendLinkOptionsEntry(value, lfbt); + this->AppendLinkOptionsEntry(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_DIRECTORIES") { - this->AppendLinkDirectoriesEntry(value, lfbt); + this->AppendLinkDirectoriesEntry(BT<std::string>(value, lfbt)); return; } diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 65e2f306299..fac5d58c6be 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -14,7 +14,6 @@ #include "cmProperty.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" -#include "cmStringAlgorithms.h" class cmStateDirectory { @@ -28,47 +27,31 @@ class cmStateDirectory std::string const& GetCurrentBinary() const; void SetCurrentBinary(std::string const& dir); - cmStringRange GetIncludeDirectoriesEntries() const; - cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const; - void AppendIncludeDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void PrependIncludeDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetIncludeDirectories(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetIncludeDirectoriesEntries() const; + void AppendIncludeDirectoriesEntry(BT<std::string> const& vec); + void PrependIncludeDirectoriesEntry(BT<std::string> const& vec); + void SetIncludeDirectories(BT<std::string> const& vec); void ClearIncludeDirectories(); - cmStringRange GetCompileDefinitionsEntries() const; - cmBacktraceRange GetCompileDefinitionsEntryBacktraces() const; - void AppendCompileDefinitionsEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetCompileDefinitions(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetCompileDefinitionsEntries() const; + void AppendCompileDefinitionsEntry(BT<std::string> const& vec); + void SetCompileDefinitions(BT<std::string> const& vec); void ClearCompileDefinitions(); - cmStringRange GetCompileOptionsEntries() const; - cmBacktraceRange GetCompileOptionsEntryBacktraces() const; - void AppendCompileOptionsEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetCompileOptions(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetCompileOptionsEntries() const; + void AppendCompileOptionsEntry(BT<std::string> const& vec); + void SetCompileOptions(BT<std::string> const& vec); void ClearCompileOptions(); - cmStringRange GetLinkOptionsEntries() const; - cmBacktraceRange GetLinkOptionsEntryBacktraces() const; - void AppendLinkOptionsEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void PrependLinkDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt); + cmBTStringRange GetLinkOptionsEntries() const; + void AppendLinkOptionsEntry(BT<std::string> const& vec); + void PrependLinkDirectoriesEntry(BT<std::string> const& vec); + void SetLinkOptions(BT<std::string> const& vec); void ClearLinkOptions(); - cmStringRange GetLinkDirectoriesEntries() const; - cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const; - void AppendLinkDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetLinkDirectories(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetLinkDirectoriesEntries() const; + void AppendLinkDirectoriesEntry(BT<std::string> const& vec); + void SetLinkDirectories(BT<std::string> const& vecs); void ClearLinkDirectories(); void SetProperty(const std::string& prop, const char* value, diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index 6f475f2eea1..fd46eedfa28 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -67,20 +67,15 @@ struct cmStateDetail::BuildsystemDirectoryStateType std::string Location; std::string OutputLocation; - std::vector<std::string> IncludeDirectories; - std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces; + std::vector<BT<std::string>> IncludeDirectories; - std::vector<std::string> CompileDefinitions; - std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; + std::vector<BT<std::string>> CompileDefinitions; - std::vector<std::string> CompileOptions; - std::vector<cmListFileBacktrace> CompileOptionsBacktraces; + std::vector<BT<std::string>> CompileOptions; - std::vector<std::string> LinkOptions; - std::vector<cmListFileBacktrace> LinkOptionsBacktraces; + std::vector<BT<std::string>> LinkOptions; - std::vector<std::string> LinkDirectories; - std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces; + std::vector<BT<std::string>> LinkDirectories; std::vector<std::string> NormalTargetNames; std::vector<std::string> ImportedTargetNames; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 66cbcca2c7c..bd7db85b0b5 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -19,6 +19,10 @@ #include "cmSystemTools.h" #include "cmVersion.h" +#if defined(__CYGWIN__) +# include "cmStringAlgorithms.h" +#endif + cmStateSnapshot::cmStateSnapshot(cmState* state) : State(state) { @@ -259,12 +263,10 @@ bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef) return true; } -template <typename T, typename U, typename V> +template <typename T, typename U> void InitializeContentFromParent(T& parentContent, T& thisContent, - U& parentBacktraces, U& thisBacktraces, - V& contentEndPosition) + U& contentEndPosition) { - auto parentBegin = parentContent.begin(); auto parentEnd = parentContent.end(); auto parentRbegin = cm::make_reverse_iterator(parentEnd); @@ -272,12 +274,7 @@ void InitializeContentFromParent(T& parentContent, T& thisContent, parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal); auto parentIt = parentRbegin.base(); - thisContent = std::vector<std::string>(parentIt, parentEnd); - - auto btIt = parentBacktraces.begin() + std::distance(parentBegin, parentIt); - auto btEnd = parentBacktraces.end(); - - thisBacktraces = std::vector<cmListFileBacktrace>(btIt, btEnd); + thisContent = std::vector<BT<std::string>>(parentIt, parentEnd); contentEndPosition = thisContent.size(); } @@ -359,36 +356,26 @@ void cmStateSnapshot::InitializeFromParent() InitializeContentFromParent( parent->BuildSystemDirectory->IncludeDirectories, this->Position->BuildSystemDirectory->IncludeDirectories, - parent->BuildSystemDirectory->IncludeDirectoryBacktraces, - this->Position->BuildSystemDirectory->IncludeDirectoryBacktraces, this->Position->IncludeDirectoryPosition); InitializeContentFromParent( parent->BuildSystemDirectory->CompileDefinitions, this->Position->BuildSystemDirectory->CompileDefinitions, - parent->BuildSystemDirectory->CompileDefinitionsBacktraces, - this->Position->BuildSystemDirectory->CompileDefinitionsBacktraces, this->Position->CompileDefinitionsPosition); InitializeContentFromParent( parent->BuildSystemDirectory->CompileOptions, this->Position->BuildSystemDirectory->CompileOptions, - parent->BuildSystemDirectory->CompileOptionsBacktraces, - this->Position->BuildSystemDirectory->CompileOptionsBacktraces, this->Position->CompileOptionsPosition); InitializeContentFromParent( parent->BuildSystemDirectory->LinkOptions, this->Position->BuildSystemDirectory->LinkOptions, - parent->BuildSystemDirectory->LinkOptionsBacktraces, - this->Position->BuildSystemDirectory->LinkOptionsBacktraces, this->Position->LinkOptionsPosition); InitializeContentFromParent( parent->BuildSystemDirectory->LinkDirectories, this->Position->BuildSystemDirectory->LinkDirectories, - parent->BuildSystemDirectory->LinkDirectoriesBacktraces, - this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces, this->Position->LinkDirectoriesPosition); cmProp include_regex = diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 4f446d84ec2..af64dcea979 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -83,15 +83,15 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>( cmTarget const* tgt, cmMessenger* messenger, cmListFileBacktrace const& context) { - cmStringRange entries = tgt->GetSourceEntries(); + cmBTStringRange entries = tgt->GetSourceEntries(); if (entries.empty()) { return nullptr; } std::ostringstream ss; const char* sep = ""; - for (std::string const& entry : entries) { - std::vector<std::string> files = cmExpandedList(entry); + for (auto const& entry : entries) { + std::vector<std::string> files = cmExpandedList(entry.Value); for (std::string const& file : files) { if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") && file.back() == '>') { @@ -187,25 +187,16 @@ class cmTargetInternals std::set<std::string> SystemIncludeDirectories; cmTarget::LinkLibraryVectorType OriginalLinkLibraries; std::map<std::string, BTs<std::string>> LanguageStandardProperties; - std::vector<std::string> IncludeDirectoriesEntries; - std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces; + std::vector<BT<std::string>> IncludeDirectoriesEntries; std::vector<std::string> InstallIncludeDirectoriesEntries; - std::vector<std::string> CompileOptionsEntries; - std::vector<cmListFileBacktrace> CompileOptionsBacktraces; - std::vector<std::string> CompileFeaturesEntries; - std::vector<cmListFileBacktrace> CompileFeaturesBacktraces; - std::vector<std::string> CompileDefinitionsEntries; - std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; - std::vector<std::string> PrecompileHeadersEntries; - std::vector<cmListFileBacktrace> PrecompileHeadersBacktraces; - std::vector<std::string> SourceEntries; - std::vector<cmListFileBacktrace> SourceBacktraces; - std::vector<std::string> LinkOptionsEntries; - std::vector<cmListFileBacktrace> LinkOptionsBacktraces; - std::vector<std::string> LinkDirectoriesEntries; - std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces; - std::vector<std::string> LinkImplementationPropertyEntries; - std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces; + std::vector<BT<std::string>> CompileOptionsEntries; + std::vector<BT<std::string>> CompileFeaturesEntries; + std::vector<BT<std::string>> CompileDefinitionsEntries; + std::vector<BT<std::string>> PrecompileHeadersEntries; + std::vector<BT<std::string>> SourceEntries; + std::vector<BT<std::string>> LinkOptionsEntries; + std::vector<BT<std::string>> LinkDirectoriesEntries; + std::vector<BT<std::string>> LinkImplementationPropertyEntries; std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>> TLLCommands; cmListFileBacktrace Backtrace; @@ -482,8 +473,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // of the same directory property: cm::append(this->impl->IncludeDirectoriesEntries, this->impl->Makefile->GetIncludeDirectoriesEntries()); - cm::append(this->impl->IncludeDirectoriesBacktraces, - this->impl->Makefile->GetIncludeDirectoriesBacktraces()); { auto const& sysInc = this->impl->Makefile->GetSystemIncludeDirectories(); @@ -493,18 +482,12 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, cm::append(this->impl->CompileOptionsEntries, this->impl->Makefile->GetCompileOptionsEntries()); - cm::append(this->impl->CompileOptionsBacktraces, - this->impl->Makefile->GetCompileOptionsBacktraces()); cm::append(this->impl->LinkOptionsEntries, this->impl->Makefile->GetLinkOptionsEntries()); - cm::append(this->impl->LinkOptionsBacktraces, - this->impl->Makefile->GetLinkOptionsBacktraces()); cm::append(this->impl->LinkDirectoriesEntries, this->impl->Makefile->GetLinkDirectoriesEntries()); - cm::append(this->impl->LinkDirectoriesBacktraces, - this->impl->Makefile->GetLinkDirectoriesBacktraces()); } if (this->impl->TargetType == cmStateEnums::EXECUTABLE) { @@ -613,11 +596,9 @@ void cmTarget::SetLanguageStandardProperty(std::string const& lang, const std::string& feature) { cmListFileBacktrace featureBacktrace; - for (size_t i = 0; i < this->impl->CompileFeaturesEntries.size(); i++) { - if (this->impl->CompileFeaturesEntries[i] == feature) { - if (i < this->impl->CompileFeaturesBacktraces.size()) { - featureBacktrace = this->impl->CompileFeaturesBacktraces[i]; - } + for (auto const& entry : this->impl->CompileFeaturesEntries) { + if (entry.Value == feature) { + featureBacktrace = entry.Backtrace; break; } } @@ -729,8 +710,7 @@ void cmTarget::AddTracedSources(std::vector<std::string> const& srcs) { if (!srcs.empty()) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.push_back(cmJoin(srcs, ";")); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(cmJoin(srcs, ";"), lfbt); } } @@ -754,8 +734,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs) } if (!srcFiles.empty()) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.push_back(std::move(srcFiles)); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(std::move(srcFiles), lfbt); } } @@ -843,9 +822,9 @@ struct TargetPropertyEntryFinder { } - bool operator()(std::string const& entry) + bool operator()(BT<std::string> const& entry) { - std::vector<std::string> files = cmExpandedList(entry); + std::vector<std::string> files = cmExpandedList(entry.Value); std::vector<cmSourceFileLocation> locations; locations.reserve(files.size()); std::transform(files.begin(), files.end(), std::back_inserter(locations), @@ -866,11 +845,7 @@ cmSourceFile* cmTarget::AddSource(const std::string& src, bool before) cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); this->impl->SourceEntries.insert(before ? this->impl->SourceEntries.begin() : this->impl->SourceEntries.end(), - src); - this->impl->SourceBacktraces.insert( - before ? this->impl->SourceBacktraces.begin() - : this->impl->SourceBacktraces.end(), - lfbt); + BT<std::string>(src, lfbt)); } if (cmGeneratorExpression::Find(src) != std::string::npos) { return nullptr; @@ -1087,96 +1062,51 @@ cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries() const return cmMakeRange(this->impl->InstallIncludeDirectoriesEntries); } -cmStringRange cmTarget::GetIncludeDirectoriesEntries() const +cmBTStringRange cmTarget::GetIncludeDirectoriesEntries() const { return cmMakeRange(this->impl->IncludeDirectoriesEntries); } -cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const -{ - return cmMakeRange(this->impl->IncludeDirectoriesBacktraces); -} - -cmStringRange cmTarget::GetCompileOptionsEntries() const +cmBTStringRange cmTarget::GetCompileOptionsEntries() const { return cmMakeRange(this->impl->CompileOptionsEntries); } -cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const -{ - return cmMakeRange(this->impl->CompileOptionsBacktraces); -} - -cmStringRange cmTarget::GetCompileFeaturesEntries() const +cmBTStringRange cmTarget::GetCompileFeaturesEntries() const { return cmMakeRange(this->impl->CompileFeaturesEntries); } -cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const -{ - return cmMakeRange(this->impl->CompileFeaturesBacktraces); -} - -cmStringRange cmTarget::GetCompileDefinitionsEntries() const +cmBTStringRange cmTarget::GetCompileDefinitionsEntries() const { return cmMakeRange(this->impl->CompileDefinitionsEntries); } -cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const -{ - return cmMakeRange(this->impl->CompileDefinitionsBacktraces); -} - -cmStringRange cmTarget::GetPrecompileHeadersEntries() const +cmBTStringRange cmTarget::GetPrecompileHeadersEntries() const { return cmMakeRange(this->impl->PrecompileHeadersEntries); } -cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const -{ - return cmMakeRange(this->impl->PrecompileHeadersBacktraces); -} - -cmStringRange cmTarget::GetSourceEntries() const +cmBTStringRange cmTarget::GetSourceEntries() const { return cmMakeRange(this->impl->SourceEntries); } -cmBacktraceRange cmTarget::GetSourceBacktraces() const -{ - return cmMakeRange(this->impl->SourceBacktraces); -} - -cmStringRange cmTarget::GetLinkOptionsEntries() const +cmBTStringRange cmTarget::GetLinkOptionsEntries() const { return cmMakeRange(this->impl->LinkOptionsEntries); } -cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const -{ - return cmMakeRange(this->impl->LinkOptionsBacktraces); -} - -cmStringRange cmTarget::GetLinkDirectoriesEntries() const +cmBTStringRange cmTarget::GetLinkDirectoriesEntries() const { return cmMakeRange(this->impl->LinkDirectoriesEntries); } -cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const -{ - return cmMakeRange(this->impl->LinkDirectoriesBacktraces); -} - -cmStringRange cmTarget::GetLinkImplementationEntries() const +cmBTStringRange cmTarget::GetLinkImplementationEntries() const { return cmMakeRange(this->impl->LinkImplementationPropertyEntries); } -cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const -{ - return cmMakeRange(this->impl->LinkImplementationPropertyBacktraces); -} - namespace { #define MAKE_PROP(PROP) const std::string prop##PROP = #PROP MAKE_PROP(C_STANDARD); @@ -1270,75 +1200,57 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) if (prop == propINCLUDE_DIRECTORIES) { this->impl->IncludeDirectoriesEntries.clear(); - this->impl->IncludeDirectoriesBacktraces.clear(); if (value) { - this->impl->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->IncludeDirectoriesBacktraces.push_back(lfbt); + this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_OPTIONS) { this->impl->CompileOptionsEntries.clear(); - this->impl->CompileOptionsBacktraces.clear(); if (value) { - this->impl->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileOptionsBacktraces.push_back(lfbt); + this->impl->CompileOptionsEntries.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_FEATURES) { this->impl->CompileFeaturesEntries.clear(); - this->impl->CompileFeaturesBacktraces.clear(); if (value) { - this->impl->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileFeaturesBacktraces.push_back(lfbt); + this->impl->CompileFeaturesEntries.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_DEFINITIONS) { this->impl->CompileDefinitionsEntries.clear(); - this->impl->CompileDefinitionsBacktraces.clear(); if (value) { - this->impl->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileDefinitionsBacktraces.push_back(lfbt); + this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt); } } else if (prop == propLINK_OPTIONS) { this->impl->LinkOptionsEntries.clear(); - this->impl->LinkOptionsBacktraces.clear(); if (value) { - this->impl->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkOptionsBacktraces.push_back(lfbt); + this->impl->LinkOptionsEntries.emplace_back(value, lfbt); } } else if (prop == propLINK_DIRECTORIES) { this->impl->LinkDirectoriesEntries.clear(); - this->impl->LinkDirectoriesBacktraces.clear(); if (value) { - this->impl->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkDirectoriesBacktraces.push_back(lfbt); + this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == propPRECOMPILE_HEADERS) { this->impl->PrecompileHeadersEntries.clear(); - this->impl->PrecompileHeadersBacktraces.clear(); if (value) { - this->impl->PrecompileHeadersEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->PrecompileHeadersBacktraces.push_back(lfbt); + this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt); } } else if (prop == propLINK_LIBRARIES) { this->impl->LinkImplementationPropertyEntries.clear(); - this->impl->LinkImplementationPropertyBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkImplementationPropertyEntries.emplace_back(value); - this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt); + this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt); } } else if (prop == propSOURCES) { this->impl->SourceEntries.clear(); - this->impl->SourceBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.emplace_back(value); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(value, lfbt); } } else if (prop == propIMPORTED_GLOBAL) { if (!cmIsOn(value)) { @@ -1443,39 +1355,33 @@ void cmTarget::AppendProperty(const std::string& prop, } if (prop == "INCLUDE_DIRECTORIES") { if (!value.empty()) { - this->impl->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->IncludeDirectoriesBacktraces.push_back(lfbt); + this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_OPTIONS") { if (!value.empty()) { - this->impl->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileOptionsBacktraces.push_back(lfbt); + this->impl->CompileOptionsEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_FEATURES") { if (!value.empty()) { - this->impl->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileFeaturesBacktraces.push_back(lfbt); + this->impl->CompileFeaturesEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_DEFINITIONS") { if (!value.empty()) { - this->impl->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileDefinitionsBacktraces.push_back(lfbt); + this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_OPTIONS") { if (!value.empty()) { - this->impl->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkOptionsBacktraces.push_back(lfbt); + this->impl->LinkOptionsEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_DIRECTORIES") { if (!value.empty()) { - this->impl->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkDirectoriesBacktraces.push_back(lfbt); + this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == "PRECOMPILE_HEADERS") { if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { @@ -1487,20 +1393,17 @@ void cmTarget::AppendProperty(const std::string& prop, return; } if (!value.empty()) { - this->impl->PrecompileHeadersEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->PrecompileHeadersBacktraces.push_back(lfbt); + this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_LIBRARIES") { if (!value.empty()) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkImplementationPropertyEntries.emplace_back(value); - this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt); + this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt); } } else if (prop == "SOURCES") { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.emplace_back(value); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(value, lfbt); } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); @@ -1550,70 +1453,46 @@ void cmTarget::AppendBuildInterfaceIncludes() } } -void cmTarget::InsertInclude(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertInclude(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->IncludeDirectoriesEntries.begin() : this->impl->IncludeDirectoriesEntries.end(); - auto btPosition = before ? this->impl->IncludeDirectoriesBacktraces.begin() - : this->impl->IncludeDirectoriesBacktraces.end(); - this->impl->IncludeDirectoriesEntries.insert(position, entry); - this->impl->IncludeDirectoriesBacktraces.insert(btPosition, bt); } -void cmTarget::InsertCompileOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertCompileOption(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->CompileOptionsEntries.begin() : this->impl->CompileOptionsEntries.end(); - auto btPosition = before ? this->impl->CompileOptionsBacktraces.begin() - : this->impl->CompileOptionsBacktraces.end(); - this->impl->CompileOptionsEntries.insert(position, entry); - this->impl->CompileOptionsBacktraces.insert(btPosition, bt); } -void cmTarget::InsertCompileDefinition(std::string const& entry, - cmListFileBacktrace const& bt) +void cmTarget::InsertCompileDefinition(BT<std::string> const& entry) { this->impl->CompileDefinitionsEntries.push_back(entry); - this->impl->CompileDefinitionsBacktraces.push_back(bt); } -void cmTarget::InsertLinkOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertLinkOption(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->LinkOptionsEntries.begin() : this->impl->LinkOptionsEntries.end(); - auto btPosition = before ? this->impl->LinkOptionsBacktraces.begin() - : this->impl->LinkOptionsBacktraces.end(); - this->impl->LinkOptionsEntries.insert(position, entry); - this->impl->LinkOptionsBacktraces.insert(btPosition, bt); } -void cmTarget::InsertLinkDirectory(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertLinkDirectory(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->LinkDirectoriesEntries.begin() : this->impl->LinkDirectoriesEntries.end(); - auto btPosition = before ? this->impl->LinkDirectoriesBacktraces.begin() - : this->impl->LinkDirectoriesBacktraces.end(); - this->impl->LinkDirectoriesEntries.insert(position, entry); - this->impl->LinkDirectoriesBacktraces.insert(btPosition, bt); } -void cmTarget::InsertPrecompileHeader(std::string const& entry, - cmListFileBacktrace const& bt) +void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry) { this->impl->PrecompileHeadersEntries.push_back(entry); - this->impl->PrecompileHeadersBacktraces.push_back(bt); } static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, diff --git a/Source/cmTarget.h b/Source/cmTarget.h index de0c4e3b693..eced1ae4a93 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -217,18 +217,12 @@ class cmTarget //! Get a backtrace from the creation of the target. cmListFileBacktrace const& GetBacktrace() const; - void InsertInclude(std::string const& entry, cmListFileBacktrace const& bt, - bool before = false); - void InsertCompileOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before = false); - void InsertCompileDefinition(std::string const& entry, - cmListFileBacktrace const& bt); - void InsertLinkOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before = false); - void InsertLinkDirectory(std::string const& entry, - cmListFileBacktrace const& bt, bool before = false); - void InsertPrecompileHeader(std::string const& entry, - cmListFileBacktrace const& bt); + void InsertInclude(BT<std::string> const& entry, bool before = false); + void InsertCompileOption(BT<std::string> const& entry, bool before = false); + void InsertCompileDefinition(BT<std::string> const& entry); + void InsertLinkOption(BT<std::string> const& entry, bool before = false); + void InsertLinkDirectory(BT<std::string> const& entry, bool before = false); + void InsertPrecompileHeader(BT<std::string> const& entry); void AppendBuildInterfaceIncludes(); @@ -248,32 +242,23 @@ class cmTarget std::string const& value, const std::string& feature); - cmStringRange GetIncludeDirectoriesEntries() const; - cmBacktraceRange GetIncludeDirectoriesBacktraces() const; + cmBTStringRange GetIncludeDirectoriesEntries() const; - cmStringRange GetCompileOptionsEntries() const; - cmBacktraceRange GetCompileOptionsBacktraces() const; + cmBTStringRange GetCompileOptionsEntries() const; - cmStringRange GetCompileFeaturesEntries() const; - cmBacktraceRange GetCompileFeaturesBacktraces() const; + cmBTStringRange GetCompileFeaturesEntries() const; - cmStringRange GetCompileDefinitionsEntries() const; - cmBacktraceRange GetCompileDefinitionsBacktraces() const; + cmBTStringRange GetCompileDefinitionsEntries() const; - cmStringRange GetPrecompileHeadersEntries() const; - cmBacktraceRange GetPrecompileHeadersBacktraces() const; + cmBTStringRange GetPrecompileHeadersEntries() const; - cmStringRange GetSourceEntries() const; - cmBacktraceRange GetSourceBacktraces() const; + cmBTStringRange GetSourceEntries() const; - cmStringRange GetLinkOptionsEntries() const; - cmBacktraceRange GetLinkOptionsBacktraces() const; + cmBTStringRange GetLinkOptionsEntries() const; - cmStringRange GetLinkDirectoriesEntries() const; - cmBacktraceRange GetLinkDirectoriesBacktraces() const; + cmBTStringRange GetLinkDirectoriesEntries() const; - cmStringRange GetLinkImplementationEntries() const; - cmBacktraceRange GetLinkImplementationBacktraces() const; + cmBTStringRange GetLinkImplementationEntries() const; std::string ImportedGetFullPath(const std::string& config, cmStateEnums::ArtifactType artifact) const; diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index dee2c10a39b..8ca3842d3db 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -37,7 +37,8 @@ class TargetCompileOptionsImpl : public cmTargetPropCommandBase } cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertCompileOption(this->Join(content), lfbt, prepend); + tgt->InsertCompileOption(BT<std::string>(this->Join(content), lfbt), + prepend); return true; // Successfully handled. } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 3897499f30e..f31501ebda5 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -63,7 +63,7 @@ bool TargetIncludeDirectoriesImpl::HandleDirectContent( bool system) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertInclude(this->Join(content), lfbt, prepend); + tgt->InsertInclude(BT<std::string>(this->Join(content), lfbt), prepend); if (system) { std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/"; std::set<std::string> sdirs; diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx index 0c68d604c83..3ba27a83a30 100644 --- a/Source/cmTargetLinkDirectoriesCommand.cxx +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -34,7 +34,8 @@ class TargetLinkDirectoriesImpl : public cmTargetPropCommandBase bool prepend, bool /*system*/) override { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend); + tgt->InsertLinkDirectory(BT<std::string>(this->Join(content), lfbt), + prepend); return true; // Successfully handled. } }; diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index df9416fad3f..3ea2d7175e4 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -30,7 +30,7 @@ class TargetLinkOptionsImpl : public cmTargetPropCommandBase bool prepend, bool /*system*/) override { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertLinkOption(this->Join(content), lfbt, prepend); + tgt->InsertLinkOption(BT<std::string>(this->Join(content), lfbt), prepend); return true; // Successfully handled. } From 115152ce103ddaf9ae4bc43d362d892731de8307 Mon Sep 17 00:00:00 2001 From: ulatekh <ulatekh@yahoo.com> Date: Mon, 30 Aug 2021 16:10:43 -0700 Subject: [PATCH 1182/1519] KWSys: SystemTools: Ensure Windows Vista APIs are available before using them Backport KWSys commit `4ef5b1063` (SystemTools: Ensure Windows Vista APIs are available before using them, 2021-08-30) to the CMake 3.21 release branch. --- Source/kwsys/SystemTools.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 7c26974ef8c..f610a7050b3 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -14,6 +14,10 @@ # endif #endif +#if defined(_WIN32) && !defined(_WIN32_WINNT) +# define _WIN32_WINNT _WIN32_WINNT_VISTA +#endif + #include "kwsysPrivate.h" #include KWSYS_HEADER(RegularExpression.hxx) #include KWSYS_HEADER(SystemTools.hxx) From 00ccc0f47c5ca1f640d1fe34eac135ac9a3adb36 Mon Sep 17 00:00:00 2001 From: KWSys Upstream <kwrobot@kitware.com> Date: Fri, 3 Sep 2021 09:58:57 -0400 Subject: [PATCH 1183/1519] KWSys 2021-09-03 (0da908d4) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 0da908d419f80a32c361d28d7ce364b8a80ae2c2 (master). Upstream Shortlog ----------------- Ben Boeckel (2): 40bbf3fd Status: offer an `IsSuccess` method a6a0bb15 Status: use the new IsSuccess method Brad King (1): 5d4c8b04 SystemInformation: Simplify demangle buffer management ulatekh (1): 4ef5b106 SystemTools: Ensure Windows Vista APIs are available before using them --- Status.hxx.in | 5 ++++- SystemInformation.cxx | 6 ++---- SystemTools.cxx | 28 ++++++++++++++++------------ testDirectory.cxx | 2 +- testStatus.cxx | 12 ++++++++++++ testSystemTools.cxx | 2 +- 6 files changed, 36 insertions(+), 19 deletions(-) diff --git a/Status.hxx.in b/Status.hxx.in index ed46d5c2bc8..16efaefdf33 100644 --- a/Status.hxx.in +++ b/Status.hxx.in @@ -55,7 +55,10 @@ public: #endif /** Return true on "Success", false otherwise. */ - explicit operator bool() const { return this->Kind_ == Kind::Success; } + bool IsSuccess() const { return this->Kind_ == Kind::Success; } + + /** Return true on "Success", false otherwise. */ + explicit operator bool() const { return this->IsSuccess(); } /** Return the kind of status. */ Kind GetKind() const { return this->Kind_; } diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 12f9139cc93..f2bf85f6a15 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -1356,14 +1356,12 @@ std::string SymbolProperties::Demangle(const char* symbol) const std::string result = safes(symbol); # if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) int status = 0; - size_t bufferLen = 1024; - char* buffer = (char*)malloc(1024); char* demangledSymbol = - abi::__cxa_demangle(symbol, buffer, &bufferLen, &status); + abi::__cxa_demangle(symbol, nullptr, nullptr, &status); if (!status) { result = demangledSymbol; } - free(buffer); + free(demangledSymbol); # else (void)symbol; # endif diff --git a/SystemTools.cxx b/SystemTools.cxx index 7c26974ef8c..930d84c873a 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -14,6 +14,10 @@ # endif #endif +#if defined(_WIN32) && !defined(_WIN32_WINNT) +# define _WIN32_WINNT _WIN32_WINNT_VISTA +#endif + #include "kwsysPrivate.h" #include KWSYS_HEADER(RegularExpression.hxx) #include KWSYS_HEADER(SystemTools.hxx) @@ -2419,7 +2423,7 @@ Status SystemTools::CopyFileAlways(std::string const& source, if (SystemTools::FileIsDirectory(source)) { status = SystemTools::MakeDirectory(destination); - if (!status) { + if (!status.IsSuccess()) { return status; } } else { @@ -2444,17 +2448,17 @@ Status SystemTools::CopyFileAlways(std::string const& source, // Create destination directory if (!destination_dir.empty()) { status = SystemTools::MakeDirectory(destination_dir); - if (!status) { + if (!status.IsSuccess()) { return status; } } status = SystemTools::CloneFileContent(source, real_destination); // if cloning did not succeed, fall back to blockwise copy - if (!status) { + if (!status.IsSuccess()) { status = SystemTools::CopyFileContentBlockwise(source, real_destination); } - if (!status) { + if (!status.IsSuccess()) { return status; } } @@ -2484,11 +2488,11 @@ Status SystemTools::CopyADirectory(std::string const& source, Status status; Directory dir; status = dir.Load(source); - if (!status) { + if (!status.IsSuccess()) { return status; } status = SystemTools::MakeDirectory(destination); - if (!status) { + if (!status.IsSuccess()) { return status; } @@ -2503,12 +2507,12 @@ Status SystemTools::CopyADirectory(std::string const& source, fullDestPath += "/"; fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum)); status = SystemTools::CopyADirectory(fullPath, fullDestPath, always); - if (!status) { + if (!status.IsSuccess()) { return status; } } else { status = SystemTools::CopyAFile(fullPath, destination, always); - if (!status) { + if (!status.IsSuccess()) { return status; } } @@ -2660,7 +2664,7 @@ Status SystemTools::RemoveADirectory(std::string const& source) Status status; Directory dir; status = dir.Load(source); - if (!status) { + if (!status.IsSuccess()) { return status; } @@ -2674,12 +2678,12 @@ Status SystemTools::RemoveADirectory(std::string const& source) if (SystemTools::FileIsDirectory(fullPath) && !SystemTools::FileIsSymlink(fullPath)) { status = SystemTools::RemoveADirectory(fullPath); - if (!status) { + if (!status.IsSuccess()) { return status; } } else { status = SystemTools::RemoveFile(fullPath); - if (!status) { + if (!status.IsSuccess()) { return status; } } @@ -3143,7 +3147,7 @@ Status SystemTools::ReadSymlink(std::string const& newName, status = Status::Windows_GetLastError(); } CloseHandle(hFile); - if (!status) { + if (!status.IsSuccess()) { return status; } PREPARSE_DATA_BUFFER data = diff --git a/testDirectory.cxx b/testDirectory.cxx index 06a22dc4753..a847462a3b1 100644 --- a/testDirectory.cxx +++ b/testDirectory.cxx @@ -122,7 +122,7 @@ int _copyDirectoryTest() } const Status copysuccess = SystemTools::CopyADirectory(source, destination); const bool destinationexists = SystemTools::PathExists(destination); - if (copysuccess) { + if (copysuccess.IsSuccess()) { std::cerr << "CopyADirectory should have returned false" << std::endl; SystemTools::RemoveADirectory(destination); return 3; diff --git a/testStatus.cxx b/testStatus.cxx index f85ef422dbf..0a767a8547d 100644 --- a/testStatus.cxx +++ b/testStatus.cxx @@ -31,6 +31,10 @@ int testStatus(int, char* []) std::cerr << "Status Success constructor does not produce Success\n"; res = false; } + if (!status.IsSuccess()) { + std::cerr << "Status Success gives false IsSuccess\n"; + res = false; + } if (!status) { std::cerr << "Status Success kind is not true\n"; res = false; @@ -55,6 +59,10 @@ int testStatus(int, char* []) std::cerr << "Status POSIX constructor does not produce POSIX\n"; res = false; } + if (status.IsSuccess()) { + std::cerr << "Status POSIX gives true IsSuccess\n"; + res = false; + } if (status) { std::cerr << "Status POSIX kind is not false\n"; res = false; @@ -87,6 +95,10 @@ int testStatus(int, char* []) std::cerr << "Status Windows constructor does not produce Windows\n"; res = false; } + if (status.IsSuccess()) { + std::cerr << "Status Windows gives true IsSuccess\n"; + res = false; + } if (status) { std::cerr << "Status Windows kind is not false\n"; res = false; diff --git a/testSystemTools.cxx b/testSystemTools.cxx index 39a19cbf241..6ccc7a7cb89 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -436,7 +436,7 @@ static bool CheckFileOperations() if (symlinkStatus.GetWindows() != ERROR_PRIVILEGE_NOT_HELD) #endif { - if (!symlinkStatus) { + if (!symlinkStatus.IsSuccess()) { std::cerr << "CreateSymlink for: " << testBadSymlink << " -> " << testBadSymlinkTgt << " failed: " << symlinkStatus.GetString() << std::endl; From fa2f6e0f5a4ae2349b3ccc309654b7f6cbadb080 Mon Sep 17 00:00:00 2001 From: Wayde Reitsma <pootisspencerherenao@gmail.com> Date: Sat, 4 Sep 2021 09:34:05 +1000 Subject: [PATCH 1184/1519] cmNinjaTargetGenerator: Use short path for cmcldeps.exe --- Source/cmNinjaTargetGenerator.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 1b6b834e5db..be8bb08e6c8 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -774,8 +774,11 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmProp d = mf->GetDefinition("CMAKE_C_COMPILER"); const std::string cl = d ? *d : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); - cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang, - ' ', vars.Source, " $DEP_FILE $out \"", + std::string cmcldepsPath; + cmSystemTools::GetShortPath(cmSystemTools::GetCMClDepsCommand(), + cmcldepsPath); + cldeps = cmStrCat(cmcldepsPath, ' ', lang, ' ', vars.Source, + " $DEP_FILE $out \"", mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"), "\" \"", cl, "\" "); } From 6d5452f1bc086dd27c34d517c8d7cad78d4c25f6 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 4 Sep 2021 00:01:13 -0400 Subject: [PATCH 1185/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 97b39484ec4..281d96ccc3c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210903) +set(CMake_VERSION_PATCH 20210904) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9ab2e0e6f7441a9c8ed37895699af061dbb0b1d1 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 5 Sep 2021 00:01:09 -0400 Subject: [PATCH 1186/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 281d96ccc3c..677872b856b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210904) +set(CMake_VERSION_PATCH 20210905) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 86ee38d75678d68bb1a79b9fa443b42723b09f23 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 6 Sep 2021 00:01:25 -0400 Subject: [PATCH 1187/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 677872b856b..d4fb546110e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210905) +set(CMake_VERSION_PATCH 20210906) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From d897391782f0452984add2e4ea10abdf14107c5d Mon Sep 17 00:00:00 2001 From: Mattias Ellert <mattias.ellert@physics.uu.se> Date: Mon, 6 Sep 2021 06:54:51 +0200 Subject: [PATCH 1188/1519] Fix typo in comment The comment lists -lpthread twice, when "-lpthreads, -lpthread" is meant. Also the grammar (did not found) is incorrect. --- Modules/FindThreads.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index c6a3451f7be..e4d6cf3cb97 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -106,7 +106,7 @@ endmacro() # Do NOT even think about using it outside of this file! macro(_check_pthreads_flag) if(NOT Threads_FOUND) - # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread + # If we did not find -lpthreads, -lpthread, or -lthread, look for -pthread if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG) message(CHECK_START "Check if compiler accepts -pthread") if(CMAKE_C_COMPILER_LOADED) From cdd2714dfa4d49b39d08da4e10dff5ea93304891 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre <mathieu.malaterre@gmail.com> Date: Mon, 6 Sep 2021 15:04:40 +0200 Subject: [PATCH 1189/1519] FindICU: Really mark variables as advanced --- Modules/FindICU.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake index 2bb49adec11..1bae825a53e 100644 --- a/Modules/FindICU.cmake +++ b/Modules/FindICU.cmake @@ -172,7 +172,7 @@ function(_ICU_FIND) DOC "ICU ${program} executable" NO_PACKAGE_ROOT_PATH ) - mark_as_advanced(cache_var) + mark_as_advanced("${cache_var}") set("${program_var}" "${${cache_var}}" PARENT_SCOPE) endforeach() @@ -301,7 +301,7 @@ function(_ICU_FIND) HINTS ${icu_roots} PATH_SUFFIXES ${icu_data_suffixes} DOC "ICU ${data} data file") - mark_as_advanced(cache_var) + mark_as_advanced("${cache_var}") set("${data_var}" "${${cache_var}}" PARENT_SCOPE) endforeach() From 84aaebf79fa25a4c3aaf04b5a9b2a8ae6355b280 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann <joerg.bornemann@qt.io> Date: Mon, 6 Sep 2021 15:09:33 +0200 Subject: [PATCH 1190/1519] Help: Mention that Qt6 is supported by AUTOGEN Co-Authored-By: Craig Scott <craig.scott@crascit.com> --- Help/prop_tgt/AUTOMOC.rst | 15 +++++++++------ Help/prop_tgt/AUTORCC.rst | 4 ++-- Help/prop_tgt/AUTOUIC.rst | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index 52d96e02fbf..ed8b2626b48 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -4,9 +4,9 @@ AUTOMOC Should the target be processed with auto-moc (for Qt projects). :prop_tgt:`AUTOMOC` is a boolean specifying whether CMake will handle the Qt -``moc`` preprocessor automatically, i.e. without having to use the -:module:`QT4_WRAP_CPP() <FindQt4>` or ``QT5_WRAP_CPP()`` macro. -Currently Qt4 and Qt5 are supported. +``moc`` preprocessor automatically, i.e. without having to use commands like +:module:`QT4_WRAP_CPP() <FindQt4>`, ``QT5_WRAP_CPP()``, etc. +Currently, Qt versions 4 to 6 are supported. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. @@ -148,10 +148,13 @@ Qt version detection :prop_tgt:`AUTOMOC` enabled targets need to know the Qt major and minor version they're working with. The major version usually is provided by the -``INTERFACE_QT_MAJOR_VERSION`` property of the ``Qt[45]Core`` library, +``INTERFACE_QT_MAJOR_VERSION`` property of the ``Qt[456]Core`` library, that the target links to. To find the minor version, CMake builds a list of available Qt versions from +- ``Qt6Core_VERSION_MAJOR`` and ``Qt6Core_VERSION_MINOR`` variables + (usually set by ``find_package(Qt6...)``) +- ``Qt6Core_VERSION_MAJOR`` and ``Qt6Core_VERSION_MINOR`` directory properties - ``Qt5Core_VERSION_MAJOR`` and ``Qt5Core_VERSION_MINOR`` variables (usually set by ``find_package(Qt5...)``) - ``Qt5Core_VERSION_MAJOR`` and ``Qt5Core_VERSION_MINOR`` directory properties @@ -167,13 +170,13 @@ version was found, an error is generated. If ``INTERFACE_QT_MAJOR_VERSION`` is not a valid number, the first entry in the list is taken. -A ``find_package(Qt[45]...)`` call sets the ``QT/Qt5Core_VERSION_MAJOR/MINOR`` +A ``find_package(Qt[456]...)`` call sets the ``QT/Qt[56]Core_VERSION_MAJOR/MINOR`` variables. If the call is in a different context than the :command:`add_executable` or :command:`add_library` call, e.g. in a function, then the version variables might not be available to the :prop_tgt:`AUTOMOC` enabled target. In that case the version variables can be forwarded from the -``find_package(Qt[45]...)`` calling context to the :command:`add_executable` +``find_package(Qt[456]...)`` calling context to the :command:`add_executable` or :command:`add_library` calling context as directory properties. The following Qt5 example demonstrates the procedure. diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst index 9a98f440ce9..0a0c2a11959 100644 --- a/Help/prop_tgt/AUTORCC.rst +++ b/Help/prop_tgt/AUTORCC.rst @@ -5,8 +5,8 @@ Should the target be processed with auto-rcc (for Qt projects). :prop_tgt:`AUTORCC` is a boolean specifying whether CMake will handle the Qt ``rcc`` code generator automatically, i.e. without having to use -the :module:`QT4_ADD_RESOURCES() <FindQt4>` or ``QT5_ADD_RESOURCES()`` -macro. Currently Qt4 and Qt5 are supported. +commands like :module:`QT4_ADD_RESOURCES() <FindQt4>`, ``QT5_ADD_RESOURCES()``, +etc. Currently, Qt versions 4 to 6 are supported. When this property is ``ON``, CMake will handle ``.qrc`` files added as target sources at build time and invoke ``rcc`` accordingly. diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst index cd24f5e5905..e0cea97a0a1 100644 --- a/Help/prop_tgt/AUTOUIC.rst +++ b/Help/prop_tgt/AUTOUIC.rst @@ -5,8 +5,8 @@ Should the target be processed with auto-uic (for Qt projects). :prop_tgt:`AUTOUIC` is a boolean specifying whether CMake will handle the Qt ``uic`` code generator automatically, i.e. without having to use -the :module:`QT4_WRAP_UI() <FindQt4>` or ``QT5_WRAP_UI()`` macro. Currently -Qt4 and Qt5 are supported. +commands like :module:`QT4_WRAP_UI() <FindQt4>`, ``QT5_WRAP_UI()``, etc. +Currently, Qt versions 4 to 6 are supported. This property is initialized by the value of the :variable:`CMAKE_AUTOUIC` variable if it is set when a target is created. From 51e7a78b0b6d4f62cb77aa4c17f3b3ba5636309f Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 7 Sep 2021 00:01:13 -0400 Subject: [PATCH 1191/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d4fb546110e..78f611b7380 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210906) +set(CMake_VERSION_PATCH 20210907) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From cf5ed709915bde5cef4a649ca2255833cc7afcd3 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 8 Sep 2021 00:01:19 -0400 Subject: [PATCH 1192/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 78f611b7380..38639a9e00b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210907) +set(CMake_VERSION_PATCH 20210908) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ce44c2cec306e6d7266ba3e5444ee36bce879e3d Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Sat, 28 Aug 2021 15:12:30 -0400 Subject: [PATCH 1193/1519] ctest_memcheck: generate `DynamicAnalysis-Test.xml` as well This is useful so that memcheck results also show up as test results on CDash. It will be submitted with the other `MemCheck` parts. Fixes: #22190 --- Help/command/ctest_submit.rst | 3 ++- .../dev/ctest_memcheck-generate-test.xml.rst | 6 ++++++ Source/CTest/cmCTestSubmitHandler.cxx | 1 + Source/CTest/cmCTestTestHandler.cxx | 15 +++++++++++++++ .../ctest_memcheck/ExpectedOutputs-check.cmake | 10 ++++++++++ .../ctest_memcheck/ExpectedOutputs-stderr.txt | 1 + .../ctest_memcheck/ExpectedOutputs-stdout.txt | 2 ++ Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake | 13 +++++++++++++ 8 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/ctest_memcheck-generate-test.xml.rst create mode 100644 Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake create mode 100644 Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt create mode 100644 Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst index e6d277f59da..d66182540a9 100644 --- a/Help/command/ctest_submit.rst +++ b/Help/command/ctest_submit.rst @@ -30,7 +30,8 @@ The options are: Build = ctest_build results, in Build.xml Test = ctest_test results, in Test.xml Coverage = ctest_coverage results, in Coverage.xml - MemCheck = ctest_memcheck results, in DynamicAnalysis.xml + MemCheck = ctest_memcheck results, in DynamicAnalysis.xml and + DynamicAnalysis-Test.xml Notes = Files listed by CTEST_NOTES_FILES, in Notes.xml ExtraFiles = Files listed by CTEST_EXTRA_SUBMIT_FILES Upload = Files prepared for upload by ctest_upload(), in Upload.xml diff --git a/Help/release/dev/ctest_memcheck-generate-test.xml.rst b/Help/release/dev/ctest_memcheck-generate-test.xml.rst new file mode 100644 index 00000000000..fac02d8b802 --- /dev/null +++ b/Help/release/dev/ctest_memcheck-generate-test.xml.rst @@ -0,0 +1,6 @@ +ctest_memcheck-generate-test.xml +-------------------------------- + +* The :command:`ctest_memcheck` command now also generates a + `DynamicAnalysis-Test.xml` file which may be used to submit test results to + CDash. diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 5b54573f34d..bf938e4900e 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -804,6 +804,7 @@ int cmCTestSubmitHandler::ProcessHandler() } } this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml"); + this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis-Test.xml"); this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml"); this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml"); this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml"); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 1157d1008a0..00c1443d04c 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -705,6 +705,21 @@ bool cmCTestTestHandler::GenerateXML() this->GenerateCTestXML(xml); } + if (this->MemCheck) { + cmGeneratedFileStream xmlfile; + if (!this->StartResultingXML(cmCTest::PartTest, "DynamicAnalysis-Test", + xmlfile)) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create testing XML file" << std::endl); + this->LogFile = nullptr; + return false; + } + cmXMLWriter xml(xmlfile); + // Explicitly call this class' `GenerateCTestXML` method to make `Test.xml` + // as well. + this->cmCTestTestHandler::GenerateCTestXML(xml); + } + return true; } diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake new file mode 100644 index 00000000000..9d2a059a490 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake @@ -0,0 +1,10 @@ +function (find_xml_file name) + file(GLOB test_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${name}.xml") + if (NOT test_xml_file) + message(FATAL_ERROR + "${name}.xml not created.") + endif () +endfunction () + +find_xml_file(DynamicAnalysis) +find_xml_file(DynamicAnalysis-Test) diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt new file mode 100644 index 00000000000..e1fc77a222c --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt @@ -0,0 +1 @@ +Cannot find memory tester output file: .*/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-build/Testing/Temporary/MemoryChecker.1.log\.\* diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt new file mode 100644 index 00000000000..b3473bfd953 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt @@ -0,0 +1,2 @@ +Memory checking results: +left shift of negative value -256 - 1 diff --git a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake index 6e0a91c8596..cb8f6963c71 100644 --- a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake @@ -94,6 +94,19 @@ run_mc_test(DummyUndefinedBehaviorSanitizer "" -DMEMCHECK_TYPE=UndefinedBehavior unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) +#----------------------------------------------------------------------------- +# add output test +set(CTEST_EXTRA_CODE +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1\") +") +set(CMAKELISTS_EXTRA_CODE +"add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\" +-P \"${RunCMake_SOURCE_DIR}/testUndefinedBehaviorSanitizer.cmake\") +") +run_mc_test(ExpectedOutputs "" -DMEMCHECK_TYPE=UndefinedBehaviorSanitizer) +unset(CMAKELISTS_EXTRA_CODE) +unset(CTEST_EXTRA_CODE) + #----------------------------------------------------------------------------- set(CTEST_EXTRA_CODE "string(REPLACE \" \" \"\\\\ \" PRE_POST_COMMAND \"\${CTEST_MEMORYCHECK_COMMAND}\") From ce6820fe215b8257bff7dc30fe5c57d8210adb09 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 9 Sep 2021 00:01:11 -0400 Subject: [PATCH 1194/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 38639a9e00b..ea70d2a62bb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210908) +set(CMake_VERSION_PATCH 20210909) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3bf013632d26241672897e4aab10823d219f025c Mon Sep 17 00:00:00 2001 From: Steven Boswell <ulatekh@yahoo.com> Date: Thu, 2 Sep 2021 17:09:37 -0700 Subject: [PATCH 1195/1519] cmVisualStudio10TargetGenerator: Factor out helper to write VS_SETTINGS --- Source/cmVisualStudio10TargetGenerator.cxx | 71 ++++++++++++---------- Source/cmVisualStudio10TargetGenerator.h | 11 ++-- 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 94072286d08..c7f608bdc14 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1864,8 +1864,8 @@ bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs( return true; } -void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, - cmSourceFile const* sf) +void cmVisualStudio10TargetGenerator::WriteExtraSource( + Elem& e1, cmSourceFile const* sf, ConfigToSettings& toolSettings) { bool toolHasSettings = false; const char* tool = "None"; @@ -1876,10 +1876,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, std::string copyToOutDir; std::string includeInVsix; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - ConfigToSettings toolSettings; - for (const auto& config : this->Configurations) { - toolSettings[config]; - } if (this->ProjectType == csproj && !this->InSourceBuild) { toolHasSettings = true; @@ -2047,10 +2043,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } - if (cmProp p = sf->GetProperty("VS_SETTINGS")) { - ParseSettingsProperty(*p, toolSettings); - } - if (!toolSettings.empty()) { toolHasSettings = true; } @@ -2060,27 +2052,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, if (toolHasSettings) { e2.SetHasElements(); - std::vector<std::string> writtenSettings; - for (const auto& configSettings : toolSettings) { - for (const auto& setting : configSettings.second) { - - if (std::find(writtenSettings.begin(), writtenSettings.end(), - setting.first) != writtenSettings.end()) { - continue; - } - - if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) { - e2.Element(setting.first, setting.second); - writtenSettings.push_back(setting.first); - } else { - e2.WritePlatformConfigTag(setting.first, - "'$(Configuration)|$(Platform)'=='" + - configSettings.first + "|" + - this->Platform + "'", - setting.second); - } - } - } + this->FinishWritingSource(e2, toolSettings); if (!deployContent.empty()) { cmGeneratorExpression ge; @@ -2217,6 +2189,15 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) // Skip explicit reference to CMakeLists.txt source. continue; } + + ConfigToSettings toolSettings; + for (const auto& config : this->Configurations) { + toolSettings[config]; + } + if (cmProp p = si.Source->GetProperty("VS_SETTINGS")) { + ParseSettingsProperty(*p, toolSettings); + } + const char* tool = nullptr; switch (si.Kind) { case cmGeneratorTarget::SourceKindAppManifest: @@ -2244,7 +2225,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } break; case cmGeneratorTarget::SourceKindExtra: - this->WriteExtraSource(e1, si.Source); + this->WriteExtraSource(e1, si.Source, toolSettings); break; case cmGeneratorTarget::SourceKindHeader: this->WriteHeaderSource(e1, si.Source); @@ -2365,6 +2346,32 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } } +void cmVisualStudio10TargetGenerator::FinishWritingSource( + Elem& e2, ConfigToSettings const& toolSettings) +{ + std::vector<std::string> writtenSettings; + for (const auto& configSettings : toolSettings) { + for (const auto& setting : configSettings.second) { + + if (std::find(writtenSettings.begin(), writtenSettings.end(), + setting.first) != writtenSettings.end()) { + continue; + } + + if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) { + e2.Element(setting.first, setting.second); + writtenSettings.push_back(setting.first); + } else { + e2.WritePlatformConfigTag(setting.first, + "'$(Configuration)|$(Platform)'=='" + + configSettings.first + "|" + + this->Platform + "'", + setting.second); + } + } + } +} + void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( Elem& e2, cmSourceFile const* source) { diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 55c5444f1a8..4de134f27b9 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -58,6 +58,10 @@ class cmVisualStudio10TargetGenerator struct Elem; struct OptionsHelper; + using ConfigToSettings = + std::unordered_map<std::string, + std::unordered_map<std::string, std::string>>; + std::string ConvertPath(std::string const& path, bool forceRelative); std::string CalcCondition(const std::string& config) const; void WriteProjectConfigurations(Elem& e0); @@ -67,11 +71,13 @@ class cmVisualStudio10TargetGenerator void WriteMSToolConfigurationValuesManaged(Elem& e1, std::string const& config); void WriteHeaderSource(Elem& e1, cmSourceFile const* sf); - void WriteExtraSource(Elem& e1, cmSourceFile const* sf); + void WriteExtraSource(Elem& e1, cmSourceFile const* sf, + ConfigToSettings& toolSettings); void WriteNsightTegraConfigurationValues(Elem& e1, std::string const& config); void WriteAndroidConfigurationValues(Elem& e1, std::string const& config); void WriteSource(Elem& e2, cmSourceFile const* sf); + void FinishWritingSource(Elem& e2, ConfigToSettings const& toolSettings); void WriteExcludeFromBuild(Elem& e2, std::vector<size_t> const& exclude_configs); void WriteAllSources(Elem& e0); @@ -252,9 +258,6 @@ class cmVisualStudio10TargetGenerator void ClassifyAllConfigSources(); void ClassifyAllConfigSource(cmGeneratorTarget::AllConfigSource const& acs); - using ConfigToSettings = - std::unordered_map<std::string, - std::unordered_map<std::string, std::string>>; std::unordered_map<std::string, ConfigToSettings> ParsedToolTargetSettings; bool PropertyIsSameInAllConfigs(const ConfigToSettings& toolSettings, const std::string& propName); From f21158cdfe8a1938401f86b85b1ae1239372115b Mon Sep 17 00:00:00 2001 From: Steven Boswell <ulatekh@yahoo.com> Date: Thu, 2 Sep 2021 17:12:44 -0700 Subject: [PATCH 1196/1519] VS: Honor VS_SETTINGS source file property on all sources Extend the feature added by commit 2ce42f281f (VS: Add VS_SETTINGS source file property, 2020-03-18, v3.18.0-rc1~449^2~3) to support all source file types. --- Help/prop_sf/VS_SETTINGS.rst | 7 ++++++- Help/release/dev/vs_settings.rst | 5 +++++ Source/cmVisualStudio10TargetGenerator.cxx | 9 ++++++--- Source/cmVisualStudio10TargetGenerator.h | 3 ++- Tests/RunCMake/VS10Project/VsSettings-check.cmake | 15 ++++++++++++--- Tests/RunCMake/VS10Project/VsSettings.cmake | 2 ++ 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 Help/release/dev/vs_settings.rst diff --git a/Help/prop_sf/VS_SETTINGS.rst b/Help/prop_sf/VS_SETTINGS.rst index 322f5a6d7f1..871e36e855d 100644 --- a/Help/prop_sf/VS_SETTINGS.rst +++ b/Help/prop_sf/VS_SETTINGS.rst @@ -3,7 +3,12 @@ VS_SETTINGS .. versionadded:: 3.18 -Set any item metadata on a non-built file. +Set any item metadata on a file. + +.. versionadded:: 3.22 + + This property is honored for all source file types. + Previously it worked only for non-built files. Takes a list of ``Key=Value`` pairs. Tells the Visual Studio generator to set ``Key`` to ``Value`` as item metadata on the file. diff --git a/Help/release/dev/vs_settings.rst b/Help/release/dev/vs_settings.rst new file mode 100644 index 00000000000..64f3ced3ed7 --- /dev/null +++ b/Help/release/dev/vs_settings.rst @@ -0,0 +1,5 @@ +vs_settings +----------- + +* The :prop_sf:`VS_SETTINGS` source file property is now supported for + all source file types. Previously it worked only for non-built sources. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index c7f608bdc14..867c5e54cd5 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1796,8 +1796,8 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( } } -void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, - cmSourceFile const* sf) +void cmVisualStudio10TargetGenerator::WriteHeaderSource( + Elem& e1, cmSourceFile const* sf, ConfigToSettings const& toolSettings) { std::string const& fileName = sf->GetFullPath(); Elem e2(e1, "ClInclude"); @@ -1808,6 +1808,7 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, e2.Element("DependentUpon", fileName.substr(0, fileName.find_last_of("."))); } + this->FinishWritingSource(e2, toolSettings); } void cmVisualStudio10TargetGenerator::ParseSettingsProperty( @@ -2228,7 +2229,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) this->WriteExtraSource(e1, si.Source, toolSettings); break; case cmGeneratorTarget::SourceKindHeader: - this->WriteHeaderSource(e1, si.Source); + this->WriteHeaderSource(e1, si.Source, toolSettings); break; case cmGeneratorTarget::SourceKindIDL: tool = "Midl"; @@ -2338,6 +2339,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (!isCSharp && !exclude_configs.empty()) { this->WriteExcludeFromBuild(e2, exclude_configs); } + + this->FinishWritingSource(e2, toolSettings); } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 4de134f27b9..a5ce5e58faa 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -70,7 +70,8 @@ class cmVisualStudio10TargetGenerator void WriteCEDebugProjectConfigurationValues(Elem& e0); void WriteMSToolConfigurationValuesManaged(Elem& e1, std::string const& config); - void WriteHeaderSource(Elem& e1, cmSourceFile const* sf); + void WriteHeaderSource(Elem& e1, cmSourceFile const* sf, + ConfigToSettings const& toolSettings); void WriteExtraSource(Elem& e1, cmSourceFile const* sf, ConfigToSettings& toolSettings); void WriteNsightTegraConfigurationValues(Elem& e1, diff --git a/Tests/RunCMake/VS10Project/VsSettings-check.cmake b/Tests/RunCMake/VS10Project/VsSettings-check.cmake index 0f8b26c281b..13cc8e25ad2 100644 --- a/Tests/RunCMake/VS10Project/VsSettings-check.cmake +++ b/Tests/RunCMake/VS10Project/VsSettings-check.cmake @@ -4,20 +4,29 @@ macro(ensure_props_set projectFile) return() endif() - set(SettingFound FALSE) + set(Setting1Found FALSE) + set(Setting2Found FALSE) file(STRINGS "${projectFile}" lines) foreach(line IN LISTS lines) if(line MATCHES "<SourceProperty1.*Debug.*>SourceProperty1Value</SourceProperty1>") message("SourceProperty1 setting found") - set(SettingFound TRUE) + set(Setting1Found TRUE) + endif() + if(line MATCHES "<SourceProperty2.*Debug.*>SourceProperty2Value</SourceProperty2>") + message("SourceProperty2 setting found") + set(Setting2Found TRUE) endif() endforeach() - if (NOT SettingFound) + if (NOT Setting1Found) set(RunCMake_TEST_FAILED "SourceProperty1 setting was not found") return() endif() + if (NOT Setting2Found) + set(RunCMake_TEST_FAILED "SourceProperty2 setting was not found") + return() + endif() endmacro() ensure_props_set("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") diff --git a/Tests/RunCMake/VS10Project/VsSettings.cmake b/Tests/RunCMake/VS10Project/VsSettings.cmake index a4b321b65a2..3a046f1647f 100644 --- a/Tests/RunCMake/VS10Project/VsSettings.cmake +++ b/Tests/RunCMake/VS10Project/VsSettings.cmake @@ -3,3 +3,5 @@ enable_language(CXX) add_library(foo foo.cpp shader.hlsl) set_property(SOURCE shader.hlsl PROPERTY VS_SETTINGS "$<$<CONFIG:DEBUG>:SourceProperty1=SourceProperty1Value>") +set_property(SOURCE foo.cpp PROPERTY VS_SETTINGS + "$<$<CONFIG:DEBUG>:SourceProperty2=SourceProperty2Value>") From b284a21fee0907effe08a4314ffa725aa0c7c86e Mon Sep 17 00:00:00 2001 From: Steven Boswell <ulatekh@yahoo.com> Date: Fri, 3 Sep 2021 14:06:27 -0700 Subject: [PATCH 1197/1519] VS: Add missing label in C# project-build events Fixes: #21440 --- Source/cmLocalVisualStudio7Generator.cxx | 4 ++-- Source/cmLocalVisualStudioGenerator.cxx | 11 ++++++++++- Source/cmLocalVisualStudioGenerator.h | 6 ++++++ Source/cmVisualStudio10TargetGenerator.cxx | 10 ++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 151470b4e5f..06d738f3415 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -566,7 +566,7 @@ class cmLocalVisualStudio7Generator::EventWriter } else { this->Stream << this->LG->EscapeForXML("\n"); } - std::string script = this->LG->ConstructScript(ccg); + std::string script = this->LG->ConstructScript(ccg, unmanaged); this->Stream << this->LG->EscapeForXML(script); } @@ -1779,7 +1779,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule( } std::string comment = this->ConstructComment(ccg); - std::string script = this->ConstructScript(ccg); + std::string script = this->ConstructScript(ccg, unmanaged); if (this->FortranProject) { cmSystemTools::ReplaceString(script, "$(Configuration)", config); } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 46f9d315f1a..acddfe16730 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -124,7 +124,8 @@ const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const } std::string cmLocalVisualStudioGenerator::ConstructScript( - cmCustomCommandGenerator const& ccg, const std::string& newline_text) + cmCustomCommandGenerator const& ccg, IsManaged isManaged, + const std::string& newline_text) { bool useLocal = this->CustomCommandUseLocal(); std::string workingDirectory = ccg.GetWorkingDirectory(); @@ -236,6 +237,14 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( script += newline; script += "if %errorlevel% neq 0 goto "; script += this->GetReportErrorLabel(); + if (isManaged == managed) { + // These aren't generated by default for C# projects. + script += newline; + script += this->GetReportErrorLabel(); + script += newline; + script += "exit /b 0"; + script += newline; + } } return script; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 91fb6b06191..0e7f63ff596 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -31,7 +31,13 @@ class cmLocalVisualStudioGenerator : public cmLocalGenerator virtual ~cmLocalVisualStudioGenerator(); /** Construct a script from the given list of command lines. */ + enum IsManaged + { + unmanaged, + managed + }; std::string ConstructScript(cmCustomCommandGenerator const& ccg, + IsManaged isManaged, const std::string& newline = "\n"); /** Label to which to jump in a batch file after a failed step in a diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 94072286d08..8a2acf3e8b4 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1465,7 +1465,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( cmCustomCommandGenerator ccg(command, c, lg, true); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); - std::string script = lg->ConstructScript(ccg); + cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed) + ? cmLocalVisualStudioGenerator::managed + : cmLocalVisualStudioGenerator::unmanaged; + std::string script = lg->ConstructScript(ccg, isManaged); bool symbolic = false; // input files for custom command std::stringstream additional_inputs; @@ -4205,7 +4208,10 @@ void cmVisualStudio10TargetGenerator::WriteEvent( comment += lg->ConstructComment(ccg); script += pre; pre = "\n"; - script += lg->ConstructScript(ccg); + cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed) + ? cmLocalVisualStudioGenerator::managed + : cmLocalVisualStudioGenerator::unmanaged; + script += lg->ConstructScript(ccg, isManaged); stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8(); } From c9c79dde41048bf6276bc56674cfefa59ca92c9e Mon Sep 17 00:00:00 2001 From: Thomas Bernard <thomas@famillebernardgouriou.fr> Date: Wed, 25 Aug 2021 22:38:25 +0200 Subject: [PATCH 1198/1519] Clang: Add MSVC frontend detection for the ASM compiler Fixes: #22495 --- Modules/CMakeDetermineASMCompiler.cmake | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index e8b9db797f3..a1814b7dd81 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -125,6 +125,7 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) include(CMakeDetermineCompilerId) set(userflags) CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}") + set(_variant "") if("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xIAR") # primary necessary to detect architecture, so the right archiver and linker can be picked # eg. "IAR Assembler V8.10.1.12857/W32 for ARM" or "IAR Assembler V4.11.1.4666 for Renesas RX" @@ -137,6 +138,19 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) if(_all_compileid_matches) list(GET _all_compileid_matches "-1" CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID) endif() + elseif("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xClang") + # Test whether an MSVC-like command-line option works. + execute_process(COMMAND ${CMAKE_ASM${ASM_DIALECT}_COMPILER} -? + OUTPUT_VARIABLE _clang_output + ERROR_VARIABLE _clang_output + RESULT_VARIABLE _clang_result) + if(_clang_result EQUAL 0) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT "MSVC") + set(CMAKE_ASM${ASM_DIALECT}_SIMULATE_ID MSVC) + else() + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT "GNU") + endif() + set(_variant " with ${CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT}-like command-line") endif() _cmake_find_compiler_sysroot(ASM${ASM_DIALECT}) @@ -144,6 +158,8 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) unset(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_OUTPUT) unset(_all_compileid_matches) unset(_compileid) + unset(_clang_result) + unset(_clang_output) endif() if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) @@ -157,9 +173,10 @@ if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) else() set(_archid "") endif() - message(STATUS "The ASM${ASM_DIALECT} compiler identification is ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}${_archid}${_version}") + message(STATUS "The ASM${ASM_DIALECT} compiler identification is ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}${_archid}${_version}${_variant}") unset(_archid) unset(_version) + unset(_variant) else() message(STATUS "The ASM${ASM_DIALECT} compiler identification is unknown") endif() From 563139e5e96f9eacbbd835212323da73db719db4 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 8 Sep 2021 12:25:24 -0400 Subject: [PATCH 1199/1519] Help: find_package document version only supports numeric components --- Help/command/find_package.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 490a5c74591..83887096baa 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -55,12 +55,13 @@ The ``[version]`` argument requests a version with which the package found should be compatible. There are two possible forms in which it may be specified: - * A single version with the format ``major[.minor[.patch[.tweak]]]``. + * A single version with the format ``major[.minor[.patch[.tweak]]]``, where + each component is a numeric value. * A version range with the format ``versionMin...[<]versionMax`` where - ``versionMin`` and ``versionMax`` have the same format as the single - version. By default, both end points are included. By specifying ``<``, - the upper end point will be excluded. Version ranges are only supported - with CMake 3.19 or later. + ``versionMin`` and ``versionMax`` have the same format and constraints + on components being integers as the single version. By default, both end + points are included. By specifying ``<``, the upper end point will be + excluded. Version ranges are only supported with CMake 3.19 or later. The ``EXACT`` option requests that the version be matched exactly. This option is incompatible with the specification of a version range. From 8defe3380e4656e4239877a0cd89607c36bf0ac7 Mon Sep 17 00:00:00 2001 From: Pablo Romero <pablorcum@gmail.com> Date: Tue, 7 Sep 2021 12:10:08 -0400 Subject: [PATCH 1200/1519] CMakeFindPackageMode: Honor CMAKE_SYSROOT to detect lib64 platforms Add `CMAKE_SYSROOT` to check the full path on host OS. In a non-crosscompiling use case, the call to `CMAKE_SYSROOT` is empty. Fixes: #22608 --- Modules/CMakeFindPackageMode.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake index 815dfc90d83..726e2a2921d 100644 --- a/Modules/CMakeFindPackageMode.cmake +++ b/Modules/CMakeFindPackageMode.cmake @@ -78,7 +78,7 @@ if(UNIX) # from the outside if(NOT CMAKE_SIZEOF_VOID_P) set(CMAKE_SIZEOF_VOID_P 4) - if(EXISTS /usr/lib64) + if(EXISTS ${CMAKE_SYSROOT}/usr/lib64) set(CMAKE_SIZEOF_VOID_P 8) else() # use the file utility to check whether itself is 64 bit: From d9f8e39357b8d7244172223f76862eea88fbc374 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 9 Sep 2021 16:00:02 -0400 Subject: [PATCH 1201/1519] jsoncpp: Update script to get jsoncpp 1.9.4 --- Utilities/Scripts/update-jsoncpp.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-jsoncpp.bash b/Utilities/Scripts/update-jsoncpp.bash index f8fe5446202..5ed00e7cf16 100755 --- a/Utilities/Scripts/update-jsoncpp.bash +++ b/Utilities/Scripts/update-jsoncpp.bash @@ -8,7 +8,7 @@ readonly name="jsoncpp" readonly ownership="JsonCpp Upstream <kwrobot@kitware.com>" readonly subtree="Utilities/cmjsoncpp" readonly repo="https://github.com/open-source-parsers/jsoncpp.git" -readonly tag="1.8.2" +readonly tag="1.9.4" readonly shortlog=false readonly paths=" LICENSE From 0b9765051855ece984fa83154d063b7cc7b62c1d Mon Sep 17 00:00:00 2001 From: JsonCpp Upstream <kwrobot@kitware.com> Date: Fri, 25 Sep 2020 19:19:16 -0700 Subject: [PATCH 1202/1519] jsoncpp 2020-09-25 (9059f5ca) Code extracted from: https://github.com/open-source-parsers/jsoncpp.git at commit 9059f5cad030ba11d37818847443a53918c327b1 (1.9.4). --- include/json/allocator.h | 141 ++- include/json/assertions.h | 43 +- include/json/config.h | 215 ++-- include/json/forwards.h | 10 +- include/json/json.h | 6 +- include/json/{features.h => json_features.h} | 14 +- include/json/reader.h | 390 ++++--- include/json/value.h | 608 +++++----- include/json/version.h | 26 +- include/json/writer.h | 250 +++-- src/lib_json/json_reader.cpp | 945 ++++++++-------- src/lib_json/json_tool.h | 55 +- src/lib_json/json_value.cpp | 1060 +++++++++--------- src/lib_json/json_valueiterator.inl | 39 +- src/lib_json/json_writer.cpp | 793 ++++++------- 15 files changed, 2291 insertions(+), 2304 deletions(-) rename include/json/{features.h => json_features.h} (86%) diff --git a/include/json/allocator.h b/include/json/allocator.h index 9c7e573aef6..0f5c224b9d7 100644 --- a/include/json/allocator.h +++ b/include/json/allocator.h @@ -3,8 +3,8 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED -#define CPPTL_JSON_ALLOCATOR_H_INCLUDED +#ifndef JSON_ALLOCATOR_H_INCLUDED +#define JSON_ALLOCATOR_H_INCLUDED #include <cstring> #include <memory> @@ -12,87 +12,78 @@ #pragma pack(push, 8) namespace Json { -template<typename T> -class SecureAllocator { - public: - // Type definitions - using value_type = T; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - /** - * Allocate memory for N items using the standard allocator. - */ - pointer allocate(size_type n) { - // allocate using "global operator new" - return static_cast<pointer>(::operator new(n * sizeof(T))); - } - - /** - * Release memory which was allocated for N items at pointer P. - * - * The memory block is filled with zeroes before being released. - * The pointer argument is tagged as "volatile" to prevent the - * compiler optimizing out this critical step. - */ - void deallocate(volatile pointer p, size_type n) { - std::memset(p, 0, n * sizeof(T)); - // free using "global operator delete" - ::operator delete(p); - } - - /** - * Construct an item in-place at pointer P. - */ - template<typename... Args> - void construct(pointer p, Args&&... args) { - // construct using "placement new" and "perfect forwarding" - ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); - } - - size_type max_size() const { - return size_t(-1) / sizeof(T); - } - - pointer address( reference x ) const { - return std::addressof(x); - } - - const_pointer address( const_reference x ) const { - return std::addressof(x); - } - - /** - * Destroy an item in-place at pointer P. - */ - void destroy(pointer p) { - // destroy using "explicit destructor" - p->~T(); - } - - // Boilerplate - SecureAllocator() {} - template<typename U> SecureAllocator(const SecureAllocator<U>&) {} - template<typename U> struct rebind { using other = SecureAllocator<U>; }; +template <typename T> class SecureAllocator { +public: + // Type definitions + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + /** + * Allocate memory for N items using the standard allocator. + */ + pointer allocate(size_type n) { + // allocate using "global operator new" + return static_cast<pointer>(::operator new(n * sizeof(T))); + } + + /** + * Release memory which was allocated for N items at pointer P. + * + * The memory block is filled with zeroes before being released. + * The pointer argument is tagged as "volatile" to prevent the + * compiler optimizing out this critical step. + */ + void deallocate(volatile pointer p, size_type n) { + std::memset(p, 0, n * sizeof(T)); + // free using "global operator delete" + ::operator delete(p); + } + + /** + * Construct an item in-place at pointer P. + */ + template <typename... Args> void construct(pointer p, Args&&... args) { + // construct using "placement new" and "perfect forwarding" + ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); + } + + size_type max_size() const { return size_t(-1) / sizeof(T); } + + pointer address(reference x) const { return std::addressof(x); } + + const_pointer address(const_reference x) const { return std::addressof(x); } + + /** + * Destroy an item in-place at pointer P. + */ + void destroy(pointer p) { + // destroy using "explicit destructor" + p->~T(); + } + + // Boilerplate + SecureAllocator() {} + template <typename U> SecureAllocator(const SecureAllocator<U>&) {} + template <typename U> struct rebind { using other = SecureAllocator<U>; }; }; - -template<typename T, typename U> +template <typename T, typename U> bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) { - return true; + return true; } -template<typename T, typename U> +template <typename T, typename U> bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) { - return false; + return false; } -} //namespace Json +} // namespace Json #pragma pack(pop) -#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED +#endif // JSON_ALLOCATOR_H_INCLUDED diff --git a/include/json/assertions.h b/include/json/assertions.h index 1cca28d959b..666fa7f542c 100644 --- a/include/json/assertions.h +++ b/include/json/assertions.h @@ -3,10 +3,10 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED -#define CPPTL_JSON_ASSERTIONS_H_INCLUDED +#ifndef JSON_ASSERTIONS_H_INCLUDED +#define JSON_ASSERTIONS_H_INCLUDED -#include <stdlib.h> +#include <cstdlib> #include <sstream> #if !defined(JSON_IS_AMALGAMATION) @@ -20,35 +20,42 @@ #if JSON_USE_EXCEPTION // @todo <= add detail about condition in exception -# define JSON_ASSERT(condition) \ - {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} - -# define JSON_FAIL_MESSAGE(message) \ - { \ - JSONCPP_OSTRINGSTREAM oss; oss << message; \ +#define JSON_ASSERT(condition) \ + do { \ + if (!(condition)) { \ + Json::throwLogicError("assert json failed"); \ + } \ + } while (0) + +#define JSON_FAIL_MESSAGE(message) \ + do { \ + OStringStream oss; \ + oss << message; \ Json::throwLogicError(oss.str()); \ abort(); \ - } + } while (0) #else // JSON_USE_EXCEPTION -# define JSON_ASSERT(condition) assert(condition) +#define JSON_ASSERT(condition) assert(condition) // The call to assert() will show the failure message in debug builds. In // release builds we abort, for a core-dump or debugger. -# define JSON_FAIL_MESSAGE(message) \ +#define JSON_FAIL_MESSAGE(message) \ { \ - JSONCPP_OSTRINGSTREAM oss; oss << message; \ + OStringStream oss; \ + oss << message; \ assert(false && oss.str().c_str()); \ abort(); \ } - #endif #define JSON_ASSERT_MESSAGE(condition, message) \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message); \ - } + do { \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } \ + } while (0) -#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED +#endif // JSON_ASSERTIONS_H_INCLUDED diff --git a/include/json/config.h b/include/json/config.h index c83e78a3f21..6359273a222 100644 --- a/include/json/config.h +++ b/include/json/config.h @@ -5,19 +5,14 @@ #ifndef JSON_CONFIG_H_INCLUDED #define JSON_CONFIG_H_INCLUDED -#include <stddef.h> -#include <string> //typedef String -#include <stdint.h> //typedef int64_t, uint64_t - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 +#include <cstddef> +#include <cstdint> +#include <istream> +#include <memory> +#include <ostream> +#include <sstream> +#include <string> +#include <type_traits> // If non-zero, the library uses exceptions to report bad input instead of C // assertion macros. The default is to use exceptions. @@ -25,163 +20,131 @@ #define JSON_USE_EXCEPTION 1 #endif -/// If defined, indicates that the source file is amalgated +// Temporary, tracked for removal with issue #982. +#ifndef JSON_USE_NULLREF +#define JSON_USE_NULLREF 1 +#endif + +/// If defined, indicates that the source file is amalgamated /// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. +/// Remarks: it is automatically defined in the generated amalgamated header. // #define JSON_IS_AMALGAMATION -#ifdef JSON_IN_CPPTL -#include <cpptl/config.h> -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) +// Export macros for DLL visibility +#if defined(JSON_DLL_BUILD) #if defined(_MSC_VER) || defined(__MINGW32__) #define JSON_API __declspec(dllexport) #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#elif defined(__GNUC__) || defined(__clang__) +#define JSON_API __attribute__((visibility("default"))) #endif // if defined(_MSC_VER) + #elif defined(JSON_DLL) #if defined(_MSC_VER) || defined(__MINGW32__) #define JSON_API __declspec(dllimport) #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL +#endif // ifdef JSON_DLL_BUILD + #if !defined(JSON_API) #define JSON_API #endif -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 +#if defined(_MSC_VER) && _MSC_VER < 1800 +#error \ + "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" +#endif -#if defined(_MSC_VER) // MSVC -# if _MSC_VER <= 1200 // MSVC 6 - // Microsoft Visual Studio 6 only support conversion from __int64 to double - // (no conversion from unsigned __int64). -# define JSON_USE_INT64_DOUBLE_CONVERSION 1 - // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' - // characters in the debug information) - // All projects I've ever seen with VS6 were using this globally (not bothering - // with pragma push/pop). -# pragma warning(disable : 4786) -# endif // MSVC 6 - -# if _MSC_VER >= 1500 // MSVC 2008 - /// Indicates that the following function is deprecated. -# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -# endif - -#endif // defined(_MSC_VER) - -// In c++11 the override keyword allows you to explicity define that a function -// is intended to override the base-class version. This makes the code more -// managable and fixes a set of common hard-to-find bugs. -#if __cplusplus >= 201103L -# define JSONCPP_OVERRIDE override -# define JSONCPP_NOEXCEPT noexcept -#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 -# define JSONCPP_OVERRIDE override -# define JSONCPP_NOEXCEPT throw() -#elif defined(_MSC_VER) && _MSC_VER >= 1900 -# define JSONCPP_OVERRIDE override -# define JSONCPP_NOEXCEPT noexcept +#if defined(_MSC_VER) && _MSC_VER < 1900 +// As recommended at +// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 +extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...); +#define jsoncpp_snprintf msvc_pre1900_c99_snprintf #else -# define JSONCPP_OVERRIDE -# define JSONCPP_NOEXCEPT throw() +#define jsoncpp_snprintf std::snprintf #endif -#ifndef JSON_HAS_RVALUE_REFERENCES +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 -#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // MSVC >= 2010 +// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. +// C++11 should be used directly in JSONCPP. +#define JSONCPP_OVERRIDE override #ifdef __clang__ -#if __has_feature(cxx_rvalue_references) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // has_feature - -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // GXX_EXPERIMENTAL - -#endif // __clang__ || __GNUC__ - -#endif // not defined JSON_HAS_RVALUE_REFERENCES - -#ifndef JSON_HAS_RVALUE_REFERENCES -#define JSON_HAS_RVALUE_REFERENCES 0 +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) #endif - -#ifdef __clang__ -# if __has_extension(attribute_deprecated_with_message) -# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -# endif -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) -# endif // GNUC version -#endif // __clang__ || __GNUC__ +#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates + // MSVC) +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif // __clang__ || __GNUC__ || _MSC_VER #if !defined(JSONCPP_DEPRECATED) #define JSONCPP_DEPRECATED(message) #endif // if !defined(JSONCPP_DEPRECATED) -#if __GNUC__ >= 6 -# define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 #endif #if !defined(JSON_IS_AMALGAMATION) -# include "version.h" - -# if JSONCPP_USING_SECURE_MEMORY -# include "allocator.h" //typedef Allocator -# endif +#include "allocator.h" +#include "version.h" #endif // if !defined(JSON_IS_AMALGAMATION) namespace Json { -typedef int Int; -typedef unsigned int UInt; +using Int = int; +using UInt = unsigned int; #if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; +using LargestInt = int; +using LargestUInt = unsigned int; #undef JSON_HAS_INT64 #else // if defined(JSON_NO_INT64) // For Microsoft Visual use specific types as long long is not supported #if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; +using Int64 = __int64; +using UInt64 = unsigned __int64; #else // if defined(_MSC_VER) // Other platforms, use long long -typedef int64_t Int64; -typedef uint64_t UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; +using Int64 = int64_t; +using UInt64 = uint64_t; +#endif // if defined(_MSC_VER) +using LargestInt = Int64; +using LargestUInt = UInt64; #define JSON_HAS_INT64 #endif // if defined(JSON_NO_INT64) -#if JSONCPP_USING_SECURE_MEMORY -#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> > -#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> > -#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>> -#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> > -#define JSONCPP_ISTREAM std::istream -#else -#define JSONCPP_STRING std::string -#define JSONCPP_OSTRINGSTREAM std::ostringstream -#define JSONCPP_OSTREAM std::ostream -#define JSONCPP_ISTRINGSTREAM std::istringstream -#define JSONCPP_ISTREAM std::istream -#endif // if JSONCPP_USING_SECURE_MEMORY -} // end namespace Json + +template <typename T> +using Allocator = + typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>, + std::allocator<T>>::type; +using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>; +using IStringStream = + std::basic_istringstream<String::value_type, String::traits_type, + String::allocator_type>; +using OStringStream = + std::basic_ostringstream<String::value_type, String::traits_type, + String::allocator_type>; +using IStream = std::istream; +using OStream = std::ostream; +} // namespace Json + +// Legacy names (formerly macros). +using JSONCPP_STRING = Json::String; +using JSONCPP_ISTRINGSTREAM = Json::IStringStream; +using JSONCPP_OSTRINGSTREAM = Json::OStringStream; +using JSONCPP_ISTREAM = Json::IStream; +using JSONCPP_OSTREAM = Json::OStream; #endif // JSON_CONFIG_H_INCLUDED diff --git a/include/json/forwards.h b/include/json/forwards.h index 70bbe191c9d..affe33a7f9e 100644 --- a/include/json/forwards.h +++ b/include/json/forwards.h @@ -13,17 +13,23 @@ namespace Json { // writer.h +class StreamWriter; +class StreamWriterBuilder; +class Writer; class FastWriter; class StyledWriter; +class StyledStreamWriter; // reader.h class Reader; +class CharReader; +class CharReaderBuilder; -// features.h +// json_features.h class Features; // value.h -typedef unsigned int ArrayIndex; +using ArrayIndex = unsigned int; class StaticString; class Path; class PathArgument; diff --git a/include/json/json.h b/include/json/json.h index 3d2798a6c71..5c776a1609e 100644 --- a/include/json/json.h +++ b/include/json/json.h @@ -6,10 +6,10 @@ #ifndef JSON_JSON_H_INCLUDED #define JSON_JSON_H_INCLUDED -#include "autolink.h" -#include "value.h" +#include "config.h" +#include "json_features.h" #include "reader.h" +#include "value.h" #include "writer.h" -#include "features.h" #endif // JSON_JSON_H_INCLUDED diff --git a/include/json/features.h b/include/json/json_features.h similarity index 86% rename from include/json/features.h rename to include/json/json_features.h index 72eb6a8a01f..7c7e9f5de15 100644 --- a/include/json/features.h +++ b/include/json/json_features.h @@ -3,8 +3,8 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -#define CPPTL_JSON_FEATURES_H_INCLUDED +#ifndef JSON_FEATURES_H_INCLUDED +#define JSON_FEATURES_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" @@ -41,21 +41,21 @@ class JSON_API Features { Features(); /// \c true if comments are allowed. Default: \c true. - bool allowComments_; + bool allowComments_{true}; /// \c true if root must be either an array or an object value. Default: \c /// false. - bool strictRoot_; + bool strictRoot_{false}; /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_; + bool allowDroppedNullPlaceholders_{false}; /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_; + bool allowNumericKeys_{false}; }; } // namespace Json #pragma pack(pop) -#endif // CPPTL_JSON_FEATURES_H_INCLUDED +#endif // JSON_FEATURES_H_INCLUDED diff --git a/include/json/reader.h b/include/json/reader.h index 82859fda1af..9175466089e 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -3,18 +3,18 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED +#ifndef JSON_READER_H_INCLUDED +#define JSON_READER_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) -#include "features.h" +#include "json_features.h" #include "value.h" #endif // if !defined(JSON_IS_AMALGAMATION) #include <deque> #include <iosfwd> +#include <istream> #include <stack> #include <string> -#include <istream> // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... @@ -28,132 +28,130 @@ namespace Json { /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a - *Value. + * Value. * * \deprecated Use CharReader and CharReaderBuilder. */ -class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader { + +class JSONCPP_DEPRECATED( + "Use CharReader and CharReaderBuilder instead.") JSON_API Reader { public: - typedef char Char; - typedef const Char* Location; + using Char = char; + using Location = const Char*; /** \brief An error tagged with where in the JSON text it was encountered. * * The offsets give the [start, limit) range of bytes within the text. Note * that this is bytes, not codepoints. - * */ struct StructuredError { ptrdiff_t offset_start; ptrdiff_t offset_limit; - JSONCPP_STRING message; + String message; }; - /** \brief Constructs a Reader allowing all features - * for parsing. + /** \brief Constructs a Reader allowing all features for parsing. */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(); - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. + /** \brief Constructs a Reader allowing the specified feature set for parsing. */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(const Features& features); /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> * document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - * back during - * serialization, \c false to discard comments. - * This parameter is ignored if - * Features::allowComments_ - * is \c false. + * + * \param document UTF-8 encoded string containing the document + * to read. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. * \return \c true if the document was successfully parsed, \c false if an * error occurred. */ - bool - parse(const std::string& document, Value& root, bool collectComments = true); + bool parse(const std::string& document, Value& root, + bool collectComments = true); /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - * Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - back during - * serialization, \c false to discard comments. - * This parameter is ignored if - Features::allowComments_ - * is \c false. + * document. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded + * string of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string + * of the document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. * \return \c true if the document was successfully parsed, \c false if an - error occurred. + * error occurred. */ - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, + bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); /// \brief Parse from input stream. /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true); + bool parse(IStream& is, Value& root, bool collectComments = true); /** \brief Returns a user friendly string that list errors in the parsed * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. * \deprecated Use getFormattedErrorMessages() instead (typo fix). */ JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") - JSONCPP_STRING getFormatedErrorMessages() const; + String getFormatedErrorMessages() const; /** \brief Returns a user friendly string that list errors in the parsed * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. */ - JSONCPP_STRING getFormattedErrorMessages() const; + String getFormattedErrorMessages() const; - /** \brief Returns a vector of structured erros encounted while parsing. + /** \brief Returns a vector of structured errors encountered while parsing. + * * \return A (possibly empty) vector of StructuredError objects. Currently - * only one error can be returned, but the caller should tolerate - * multiple - * errors. This can occur if the parser recovers from a non-fatal - * parse error and then encounters additional errors. + * only one error can be returned, but the caller should tolerate multiple + * errors. This can occur if the parser recovers from a non-fatal parse + * error and then encounters additional errors. */ std::vector<StructuredError> getStructuredErrors() const; /** \brief Add a semantic error message. - * \param value JSON Value location associated with the error + * + * \param value JSON Value location associated with the error * \param message The error message. - * \return \c true if the error was successfully added, \c false if the - * Value offset exceeds the document size. + * \return \c true if the error was successfully added, \c false if the Value + * offset exceeds the document size. */ - bool pushError(const Value& value, const JSONCPP_STRING& message); + bool pushError(const Value& value, const String& message); /** \brief Add a semantic error message with extra context. - * \param value JSON Value location associated with the error + * + * \param value JSON Value location associated with the error * \param message The error message. - * \param extra Additional JSON Value location to contextualize the error + * \param extra Additional JSON Value location to contextualize the error * \return \c true if the error was successfully added, \c false if either * Value offset exceeds the document size. */ - bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra); + bool pushError(const Value& value, const String& message, const Value& extra); /** \brief Return whether there are any errors. - * \return \c true if there are no errors to report \c false if - * errors have occurred. + * + * \return \c true if there are no errors to report \c false if errors have + * occurred. */ bool good() const; @@ -185,15 +183,15 @@ class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_AP class ErrorInfo { public: Token token_; - JSONCPP_STRING message_; + String message_; Location extra_; }; - typedef std::deque<ErrorInfo> Errors; + using Errors = std::deque<ErrorInfo>; bool readToken(Token& token); void skipSpaces(); - bool match(Location pattern, int patternLength); + bool match(const Char* pattern, int patternLength); bool readComment(); bool readCStyleComment(); bool readCppStyleComment(); @@ -205,142 +203,138 @@ class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_AP bool decodeNumber(Token& token); bool decodeNumber(Token& token, Value& decoded); bool decodeString(Token& token); - bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeString(Token& token, String& decoded); bool decodeDouble(Token& token); bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, + bool addErrorAndRecover(const String& message, Token& token, TokenType skipUntilToken); void skipUntilSpace(); Value& currentValue(); Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); void skipCommentTokens(Token& token); static bool containsNewLine(Location begin, Location end); - static JSONCPP_STRING normalizeEOL(Location begin, Location end); + static String normalizeEOL(Location begin, Location end); - typedef std::stack<Value*> Nodes; + using Nodes = std::stack<Value*>; Nodes nodes_; Errors errors_; - JSONCPP_STRING document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - JSONCPP_STRING commentsBefore_; + String document_; + Location begin_{}; + Location end_{}; + Location current_{}; + Location lastValueEnd_{}; + Value* lastValue_{}; + String commentsBefore_; Features features_; - bool collectComments_; -}; // Reader + bool collectComments_{}; +}; // Reader /** Interface for reading JSON from a char array. */ class JSON_API CharReader { public: - virtual ~CharReader() {} + virtual ~CharReader() = default; /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - document. - * The document must be a UTF-8 encoded string containing the document to read. + * document. The document must be a UTF-8 encoded string containing the + * document to read. * - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - * Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param errs [out] Formatted error messages (if not NULL) - * a user friendly string that lists errors in the parsed - * document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string + * of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + * document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it was + * successfully parsed. + * \param[out] errs Formatted error messages (if not NULL) a user + * friendly string that lists errors in the parsed + * document. * \return \c true if the document was successfully parsed, \c false if an - error occurred. + * error occurred. */ - virtual bool parse( - char const* beginDoc, char const* endDoc, - Value* root, JSONCPP_STRING* errs) = 0; + virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) = 0; class JSON_API Factory { public: - virtual ~Factory() {} + virtual ~Factory() = default; /** \brief Allocate a CharReader via operator new(). * \throw std::exception if something goes wrong (e.g. invalid settings) */ virtual CharReader* newCharReader() const = 0; - }; // Factory -}; // CharReader + }; // Factory +}; // CharReader /** \brief Build a CharReader implementation. - -Usage: -\code - using namespace Json; - CharReaderBuilder builder; - builder["collectComments"] = false; - Value value; - JSONCPP_STRING errs; - bool ok = parseFromStream(builder, std::cin, &value, &errs); -\endcode -*/ + * + * Usage: + * \code + * using namespace Json; + * CharReaderBuilder builder; + * builder["collectComments"] = false; + * Value value; + * String errs; + * bool ok = parseFromStream(builder, std::cin, &value, &errs); + * \endcode + */ class JSON_API CharReaderBuilder : public CharReader::Factory { public: // Note: We use a Json::Value so that we can add data-members to this class // without a major version bump. /** Configuration of this builder. - These are case-sensitive. - Available settings (case-sensitive): - - `"collectComments": false or true` - - true to collect comment and allow writing them - back during serialization, false to discard comments. - This parameter is ignored if allowComments is false. - - `"allowComments": false or true` - - true if comments are allowed. - - `"strictRoot": false or true` - - true if root must be either an array or an object value - - `"allowDroppedNullPlaceholders": false or true` - - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) - - `"allowNumericKeys": false or true` - - true if numeric object keys are allowed. - - `"allowSingleQuotes": false or true` - - true if '' are allowed for strings (both keys and values) - - `"stackLimit": integer` - - Exceeding stackLimit (recursive depth of `readValue()`) will - cause an exception. - - This is a security issue (seg-faults caused by deeply nested JSON), - so the default is low. - - `"failIfExtra": false or true` - - If true, `parse()` returns false when extra non-whitespace trails - the JSON value in the input string. - - `"rejectDupKeys": false or true` - - If true, `parse()` returns false when a key is duplicated within an object. - - `"allowSpecialFloats": false or true` - - If true, special float values (NaNs and infinities) are allowed - and their values are lossfree restorable. - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ + * These are case-sensitive. + * Available settings (case-sensitive): + * - `"collectComments": false or true` + * - true to collect comment and allow writing them back during + * serialization, false to discard comments. This parameter is ignored + * if allowComments is false. + * - `"allowComments": false or true` + * - true if comments are allowed. + * - `"allowTrailingCommas": false or true` + * - true if trailing commas in objects and arrays are allowed. + * - `"strictRoot": false or true` + * - true if root must be either an array or an object value + * - `"allowDroppedNullPlaceholders": false or true` + * - true if dropped null placeholders are allowed. (See + * StreamWriterBuilder.) + * - `"allowNumericKeys": false or true` + * - true if numeric object keys are allowed. + * - `"allowSingleQuotes": false or true` + * - true if '' are allowed for strings (both keys and values) + * - `"stackLimit": integer` + * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an + * exception. + * - This is a security issue (seg-faults caused by deeply nested JSON), so + * the default is low. + * - `"failIfExtra": false or true` + * - If true, `parse()` returns false when extra non-whitespace trails the + * JSON value in the input string. + * - `"rejectDupKeys": false or true` + * - If true, `parse()` returns false when a key is duplicated within an + * object. + * - `"allowSpecialFloats": false or true` + * - If true, special float values (NaNs and infinities) are allowed and + * their values are lossfree restorable. + * + * You can examine 'settings_` yourself to see the defaults. You can also + * write and read them just like any JSON Value. + * \sa setDefaults() + */ Json::Value settings_; CharReaderBuilder(); - ~CharReaderBuilder() JSONCPP_OVERRIDE; + ~CharReaderBuilder() override; - CharReader* newCharReader() const JSONCPP_OVERRIDE; + CharReader* newCharReader() const override; /** \return true if 'settings' are legal and consistent; * otherwise, indicate bad settings via 'invalid'. @@ -349,7 +343,7 @@ class JSON_API CharReaderBuilder : public CharReader::Factory { /** A simple way to update a specific setting. */ - Value& operator[](JSONCPP_STRING key); + Value& operator[](const String& key); /** Called by ctor, but you can use this to reset settings_. * \pre 'settings' != NULL (but Json::null is fine) @@ -366,39 +360,37 @@ class JSON_API CharReaderBuilder : public CharReader::Factory { }; /** Consume entire stream and use its begin/end. - * Someday we might have a real StreamReader, but for now this - * is convenient. - */ -bool JSON_API parseFromStream( - CharReader::Factory const&, - JSONCPP_ISTREAM&, - Value* root, std::string* errs); + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root, + String* errs); /** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() -*/ -JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); + * + * Always keep comments from the input JSON. + * + * This can be used to read a file into a particular sub-object. + * For example: + * \code + * Json::Value root; + * cin >> root["dir"]["file"]; + * cout << root; + * \endcode + * Result: + * \verbatim + * { + * "dir": { + * "file": { + * // The input stream JSON would be nested here. + * } + * } + * } + * \endverbatim + * \throw std::exception on parse error. + * \see Json::operator<<() + */ +JSON_API IStream& operator>>(IStream&, Value&); } // namespace Json @@ -408,4 +400,4 @@ JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); #pragma warning(pop) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#endif // CPPTL_JSON_READER_H_INCLUDED +#endif // JSON_READER_H_INCLUDED diff --git a/include/json/value.h b/include/json/value.h index ebca175db6d..df1eba6acb2 100644 --- a/include/json/value.h +++ b/include/json/value.h @@ -3,38 +3,49 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_H_INCLUDED -#define CPPTL_JSON_H_INCLUDED +#ifndef JSON_H_INCLUDED +#define JSON_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <string> -#include <vector> -#include <exception> -#ifndef JSON_USE_CPPTL_SMALLMAP -#include <map> +// Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +#if defined(_MSC_VER) && _MSC_VER == 1800 +#define JSONCPP_NORETURN __declspec(noreturn) #else -#include <cpptl/smallmap.h> +#define JSONCPP_NORETURN [[noreturn]] #endif -#ifdef JSON_USE_CPPTL -#include <cpptl/forwards.h> #endif -//Conditional NORETURN attribute on the throw functions would: -// a) suppress false positives from static code analysis -// b) possibly improve optimization opportunities. -#if !defined(JSONCPP_NORETURN) -# if defined(_MSC_VER) -# define JSONCPP_NORETURN __declspec(noreturn) -# elif defined(__GNUC__) -# define JSONCPP_NORETURN __attribute__ ((__noreturn__)) -# else -# define JSONCPP_NORETURN -# endif +// Support for '= delete' with template declarations was a late addition +// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2 +// even though these declare themselves to be c++11 compilers. +#if !defined(JSONCPP_TEMPLATE_DELETE) +#if defined(__clang__) && defined(__apple_build_version__) +#if __apple_build_version__ <= 8000042 +#define JSONCPP_TEMPLATE_DELETE +#endif +#elif defined(__clang__) +#if __clang_major__ == 3 && __clang_minor__ <= 8 +#define JSONCPP_TEMPLATE_DELETE +#endif +#endif +#if !defined(JSONCPP_TEMPLATE_DELETE) +#define JSONCPP_TEMPLATE_DELETE = delete +#endif #endif +#include <array> +#include <exception> +#include <map> +#include <memory> +#include <string> +#include <vector> + // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) @@ -48,17 +59,19 @@ */ namespace Json { +#if JSON_USE_EXCEPTION /** Base class for all exceptions we throw. * * We use nothing but these internally. Of course, STL can throw others. */ class JSON_API Exception : public std::exception { public: - Exception(JSONCPP_STRING const& msg); - ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; - char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; + Exception(String msg); + ~Exception() noexcept override; + char const* what() const noexcept override; + protected: - JSONCPP_STRING msg_; + String msg_; }; /** Exceptions which the user cannot easily avoid. @@ -69,7 +82,7 @@ class JSON_API Exception : public std::exception { */ class JSON_API RuntimeError : public Exception { public: - RuntimeError(JSONCPP_STRING const& msg); + RuntimeError(String const& msg); }; /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. @@ -80,13 +93,14 @@ class JSON_API RuntimeError : public Exception { */ class JSON_API LogicError : public Exception { public: - LogicError(JSONCPP_STRING const& msg); + LogicError(String const& msg); }; +#endif /// used internally -JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg); +JSONCPP_NORETURN void throwRuntimeError(String const& msg); /// used internally -JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg); +JSONCPP_NORETURN void throwLogicError(String const& msg); /** \brief Type of the value held by a Value object. */ @@ -109,14 +123,16 @@ enum CommentPlacement { numberOfCommentPlacement }; -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; -// typedef CppTL::AnyEnumerator<const Value &> EnumValues; -//# endif +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; /** \brief Lightweight wrapper to tag static string. * - * Value constructor and objectValue member assignement takes advantage of the + * Value constructor and objectValue member assignment takes advantage of the * StaticString and avoid the cost of string duplication when storing the * string or the member name. * @@ -165,7 +181,7 @@ class JSON_API StaticString { * The get() methods can be used to obtain default value in the case the * required element does not exist. * - * It is possible to iterate over the list of a #objectValue values using + * It is possible to iterate over the list of member keys of an object using * the getMemberNames() method. * * \note #Value string-length fit in size_t, but keys must be < 2^30. @@ -176,73 +192,86 @@ class JSON_API StaticString { */ class JSON_API Value { friend class ValueIteratorBase; + public: - typedef std::vector<JSONCPP_STRING> Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; + using Members = std::vector<String>; + using iterator = ValueIterator; + using const_iterator = ValueConstIterator; + using UInt = Json::UInt; + using Int = Json::Int; #if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; + using UInt64 = Json::UInt64; + using Int64 = Json::Int64; #endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; + using LargestInt = Json::LargestInt; + using LargestUInt = Json::LargestUInt; + using ArrayIndex = Json::ArrayIndex; - static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). - static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null - static Value const& nullSingleton(); ///< Prefer this to null or nullRef. + // Required for boost integration, e. g. BOOST_TEST + using value_type = std::string; + +#if JSON_USE_NULLREF + // Binary compatibility kludges, do not use. + static const Value& null; + static const Value& nullRef; +#endif + + // null and nullRef are deprecated, use this instead. + static Value const& nullSingleton(); /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; + static constexpr LargestInt minLargestInt = + LargestInt(~(LargestUInt(-1) / 2)); /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; + static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2); /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; + static constexpr LargestUInt maxLargestUInt = LargestUInt(-1); /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; + static constexpr Int minInt = Int(~(UInt(-1) / 2)); /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; + static constexpr Int maxInt = Int(UInt(-1) / 2); /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; + static constexpr UInt maxUInt = UInt(-1); #if defined(JSON_HAS_INT64) /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; + static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2)); /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; + static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2); /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; + static constexpr UInt64 maxUInt64 = UInt64(-1); #endif // defined(JSON_HAS_INT64) - + /// Default precision for real value for string representation. + static constexpr UInt defaultRealPrecision = 17; + // The constant is hard-coded because some compiler have trouble + // converting Value::maxUInt64 to a double correctly (AIX/xlC). + // Assumes that UInt64 is a 64 bits integer. + static constexpr double maxUInt64AsDouble = 18446744073709551615.0; +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else private: +#endif #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION class CZString { public: - enum DuplicationPolicy { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; CZString(ArrayIndex index); CZString(char const* str, unsigned length, DuplicationPolicy allocate); CZString(CZString const& other); -#if JSON_HAS_RVALUE_REFERENCES CZString(CZString&& other); -#endif ~CZString(); CZString& operator=(const CZString& other); - -#if JSON_HAS_RVALUE_REFERENCES CZString& operator=(CZString&& other); -#endif bool operator<(CZString const& other) const; bool operator==(CZString const& other) const; ArrayIndex index() const; - //const char* c_str() const; ///< \deprecated + // const char* c_str() const; ///< \deprecated char const* data() const; unsigned length() const; bool isStaticString() const; @@ -251,11 +280,11 @@ class JSON_API Value { void swap(CZString& other); struct StringStorage { - unsigned policy_: 2; - unsigned length_: 30; // 1GB max + unsigned policy_ : 2; + unsigned length_ : 30; // 1GB max }; - char const* cstr_; // actually, a prefixed string, unless policy is noDup + char const* cstr_; // actually, a prefixed string, unless policy is noDup union { ArrayIndex index_; StringStorage storage_; @@ -263,29 +292,26 @@ class JSON_API Value { }; public: -#ifndef JSON_USE_CPPTL_SMALLMAP typedef std::map<CZString, Value> ObjectValues; -#else - typedef CppTL::SmallMap<CZString, Value> ObjectValues; -#endif // ifndef JSON_USE_CPPTL_SMALLMAP #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. -This is useful since clear() and resize() will not alter types. - - Examples: -\code -Json::Value null_value; // null -Json::Value arr_value(Json::arrayValue); // [] -Json::Value obj_value(Json::objectValue); // {} -\endcode - */ + /** + * \brief Create a default Value of the given type. + * + * This is a very useful constructor. + * To create an empty array, pass arrayValue. + * To create an empty object, pass objectValue. + * Another Value can then be set to this one by assignment. + * This is useful since clear() and resize() will not alter types. + * + * Examples: + * \code + * Json::Value null_value; // null + * Json::Value arr_value(Json::arrayValue); // [] + * Json::Value obj_value(Json::objectValue); // {} + * \endcode + */ Value(ValueType type = nullValue); Value(Int value); Value(UInt value); @@ -296,38 +322,35 @@ Json::Value obj_value(Json::objectValue); // {} Value(double value); Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) Value(const char* begin, const char* end); ///< Copy all, incl zeroes. - /** \brief Constructs a value from a static string. - + /** + * \brief Constructs a value from a static string. + * * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. + * internal storage. The given string must remain alive after the call to + * this constructor. + * * \note This works only for null-terminated strings. (We cannot change the - * size of this class, so we have nowhere to store the length, - * which might be computed later for various operations.) + * size of this class, so we have nowhere to store the length, which might be + * computed later for various operations.) * * Example of usage: - * \code - * static StaticString foo("some text"); - * Json::Value aValue(foo); - * \endcode + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode */ Value(const StaticString& value); - Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too. -#ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString& value); -#endif + Value(const String& value); Value(bool value); - /// Deep copy. + Value(std::nullptr_t ptr) = delete; Value(const Value& other); -#if JSON_HAS_RVALUE_REFERENCES - /// Move constructor Value(Value&& other); -#endif ~Value(); - /// Deep copy, then swap(other). - /// \note Over-write existing comments. To preserve comments, use #swapPayload(). - Value& operator=(Value other); + /// \note Overwrite existing comments. To preserve comments, use + /// #swapPayload(). + Value& operator=(const Value& other); + Value& operator=(Value&& other); /// Swap everything. void swap(Value& other); @@ -352,17 +375,14 @@ Json::Value obj_value(Json::objectValue); // {} const char* asCString() const; ///< Embedded zeroes could cause you trouble! #if JSONCPP_USING_SECURE_MEMORY - unsigned getCStringLength() const; //Allows you to understand the length of the CString + unsigned getCStringLength() const; // Allows you to understand the length of + // the CString #endif - JSONCPP_STRING asString() const; ///< Embedded zeroes are possible. + String asString() const; ///< Embedded zeroes are possible. /** Get raw char* of string-value. * \return false if !string. (Seg-fault if str or end are NULL.) */ - bool getString( - char const** begin, char const** end) const; -#ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -#endif + bool getString(char const** begin, char const** end) const; Int asInt() const; UInt asUInt() const; #if defined(JSON_HAS_INT64) @@ -388,6 +408,10 @@ Json::Value obj_value(Json::objectValue); // {} bool isArray() const; bool isObject() const; + /// The `as<T>` and `is<T>` member function templates and specializations. + template <typename T> T as() const JSONCPP_TEMPLATE_DELETE; + template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE; + bool isConvertibleTo(ValueType other) const; /// Number of values in array or object @@ -397,50 +421,41 @@ Json::Value obj_value(Json::objectValue); // {} /// otherwise, false. bool empty() const; - /// Return isNull() - bool operator!() const; + /// Return !isNull() + explicit operator bool() const; /// Remove all object members and array elements. /// \pre type() is arrayValue, objectValue, or nullValue /// \post type() is unchanged void clear(); - /// Resize the array to size elements. + /// Resize the array to newSize elements. /// New elements are initialized to null. /// May only be called on nullValue or arrayValue. /// \pre type() is arrayValue or nullValue /// \post type() is arrayValue - void resize(ArrayIndex size); + void resize(ArrayIndex newSize); - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. + //@{ + /// Access an array element (zero based index). If the array contains less + /// than index element, then null value are inserted in the array so that + /// its size is index+1. /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) + /// this from the operator[] which takes a string.) Value& operator[](ArrayIndex index); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) Value& operator[](int index); + //@} - /// Access an array element (zero based index ) + //@{ + /// Access an array element (zero based index). /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) + /// this from the operator[] which takes a string.) const Value& operator[](ArrayIndex index) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) const Value& operator[](int index) const; + //@} /// If the array contains at least index+1 elements, returns the element - /// value, - /// otherwise returns defaultValue. + /// value, otherwise returns defaultValue. Value get(ArrayIndex index, const Value& defaultValue) const; /// Return true if index < size(). bool isValidIndex(ArrayIndex index) const; @@ -448,61 +463,51 @@ Json::Value obj_value(Json::objectValue); // {} /// /// Equivalent to jsonvalue[jsonvalue.size()] = value; Value& append(const Value& value); - -#if JSON_HAS_RVALUE_REFERENCES Value& append(Value&& value); -#endif + + /// \brief Insert value in array at specific index + bool insert(ArrayIndex index, const Value& newValue); + bool insert(ArrayIndex index, Value&& newValue); /// Access an object value by name, create a null member if it does not exist. /// \note Because of our implementation, keys are limited to 2^30 -1 chars. - /// Exceeding that will cause an exception. + /// Exceeding that will cause an exception. Value& operator[](const char* key); /// Access an object value by name, returns null if there is no member with /// that name. const Value& operator[](const char* key) const; /// Access an object value by name, create a null member if it does not exist. /// \param key may contain embedded nulls. - Value& operator[](const JSONCPP_STRING& key); + Value& operator[](const String& key); /// Access an object value by name, returns null if there is no member with /// that name. /// \param key may contain embedded nulls. - const Value& operator[](const JSONCPP_STRING& key) const; + const Value& operator[](const String& key) const; /** \brief Access an object value by name, create a null member if it does not - exist. - - * If the object has no entry for that name, then the member name used to store - * the new entry is not duplicated. + * exist. + * + * If the object has no entry for that name, then the member name used to + * store the new entry is not duplicated. * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode */ Value& operator[](const StaticString& key); -#ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const CppTL::ConstString& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const CppTL::ConstString& key) const; -#endif /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy Value get(const char* key, const Value& defaultValue) const; /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy /// \note key may contain embedded nulls. - Value get(const char* begin, const char* end, const Value& defaultValue) const; + Value get(const char* begin, const char* end, + const Value& defaultValue) const; /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy /// \param key may contain embedded nulls. - Value get(const JSONCPP_STRING& key, const Value& defaultValue) const; -#ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const CppTL::ConstString& key, const Value& defaultValue) const; -#endif + Value get(const String& key, const Value& defaultValue) const; /// Most general and efficient version of isMember()const, get()const, /// and operator[]const /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 @@ -510,53 +515,44 @@ Json::Value obj_value(Json::objectValue); // {} /// Most general and efficient version of object-mutators. /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. - Value const* demand(char const* begin, char const* end); + Value* demand(char const* begin, char const* end); /// \brief Remove and return the named member. /// /// Do nothing if it did not exist. - /// \return the removed Value, or null. /// \pre type() is objectValue or nullValue /// \post type() is unchanged - /// \deprecated - JSONCPP_DEPRECATED("") - Value removeMember(const char* key); + void removeMember(const char* key); /// Same as removeMember(const char*) /// \param key may contain embedded nulls. - /// \deprecated - JSONCPP_DEPRECATED("") - Value removeMember(const JSONCPP_STRING& key); + void removeMember(const String& key); /// Same as removeMember(const char* begin, const char* end, Value* removed), /// but 'key' is null-terminated. bool removeMember(const char* key, Value* removed); /** \brief Remove the named map member. - - Update 'removed' iff removed. - \param key may contain embedded nulls. - \return true iff removed (no exceptions) - */ - bool removeMember(JSONCPP_STRING const& key, Value* removed); - /// Same as removeMember(JSONCPP_STRING const& key, Value* removed) + * + * Update 'removed' iff removed. + * \param key may contain embedded nulls. + * \return true iff removed (no exceptions) + */ + bool removeMember(String const& key, Value* removed); + /// Same as removeMember(String const& key, Value* removed) bool removeMember(const char* begin, const char* end, Value* removed); /** \brief Remove the indexed array element. - - O(n) expensive operations. - Update 'removed' iff removed. - \return true iff removed (no exceptions) - */ - bool removeIndex(ArrayIndex i, Value* removed); + * + * O(n) expensive operations. + * Update 'removed' iff removed. + * \return true if removed (no exceptions) + */ + bool removeIndex(ArrayIndex index, Value* removed); /// Return true if the object has a member named key. /// \note 'key' must be null-terminated. bool isMember(const char* key) const; /// Return true if the object has a member named key. /// \param key may contain embedded nulls. - bool isMember(const JSONCPP_STRING& key) const; - /// Same as isMember(JSONCPP_STRING const& key)const + bool isMember(const String& key) const; + /// Same as isMember(String const& key)const bool isMember(const char* begin, const char* end) const; -#ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString& key) const; -#endif /// \brief Return a list of the member names. /// @@ -565,23 +561,22 @@ Json::Value obj_value(Json::objectValue); // {} /// \post if type() was nullValue, it remains nullValue Members getMemberNames() const; - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif - /// \deprecated Always pass len. - JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.") - void setComment(const char* comment, CommentPlacement placement); + JSONCPP_DEPRECATED("Use setComment(String const&) instead.") + void setComment(const char* comment, CommentPlacement placement) { + setComment(String(comment, strlen(comment)), placement); + } /// Comments must be //... or /* ... */ - void setComment(const char* comment, size_t len, CommentPlacement placement); + void setComment(const char* comment, size_t len, CommentPlacement placement) { + setComment(String(comment, len), placement); + } /// Comments must be //... or /* ... */ - void setComment(const JSONCPP_STRING& comment, CommentPlacement placement); + void setComment(String comment, CommentPlacement placement); bool hasComment(CommentPlacement placement) const; /// Include delimiters and embedded newlines. - JSONCPP_STRING getComment(CommentPlacement placement) const; + String getComment(CommentPlacement placement) const; - JSONCPP_STRING toStyledString() const; + String toStyledString() const; const_iterator begin() const; const_iterator end() const; @@ -597,20 +592,20 @@ Json::Value obj_value(Json::objectValue); // {} ptrdiff_t getOffsetLimit() const; private: + void setType(ValueType v) { + bits_.value_type_ = static_cast<unsigned char>(v); + } + bool isAllocated() const { return bits_.allocated_; } + void setIsAllocated(bool v) { bits_.allocated_ = v; } + void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); Value& resolveReference(const char* key); Value& resolveReference(const char* key, const char* end); - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); - - void setComment(const char* text, size_t len); - - char* comment_; - }; - // struct MemberNamesTransform //{ // typedef const char *result_type; @@ -625,13 +620,33 @@ Json::Value obj_value(Json::objectValue); // {} LargestUInt uint_; double real_; bool bool_; - char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ + char* string_; // if allocated_, ptr to { unsigned, char[] }. ObjectValues* map_; } value_; - ValueType type_ : 8; - unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. - // If not allocated_, string_ must be null-terminated. - CommentInfo* comments_; + + struct { + // Really a ValueType, but types should agree for bitfield packing. + unsigned int value_type_ : 8; + // Unless allocated_, string_ must be null-terminated. + unsigned int allocated_ : 1; + } bits_; + + class Comments { + public: + Comments() = default; + Comments(const Comments& that); + Comments(Comments&& that); + Comments& operator=(const Comments& that); + Comments& operator=(Comments&& that); + bool has(CommentPlacement slot) const; + String get(CommentPlacement slot) const; + void set(CommentPlacement slot, String comment); + + private: + using Array = std::array<String, numberOfCommentPlacement>; + std::unique_ptr<Array> ptr_; + }; + Comments comments_; // [start, limit) byte offsets in the source JSON text from which this Value // was extracted. @@ -639,6 +654,36 @@ Json::Value obj_value(Json::objectValue); // {} ptrdiff_t limit_; }; +template <> inline bool Value::as<bool>() const { return asBool(); } +template <> inline bool Value::is<bool>() const { return isBool(); } + +template <> inline Int Value::as<Int>() const { return asInt(); } +template <> inline bool Value::is<Int>() const { return isInt(); } + +template <> inline UInt Value::as<UInt>() const { return asUInt(); } +template <> inline bool Value::is<UInt>() const { return isUInt(); } + +#if defined(JSON_HAS_INT64) +template <> inline Int64 Value::as<Int64>() const { return asInt64(); } +template <> inline bool Value::is<Int64>() const { return isInt64(); } + +template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); } +template <> inline bool Value::is<UInt64>() const { return isUInt64(); } +#endif + +template <> inline double Value::as<double>() const { return asDouble(); } +template <> inline bool Value::is<double>() const { return isDouble(); } + +template <> inline String Value::as<String>() const { return asString(); } +template <> inline bool Value::is<String>() const { return isString(); } + +/// These `as` specializations are type conversions, and do not have a +/// corresponding `is`. +template <> inline float Value::as<float>() const { return asFloat(); } +template <> inline const char* Value::as<const char*>() const { + return asCString(); +} + /** \brief Experimental and untested: represents an element of the "path" to * access a node. */ @@ -649,17 +694,13 @@ class JSON_API PathArgument { PathArgument(); PathArgument(ArrayIndex index); PathArgument(const char* key); - PathArgument(const JSONCPP_STRING& key); + PathArgument(String key); private: - enum Kind { - kindNone = 0, - kindIndex, - kindKey - }; - JSONCPP_STRING key_; - ArrayIndex index_; - Kind kind_; + enum Kind { kindNone = 0, kindIndex, kindKey }; + String key_; + ArrayIndex index_{}; + Kind kind_{kindNone}; }; /** \brief Experimental and untested: represents a "path" to access a node. @@ -671,12 +712,11 @@ class JSON_API PathArgument { * - ".name1.name2.name3" * - ".[0][1][2].name1[3]" * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter + * - ".[%]" => index is provided as parameter */ class JSON_API Path { public: - Path(const JSONCPP_STRING& path, - const PathArgument& a1 = PathArgument(), + Path(const String& path, const PathArgument& a1 = PathArgument(), const PathArgument& a2 = PathArgument(), const PathArgument& a3 = PathArgument(), const PathArgument& a4 = PathArgument(), @@ -689,15 +729,13 @@ class JSON_API Path { Value& make(Value& root) const; private: - typedef std::vector<const PathArgument*> InArgs; - typedef std::vector<PathArgument> Args; + using InArgs = std::vector<const PathArgument*>; + using Args = std::vector<PathArgument>; - void makePath(const JSONCPP_STRING& path, const InArgs& in); - void addPathInArg(const JSONCPP_STRING& path, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind); - void invalidPath(const JSONCPP_STRING& path, int location); + void makePath(const String& path, const InArgs& in); + void addPathInArg(const String& path, const InArgs& in, + InArgs::const_iterator& itInArg, PathArgument::Kind kind); + static void invalidPath(const String& path, int location); Args args_; }; @@ -707,10 +745,10 @@ class JSON_API Path { */ class JSON_API ValueIteratorBase { public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; + using iterator_category = std::bidirectional_iterator_tag; + using size_t = unsigned int; + using difference_type = int; + using SelfType = ValueIteratorBase; bool operator==(const SelfType& other) const { return isEqual(other); } @@ -724,17 +762,19 @@ class JSON_API ValueIteratorBase { /// Value. Value key() const; - /// Return the index of the referenced Value, or -1 if it is not an arrayValue. + /// Return the index of the referenced Value, or -1 if it is not an + /// arrayValue. UInt index() const; /// Return the member name of the referenced Value, or "" if it is not an /// objectValue. /// \note Avoid `c_str()` on result, as embedded zeroes are possible. - JSONCPP_STRING name() const; + String name() const; /// Return the member name of the referenced Value. "" if it is not an /// objectValue. - /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. + /// \deprecated This cannot be used for UTF-8 strings, since there can be + /// embedded nulls. JSONCPP_DEPRECATED("Use `key = name();` instead.") char const* memberName() const; /// Return the member name of the referenced Value, or NULL if it is not an @@ -743,7 +783,14 @@ class JSON_API ValueIteratorBase { char const* memberName(char const** end) const; protected: - Value& deref() const; + /*! Internal utility functions to assist with implementing + * other iterator functions. The const and non-const versions + * of the "deref" protected methods expose the protected + * current_ member variable in a way that can often be + * optimized away by the compiler. + */ + const Value& deref() const; + Value& deref(); void increment(); @@ -758,7 +805,7 @@ class JSON_API ValueIteratorBase { private: Value::ObjectValues::iterator current_; // Indicates that iterator is for a null value. - bool isNull_; + bool isNull_{true}; public: // For some reason, BORLAND needs these at the end, rather @@ -774,20 +821,21 @@ class JSON_API ValueConstIterator : public ValueIteratorBase { friend class Value; public: - typedef const Value value_type; - //typedef unsigned int size_t; - //typedef int difference_type; - typedef const Value& reference; - typedef const Value* pointer; - typedef ValueConstIterator SelfType; + using value_type = const Value; + // typedef unsigned int size_t; + // typedef int difference_type; + using reference = const Value&; + using pointer = const Value*; + using SelfType = ValueConstIterator; ValueConstIterator(); ValueConstIterator(ValueIterator const& other); private: -/*! \internal Use by Value to create an iterator. - */ + /*! \internal Use by Value to create an iterator. + */ explicit ValueConstIterator(const Value::ObjectValues::iterator& current); + public: SelfType& operator=(const ValueIteratorBase& other); @@ -824,21 +872,22 @@ class JSON_API ValueIterator : public ValueIteratorBase { friend class Value; public: - typedef Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef Value& reference; - typedef Value* pointer; - typedef ValueIterator SelfType; + using value_type = Value; + using size_t = unsigned int; + using difference_type = int; + using reference = Value&; + using pointer = Value*; + using SelfType = ValueIterator; ValueIterator(); explicit ValueIterator(const ValueConstIterator& other); ValueIterator(const ValueIterator& other); private: -/*! \internal Use by Value to create an iterator. - */ + /*! \internal Use by Value to create an iterator. + */ explicit ValueIterator(const Value::ObjectValues::iterator& current); + public: SelfType& operator=(const SelfType& other); @@ -864,19 +913,18 @@ class JSON_API ValueIterator : public ValueIteratorBase { return *this; } - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } + /*! The return value of non-const iterators can be + * changed, so the these functions are not const + * because the returned references/pointers can be used + * to change state of the base class. + */ + reference operator*() { return deref(); } + pointer operator->() { return &deref(); } }; -} // namespace Json +inline void swap(Value& a, Value& b) { a.swap(b); } - -namespace std { -/// Specialize std::swap() for Json::Value. -template<> -inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } -} +} // namespace Json #pragma pack(pop) @@ -884,4 +932,4 @@ inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } #pragma warning(pop) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#endif // CPPTL_JSON_H_INCLUDED +#endif // JSON_H_INCLUDED diff --git a/include/json/version.h b/include/json/version.h index d9539618957..5b9783d9656 100644 --- a/include/json/version.h +++ b/include/json/version.h @@ -1,14 +1,22 @@ -// DO NOT EDIT. This file (and "version") is generated by CMake. -// Run CMake configure step to update it. #ifndef JSON_VERSION_H_INCLUDED -# define JSON_VERSION_H_INCLUDED +#define JSON_VERSION_H_INCLUDED -# define JSONCPP_VERSION_STRING "1.8.2" -# define JSONCPP_VERSION_MAJOR 1 -# define JSONCPP_VERSION_MINOR 8 -# define JSONCPP_VERSION_PATCH 2 -# define JSONCPP_VERSION_QUALIFIER -# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) +// Note: version must be updated in three places when doing a release. This +// annoying process ensures that amalgamate, CMake, and meson all report the +// correct version. +// 1. /meson.build +// 2. /include/json/version.h +// 3. /CMakeLists.txt +// IMPORTANT: also update the SOVERSION!! + +#define JSONCPP_VERSION_STRING "1.9.4" +#define JSONCPP_VERSION_MAJOR 1 +#define JSONCPP_VERSION_MINOR 9 +#define JSONCPP_VERSION_PATCH 3 +#define JSONCPP_VERSION_QUALIFIER +#define JSONCPP_VERSION_HEXA \ + ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ + (JSONCPP_VERSION_PATCH << 8)) #ifdef JSONCPP_USING_SECURE_MEMORY #undef JSONCPP_USING_SECURE_MEMORY diff --git a/include/json/writer.h b/include/json/writer.h index f258cbfdca5..fb0852a0ca8 100644 --- a/include/json/writer.h +++ b/include/json/writer.h @@ -9,13 +9,13 @@ #if !defined(JSON_IS_AMALGAMATION) #include "value.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <vector> -#include <string> #include <ostream> +#include <string> +#include <vector> // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4251) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) @@ -27,31 +27,31 @@ namespace Json { class Value; /** - -Usage: -\code - using namespace Json; - void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { - std::unique_ptr<StreamWriter> const writer( - factory.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush - } -\endcode -*/ + * + * Usage: + * \code + * using namespace Json; + * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) + * { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter()); + * writer->write(value, &std::cout); + * std::cout << std::endl; // add lf and flush + * } + * \endcode + */ class JSON_API StreamWriter { protected: - JSONCPP_OSTREAM* sout_; // not owned; will not delete + OStream* sout_; // not owned; will not delete public: StreamWriter(); virtual ~StreamWriter(); /** Write Value into document as configured in sub-class. - Do not take ownership of sout, but maintain a reference during function. - \pre sout != NULL - \return zero on success (For now, we always return zero, so check the stream instead.) - \throw std::exception possibly, depending on configuration + * Do not take ownership of sout, but maintain a reference during function. + * \pre sout != NULL + * \return zero on success (For now, we always return zero, so check the + * stream instead.) \throw std::exception possibly, depending on + * configuration */ - virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0; + virtual int write(Value const& root, OStream* sout) = 0; /** \brief A simple abstract factory. */ @@ -62,64 +62,69 @@ class JSON_API StreamWriter { * \throw std::exception if something goes wrong (e.g. invalid settings) */ virtual StreamWriter* newStreamWriter() const = 0; - }; // Factory -}; // StreamWriter + }; // Factory +}; // StreamWriter /** \brief Write into stringstream, then return string, for convenience. * A StreamWriter will be created from the factory, used, and then deleted. */ -JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); - +String JSON_API writeString(StreamWriter::Factory const& factory, + Value const& root); /** \brief Build a StreamWriter implementation. -Usage: -\code - using namespace Json; - Value value = ...; - StreamWriterBuilder builder; - builder["commentStyle"] = "None"; - builder["indentation"] = " "; // or whatever you like - std::unique_ptr<Json::StreamWriter> writer( - builder.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush -\endcode +* Usage: +* \code +* using namespace Json; +* Value value = ...; +* StreamWriterBuilder builder; +* builder["commentStyle"] = "None"; +* builder["indentation"] = " "; // or whatever you like +* std::unique_ptr<Json::StreamWriter> writer( +* builder.newStreamWriter()); +* writer->write(value, &std::cout); +* std::cout << std::endl; // add lf and flush +* \endcode */ class JSON_API StreamWriterBuilder : public StreamWriter::Factory { public: // Note: We use a Json::Value so that we can add data-members to this class // without a major version bump. /** Configuration of this builder. - Available settings (case-sensitive): - - "commentStyle": "None" or "All" - - "indentation": "<anything>" - - "enableYAMLCompatibility": false or true - - slightly change the whitespace around colons - - "dropNullPlaceholders": false or true - - Drop the "null" string from the writer's output for nullValues. - Strictly speaking, this is not valid JSON. But when the output is being - fed to a browser's Javascript, it makes for smaller output and the - browser can handle the output just fine. - - "useSpecialFloats": false or true - - If true, outputs non-finite floating point values in the following way: - NaN values as "NaN", positive infinity as "Infinity", and negative infinity - as "-Infinity". - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ + * Available settings (case-sensitive): + * - "commentStyle": "None" or "All" + * - "indentation": "<anything>". + * - Setting this to an empty string also omits newline characters. + * - "enableYAMLCompatibility": false or true + * - slightly change the whitespace around colons + * - "dropNullPlaceholders": false or true + * - Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + * - "useSpecialFloats": false or true + * - If true, outputs non-finite floating point values in the following way: + * NaN values as "NaN", positive infinity as "Infinity", and negative + * infinity as "-Infinity". + * - "precision": int + * - Number of precision digits for formatting of real values. + * - "precisionType": "significant"(default) or "decimal" + * - Type of precision for formatting of real values. + + * You can examine 'settings_` yourself + * to see the defaults. You can also write and read them just like any + * JSON Value. + * \sa setDefaults() + */ Json::Value settings_; StreamWriterBuilder(); - ~StreamWriterBuilder() JSONCPP_OVERRIDE; + ~StreamWriterBuilder() override; /** * \throw std::exception if something goes wrong (e.g. invalid settings) */ - StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE; + StreamWriter* newStreamWriter() const override; /** \return true if 'settings' are legal and consistent; * otherwise, indicate bad settings via 'invalid'. @@ -127,7 +132,7 @@ class JSON_API StreamWriterBuilder : public StreamWriter::Factory { bool validate(Json::Value* invalid) const; /** A simple way to update a specific setting. */ - Value& operator[](JSONCPP_STRING key); + Value& operator[](const String& key); /** Called by ctor, but you can use this to reset settings_. * \pre 'settings' != NULL (but Json::null is fine) @@ -144,7 +149,7 @@ class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { public: virtual ~Writer(); - virtual JSONCPP_STRING write(const Value& root) = 0; + virtual String write(const Value& root) = 0; }; /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format @@ -152,21 +157,25 @@ class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { * * The JSON document is written in a single line. It is not intended for 'human' *consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. + * but may be useful to support feature such as RPC where bandwidth is limited. * \sa Reader, Value * \deprecated Use StreamWriterBuilder. */ -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer { - +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter + : public Writer { public: FastWriter(); - ~FastWriter() JSONCPP_OVERRIDE {} + ~FastWriter() override = default; void enableYAMLCompatibility(); /** \brief Drop the "null" string from the writer's output for nullValues. * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's Javascript, it makes for smaller output and the + * fed to a browser's JavaScript, it makes for smaller output and the * browser can handle the output just fine. */ void dropNullPlaceholders(); @@ -174,16 +183,19 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter void omitEndingLineFeed(); public: // overridden from Writer - JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + String write(const Value& root) override; private: void writeValue(const Value& value); - JSONCPP_STRING document_; - bool yamlCompatiblityEnabled_; - bool dropNullPlaceholders_; - bool omitEndingLineFeed_; + String document_; + bool yamlCompatibilityEnabled_{false}; + bool dropNullPlaceholders_{false}; + bool omitEndingLineFeed_{false}; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a *human friendly way. @@ -209,41 +221,49 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter * \sa Reader, Value, Value::setComment() * \deprecated Use StreamWriterBuilder. */ -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledWriter : public Writer { public: StyledWriter(); - ~StyledWriter() JSONCPP_OVERRIDE {} + ~StyledWriter() override = default; public: // overridden from Writer /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. * \param root Value to serialize. * \return String containing the JSON document that represents the root value. */ - JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + String write(const Value& root) override; private: void writeValue(const Value& value); void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const JSONCPP_STRING& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); void writeIndent(); - void writeWithIndent(const JSONCPP_STRING& value); + void writeWithIndent(const String& value); void indent(); void unindent(); void writeCommentBeforeValue(const Value& root); void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); - typedef std::vector<JSONCPP_STRING> ChildValues; + using ChildValues = std::vector<String>; ChildValues childValues_; - JSONCPP_STRING document_; - JSONCPP_STRING indentString_; - unsigned int rightMargin_; - unsigned int indentSize_; - bool addChildValues_; + String document_; + String indentString_; + unsigned int rightMargin_{74}; + unsigned int indentSize_{3}; + bool addChildValues_{false}; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way, @@ -270,13 +290,18 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWrite * \sa Reader, Value, Value::setComment() * \deprecated Use StreamWriterBuilder. */ -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledStreamWriter { public: -/** - * \param indentation Each level will be indented by this amount extra. - */ - StyledStreamWriter(JSONCPP_STRING indentation = "\t"); - ~StyledStreamWriter() {} + /** + * \param indentation Each level will be indented by this amount extra. + */ + StyledStreamWriter(String indentation = "\t"); + ~StyledStreamWriter() = default; public: /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. @@ -285,46 +310,51 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStrea * \note There is no point in deriving from Writer, since write() should not * return a value. */ - void write(JSONCPP_OSTREAM& out, const Value& root); + void write(OStream& out, const Value& root); private: void writeValue(const Value& value); void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const JSONCPP_STRING& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); void writeIndent(); - void writeWithIndent(const JSONCPP_STRING& value); + void writeWithIndent(const String& value); void indent(); void unindent(); void writeCommentBeforeValue(const Value& root); void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); - typedef std::vector<JSONCPP_STRING> ChildValues; + using ChildValues = std::vector<String>; ChildValues childValues_; - JSONCPP_OSTREAM* document_; - JSONCPP_STRING indentString_; - unsigned int rightMargin_; - JSONCPP_STRING indentation_; + OStream* document_; + String indentString_; + unsigned int rightMargin_{74}; + String indentation_; bool addChildValues_ : 1; bool indented_ : 1; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif #if defined(JSON_HAS_INT64) -JSONCPP_STRING JSON_API valueToString(Int value); -JSONCPP_STRING JSON_API valueToString(UInt value); +String JSON_API valueToString(Int value); +String JSON_API valueToString(UInt value); #endif // if defined(JSON_HAS_INT64) -JSONCPP_STRING JSON_API valueToString(LargestInt value); -JSONCPP_STRING JSON_API valueToString(LargestUInt value); -JSONCPP_STRING JSON_API valueToString(double value); -JSONCPP_STRING JSON_API valueToString(bool value); -JSONCPP_STRING JSON_API valueToQuotedString(const char* value); +String JSON_API valueToString(LargestInt value); +String JSON_API valueToString(LargestUInt value); +String JSON_API valueToString( + double value, unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); +String JSON_API valueToString(bool value); +String JSON_API valueToQuotedString(const char* value); /// \brief Output using the StyledStreamWriter. /// \see Json::operator>>() -JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root); +JSON_API OStream& operator<<(OStream&, const Value& root); } // namespace Json diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 9e346aee268..19922a823c9 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -5,69 +5,65 @@ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" #include <json/assertions.h> #include <json/reader.h> #include <json/value.h> -#include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <utility> -#include <cstdio> +#include <algorithm> #include <cassert> #include <cstring> +#include <iostream> #include <istream> -#include <sstream> +#include <limits> #include <memory> #include <set> -#include <limits> +#include <sstream> +#include <utility> -#if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above -#define snprintf sprintf_s -#elif _MSC_VER >= 1900 // VC++ 14.0 and above -#define snprintf std::snprintf -#else -#define snprintf _snprintf -#endif -#elif defined(__ANDROID__) || defined(__QNXNTO__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#if !defined(__MINGW32__) && !defined(__CYGWIN__) -#define snprintf std::snprintf -#endif -#endif +#include <cstdio> +#if __cplusplus >= 201103L -#if defined(__QNXNTO__) +#if !defined(sscanf) #define sscanf std::sscanf #endif -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +#endif //__cplusplus + +#if defined(_MSC_VER) +#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#endif //_MSC_VER + +#if defined(_MSC_VER) // Disable warning about strdup being deprecated. #pragma warning(disable : 4996) #endif -// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile +// time to change the stack limit #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) #define JSONCPP_DEPRECATED_STACK_LIMIT 1000 #endif -static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() +static size_t const stackLimit_g = + JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -typedef std::unique_ptr<CharReader> CharReaderPtr; +using CharReaderPtr = std::unique_ptr<CharReader>; #else -typedef std::auto_ptr<CharReader> CharReaderPtr; +using CharReaderPtr = std::auto_ptr<CharReader>; #endif // Implementation of class Features // //////////////////////////////// -Features::Features() - : allowComments_(true), strictRoot_(false), - allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} +Features::Features() = default; -Features Features::all() { return Features(); } +Features Features::all() { return {}; } Features Features::strictMode() { Features features; @@ -82,49 +78,38 @@ Features Features::strictMode() { // //////////////////////////////// bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; + return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); } // Class Reader // ////////////////////////////////////////////////////////////////// -Reader::Reader() - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(Features::all()), - collectComments_() {} +Reader::Reader() : features_(Features::all()) {} -Reader::Reader(const Features& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} +Reader::Reader(const Features& features) : features_(features) {} -bool -Reader::parse(const std::string& document, Value& root, bool collectComments) { +bool Reader::parse(const std::string& document, Value& root, + bool collectComments) { document_.assign(document.begin(), document.end()); const char* begin = document_.c_str(); const char* end = begin + document_.length(); return parse(begin, end, root, collectComments); } -bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { - // std::istream_iterator<char> begin(sin); +bool Reader::parse(std::istream& is, Value& root, bool collectComments) { + // std::istream_iterator<char> begin(is); // std::istream_iterator<char> end; // Those would allow streamed input from a file, if parse() were a // template function. - // Since JSONCPP_STRING is reference-counted, this at least does not + // Since String is reference-counted, this at least does not // create an extra copy. - JSONCPP_STRING doc; - std::getline(sin, doc, (char)EOF); + String doc; + std::getline(is, doc, static_cast<char> EOF); return parse(doc.data(), doc.data() + doc.size(), root, collectComments); } -bool Reader::parse(const char* beginDoc, - const char* endDoc, - Value& root, +bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments) { if (!features_.allowComments_) { collectComments = false; @@ -134,8 +119,8 @@ bool Reader::parse(const char* beginDoc, end_ = endDoc; collectComments_ = collectComments; current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; commentsBefore_.clear(); errors_.clear(); while (!nodes_.empty()) @@ -165,9 +150,11 @@ bool Reader::parse(const char* beginDoc, bool Reader::readValue() { // readValue() may call itself only if it calls readObject() or ReadArray(). - // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). - // parse() executes one nodes_.push(), so > instead of >=. - if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); + // These methods execute nodes_.push() just before and nodes_.pop)() just + // after calling readValue(). parse() executes one nodes_.push(), so > instead + // of >=. + if (nodes_.size() > stackLimit_g) + throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; skipCommentTokens(token); @@ -193,30 +180,24 @@ bool Reader::readValue() { case tokenString: successful = decodeString(token); break; - case tokenTrue: - { + case tokenTrue: { Value v(true); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenFalse: - { + } break; + case tokenFalse: { Value v(false); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNull: - { + } break; + case tokenNull: { Value v; currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; + } break; case tokenArraySeparator: case tokenObjectEnd: case tokenArrayEnd: @@ -322,7 +303,7 @@ bool Reader::readToken(Token& token) { if (!ok) token.type_ = tokenError; token.end_ = current_; - return true; + return ok; } void Reader::skipSpaces() { @@ -335,7 +316,7 @@ void Reader::skipSpaces() { } } -bool Reader::match(Location pattern, int patternLength) { +bool Reader::match(const Char* pattern, int patternLength) { if (end_ - current_ < patternLength) return false; int index = patternLength; @@ -369,16 +350,16 @@ bool Reader::readComment() { return true; } -JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { - JSONCPP_STRING normalized; +String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { + String normalized; normalized.reserve(static_cast<size_t>(end - begin)); Reader::Location current = begin; while (current != end) { char c = *current++; if (c == '\r') { if (current != end && *current == '\n') - // convert dos EOL - ++current; + // convert dos EOL + ++current; // convert Mac EOL normalized += '\n'; } else { @@ -388,12 +369,12 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end return normalized; } -void -Reader::addComment(Location begin, Location end, CommentPlacement placement) { +void Reader::addComment(Location begin, Location end, + CommentPlacement placement) { assert(collectComments_); - const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + const String& normalized = normalizeEOL(begin, end); if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); + assert(lastValue_ != nullptr); lastValue_->setComment(normalized, placement); } else { commentsBefore_ += normalized; @@ -426,7 +407,7 @@ bool Reader::readCppStyleComment() { } void Reader::readNumber() { - const char *p = current_; + Location p = current_; char c = '0'; // stopgap for already consumed character // integral part while (c >= '0' && c <= '9') @@ -459,12 +440,12 @@ bool Reader::readString() { return c == '"'; } -bool Reader::readObject(Token& tokenStart) { +bool Reader::readObject(Token& token) { Token tokenName; - JSONCPP_STRING name; + String name; Value init(objectValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); + currentValue().setOffsetStart(token.start_ - begin_); while (readToken(tokenName)) { bool initialTokenOk = true; while (tokenName.type_ == tokenComment && initialTokenOk) @@ -481,15 +462,15 @@ bool Reader::readObject(Token& tokenStart) { Value numberName; if (!decodeNumber(tokenName, numberName)) return recoverFromError(tokenObjectEnd); - name = JSONCPP_STRING(numberName.asCString()); + name = numberName.asString(); } else { break; } Token colon; if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); } Value& value = currentValue()[name]; nodes_.push(&value); @@ -502,8 +483,8 @@ bool Reader::readObject(Token& tokenStart) { if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); } bool finalizeTokenOk = true; while (comma.type_ == tokenComment && finalizeTokenOk) @@ -511,14 +492,14 @@ bool Reader::readObject(Token& tokenStart) { if (comma.type_ == tokenObjectEnd) return true; } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); } -bool Reader::readArray(Token& tokenStart) { +bool Reader::readArray(Token& token) { Value init(arrayValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); + currentValue().setOffsetStart(token.start_ - begin_); skipSpaces(); if (current_ != end_ && *current_ == ']') // empty array { @@ -535,19 +516,19 @@ bool Reader::readArray(Token& tokenStart) { if (!ok) // error already set return recoverFromError(tokenArrayEnd); - Token token; + Token currentToken; // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); } - if (token.type_ == tokenArrayEnd) + if (currentToken.type_ == tokenArrayEnd) break; } return true; @@ -571,7 +552,8 @@ bool Reader::decodeNumber(Token& token, Value& decoded) { bool isNegative = *current == '-'; if (isNegative) ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of them. + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 : Value::maxLargestUInt; @@ -581,7 +563,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) { Char c = *current++; if (c < '0' || c > '9') return decodeDouble(token, decoded); - Value::UInt digit(static_cast<Value::UInt>(c - '0')); + auto digit(static_cast<Value::UInt>(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If // a) we've only just touched the limit, b) this is the last digit, and @@ -617,18 +599,17 @@ bool Reader::decodeDouble(Token& token) { bool Reader::decodeDouble(Token& token, Value& decoded) { double value = 0; - JSONCPP_STRING buffer(token.start_, token.end_); - JSONCPP_ISTRINGSTREAM is(buffer); + String buffer(token.start_, token.end_); + IStringStream is(buffer); if (!(is >> value)) - return addError("'" + JSONCPP_STRING(token.start_, token.end_) + - "' is not a number.", - token); + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); decoded = value; return true; } bool Reader::decodeString(Token& token) { - JSONCPP_STRING decoded_string; + String decoded_string; if (!decodeString(token, decoded_string)) return false; Value decoded(decoded_string); @@ -638,7 +619,7 @@ bool Reader::decodeString(Token& token) { return true; } -bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { +bool Reader::decodeString(Token& token, String& decoded) { decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2)); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' @@ -646,7 +627,7 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { Char c = *current++; if (c == '"') break; - else if (c == '\\') { + if (c == '\\') { if (current == end) return addError("Empty escape sequence in string", token, current); Char escape = *current++; @@ -691,10 +672,8 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { return true; } -bool Reader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { +bool Reader::decodeUnicodeCodePoint(Token& token, Location& current, + Location end, unsigned int& unicode) { if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; @@ -703,10 +682,9 @@ bool Reader::decodeUnicodeCodePoint(Token& token, if (end - current < 6) return addError( "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; + token, current); if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else @@ -714,20 +692,17 @@ bool Reader::decodeUnicodeCodePoint(Token& token, } else return addError("expecting another \\u token to begin the second half of " "a unicode surrogate pair", - token, - current); + token, current); } return true; } -bool Reader::decodeUnicodeEscapeSequence(Token& token, - Location& current, +bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, Location end, unsigned int& ret_unicode) { if (end - current < 4) return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, + "Bad unicode escape sequence in string: four digits expected.", token, current); int unicode = 0; for (int index = 0; index < 4; ++index) { @@ -742,15 +717,13 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token, else return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); + token, current); } ret_unicode = static_cast<unsigned int>(unicode); return true; } -bool -Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) { +bool Reader::addError(const String& message, Token& token, Location extra) { ErrorInfo info; info.token_ = token; info.message_ = message; @@ -772,8 +745,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken) { return false; } -bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, +bool Reader::addErrorAndRecover(const String& message, Token& token, TokenType skipUntilToken) { addError(message, token); return recoverFromError(skipUntilToken); @@ -787,8 +759,7 @@ Reader::Char Reader::getNextChar() { return *current_++; } -void Reader::getLocationLineAndColumn(Location location, - int& line, +void Reader::getLocationLineAndColumn(Location location, int& line, int& column) const { Location current = begin_; Location lastLineStart = current; @@ -810,25 +781,22 @@ void Reader::getLocationLineAndColumn(Location location, ++line; } -JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const { +String Reader::getLocationLineAndColumn(Location location) const { int line, column; getLocationLineAndColumn(location, line, column); char buffer[18 + 16 + 16 + 1]; - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); return buffer; } // Deprecated. Preserved for backward compatibility -JSONCPP_STRING Reader::getFormatedErrorMessages() const { +String Reader::getFormatedErrorMessages() const { return getFormattedErrorMessages(); } -JSONCPP_STRING Reader::getFormattedErrorMessages() const { - JSONCPP_STRING formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; +String Reader::getFormattedErrorMessages() const { + String formattedMessage; + for (const auto& error : errors_) { formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; @@ -841,10 +809,7 @@ JSONCPP_STRING Reader::getFormattedErrorMessages() const { std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { std::vector<Reader::StructuredError> allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; + for (const auto& error : errors_) { Reader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; @@ -854,28 +819,27 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { return allErrors; } -bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) { +bool Reader::pushError(const Value& value, const String& message) { ptrdiff_t const length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length) + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); + token.end_ = begin_ + value.getOffsetLimit(); ErrorInfo info; info.token_ = token; info.message_ = message; - info.extra_ = 0; + info.extra_ = nullptr; errors_.push_back(info); return true; } -bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) { +bool Reader::pushError(const Value& value, const String& message, + const Value& extra) { ptrdiff_t const length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length - || extra.getOffsetLimit() > length) + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; @@ -889,15 +853,15 @@ bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const return true; } -bool Reader::good() const { - return !errors_.size(); -} +bool Reader::good() const { return errors_.empty(); } -// exact copy of Features +// Originally copied from the Features class (now deprecated), used internally +// for features implementation. class OurFeatures { public: static OurFeatures all(); bool allowComments_; + bool allowTrailingCommas_; bool strictRoot_; bool allowDroppedNullPlaceholders_; bool allowNumericKeys_; @@ -905,42 +869,36 @@ class OurFeatures { bool failIfExtra_; bool rejectDupKeys_; bool allowSpecialFloats_; - int stackLimit_; -}; // OurFeatures + bool skipBom_; + size_t stackLimit_; +}; // OurFeatures -// exact copy of Implementation of class Features -// //////////////////////////////// - -OurFeatures OurFeatures::all() { return OurFeatures(); } +OurFeatures OurFeatures::all() { return {}; } // Implementation of class Reader // //////////////////////////////// -// exact copy of Reader, renamed to OurReader +// Originally copied from the Reader class (now deprecated), used internally +// for implementing JSON reading. class OurReader { public: - typedef char Char; - typedef const Char* Location; + using Char = char; + using Location = const Char*; struct StructuredError { ptrdiff_t offset_start; ptrdiff_t offset_limit; - JSONCPP_STRING message; + String message; }; - OurReader(OurFeatures const& features); - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, + explicit OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); - JSONCPP_STRING getFormattedErrorMessages() const; + String getFormattedErrorMessages() const; std::vector<StructuredError> getStructuredErrors() const; - bool pushError(const Value& value, const JSONCPP_STRING& message); - bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra); - bool good() const; private: - OurReader(OurReader const&); // no impl - void operator=(OurReader const&); // no impl + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl enum TokenType { tokenEndOfStream = 0, @@ -972,17 +930,18 @@ class OurReader { class ErrorInfo { public: Token token_; - JSONCPP_STRING message_; + String message_; Location extra_; }; - typedef std::deque<ErrorInfo> Errors; + using Errors = std::deque<ErrorInfo>; bool readToken(Token& token); void skipSpaces(); - bool match(Location pattern, int patternLength); + void skipBom(bool skipBom); + bool match(const Char* pattern, int patternLength); bool readComment(); - bool readCStyleComment(); + bool readCStyleComment(bool* containsNewLineResult); bool readCppStyleComment(); bool readString(); bool readStringSingleQuote(); @@ -993,68 +952,57 @@ class OurReader { bool decodeNumber(Token& token); bool decodeNumber(Token& token, Value& decoded); bool decodeString(Token& token); - bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeString(Token& token, String& decoded); bool decodeDouble(Token& token); bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, + bool addErrorAndRecover(const String& message, Token& token, TokenType skipUntilToken); void skipUntilSpace(); Value& currentValue(); Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); void skipCommentTokens(Token& token); - static JSONCPP_STRING normalizeEOL(Location begin, Location end); + static String normalizeEOL(Location begin, Location end); static bool containsNewLine(Location begin, Location end); - typedef std::stack<Value*> Nodes; - Nodes nodes_; - Errors errors_; - JSONCPP_STRING document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - JSONCPP_STRING commentsBefore_; + using Nodes = std::stack<Value*>; + + Nodes nodes_{}; + Errors errors_{}; + String document_{}; + Location begin_ = nullptr; + Location end_ = nullptr; + Location current_ = nullptr; + Location lastValueEnd_ = nullptr; + Value* lastValue_ = nullptr; + bool lastValueHasAComment_ = false; + String commentsBefore_{}; OurFeatures const features_; - bool collectComments_; -}; // OurReader + bool collectComments_ = false; +}; // OurReader // complete copy of Read impl, for OurReader -bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; +bool OurReader::containsNewLine(OurReader::Location begin, + OurReader::Location end) { + return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); } -OurReader::OurReader(OurFeatures const& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), - features_(features), collectComments_() { -} +OurReader::OurReader(OurFeatures const& features) : features_(features) {} -bool OurReader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { +bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments) { if (!features_.allowComments_) { collectComments = false; } @@ -1063,22 +1011,23 @@ bool OurReader::parse(const char* beginDoc, end_ = endDoc; collectComments_ = collectComments; current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; commentsBefore_.clear(); errors_.clear(); while (!nodes_.empty()) nodes_.pop(); nodes_.push(&root); + // skip byte order mark if it exists at the beginning of the UTF-8 text. + skipBom(features_.skipBom_); bool successful = readValue(); + nodes_.pop(); Token token; skipCommentTokens(token); - if (features_.failIfExtra_) { - if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) { - addError("Extra non-whitespace after JSON value.", token); - return false; - } + if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) { + addError("Extra non-whitespace after JSON value.", token); + return false; } if (collectComments_ && !commentsBefore_.empty()) root.setComment(commentsBefore_, commentAfter); @@ -1100,7 +1049,8 @@ bool OurReader::parse(const char* beginDoc, bool OurReader::readValue() { // To preserve the old behaviour we cast size_t to int. - if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); + if (nodes_.size() > features_.stackLimit_) + throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; skipCommentTokens(token); bool successful = true; @@ -1125,54 +1075,42 @@ bool OurReader::readValue() { case tokenString: successful = decodeString(token); break; - case tokenTrue: - { + case tokenTrue: { Value v(true); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenFalse: - { + } break; + case tokenFalse: { Value v(false); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNull: - { + } break; + case tokenNull: { Value v; currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNaN: - { + } break; + case tokenNaN: { Value v(std::numeric_limits<double>::quiet_NaN()); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenPosInf: - { + } break; + case tokenPosInf: { Value v(std::numeric_limits<double>::infinity()); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNegInf: - { + } break; + case tokenNegInf: { Value v(-std::numeric_limits<double>::infinity()); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; + } break; case tokenArraySeparator: case tokenObjectEnd: case tokenArrayEnd: @@ -1194,6 +1132,7 @@ bool OurReader::readValue() { if (collectComments_) { lastValueEnd_ = current_; + lastValueHasAComment_ = false; lastValue_ = ¤tValue(); } @@ -1234,10 +1173,13 @@ bool OurReader::readToken(Token& token) { break; case '\'': if (features_.allowSingleQuotes_) { - token.type_ = tokenString; - ok = readStringSingleQuote(); + token.type_ = tokenString; + ok = readStringSingleQuote(); + } else { + // If we don't allow single quotes, this is a failure case. + ok = false; + } break; - } // else continue case '/': token.type_ = tokenComment; ok = readComment(); @@ -1263,6 +1205,14 @@ bool OurReader::readToken(Token& token) { ok = features_.allowSpecialFloats_ && match("nfinity", 7); } break; + case '+': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenPosInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; case 't': token.type_ = tokenTrue; ok = match("rue", 3); @@ -1307,7 +1257,7 @@ bool OurReader::readToken(Token& token) { if (!ok) token.type_ = tokenError; token.end_ = current_; - return true; + return ok; } void OurReader::skipSpaces() { @@ -1320,7 +1270,17 @@ void OurReader::skipSpaces() { } } -bool OurReader::match(Location pattern, int patternLength) { +void OurReader::skipBom(bool skipBom) { + // The default behavior is to skip BOM. + if (skipBom) { + if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) { + begin_ += 3; + current_ = begin_; + } + } +} + +bool OurReader::match(const Char* pattern, int patternLength) { if (end_ - current_ < patternLength) return false; int index = patternLength; @@ -1332,21 +1292,32 @@ bool OurReader::match(Location pattern, int patternLength) { } bool OurReader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); + const Location commentBegin = current_ - 1; + const Char c = getNextChar(); bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') + bool cStyleWithEmbeddedNewline = false; + + const bool isCStyleComment = (c == '*'); + const bool isCppStyleComment = (c == '/'); + if (isCStyleComment) { + successful = readCStyleComment(&cStyleWithEmbeddedNewline); + } else if (isCppStyleComment) { successful = readCppStyleComment(); + } + if (!successful) return false; if (collectComments_) { CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; + + if (!lastValueHasAComment_) { + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (isCppStyleComment || !cStyleWithEmbeddedNewline) { + placement = commentAfterOnSameLine; + lastValueHasAComment_ = true; + } + } } addComment(commentBegin, current_, placement); @@ -1354,16 +1325,17 @@ bool OurReader::readComment() { return true; } -JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) { - JSONCPP_STRING normalized; +String OurReader::normalizeEOL(OurReader::Location begin, + OurReader::Location end) { + String normalized; normalized.reserve(static_cast<size_t>(end - begin)); OurReader::Location current = begin; while (current != end) { char c = *current++; if (c == '\r') { if (current != end && *current == '\n') - // convert dos EOL - ++current; + // convert dos EOL + ++current; // convert Mac EOL normalized += '\n'; } else { @@ -1373,24 +1345,29 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc return normalized; } -void -OurReader::addComment(Location begin, Location end, CommentPlacement placement) { +void OurReader::addComment(Location begin, Location end, + CommentPlacement placement) { assert(collectComments_); - const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + const String& normalized = normalizeEOL(begin, end); if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); + assert(lastValue_ != nullptr); lastValue_->setComment(normalized, placement); } else { commentsBefore_ += normalized; } } -bool OurReader::readCStyleComment() { +bool OurReader::readCStyleComment(bool* containsNewLineResult) { + *containsNewLineResult = false; + while ((current_ + 1) < end_) { Char c = getNextChar(); if (c == '*' && *current_ == '/') break; + if (c == '\n') + *containsNewLineResult = true; } + return getNextChar() == '/'; } @@ -1411,7 +1388,7 @@ bool OurReader::readCppStyleComment() { } bool OurReader::readNumber(bool checkInf) { - const char *p = current_; + Location p = current_; if (checkInf && p != end_ && *p == 'I') { current_ = ++p; return false; @@ -1448,7 +1425,6 @@ bool OurReader::readString() { return c == '"'; } - bool OurReader::readStringSingleQuote() { Char c = 0; while (current_ != end_) { @@ -1461,19 +1437,21 @@ bool OurReader::readStringSingleQuote() { return c == '\''; } -bool OurReader::readObject(Token& tokenStart) { +bool OurReader::readObject(Token& token) { Token tokenName; - JSONCPP_STRING name; + String name; Value init(objectValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); + currentValue().setOffsetStart(token.start_ - begin_); while (readToken(tokenName)) { bool initialTokenOk = true; while (tokenName.type_ == tokenComment && initialTokenOk) initialTokenOk = readToken(tokenName); if (!initialTokenOk) break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + if (tokenName.type_ == tokenObjectEnd && + (name.empty() || + features_.allowTrailingCommas_)) // empty object or trailing comma return true; name.clear(); if (tokenName.type_ == tokenString) { @@ -1487,17 +1465,17 @@ bool OurReader::readObject(Token& tokenStart) { } else { break; } + if (name.length() >= (1U << 30)) + throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + String msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover(msg, tokenName, tokenObjectEnd); + } Token colon; if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); - } - if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); - if (features_.rejectDupKeys_ && currentValue().isMember(name)) { - JSONCPP_STRING msg = "Duplicate key: '" + name + "'"; - return addErrorAndRecover( - msg, tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); } Value& value = currentValue()[name]; nodes_.push(&value); @@ -1510,8 +1488,8 @@ bool OurReader::readObject(Token& tokenStart) { if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); } bool finalizeTokenOk = true; while (comma.type_ == tokenComment && finalizeTokenOk) @@ -1519,23 +1497,27 @@ bool OurReader::readObject(Token& tokenStart) { if (comma.type_ == tokenObjectEnd) return true; } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); } -bool OurReader::readArray(Token& tokenStart) { +bool OurReader::readArray(Token& token) { Value init(arrayValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - skipSpaces(); - if (current_ != end_ && *current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } + currentValue().setOffsetStart(token.start_ - begin_); int index = 0; for (;;) { + skipSpaces(); + if (current_ != end_ && *current_ == ']' && + (index == 0 || + (features_.allowTrailingCommas_ && + !features_.allowDroppedNullPlaceholders_))) // empty array or trailing + // comma + { + Token endArray; + readToken(endArray); + return true; + } Value& value = currentValue()[index++]; nodes_.push(&value); bool ok = readValue(); @@ -1543,19 +1525,19 @@ bool OurReader::readArray(Token& tokenStart) { if (!ok) // error already set return recoverFromError(tokenArrayEnd); - Token token; + Token currentToken; // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); } - if (token.type_ == tokenArrayEnd) + if (currentToken.type_ == tokenArrayEnd) break; } return true; @@ -1576,38 +1558,78 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // larger than the maximum supported value of an integer then // we decode the number as a double. Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) + const bool isNegative = *current == '-'; + if (isNegative) { ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(-Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; + } + + // We assume we can represent the largest and smallest integer types as + // unsigned integers with separate sign. This is only true if they can fit + // into an unsigned integer. + static_assert(Value::maxLargestInt <= Value::maxLargestUInt, + "Int must be smaller than UInt"); + + // We need to convert minLargestInt into a positive number. The easiest way + // to do this conversion is to assume our "threshold" value of minLargestInt + // divided by 10 can fit in maxLargestInt when absolute valued. This should + // be a safe assumption. + static_assert(Value::minLargestInt <= -Value::maxLargestInt, + "The absolute value of minLargestInt must be greater than or " + "equal to maxLargestInt"); + static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, + "The absolute value of minLargestInt must be only 1 magnitude " + "larger than maxLargest Int"); + + static constexpr Value::LargestUInt positive_threshold = + Value::maxLargestUInt / 10; + static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10; + + // For the negative values, we have to be more careful. Since typically + // -Value::minLargestInt will cause an overflow, we first divide by 10 and + // then take the inverse. This assumes that minLargestInt is only a single + // power of 10 different in magnitude, which we check above. For the last + // digit, we take the modulus before negating for the same reason. + static constexpr auto negative_threshold = + Value::LargestUInt(-(Value::minLargestInt / 10)); + static constexpr auto negative_last_digit = + Value::UInt(-(Value::minLargestInt % 10)); + + const Value::LargestUInt threshold = + isNegative ? negative_threshold : positive_threshold; + const Value::UInt max_last_digit = + isNegative ? negative_last_digit : positive_last_digit; + Value::LargestUInt value = 0; while (current < token.end_) { Char c = *current++; if (c < '0' || c > '9') return decodeDouble(token, decoded); - Value::UInt digit(static_cast<Value::UInt>(c - '0')); + + const auto digit(static_cast<Value::UInt>(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and + // a) we've only just touched the limit, meaing value == threshold, + // b) this is the last digit, or // c) it's small enough to fit in that rounding delta, we're okay. // Otherwise treat this number as a double to avoid overflow. if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { + digit > max_last_digit) { return decodeDouble(token, decoded); } } value = value * 10 + digit; } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) + + if (isNegative) { + // We use the same magnitude assumption here, just in case. + const auto last_digit = static_cast<Value::UInt>(value % 10); + decoded = -Value::LargestInt(value / 10) * 10 - last_digit; + } else if (value <= Value::LargestUInt(Value::maxLargestInt)) { decoded = Value::LargestInt(value); - else + } else { decoded = value; + } + return true; } @@ -1623,44 +1645,18 @@ bool OurReader::decodeDouble(Token& token) { bool OurReader::decodeDouble(Token& token, Value& decoded) { double value = 0; - const int bufferSize = 32; - int count; - ptrdiff_t const length = token.end_ - token.start_; - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - size_t const ulength = static_cast<size_t>(length); - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, ulength); - buffer[length] = 0; - fixNumericLocaleInput(buffer, buffer + length); - count = sscanf(buffer, format, &value); - } else { - JSONCPP_STRING buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); + const String buffer(token.start_, token.end_); + IStringStream is(buffer); + if (!(is >> value)) { + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); } - - if (count != 1) - return addError("'" + JSONCPP_STRING(token.start_, token.end_) + - "' is not a number.", - token); decoded = value; return true; } bool OurReader::decodeString(Token& token) { - JSONCPP_STRING decoded_string; + String decoded_string; if (!decodeString(token, decoded_string)) return false; Value decoded(decoded_string); @@ -1670,7 +1666,7 @@ bool OurReader::decodeString(Token& token) { return true; } -bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { +bool OurReader::decodeString(Token& token, String& decoded) { decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2)); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' @@ -1678,7 +1674,7 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { Char c = *current++; if (c == '"') break; - else if (c == '\\') { + if (c == '\\') { if (current == end) return addError("Empty escape sequence in string", token, current); Char escape = *current++; @@ -1723,10 +1719,8 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { return true; } -bool OurReader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { +bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current, + Location end, unsigned int& unicode) { if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; @@ -1735,10 +1729,9 @@ bool OurReader::decodeUnicodeCodePoint(Token& token, if (end - current < 6) return addError( "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; + token, current); if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else @@ -1746,20 +1739,17 @@ bool OurReader::decodeUnicodeCodePoint(Token& token, } else return addError("expecting another \\u token to begin the second half of " "a unicode surrogate pair", - token, - current); + token, current); } return true; } -bool OurReader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& ret_unicode) { +bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, + unsigned int& ret_unicode) { if (end - current < 4) return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, + "Bad unicode escape sequence in string: four digits expected.", token, current); int unicode = 0; for (int index = 0; index < 4; ++index) { @@ -1774,15 +1764,13 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token, else return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); + token, current); } ret_unicode = static_cast<unsigned int>(unicode); return true; } -bool -OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) { +bool OurReader::addError(const String& message, Token& token, Location extra) { ErrorInfo info; info.token_ = token; info.message_ = message; @@ -1804,9 +1792,8 @@ bool OurReader::recoverFromError(TokenType skipUntilToken) { return false; } -bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, - TokenType skipUntilToken) { +bool OurReader::addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken) { addError(message, token); return recoverFromError(skipUntilToken); } @@ -1819,9 +1806,8 @@ OurReader::Char OurReader::getNextChar() { return *current_++; } -void OurReader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { +void OurReader::getLocationLineAndColumn(Location location, int& line, + int& column) const { Location current = begin_; Location lastLineStart = current; line = 0; @@ -1842,20 +1828,17 @@ void OurReader::getLocationLineAndColumn(Location location, ++line; } -JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const { +String OurReader::getLocationLineAndColumn(Location location) const { int line, column; getLocationLineAndColumn(location, line, column); char buffer[18 + 16 + 16 + 1]; - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); return buffer; } -JSONCPP_STRING OurReader::getFormattedErrorMessages() const { - JSONCPP_STRING formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; +String OurReader::getFormattedErrorMessages() const { + String formattedMessage; + for (const auto& error : errors_) { formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; @@ -1868,10 +1851,7 @@ JSONCPP_STRING OurReader::getFormattedErrorMessages() const { std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { std::vector<OurReader::StructuredError> allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; + for (const auto& error : errors_) { OurReader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; @@ -1881,59 +1861,15 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { return allErrors; } -bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) { - ptrdiff_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = 0; - errors_.push_back(info); - return true; -} - -bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) { - ptrdiff_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length - || extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool OurReader::good() const { - return !errors_.size(); -} - - class OurCharReader : public CharReader { bool const collectComments_; OurReader reader_; + public: - OurCharReader( - bool collectComments, - OurFeatures const& features) - : collectComments_(collectComments) - , reader_(features) - {} - bool parse( - char const* beginDoc, char const* endDoc, - Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE { + OurCharReader(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) override { bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); if (errs) { *errs = reader_.getFormattedErrorMessages(); @@ -1942,67 +1878,64 @@ class OurCharReader : public CharReader { } }; -CharReaderBuilder::CharReaderBuilder() -{ - setDefaults(&settings_); -} -CharReaderBuilder::~CharReaderBuilder() -{} -CharReader* CharReaderBuilder::newCharReader() const -{ +CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } +CharReaderBuilder::~CharReaderBuilder() = default; +CharReader* CharReaderBuilder::newCharReader() const { bool collectComments = settings_["collectComments"].asBool(); OurFeatures features = OurFeatures::all(); features.allowComments_ = settings_["allowComments"].asBool(); + features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool(); features.strictRoot_ = settings_["strictRoot"].asBool(); - features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowDroppedNullPlaceholders_ = + settings_["allowDroppedNullPlaceholders"].asBool(); features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); - features.stackLimit_ = settings_["stackLimit"].asInt(); + + // Stack limit is always a size_t, so we get this as an unsigned int + // regardless of it we have 64-bit integer support enabled. + features.stackLimit_ = static_cast<size_t>(settings_["stackLimit"].asUInt()); features.failIfExtra_ = settings_["failIfExtra"].asBool(); features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); + features.skipBom_ = settings_["skipBom"].asBool(); return new OurCharReader(collectComments, features); } -static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys) -{ - valid_keys->clear(); - valid_keys->insert("collectComments"); - valid_keys->insert("allowComments"); - valid_keys->insert("strictRoot"); - valid_keys->insert("allowDroppedNullPlaceholders"); - valid_keys->insert("allowNumericKeys"); - valid_keys->insert("allowSingleQuotes"); - valid_keys->insert("stackLimit"); - valid_keys->insert("failIfExtra"); - valid_keys->insert("rejectDupKeys"); - valid_keys->insert("allowSpecialFloats"); -} -bool CharReaderBuilder::validate(Json::Value* invalid) const -{ - Json::Value my_invalid; - if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set<JSONCPP_STRING> valid_keys; - getValidReaderKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - JSONCPP_STRING const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } + +bool CharReaderBuilder::validate(Json::Value* invalid) const { + static const auto& valid_keys = *new std::set<String>{ + "collectComments", + "allowComments", + "allowTrailingCommas", + "strictRoot", + "allowDroppedNullPlaceholders", + "allowNumericKeys", + "allowSingleQuotes", + "stackLimit", + "failIfExtra", + "rejectDupKeys", + "allowSpecialFloats", + "skipBom", + }; + for (auto si = settings_.begin(); si != settings_.end(); ++si) { + auto key = si.name(); + if (valid_keys.count(key)) + continue; + if (invalid) + (*invalid)[std::move(key)] = *si; + else + return false; } - return 0u == inv.size(); + return invalid ? invalid->empty() : true; } -Value& CharReaderBuilder::operator[](JSONCPP_STRING key) -{ + +Value& CharReaderBuilder::operator[](const String& key) { return settings_[key]; } // static -void CharReaderBuilder::strictMode(Json::Value* settings) -{ -//! [CharReaderBuilderStrictMode] +void CharReaderBuilder::strictMode(Json::Value* settings) { + //! [CharReaderBuilderStrictMode] (*settings)["allowComments"] = false; + (*settings)["allowTrailingCommas"] = false; (*settings)["strictRoot"] = true; (*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowNumericKeys"] = false; @@ -2011,14 +1944,15 @@ void CharReaderBuilder::strictMode(Json::Value* settings) (*settings)["failIfExtra"] = true; (*settings)["rejectDupKeys"] = true; (*settings)["allowSpecialFloats"] = false; -//! [CharReaderBuilderStrictMode] + (*settings)["skipBom"] = true; + //! [CharReaderBuilderStrictMode] } // static -void CharReaderBuilder::setDefaults(Json::Value* settings) -{ -//! [CharReaderBuilderDefaults] +void CharReaderBuilder::setDefaults(Json::Value* settings) { + //! [CharReaderBuilderDefaults] (*settings)["collectComments"] = true; (*settings)["allowComments"] = true; + (*settings)["allowTrailingCommas"] = true; (*settings)["strictRoot"] = false; (*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowNumericKeys"] = false; @@ -2027,19 +1961,18 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) (*settings)["failIfExtra"] = false; (*settings)["rejectDupKeys"] = false; (*settings)["allowSpecialFloats"] = false; -//! [CharReaderBuilderDefaults] + (*settings)["skipBom"] = true; + //! [CharReaderBuilderDefaults] } ////////////////////////////////// // global functions -bool parseFromStream( - CharReader::Factory const& fact, JSONCPP_ISTREAM& sin, - Value* root, JSONCPP_STRING* errs) -{ - JSONCPP_OSTRINGSTREAM ssin; +bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root, + String* errs) { + OStringStream ssin; ssin << sin.rdbuf(); - JSONCPP_STRING doc = ssin.str(); + String doc = ssin.str(); char const* begin = doc.data(); char const* end = begin + doc.size(); // Note that we do not actually need a null-terminator. @@ -2047,15 +1980,11 @@ bool parseFromStream( return reader->parse(begin, end, root, errs); } -JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) { +IStream& operator>>(IStream& sin, Value& root) { CharReaderBuilder b; - JSONCPP_STRING errs; + String errs; bool ok = parseFromStream(b, sin, &root, &errs); if (!ok) { - fprintf(stderr, - "Error from reader: %s", - errs.c_str()); - throwRuntimeError(errs); } return sin; diff --git a/src/lib_json/json_tool.h b/src/lib_json/json_tool.h index 431617830ce..2d7b7d9a003 100644 --- a/src/lib_json/json_tool.h +++ b/src/lib_json/json_tool.h @@ -6,6 +6,9 @@ #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#if !defined(JSON_IS_AMALGAMATION) +#include <json/config.h> +#endif // Also support old flag NO_LOCALE_SUPPORT #ifdef NO_LOCALE_SUPPORT @@ -23,7 +26,7 @@ */ namespace Json { -static char getDecimalPoint() { +static inline char getDecimalPoint() { #ifdef JSONCPP_NO_LOCALE_SUPPORT return '\0'; #else @@ -33,8 +36,8 @@ static char getDecimalPoint() { } /// Converts a unicode code-point to UTF-8. -static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) { - JSONCPP_STRING result; +static inline String codePointToUTF8(unsigned int cp) { + String result; // based on description from http://en.wikipedia.org/wiki/UTF-8 @@ -61,9 +64,6 @@ static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) { return result; } -/// Returns true if ch is a control character (in range [1,31]). -static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } - enum { /// Constant that specify the size of the buffer that must be passed to /// uintToString. @@ -71,10 +71,10 @@ enum { }; // Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; +using UIntToStringBuffer = char[uintToStringBufferSize]; /** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string + * @param value Unsigned integer to convert to string * @param current Input/Output string buffer. * Must have at least uintToStringBufferSize chars free. */ @@ -91,27 +91,44 @@ static inline void uintToString(LargestUInt value, char*& current) { * We had a sophisticated way, but it did not work in WinCE. * @see https://github.com/open-source-parsers/jsoncpp/pull/9 */ -static inline void fixNumericLocale(char* begin, char* end) { - while (begin < end) { +template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) { + for (; begin != end; ++begin) { if (*begin == ',') { *begin = '.'; } - ++begin; } + return begin; } -static inline void fixNumericLocaleInput(char* begin, char* end) { +template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) { char decimalPoint = getDecimalPoint(); - if (decimalPoint != '\0' && decimalPoint != '.') { - while (begin < end) { - if (*begin == '.') { - *begin = decimalPoint; - } - ++begin; + if (decimalPoint == '\0' || decimalPoint == '.') { + return; + } + for (; begin != end; ++begin) { + if (*begin == '.') { + *begin = decimalPoint; + } + } +} + +/** + * Return iterator that would be the new end of the range [begin,end), if we + * were to delete zeros in the end of string, but not the last zero before '.'. + */ +template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) { + for (; begin != end; --end) { + if (*(end - 1) != '0') { + return end; + } + // Don't delete the last zero before the decimal point. + if (begin != (end - 1) && *(end - 2) == '.') { + return end; } } + return end; } -} // namespace Json { +} // namespace Json #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 2a53138bca0..0872ff54872 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -8,20 +8,54 @@ #include <json/value.h> #include <json/writer.h> #endif // if !defined(JSON_IS_AMALGAMATION) -#include <math.h> +#include <algorithm> +#include <cassert> +#include <cmath> +#include <cstddef> +#include <cstring> +#include <iostream> #include <sstream> #include <utility> -#include <cstring> -#include <cassert> -#ifdef JSON_USE_CPPTL -#include <cpptl/conststring.h> + +// Provide implementation equivalent of std::snprintf for older _MSC compilers +#if defined(_MSC_VER) && _MSC_VER < 1900 +#include <stdarg.h> +static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size, + const char* format, va_list ap) { + int count = -1; + if (size != 0) + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + return count; +} + +int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...) { + va_list ap; + va_start(ap, format); + const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + return count; +} +#endif + +// Disable warning C4702 : unreachable code +#if defined(_MSC_VER) +#pragma warning(disable : 4702) #endif -#include <cstddef> // size_t -#include <algorithm> // min() #define JSON_ASSERT_UNREACHABLE assert(false) namespace Json { +template <typename T> +static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) { + std::unique_ptr<T> r; + if (p) { + r = std::unique_ptr<T>(new T(*p)); + } + return r; +} // This is a walkaround to avoid the static initialization of Value::null. // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of @@ -31,50 +65,34 @@ namespace Json { #else #define ALIGNAS(byte_alignment) #endif -//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -//const unsigned char& kNullRef = kNull[0]; -//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef); -//const Value& Value::nullRef = null; // static -Value const& Value::nullSingleton() -{ - static Value const nullStatic; - return nullStatic; +Value const& Value::nullSingleton() { + static Value const nullStatic; + return nullStatic; } -// for backwards compatibility, we'll leave these global references around, but DO NOT -// use them in JSONCPP library code any more! +#if JSON_USE_NULLREF +// for backwards compatibility, we'll leave these global references around, but +// DO NOT use them in JSONCPP library code any more! +// static Value const& Value::null = Value::nullSingleton(); -Value const& Value::nullRef = Value::nullSingleton(); -const Int Value::minInt = Int(~(UInt(-1) / 2)); -const Int Value::maxInt = Int(UInt(-1) / 2); -const UInt Value::maxUInt = UInt(-1); -#if defined(JSON_HAS_INT64) -const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); -const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); -const UInt64 Value::maxUInt64 = UInt64(-1); -// The constant is hard-coded because some compiler have trouble -// converting Value::maxUInt64 to a double correctly (AIX/xlC). -// Assumes that UInt64 is a 64 bits integer. -static const double maxUInt64AsDouble = 18446744073709551615.0; -#endif // defined(JSON_HAS_INT64) -const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); -const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); +// static +Value const& Value::nullRef = Value::nullSingleton(); +#endif #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) template <typename T, typename U> static inline bool InRange(double d, T min, U max) { // The casts can lose precision, but we are looking only for // an approximate range. Might fail on edge cases though. ~cdunn - //return d >= static_cast<double>(min) && d <= static_cast<double>(max); - return d >= min && d <= max; + return d >= static_cast<double>(min) && d <= static_cast<double>(max); } #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) static inline double integerToDouble(Json::UInt64 value) { - return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1)); + return static_cast<double>(Int64(value / 2)) * 2.0 + + static_cast<double>(Int64(value & 1)); } template <typename T> static inline double integerToDouble(T value) { @@ -94,19 +112,16 @@ static inline bool InRange(double d, T min, U max) { * computed using strlen(value). * @return Pointer on the duplicate instance of string. */ -static inline char* duplicateStringValue(const char* value, - size_t length) -{ +static inline char* duplicateStringValue(const char* value, size_t length) { // Avoid an integer overflow in the call to malloc below by limiting length // to a sane value. if (length >= static_cast<size_t>(Value::maxInt)) length = Value::maxInt - 1; - char* newString = static_cast<char*>(malloc(length + 1)); - if (newString == NULL) { - throwRuntimeError( - "in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); + auto newString = static_cast<char*>(malloc(length + 1)); + if (newString == nullptr) { + throwRuntimeError("in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); } memcpy(newString, value, length); newString[length] = 0; @@ -115,31 +130,28 @@ static inline char* duplicateStringValue(const char* value, /* Record the length as a prefix. */ -static inline char* duplicateAndPrefixStringValue( - const char* value, - unsigned int length) -{ +static inline char* duplicateAndPrefixStringValue(const char* value, + unsigned int length) { // Avoid an integer overflow in the call to malloc below by limiting length // to a sane value. - JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U, + JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - + sizeof(unsigned) - 1U, "in Json::Value::duplicateAndPrefixStringValue(): " "length too big for prefixing"); - unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U; - char* newString = static_cast<char*>(malloc(actualLength)); - if (newString == 0) { - throwRuntimeError( - "in Json::Value::duplicateAndPrefixStringValue(): " - "Failed to allocate string value buffer"); + size_t actualLength = sizeof(length) + length + 1; + auto newString = static_cast<char*>(malloc(actualLength)); + if (newString == nullptr) { + throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); } *reinterpret_cast<unsigned*>(newString) = length; memcpy(newString + sizeof(unsigned), value, length); - newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later + newString[actualLength - 1U] = + 0; // to avoid buffer over-run accidents by users later return newString; } -inline static void decodePrefixedString( - bool isPrefixed, char const* prefixed, - unsigned* length, char const** value) -{ +inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, + unsigned* length, char const** value) { if (!isPrefixed) { *length = static_cast<unsigned>(strlen(prefixed)); *value = prefixed; @@ -148,7 +160,8 @@ inline static void decodePrefixedString( *value = prefixed + sizeof(unsigned); } } -/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). +/** Free the string duplicated by + * duplicateStringValue()/duplicateAndPrefixStringValue(). */ #if JSONCPP_USING_SECURE_MEMORY static inline void releasePrefixedStringValue(char* value) { @@ -161,17 +174,13 @@ static inline void releasePrefixedStringValue(char* value) { } static inline void releaseStringValue(char* value, unsigned length) { // length==0 => we allocated the strings memory - size_t size = (length==0) ? strlen(value) : length; + size_t size = (length == 0) ? strlen(value) : length; memset(value, 0, size); free(value); } -#else // !JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) { - free(value); -} -static inline void releaseStringValue(char* value, unsigned) { - free(value); -} +#else // !JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { free(value); } +static inline void releaseStringValue(char* value, unsigned) { free(value); } #endif // JSONCPP_USING_SECURE_MEMORY } // namespace Json @@ -190,58 +199,28 @@ static inline void releaseStringValue(char* value, unsigned) { namespace Json { -Exception::Exception(JSONCPP_STRING const& msg) - : msg_(msg) -{} -Exception::~Exception() JSONCPP_NOEXCEPT -{} -char const* Exception::what() const JSONCPP_NOEXCEPT -{ - return msg_.c_str(); -} -RuntimeError::RuntimeError(JSONCPP_STRING const& msg) - : Exception(msg) -{} -LogicError::LogicError(JSONCPP_STRING const& msg) - : Exception(msg) -{} -JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg) -{ +#if JSON_USE_EXCEPTION +Exception::Exception(String msg) : msg_(std::move(msg)) {} +Exception::~Exception() noexcept = default; +char const* Exception::what() const noexcept { return msg_.c_str(); } +RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} +LogicError::LogicError(String const& msg) : Exception(msg) {} +JSONCPP_NORETURN void throwRuntimeError(String const& msg) { throw RuntimeError(msg); } -JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg) -{ +JSONCPP_NORETURN void throwLogicError(String const& msg) { throw LogicError(msg); } - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Value::CommentInfo::CommentInfo() : comment_(0) -{} - -Value::CommentInfo::~CommentInfo() { - if (comment_) - releaseStringValue(comment_, 0u); +#else // !JSON_USE_EXCEPTION +JSONCPP_NORETURN void throwRuntimeError(String const& msg) { + std::cerr << msg << std::endl; + abort(); } - -void Value::CommentInfo::setComment(const char* text, size_t len) { - if (comment_) { - releaseStringValue(comment_, 0u); - comment_ = 0; - } - JSON_ASSERT(text != 0); - JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue(text, len); +JSONCPP_NORETURN void throwLogicError(String const& msg) { + std::cerr << msg << std::endl; + abort(); } +#endif // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -254,36 +233,44 @@ void Value::CommentInfo::setComment(const char* text, size_t len) { // Notes: policy_ indicates if the string was allocated when // a string is stored. -Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} +Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {} -Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) +Value::CZString::CZString(char const* str, unsigned length, + DuplicationPolicy allocate) : cstr_(str) { // allocate != duplicate storage_.policy_ = allocate & 0x3; - storage_.length_ = ulength & 0x3FFFFFFF; + storage_.length_ = length & 0x3FFFFFFF; } Value::CZString::CZString(const CZString& other) { - cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue(other.cstr_, other.storage_.length_) - : other.cstr_); - storage_.policy_ = static_cast<unsigned>(other.cstr_ - ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication - ? noDuplication : duplicate) - : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U; + cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_); + storage_.policy_ = + static_cast<unsigned>( + other.cstr_ + ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == + noDuplication + ? noDuplication + : duplicate) + : static_cast<DuplicationPolicy>(other.storage_.policy_)) & + 3U; storage_.length_ = other.storage_.length_; } -#if JSON_HAS_RVALUE_REFERENCES Value::CZString::CZString(CZString&& other) - : cstr_(other.cstr_), index_(other.index_) { + : cstr_(other.cstr_), index_(other.index_) { other.cstr_ = nullptr; } -#endif Value::CZString::~CZString() { if (cstr_ && storage_.policy_ == duplicate) { - releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary + releaseStringValue(const_cast<char*>(cstr_), + storage_.length_ + 1U); // +1 for null terminating + // character for sake of + // completeness but not actually + // necessary } } @@ -298,36 +285,39 @@ Value::CZString& Value::CZString::operator=(const CZString& other) { return *this; } -#if JSON_HAS_RVALUE_REFERENCES Value::CZString& Value::CZString::operator=(CZString&& other) { cstr_ = other.cstr_; index_ = other.index_; other.cstr_ = nullptr; return *this; } -#endif bool Value::CZString::operator<(const CZString& other) const { - if (!cstr_) return index_ < other.index_; - //return strcmp(cstr_, other.cstr_) < 0; + if (!cstr_) + return index_ < other.index_; + // return strcmp(cstr_, other.cstr_) < 0; // Assume both are strings. unsigned this_len = this->storage_.length_; unsigned other_len = other.storage_.length_; unsigned min_len = std::min<unsigned>(this_len, other_len); JSON_ASSERT(this->cstr_ && other.cstr_); int comp = memcmp(this->cstr_, other.cstr_, min_len); - if (comp < 0) return true; - if (comp > 0) return false; + if (comp < 0) + return true; + if (comp > 0) + return false; return (this_len < other_len); } bool Value::CZString::operator==(const CZString& other) const { - if (!cstr_) return index_ == other.index_; - //return strcmp(cstr_, other.cstr_) == 0; + if (!cstr_) + return index_ == other.index_; + // return strcmp(cstr_, other.cstr_) == 0; // Assume both are strings. unsigned this_len = this->storage_.length_; unsigned other_len = other.storage_.length_; - if (this_len != other_len) return false; + if (this_len != other_len) + return false; JSON_ASSERT(this->cstr_ && other.cstr_); int comp = memcmp(this->cstr_, other.cstr_, this_len); return comp == 0; @@ -335,10 +325,12 @@ bool Value::CZString::operator==(const CZString& other) const { ArrayIndex Value::CZString::index() const { return index_; } -//const char* Value::CZString::c_str() const { return cstr_; } +// const char* Value::CZString::c_str() const { return cstr_; } const char* Value::CZString::data() const { return cstr_; } unsigned Value::CZString::length() const { return storage_.length_; } -bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } +bool Value::CZString::isStaticString() const { + return storage_.policy_ == noDuplication; +} // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -352,10 +344,10 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl * memset( this, 0, sizeof(Value) ) * This optimization is used in ValueInternalMap fast allocator. */ -Value::Value(ValueType vtype) { +Value::Value(ValueType type) { static char const emptyString[] = ""; - initBasic(vtype); - switch (vtype) { + initBasic(type); + switch (type) { case nullValue: break; case intValue: @@ -408,20 +400,22 @@ Value::Value(double value) { Value::Value(const char* value) { initBasic(stringValue, true); - JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor"); - value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value))); + JSON_ASSERT_MESSAGE(value != nullptr, + "Null Value Passed to Value Constructor"); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast<unsigned>(strlen(value))); } -Value::Value(const char* beginValue, const char* endValue) { +Value::Value(const char* begin, const char* end) { initBasic(stringValue, true); value_.string_ = - duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue)); + duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin)); } -Value::Value(const JSONCPP_STRING& value) { +Value::Value(const String& value) { initBasic(stringValue, true); - value_.string_ = - duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length())); + value_.string_ = duplicateAndPrefixStringValue( + value.data(), static_cast<unsigned>(value.length())); } Value::Value(const StaticString& value) { @@ -429,114 +423,44 @@ Value::Value(const StaticString& value) { value_.string_ = const_cast<char*>(value.c_str()); } -#ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length())); -} -#endif - Value::Value(bool value) { initBasic(booleanValue); value_.bool_ = value; } -Value::Value(Value const& other) - : type_(other.type_), allocated_(false) - , - comments_(0), start_(other.start_), limit_(other.limit_) -{ - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.allocated_) { - unsigned len; - char const* str; - decodePrefixedString(other.allocated_, other.value_.string_, - &len, &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - allocated_ = true; - } else { - value_.string_ = other.value_.string_; - allocated_ = false; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment( - otherComment.comment_, strlen(otherComment.comment_)); - } - } +Value::Value(const Value& other) { + dupPayload(other); + dupMeta(other); } -#if JSON_HAS_RVALUE_REFERENCES -// Move constructor Value::Value(Value&& other) { initBasic(nullValue); swap(other); } -#endif Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releasePrefixedStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } - - delete[] comments_; - + releasePayload(); value_.uint_ = 0; } -Value& Value::operator=(Value other) { - swap(other); +Value& Value::operator=(const Value& other) { + Value(other).swap(*this); + return *this; +} + +Value& Value::operator=(Value&& other) { + other.swap(*this); return *this; } void Value::swapPayload(Value& other) { - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; + std::swap(bits_, other.bits_); std::swap(value_, other.value_); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2 & 0x1; } void Value::copyPayload(const Value& other) { - type_ = other.type_; - value_ = other.value_; - allocated_ = other.allocated_; + releasePayload(); + dupPayload(other); } void Value::swap(Value& other) { @@ -548,12 +472,12 @@ void Value::swap(Value& other) { void Value::copy(const Value& other) { copyPayload(other); - comments_ = other.comments_; - start_ = other.start_; - limit_ = other.limit_; + dupMeta(other); } -ValueType Value::type() const { return type_; } +ValueType Value::type() const { + return static_cast<ValueType>(bits_.value_type_); +} int Value::compare(const Value& other) const { if (*this < other) @@ -564,10 +488,10 @@ int Value::compare(const Value& other) const { } bool Value::operator<(const Value& other) const { - int typeDelta = type_ - other.type_; + int typeDelta = type() - other.type(); if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type_) { + return typeDelta < 0; + switch (type()) { case nullValue: return false; case intValue: @@ -578,30 +502,33 @@ bool Value::operator<(const Value& other) const { return value_.real_ < other.value_.real_; case booleanValue: return value_.bool_ < other.value_.bool_; - case stringValue: - { - if ((value_.string_ == 0) || (other.value_.string_ == 0)) { - if (other.value_.string_) return true; - else return false; + case stringValue: { + if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { + return other.value_.string_ != nullptr; } unsigned this_len; unsigned other_len; char const* this_str; char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, + &other_str); unsigned min_len = std::min<unsigned>(this_len, other_len); JSON_ASSERT(this_str && other_str); int comp = memcmp(this_str, other_str, min_len); - if (comp < 0) return true; - if (comp > 0) return false; + if (comp < 0) + return true; + if (comp > 0) + return false; return (this_len < other_len); } case arrayValue: case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; + auto thisSize = value_.map_->size(); + auto otherSize = other.value_.map_->size(); + if (thisSize != otherSize) + return thisSize < otherSize; return (*value_.map_) < (*other.value_.map_); } default: @@ -617,14 +544,9 @@ bool Value::operator>=(const Value& other) const { return !(*this < other); } bool Value::operator>(const Value& other) const { return other < *this; } bool Value::operator==(const Value& other) const { - // if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if (type_ != temp) + if (type() != other.type()) return false; - switch (type_) { + switch (type()) { case nullValue: return true; case intValue: @@ -635,18 +557,20 @@ bool Value::operator==(const Value& other) const { return value_.real_ == other.value_.real_; case booleanValue: return value_.bool_ == other.value_.bool_; - case stringValue: - { - if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + case stringValue: { + if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { return (value_.string_ == other.value_.string_); } unsigned this_len; unsigned other_len; char const* this_str; char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); - if (this_len != other_len) return false; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, + &other_str); + if (this_len != other_len) + return false; JSON_ASSERT(this_str && other_str); int comp = memcmp(this_str, other_str, this_len); return comp == 0; @@ -664,47 +588,55 @@ bool Value::operator==(const Value& other) const { bool Value::operator!=(const Value& other) const { return !(*this == other); } const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, + JSON_ASSERT_MESSAGE(type() == stringValue, "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) return 0; + if (value_.string_ == nullptr) + return nullptr; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); return this_str; } #if JSONCPP_USING_SECURE_MEMORY unsigned Value::getCStringLength() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) return 0; + JSON_ASSERT_MESSAGE(type() == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); return this_len; } #endif -bool Value::getString(char const** str, char const** cend) const { - if (type_ != stringValue) return false; - if (value_.string_ == 0) return false; +bool Value::getString(char const** begin, char const** end) const { + if (type() != stringValue) + return false; + if (value_.string_ == nullptr) + return false; unsigned length; - decodePrefixedString(this->allocated_, this->value_.string_, &length, str); - *cend = *str + length; + decodePrefixedString(this->isAllocated(), this->value_.string_, &length, + begin); + *end = *begin + length; return true; } -JSONCPP_STRING Value::asString() const { - switch (type_) { +String Value::asString() const { + switch (type()) { case nullValue: return ""; - case stringValue: - { - if (value_.string_ == 0) return ""; + case stringValue: { + if (value_.string_ == nullptr) + return ""; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - return JSONCPP_STRING(this_str, this_len); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + return String(this_str, this_len); } case booleanValue: return value_.bool_ ? "true" : "false"; @@ -719,18 +651,8 @@ JSONCPP_STRING Value::asString() const { } } -#ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const { - unsigned len; - char const* str; - decodePrefixedString(allocated_, value_.string_, - &len, &str); - return CppTL::ConstString(str, len); -} -#endif - Value::Int Value::asInt() const { - switch (type_) { + switch (type()) { case intValue: JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); return Int(value_.int_); @@ -752,7 +674,7 @@ Value::Int Value::asInt() const { } Value::UInt Value::asUInt() const { - switch (type_) { + switch (type()) { case intValue: JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); return UInt(value_.int_); @@ -776,7 +698,7 @@ Value::UInt Value::asUInt() const { #if defined(JSON_HAS_INT64) Value::Int64 Value::asInt64() const { - switch (type_) { + switch (type()) { case intValue: return Int64(value_.int_); case uintValue: @@ -797,7 +719,7 @@ Value::Int64 Value::asInt64() const { } Value::UInt64 Value::asUInt64() const { - switch (type_) { + switch (type()) { case intValue: JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); return UInt64(value_.int_); @@ -835,7 +757,7 @@ LargestUInt Value::asLargestUInt() const { } double Value::asDouble() const { - switch (type_) { + switch (type()) { case intValue: return static_cast<double>(value_.int_); case uintValue: @@ -857,7 +779,7 @@ double Value::asDouble() const { } float Value::asFloat() const { - switch (type_) { + switch (type()) { case intValue: return static_cast<float>(value_.int_); case uintValue: @@ -872,7 +794,7 @@ float Value::asFloat() const { case nullValue: return 0.0; case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; + return value_.bool_ ? 1.0F : 0.0F; default: break; } @@ -880,18 +802,20 @@ float Value::asFloat() const { } bool Value::asBool() const { - switch (type_) { + switch (type()) { case booleanValue: return value_.bool_; case nullValue: return false; case intValue: - return value_.int_ ? true : false; + return value_.int_ != 0; case uintValue: - return value_.uint_ ? true : false; - case realValue: - // This is kind of strange. Not recommended. - return (value_.real_ != 0.0) ? true : false; + return value_.uint_ != 0; + case realValue: { + // According to JavaScript language zero or NaN is regarded as false + const auto value_classification = std::fpclassify(value_.real_); + return value_classification != FP_ZERO && value_classification != FP_NAN; + } default: break; } @@ -902,30 +826,30 @@ bool Value::isConvertibleTo(ValueType other) const { switch (other) { case nullValue: return (isNumeric() && asDouble() == 0.0) || - (type_ == booleanValue && value_.bool_ == false) || - (type_ == stringValue && asString().empty()) || - (type_ == arrayValue && value_.map_->size() == 0) || - (type_ == objectValue && value_.map_->size() == 0) || - type_ == nullValue; + (type() == booleanValue && !value_.bool_) || + (type() == stringValue && asString().empty()) || + (type() == arrayValue && value_.map_->empty()) || + (type() == objectValue && value_.map_->empty()) || + type() == nullValue; case intValue: return isInt() || - (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || - type_ == booleanValue || type_ == nullValue; + (type() == realValue && InRange(value_.real_, minInt, maxInt)) || + type() == booleanValue || type() == nullValue; case uintValue: return isUInt() || - (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || - type_ == booleanValue || type_ == nullValue; + (type() == realValue && InRange(value_.real_, 0, maxUInt)) || + type() == booleanValue || type() == nullValue; case realValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; + return isNumeric() || type() == booleanValue || type() == nullValue; case booleanValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; + return isNumeric() || type() == booleanValue || type() == nullValue; case stringValue: - return isNumeric() || type_ == booleanValue || type_ == stringValue || - type_ == nullValue; + return isNumeric() || type() == booleanValue || type() == stringValue || + type() == nullValue; case arrayValue: - return type_ == arrayValue || type_ == nullValue; + return type() == arrayValue || type() == nullValue; case objectValue: - return type_ == objectValue || type_ == nullValue; + return type() == objectValue || type() == nullValue; } JSON_ASSERT_UNREACHABLE; return false; @@ -933,7 +857,7 @@ bool Value::isConvertibleTo(ValueType other) const { /// Number of values in array or object ArrayIndex Value::size() const { - switch (type_) { + switch (type()) { case nullValue: case intValue: case uintValue: @@ -957,20 +881,19 @@ ArrayIndex Value::size() const { bool Value::empty() const { if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; + return size() == 0U; + return false; } -bool Value::operator!() const { return isNull(); } +Value::operator bool() const { return !isNull(); } void Value::clear() { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || - type_ == objectValue, + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || + type() == objectValue, "in Json::Value::clear(): requires complex value"); start_ = 0; limit_ = 0; - switch (type_) { + switch (type()) { case arrayValue: case objectValue: value_.map_->clear(); @@ -981,15 +904,15 @@ void Value::clear() { } void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, "in Json::Value::resize(): requires arrayValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(arrayValue); ArrayIndex oldSize = size(); if (newSize == 0) clear(); else if (newSize > oldSize) - (*this)[newSize - 1]; + this->operator[](newSize - 1); else { for (ArrayIndex index = newSize; index < oldSize; ++index) { value_.map_->erase(index); @@ -1000,12 +923,12 @@ void Value::resize(ArrayIndex newSize) { Value& Value::operator[](ArrayIndex index) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, + type() == nullValue || type() == arrayValue, "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(arrayValue); CZString key(index); - ObjectValues::iterator it = value_.map_->lower_bound(key); + auto it = value_.map_->lower_bound(key); if (it != value_.map_->end() && (*it).first == key) return (*it).second; @@ -1023,9 +946,9 @@ Value& Value::operator[](int index) { const Value& Value::operator[](ArrayIndex index) const { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, + type() == nullValue || type() == arrayValue, "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type_ == nullValue) + if (type() == nullValue) return nullSingleton(); CZString key(index); ObjectValues::const_iterator it = value_.map_->find(key); @@ -1041,26 +964,85 @@ const Value& Value::operator[](int index) const { return (*this)[ArrayIndex(index)]; } -void Value::initBasic(ValueType vtype, bool allocated) { - type_ = vtype; - allocated_ = allocated; - comments_ = 0; +void Value::initBasic(ValueType type, bool allocated) { + setType(type); + setIsAllocated(allocated); + comments_ = Comments{}; start_ = 0; limit_ = 0; } +void Value::dupPayload(const Value& other) { + setType(other.type()); + setIsAllocated(false); + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.isAllocated()) { + unsigned len; + char const* str; + decodePrefixedString(other.isAllocated(), other.value_.string_, &len, + &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + setIsAllocated(true); + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::releasePayload() { + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (isAllocated()) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::dupMeta(const Value& other) { + comments_ = other.comments_; + start_ = other.start_; + limit_ = other.limit_; +} + // Access an object value by name, create a null member if it does not exist. // @pre Type of '*this' is object or null. // @param key is null-terminated. Value& Value::resolveReference(const char* key) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, + type() == nullValue || type() == objectValue, "in Json::Value::resolveReference(): requires objectValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(objectValue); - CZString actualKey( - key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE! - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + CZString actualKey(key, static_cast<unsigned>(strlen(key)), + CZString::noDuplication); // NOTE! + auto it = value_.map_->lower_bound(actualKey); if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; @@ -1071,16 +1053,15 @@ Value& Value::resolveReference(const char* key) { } // @param key is not null-terminated. -Value& Value::resolveReference(char const* key, char const* cend) -{ +Value& Value::resolveReference(char const* key, char const* end) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, + type() == nullValue || type() == objectValue, "in Json::Value::resolveReference(key, end): requires objectValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(objectValue); - CZString actualKey( - key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy); - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + CZString actualKey(key, static_cast<unsigned>(end - key), + CZString::duplicateOnCopy); + auto it = value_.map_->lower_bound(actualKey); if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; @@ -1097,27 +1078,35 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const { bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } -Value const* Value::find(char const* key, char const* cend) const -{ - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::find(key, end, found): requires objectValue or nullValue"); - if (type_ == nullValue) return NULL; - CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); +Value const* Value::find(char const* begin, char const* end) const { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::find(begin, end): requires " + "objectValue or nullValue"); + if (type() == nullValue) + return nullptr; + CZString actualKey(begin, static_cast<unsigned>(end - begin), + CZString::noDuplication); ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) return NULL; + if (it == value_.map_->end()) + return nullptr; return &(*it).second; } -const Value& Value::operator[](const char* key) const -{ +Value* Value::demand(char const* begin, char const* end) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::demand(begin, end): requires " + "objectValue or nullValue"); + return &resolveReference(begin, end); +} +const Value& Value::operator[](const char* key) const { Value const* found = find(key, key + strlen(key)); - if (!found) return nullSingleton(); + if (!found) + return nullSingleton(); return *found; } -Value const& Value::operator[](JSONCPP_STRING const& key) const -{ +Value const& Value::operator[](const String& key) const { Value const* found = find(key.data(), key.data() + key.length()); - if (!found) return nullSingleton(); + if (!found) + return nullSingleton(); return *found; } @@ -1125,7 +1114,7 @@ Value& Value::operator[](const char* key) { return resolveReference(key, key + strlen(key)); } -Value& Value::operator[](const JSONCPP_STRING& key) { +Value& Value::operator[](const String& key) { return resolveReference(key.data(), key.data() + key.length()); } @@ -1133,179 +1122,140 @@ Value& Value::operator[](const StaticString& key) { return resolveReference(key.c_str()); } -#ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) { - return resolveReference(key.c_str(), key.end_c_str()); -} -Value const& Value::operator[](CppTL::ConstString const& key) const -{ - Value const* found = find(key.c_str(), key.end_c_str()); - if (!found) return nullSingleton(); - return *found; +Value& Value::append(const Value& value) { return append(Value(value)); } + +Value& Value::append(Value&& value) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::append: requires arrayValue"); + if (type() == nullValue) { + *this = Value(arrayValue); + } + return this->value_.map_->emplace(size(), std::move(value)).first->second; } -#endif -Value& Value::append(const Value& value) { return (*this)[size()] = value; } +bool Value::insert(ArrayIndex index, const Value& newValue) { + return insert(index, Value(newValue)); +} -#if JSON_HAS_RVALUE_REFERENCES - Value& Value::append(Value&& value) { return (*this)[size()] = value; } -#endif +bool Value::insert(ArrayIndex index, Value&& newValue) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::insert: requires arrayValue"); + ArrayIndex length = size(); + if (index > length) { + return false; + } + for (ArrayIndex i = length; i > index; i--) { + (*this)[i] = std::move((*this)[i - 1]); + } + (*this)[index] = std::move(newValue); + return true; +} -Value Value::get(char const* key, char const* cend, Value const& defaultValue) const -{ - Value const* found = find(key, cend); +Value Value::get(char const* begin, char const* end, + Value const& defaultValue) const { + Value const* found = find(begin, end); return !found ? defaultValue : *found; } -Value Value::get(char const* key, Value const& defaultValue) const -{ +Value Value::get(char const* key, Value const& defaultValue) const { return get(key, key + strlen(key), defaultValue); } -Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const -{ +Value Value::get(String const& key, Value const& defaultValue) const { return get(key.data(), key.data() + key.length(), defaultValue); } - -bool Value::removeMember(const char* key, const char* cend, Value* removed) -{ - if (type_ != objectValue) { +bool Value::removeMember(const char* begin, const char* end, Value* removed) { + if (type() != objectValue) { return false; } - CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); - ObjectValues::iterator it = value_.map_->find(actualKey); + CZString actualKey(begin, static_cast<unsigned>(end - begin), + CZString::noDuplication); + auto it = value_.map_->find(actualKey); if (it == value_.map_->end()) return false; - *removed = it->second; + if (removed) + *removed = std::move(it->second); value_.map_->erase(it); return true; } -bool Value::removeMember(const char* key, Value* removed) -{ +bool Value::removeMember(const char* key, Value* removed) { return removeMember(key, key + strlen(key), removed); } -bool Value::removeMember(JSONCPP_STRING const& key, Value* removed) -{ +bool Value::removeMember(String const& key, Value* removed) { return removeMember(key.data(), key.data() + key.length(), removed); } -Value Value::removeMember(const char* key) -{ - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, +void Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, "in Json::Value::removeMember(): requires objectValue"); - if (type_ == nullValue) - return nullSingleton(); + if (type() == nullValue) + return; - Value removed; // null - removeMember(key, key + strlen(key), &removed); - return removed; // still null if removeMember() did nothing -} -Value Value::removeMember(const JSONCPP_STRING& key) -{ - return removeMember(key.c_str()); + CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); + value_.map_->erase(actualKey); } +void Value::removeMember(const String& key) { removeMember(key.c_str()); } bool Value::removeIndex(ArrayIndex index, Value* removed) { - if (type_ != arrayValue) { + if (type() != arrayValue) { return false; } CZString key(index); - ObjectValues::iterator it = value_.map_->find(key); + auto it = value_.map_->find(key); if (it == value_.map_->end()) { return false; } - *removed = it->second; + if (removed) + *removed = it->second; ArrayIndex oldSize = size(); // shift left all items left, into the place of the "removed" - for (ArrayIndex i = index; i < (oldSize - 1); ++i){ + for (ArrayIndex i = index; i < (oldSize - 1); ++i) { CZString keey(i); (*value_.map_)[keey] = (*this)[i + 1]; } // erase the last one ("leftover") CZString keyLast(oldSize - 1); - ObjectValues::iterator itLast = value_.map_->find(keyLast); + auto itLast = value_.map_->find(keyLast); value_.map_->erase(itLast); return true; } -#ifdef JSON_USE_CPPTL -Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const { - return get(key.c_str(), key.end_c_str(), defaultValue); +bool Value::isMember(char const* begin, char const* end) const { + Value const* value = find(begin, end); + return nullptr != value; } -#endif - -bool Value::isMember(char const* key, char const* cend) const -{ - Value const* value = find(key, cend); - return NULL != value; -} -bool Value::isMember(char const* key) const -{ +bool Value::isMember(char const* key) const { return isMember(key, key + strlen(key)); } -bool Value::isMember(JSONCPP_STRING const& key) const -{ +bool Value::isMember(String const& key) const { return isMember(key.data(), key.data() + key.length()); } -#ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const { - return isMember(key.c_str(), key.end_c_str()); -} -#endif - Value::Members Value::getMemberNames() const { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, + type() == nullValue || type() == objectValue, "in Json::Value::getMemberNames(), value must be objectValue"); - if (type_ == nullValue) + if (type() == nullValue) return Value::Members(); Members members; members.reserve(value_.map_->size()); ObjectValues::const_iterator it = value_.map_->begin(); ObjectValues::const_iterator itEnd = value_.map_->end(); for (; it != itEnd; ++it) { - members.push_back(JSONCPP_STRING((*it).first.data(), - (*it).first.length())); + members.push_back(String((*it).first.data(), (*it).first.length())); } return members; } -// -//# ifdef JSON_USE_CPPTL -// EnumMemberNames -// Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -// EnumValues -// Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type<const Value &>() ); -// return EnumValues(); -//} -// -//# endif static bool IsIntegral(double d) { double integral_part; return modf(d, &integral_part) == 0.0; } -bool Value::isNull() const { return type_ == nullValue; } +bool Value::isNull() const { return type() == nullValue; } -bool Value::isBool() const { return type_ == booleanValue; } +bool Value::isBool() const { return type() == booleanValue; } bool Value::isInt() const { - switch (type_) { + switch (type()) { case intValue: #if defined(JSON_HAS_INT64) return value_.int_ >= minInt && value_.int_ <= maxInt; @@ -1324,7 +1274,7 @@ bool Value::isInt() const { } bool Value::isUInt() const { - switch (type_) { + switch (type()) { case intValue: #if defined(JSON_HAS_INT64) return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); @@ -1348,7 +1298,7 @@ bool Value::isUInt() const { bool Value::isInt64() const { #if defined(JSON_HAS_INT64) - switch (type_) { + switch (type()) { case intValue: return true; case uintValue: @@ -1368,7 +1318,7 @@ bool Value::isInt64() const { bool Value::isUInt64() const { #if defined(JSON_HAS_INT64) - switch (type_) { + switch (type()) { case intValue: return value_.int_ >= 0; case uintValue: @@ -1387,61 +1337,92 @@ bool Value::isUInt64() const { } bool Value::isIntegral() const { - switch (type_) { - case intValue: - case uintValue: - return true; - case realValue: + switch (type()) { + case intValue: + case uintValue: + return true; + case realValue: #if defined(JSON_HAS_INT64) - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); #else - return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_); + return value_.real_ >= minInt && value_.real_ <= maxUInt && + IsIntegral(value_.real_); #endif // JSON_HAS_INT64 - default: - break; + default: + break; } return false; } -bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; } +bool Value::isDouble() const { + return type() == intValue || type() == uintValue || type() == realValue; +} bool Value::isNumeric() const { return isDouble(); } -bool Value::isString() const { return type_ == stringValue; } +bool Value::isString() const { return type() == stringValue; } -bool Value::isArray() const { return type_ == arrayValue; } +bool Value::isArray() const { return type() == arrayValue; } -bool Value::isObject() const { return type_ == objectValue; } +bool Value::isObject() const { return type() == objectValue; } -void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - if ((len > 0) && (comment[len-1] == '\n')) { - // Always discard trailing newline, to aid indentation. - len -= 1; - } - comments_[placement].setComment(comment, len); +Value::Comments::Comments(const Comments& that) + : ptr_{cloneUnique(that.ptr_)} {} + +Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {} + +Value::Comments& Value::Comments::operator=(const Comments& that) { + ptr_ = cloneUnique(that.ptr_); + return *this; } -void Value::setComment(const char* comment, CommentPlacement placement) { - setComment(comment, strlen(comment), placement); +Value::Comments& Value::Comments::operator=(Comments&& that) { + ptr_ = std::move(that.ptr_); + return *this; +} + +bool Value::Comments::has(CommentPlacement slot) const { + return ptr_ && !(*ptr_)[slot].empty(); } -void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) { - setComment(comment.c_str(), comment.length(), placement); +String Value::Comments::get(CommentPlacement slot) const { + if (!ptr_) + return {}; + return (*ptr_)[slot]; +} + +void Value::Comments::set(CommentPlacement slot, String comment) { + if (!ptr_) { + ptr_ = std::unique_ptr<Array>(new Array()); + } + // check comments array boundry. + if (slot < CommentPlacement::numberOfCommentPlacement) { + (*ptr_)[slot] = std::move(comment); + } +} + +void Value::setComment(String comment, CommentPlacement placement) { + if (!comment.empty() && (comment.back() == '\n')) { + // Always discard trailing newline, to aid indentation. + comment.pop_back(); + } + JSON_ASSERT(!comment.empty()); + JSON_ASSERT_MESSAGE( + comment[0] == '\0' || comment[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + comments_.set(placement, std::move(comment)); } bool Value::hasComment(CommentPlacement placement) const { - return comments_ != 0 && comments_[placement].comment_ != 0; + return comments_.has(placement); } -JSONCPP_STRING Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; +String Value::getComment(CommentPlacement placement) const { + return comments_.get(placement); } void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } @@ -1452,18 +1433,18 @@ ptrdiff_t Value::getOffsetStart() const { return start_; } ptrdiff_t Value::getOffsetLimit() const { return limit_; } -JSONCPP_STRING Value::toStyledString() const { +String Value::toStyledString() const { StreamWriterBuilder builder; - JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : ""; + String out = this->hasComment(commentBefore) ? "\n" : ""; out += Json::writeString(builder, *this); - out += "\n"; + out += '\n'; return out; } Value::const_iterator Value::begin() const { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1472,11 +1453,11 @@ Value::const_iterator Value::begin() const { default: break; } - return const_iterator(); + return {}; } Value::const_iterator Value::end() const { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1485,11 +1466,11 @@ Value::const_iterator Value::end() const { default: break; } - return const_iterator(); + return {}; } Value::iterator Value::begin() { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1502,7 +1483,7 @@ Value::iterator Value::begin() { } Value::iterator Value::end() { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1517,25 +1498,20 @@ Value::iterator Value::end() { // class PathArgument // ////////////////////////////////////////////////////////////////// -PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} +PathArgument::PathArgument() = default; PathArgument::PathArgument(ArrayIndex index) - : key_(), index_(index), kind_(kindIndex) {} + : index_(index), kind_(kindIndex) {} -PathArgument::PathArgument(const char* key) - : key_(key), index_(), kind_(kindKey) {} +PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {} -PathArgument::PathArgument(const JSONCPP_STRING& key) - : key_(key.c_str()), index_(), kind_(kindKey) {} +PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {} // class Path // ////////////////////////////////////////////////////////////////// -Path::Path(const JSONCPP_STRING& path, - const PathArgument& a1, - const PathArgument& a2, - const PathArgument& a3, - const PathArgument& a4, +Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2, + const PathArgument& a3, const PathArgument& a4, const PathArgument& a5) { InArgs in; in.reserve(5); @@ -1547,10 +1523,10 @@ Path::Path(const JSONCPP_STRING& path, makePath(path, in); } -void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { +void Path::makePath(const String& path, const InArgs& in) { const char* current = path.c_str(); const char* end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); + auto itInArg = in.begin(); while (current != end) { if (*current == '[') { ++current; @@ -1573,13 +1549,12 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { const char* beginName = current; while (current != end && !strchr("[.", *current)) ++current; - args_.push_back(JSONCPP_STRING(beginName, current)); + args_.push_back(String(beginName, current)); } } } -void Path::addPathInArg(const JSONCPP_STRING& /*path*/, - const InArgs& in, +void Path::addPathInArg(const String& /*path*/, const InArgs& in, InArgs::const_iterator& itInArg, PathArgument::Kind kind) { if (itInArg == in.end()) { @@ -1591,30 +1566,29 @@ void Path::addPathInArg(const JSONCPP_STRING& /*path*/, } } -void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) { +void Path::invalidPath(const String& /*path*/, int /*location*/) { // Error: invalid path. } const Value& Path::resolve(const Value& root) const { const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; + for (const auto& arg : args_) { if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - return Value::null; + // Error: unable to resolve path (array value expected at position... ) + return Value::nullSingleton(); } node = &((*node)[arg.index_]); } else if (arg.kind_ == PathArgument::kindKey) { if (!node->isObject()) { // Error: unable to resolve path (object value expected at position...) - return Value::null; + return Value::nullSingleton(); } node = &((*node)[arg.key_]); if (node == &Value::nullSingleton()) { // Error: unable to resolve path (object has no member named '' at // position...) - return Value::null; + return Value::nullSingleton(); } } } @@ -1623,8 +1597,7 @@ const Value& Path::resolve(const Value& root) const { Value Path::resolve(const Value& root, const Value& defaultValue) const { const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; + for (const auto& arg : args_) { if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray() || !node->isValidIndex(arg.index_)) return defaultValue; @@ -1642,8 +1615,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const { Value& Path::make(Value& root) const { Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; + for (const auto& arg : args_) { if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray()) { // Error: node is not an array at position ... diff --git a/src/lib_json/json_valueiterator.inl b/src/lib_json/json_valueiterator.inl index 5243bfe4bbb..d6128b8edf0 100644 --- a/src/lib_json/json_valueiterator.inl +++ b/src/lib_json/json_valueiterator.inl @@ -15,31 +15,21 @@ namespace Json { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueIteratorBase::ValueIteratorBase() - : current_(), isNull_(true) { -} +ValueIteratorBase::ValueIteratorBase() : current_() {} ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator& current) : current_(current), isNull_(false) {} -Value& ValueIteratorBase::deref() const { - return current_->second; -} +Value& ValueIteratorBase::deref() { return current_->second; } +const Value& ValueIteratorBase::deref() const { return current_->second; } -void ValueIteratorBase::increment() { - ++current_; -} +void ValueIteratorBase::increment() { ++current_; } -void ValueIteratorBase::decrement() { - --current_; -} +void ValueIteratorBase::decrement() { --current_; } ValueIteratorBase::difference_type ValueIteratorBase::computeDistance(const SelfType& other) const { -#ifdef JSON_USE_CPPTL_SMALLMAP - return other.current_ - current_; -#else // Iterator for null value are initialized using the default // constructor, which initialize current_ to the default // std::map::iterator. As begin() and end() are two instance @@ -60,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const { ++myDistance; } return myDistance; -#endif } bool ValueIteratorBase::isEqual(const SelfType& other) const { @@ -92,12 +81,13 @@ UInt ValueIteratorBase::index() const { return Value::UInt(-1); } -JSONCPP_STRING ValueIteratorBase::name() const { +String ValueIteratorBase::name() const { char const* keey; char const* end; keey = memberName(&end); - if (!keey) return JSONCPP_STRING(); - return JSONCPP_STRING(keey, end); + if (!keey) + return String(); + return String(keey, end); } char const* ValueIteratorBase::memberName() const { @@ -108,8 +98,8 @@ char const* ValueIteratorBase::memberName() const { char const* ValueIteratorBase::memberName(char const** end) const { const char* cname = (*current_).first.data(); if (!cname) { - *end = NULL; - return NULL; + *end = nullptr; + return nullptr; } *end = cname + (*current_).first.length(); return cname; @@ -123,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueConstIterator::ValueConstIterator() {} +ValueConstIterator::ValueConstIterator() = default; ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator& current) @@ -146,7 +136,7 @@ operator=(const ValueIteratorBase& other) { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueIterator::ValueIterator() {} +ValueIterator::ValueIterator() = default; ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) : ValueIteratorBase(current) {} @@ -156,8 +146,7 @@ ValueIterator::ValueIterator(const ValueConstIterator& other) throwRuntimeError("ConstIterator to Iterator should never be allowed."); } -ValueIterator::ValueIterator(const ValueIterator& other) - : ValueIteratorBase(other) {} +ValueIterator::ValueIterator(const ValueIterator& other) = default; ValueIterator& ValueIterator::operator=(const SelfType& other) { copy(other); diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp index 02f1cb11b63..8bf02dbdbc1 100644 --- a/src/lib_json/json_writer.cpp +++ b/src/lib_json/json_writer.cpp @@ -4,71 +4,81 @@ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) -#include <json/writer.h> #include "json_tool.h" +#include <json/writer.h> #endif // if !defined(JSON_IS_AMALGAMATION) +#include <algorithm> +#include <cassert> +#include <cctype> +#include <cstring> #include <iomanip> #include <memory> +#include <set> #include <sstream> #include <utility> -#include <set> -#include <cassert> -#include <cstring> + +#if __cplusplus >= 201103L +#include <cmath> +#include <cstdio> + +#if !defined(isnan) +#define isnan std::isnan +#endif + +#if !defined(isfinite) +#define isfinite std::isfinite +#endif + +#else +#include <cmath> #include <cstdio> -#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 +#if defined(_MSC_VER) +#if !defined(isnan) +#include <float.h> +#define isnan _isnan +#endif + +#if !defined(isfinite) #include <float.h> #define isfinite _finite -#elif defined(__sun) && defined(__SVR4) //Solaris +#endif + +#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES + +#endif //_MSC_VER + +#if defined(__sun) && defined(__SVR4) // Solaris #if !defined(isfinite) #include <ieeefp.h> #define isfinite finite #endif -#elif defined(_AIX) -#if !defined(isfinite) -#include <math.h> -#define isfinite finite #endif -#elif defined(__hpux) + +#if defined(__hpux) #if !defined(isfinite) #if defined(__ia64) && !defined(finite) -#define isfinite(x) ((sizeof(x) == sizeof(float) ? \ - _Isfinitef(x) : _IsFinite(x))) -#else -#include <math.h> -#define isfinite finite +#define isfinite(x) \ + ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) #endif #endif -#else -#include <cmath> -#if !(defined(__QNXNTO__)) // QNX already defines isfinite -#define isfinite std::isfinite -#endif #endif -#if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above -#define snprintf sprintf_s -#elif _MSC_VER >= 1900 // VC++ 14.0 and above -#define snprintf std::snprintf -#else -#define snprintf _snprintf +#if !defined(isnan) +// IEEE standard states that NaN values will not compare to themselves +#define isnan(x) (x != x) #endif -#elif defined(__ANDROID__) || defined(__QNXNTO__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#if !defined(__MINGW32__) && !defined(__CYGWIN__) -#define snprintf std::snprintf + +#if !defined(__APPLE__) +#if !defined(isfinite) +#define isfinite finite #endif #endif - -#if defined(__BORLANDC__) -#include <float.h> -#define isfinite _finite -#define snprintf _snprintf #endif -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +#if defined(_MSC_VER) // Disable warning about strdup being deprecated. #pragma warning(disable : 4996) #endif @@ -76,30 +86,12 @@ namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -typedef std::unique_ptr<StreamWriter> StreamWriterPtr; +using StreamWriterPtr = std::unique_ptr<StreamWriter>; #else -typedef std::auto_ptr<StreamWriter> StreamWriterPtr; +using StreamWriterPtr = std::auto_ptr<StreamWriter>; #endif -static bool containsControlCharacter(const char* str) { - while (*str) { - if (isControlCharacter(*(str++))) - return true; - } - return false; -} - -static bool containsControlCharacter0(const char* str, unsigned len) { - char const* end = str + len; - while (end != str) { - if (isControlCharacter(*str) || 0==*str) - return true; - ++str; - } - return false; -} - -JSONCPP_STRING valueToString(LargestInt value) { +String valueToString(LargestInt value) { UIntToStringBuffer buffer; char* current = buffer + sizeof(buffer); if (value == Value::minLargestInt) { @@ -115,7 +107,7 @@ JSONCPP_STRING valueToString(LargestInt value) { return current; } -JSONCPP_STRING valueToString(LargestUInt value) { +String valueToString(LargestUInt value) { UIntToStringBuffer buffer; char* current = buffer + sizeof(buffer); uintToString(value, current); @@ -125,147 +117,171 @@ JSONCPP_STRING valueToString(LargestUInt value) { #if defined(JSON_HAS_INT64) -JSONCPP_STRING valueToString(Int value) { - return valueToString(LargestInt(value)); -} +String valueToString(Int value) { return valueToString(LargestInt(value)); } -JSONCPP_STRING valueToString(UInt value) { - return valueToString(LargestUInt(value)); -} +String valueToString(UInt value) { return valueToString(LargestUInt(value)); } #endif // # if defined(JSON_HAS_INT64) namespace { -JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) { - // Allocate a buffer that is more than large enough to store the 16 digits of - // precision requested below. - char buffer[36]; - int len = -1; - - char formatString[15]; - snprintf(formatString, sizeof(formatString), "%%.%dg", precision); - +String valueToString(double value, bool useSpecialFloats, + unsigned int precision, PrecisionType precisionType) { // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distingish the + // that always has a decimal point because JSON doesn't distinguish the // concepts of reals and integers. - if (isfinite(value)) { - len = snprintf(buffer, sizeof(buffer), formatString, value); - fixNumericLocale(buffer, buffer + len); + if (!isfinite(value)) { + static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"}, + {"null", "-1e+9999", "1e+9999"}}; + return reps[useSpecialFloats ? 0 : 1] + [isnan(value) ? 0 : (value < 0) ? 1 : 2]; + } - // try to ensure we preserve the fact that this was given to us as a double on input - if (!strchr(buffer, '.') && !strchr(buffer, 'e')) { - strcat(buffer, ".0"); + String buffer(size_t(36), '\0'); + while (true) { + int len = jsoncpp_snprintf( + &*buffer.begin(), buffer.size(), + (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", + precision, value); + assert(len >= 0); + auto wouldPrint = static_cast<size_t>(len); + if (wouldPrint >= buffer.size()) { + buffer.resize(wouldPrint + 1); + continue; } + buffer.resize(wouldPrint); + break; + } - } else { - // IEEE standard states that NaN values will not compare to themselves - if (value != value) { - len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); - } else if (value < 0) { - len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); - } else { - len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); - } + buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); + + // strip the zero padding from the right + if (precisionType == PrecisionType::decimalPlaces) { + buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end()); + } + + // try to ensure we preserve the fact that this was given to us as a double on + // input + if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { + buffer += ".0"; } - assert(len >= 0); return buffer; } +} // namespace + +String valueToString(double value, unsigned int precision, + PrecisionType precisionType) { + return valueToString(value, false, precision, precisionType); } -JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); } +String valueToString(bool value) { return value ? "true" : "false"; } -JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; } +static bool doesAnyCharRequireEscaping(char const* s, size_t n) { + assert(s || !n); -JSONCPP_STRING valueToQuotedString(const char* value) { - if (value == NULL) - return ""; - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && - !containsControlCharacter(value)) - return JSONCPP_STRING("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to JSONCPP_STRING is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - JSONCPP_STRING::size_type maxsize = - strlen(value) * 2 + 3; // allescaped+quotes+NULL - JSONCPP_STRING result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c = value; *c != 0; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid </ - // sequence. - // Should add a flag to allow this compatibility mode and prevent this - // sequence from occurring. - default: - if (isControlCharacter(*c)) { - JSONCPP_OSTRINGSTREAM oss; - oss << "\\u" << std::hex << std::uppercase << std::setfill('0') - << std::setw(4) << static_cast<int>(*c); - result += oss.str(); - } else { - result += *c; - } - break; - } + return std::any_of(s, s + n, [](unsigned char c) { + return c == '\\' || c == '"' || c < 0x20 || c > 0x7F; + }); +} + +static unsigned int utf8ToCodepoint(const char*& s, const char* e) { + const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; + + unsigned int firstByte = static_cast<unsigned char>(*s); + + if (firstByte < 0x80) + return firstByte; + + if (firstByte < 0xE0) { + if (e - s < 2) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = + ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F); + s += 1; + // oversized encoded characters are invalid + return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; } - result += "\""; + + if (firstByte < 0xF0) { + if (e - s < 3) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x0F) << 12) | + ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) | + (static_cast<unsigned int>(s[2]) & 0x3F); + s += 2; + // surrogates aren't valid codepoints itself + // shouldn't be UTF-8 encoded + if (calculated >= 0xD800 && calculated <= 0xDFFF) + return REPLACEMENT_CHARACTER; + // oversized encoded characters are invalid + return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF8) { + if (e - s < 4) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x07) << 18) | + ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) | + ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) | + (static_cast<unsigned int>(s[3]) & 0x3F); + s += 3; + // oversized encoded characters are invalid + return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; + } + + return REPLACEMENT_CHARACTER; +} + +static const char hex2[] = "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + +static String toHex16Bit(unsigned int x) { + const unsigned int hi = (x >> 8) & 0xff; + const unsigned int lo = x & 0xff; + String result(4, ' '); + result[0] = hex2[2 * hi]; + result[1] = hex2[2 * hi + 1]; + result[2] = hex2[2 * lo]; + result[3] = hex2[2 * lo + 1]; return result; } -// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp -static char const* strnpbrk(char const* s, char const* accept, size_t n) { - assert((s || !n) && accept); +static void appendRaw(String& result, unsigned ch) { + result += static_cast<char>(ch); +} - char const* const end = s + n; - for (char const* cur = s; cur < end; ++cur) { - int const c = *cur; - for (char const* a = accept; *a; ++a) { - if (*a == c) { - return cur; - } - } - } - return NULL; +static void appendHex(String& result, unsigned ch) { + result.append("\\u").append(toHex16Bit(ch)); } -static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { - if (value == NULL) + +static String valueToQuotedStringN(const char* value, unsigned length, + bool emitUTF8 = false) { + if (value == nullptr) return ""; - // Not sure how to handle unicode... - if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && - !containsControlCharacter0(value, length)) - return JSONCPP_STRING("\"") + value + "\""; + + if (!doesAnyCharRequireEscaping(value, length)) + return String("\"") + value + "\""; // We have to walk value and escape any special characters. - // Appending to JSONCPP_STRING is not efficient, but this should be rare. + // Appending to String is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) - JSONCPP_STRING::size_type maxsize = - length * 2 + 3; // allescaped+quotes+NULL - JSONCPP_STRING result; + String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL + String result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; char const* end = value + length; @@ -300,44 +316,63 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { // sequence. // Should add a flag to allow this compatibility mode and prevent this // sequence from occurring. - default: - if ((isControlCharacter(*c)) || (*c == 0)) { - JSONCPP_OSTRINGSTREAM oss; - oss << "\\u" << std::hex << std::uppercase << std::setfill('0') - << std::setw(4) << static_cast<int>(*c); - result += oss.str(); + default: { + if (emitUTF8) { + unsigned codepoint = static_cast<unsigned char>(*c); + if (codepoint < 0x20) { + appendHex(result, codepoint); + } else { + appendRaw(result, codepoint); + } } else { - result += *c; + unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c` + if (codepoint < 0x20) { + appendHex(result, codepoint); + } else if (codepoint < 0x80) { + appendRaw(result, codepoint); + } else if (codepoint < 0x10000) { + // Basic Multilingual Plane + appendHex(result, codepoint); + } else { + // Extended Unicode. Encode 20 bits as a surrogate pair. + codepoint -= 0x10000; + appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff)); + appendHex(result, 0xdc00 + (codepoint & 0x3ff)); + } } - break; + } break; } } result += "\""; return result; } +String valueToQuotedString(const char* value) { + return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value))); +} + // Class Writer // ////////////////////////////////////////////////////////////////// -Writer::~Writer() {} +Writer::~Writer() = default; // Class FastWriter // ////////////////////////////////////////////////////////////////// FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), - omitEndingLineFeed_(false) {} -void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + = default; + +void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } -JSONCPP_STRING FastWriter::write(const Value& root) { +String FastWriter::write(const Value& root) { document_.clear(); writeValue(root); if (!omitEndingLineFeed_) - document_ += "\n"; + document_ += '\n'; return document_; } @@ -356,13 +391,13 @@ void FastWriter::writeValue(const Value& value) { case realValue: document_ += valueToString(value.asDouble()); break; - case stringValue: - { + case stringValue: { // Is NULL possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str)); + if (ok) + document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str)); break; } case booleanValue: @@ -381,13 +416,13 @@ void FastWriter::writeValue(const Value& value) { case objectValue: { Value::Members members(value.getMemberNames()); document_ += '{'; - for (Value::Members::iterator it = members.begin(); it != members.end(); - ++it) { - const JSONCPP_STRING& name = *it; + for (auto it = members.begin(); it != members.end(); ++it) { + const String& name = *it; if (it != members.begin()) document_ += ','; - document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + document_ += valueToQuotedStringN(name.data(), + static_cast<unsigned>(name.length())); + document_ += yamlCompatibilityEnabled_ ? ": " : ":"; writeValue(value[name]); } document_ += '}'; @@ -398,17 +433,16 @@ void FastWriter::writeValue(const Value& value) { // Class StyledWriter // ////////////////////////////////////////////////////////////////// -StyledWriter::StyledWriter() - : rightMargin_(74), indentSize_(3), addChildValues_() {} +StyledWriter::StyledWriter() = default; -JSONCPP_STRING StyledWriter::write(const Value& root) { +String StyledWriter::write(const Value& root) { document_.clear(); addChildValues_ = false; indentString_.clear(); writeCommentBeforeValue(root); writeValue(root); writeCommentAfterValueOnSameLine(root); - document_ += "\n"; + document_ += '\n'; return document_; } @@ -426,14 +460,15 @@ void StyledWriter::writeValue(const Value& value) { case realValue: pushValue(valueToString(value.asDouble())); break; - case stringValue: - { + case stringValue: { // Is NULL possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); - else pushValue(""); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); + else + pushValue(""); break; } case booleanValue: @@ -449,9 +484,9 @@ void StyledWriter::writeValue(const Value& value) { else { writeWithIndent("{"); indent(); - Value::Members::iterator it = members.begin(); + auto it = members.begin(); for (;;) { - const JSONCPP_STRING& name = *it; + const String& name = *it; const Value& childValue = value[name]; writeCommentBeforeValue(childValue); writeWithIndent(valueToQuotedString(name.c_str())); @@ -476,7 +511,7 @@ void StyledWriter::writeArrayValue(const Value& value) { if (size == 0) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { writeWithIndent("["); indent(); @@ -514,14 +549,14 @@ void StyledWriter::writeArrayValue(const Value& value) { } } -bool StyledWriter::isMultineArray(const Value& value) { +bool StyledWriter::isMultilineArray(const Value& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { const Value& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + !childValue.empty()); } if (!isMultiLine) // check if line length > max line length { @@ -541,7 +576,7 @@ bool StyledWriter::isMultineArray(const Value& value) { return isMultiLine; } -void StyledWriter::pushValue(const JSONCPP_STRING& value) { +void StyledWriter::pushValue(const String& value) { if (addChildValues_) childValues_.push_back(value); else @@ -559,12 +594,12 @@ void StyledWriter::writeIndent() { document_ += indentString_; } -void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) { +void StyledWriter::writeWithIndent(const String& value) { writeIndent(); document_ += value; } -void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); } +void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); } void StyledWriter::unindent() { assert(indentString_.size() >= indentSize_); @@ -575,20 +610,19 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) { if (!root.hasComment(commentBefore)) return; - document_ += "\n"; + document_ += '\n'; writeIndent(); - const JSONCPP_STRING& comment = root.getComment(commentBefore); - JSONCPP_STRING::const_iterator iter = comment.begin(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); while (iter != comment.end()) { document_ += *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) writeIndent(); ++iter; } // Comments are stripped of trailing newlines, so add one here - document_ += "\n"; + document_ += '\n'; } void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { @@ -596,9 +630,9 @@ void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { document_ += " " + root.getComment(commentAfterOnSameLine); if (root.hasComment(commentAfter)) { - document_ += "\n"; + document_ += '\n'; document_ += root.getComment(commentAfter); - document_ += "\n"; + document_ += '\n'; } } @@ -611,22 +645,23 @@ bool StyledWriter::hasCommentForValue(const Value& value) { // Class StyledStreamWriter // ////////////////////////////////////////////////////////////////// -StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation) - : document_(NULL), rightMargin_(74), indentation_(indentation), - addChildValues_() {} +StyledStreamWriter::StyledStreamWriter(String indentation) + : document_(nullptr), indentation_(std::move(indentation)), + addChildValues_(), indented_(false) {} -void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) { +void StyledStreamWriter::write(OStream& out, const Value& root) { document_ = &out; addChildValues_ = false; indentString_.clear(); indented_ = true; writeCommentBeforeValue(root); - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(root); writeCommentAfterValueOnSameLine(root); *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. + document_ = nullptr; // Forget the stream, for safety. } void StyledStreamWriter::writeValue(const Value& value) { @@ -643,14 +678,15 @@ void StyledStreamWriter::writeValue(const Value& value) { case realValue: pushValue(valueToString(value.asDouble())); break; - case stringValue: - { + case stringValue: { // Is NULL possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); - else pushValue(""); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); + else + pushValue(""); break; } case booleanValue: @@ -666,9 +702,9 @@ void StyledStreamWriter::writeValue(const Value& value) { else { writeWithIndent("{"); indent(); - Value::Members::iterator it = members.begin(); + auto it = members.begin(); for (;;) { - const JSONCPP_STRING& name = *it; + const String& name = *it; const Value& childValue = value[name]; writeCommentBeforeValue(childValue); writeWithIndent(valueToQuotedString(name.c_str())); @@ -693,7 +729,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { if (size == 0) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { writeWithIndent("["); indent(); @@ -705,7 +741,8 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { if (hasChildValue) writeWithIndent(childValues_[index]); else { - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(childValue); indented_ = false; @@ -733,14 +770,14 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { } } -bool StyledStreamWriter::isMultineArray(const Value& value) { +bool StyledStreamWriter::isMultilineArray(const Value& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { const Value& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + !childValue.empty()); } if (!isMultiLine) // check if line length > max line length { @@ -760,7 +797,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) { return isMultiLine; } -void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) { +void StyledStreamWriter::pushValue(const String& value) { if (addChildValues_) childValues_.push_back(value); else @@ -775,8 +812,9 @@ void StyledStreamWriter::writeIndent() { *document_ << '\n' << indentString_; } -void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) { - if (!indented_) writeIndent(); +void StyledStreamWriter::writeWithIndent(const String& value) { + if (!indented_) + writeIndent(); *document_ << value; indented_ = false; } @@ -792,13 +830,13 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { if (!root.hasComment(commentBefore)) return; - if (!indented_) writeIndent(); - const JSONCPP_STRING& comment = root.getComment(commentBefore); - JSONCPP_STRING::const_iterator iter = comment.begin(); + if (!indented_) + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); while (iter != comment.end()) { *document_ << *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) // writeIndent(); // would include newline *document_ << indentString_; ++iter; @@ -830,84 +868,73 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) { struct CommentStyle { /// Decide whether to write comments. enum Enum { - None, ///< Drop all comments. - Most, ///< Recover odd behavior of previous versions (not implemented yet). - All ///< Keep all comments. + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. }; }; -struct BuiltStyledStreamWriter : public StreamWriter -{ - BuiltStyledStreamWriter( - JSONCPP_STRING const& indentation, - CommentStyle::Enum cs, - JSONCPP_STRING const& colonSymbol, - JSONCPP_STRING const& nullSymbol, - JSONCPP_STRING const& endingLineFeedSymbol, - bool useSpecialFloats, - unsigned int precision); - int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE; +struct BuiltStyledStreamWriter : public StreamWriter { + BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs, + String colonSymbol, String nullSymbol, + String endingLineFeedSymbol, bool useSpecialFloats, + bool emitUTF8, unsigned int precision, + PrecisionType precisionType); + int write(Value const& root, OStream* sout) override; + private: void writeValue(Value const& value); void writeArrayValue(Value const& value); - bool isMultineArray(Value const& value); - void pushValue(JSONCPP_STRING const& value); + bool isMultilineArray(Value const& value); + void pushValue(String const& value); void writeIndent(); - void writeWithIndent(JSONCPP_STRING const& value); + void writeWithIndent(String const& value); void indent(); void unindent(); void writeCommentBeforeValue(Value const& root); void writeCommentAfterValueOnSameLine(Value const& root); static bool hasCommentForValue(const Value& value); - typedef std::vector<JSONCPP_STRING> ChildValues; + using ChildValues = std::vector<String>; ChildValues childValues_; - JSONCPP_STRING indentString_; + String indentString_; unsigned int rightMargin_; - JSONCPP_STRING indentation_; + String indentation_; CommentStyle::Enum cs_; - JSONCPP_STRING colonSymbol_; - JSONCPP_STRING nullSymbol_; - JSONCPP_STRING endingLineFeedSymbol_; + String colonSymbol_; + String nullSymbol_; + String endingLineFeedSymbol_; bool addChildValues_ : 1; bool indented_ : 1; bool useSpecialFloats_ : 1; + bool emitUTF8_ : 1; unsigned int precision_; + PrecisionType precisionType_; }; BuiltStyledStreamWriter::BuiltStyledStreamWriter( - JSONCPP_STRING const& indentation, - CommentStyle::Enum cs, - JSONCPP_STRING const& colonSymbol, - JSONCPP_STRING const& nullSymbol, - JSONCPP_STRING const& endingLineFeedSymbol, - bool useSpecialFloats, - unsigned int precision) - : rightMargin_(74) - , indentation_(indentation) - , cs_(cs) - , colonSymbol_(colonSymbol) - , nullSymbol_(nullSymbol) - , endingLineFeedSymbol_(endingLineFeedSymbol) - , addChildValues_(false) - , indented_(false) - , useSpecialFloats_(useSpecialFloats) - , precision_(precision) -{ -} -int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout) -{ + String indentation, CommentStyle::Enum cs, String colonSymbol, + String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats, + bool emitUTF8, unsigned int precision, PrecisionType precisionType) + : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs), + colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)), + endingLineFeedSymbol_(std::move(endingLineFeedSymbol)), + addChildValues_(false), indented_(false), + useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8), + precision_(precision), precisionType_(precisionType) {} +int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) { sout_ = sout; addChildValues_ = false; indented_ = true; indentString_.clear(); writeCommentBeforeValue(root); - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(root); writeCommentAfterValueOnSameLine(root); *sout_ << endingLineFeedSymbol_; - sout_ = NULL; + sout_ = nullptr; return 0; } void BuiltStyledStreamWriter::writeValue(Value const& value) { @@ -922,16 +949,19 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { pushValue(valueToString(value.asLargestUInt())); break; case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, + precisionType_)); break; - case stringValue: - { + case stringValue: { // Is NULL is possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); - else pushValue(""); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str), + emitUTF8_)); + else + pushValue(""); break; } case booleanValue: @@ -947,12 +977,13 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { else { writeWithIndent("{"); indent(); - Value::Members::iterator it = members.begin(); + auto it = members.begin(); for (;;) { - JSONCPP_STRING const& name = *it; + String const& name = *it; Value const& childValue = value[name]; writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()))); + writeWithIndent(valueToQuotedStringN( + name.data(), static_cast<unsigned>(name.length()), emitUTF8_)); *sout_ << colonSymbol_; writeValue(childValue); if (++it == members.end()) { @@ -974,7 +1005,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { if (size == 0) pushValue("[]"); else { - bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); + bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); if (isMultiLine) { writeWithIndent("["); indent(); @@ -986,7 +1017,8 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { if (hasChildValue) writeWithIndent(childValues_[index]); else { - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(childValue); indented_ = false; @@ -1004,26 +1036,28 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { { assert(childValues_.size() == size); *sout_ << "["; - if (!indentation_.empty()) *sout_ << " "; + if (!indentation_.empty()) + *sout_ << " "; for (unsigned index = 0; index < size; ++index) { if (index > 0) *sout_ << ((!indentation_.empty()) ? ", " : ","); *sout_ << childValues_[index]; } - if (!indentation_.empty()) *sout_ << " "; + if (!indentation_.empty()) + *sout_ << " "; *sout_ << "]"; } } } -bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { +bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { Value const& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + !childValue.empty()); } if (!isMultiLine) // check if line length > max line length { @@ -1043,7 +1077,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { return isMultiLine; } -void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) { +void BuiltStyledStreamWriter::pushValue(String const& value) { if (addChildValues_) childValues_.push_back(value); else @@ -1062,8 +1096,9 @@ void BuiltStyledStreamWriter::writeIndent() { } } -void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) { - if (!indented_) writeIndent(); +void BuiltStyledStreamWriter::writeWithIndent(String const& value) { + if (!indented_) + writeIndent(); *sout_ << value; indented_ = false; } @@ -1076,17 +1111,18 @@ void BuiltStyledStreamWriter::unindent() { } void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { - if (cs_ == CommentStyle::None) return; + if (cs_ == CommentStyle::None) + return; if (!root.hasComment(commentBefore)) return; - if (!indented_) writeIndent(); - const JSONCPP_STRING& comment = root.getComment(commentBefore); - JSONCPP_STRING::const_iterator iter = comment.begin(); + if (!indented_) + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); while (iter != comment.end()) { *sout_ << *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) // writeIndent(); // would write extra newline *sout_ << indentString_; ++iter; @@ -1094,8 +1130,10 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { indented_ = false; } -void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { - if (cs_ == CommentStyle::None) return; +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( + Value const& root) { + if (cs_ == CommentStyle::None) + return; if (root.hasComment(commentAfterOnSameLine)) *sout_ << " " + root.getComment(commentAfterOnSameLine); @@ -1115,28 +1153,19 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { /////////////// // StreamWriter -StreamWriter::StreamWriter() - : sout_(NULL) -{ -} -StreamWriter::~StreamWriter() -{ -} -StreamWriter::Factory::~Factory() -{} -StreamWriterBuilder::StreamWriterBuilder() -{ - setDefaults(&settings_); -} -StreamWriterBuilder::~StreamWriterBuilder() -{} -StreamWriter* StreamWriterBuilder::newStreamWriter() const -{ - JSONCPP_STRING indentation = settings_["indentation"].asString(); - JSONCPP_STRING cs_str = settings_["commentStyle"].asString(); - bool eyc = settings_["enableYAMLCompatibility"].asBool(); - bool dnp = settings_["dropNullPlaceholders"].asBool(); - bool usf = settings_["useSpecialFloats"].asBool(); +StreamWriter::StreamWriter() : sout_(nullptr) {} +StreamWriter::~StreamWriter() = default; +StreamWriter::Factory::~Factory() = default; +StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } +StreamWriterBuilder::~StreamWriterBuilder() = default; +StreamWriter* StreamWriterBuilder::newStreamWriter() const { + const String indentation = settings_["indentation"].asString(); + const String cs_str = settings_["commentStyle"].asString(); + const String pt_str = settings_["precisionType"].asString(); + const bool eyc = settings_["enableYAMLCompatibility"].asBool(); + const bool dnp = settings_["dropNullPlaceholders"].asBool(); + const bool usf = settings_["useSpecialFloats"].asBool(); + const bool emitUTF8 = settings_["emitUTF8"].asBool(); unsigned int pre = settings_["precision"].asUInt(); CommentStyle::Enum cs = CommentStyle::All; if (cs_str == "All") { @@ -1146,74 +1175,80 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const } else { throwRuntimeError("commentStyle must be 'All' or 'None'"); } - JSONCPP_STRING colonSymbol = " : "; + PrecisionType precisionType(significantDigits); + if (pt_str == "significant") { + precisionType = PrecisionType::significantDigits; + } else if (pt_str == "decimal") { + precisionType = PrecisionType::decimalPlaces; + } else { + throwRuntimeError("precisionType must be 'significant' or 'decimal'"); + } + String colonSymbol = " : "; if (eyc) { colonSymbol = ": "; } else if (indentation.empty()) { colonSymbol = ":"; } - JSONCPP_STRING nullSymbol = "null"; + String nullSymbol = "null"; if (dnp) { nullSymbol.clear(); } - if (pre > 17) pre = 17; - JSONCPP_STRING endingLineFeedSymbol; - return new BuiltStyledStreamWriter( - indentation, cs, - colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); + if (pre > 17) + pre = 17; + String endingLineFeedSymbol; + return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, + endingLineFeedSymbol, usf, emitUTF8, pre, + precisionType); } -static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys) -{ - valid_keys->clear(); - valid_keys->insert("indentation"); - valid_keys->insert("commentStyle"); - valid_keys->insert("enableYAMLCompatibility"); - valid_keys->insert("dropNullPlaceholders"); - valid_keys->insert("useSpecialFloats"); - valid_keys->insert("precision"); -} -bool StreamWriterBuilder::validate(Json::Value* invalid) const -{ - Json::Value my_invalid; - if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set<JSONCPP_STRING> valid_keys; - getValidWriterKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - JSONCPP_STRING const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } + +bool StreamWriterBuilder::validate(Json::Value* invalid) const { + static const auto& valid_keys = *new std::set<String>{ + "indentation", + "commentStyle", + "enableYAMLCompatibility", + "dropNullPlaceholders", + "useSpecialFloats", + "emitUTF8", + "precision", + "precisionType", + }; + for (auto si = settings_.begin(); si != settings_.end(); ++si) { + auto key = si.name(); + if (valid_keys.count(key)) + continue; + if (invalid) + (*invalid)[std::move(key)] = *si; + else + return false; } - return 0u == inv.size(); + return invalid ? invalid->empty() : true; } -Value& StreamWriterBuilder::operator[](JSONCPP_STRING key) -{ + +Value& StreamWriterBuilder::operator[](const String& key) { return settings_[key]; } // static -void StreamWriterBuilder::setDefaults(Json::Value* settings) -{ +void StreamWriterBuilder::setDefaults(Json::Value* settings) { //! [StreamWriterBuilderDefaults] (*settings)["commentStyle"] = "All"; (*settings)["indentation"] = "\t"; (*settings)["enableYAMLCompatibility"] = false; (*settings)["dropNullPlaceholders"] = false; (*settings)["useSpecialFloats"] = false; + (*settings)["emitUTF8"] = false; (*settings)["precision"] = 17; + (*settings)["precisionType"] = "significant"; //! [StreamWriterBuilderDefaults] } -JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) { - JSONCPP_OSTRINGSTREAM sout; - StreamWriterPtr const writer(builder.newStreamWriter()); +String writeString(StreamWriter::Factory const& factory, Value const& root) { + OStringStream sout; + StreamWriterPtr const writer(factory.newStreamWriter()); writer->write(root, &sout); return sout.str(); } -JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) { +OStream& operator<<(OStream& sout, Value const& root) { StreamWriterBuilder builder; StreamWriterPtr const writer(builder.newStreamWriter()); writer->write(root, &sout); From 0627020baed909c610ffcd663ebd0083006fe421 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 10 Sep 2021 00:01:15 -0400 Subject: [PATCH 1203/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ea70d2a62bb..6e3cf1f0e63 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210909) +set(CMake_VERSION_PATCH 20210910) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 3c2e58eeb884adea8ee12462f7d471ab518a673f Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Thu, 2 Sep 2021 17:52:37 +0200 Subject: [PATCH 1204/1519] AddCacheEntry accept cmProp or std::string --- Source/cmCacheManager.cxx | 6 +++--- Source/cmCacheManager.h | 16 ++++++++++++++-- Source/cmState.cxx | 2 +- Source/cmState.h | 12 ++++++++++++ Source/cmake.cxx | 2 +- Source/cmake.h | 12 ++++++++++++ 6 files changed, 43 insertions(+), 7 deletions(-) diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 8fefaa6b657..0b59840a9a9 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -521,7 +521,7 @@ void cmCacheManager::PrintCache(std::ostream& out) const "=================================================\n"; } -void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, +void cmCacheManager::AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type) { @@ -550,10 +550,10 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, : "(This variable does not exist and should not be used)"); } -void cmCacheManager::CacheEntry::SetValue(const char* value) +void cmCacheManager::CacheEntry::SetValue(cmProp value) { if (value) { - this->Value = value; + this->Value = *value; this->Initialized = true; } else { this->Value.clear(); diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index 0238fb8e0cd..eca7150d3d4 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -31,7 +31,7 @@ class cmCacheManager public: const std::string& GetValue() const { return this->Value; } - void SetValue(const char*); + void SetValue(cmProp); cmStateEnums::CacheEntryType GetType() const { return this->Type; } void SetType(cmStateEnums::CacheEntryType ty) { this->Type = ty; } @@ -83,7 +83,7 @@ class cmCacheManager void SetCacheEntryValue(std::string const& key, std::string const& value) { if (auto* entry = this->GetCacheEntry(key)) { - entry->SetValue(value.c_str()); + entry->SetValue(cmProp(value)); } } @@ -173,6 +173,18 @@ class cmCacheManager //! Add an entry into the cache void AddCacheEntry(const std::string& key, const char* value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, + value ? cmProp(std::string(value)) : cmProp(nullptr), + helpString, type); + } + void AddCacheEntry(const std::string& key, const std::string& value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, cmProp(value), helpString, type); + } + void AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a045545971f..5a1ff278b44 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -206,7 +206,7 @@ bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, return this->CacheManager->GetCacheEntryPropertyAsBool(key, propertyName); } -void cmState::AddCacheEntry(const std::string& key, const char* value, +void cmState::AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type) { diff --git a/Source/cmState.h b/Source/cmState.h index 0fd28d08950..390f6d6f23f 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -219,6 +219,18 @@ class cmState private: friend class cmake; void AddCacheEntry(const std::string& key, const char* value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, + value ? cmProp(std::string(value)) : cmProp(nullptr), + helpString, type); + } + void AddCacheEntry(const std::string& key, const std::string& value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, cmProp(value), helpString, type); + } + void AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index beb5d1617f3..62ee380ebf4 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2416,7 +2416,7 @@ int cmake::Generate() return 0; } -void cmake::AddCacheEntry(const std::string& key, const char* value, +void cmake::AddCacheEntry(const std::string& key, cmProp value, const char* helpString, int type) { this->State->AddCacheEntry(key, value, helpString, diff --git a/Source/cmake.h b/Source/cmake.h index 32c75824228..74080440c5f 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -332,6 +332,18 @@ class cmake cmProp GetCacheDefinition(const std::string&) const; //! Add an entry into the cache void AddCacheEntry(const std::string& key, const char* value, + const char* helpString, int type) + { + this->AddCacheEntry(key, + value ? cmProp(std::string(value)) : cmProp(nullptr), + helpString, type); + } + void AddCacheEntry(const std::string& key, const std::string& value, + const char* helpString, int type) + { + this->AddCacheEntry(key, cmProp(value), helpString, type); + } + void AddCacheEntry(const std::string& key, cmProp value, const char* helpString, int type); bool DoWriteGlobVerifyTarget() const; From f84193292cb36e26d13a3f1f56a1539f088e8827 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Thu, 2 Sep 2021 18:42:21 +0200 Subject: [PATCH 1205/1519] Use new AddCacheEntry signatures --- Source/cmCacheManager.cxx | 8 +-- Source/cmFindBase.cxx | 4 +- Source/cmGlobalCommonGenerator.cxx | 2 +- Source/cmGlobalGenerator.cxx | 5 +- ...cmGlobalVisualStudioVersionedGenerator.cxx | 6 +- Source/cmGlobalXCodeGenerator.cxx | 5 +- Source/cmIncludeExternalMSProjectCommand.cxx | 5 +- Source/cmLocalVisualStudio7Generator.cxx | 2 +- Source/cmMakefile.cxx | 8 +-- Source/cmake.cxx | 58 +++++++++---------- 10 files changed, 47 insertions(+), 56 deletions(-) diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 0b59840a9a9..17369c8d3f4 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -232,17 +232,17 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) // before writing the cache, update the version numbers // to the this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", - std::to_string(cmVersion::GetMajorVersion()).c_str(), + std::to_string(cmVersion::GetMajorVersion()), "Major version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", - std::to_string(cmVersion::GetMinorVersion()).c_str(), + std::to_string(cmVersion::GetMinorVersion()), "Minor version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", - std::to_string(cmVersion::GetPatchVersion()).c_str(), + std::to_string(cmVersion::GetPatchVersion()), "Patch version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); @@ -256,7 +256,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a'); } cmSystemTools::ConvertToUnixSlashes(currentcwd); - this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(), + this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd, "This is the directory where this CMakeCache.txt" " was created", cmStateEnums::INTERNAL); diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index f4e1763e7fc..37f95727011 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -358,8 +358,8 @@ void cmFindBase::NormalizeFindResult() // value. if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) { this->Makefile->GetCMakeInstance()->AddCacheEntry( - this->VariableName, value.c_str(), - this->VariableDocumentation.c_str(), this->VariableType); + this->VariableName, value, this->VariableDocumentation.c_str(), + this->VariableType); if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW) { if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) { diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index a8e0f235a48..24c8944fe9e 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -117,7 +117,7 @@ std::string cmGlobalCommonGenerator::GetEditCacheCommand() const editCacheCommand = cmSystemTools::GetCMakeGUICommand(); } if (!editCacheCommand.empty()) { - cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), + cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand, "Path to cache edit program executable.", cmStateEnums::INTERNAL); } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 3561deb8800..6b37b4b8cc4 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2191,9 +2191,8 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen, this->TryCompileOuterMakefile = mf; cmProp make = gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); - this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", cmToCStr(make), - "make program", - cmStateEnums::FILEPATH); + this->GetCMakeInstance()->AddCacheEntry( + "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH); // copy the enabled languages this->GetCMakeInstance()->GetState()->SetEnabledLanguages( gen->GetCMakeInstance()->GetState()->GetEnabledLanguages()); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index d0ad53e984a..3ecf32e2451 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -467,9 +467,9 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( // Save the selected instance persistently. std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); if (vsInstance != genInstance) { - this->CMakeInstance->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); + this->CMakeInstance->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", vsInstance, + "Generator instance identifier.", + cmStateEnums::INTERNAL); } return true; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 763f12a3a94..fa76b010b56 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3241,9 +3241,8 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name, return *storedGUID; } - this->CMakeInstance->AddCacheEntry(guidStoreName, id.c_str(), - "Stored Xcode object GUID", - cmStateEnums::INTERNAL); + this->CMakeInstance->AddCacheEntry( + guidStoreName, id, "Stored Xcode object GUID", cmStateEnums::INTERNAL); return id; } diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx index 5b532ce0fad..c8b4a39e737 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -77,9 +77,8 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args, if (!customGuid.empty()) { std::string guidVariable = utility_name + "_GUID_CMAKE"; - mf.GetCMakeInstance()->AddCacheEntry(guidVariable, customGuid.c_str(), - "Stored GUID", - cmStateEnums::INTERNAL); + mf.GetCMakeInstance()->AddCacheEntry( + guidVariable, customGuid, "Stored GUID", cmStateEnums::INTERNAL); } // Create a target instance for this utility. diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 151470b4e5f..46bd5246527 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -2142,7 +2142,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); // save the GUID in the cache this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry( - guidStoreName, parser.GUID.c_str(), "Stored GUID", cmStateEnums::INTERNAL); + guidStoreName, parser.GUID, "Stored GUID", cmStateEnums::INTERNAL); } std::string cmLocalVisualStudio7Generator::GetTargetDirectory( diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 7abbd319238..7b2563c4051 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1955,7 +1955,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, nvalue += files[cc]; } - this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type); + this->GetCMakeInstance()->AddCacheEntry(name, nvalue, doc, type); nvalue = *this->GetState()->GetInitializedCacheValue(name); value = nvalue.c_str(); } @@ -3589,13 +3589,13 @@ int cmMakefile::TryCompile(const std::string& srcdir, // Tell the single-configuration generator which one to use. // Add this before the user-provided CMake arguments in case // one of the arguments is -DCMAKE_BUILD_TYPE=... - cm.AddCacheEntry("CMAKE_BUILD_TYPE", config->c_str(), - "Build configuration", cmStateEnums::STRING); + cm.AddCacheEntry("CMAKE_BUILD_TYPE", config, "Build configuration", + cmStateEnums::STRING); } } cmProp recursionDepth = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); if (recursionDepth) { - cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth->c_str(), + cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth, "Maximum recursion depth", cmStateEnums::STRING); } // if cmake args were provided then pass them in diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 62ee380ebf4..7cafaee92d7 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -605,9 +605,8 @@ void cmake::ProcessCacheArg(const std::string& var, const std::string& value, } } - this->AddCacheEntry(var, value.c_str(), - "No help, variable specified on the command line.", - type); + this->AddCacheEntry( + var, value, "No help, variable specified on the command line.", type); if (this->WarnUnusedCli) { if (!haveValue || @@ -1517,16 +1516,15 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) int cmake::AddCMakePaths() { // Save the value in the cache - this->AddCacheEntry("CMAKE_COMMAND", - cmSystemTools::GetCMakeCommand().c_str(), + this->AddCacheEntry("CMAKE_COMMAND", cmSystemTools::GetCMakeCommand(), "Path to CMake executable.", cmStateEnums::INTERNAL); #ifndef CMAKE_BOOTSTRAP - this->AddCacheEntry( - "CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(), - "Path to ctest program executable.", cmStateEnums::INTERNAL); - this->AddCacheEntry( - "CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand().c_str(), - "Path to cpack program executable.", cmStateEnums::INTERNAL); + this->AddCacheEntry("CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand(), + "Path to ctest program executable.", + cmStateEnums::INTERNAL); + this->AddCacheEntry("CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand(), + "Path to cpack program executable.", + cmStateEnums::INTERNAL); #endif if (!cmSystemTools::FileExists( (cmSystemTools::GetCMakeRoot() + "/Modules/CMake.cmake"))) { @@ -1538,7 +1536,7 @@ int cmake::AddCMakePaths() cmSystemTools::GetCMakeRoot()); return 0; } - this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot().c_str(), + this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot(), "Path to CMake installation.", cmStateEnums::INTERNAL); return 1; @@ -1886,7 +1884,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) this->LoadCache(); // restore the changed compilers for (SaveCacheEntry const& i : saved) { - this->AddCacheEntry(i.key, i.value.c_str(), i.help.c_str(), i.type); + this->AddCacheEntry(i.key, i.value, i.help.c_str(), i.type); } cmSystemTools::Message(warning.str()); // avoid reconfigure if there were errors @@ -1993,7 +1991,7 @@ int cmake::ActualConfigure() } if (!res) { this->AddCacheEntry( - "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory().c_str(), + "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory(), "Source directory with the top level CMakeLists.txt file for this " "project", cmStateEnums::INTERNAL); @@ -2038,19 +2036,17 @@ int cmake::ActualConfigure() } } if (!this->State->GetInitializedCacheValue("CMAKE_GENERATOR")) { - this->AddCacheEntry("CMAKE_GENERATOR", - this->GlobalGenerator->GetName().c_str(), + this->AddCacheEntry("CMAKE_GENERATOR", this->GlobalGenerator->GetName(), "Name of generator.", cmStateEnums::INTERNAL); - this->AddCacheEntry("CMAKE_EXTRA_GENERATOR", - this->GlobalGenerator->GetExtraGeneratorName().c_str(), - "Name of external makefile project generator.", - cmStateEnums::INTERNAL); + this->AddCacheEntry( + "CMAKE_EXTRA_GENERATOR", this->GlobalGenerator->GetExtraGeneratorName(), + "Name of external makefile project generator.", cmStateEnums::INTERNAL); if (!this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) { std::string envToolchain; if (cmSystemTools::GetEnv("CMAKE_TOOLCHAIN_FILE", envToolchain) && !envToolchain.empty()) { - this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain.c_str(), + this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain, "The CMake toolchain file", cmStateEnums::FILEPATH); } @@ -2069,9 +2065,9 @@ int cmake::ActualConfigure() return -2; } } else { - this->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); + this->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance, + "Generator instance identifier.", + cmStateEnums::INTERNAL); } if (cmProp platformName = @@ -2087,8 +2083,7 @@ int cmake::ActualConfigure() return -2; } } else { - this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM", - this->GeneratorPlatform.c_str(), + this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform, "Name of generator platform.", cmStateEnums::INTERNAL); } @@ -2104,8 +2099,7 @@ int cmake::ActualConfigure() return -2; } } else { - this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET", - this->GeneratorToolset.c_str(), + this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset, "Name of generator toolset.", cmStateEnums::INTERNAL); } @@ -3540,7 +3534,7 @@ void cmake::SetSuppressDevWarnings(bool b) value = "FALSE"; } - this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value.c_str(), + this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value, "Suppress Warnings that are meant for" " the author of the CMakeLists.txt files.", cmStateEnums::INTERNAL); @@ -3564,7 +3558,7 @@ void cmake::SetSuppressDeprecatedWarnings(bool b) value = "TRUE"; } - this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value.c_str(), + this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value, "Whether to issue warnings for deprecated " "functionality.", cmStateEnums::INTERNAL); @@ -3588,7 +3582,7 @@ void cmake::SetDevWarningsAsErrors(bool b) value = "TRUE"; } - this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value.c_str(), + this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value, "Suppress errors that are meant for" " the author of the CMakeLists.txt files.", cmStateEnums::INTERNAL); @@ -3612,7 +3606,7 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b) value = "FALSE"; } - this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value.c_str(), + this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value, "Whether to issue deprecation errors for macros" " and functions.", cmStateEnums::INTERNAL); From 059b90a0b4760c3c0bb761870be2a0811f80ce70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= <daschuer@mixxx.org> Date: Sun, 29 Aug 2021 23:05:38 +0200 Subject: [PATCH 1206/1519] CMakeDependentOption: Introduce policy CMP0127 for full Condition Syntax Fixes: #22303 --- Help/manual/cmake-policies.7.rst | 8 +++ Help/policy/CMP0127.rst | 32 ++++++++++ .../dev/cmake_dependent_option_policy.rst | 6 ++ Modules/CMakeDependentOption.cmake | 61 +++++++++++++------ Source/cmPolicies.h | 5 +- ...txt => Parentheses-CMP0127-NEW-stdout.txt} | 0 .../Parentheses-CMP0127-NEW.cmake | 9 +++ .../Parentheses-CMP0127-WARN-stderr.txt | 9 +++ .../Parentheses-CMP0127-WARN-stdout.txt | 2 + .../Parentheses-CMP0127-WARN.cmake | 9 +++ .../Regex-CMP0127-NEW-stdout.txt | 1 + .../Regex-CMP0127-NEW.cmake | 7 +++ .../Regex-CMP0127-OLD-stdout.txt | 1 + .../{Regex.cmake => Regex-CMP0127-OLD.cmake} | 2 + .../CMakeDependentOption/RunCMakeTest.cmake | 5 +- .../Simple-CMP0127-OLD-stdout.txt | 1 + .../Simple-CMP0127-OLD.cmake | 6 ++ 17 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 Help/policy/CMP0127.rst create mode 100644 Help/release/dev/cmake_dependent_option_policy.rst rename Tests/RunCMake/CMakeDependentOption/{Regex-stdout.txt => Parentheses-CMP0127-NEW-stdout.txt} (100%) create mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake create mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt create mode 100644 Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake create mode 100644 Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt create mode 100644 Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake create mode 100644 Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt rename Tests/RunCMake/CMakeDependentOption/{Regex.cmake => Regex-CMP0127-OLD.cmake} (84%) create mode 100644 Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt create mode 100644 Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index b9e3d452fdd..0f0c0abbecd 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.22 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0127: cmake_dependent_option() supports full Condition Syntax. </policy/CMP0127> + Policies Introduced by CMake 3.21 ================================= diff --git a/Help/policy/CMP0127.rst b/Help/policy/CMP0127.rst new file mode 100644 index 00000000000..8560bbf615c --- /dev/null +++ b/Help/policy/CMP0127.rst @@ -0,0 +1,32 @@ +CMP0127 +------- + +:command:`cmake_dependent_option` supports full :ref:`Condition Syntax`. + +The ``<depends>`` parameter accepts a :ref:`semicolon-separated list <CMake +Language Lists>` of conditions. CMake 3.21 and lower evaluates each +``condition`` as ``if(${condition})``, which does not properly handle +conditions with nested paren groups. CMake 3.22 and above instead prefer +to evaluate each ``condition`` as ``if(<condition>)``, where ``<condition>`` +is re-parsed as if literally written in a call to :command:`if`. This +allows expressions like:: + + "A AND (B OR C)" + +but requires expressions like:: + + "FOO MATCHES (UPPER|lower)" + +to be re-written as:: + + "FOO MATCHES \"(UPPER|lower)\"" + +Policy ``CMP0127`` provides compatibility for projects that have not +been updated to expect the new behavior. + +This policy was introduced in CMake version 3.22. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/cmake_dependent_option_policy.rst b/Help/release/dev/cmake_dependent_option_policy.rst new file mode 100644 index 00000000000..c1311700ff9 --- /dev/null +++ b/Help/release/dev/cmake_dependent_option_policy.rst @@ -0,0 +1,6 @@ +cmake_dependent_option_policy +----------------------------- + +* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` + macro now supports full :ref:`Condition Syntax`. + See policy :policy:`CMP0127`. diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index 96855d28f1c..b7c478f6440 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -10,44 +10,62 @@ Macro to provide an option dependent on other options. This macro presents an option to the user only if a set of other conditions are true. -Usage: +.. command:: cmake_dependent_option -.. code-block:: cmake + .. code-block:: cmake - cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) + cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) -Where ``<option>`` is available to the user if ``<depends>`` is true. When -``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` -are used. If the ``<depends>`` condition is not true, ``<option>`` will not be -presented and will always have the value given by ``<force>``. Any value set by -the user is preserved for when the option is presented again. Each element in -the fourth parameter is evaluated as an if-condition, so -:ref:`Condition Syntax` can be used. + Makes ``<option>`` available to the user if ``<depends>`` is true. When + ``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` + are used. If the ``<depends>`` condition is not true, ``<option>`` will not be + presented and will always have the value given by ``<force>``. Any value set by + the user is preserved for when the option is presented again. In case ``<depends>`` + is a :ref:`semicolon-separated list <CMake Language Lists>`, all elements must + be true in order to initialize ``<option>`` with ``<value>``. Example invocation: .. code-block:: cmake - cmake_dependent_option(USE_FOO "Use Foo" ON - "USE_BAR;NOT USE_ZOT" OFF) + cmake_dependent_option(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF) If ``USE_BAR`` is true and ``USE_ZOT`` is false, this provides an option called ``USE_FOO`` that defaults to ON. Otherwise, it sets ``USE_FOO`` to OFF and hides the option from the user. If the status of ``USE_BAR`` or ``USE_ZOT`` ever changes, any value for the ``USE_FOO`` option is saved so that when the option is re-enabled it retains its old value. + +.. versionadded:: 3.22 + + Full :ref:`Condition Syntax` is now supported. See policy :policy:`CMP0127`. + #]=======================================================================] macro(CMAKE_DEPENDENT_OPTION option doc default depends force) + cmake_policy(GET CMP0127 _CDO_CMP0127 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) if(${option}_ISSET MATCHES "^${option}_ISSET$") set(${option}_AVAILABLE 1) - foreach(d ${depends}) - string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") - if(${CMAKE_DEPENDENT_OPTION_DEP}) - else() - set(${option}_AVAILABLE 0) - endif() - endforeach() + if("x${_CDO_CMP0127}x" STREQUAL "xNEWx") + foreach(d ${depends}) + cmake_language(EVAL CODE " + if (${d}) + else() + set(${option}_AVAILABLE 0) + endif()" + ) + endforeach() + else() + foreach(d ${depends}) + string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") + if(${CMAKE_DEPENDENT_OPTION_DEP}) + else() + set(${option}_AVAILABLE 0) + endif() + endforeach() + endif() if(${option}_AVAILABLE) option(${option} "${doc}" "${default}") set(${option} "${${option}}" CACHE BOOL "${doc}" FORCE) @@ -61,4 +79,9 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force) else() set(${option} "${${option}_ISSET}") endif() + if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_; ]") + cmake_policy(GET_WARNING CMP0127 _CDO_CMP0127_WARNING) + message(AUTHOR_WARNING "${_CDO_CMP0127_WARNING}") + endif() + unset(_CDO_CMP0127) endmacro() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index f7c0d2592e7..a98e6c6df9c 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -379,7 +379,10 @@ class cmMakefile; 3, 21, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0126, \ "set(CACHE) does not remove a normal variable of the same name.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0127, \ + "cmake_dependent_option() supports full Condition Syntax.", 3, 22, \ + 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt similarity index 100% rename from Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt rename to Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake new file mode 100644 index 00000000000..5a2b018852c --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake @@ -0,0 +1,9 @@ +include(CMakeDependentOption) + +cmake_policy(SET CMP0127 NEW) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt new file mode 100644 index 00000000000..b16e84b7840 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt @@ -0,0 +1,9 @@ +^CMake Warning \(dev\) at [^ +]*/Modules/CMakeDependentOption.cmake:[0-9]+ \(message\): + Policy CMP0127 is not set: cmake_dependent_option\(\) supports full Condition + Syntax. Run "cmake --help-policy CMP0127" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. +Call Stack \(most recent call first\): + [^ +]*/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake:[0-9]+ \(cmake_dependent_option\) +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt new file mode 100644 index 00000000000..d89dbd3dbc7 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt @@ -0,0 +1,2 @@ +-- USE_FOO='OFF' +-- USE_BAR='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake new file mode 100644 index 00000000000..00d440d37e3 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake @@ -0,0 +1,9 @@ +include(CMakeDependentOption) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") +cmake_dependent_option(USE_BAR "Use Bar" ON "A;B" OFF) +message(STATUS "USE_BAR='${USE_BAR}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt new file mode 100644 index 00000000000..15b56a10d4b --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake new file mode 100644 index 00000000000..e92c1e697f1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake @@ -0,0 +1,7 @@ +include(CMakeDependentOption) + +cmake_policy(SET CMP0127 NEW) + +set(FOO "lower") +cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES \"(UPPER|lower)\"" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt new file mode 100644 index 00000000000..15b56a10d4b --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Regex.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake similarity index 84% rename from Tests/RunCMake/CMakeDependentOption/Regex.cmake rename to Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake index 8342a01b7de..81df003d9d1 100644 --- a/Tests/RunCMake/CMakeDependentOption/Regex.cmake +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake @@ -1,5 +1,7 @@ include(CMakeDependentOption) +cmake_policy(SET CMP0127 OLD) + set(FOO "lower") cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES (UPPER|lower)" OFF) message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake index e1045f2317d..61e046f8945 100644 --- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake @@ -1,3 +1,6 @@ include(RunCMake) -run_cmake_script(Regex) +run_cmake_script(Regex-CMP0127-NEW) +run_cmake_script(Regex-CMP0127-OLD) +run_cmake_script(Parentheses-CMP0127-NEW) +run_cmake_script(Parentheses-CMP0127-WARN) diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt new file mode 100644 index 00000000000..15b56a10d4b --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake new file mode 100644 index 00000000000..6db2128e347 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake @@ -0,0 +1,6 @@ +include(CMakeDependentOption) + +set(A1 1) +set(bb 1) +cmake_dependent_option(USE_FOO "Use Foo" ON "A1;bb" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") From ccfe1b0b401863a8ac9ef07bb88ef970af587edc Mon Sep 17 00:00:00 2001 From: PigeonF <fnoegip@gmail.com> Date: Wed, 8 Sep 2021 19:08:28 +0200 Subject: [PATCH 1207/1519] IWYU: Add `--driver-mode=cl` when applicable We already do this for `clang-tidy`. Fixes: #16554 --- Modules/Compiler/Clang-C.cmake | 1 + Modules/Compiler/Clang-CXX.cmake | 1 + Modules/Compiler/Intel-C.cmake | 1 + Modules/Compiler/Intel-CXX.cmake | 1 + Modules/Compiler/IntelLLVM-C.cmake | 1 + Modules/Compiler/IntelLLVM-CXX.cmake | 1 + Modules/Compiler/MSVC-C.cmake | 1 + Modules/Compiler/MSVC-CXX.cmake | 1 + Source/cmMakefileTargetGenerator.cxx | 20 +++++++++++++++++++- Source/cmNinjaTargetGenerator.cxx | 22 ++++++++++++++++++++-- 10 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index cf493d7200c..1b765ad14d1 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -9,6 +9,7 @@ endif() if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" AND CMAKE_DEPFILE_FLAGS_C) diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 98828e01192..84b05d7f09d 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -22,6 +22,7 @@ endif() if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles" AND CMAKE_DEPFILE_FLAGS_CXX) diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake index ead9069f350..9884b58c3d8 100644 --- a/Modules/Compiler/Intel-C.cmake +++ b/Modules/Compiler/Intel-C.cmake @@ -17,6 +17,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0) set(CMAKE_C11_STANDARD_COMPILE_OPTION "-Qstd=c11") diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake index 37f339a77d5..7c9cca97e2d 100644 --- a/Modules/Compiler/Intel-CXX.cmake +++ b/Modules/Compiler/Intel-CXX.cmake @@ -16,6 +16,7 @@ endif() if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.0) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-Qstd=c++20") diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake index d69d0647783..d7346f62b77 100644 --- a/Modules/Compiler/IntelLLVM-C.cmake +++ b/Modules/Compiler/IntelLLVM-C.cmake @@ -4,6 +4,7 @@ __compiler_intel_llvm(C) if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" AND CMAKE_DEPFILE_FLAGS_C) diff --git a/Modules/Compiler/IntelLLVM-CXX.cmake b/Modules/Compiler/IntelLLVM-CXX.cmake index 979988846d7..cae1f11993d 100644 --- a/Modules/Compiler/IntelLLVM-CXX.cmake +++ b/Modules/Compiler/IntelLLVM-CXX.cmake @@ -4,6 +4,7 @@ __compiler_intel_llvm(CXX) if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TP) set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" AND CMAKE_DEPFILE_FLAGS_CXX) diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index 73cca362047..4ba1eea3f5e 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -29,6 +29,7 @@ endif() set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") +set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") # There are no C compiler modes so we hard-code the known compiler supported # features. Override the default macro for this special case. Pretend that diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 09fe851d633..9bb77222341 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -4,6 +4,7 @@ include(Compiler/CMakeCommonCompilerMacros) set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) OR diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index c83a7ab3da4..70b6d27352f 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -999,7 +999,25 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } if (cmNonempty(iwyu)) { run_iwyu += " --iwyu="; - run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); + + // Only add --driver-mode if it is not already specified, as adding + // it unconditionally might override a user-specified driver-mode + if (iwyu.Get()->find("--driver-mode=") == std::string::npos) { + cmProp p = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE")); + std::string driverMode; + + if (cmNonempty(p)) { + driverMode = *p; + } else { + driverMode = lang == "C" ? "gcc" : "g++"; + } + + run_iwyu += this->LocalGenerator->EscapeForShell( + cmStrCat(*iwyu, ";--driver-mode=", driverMode)); + } else { + run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); + } } if (cmNonempty(tidy)) { run_iwyu += " --tidy="; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 1b6b834e5db..f1ea229d0b3 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -874,8 +874,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, compilerLauncher.clear(); } if (cmNonempty(iwyu)) { - run_iwyu += cmStrCat(" --iwyu=", - this->GetLocalGenerator()->EscapeForShell(*iwyu)); + run_iwyu += " --iwyu="; + + // Only add --driver-mode if it is not already specified, as adding + // it unconditionally might override a user-specified driver-mode + if (iwyu.Get()->find("--driver-mode=") == std::string::npos) { + cmProp p = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE")); + std::string driverMode; + + if (cmNonempty(p)) { + driverMode = *p; + } else { + driverMode = lang == "C" ? "gcc" : "g++"; + } + + run_iwyu += this->LocalGenerator->EscapeForShell( + cmStrCat(*iwyu, ";--driver-mode=", driverMode)); + } else { + run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); + } } if (cmNonempty(tidy)) { run_iwyu += " --tidy="; From ffc6be33a7dd60c83b9a753a460b8cad122038ff Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 10 Sep 2021 11:05:01 -0400 Subject: [PATCH 1208/1519] IWYU: Map jsoncpp internal header to its public header --- Utilities/IWYU/mapping.imp | 1 + 1 file changed, 1 insertion(+) diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index f1bdcc4cad2..8c55c85f86a 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -101,6 +101,7 @@ # Wrappers for 3rd-party libraries { include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] }, + { include: [ "@<.*json/config.h>", private, "<cm3p/json/value.h>", public ] }, { include: [ "@<.*json/forwards.h>", private, "<cm3p/json/value.h>", public ] }, { include: [ "@<.*uv/.+\\.h>", private, "<cm3p/uv.h>", public ] }, { include: [ "@<.*expat_external.h>", private, "<cm3p/expat.h>", public ] }, From 00a2dc4d2f7bb5dcf2a4654863d7f74a3acb6676 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 11 Sep 2021 00:01:17 -0400 Subject: [PATCH 1209/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6e3cf1f0e63..f1f91137e17 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210910) +set(CMake_VERSION_PATCH 20210911) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b7bcf70761b0008697074073b161f2569e8b46cb Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 12 Sep 2021 00:01:13 -0400 Subject: [PATCH 1210/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f1f91137e17..6cfb8a30f53 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210911) +set(CMake_VERSION_PATCH 20210912) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 253f31f5efb27215049c81a0aff4c67b37a378d5 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 13 Sep 2021 00:01:21 -0400 Subject: [PATCH 1211/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6cfb8a30f53..8b12a1a9918 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210912) +set(CMake_VERSION_PATCH 20210913) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f9bcde974e7faf866979e2589dab3d5ee10776eb Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sun, 5 Sep 2021 14:32:14 +0200 Subject: [PATCH 1212/1519] cmCTestGenericHandler::GetOption returns cmProp --- Source/CTest/cmCTestGenericHandler.cxx | 4 ++-- Source/CTest/cmCTestGenericHandler.h | 3 ++- Source/CTest/cmCTestSubmitHandler.cxx | 20 ++++++-------------- Source/CTest/cmCTestTestHandler.cxx | 24 ++++++++++++------------ Source/CTest/cmCTestTestHandler.h | 7 ++++--- Source/CTest/cmCTestUpdateHandler.cxx | 5 +++-- Source/CTest/cmCTestUpdateHandler.h | 2 +- 7 files changed, 30 insertions(+), 35 deletions(-) diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 48cc0e45007..bd330558589 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -72,13 +72,13 @@ void cmCTestGenericHandler::Initialize() this->MultiOptions = this->PersistentMultiOptions; } -const char* cmCTestGenericHandler::GetOption(const std::string& op) +cmProp cmCTestGenericHandler::GetOption(const std::string& op) { auto remit = this->Options.find(op); if (remit == this->Options.end()) { return nullptr; } - return remit->second.c_str(); + return cmProp(remit->second); } std::vector<std::string> cmCTestGenericHandler::GetMultiOption( diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index e846fd9569d..0b8b224f0dd 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -11,6 +11,7 @@ #include <stddef.h> #include "cmCTest.h" +#include "cmProperty.h" #include "cmSystemTools.h" class cmGeneratedFileStream; @@ -87,7 +88,7 @@ class cmCTestGenericHandler */ void SetPersistentOption(const std::string& op, const char* value); void SetOption(const std::string& op, const char* value); - const char* GetOption(const std::string& op); + cmProp GetOption(const std::string& op); /** * Multi-Options collect one or more values from flags; passing diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index bf938e4900e..9322bd572de 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -357,12 +357,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( // If curl failed for any reason, or checksum fails, wait and retry // if (res != CURLE_OK || this->HasErrors) { - std::string retryDelay = this->GetOption("RetryDelay") == nullptr - ? "" - : this->GetOption("RetryDelay"); - std::string retryCount = this->GetOption("RetryCount") == nullptr - ? "" - : this->GetOption("RetryCount"); + std::string retryDelay = *this->GetOption("RetryDelay"); + std::string retryCount = *this->GetOption("RetryCount"); auto delay = cmDuration( retryDelay.empty() @@ -522,12 +518,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, bool internalTest = cmIsOn(this->GetOption("InternalTest")); // Get RETRY_COUNT and RETRY_DELAY values if they were set. - std::string retryDelayString = this->GetOption("RetryDelay") == nullptr - ? "" - : this->GetOption("RetryDelay"); - std::string retryCountString = this->GetOption("RetryCount") == nullptr - ? "" - : this->GetOption("RetryCount"); + std::string retryDelayString = *this->GetOption("RetryDelay"); + std::string retryCountString = *this->GetOption("RetryCount"); auto retryDelay = std::chrono::seconds(0); if (!retryDelayString.empty()) { unsigned long retryDelayValue = 0; @@ -716,8 +708,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, int cmCTestSubmitHandler::ProcessHandler() { - const char* cdashUploadFile = this->GetOption("CDashUploadFile"); - const char* cdashUploadType = this->GetOption("CDashUploadType"); + cmProp cdashUploadFile = this->GetOption("CDashUploadFile"); + cmProp cdashUploadType = this->GetOption("CDashUploadType"); if (cdashUploadFile && cdashUploadType) { return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType); } diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 00c1443d04c..c41b661783a 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -521,7 +521,7 @@ bool cmCTestTestHandler::ProcessOptions() if (cmIsOn(this->GetOption("ScheduleRandom"))) { this->CTest->SetScheduleType("Random"); } - if (const char* repeat = this->GetOption("Repeat")) { + if (cmProp repeat = this->GetOption("Repeat")) { cmsys::RegularExpression repeatRegex( "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$"); if (repeatRegex.find(repeat)) { @@ -546,7 +546,7 @@ bool cmCTestTestHandler::ProcessOptions() } } if (this->GetOption("ParallelLevel")) { - this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); + this->CTest->SetParallelLevel(std::stoi(this->GetOption("ParallelLevel"))); } if (this->GetOption("StopOnFailure")) { @@ -557,7 +557,7 @@ bool cmCTestTestHandler::ProcessOptions() this->IncludeLabelRegularExpressions); BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), this->ExcludeLabelRegularExpressions); - const char* val = this->GetOption("IncludeRegularExpression"); + cmProp val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -569,19 +569,19 @@ bool cmCTestTestHandler::ProcessOptions() } val = this->GetOption("ExcludeFixtureRegularExpression"); if (val) { - this->ExcludeFixtureRegExp = val; + this->ExcludeFixtureRegExp = *val; } val = this->GetOption("ExcludeFixtureSetupRegularExpression"); if (val) { - this->ExcludeFixtureSetupRegExp = val; + this->ExcludeFixtureSetupRegExp = *val; } val = this->GetOption("ExcludeFixtureCleanupRegularExpression"); if (val) { - this->ExcludeFixtureCleanupRegExp = val; + this->ExcludeFixtureCleanupRegExp = *val; } val = this->GetOption("ResourceSpecFile"); if (val) { - this->ResourceSpecFile = val; + this->ResourceSpecFile = *val; } this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed"))); @@ -2081,26 +2081,26 @@ void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml, } } -void cmCTestTestHandler::SetIncludeRegExp(const char* arg) +void cmCTestTestHandler::SetIncludeRegExp(const std::string& arg) { this->IncludeRegExp = arg; } -void cmCTestTestHandler::SetExcludeRegExp(const char* arg) +void cmCTestTestHandler::SetExcludeRegExp(const std::string& arg) { this->ExcludeRegExp = arg; } -void cmCTestTestHandler::SetTestsToRunInformation(const char* in) +void cmCTestTestHandler::SetTestsToRunInformation(cmProp in) { if (!in) { return; } - this->TestsToRunString = in; + this->TestsToRunString = *in; // if the argument is a file, then read it and use the contents as the // string if (cmSystemTools::FileExists(in)) { - cmsys::ifstream fin(in); + cmsys::ifstream fin(in->c_str()); unsigned long filelen = cmSystemTools::FileLength(in); auto buff = cm::make_unique<char[]>(filelen + 1); fin.getline(buff.get(), filelen); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index f2da320b0b0..585a3365758 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -22,6 +22,7 @@ #include "cmCTestResourceSpec.h" #include "cmDuration.h" #include "cmListFileCache.h" +#include "cmProperty.h" class cmMakefile; class cmXMLWriter; @@ -65,8 +66,8 @@ class cmCTestTestHandler : public cmCTestGenericHandler /// them on void UseIncludeRegExp(); void UseExcludeRegExp(); - void SetIncludeRegExp(const char*); - void SetExcludeRegExp(const char*); + void SetIncludeRegExp(const std::string&); + void SetExcludeRegExp(const std::string&); void SetMaxIndex(int n) { this->MaxIndex = n; } int GetMaxIndex() { return this->MaxIndex; } @@ -81,7 +82,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler } //! pass the -I argument down - void SetTestsToRunInformation(const char*); + void SetTestsToRunInformation(cmProp); cmCTestTestHandler(); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 57cc02420a9..7c7c380e578 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -17,6 +17,7 @@ #include "cmCTestSVN.h" #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -108,7 +109,7 @@ int cmCTestUpdateHandler::ProcessHandler() static_cast<void>(fixLocale); // Get source dir - const char* sourceDirectory = this->GetOption("SourceDirectory"); + cmProp sourceDirectory = this->GetOption("SourceDirectory"); if (!sourceDirectory) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find SourceDirectory key in the DartConfiguration.tcl" @@ -257,7 +258,7 @@ int cmCTestUpdateHandler::ProcessHandler() return updated && loadedMods ? numUpdated : -1; } -int cmCTestUpdateHandler::DetectVCS(const char* dir) +int cmCTestUpdateHandler::DetectVCS(const std::string& dir) { std::string sourceDirectory = dir; cmCTestOptionalLog(this->CTest, DEBUG, diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h index 25bbb2f5cf6..70269ea5476 100644 --- a/Source/CTest/cmCTestUpdateHandler.h +++ b/Source/CTest/cmCTestUpdateHandler.h @@ -59,6 +59,6 @@ class cmCTestUpdateHandler : public cmCTestGenericHandler std::string UpdateCommand; int UpdateType; - int DetectVCS(const char* dir); + int DetectVCS(const std::string& dir); bool SelectVCS(); }; From ecaca8c129ea8f1f772823d221760fc103a32c28 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 8 Sep 2021 15:44:23 -0400 Subject: [PATCH 1213/1519] GNUInstallDirs now aware of conda lib directory requirements No matter the OS when installing for conda the library components need to be placed into the `lib` directory. To better meet these requirements GNUInstallDirs now checks to see if it is being asked to install into a conda install location, and if so use the 'lib' directory instead of the system directory name. --- Modules/GNUInstallDirs.cmake | 37 +++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index ead55ca1d86..1b9cfce2584 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -216,6 +216,7 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set # Override this default 'lib' with 'lib64' iff: # - we are on Linux system but NOT cross-compiling # - we are NOT on debian + # - we are NOT building for conda # - we are on a 64 bits system # reason is: amd64 ABI: https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI # For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if @@ -237,11 +238,34 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. " "Please enable at least one language before including GNUInstallDirs.") endif() + if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" - AND NOT CMAKE_CROSSCOMPILING - AND NOT EXISTS "/etc/alpine-release" - AND NOT EXISTS "/etc/arch-release") - if (EXISTS "/etc/debian_version") # is this a debian system ? + AND NOT CMAKE_CROSSCOMPILING) + unset(__system_type_for_install) + if(DEFINED ENV{CONDA_BUILD} AND DEFINED ENV{PREFIX}) + set(conda_prefix "$ENV{PREFIX}") + cmake_path(ABSOLUTE_PATH conda_prefix NORMALIZE) + if("${CMAKE_INSTALL_PREFIX}" STREQUAL conda_prefix) + set(__system_type_for_install "conda") + endif() + elseif(DEFINED ENV{CONDA_PREFIX}) + set(conda_prefix "$ENV{CONDA_PREFIX}") + cmake_path(ABSOLUTE_PATH conda_prefix NORMALIZE) + if("${CMAKE_INSTALL_PREFIX}" STREQUAL conda_prefix) + set(__system_type_for_install "conda") + endif() + endif() + if(NOT __system_type_for_install) + if (EXISTS "/etc/alpine-release") + set(__system_type_for_install "alpine") + elseif (EXISTS "/etc/arch-release") + set(__system_type_for_install "arch linux") + elseif (EXISTS "/etc/debian_version") + set(__system_type_for_install "debian") + endif() + endif() + + if(__system_type_for_install STREQUAL "debian") if(CMAKE_LIBRARY_ARCHITECTURE) if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$") set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}") @@ -251,7 +275,8 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set set(__LAST_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}") endif() endif() - else() # not debian, rely on CMAKE_SIZEOF_VOID_P: + elseif(NOT DEFINED __system_type_for_install) + # not debian, alpine, arch, or conda so rely on CMAKE_SIZEOF_VOID_P: if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(_LIBDIR_DEFAULT "lib64") if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX) @@ -260,6 +285,8 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set endif() endif() endif() + unset(__system_type_for_install) + if(NOT DEFINED CMAKE_INSTALL_LIBDIR) set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "Object code libraries (${_LIBDIR_DEFAULT})") elseif(DEFINED __LAST_LIBDIR_DEFAULT From 202a65759b98ed955af56db0415ae5033a90f740 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sun, 5 Sep 2021 15:44:04 +0200 Subject: [PATCH 1214/1519] cmCPackGenerator::GetOption returns cmProp --- Source/CPack/IFW/cmCPackIFWCommon.cxx | 2 +- Source/CPack/IFW/cmCPackIFWCommon.h | 4 +- Source/CPack/IFW/cmCPackIFWGenerator.cxx | 57 ++++--- Source/CPack/IFW/cmCPackIFWInstaller.cxx | 112 +++++++------ Source/CPack/IFW/cmCPackIFWPackage.cxx | 96 +++++------ Source/CPack/IFW/cmCPackIFWRepository.cxx | 25 +-- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 79 +++++---- Source/CPack/cmCPackArchiveGenerator.cxx | 20 +-- Source/CPack/cmCPackBundleGenerator.cxx | 45 ++---- Source/CPack/cmCPackCygwinBinaryGenerator.cxx | 8 +- Source/CPack/cmCPackCygwinSourceGenerator.cxx | 15 +- Source/CPack/cmCPackDebGenerator.cxx | 147 +++++++++-------- Source/CPack/cmCPackDragNDropGenerator.cxx | 52 +++--- Source/CPack/cmCPackExternalGenerator.cxx | 37 +++-- Source/CPack/cmCPackFreeBSDGenerator.cxx | 4 +- Source/CPack/cmCPackGenerator.cxx | 153 ++++++++---------- Source/CPack/cmCPackGenerator.h | 3 +- Source/CPack/cmCPackNSISGenerator.cxx | 26 +-- Source/CPack/cmCPackNuGetGenerator.cxx | 5 +- Source/CPack/cmCPackOSXX11Generator.cxx | 11 +- Source/CPack/cmCPackPKGGenerator.cxx | 9 +- Source/CPack/cmCPackPackageMakerGenerator.cxx | 23 +-- Source/CPack/cmCPackProductBuildGenerator.cxx | 15 +- Source/CPack/cmCPackProductBuildGenerator.h | 4 +- Source/CPack/cmCPackRPMGenerator.cxx | 3 +- Source/CPack/cmCPackSTGZGenerator.cxx | 1 + 26 files changed, 462 insertions(+), 494 deletions(-) diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index 87ebbfeb9c8..177a959a226 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -21,7 +21,7 @@ cmCPackIFWCommon::cmCPackIFWCommon() { } -const char* cmCPackIFWCommon::GetOption(const std::string& op) const +cmProp cmCPackIFWCommon::GetOption(const std::string& op) const { return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op) : nullptr; diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h index 42deda4eabd..cf243dcb6ce 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.h +++ b/Source/CPack/IFW/cmCPackIFWCommon.h @@ -7,6 +7,8 @@ #include <map> #include <string> +#include "cmProperty.h" + class cmCPackIFWGenerator; class cmXMLWriter; @@ -26,7 +28,7 @@ class cmCPackIFWCommon public: // Internal implementation - const char* GetOption(const std::string& op) const; + cmProp GetOption(const std::string& op) const; bool IsOn(const std::string& op) const; bool IsSetToOff(const std::string& op) const; bool IsSetToEmpty(const std::string& op) const; diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 2806c614e76..4993b40dd21 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -14,6 +14,7 @@ #include "cmCPackLog.h" // IWYU pragma: keep #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -250,7 +251,7 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix() this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); - return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX"); + return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX")->c_str(); } const char* cmCPackIFWGenerator::GetOutputExtension() @@ -273,11 +274,11 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'binarycreator' executable (needs) - const char* BinCreatorStr = this->GetOption(BinCreatorOpt); + cmProp BinCreatorStr = this->GetOption(BinCreatorOpt); if (!BinCreatorStr || cmIsNOTFOUND(BinCreatorStr)) { this->BinCreator.clear(); } else { - this->BinCreator = BinCreatorStr; + this->BinCreator = *BinCreatorStr; } if (this->BinCreator.empty()) { @@ -290,16 +291,16 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'repogen' executable (optional) - const char* RepoGenStr = this->GetOption(RepoGenOpt); - if (!RepoGenStr || cmIsNOTFOUND(RepoGenStr)) { + cmProp repoGen = this->GetOption(RepoGenOpt); + if (!repoGen || cmIsNOTFOUND(repoGen)) { this->RepoGen.clear(); } else { - this->RepoGen = RepoGenStr; + this->RepoGen = *repoGen; } // Framework version - if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) { - this->FrameworkVersion = FrameworkVersionSrt; + if (cmProp frameworkVersion = this->GetOption(FrameworkVersionOpt)) { + this->FrameworkVersion = *frameworkVersion; } else { this->FrameworkVersion = "1.9.9"; } @@ -312,14 +313,13 @@ int cmCPackIFWGenerator::InitializeInternal() // Additional packages dirs this->PkgsDirsVector.clear(); - if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { + if (cmProp dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { cmExpandList(dirs, this->PkgsDirsVector); } // Additional repositories dirs this->RepoDirsVector.clear(); - if (const char* dirs = - this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { + if (cmProp dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { cmExpandList(dirs, this->RepoDirsVector); } @@ -330,23 +330,22 @@ int cmCPackIFWGenerator::InitializeInternal() // Repository this->Repository.Generator = this; this->Repository.Name = "Unspecified"; - if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) { - this->Repository.Url = site; + if (cmProp site = this->GetOption("CPACK_DOWNLOAD_SITE")) { + this->Repository.Url = *site; this->Installer.RemoteRepositories.push_back(&this->Repository); } // Repositories - if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { + if (cmProp RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr); for (std::string const& r : RepoAllVector) { this->GetRepository(r); } } - if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { + if (cmProp ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { this->OnlineOnly = cmIsOn(ifwDownloadAll); - } else if (const char* cpackDownloadAll = - this->GetOption("CPACK_DOWNLOAD_ALL")) { + } else if (cmProp cpackDownloadAll = this->GetOption("CPACK_DOWNLOAD_ALL")) { this->OnlineOnly = cmIsOn(cpackDownloadAll); } else { this->OnlineOnly = false; @@ -374,9 +373,8 @@ int cmCPackIFWGenerator::InitializeInternal() } // Output extension - if (const char* optOutExt = - this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) { - this->OutputExtension = optOutExt; + if (cmProp optOutExt = this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) { + this->OutputExtension = *optOutExt; } else if (sysName == "Darwin") { this->OutputExtension = ".dmg"; } else { @@ -508,21 +506,20 @@ std::string cmCPackIFWGenerator::GetRootPackageName() { // Default value std::string name = "root"; - if (const char* optIFW_PACKAGE_GROUP = + if (cmProp optIFW_PACKAGE_GROUP = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { // Configure from root group cmCPackIFWPackage package; package.Generator = this; package.ConfigureFromGroup(optIFW_PACKAGE_GROUP); name = package.Name; - } else if (const char* optIFW_PACKAGE_NAME = + } else if (cmProp optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { // Configure from root package name - name = optIFW_PACKAGE_NAME; - } else if (const char* optPACKAGE_NAME = - this->GetOption("CPACK_PACKAGE_NAME")) { + name = *optIFW_PACKAGE_NAME; + } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { // Configure from package name - name = optPACKAGE_NAME; + name = *optPACKAGE_NAME; } return name; } @@ -537,10 +534,10 @@ std::string cmCPackIFWGenerator::GetGroupPackageName( if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) { return package->Name; } - const char* option = + cmProp option = this->GetOption("CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(group->Name) + "_NAME"); - name = option ? option : group->Name; + name = option ? *option : group->Name; if (group->ParentGroup) { cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup); bool dot = !this->ResolveDuplicateNames; @@ -563,8 +560,8 @@ std::string cmCPackIFWGenerator::GetComponentPackageName( } std::string prefix = "CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_"; - const char* option = this->GetOption(prefix + "NAME"); - name = option ? option : component->Name; + cmProp option = this->GetOption(prefix + "NAME"); + name = option ? *option : component->Name; if (component->Group) { cmCPackIFWPackage* package = this->GetGroupPackage(component->Group); if ((this->componentPackageMethod == diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index bf8b457b4a4..23b73ff163c 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -12,6 +12,7 @@ #include "cmCPackIFWRepository.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" @@ -33,61 +34,59 @@ void cmCPackIFWInstaller::printSkippedOptionWarning( void cmCPackIFWInstaller::ConfigureFromOptions() { // Name; - if (const char* optIFW_PACKAGE_NAME = - this->GetOption("CPACK_IFW_PACKAGE_NAME")) { - this->Name = optIFW_PACKAGE_NAME; - } else if (const char* optPACKAGE_NAME = - this->GetOption("CPACK_PACKAGE_NAME")) { - this->Name = optPACKAGE_NAME; + if (cmProp optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { + this->Name = *optIFW_PACKAGE_NAME; + } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { + this->Name = *optPACKAGE_NAME; } else { this->Name = "Your package"; } // Title; - if (const char* optIFW_PACKAGE_TITLE = + if (cmProp optIFW_PACKAGE_TITLE = this->GetOption("CPACK_IFW_PACKAGE_TITLE")) { - this->Title = optIFW_PACKAGE_TITLE; - } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY = + this->Title = *optIFW_PACKAGE_TITLE; + } else if (cmProp optPACKAGE_DESCRIPTION_SUMMARY = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { - this->Title = optPACKAGE_DESCRIPTION_SUMMARY; + this->Title = *optPACKAGE_DESCRIPTION_SUMMARY; } else { this->Title = "Your package description"; } // Version; - if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = *option; } else { this->Version = "1.0.0"; } // Publisher - if (const char* optIFW_PACKAGE_PUBLISHER = + if (cmProp optIFW_PACKAGE_PUBLISHER = this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { - this->Publisher = optIFW_PACKAGE_PUBLISHER; - } else if (const char* optPACKAGE_VENDOR = + this->Publisher = *optIFW_PACKAGE_PUBLISHER; + } else if (cmProp optPACKAGE_VENDOR = this->GetOption("CPACK_PACKAGE_VENDOR")) { - this->Publisher = optPACKAGE_VENDOR; + this->Publisher = *optPACKAGE_VENDOR; } // ProductUrl - if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { - this->ProductUrl = option; + if (cmProp option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { + this->ProductUrl = *option; } // ApplicationIcon - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { if (cmSystemTools::FileExists(option)) { - this->InstallerApplicationIcon = option; + this->InstallerApplicationIcon = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option); } } // WindowIcon - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { if (cmSystemTools::FileExists(option)) { - this->InstallerWindowIcon = option; + this->InstallerWindowIcon = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option); } @@ -103,45 +102,45 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Logo - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { if (cmSystemTools::FileExists(option)) { - this->Logo = option; + this->Logo = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option); } } // Watermark - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { if (cmSystemTools::FileExists(option)) { - this->Watermark = option; + this->Watermark = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option); } } // Banner - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { if (cmSystemTools::FileExists(option)) { - this->Banner = option; + this->Banner = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option); } } // Background - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { if (cmSystemTools::FileExists(option)) { - this->Background = option; + this->Background = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option); } } // WizardStyle - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { // Setting the user value in any case - this->WizardStyle = option; + this->WizardStyle = *option; // Check known values if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" && this->WizardStyle != "Mac" && this->WizardStyle != "Classic") { @@ -154,28 +153,28 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // StyleSheet - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) { if (cmSystemTools::FileExists(option)) { - this->StyleSheet = option; + this->StyleSheet = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_STYLE_SHEET", option); } } // WizardDefaultWidth - if (const char* option = + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { - this->WizardDefaultWidth = option; + this->WizardDefaultWidth = *option; } // WizardDefaultHeight - if (const char* option = + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { - this->WizardDefaultHeight = option; + this->WizardDefaultHeight = *option; } // WizardShowPageList - if (const char* option = + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) { if (!this->IsVersionLess("4.0")) { if (this->IsSetToOff("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) { @@ -204,23 +203,23 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // TitleColor - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { - this->TitleColor = option; + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { + this->TitleColor = *option; } // Start menu - if (const char* optIFW_START_MENU_DIR = + if (cmProp optIFW_START_MENU_DIR = this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) { - this->StartMenuDir = optIFW_START_MENU_DIR; + this->StartMenuDir = *optIFW_START_MENU_DIR; } else { this->StartMenuDir = this->Name; } // Default target directory for installation - if (const char* optIFW_TARGET_DIRECTORY = + if (cmProp optIFW_TARGET_DIRECTORY = this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) { - this->TargetDir = optIFW_TARGET_DIRECTORY; - } else if (const char* optPACKAGE_INSTALL_DIRECTORY = + this->TargetDir = *optIFW_TARGET_DIRECTORY; + } else if (cmProp optPACKAGE_INSTALL_DIRECTORY = this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { this->TargetDir = cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY); @@ -229,21 +228,20 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Default target directory for installation with administrator rights - if (const char* option = - this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { - this->AdminTargetDir = option; + if (cmProp option = this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { + this->AdminTargetDir = *option; } // Maintenance tool - if (const char* optIFW_MAINTENANCE_TOOL = + if (cmProp optIFW_MAINTENANCE_TOOL = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) { - this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL; + this->MaintenanceToolName = *optIFW_MAINTENANCE_TOOL; } // Maintenance tool ini file - if (const char* optIFW_MAINTENANCE_TOOL_INI = + if (cmProp optIFW_MAINTENANCE_TOOL_INI = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) { - this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; + this->MaintenanceToolIniFile = *optIFW_MAINTENANCE_TOOL_INI; } // Allow non-ASCII characters @@ -265,13 +263,13 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Control script - if (const char* optIFW_CONTROL_SCRIPT = + if (cmProp optIFW_CONTROL_SCRIPT = this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) { - this->ControlScript = optIFW_CONTROL_SCRIPT; + this->ControlScript = *optIFW_CONTROL_SCRIPT; } // Resources - if (const char* optIFW_PACKAGE_RESOURCES = + if (cmProp optIFW_PACKAGE_RESOURCES = this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { this->Resources.clear(); cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources); @@ -541,7 +539,7 @@ void cmCPackIFWInstaller::GeneratePackageFiles() package.Generator = this->Generator; package.Installer = this; // Check package group - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { package.ConfigureFromGroup(option); std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION"; diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 1429c4670e5..c1e11d27c33 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -15,6 +15,7 @@ #include "cmCPackIFWInstaller.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" @@ -124,10 +125,10 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component) if (!component) { return ""; } - const char* option = + cmProp option = this->GetOption("CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_NAME"); - return option ? option : component->Name; + return option ? *option : component->Name; } void cmCPackIFWPackage::DefaultConfiguration() @@ -159,23 +160,22 @@ int cmCPackIFWPackage::ConfigureFromOptions() this->Name = this->Generator->GetRootPackageName(); // Display name - if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) { - this->DisplayName[""] = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_NAME")) { + this->DisplayName[""] = *option; } else { this->DisplayName[""] = "Your package"; } // Description - if (const char* option = - this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { - this->Description[""] = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + this->Description[""] = *option; } else { this->Description[""] = "Your package description"; } // Version - if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = *option; } else { this->Version = "1.0.0"; } @@ -204,22 +204,22 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) this->Description[""] = component->Description; // Version - if (const char* optVERSION = this->GetOption(prefix + "VERSION")) { - this->Version = optVERSION; - } else if (const char* optPACKAGE_VERSION = + if (cmProp optVERSION = this->GetOption(prefix + "VERSION")) { + this->Version = *optVERSION; + } else if (cmProp optPACKAGE_VERSION = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = optPACKAGE_VERSION; + this->Version = *optPACKAGE_VERSION; } else { this->Version = "1.0.0"; } // Script - if (const char* option = this->GetOption(prefix + "SCRIPT")) { - this->Script = option; + if (cmProp option = this->GetOption(prefix + "SCRIPT")) { + this->Script = *option; } // User interfaces - if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { + if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); cmExpandList(option, this->UserInterfaces); } @@ -232,7 +232,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Licenses - if (const char* option = this->GetOption(prefix + "LICENSES")) { + if (cmProp option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { @@ -246,8 +246,8 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Priority - if (const char* option = this->GetOption(prefix + "PRIORITY")) { - this->SortingPriority = option; + if (cmProp option = this->GetOption(prefix + "PRIORITY")) { + this->SortingPriority = *option; cmCPackIFWLogger( WARNING, "The \"PRIORITY\" option is set " @@ -289,28 +289,28 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) this->Description[""] = group->Description; // Version - if (const char* optVERSION = this->GetOption(prefix + "VERSION")) { - this->Version = optVERSION; - } else if (const char* optPACKAGE_VERSION = + if (cmProp optVERSION = this->GetOption(prefix + "VERSION")) { + this->Version = *optVERSION; + } else if (cmProp optPACKAGE_VERSION = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = optPACKAGE_VERSION; + this->Version = *optPACKAGE_VERSION; } else { this->Version = "1.0.0"; } // Script - if (const char* option = this->GetOption(prefix + "SCRIPT")) { - this->Script = option; + if (cmProp option = this->GetOption(prefix + "SCRIPT")) { + this->Script = *option; } // User interfaces - if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { + if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); cmExpandList(option, this->UserInterfaces); } // Licenses - if (const char* option = this->GetOption(prefix + "LICENSES")) { + if (cmProp option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { @@ -324,8 +324,8 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) } // Priority - if (const char* option = this->GetOption(prefix + "PRIORITY")) { - this->SortingPriority = option; + if (cmProp option = this->GetOption(prefix + "PRIORITY")) { + this->SortingPriority = *option; cmCPackIFWLogger( WARNING, "The \"PRIORITY\" option is set " @@ -346,14 +346,14 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName) std::string prefix = "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_"; - if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) { - group.DisplayName = option; + if (cmProp option = this->GetOption(prefix + "DISPLAY_NAME")) { + group.DisplayName = *option; } else { group.DisplayName = group.Name; } - if (const char* option = this->GetOption(prefix + "DESCRIPTION")) { - group.Description = option; + if (cmProp option = this->GetOption(prefix + "DESCRIPTION")) { + group.Description = *option; } group.IsBold = this->IsOn(prefix + "BOLD_TITLE"); group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED"); @@ -381,7 +381,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DISPLAY_NAME"; if (this->IsSetToEmpty(option)) { this->DisplayName.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName); } @@ -389,7 +389,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DESCRIPTION"; if (this->IsSetToEmpty(option)) { this->Description.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { cmCPackIFWPackage::ExpandListArgument(value, this->Description); } @@ -397,31 +397,31 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "RELEASE_DATE"; if (this->IsSetToEmpty(option)) { this->ReleaseDate.clear(); - } else if (const char* value = this->GetOption(option)) { - this->ReleaseDate = value; + } else if (cmProp value = this->GetOption(option)) { + this->ReleaseDate = *value; } // Sorting priority option = prefix + "SORTING_PRIORITY"; if (this->IsSetToEmpty(option)) { this->SortingPriority.clear(); - } else if (const char* value = this->GetOption(option)) { - this->SortingPriority = value; + } else if (cmProp value = this->GetOption(option)) { + this->SortingPriority = *value; } // Update text option = prefix + "UPDATE_TEXT"; if (this->IsSetToEmpty(option)) { this->UpdateText.clear(); - } else if (const char* value = this->GetOption(option)) { - this->UpdateText = value; + } else if (cmProp value = this->GetOption(option)) { + this->UpdateText = *value; } // Translations option = prefix + "TRANSLATIONS"; if (this->IsSetToEmpty(option)) { this->Translations.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { this->Translations.clear(); cmExpandList(value, this->Translations); } @@ -429,11 +429,11 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) // QtIFW dependencies std::vector<std::string> deps; option = prefix + "DEPENDS"; - if (const char* value = this->GetOption(option)) { + if (cmProp value = this->GetOption(option)) { cmExpandList(value, deps); } option = prefix + "DEPENDENCIES"; - if (const char* value = this->GetOption(option)) { + if (cmProp value = this->GetOption(option)) { cmExpandList(value, deps); } for (std::string const& d : deps) { @@ -454,7 +454,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "AUTO_DEPEND_ON"; if (this->IsSetToEmpty(option)) { this->AlienAutoDependOn.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { std::vector<std::string> depsOn = cmExpandedList(value); for (std::string const& d : depsOn) { DependenceStruct dep(d); @@ -483,7 +483,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DEFAULT"; if (this->IsSetToEmpty(option)) { this->Default.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { std::string lowerValue = cmsys::SystemTools::LowerCase(value); if (lowerValue == "true") { this->Default = "true"; @@ -492,7 +492,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) } else if (lowerValue == "script") { this->Default = "script"; } else { - this->Default = value; + this->Default = *value; } } @@ -510,7 +510,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "REPLACES"; if (this->IsSetToEmpty(option)) { this->Replaces.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { this->Replaces.clear(); cmExpandList(value, this->Replaces); } diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index 7ec22568609..cc64e936195 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -6,6 +6,7 @@ #include "cmCPackIFWGenerator.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" @@ -55,22 +56,22 @@ bool cmCPackIFWRepository::ConfigureFromOptions() } // Url - if (const char* url = this->GetOption(prefix + "URL")) { - this->Url = url; + if (cmProp url = this->GetOption(prefix + "URL")) { + this->Url = *url; } else { this->Url.clear(); } // Old url - if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) { - this->OldUrl = oldUrl; + if (cmProp oldUrl = this->GetOption(prefix + "OLD_URL")) { + this->OldUrl = *oldUrl; } else { this->OldUrl.clear(); } // New url - if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) { - this->NewUrl = newUrl; + if (cmProp newUrl = this->GetOption(prefix + "NEW_URL")) { + this->NewUrl = *newUrl; } else { this->NewUrl.clear(); } @@ -83,22 +84,22 @@ bool cmCPackIFWRepository::ConfigureFromOptions() } // Username - if (const char* username = this->GetOption(prefix + "USERNAME")) { - this->Username = username; + if (cmProp username = this->GetOption(prefix + "USERNAME")) { + this->Username = *username; } else { this->Username.clear(); } // Password - if (const char* password = this->GetOption(prefix + "PASSWORD")) { - this->Password = password; + if (cmProp password = this->GetOption(prefix + "PASSWORD")) { + this->Password = *password; } else { this->Password.clear(); } // DisplayName - if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) { - this->DisplayName = displayName; + if (cmProp displayName = this->GetOption(prefix + "DISPLAY_NAME")) { + this->DisplayName = *displayName; } else { this->DisplayName.clear(); } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 8b3644f910a..7ec2c3f1c45 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -18,6 +18,7 @@ #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUuid.h" @@ -125,7 +126,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles) command << " -ext " << QuotePath(ext); } - const char* const cultures = GetOption("CPACK_WIX_CULTURES"); + cmProp const cultures = GetOption("CPACK_WIX_CULTURES"); if (cultures) { command << " -cultures:" << cultures; } @@ -156,7 +157,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() return false; } - if (GetOption("CPACK_WIX_PRODUCT_GUID") == 0) { + if (!GetOption("CPACK_WIX_PRODUCT_GUID")) { std::string guid = GenerateGUID(); SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str()); @@ -165,7 +166,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() << std::endl); } - if (GetOption("CPACK_WIX_UPGRADE_GUID") == 0) { + if (!GetOption("CPACK_WIX_UPGRADE_GUID")) { std::string guid = GenerateGUID(); SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str()); @@ -182,7 +183,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() return false; } - if (GetOption("CPACK_WIX_LICENSE_RTF") == 0) { + if (!GetOption("CPACK_WIX_LICENSE_RTF")) { std::string licenseFilename = this->CPackTopLevel + "/License.rtf"; SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str()); @@ -191,7 +192,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() } } - if (GetOption("CPACK_PACKAGE_VENDOR") == 0) { + if (!GetOption("CPACK_PACKAGE_VENDOR")) { std::string defaultVendor = "Humanity"; SetOption("CPACK_PACKAGE_VENDOR", defaultVendor.c_str()); @@ -200,7 +201,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() << defaultVendor << " . " << std::endl); } - if (GetOption("CPACK_WIX_UI_REF") == 0) { + if (!GetOption("CPACK_WIX_UI_REF")) { std::string defaultRef = "WixUI_InstallDir"; if (!this->Components.empty()) { @@ -210,9 +211,9 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() SetOption("CPACK_WIX_UI_REF", defaultRef.c_str()); } - const char* packageContact = GetOption("CPACK_PACKAGE_CONTACT"); - if (packageContact != 0 && GetOption("CPACK_WIX_PROPERTY_ARPCONTACT") == 0) { - SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact); + cmProp packageContact = GetOption("CPACK_PACKAGE_CONTACT"); + if (packageContact && !GetOption("CPACK_WIX_PROPERTY_ARPCONTACT")) { + SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact->c_str()); } CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions); @@ -223,7 +224,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces); - const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); + cmProp patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if (patchFilePath) { std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath); @@ -295,7 +296,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl() void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() { - const char* cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); + cmProp cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); if (!cpackWixExtraSources) return; @@ -304,7 +305,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) { - const char* cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); + cmProp cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); if (!cpackWixExtraObjects) return; @@ -335,7 +336,7 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH); CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH); SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", - GetOption("CPACK_PACKAGE_NAME")); + GetOption("CPACK_PACKAGE_NAME").GetCStr()); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); CopyDefinition(includeFile, "CPACK_WIX_UI_REF"); } @@ -355,7 +356,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() for (std::string const& name : options) { if (cmHasPrefix(name, prefix)) { std::string id = name.substr(prefix.length()); - std::string value = GetOption(name.c_str()); + std::string value = GetOption(name); includeFile.BeginElement("Property"); includeFile.AddAttribute("Id", id); @@ -364,7 +365,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() } } - if (GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION") == 0) { + if (!GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION")) { includeFile.BeginElement("Property"); includeFile.AddAttribute("Id", "INSTALL_ROOT"); includeFile.AddAttribute("Secure", "yes"); @@ -405,7 +406,7 @@ void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source, std::string const& name, DefinitionType type) { - const char* value = GetOption(name.c_str()); + cmProp value = GetOption(name); if (value) { if (type == DefinitionType::PATH) { AddDefinition(source, name, CMakeToWixPath(value)); @@ -485,17 +486,17 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } std::string featureTitle = cpackPackageName; - if (const char* title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) { - featureTitle = title; + if (cmProp title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) { + featureTitle = *title; } featureDefinitions.AddAttribute("Title", featureTitle); - if (const char* desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) { + if (cmProp desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) { featureDefinitions.AddAttribute("Description", desc); } featureDefinitions.AddAttribute("Level", "1"); this->Patch->ApplyFragment("#PRODUCTFEATURE", featureDefinitions); - const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); + cmProp package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); if (package) { featureDefinitions.CreateCMakePackageRegistryEntry( package, GetOption("CPACK_WIX_UPGRADE_GUID")); @@ -540,10 +541,9 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } bool emitUninstallShortcut = true; - const char* cpackWixProgramMenuFolder = + cmProp cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - if (cpackWixProgramMenuFolder && - cm::string_view(cpackWixProgramMenuFolder) == ".") { + if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") { emitUninstallShortcut = false; } else if (emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) == emittedShortcutTypes.end()) { @@ -595,9 +595,9 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const std::string result = "ProgramFiles<64>Folder"; - const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); + cmProp rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); if (rootFolderId) { - result = rootFolderId; + result = *rootFolderId; } if (GetArchitecture() == "x86") { @@ -612,8 +612,8 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() { std::string wixTemplate = FindTemplate("WIX.template.in"); - if (GetOption("CPACK_WIX_TEMPLATE") != 0) { - wixTemplate = GetOption("CPACK_WIX_TEMPLATE"); + if (cmProp wixtpl = GetOption("CPACK_WIX_TEMPLATE")) { + wixTemplate = *wixtpl; } if (wixTemplate.empty()) { @@ -669,7 +669,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( featureDefinitions.AddAttribute("Id", featureId); std::vector<std::string> cpackPackageExecutablesList; - const char* cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); + cmProp cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList); if (cpackPackageExecutablesList.size() % 2 != 0) { @@ -683,8 +683,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( } std::vector<std::string> cpackPackageDesktopLinksList; - const char* cpackPackageDesktopLinks = - GetOption("CPACK_CREATE_DESKTOP_LINKS"); + cmProp cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS"); if (cpackPackageDesktopLinks) { cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList); } @@ -743,10 +742,9 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType( std::string directoryId; switch (type) { case cmWIXShortcuts::START_MENU: { - const char* cpackWixProgramMenuFolder = + cmProp cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - if (cpackWixProgramMenuFolder && - cm::string_view(cpackWixProgramMenuFolder) == ".") { + if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") { directoryId = "ProgramMenuFolder"; } else { directoryId = "PROGRAM_MENU_FOLDER"; @@ -805,10 +803,9 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType( fileDefinitions); if (type == cmWIXShortcuts::START_MENU) { - const char* cpackWixProgramMenuFolder = + cmProp cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - if (cpackWixProgramMenuFolder && - cm::string_view(cpackWixProgramMenuFolder) != ".") { + if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder != ".") { fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" + idSuffix); } @@ -973,9 +970,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions( bool cmCPackWIXGenerator::RequireOption(std::string const& name, std::string& value) const { - const char* tmp = GetOption(name.c_str()); + cmProp tmp = GetOption(name); if (tmp) { - value = tmp; + value = *tmp; return true; } else { @@ -1146,7 +1143,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c) void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, extension_set_t& extensions) { - const char* variableContent = GetOption(variableName.c_str()); + cmProp variableContent = GetOption(variableName); if (!variableContent) return; @@ -1157,7 +1154,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, xmlns_map_t& namespaces) { - const char* variableContent = GetOption(variableName.c_str()); + cmProp variableContent = GetOption(variableName); if (!variableContent) { return; } @@ -1186,7 +1183,7 @@ void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, std::ostream& stream) { - const char* variableContent = GetOption(variableName.c_str()); + cmProp variableContent = GetOption(variableName); if (!variableContent) return; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index d9234e66699..4f90ba28c9c 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackArchiveGenerator.h" -#include <cstdlib> #include <cstring> #include <map> #include <ostream> @@ -13,6 +12,7 @@ #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" @@ -77,7 +77,7 @@ std::string cmCPackArchiveGenerator::GetArchiveComponentFileName( if (this->IsSet("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME")) { packageFileName += - this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME"); + *this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME"); } else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) { packageFileName += this->GetComponentPackageFileName( this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName); @@ -118,11 +118,11 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/'); } - const char* installPrefix = - this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); - if (installPrefix && installPrefix[0] == '/' && installPrefix[1] != 0) { + cmProp installPrefix = this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + if (installPrefix && installPrefix->size() > 1 && + (*installPrefix)[0] == '/') { // add to file prefix and remove the leading '/' - filePrefix += installPrefix + 1; + filePrefix += installPrefix->substr(1); filePrefix += "/"; } for (std::string const& file : component->Files) { @@ -257,9 +257,9 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne() this->packageFileNames[0] += "/"; if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) { - this->packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME"); + this->packageFileNames[0] += *this->GetOption("CPACK_ARCHIVE_FILE_NAME"); } else { - this->packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + this->packageFileNames[0] += *this->GetOption("CPACK_PACKAGE_FILE_NAME"); } this->packageFileNames[0] += this->GetOutputExtension(); @@ -345,9 +345,9 @@ int cmCPackArchiveGenerator::GetThreadCount() const // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS if (this->IsSet("CPACK_ARCHIVE_THREADS")) { - threads = std::atoi(this->GetOption("CPACK_ARCHIVE_THREADS")); + threads = std::stoi(this->GetOption("CPACK_ARCHIVE_THREADS")); } else if (this->IsSet("CPACK_THREADS")) { - threads = std::atoi(this->GetOption("CPACK_THREADS")); + threads = std::stoi(this->GetOption("CPACK_THREADS")); } return threads; diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index 4d5f43f9eb8..a2e0be491c8 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -6,6 +6,7 @@ #include <vector> #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -15,8 +16,8 @@ cmCPackBundleGenerator::~cmCPackBundleGenerator() = default; int cmCPackBundleGenerator::InitializeInternal() { - const char* name = this->GetOption("CPACK_BUNDLE_NAME"); - if (nullptr == name) { + cmProp name = this->GetOption("CPACK_BUNDLE_NAME"); + if (!name) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set to use the Bundle generator." << std::endl); @@ -51,30 +52,24 @@ int cmCPackBundleGenerator::ConstructBundle() { // Get required arguments ... - const std::string cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME") - ? this->GetOption("CPACK_BUNDLE_NAME") - : ""; - if (cpack_bundle_name.empty()) { + cmProp cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME"); + if (cpack_bundle_name->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set." << std::endl); return 0; } - const std::string cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST") - ? this->GetOption("CPACK_BUNDLE_PLIST") - : ""; - if (cpack_bundle_plist.empty()) { + cmProp cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST"); + if (cpack_bundle_plist->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set." << std::endl); return 0; } - const std::string cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON") - ? this->GetOption("CPACK_BUNDLE_ICON") - : ""; - if (cpack_bundle_icon.empty()) { + cmProp cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON"); + if (cpack_bundle_icon->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set." << std::endl); @@ -82,10 +77,8 @@ int cmCPackBundleGenerator::ConstructBundle() } // Get optional arguments ... - const std::string cpack_bundle_startup_command = - this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND") - ? this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND") - : ""; + cmProp cpack_bundle_startup_command = + this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND"); // The staging directory contains everything that will end-up inside the // final disk image ... @@ -138,7 +131,7 @@ int cmCPackBundleGenerator::ConstructBundle() // Optionally a user-provided startup command (could be an // executable or a script) ... - if (!cpack_bundle_startup_command.empty()) { + if (!cpack_bundle_startup_command->empty()) { std::ostringstream command_source; command_source << cpack_bundle_startup_command; @@ -180,13 +173,10 @@ bool cmCPackBundleGenerator::SupportsComponentInstallation() const int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) { - const std::string cpack_apple_cert_app = - this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP") - ? this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP") - : ""; + cmProp cpack_apple_cert_app = this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP"); // codesign the application. - if (!cpack_apple_cert_app.empty()) { + if (!cpack_apple_cert_app->empty()) { std::string output; std::string bundle_path; bundle_path = @@ -195,13 +185,10 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) // A list of additional files to sign, ie. frameworks and plugins. const std::string sign_parameter = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") - ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") + ? *this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") : "--deep -f"; - const std::string sign_files = - this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") - ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") - : ""; + cmProp sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES"); std::vector<std::string> relFiles = cmExpandedList(sign_files); diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx index b5abd5a6b2a..1de5e1c07f6 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSystemTools.h" #include "cmake.h" @@ -59,14 +60,15 @@ int cmCPackCygwinBinaryGenerator::PackageFiles() const char* cmCPackCygwinBinaryGenerator::GetOutputExtension() { this->OutputExtension = "-"; - const char* patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmProp patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patchNumber) { - patchNumber = "1"; + this->OutputExtension += "1"; cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER not specified using 1" << std::endl); + } else { + this->OutputExtension += patchNumber; } - this->OutputExtension += patchNumber; this->OutputExtension += ".tar.bz2"; return this->OutputExtension.c_str(); } diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx index 64a88eba452..684a98845cc 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx +++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSystemTools.h" #include "cmake.h" @@ -94,14 +95,15 @@ int cmCPackCygwinSourceGenerator::PackageFiles() } std::string outerTarFile = cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-'); - const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmProp patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER" << " not specified, defaulting to 1\n"); - patch = "1"; + outerTarFile += "1"; + } else { + outerTarFile += patch; } - outerTarFile += patch; outerTarFile += "-src.tar.bz2"; std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string buildScript = @@ -145,14 +147,15 @@ const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix() const char* cmCPackCygwinSourceGenerator::GetOutputExtension() { this->OutputExtension = "-"; - const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmProp patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER" << " not specified, defaulting to 1\n"); - patch = "1"; + this->OutputExtension += "1"; + } else { + this->OutputExtension += patch; } - this->OutputExtension += patch; this->OutputExtension += "-src.tar.bz2"; return this->OutputExtension.c_str(); } diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 829cef4ec4d..52b94c49ece 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -20,6 +20,7 @@ #include "cmCPackLog.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -30,12 +31,12 @@ class DebGenerator public: DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir, std::string topLevelDir, std::string temporaryDir, - const char* debianCompressionType, const char* numThreads, - const char* debianArchiveType, + cmProp debianCompressionType, cmProp numThreads, + cmProp debianArchiveType, std::map<std::string, std::string> controlValues, bool genShLibs, std::string shLibsFilename, bool genPostInst, std::string postInst, bool genPostRm, std::string postRm, - const char* controlExtra, bool permissionStrctPolicy, + cmProp controlExtra, bool permissionStrctPolicy, std::vector<std::string> packageFiles); bool generate() const; @@ -54,7 +55,7 @@ class DebGenerator std::string CompressionSuffix; const std::string TopLevelDir; const std::string TemporaryDir; - const char* DebianArchiveType; + const std::string DebianArchiveType; long NumThreads; const std::map<std::string, std::string> ControlValues; const bool GenShLibs; @@ -63,27 +64,28 @@ class DebGenerator const std::string PostInst; const bool GenPostRm; const std::string PostRm; - const char* ControlExtra; + cmProp ControlExtra; const bool PermissionStrictPolicy; const std::vector<std::string> PackageFiles; cmArchiveWrite::Compress TarCompressionType; }; -DebGenerator::DebGenerator( - cmCPackLog* logger, std::string outputName, std::string workDir, - std::string topLevelDir, std::string temporaryDir, - const char* debianCompressionType, const char* numThreads, - const char* debianArchiveType, - std::map<std::string, std::string> controlValues, bool genShLibs, - std::string shLibsFilename, bool genPostInst, std::string postInst, - bool genPostRm, std::string postRm, const char* controlExtra, - bool permissionStrictPolicy, std::vector<std::string> packageFiles) +DebGenerator::DebGenerator(cmCPackLog* logger, std::string outputName, + std::string workDir, std::string topLevelDir, + std::string temporaryDir, cmProp debCompressionType, + cmProp numThreads, cmProp debianArchiveType, + std::map<std::string, std::string> controlValues, + bool genShLibs, std::string shLibsFilename, + bool genPostInst, std::string postInst, + bool genPostRm, std::string postRm, + cmProp controlExtra, bool permissionStrictPolicy, + std::vector<std::string> packageFiles) : Logger(logger) , OutputName(std::move(outputName)) , WorkDir(std::move(workDir)) , TopLevelDir(std::move(topLevelDir)) , TemporaryDir(std::move(temporaryDir)) - , DebianArchiveType(debianArchiveType ? debianArchiveType : "gnutar") + , DebianArchiveType(debianArchiveType ? *debianArchiveType : "gnutar") , ControlValues(std::move(controlValues)) , GenShLibs(genShLibs) , ShLibsFilename(std::move(shLibsFilename)) @@ -95,26 +97,27 @@ DebGenerator::DebGenerator( , PermissionStrictPolicy(permissionStrictPolicy) , PackageFiles(std::move(packageFiles)) { - if (!debianCompressionType) { - debianCompressionType = "gzip"; + std::string debianCompressionType = "gzip"; + if (debCompressionType) { + debianCompressionType = *debCompressionType; } - if (!std::strcmp(debianCompressionType, "lzma")) { + if (debianCompressionType == "lzma") { this->CompressionSuffix = ".lzma"; this->TarCompressionType = cmArchiveWrite::CompressLZMA; - } else if (!std::strcmp(debianCompressionType, "xz")) { + } else if (debianCompressionType == "xz") { this->CompressionSuffix = ".xz"; this->TarCompressionType = cmArchiveWrite::CompressXZ; - } else if (!std::strcmp(debianCompressionType, "bzip2")) { + } else if (debianCompressionType == "bzip2") { this->CompressionSuffix = ".bz2"; this->TarCompressionType = cmArchiveWrite::CompressBZip2; - } else if (!std::strcmp(debianCompressionType, "gzip")) { + } else if (debianCompressionType == "gzip") { this->CompressionSuffix = ".gz"; this->TarCompressionType = cmArchiveWrite::CompressGZip; - } else if (!std::strcmp(debianCompressionType, "zstd")) { + } else if (debianCompressionType == "zstd") { this->CompressionSuffix = ".zst"; this->TarCompressionType = cmArchiveWrite::CompressZstd; - } else if (!std::strcmp(debianCompressionType, "none")) { + } else if (debianCompressionType == "none") { this->CompressionSuffix.clear(); this->TarCompressionType = cmArchiveWrite::CompressNone; } else { @@ -539,9 +542,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, std::string localToplevel(initialTopLevel); std::string packageFileName( cmSystemTools::GetParentDirectory(this->toplevel)); - std::string outputFileName( - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + "-" + - packageName + this->GetOutputExtension()); + std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") + + "-" + packageName + this->GetOutputExtension()); localToplevel += "/" + packageName; /* replace the TEMP DIRECTORY with the component one */ @@ -627,9 +629,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( std::string localToplevel(initialTopLevel); std::string packageFileName( cmSystemTools::GetParentDirectory(this->toplevel)); - std::string outputFileName( - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + - this->GetOutputExtension()); + std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") + + this->GetOutputExtension()); // all GROUP in one vs all COMPONENT in one // if must be here otherwise non component paths have a trailing / while // components don't @@ -684,7 +685,7 @@ int cmCPackDebGenerator::PackageFiles() bool cmCPackDebGenerator::createDebPackages() { - auto make_package = [this](const char* const path, + auto make_package = [this](const std::string& path, const char* const output_var, bool (cmCPackDebGenerator::*creator)()) -> bool { try { @@ -706,7 +707,7 @@ bool cmCPackDebGenerator::createDebPackages() bool retval = make_package(this->GetOption("GEN_WDIR"), "GEN_CPACK_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDeb); - const char* const dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); + cmProp dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && dbgsymdir_path) { retval = make_package(dbgsymdir_path, "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDbgsymDDeb) && @@ -723,78 +724,75 @@ bool cmCPackDebGenerator::createDeb() controlValues["Package"] = cmsys::SystemTools::LowerCase( this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); controlValues["Version"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); controlValues["Section"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION"); controlValues["Priority"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY"); controlValues["Architecture"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); controlValues["Maintainer"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); controlValues["Description"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); - const char* debian_pkg_source = + cmProp debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); if (cmNonempty(debian_pkg_source)) { - controlValues["Source"] = debian_pkg_source; + controlValues["Source"] = *debian_pkg_source; } - const char* debian_pkg_dep = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); + cmProp debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); if (cmNonempty(debian_pkg_dep)) { - controlValues["Depends"] = debian_pkg_dep; + controlValues["Depends"] = *debian_pkg_dep; } - const char* debian_pkg_rec = + cmProp debian_pkg_rec = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS"); if (cmNonempty(debian_pkg_rec)) { - controlValues["Recommends"] = debian_pkg_rec; + controlValues["Recommends"] = *debian_pkg_rec; } - const char* debian_pkg_sug = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); + cmProp debian_pkg_sug = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); if (cmNonempty(debian_pkg_sug)) { - controlValues["Suggests"] = debian_pkg_sug; + controlValues["Suggests"] = *debian_pkg_sug; } - const char* debian_pkg_url = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); + cmProp debian_pkg_url = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); if (cmNonempty(debian_pkg_url)) { - controlValues["Homepage"] = debian_pkg_url; + controlValues["Homepage"] = *debian_pkg_url; } - const char* debian_pkg_predep = + cmProp debian_pkg_predep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS"); if (cmNonempty(debian_pkg_predep)) { - controlValues["Pre-Depends"] = debian_pkg_predep; + controlValues["Pre-Depends"] = *debian_pkg_predep; } - const char* debian_pkg_enhances = + cmProp debian_pkg_enhances = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES"); if (cmNonempty(debian_pkg_enhances)) { - controlValues["Enhances"] = debian_pkg_enhances; + controlValues["Enhances"] = *debian_pkg_enhances; } - const char* debian_pkg_breaks = + cmProp debian_pkg_breaks = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS"); if (cmNonempty(debian_pkg_breaks)) { - controlValues["Breaks"] = debian_pkg_breaks; + controlValues["Breaks"] = *debian_pkg_breaks; } - const char* debian_pkg_conflicts = + cmProp debian_pkg_conflicts = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS"); if (cmNonempty(debian_pkg_conflicts)) { - controlValues["Conflicts"] = debian_pkg_conflicts; + controlValues["Conflicts"] = *debian_pkg_conflicts; } - const char* debian_pkg_provides = + cmProp debian_pkg_provides = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES"); if (cmNonempty(debian_pkg_provides)) { - controlValues["Provides"] = debian_pkg_provides; + controlValues["Provides"] = *debian_pkg_provides; } - const char* debian_pkg_replaces = + cmProp debian_pkg_replaces = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES"); if (cmNonempty(debian_pkg_replaces)) { - controlValues["Replaces"] = debian_pkg_replaces; + controlValues["Replaces"] = *debian_pkg_replaces; } const std::string strGenWDIR(this->GetOption("GEN_WDIR")); const std::string shlibsfilename = strGenWDIR + "/shlibs"; - const char* debian_pkg_shlibs = + cmProp debian_pkg_shlibs = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS"); const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") && cmNonempty(debian_pkg_shlibs); @@ -851,32 +849,33 @@ bool cmCPackDebGenerator::createDbgsymDDeb() // debian policy enforce lower case for package name std::string packageNameLower = cmsys::SystemTools::LowerCase( this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); - const char* debian_pkg_version = + cmProp debian_pkg_version = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); controlValues["Package"] = packageNameLower + "-dbgsym"; controlValues["Package-Type"] = "ddeb"; - controlValues["Version"] = debian_pkg_version; + controlValues["Version"] = *debian_pkg_version; controlValues["Auto-Built-Package"] = "debug-symbols"; - controlValues["Depends"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") + - std::string(" (= ") + debian_pkg_version + ")"; + controlValues["Depends"] = + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") + std::string(" (= ") + + *debian_pkg_version + ")"; controlValues["Section"] = "debug"; controlValues["Priority"] = "optional"; controlValues["Architecture"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); controlValues["Maintainer"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); controlValues["Description"] = std::string("debug symbols for ") + packageNameLower; - const char* debian_pkg_source = + cmProp debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); if (cmNonempty(debian_pkg_source)) { - controlValues["Source"] = debian_pkg_source; + controlValues["Source"] = *debian_pkg_source; } - const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS"); + cmProp debian_build_ids = this->GetOption("GEN_BUILD_IDS"); if (cmNonempty(debian_build_ids)) { - controlValues["Build-Ids"] = debian_build_ids; + controlValues["Build-Ids"] = *debian_build_ids; } DebGenerator gen( @@ -914,7 +913,7 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; if (nullptr != this->GetOption(groupVar)) { - return std::string(this->GetOption(groupVar)); + return *this->GetOption(groupVar); } return componentName; } diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index b71c9698280..a4e4ab39f9f 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -18,6 +18,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -260,48 +261,35 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, const std::string& output_file) { // Get optional arguments ... - const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON") - ? this->GetOption("CPACK_PACKAGE_ICON") - : ""; + cmProp cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON"); const std::string cpack_dmg_volume_name = this->GetOption("CPACK_DMG_VOLUME_NAME") - ? this->GetOption("CPACK_DMG_VOLUME_NAME") - : this->GetOption("CPACK_PACKAGE_FILE_NAME"); + ? *this->GetOption("CPACK_DMG_VOLUME_NAME") + : *this->GetOption("CPACK_PACKAGE_FILE_NAME"); const std::string cpack_dmg_format = this->GetOption("CPACK_DMG_FORMAT") - ? this->GetOption("CPACK_DMG_FORMAT") + ? *this->GetOption("CPACK_DMG_FORMAT") : "UDZO"; const std::string cpack_dmg_filesystem = this->GetOption("CPACK_DMG_FILESYSTEM") - ? this->GetOption("CPACK_DMG_FILESYSTEM") + ? *this->GetOption("CPACK_DMG_FILESYSTEM") : "HFS+"; // Get optional arguments ... std::string cpack_license_file = - this->GetOption("CPACK_RESOURCE_FILE_LICENSE") - ? this->GetOption("CPACK_RESOURCE_FILE_LICENSE") - : ""; + *this->GetOption("CPACK_RESOURCE_FILE_LICENSE"); - const std::string cpack_dmg_background_image = - this->GetOption("CPACK_DMG_BACKGROUND_IMAGE") - ? this->GetOption("CPACK_DMG_BACKGROUND_IMAGE") - : ""; + cmProp cpack_dmg_background_image = + this->GetOption("CPACK_DMG_BACKGROUND_IMAGE"); - const std::string cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE") - ? this->GetOption("CPACK_DMG_DS_STORE") - : ""; + cmProp cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE"); - const std::string cpack_dmg_languages = - this->GetOption("CPACK_DMG_SLA_LANGUAGES") - ? this->GetOption("CPACK_DMG_SLA_LANGUAGES") - : ""; + cmProp cpack_dmg_languages = this->GetOption("CPACK_DMG_SLA_LANGUAGES"); - const std::string cpack_dmg_ds_store_setup_script = - this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT") - ? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT") - : ""; + cmProp cpack_dmg_ds_store_setup_script = + this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT"); const bool cpack_dmg_disable_applications_symlink = this->IsOn("CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK"); @@ -332,7 +320,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } // Optionally add a custom volume icon ... - if (!cpack_package_icon.empty()) { + if (!cpack_package_icon->empty()) { std::ostringstream package_icon_source; package_icon_source << cpack_package_icon; @@ -351,7 +339,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally add a custom .DS_Store file // (e.g. for setting background/layout) ... - if (!cpack_dmg_ds_store.empty()) { + if (!cpack_dmg_ds_store->empty()) { std::ostringstream package_settings_source; package_settings_source << cpack_dmg_ds_store; @@ -372,7 +360,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally add a custom background image ... // Make sure the background file type is the same as the custom image // and that the file is hidden so it doesn't show up. - if (!cpack_dmg_background_image.empty()) { + if (!cpack_dmg_background_image->empty()) { const std::string extension = cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image); std::ostringstream package_background_source; @@ -394,7 +382,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } bool remount_image = - !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty(); + !cpack_package_icon->empty() || !cpack_dmg_ds_store_setup_script->empty(); std::string temp_image_format = "UDZO"; @@ -471,7 +459,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } // Optionally set the custom icon flag for the image ... - if (!had_error && !cpack_package_icon.empty()) { + if (!had_error && !cpack_package_icon->empty()) { std::string error; std::ostringstream setfile_command; setfile_command << this->GetOption("CPACK_COMMAND_SETFILE"); @@ -490,7 +478,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally we can execute a custom apple script to generate // the .DS_Store for the volume folder ... - if (!had_error && !cpack_dmg_ds_store_setup_script.empty()) { + if (!had_error && !cpack_dmg_ds_store_setup_script->empty()) { std::ostringstream setup_script_command; setup_script_command << "osascript" << " \"" << cpack_dmg_ds_store_setup_script << "\"" @@ -718,7 +706,7 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( // the current COMPONENT belongs to. std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; - const char* _groupName = GetOption(groupVar); + cmProp _groupName = this->GetOption(groupVar); if (_groupName) { std::string groupName = _groupName; diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index e3521a0e5a9..9cdaafe8749 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -16,6 +16,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -60,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); + cmProp packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); if (cmNonempty(packageScript)) { if (!cmSystemTools::FileIsFullPath(packageScript)) { cmCPackLogger( @@ -76,10 +77,9 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - const char* builtPackagesStr = - this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); - if (builtPackagesStr) { - cmExpandList(builtPackagesStr, this->packageFileNames, false); + cmProp builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); + if (builtPackages) { + cmExpandList(builtPackages, this->packageFileNames, false); } } @@ -181,43 +181,42 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( return 0; } - const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); + cmProp packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); if (packageName) { - root["packageName"] = packageName; + root["packageName"] = *packageName; } - const char* packageVersion = - this->Parent->GetOption("CPACK_PACKAGE_VERSION"); + cmProp packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION"); if (packageVersion) { - root["packageVersion"] = packageVersion; + root["packageVersion"] = *packageVersion; } - const char* packageDescriptionFile = + cmProp packageDescriptionFile = this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); if (packageDescriptionFile) { - root["packageDescriptionFile"] = packageDescriptionFile; + root["packageDescriptionFile"] = *packageDescriptionFile; } - const char* packageDescriptionSummary = + cmProp packageDescriptionSummary = this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY"); if (packageDescriptionSummary) { - root["packageDescriptionSummary"] = packageDescriptionSummary; + root["packageDescriptionSummary"] = *packageDescriptionSummary; } - const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); + cmProp buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); if (buildConfigCstr) { - root["buildConfig"] = buildConfigCstr; + root["buildConfig"] = *buildConfigCstr; } - const char* defaultDirectoryPermissions = + cmProp defaultDirectoryPermissions = this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(defaultDirectoryPermissions)) { - root["defaultDirectoryPermissions"] = defaultDirectoryPermissions; + root["defaultDirectoryPermissions"] = *defaultDirectoryPermissions; } if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) { root["setDestdir"] = true; root["packagingInstallPrefix"] = - this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + *this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); } else { root["setDestdir"] = false; } diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index b673006f25c..39ec3c83ed2 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -203,11 +203,11 @@ cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s, // basically a wrapper that handles the NULL-ptr return from GetOption(). std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name) { - const char* pv = this->GetOption(var_name); + cmProp pv = this->GetOption(var_name); if (!pv) { return std::string(); } - return pv; + return *pv; } // Produce UCL in the given @p manifest file for the common diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 00e274d6d0b..1527e80c6b6 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -78,14 +78,14 @@ int cmCPackGenerator::PrepareNames() std::string tempDirectory = cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/"); - const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); + cmProp toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); if (toplevelTag) { - tempDirectory += toplevelTag; + tempDirectory += *toplevelTag; tempDirectory += "/"; } - tempDirectory += this->GetOption("CPACK_GENERATOR"); + tempDirectory += *this->GetOption("CPACK_GENERATOR"); std::string topDirectory = tempDirectory; - const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME"); + cmProp pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME"); if (!pfname) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_FILE_NAME not specified" << std::endl); @@ -99,7 +99,7 @@ int cmCPackGenerator::PrepareNames() return 0; } outName += this->GetOutputExtension(); - const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY"); + cmProp pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY"); if (!pdir) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_DIRECTORY not specified" << std::endl); @@ -125,7 +125,7 @@ int cmCPackGenerator::PrepareNames() cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl); - const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); + cmProp descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName << std::endl); @@ -135,7 +135,7 @@ int cmCPackGenerator::PrepareNames() << descFileName << "]" << std::endl); return 0; } - cmsys::ifstream ifs(descFileName); + cmsys::ifstream ifs(descFileName->c_str()); if (!ifs) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot open description file name: " << descFileName @@ -151,9 +151,9 @@ int cmCPackGenerator::PrepareNames() ostr << cmXMLSafe(line) << std::endl; } this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); - const char* defFileName = + cmProp defFileName = this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE"); - if (defFileName && !strcmp(defFileName, descFileName)) { + if (defFileName && (defFileName == descFileName)) { this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON"); } } @@ -165,7 +165,7 @@ int cmCPackGenerator::PrepareNames() << std::endl); return 0; } - const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); + cmProp algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); if (algoSignature) { if (!cmCryptoHash::New(algoSignature)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -215,7 +215,7 @@ int cmCPackGenerator::InstallProject() // prepare default created directory permissions mode_t default_dir_mode_v = 0; mode_t* default_dir_mode = nullptr; - const char* default_dir_install_permissions = + cmProp default_dir_install_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_install_permissions)) { std::vector<std::string> items = @@ -266,7 +266,7 @@ int cmCPackGenerator::InstallProject() } // Run pre-build actions - const char* preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); + cmProp preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); if (preBuildScripts) { const auto scripts = cmExpandedList(preBuildScripts, false); for (const auto& script : scripts) { @@ -293,7 +293,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( bool setDestDir, const std::string& tempInstallDirectory) { (void)setDestDir; - const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); + cmProp installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); if (cmNonempty(installCommands)) { std::string tempInstallDirectoryEnv = cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory); @@ -333,7 +333,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( (void)setDestDir; (void)tempInstallDirectory; std::vector<cmsys::RegularExpression> ignoreFilesRegex; - const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); + cmProp cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); if (cpackIgnoreFiles) { std::vector<std::string> ignoreFilesRegexString = cmExpandedList(cpackIgnoreFiles); @@ -343,8 +343,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( ignoreFilesRegex.emplace_back(ifr); } } - const char* installDirectories = - this->GetOption("CPACK_INSTALLED_DIRECTORIES"); + cmProp installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); if (cmNonempty(installDirectories)) { std::vector<std::string> installDirectoriesVector = cmExpandedList(installDirectories); @@ -472,9 +471,9 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( int cmCPackGenerator::InstallProjectViaInstallScript( bool setDestDir, const std::string& tempInstallDirectory) { - const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); + cmProp cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); { - const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); + cmProp const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); if (cmakeScript && cmakeScripts) { cmCPackLogger( cmCPackLog::LOG_WARNING, @@ -485,7 +484,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( cmakeScripts = cmakeScript; } } - if (cmakeScripts && *cmakeScripts) { + if (cmakeScripts && !cmakeScripts->empty()) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts << std::endl); std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts); @@ -502,7 +501,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( std::string dir; if (this->GetOption("CPACK_INSTALL_PREFIX")) { - dir += this->GetOption("CPACK_INSTALL_PREFIX"); + dir += *this->GetOption("CPACK_INSTALL_PREFIX"); } this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str()); cmCPackLogger( @@ -540,8 +539,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( bool setDestDir, const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode) { - const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); - const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); + cmProp cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); + cmProp cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); std::string absoluteDestFiles; if (cmNonempty(cmakeProjects)) { if (!cmakeGenerator) { @@ -595,7 +594,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // Determine the installation types for this project (if provided). std::string installTypesVar = "CPACK_" + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; - const char* installTypes = this->GetOption(installTypesVar); + cmProp installTypes = this->GetOption(installTypesVar); if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); @@ -608,7 +607,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // Determine the set of components that will be used in this project std::string componentsVar = "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); - const char* components = this->GetOption(componentsVar); + cmProp components = this->GetOption(componentsVar); if (cmNonempty(components)) { cmExpandList(components, componentsVector); for (std::string const& comp : componentsVector) { @@ -625,12 +624,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::vector<std::string> buildConfigs; // Try get configuration names given via `-C` CLI option - { - const char* const buildConfigCstr = - this->GetOption("CPACK_BUILD_CONFIG"); - auto buildConfig = buildConfigCstr ? buildConfigCstr : std::string{}; - cmExpandList(buildConfig, buildConfigs); - } + cmExpandList(this->GetOption("CPACK_BUILD_CONFIG"), buildConfigs); // Remove duplicates std::sort(buildConfigs.begin(), buildConfigs.end()); @@ -767,11 +761,11 @@ int cmCPackGenerator::InstallCMakeProject( tempInstallDirectory += this->GetComponentInstallDirNameSuffix(component); if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { tempInstallDirectory += "/"; - tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + tempInstallDirectory += *this->GetOption("CPACK_PACKAGE_FILE_NAME"); } } - const char* default_dir_inst_permissions = + cmProp default_dir_inst_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_inst_permissions)) { mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", @@ -795,12 +789,13 @@ int cmCPackGenerator::InstallCMakeProject( // I know this is tricky and awkward but it's the price for // CPACK_SET_DESTDIR backward compatibility. if (cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) { - this->SetOption("CPACK_INSTALL_PREFIX", - this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); + this->SetOption( + "CPACK_INSTALL_PREFIX", + this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX").GetCStr()); } std::string dir; if (this->GetOption("CPACK_INSTALL_PREFIX")) { - dir += this->GetOption("CPACK_INSTALL_PREFIX"); + dir += *this->GetOption("CPACK_INSTALL_PREFIX"); } mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir); @@ -979,7 +974,7 @@ int cmCPackGenerator::InstallCMakeProject( } else { this->SetOption( absoluteDestFileComponent, - cmToCStr(mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"))); + mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES").GetCStr()); } } } @@ -1038,8 +1033,7 @@ int cmCPackGenerator::DoPackage() } if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) { - const char* toplevelDirectory = - this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + cmProp toplevelDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); if (cmSystemTools::FileExists(toplevelDirectory)) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove toplevel directory: " << toplevelDirectory @@ -1060,9 +1054,9 @@ int cmCPackGenerator::DoPackage() } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl); - const char* tempPackageFileName = + cmProp tempPackageFileName = this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME"); - const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); + cmProp tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); cmsys::Glob gl; @@ -1079,7 +1073,7 @@ int cmCPackGenerator::DoPackage() cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Package files to: " - << (tempPackageFileName ? tempPackageFileName : "(NULL)") + << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << std::endl); if (cmSystemTools::FileExists(tempPackageFileName)) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, @@ -1099,9 +1093,8 @@ int cmCPackGenerator::DoPackage() * may update this during PackageFiles. * (either putting several names or updating the provided one) */ - this->packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName - : ""); - this->toplevel = tempDirectory; + this->packageFileNames.emplace_back(tempPackageFileName); + this->toplevel = *tempDirectory; { // scope that enables package generators to run internal scripts with // latest CMake policies enabled cmMakefile::ScopePushPop pp{ this->MakefileMap }; @@ -1115,7 +1108,7 @@ int cmCPackGenerator::DoPackage() } } // Run post-build actions - const char* postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); + cmProp postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); if (postBuildScripts) { this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES", cmJoin(this->packageFileNames, ";")); @@ -1135,8 +1128,8 @@ int cmCPackGenerator::DoPackage() } /* Prepare checksum algorithm*/ - const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); - std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : ""); + cmProp algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); + std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo); /* * Copy the generated packages to final destination @@ -1151,19 +1144,19 @@ int cmCPackGenerator::DoPackage() for (std::string const& pkgFileName : this->packageFileNames) { std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX")); std::string filename(cmSystemTools::GetFilenameName(pkgFileName)); - tempPackageFileName = pkgFileName.c_str(); + tempPackageFileName = cmProp(pkgFileName); tmpPF += "/" + filename; const char* packageFileName = tmpPF.c_str(); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy final package(s): " - << (tempPackageFileName ? tempPackageFileName : "(NULL)") + << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << " to " << (packageFileName ? packageFileName : "(NULL)") << std::endl); if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Problem copying the package: " - << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to " + << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << " to " << (packageFileName ? packageFileName : "(NULL)") << std::endl); return 0; } @@ -1200,7 +1193,7 @@ int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf) // set the running generator name this->SetOption("CPACK_GENERATOR", this->Name.c_str()); // Load the project specific config file - const char* config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); + cmProp config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); if (config) { mf->ReadListFile(config); } @@ -1250,15 +1243,14 @@ bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const return false; } -const char* cmCPackGenerator::GetOption(const std::string& op) const +cmProp cmCPackGenerator::GetOption(const std::string& op) const { cmProp ret = this->MakefileMap->GetDefinition(op); if (!ret) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Warning, GetOption return NULL for: " << op << std::endl); - return nullptr; } - return ret->c_str(); + return ret; } std::vector<std::string> cmCPackGenerator::GetOptions() const @@ -1311,7 +1303,7 @@ const char* cmCPackGenerator::GetPackagingInstallPrefix() << this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'" << std::endl); - return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")->c_str(); } std::string cmCPackGenerator::FindTemplate(const char* name) @@ -1391,12 +1383,8 @@ int cmCPackGenerator::PrepareGroupingKind() method = ONE_PACKAGE_PER_GROUP; } - std::string groupingType; - // Second way to specify grouping - if (nullptr != this->GetOption("CPACK_COMPONENTS_GROUPING")) { - groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING"); - } + std::string groupingType = *this->GetOption("CPACK_COMPONENTS_GROUPING"); if (!groupingType.empty()) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, @@ -1477,18 +1465,18 @@ std::string cmCPackGenerator::GetComponentPackageFileName( if (isGroupName) { std::string groupDispVar = "CPACK_COMPONENT_GROUP_" + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME"; - const char* groupDispName = this->GetOption(groupDispVar); + cmProp groupDispName = this->GetOption(groupDispVar); if (groupDispName) { - suffix = "-" + std::string(groupDispName); + suffix = "-" + *groupDispName; } } /* the [single] component case */ else { std::string dispVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME"; - const char* dispName = this->GetOption(dispVar); + cmProp dispName = this->GetOption(dispVar); if (dispName) { - suffix = "-" + std::string(dispName); + suffix = "-" + *dispName; } } } @@ -1531,9 +1519,9 @@ cmCPackInstallationType* cmCPackGenerator::GetInstallationType( "CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name); installType->Name = name; - const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { - installType->DisplayName = displayName; + installType->DisplayName = *displayName; } else { installType->DisplayName = installType->Name; } @@ -1553,9 +1541,9 @@ cmCPackComponent* cmCPackGenerator::GetComponent( std::string macroPrefix = "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name); component->Name = name; - const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { - component->DisplayName = displayName; + component->DisplayName = *displayName; } else { component->DisplayName = component->Name; } @@ -1565,17 +1553,17 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") || cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); - const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); + cmProp archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); if (cmNonempty(archiveFile)) { - component->ArchiveFile = archiveFile; + component->ArchiveFile = *archiveFile; } - const char* plist = this->GetOption(macroPrefix + "_PLIST"); + cmProp plist = this->GetOption(macroPrefix + "_PLIST"); if (cmNonempty(plist)) { - component->Plist = plist; + component->Plist = *plist; } - const char* groupName = this->GetOption(macroPrefix + "_GROUP"); + cmProp groupName = this->GetOption(macroPrefix + "_GROUP"); if (cmNonempty(groupName)) { component->Group = this->GetComponentGroup(projectName, groupName); component->Group->Components.push_back(component); @@ -1583,13 +1571,13 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->Group = nullptr; } - const char* description = this->GetOption(macroPrefix + "_DESCRIPTION"); + cmProp description = this->GetOption(macroPrefix + "_DESCRIPTION"); if (cmNonempty(description)) { - component->Description = description; + component->Description = *description; } // Determine the installation types. - const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); + cmProp installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); @@ -1600,7 +1588,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( } // Determine the component dependencies. - const char* depends = this->GetOption(macroPrefix + "_DEPENDS"); + cmProp depends = this->GetOption(macroPrefix + "_DEPENDS"); if (cmNonempty(depends)) { std::vector<std::string> dependsVector = cmExpandedList(depends); for (std::string const& depend : dependsVector) { @@ -1624,21 +1612,20 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup( if (!hasGroup) { // Define the group group->Name = name; - const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { - group->DisplayName = displayName; + group->DisplayName = *displayName; } else { group->DisplayName = group->Name; } - const char* description = this->GetOption(macroPrefix + "_DESCRIPTION"); + cmProp description = this->GetOption(macroPrefix + "_DESCRIPTION"); if (cmNonempty(description)) { - group->Description = description; + group->Description = *description; } group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE"); group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED"); - const char* parentGroupName = - this->GetOption(macroPrefix + "_PARENT_GROUP"); + cmProp parentGroupName = this->GetOption(macroPrefix + "_PARENT_GROUP"); if (cmNonempty(parentGroupName)) { group->ParentGroup = this->GetComponentGroup(projectName, parentGroupName); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 2512d4208a3..1968c35585e 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -12,6 +12,7 @@ #include "cm_sys_stat.h" #include "cmCPackComponentGroup.h" +#include "cmProperty.h" #include "cmSystemTools.h" class cmCPackLog; @@ -85,7 +86,7 @@ class cmCPackGenerator //! Set and get the options void SetOption(const std::string& op, const char* value); void SetOptionIfNotSet(const std::string& op, const char* value); - const char* GetOption(const std::string& op) const; + cmProp GetOption(const std::string& op) const; std::vector<std::string> GetOptions() const; bool IsSet(const std::string& name) const; bool IsOn(const std::string& name) const; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 395b1dfb5d8..a3b59ca7887 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -19,6 +19,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -142,9 +143,9 @@ int cmCPackNSISGenerator::PackageFiles() } std::string installerHeaderImage; if (this->IsSet("CPACK_NSIS_MUI_HEADERIMAGE")) { - installerHeaderImage = this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE"); + installerHeaderImage = *this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE"); } else if (this->IsSet("CPACK_PACKAGE_ICON")) { - installerHeaderImage = this->GetOption("CPACK_PACKAGE_ICON"); + installerHeaderImage = *this->GetOption("CPACK_PACKAGE_ICON"); } if (!installerHeaderImage.empty()) { std::string installerIconCode = cmStrCat( @@ -479,8 +480,8 @@ int cmCPackNSISGenerator::InitializeInternal() cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs"); if (!resS || retVal || (!versionRex.find(output) && !versionRexCVS.find(output))) { - const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log"); + cmProp topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + std::string tmpFile = cmStrCat(topDir ? *topDir : ".", "/NSISOutput.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << nsisCmd << std::endl << "# Output:" << std::endl @@ -512,11 +513,11 @@ int cmCPackNSISGenerator::InitializeInternal() } this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str()); this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin"); - const char* cpackPackageExecutables = + cmProp cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); - const char* cpackPackageDeskTopLinks = + cmProp cpackPackageDeskTopLinks = this->GetOption("CPACK_CREATE_DESKTOP_LINKS"); - const char* cpackNsisExecutablesDirectory = + cmProp cpackNsisExecutablesDirectory = this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"); std::vector<std::string> cpackPackageDesktopLinksVector; if (cpackPackageDeskTopLinks) { @@ -589,7 +590,7 @@ int cmCPackNSISGenerator::InitializeInternal() void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, std::ostream& deleteStr) { - const char* cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS"); + cmProp cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS"); if (!cpackMenuLinks) { return; } @@ -728,11 +729,10 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( } // Create the directory for the upload area - const char* userUploadDirectory = - this->GetOption("CPACK_UPLOAD_DIRECTORY"); + cmProp userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; if (cmNonempty(userUploadDirectory)) { - uploadDirectory = userUploadDirectory; + uploadDirectory = *userUploadDirectory; } else { uploadDirectory = cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads"); @@ -968,9 +968,9 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription( std::string cmCPackNSISGenerator::CustomComponentInstallDirectory( cm::string_view componentName) { - const char* outputDir = this->GetOption( + cmProp outputDir = this->GetOption( cmStrCat("CPACK_NSIS_", componentName, "_INSTALL_DIRECTORY")); - return outputDir ? outputDir : "$INSTDIR"; + return outputDir ? *outputDir : "$INSTDIR"; } std::string cmCPackNSISGenerator::TranslateNewlines(std::string str) diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx index 98dc8906f0a..9e7f92aed7e 100644 --- a/Source/CPack/cmCPackNuGetGenerator.cxx +++ b/Source/CPack/cmCPackNuGetGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -120,7 +121,7 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup) void cmCPackNuGetGenerator::AddGeneratedPackageNames() { - const char* const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES"); + cmProp const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES"); if (!files_list) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -129,7 +130,7 @@ void cmCPackNuGetGenerator::AddGeneratedPackageNames() return; } // add the generated packages to package file names list - std::string fileNames{ files_list }; + const std::string& fileNames = *files_list; const char sep = ';'; std::string::size_type pos1 = 0; std::string::size_type pos2 = fileNames.find(sep, pos1 + 1); diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 5de4a6f3fe3..262cc6e203e 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -10,6 +10,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -22,7 +23,7 @@ int cmCPackOSXX11Generator::PackageFiles() // TODO: Use toplevel ? // It is used! Is this an obsolete comment? - const char* cpackPackageExecutables = + cmProp cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { cmCPackLogger(cmCPackLog::LOG_DEBUG, @@ -70,7 +71,7 @@ int cmCPackOSXX11Generator::PackageFiles() const char* scrDir = scriptDirectory.c_str(); const char* contDir = contentsDirectory.c_str(); const char* rsrcFile = resourceFileName.c_str(); - const char* iconFile = this->GetOption("CPACK_PACKAGE_ICON"); + cmProp iconFile = this->GetOption("CPACK_PACKAGE_ICON"); if (iconFile) { std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile); if (!cmSystemTools::FileExists(iconFile)) { @@ -103,9 +104,9 @@ int cmCPackOSXX11Generator::PackageFiles() true) || !this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir, rsrcFile, true) || - !this->CopyResourcePlistFile("OSXScriptLauncher", appdir, - this->GetOption("CPACK_PACKAGE_FILE_NAME"), - true)) { + !this->CopyResourcePlistFile( + "OSXScriptLauncher", appdir, + this->GetOption("CPACK_PACKAGE_FILE_NAME").GetCStr(), true)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files" << std::endl); return 0; diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index ac3d64d9aec..a1eba561cc2 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -7,6 +7,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -56,7 +57,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName, std::string opt = (themeName == nullptr) ? cmStrCat("CPACK_", genName, "_BACKGROUND") : cmStrCat("CPACK_", genName, "_BACKGROUND_", paramSuffix); - const char* bgFileName = this->GetOption(opt); + cmProp bgFileName = this->GetOption(opt); if (bgFileName == nullptr) { return; } @@ -78,7 +79,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName, xout.Attribute("file", bgFileName); - const char* param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); + cmProp param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); if (param != nullptr) { xout.Attribute("alignment", param); } @@ -315,7 +316,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, { std::string uname = cmSystemTools::UpperCase(name); std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname; - const char* inFileName = this->GetOption(cpackVar); + cmProp inFileName = this->GetOption(cpackVar); if (!inFileName) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str() @@ -351,7 +352,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, (name + ext).c_str()); cmCPackLogger(cmCPackLog::LOG_VERBOSE, - "Configure file: " << (inFileName ? inFileName : "(NULL)") + "Configure file: " << (inFileName ? *inFileName : "(NULL)") << " to " << destFileName << std::endl); this->ConfigureFile(inFileName, destFileName); return true; diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index f51ea42de9e..33b601c9006 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -16,6 +16,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -79,9 +80,9 @@ int cmCPackPackageMakerGenerator::PackageFiles() resDir += "/en.lproj"; } - const char* preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); - const char* postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); - const char* postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); + cmProp preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); + cmProp postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); + cmProp postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); if (this->Components.empty()) { // Create directory structure @@ -167,10 +168,9 @@ int cmCPackPackageMakerGenerator::PackageFiles() // Create the directory where downloaded component packages will // be placed. - const char* userUploadDirectory = - this->GetOption("CPACK_UPLOAD_DIRECTORY"); + cmProp userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; - if (userUploadDirectory && *userUploadDirectory) { + if (userUploadDirectory && !userUploadDirectory->empty()) { uploadDirectory = userUploadDirectory; } else { uploadDirectory = @@ -352,8 +352,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal() "/PackageMaker.app/Contents/MacOS"); std::string pkgPath; - const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); - if (inst_program && *inst_program) { + cmProp inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); + if (inst_program && !inst_program->empty()) { pkgPath = inst_program; } else { pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false); @@ -427,11 +427,12 @@ int cmCPackPackageMakerGenerator::InitializeInternal() // Determine the package compatibility version. If it wasn't // specified by the user, we define it based on which features the // user requested. - const char* packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); - if (packageCompat && *packageCompat) { + cmProp packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); + if (packageCompat && !packageCompat->empty()) { unsigned int majorVersion = 10; unsigned int minorVersion = 5; - int res = sscanf(packageCompat, "%u.%u", &majorVersion, &minorVersion); + int res = + sscanf(packageCompat->c_str(), "%u.%u", &majorVersion, &minorVersion); if (res == 2) { this->PackageCompatibilityVersion = getVersion(majorVersion, minorVersion); diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a3e55de5c28..99c55a00fc9 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -10,6 +10,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -87,11 +88,11 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); std::string identityName; - if (const char* n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { + if (cmProp n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { identityName = n; } std::string keychainPath; - if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { + if (cmProp p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { keychainPath = p; } @@ -173,8 +174,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( const char* comp_name = component ? component->Name.c_str() : nullptr; - const char* preflight = this->GetComponentScript("PREFLIGHT", comp_name); - const char* postflight = this->GetComponentScript("POSTFLIGHT", comp_name); + cmProp preflight = this->GetComponentScript("PREFLIGHT", comp_name); + cmProp postflight = this->GetComponentScript("POSTFLIGHT", comp_name); std::string resDir = packageFileDir; if (component) { @@ -213,11 +214,11 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); std::string identityName; - if (const char* n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { + if (cmProp n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { identityName = n; } std::string keychainPath; - if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { + if (cmProp p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { keychainPath = p; } @@ -239,7 +240,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( return RunProductBuild(pkgCmd.str()); } -const char* cmCPackProductBuildGenerator::GetComponentScript( +cmProp cmCPackProductBuildGenerator::GetComponentScript( const char* script, const char* component_name) { std::string scriptname = std::string("CPACK_") + script + "_"; diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h index 462e2fcc9c2..8f169b0c6e4 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.h +++ b/Source/CPack/cmCPackProductBuildGenerator.h @@ -8,6 +8,7 @@ #include "cmCPackGenerator.h" #include "cmCPackPKGGenerator.h" +#include "cmProperty.h" class cmCPackComponent; @@ -45,6 +46,5 @@ class cmCPackProductBuildGenerator : public cmCPackPKGGenerator const std::string& packageDir, const cmCPackComponent* component); - const char* GetComponentScript(const char* script, - const char* script_component); + cmProp GetComponentScript(const char* script, const char* script_component); }; diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index c3f6d594b5e..2765c58d3d4 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -103,7 +104,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) this->packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); + cmProp mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") && !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) { diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index ad0a3e21b05..7eb8cc31f86 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -14,6 +14,7 @@ #include "cmArchiveWrite.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmSystemTools.h" cmCPackSTGZGenerator::cmCPackSTGZGenerator() From bbcdac4e5d53de12013c6af6395b28e4816f7823 Mon Sep 17 00:00:00 2001 From: Cristian Adam <cristian.adam@gmail.com> Date: Sat, 7 Aug 2021 08:07:55 -0700 Subject: [PATCH 1215/1519] PCH: Fix all-language precompile header support in Xcode Fixes: #22384 --- Source/cmGeneratorTarget.cxx | 4 ++-- Source/cmLocalGenerator.cxx | 15 +++++++++++++++ .../PchIncludedAllLanguages.cmake | 16 ++++++++++++++++ .../PrecompileHeaders/RunCMakeTest.cmake | 1 + Tests/RunCMake/PrecompileHeaders/pch-included.c | 8 ++++++++ .../RunCMake/PrecompileHeaders/pch-included.cpp | 8 ++++++++ Tests/RunCMake/PrecompileHeaders/pch.h | 2 ++ 7 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake create mode 100644 Tests/RunCMake/PrecompileHeaders/pch-included.c create mode 100644 Tests/RunCMake/PrecompileHeaders/pch-included.cpp diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 17237bb5069..bb751d68775 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4100,7 +4100,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, if (this->GetGlobalGenerator()->IsXcode()) { file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n"; } - if (language == "CXX") { + if (language == "CXX" && !this->GetGlobalGenerator()->IsXcode()) { file << "#ifdef __cplusplus\n"; } for (auto const& header_bt : headers) { @@ -4118,7 +4118,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, firstHeaderOnDisk = header_bt.Value; } } - if (language == "CXX") { + if (language == "CXX" && !this->GetGlobalGenerator()->IsXcode()) { file << "#endif // __cplusplus\n"; } if (this->GetGlobalGenerator()->IsXcode()) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 028952a9c00..016653bd731 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2512,6 +2512,16 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) static const std::array<std::string, 4> langs = { { "C", "CXX", "OBJC", "OBJCXX" } }; + bool haveAnyPch = false; + if (this->GetGlobalGenerator()->IsXcode()) { + for (const std::string& lang : langs) { + const std::string pchHeader = target->GetPchHeader(config, lang, ""); + if (!pchHeader.empty()) { + haveAnyPch = true; + } + } + } + for (const std::string& lang : langs) { auto langSources = std::count_if( sources.begin(), sources.end(), [lang](cmSourceFile* sf) { @@ -2552,6 +2562,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) const std::string pchHeader = target->GetPchHeader(config, lang, arch); if (pchSource.empty() || pchHeader.empty()) { + if (this->GetGlobalGenerator()->IsXcode() && haveAnyPch) { + for (auto* sf : sources) { + sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON"); + } + } continue; } diff --git a/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake new file mode 100644 index 00000000000..a4554103d24 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.15) +project(PchIncludedAllLanguages C CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +add_executable(main + main.cpp + pch-included.c + pch-included.cpp +) +target_precompile_headers(main PRIVATE pch.h) + +enable_testing() +add_test(NAME main COMMAND main) diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index 8cc59d224e2..e723e03f1c0 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -28,3 +28,4 @@ if(RunCMake_GENERATOR MATCHES "Make|Ninja") endif() endif() run_test(PchReuseFromObjLib) +run_test(PchIncludedAllLanguages) diff --git a/Tests/RunCMake/PrecompileHeaders/pch-included.c b/Tests/RunCMake/PrecompileHeaders/pch-included.c new file mode 100644 index 00000000000..96fce697ef0 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/pch-included.c @@ -0,0 +1,8 @@ +#ifndef HAVE_PCH_SUPPORT +# include "pch.h" +#endif + +int testC(void) +{ + return PCH_INCLUDED; +} diff --git a/Tests/RunCMake/PrecompileHeaders/pch-included.cpp b/Tests/RunCMake/PrecompileHeaders/pch-included.cpp new file mode 100644 index 00000000000..bf4d95d47eb --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/pch-included.cpp @@ -0,0 +1,8 @@ +#ifndef HAVE_PCH_SUPPORT +# include "pch.h" +#endif + +int testCpp() +{ + return PCH_INCLUDED; +} diff --git a/Tests/RunCMake/PrecompileHeaders/pch.h b/Tests/RunCMake/PrecompileHeaders/pch.h index 81b6d9eed0a..20672d1f848 100644 --- a/Tests/RunCMake/PrecompileHeaders/pch.h +++ b/Tests/RunCMake/PrecompileHeaders/pch.h @@ -1,3 +1,5 @@ #pragma once #define PCH_INCLUDED 1 + +int testC(void); From 161990b92135c6b464ce696692f742667832b6e3 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro <silvio.traversaro@iit.it> Date: Sat, 28 Aug 2021 12:12:09 +0200 Subject: [PATCH 1216/1519] FindMatlab: Add imported targets --- .../dev/find-matlab-imported-targets.rst | 4 ++ Modules/FindMatlab.cmake | 53 +++++++++++++++++++ Tests/CMakeLists.txt | 2 + .../FindMatlab/targets_checks/CMakeLists.txt | 44 +++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 Help/release/dev/find-matlab-imported-targets.rst create mode 100644 Tests/FindMatlab/targets_checks/CMakeLists.txt diff --git a/Help/release/dev/find-matlab-imported-targets.rst b/Help/release/dev/find-matlab-imported-targets.rst new file mode 100644 index 00000000000..33a93ffc087 --- /dev/null +++ b/Help/release/dev/find-matlab-imported-targets.rst @@ -0,0 +1,4 @@ +find-matlab-imported-targets +---------------------------- + +* The :module:`FindMatlab` module now provides imported targets. diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index c8df670b1b6..12a5fde7e6d 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -93,6 +93,33 @@ behavior: additional versions of Matlab for the automatic retrieval of the installed versions. +Imported targets +^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.22 + +This module defines the following :prop_tgt:`IMPORTED` targets: + +``Matlab::mex`` + The ``mex`` library, always available. + +``Matlab::mx`` + The mx library of Matlab (arrays), always available. + +``Matlab::eng`` + Matlab engine library. Available only if the ``ENG_LIBRARY`` component + is requested. + +``Matlab::mat`` + Matlab matrix library. Available only if the ``MAT_LIBRARY`` component + is requested. + +``Matlab::MatlabEngine`` + Matlab C++ engine library, always available for R2018a and newer. + +``Matlab::MatlabDataArray`` + Matlab C++ data array library, always available for R2018a and newer. + Variables defined by the module ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1865,6 +1892,32 @@ if(Matlab_DATAARRAY_LIBRARY) list(APPEND Matlab_LIBRARIES ${Matlab_DATAARRAY_LIBRARY}) endif() +# internal +# This small stub permits to add imported targets for the found MATLAB libraries +function(_Matlab_add_imported_target _matlab_library_variable_name _matlab_library_target_name) + if(Matlab_${_matlab_library_variable_name}_LIBRARY) + if(NOT TARGET Matlab::${_matlab_library_target_name}) + add_library(Matlab::${_matlab_library_target_name} UNKNOWN IMPORTED) + set_target_properties(Matlab::${_matlab_library_target_name} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Matlab_INCLUDE_DIRS}" + IMPORTED_LOCATION "${Matlab_${_matlab_library_variable_name}_LIBRARY}") + if(_matlab_library_target_name STREQUAL "mex" OR + _matlab_library_target_name STREQUAL "eng" OR + _matlab_library_target_name STREQUAL "mat") + set_target_properties(Matlab::${_matlab_library_target_name} PROPERTIES + INTERFACE_LINK_LIBRARIES Matlab::mx) + endif() + endif() + endif() +endfunction() + +_Matlab_add_imported_target(MX mx) +_Matlab_add_imported_target(MEX mex) +_Matlab_add_imported_target(ENG eng) +_Matlab_add_imported_target(MAT mat) +_Matlab_add_imported_target(ENGINE MatlabEngine) +_Matlab_add_imported_target(DATAARRAY MatlabDataArray) + find_package_handle_standard_args( Matlab FOUND_VAR Matlab_FOUND diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 76c6c05cdef..4ccbfebf46c 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1551,6 +1551,8 @@ if(BUILD_TESTING) ADD_TEST_MACRO(FindMatlab.failure_reports ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) set(FindMatlab.r2018a_check_BUILD_OPTIONS ${FindMatlab_additional_test_options}) ADD_TEST_MACRO(FindMatlab.r2018a_check ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) + set(FindMatlab.targets_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options}) + ADD_TEST_MACRO(FindMatlab.targets_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) endif() add_test(ExternalProject ${CMAKE_CTEST_COMMAND} diff --git a/Tests/FindMatlab/targets_checks/CMakeLists.txt b/Tests/FindMatlab/targets_checks/CMakeLists.txt new file mode 100644 index 00000000000..4af7cc36065 --- /dev/null +++ b/Tests/FindMatlab/targets_checks/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required (VERSION 2.8.12) +enable_testing() +project(targets_checks) + +set(MATLAB_FIND_DEBUG TRUE) + +if(NOT "${MCR_ROOT}" STREQUAL "") + set(Matlab_ROOT_DIR "${MCR_ROOT}") + if(NOT EXISTS "${MCR_ROOT}") + message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}") + endif() +endif() + +# the success of the following command is dependent on the current configuration: +# - on 32bits builds (cmake is building with 32 bits), it looks for 32 bits Matlab +# - on 64bits builds (cmake is building with 64 bits), it looks for 64 bits Matlab +find_package(Matlab REQUIRED COMPONENTS ENG_LIBRARY MAT_LIBRARY + OPTIONAL_COMPONENTS MAIN_PROGRAM) + +if(NOT TARGET Matlab::mx) + message(FATAL_ERROR "Matlab::mx target does not exist") +endif() + +if(NOT TARGET Matlab::mex) + message(FATAL_ERROR "Matlab::mex target does not exist") +endif() + +if(NOT TARGET Matlab::eng) + message(FATAL_ERROR "Matlab::eng target does not exist") +endif() + +if(NOT TARGET Matlab::mat) + message(FATAL_ERROR "Matlab::mat target does not exist") +endif() + +matlab_add_mex( + # target name + NAME cmake_matlab_test_wrapper1 + # output name + OUTPUT_NAME cmake_matlab_mex1 + SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp + DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt + LINK_TO Matlab::mex + ) From 6ef7bfbb645c9f232b41b66b8fb334da8b5ca947 Mon Sep 17 00:00:00 2001 From: Lucas SOLTIC <lucas.soltic@orange.fr> Date: Tue, 14 Sep 2021 08:37:48 +1000 Subject: [PATCH 1217/1519] Xcode: add support for embedding dynamic libraries --- Source/cmGlobalXCodeGenerator.cxx | 7 ++-- Source/cmSystemTools.cxx | 6 ++++ Source/cmSystemTools.h | 6 +++- .../EmbedFrameworksFlagsOff.cmake | 2 +- ...rameworksFlagsOnNoSubdir-build-check.cmake | 4 +-- .../EmbedFrameworksFlagsOnNoSubdir.cmake | 2 +- ...meworksFlagsOnWithSubdir-build-check.cmake | 4 +-- .../EmbedFrameworksFlagsOnWithSubdir.cmake | 2 +- ...ework.cmake => ExternalDependencies.cmake} | 2 ++ .../XcodeProject-Embed/RunCMakeTest.cmake | 36 ++++++++++--------- 10 files changed, 44 insertions(+), 27 deletions(-) rename Tests/RunCMake/XcodeProject-Embed/{ExternalFramework.cmake => ExternalDependencies.cmake} (72%) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index fa76b010b56..4ccc955d2d5 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3809,7 +3809,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects( copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", this->CreateString("0")); cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - // Collect all embedded frameworks and add them to build phase + // Collect all embedded frameworks and dylibs and add them to build phase std::vector<std::string> relFiles = cmExpandedList(*files); for (std::string const& relFile : relFiles) { cmXCodeObject* buildFile{ nullptr }; @@ -3839,7 +3839,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects( } else { buildFile = it->second; } - } else if (cmSystemTools::IsPathToFramework(relFile)) { + } else if (cmSystemTools::IsPathToFramework(relFile) || + cmSystemTools::IsPathToMacOSSharedLibrary(relFile)) { // This is a regular string path - create file reference auto it = this->EmbeddedLibRefs.find(relFile); if (it == this->EmbeddedLibRefs.end()) { @@ -3905,6 +3906,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) { static const auto dstSubfolderSpec = "10"; + // Despite the name, by default Xcode uses "Embed Frameworks" build phase for + // both frameworks and dynamic libraries this->AddEmbeddedObjects(target, "Embed Frameworks", "XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec, NoActionOnCopyByDefault); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 54fe7a14a5e..a20e787346c 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1592,6 +1592,12 @@ bool cmSystemTools::IsPathToFramework(const std::string& path) cmHasLiteralSuffix(path, ".framework")); } +bool cmSystemTools::IsPathToMacOSSharedLibrary(const std::string& path) +{ + return (cmSystemTools::FileIsFullPath(path) && + cmHasLiteralSuffix(path, ".dylib")); +} + bool cmSystemTools::CreateTar(const std::string& outFileName, const std::vector<std::string>& files, cmTarCompression compressType, bool verbose, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 44ccbf7a39a..be817b14801 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -102,7 +102,11 @@ class cmSystemTools : public cmsys::SystemTools } //! Return true if the path is a framework - static bool IsPathToFramework(const std::string& value); + static bool IsPathToFramework(const std::string& path); + + //! Return true if the path is a macOS non-framework shared library (aka + //! .dylib) + static bool IsPathToMacOSSharedLibrary(const std::string& path); static bool DoesFileExistWithExtensions( const std::string& name, const std::vector<std::string>& sourceExts); diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake index f4fe07fde7e..54375d52b7d 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake @@ -1,7 +1,7 @@ add_executable(app MACOSX_BUNDLE main.m) set_target_properties(app PROPERTIES - XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}" + XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}" XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY OFF XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY OFF ) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake index e4ea55df2bc..23fd49d593b 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake @@ -1,3 +1,3 @@ -if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/sharedFrameworkExt.framework) - set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location") +if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/${EXTERNAL_DEPENDENCY_NAME}) + set(RunCMake_TEST_FAILED "${EXTERNAL_DEPENDENCY_NAME} was not embedded at the expected location") endif() diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake index 79d8d777943..c76226fb955 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake @@ -1,7 +1,7 @@ add_executable(app MACOSX_BUNDLE main.m) set_target_properties(app PROPERTIES - XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}" + XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}" XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON ) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake index 57c79eae4bb..732f04c2313 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake @@ -1,3 +1,3 @@ -if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/sharedFrameworkExt.framework) - set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location") +if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/${EXTERNAL_DEPENDENCY_NAME}) + set(RunCMake_TEST_FAILED "${EXTERNAL_DEPENDENCY_NAME} was not embedded at the expected location") endif() diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake index 4c78199e518..f83b1bf795a 100644 --- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake @@ -1,7 +1,7 @@ add_executable(app MACOSX_BUNDLE main.m) set_target_properties(app PROPERTIES - XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}" + XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}" XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON XCODE_EMBED_FRAMEWORKS_PATH "subdir" diff --git a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake b/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake similarity index 72% rename from Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake rename to Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake index 64e2f958766..8c7b06af9c4 100644 --- a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake @@ -1,2 +1,4 @@ add_library(sharedFrameworkExt SHARED func.m) set_target_properties(sharedFrameworkExt PROPERTIES FRAMEWORK TRUE) + +add_library(sharedDylibExt SHARED func.m) diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake index e94d084c10c..f3a691872b4 100644 --- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake @@ -1,47 +1,49 @@ include(RunCMake) -# Build a framework that the other tests will use and treat as external. +# Build dependencies that the other tests will use and treat as external. # Always build in the Debug configuration so that the path to the framework # is predictable. -function(ExternalFramework) +function(ExternalDependencies) set(RunCMake_TEST_NO_CLEAN 1) - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalFramework-build) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalDependencies-build) set(externalFramework ${RunCMake_TEST_BINARY_DIR}/Debug/sharedFrameworkExt.framework PARENT_SCOPE) + set(externalDylib ${RunCMake_TEST_BINARY_DIR}/Debug/libsharedDylibExt.dylib PARENT_SCOPE) file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") - run_cmake(ExternalFramework) - run_cmake_command(ExternalFramework-build + run_cmake(ExternalDependencies) + run_cmake_command(ExternalDependencies-build ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --config Debug - --target sharedFrameworkExt + --target sharedFrameworkExt sharedDylibExt ) endfunction() -ExternalFramework() +ExternalDependencies() -set(RunCMake_TEST_OPTIONS -DEXTERNAL_FWK=${externalFramework}) - -run_cmake(EmbedFrameworksFlagsOff) - -function(TestFlagsOn testName) +function(TestFlagsOn testName dependencyName) set(RunCMake_TEST_NO_CLEAN 1) - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-${dependencyName}-build) file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") run_cmake(${testName}) - run_cmake_command(${testName}-build + run_cmake_command(${testName}-${dependencyName}-build ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --config Debug --target app ) endfunction() -TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir) -TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir) - +foreach(dependency ${externalFramework} ${externalDylib}) + cmake_path(GET dependency FILENAME dependencyName) + set(RunCMake_TEST_OPTIONS -DEXTERNAL_DEPENDENCY=${dependency} -DEXTERNAL_DEPENDENCY_NAME=${dependencyName}) + run_cmake(EmbedFrameworksFlagsOff) + TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir ${dependencyName}) + TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir ${dependencyName}) +endforeach() +unset(RunCMake_TEST_OPTIONS) function(TestAppExtension platform) set(testName EmbedAppExtensions-${platform}) From de1c6c0bc5c6745526e2923783349faed1c0bbf5 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 14 Sep 2021 00:01:11 -0400 Subject: [PATCH 1218/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8b12a1a9918..94e36e8a671 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210913) +set(CMake_VERSION_PATCH 20210914) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From eb3b3bacdc93e44d942af912ac5a5b16cfa9813a Mon Sep 17 00:00:00 2001 From: Andras Lasso <lasso@queensu.ca> Date: Mon, 13 Sep 2021 19:45:46 -0400 Subject: [PATCH 1219/1519] CPack/NSIS: Fix uninstall on Windows using "Apps & Features" According to NSIS documentation [1], uninstaller executable path in UninstallString must always be quoted. Quote the uninstall executable in `NSIS.template.in` so that it works when the path has spaces. [1] https://nsis.sourceforge.io/Add_uninstall_information_to_Add/Remove_Programs --- Modules/Internal/CPack/NSIS.template.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index 1df8a5885f6..8a0c9726c9d 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -674,7 +674,7 @@ Section "-Core installation" Push "@CPACK_PACKAGE_VENDOR@" Call ConditionalAddToRegisty Push "UninstallString" - Push "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" + Push "$\"$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe$\"" Call ConditionalAddToRegisty Push "NoRepair" Push "1" From 51fd21736b10e2fa04382c5aa71f2044d31e362f Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Tue, 14 Sep 2021 11:08:42 -0400 Subject: [PATCH 1220/1519] FindFLTK: Safe to include multiple times FindFLTK could store multiple entries in `FLTK_INCLUDE_DIR`, and when re-executed would stored into `FLTK_DIR` which had uses which presumed single entries. Fixes #13198 --- Modules/FindFLTK.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Modules/FindFLTK.cmake b/Modules/FindFLTK.cmake index bab72560dfd..d54d2f68b7c 100644 --- a/Modules/FindFLTK.cmake +++ b/Modules/FindFLTK.cmake @@ -152,13 +152,17 @@ if(NOT FLTK_DIR) endif() # Check if FLTK was built using CMake -if(EXISTS ${FLTK_DIR}/FLTKConfig.cmake) - set(FLTK_BUILT_WITH_CMAKE 1) -endif() +foreach(fltk_include IN LISTS FLTK_DIR) + if(EXISTS "${fltk_include}/FLTKConfig.cmake") + set(FLTK_BUILT_WITH_CMAKE 1) + set(FLTK_CMAKE_PATH "${fltk_include}/FLTKConfig.cmake") + break() + endif() +endforeach() if(FLTK_BUILT_WITH_CMAKE) set(FLTK_FOUND 1) - include(${FLTK_DIR}/FLTKConfig.cmake) + include("${FLTK_CMAKE_PATH}") # Fluid if(FLUID_COMMAND) From 79362cf11715ffc5acd48ec884559d69a35a655d Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 13 Sep 2021 16:55:00 +0200 Subject: [PATCH 1221/1519] cmProp: cm::string_view cast operator must be explicit To avoid ambiguity on std::string assigment between the following two cmProp cast operators: * operator const std::string&() const noexcept * operator cm::string_view() const noexcept --- Source/CPack/cmCPackGenerator.cxx | 4 ++-- Source/cmCoreTryCompile.cxx | 6 +++--- Source/cmMakefile.h | 4 ++++ Source/cmProperty.h | 5 ++++- Source/cmSeparateArgumentsCommand.cxx | 3 ++- Source/cmStringAlgorithms.h | 26 ++++++++++++++++++++++++-- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 1527e80c6b6..4ad25ad66ed 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -167,7 +167,7 @@ int cmCPackGenerator::PrepareNames() } cmProp algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); if (algoSignature) { - if (!cmCryptoHash::New(algoSignature)) { + if (!cmCryptoHash::New(*algoSignature)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot recognize algorithm: " << algoSignature << std::endl); @@ -1129,7 +1129,7 @@ int cmCPackGenerator::DoPackage() /* Prepare checksum algorithm*/ cmProp algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); - std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo); + std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(*algo); /* * Copy the generated packages to final destination diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 0fd48f0b8f9..0c85d287252 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -606,7 +606,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string langFlags = "CMAKE_" + li + "_FLAGS"; cmProp flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(), - cmOutputConverter::EscapeForCMake(flags).c_str()); + cmOutputConverter::EscapeForCMake(*flags).c_str()); fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" " ${COMPILE_DEFINITIONS}\")\n", @@ -645,7 +645,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmStrCat("CMAKE_", li, "_FLAGS_", cfg); cmProp flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(), - cmOutputConverter::EscapeForCMake(flagsCfg).c_str()); + cmOutputConverter::EscapeForCMake(*flagsCfg).c_str()); } } break; } @@ -678,7 +678,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmProp exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", - cmOutputConverter::EscapeForCMake(exeLinkFlags).c_str()); + cmOutputConverter::EscapeForCMake(*exeLinkFlags).c_str()); } break; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index bdcab3b1676..bad9d914998 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -286,6 +286,10 @@ class cmMakefile * can be used in CMake to refer to lists, directories, etc. */ void AddDefinition(const std::string& name, cm::string_view value); + void AddDefinition(const std::string& name, cmProp value) + { + this->AddDefinition(name, *value); + } /** * Add bool variable definition to the build. */ diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 3a0a5be25c4..4179187170e 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -66,7 +66,10 @@ class cmProp explicit operator bool() const noexcept { return this->Value != nullptr; } operator const std::string&() const noexcept { return this->operator*(); } - operator cm::string_view() const noexcept { return this->operator*(); } + explicit operator cm::string_view() const noexcept + { + return this->operator*(); + } /** * Does the value indicate a true or ON value? diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx index 52b1a4431b8..c2fc45cf3ae 100644 --- a/Source/cmSeparateArgumentsCommand.cxx +++ b/Source/cmSeparateArgumentsCommand.cxx @@ -4,6 +4,7 @@ #include <algorithm> +#include <cm/string_view> #include <cmext/string_view> #include "cmArgumentParser.h" @@ -81,7 +82,7 @@ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, } if (unparsedArguments.empty()) { - status.GetMakefile().AddDefinition(var, {}); + status.GetMakefile().AddDefinition(var, cm::string_view{}); return true; } diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 20061e9af1b..33ab403b7df 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -94,6 +94,13 @@ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep); */ void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut, bool emptyArgs = false); +inline void cmExpandList(cmProp arg, std::vector<std::string>& argsOut, + bool emptyArgs = false) +{ + if (arg) { + cmExpandList(*arg, argsOut, emptyArgs); + } +} /** * Expand out any arguments in the string range [@a first, @a last) that have @@ -115,6 +122,14 @@ void cmExpandLists(InputIt first, InputIt last, */ std::vector<std::string> cmExpandedList(cm::string_view arg, bool emptyArgs = false); +inline std::vector<std::string> cmExpandedList(cmProp arg, + bool emptyArgs = false) +{ + if (!arg) { + return {}; + } + return cmExpandedList(*arg, emptyArgs); +} /** * Same as cmExpandList but a new vector is created containing the expanded @@ -217,6 +232,13 @@ inline bool cmIsInternallyOn(const char* val) } return cmIsInternallyOn(cm::string_view(val)); } +inline bool cmIsInternallyOn(cmProp val) +{ + if (!val) { + return false; + } + return cmIsInternallyOn(*val); +} /** Check for non-empty Property/Variable value. */ inline bool cmNonempty(cm::string_view val) @@ -297,7 +319,7 @@ inline bool cmHasPrefix(cm::string_view str, cmProp prefix) return false; } - return str.compare(0, prefix->size(), prefix) == 0; + return str.compare(0, prefix->size(), *prefix) == 0; } /** Returns true if string @a str starts with string @a prefix. */ @@ -328,7 +350,7 @@ inline bool cmHasSuffix(cm::string_view str, cmProp suffix) } return str.size() >= suffix->size() && - str.compare(str.size() - suffix->size(), suffix->size(), suffix) == 0; + str.compare(str.size() - suffix->size(), suffix->size(), *suffix) == 0; } /** Returns true if string @a str ends with string @a suffix. */ From c2c1c701c7f0768c382c819b6922b134690212ba Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 15 Sep 2021 00:01:22 -0400 Subject: [PATCH 1222/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 94e36e8a671..55a76f959c3 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210914) +set(CMake_VERSION_PATCH 20210915) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1230ceb97e2c7e89682e55770e164176a6719975 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 15 Sep 2021 09:12:01 -0400 Subject: [PATCH 1223/1519] Help: Improve explanation on CMAKE_POLICY_WARNING warnings occur --- Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst index b991db2df31..11dd194c2c2 100644 --- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst +++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst @@ -2,8 +2,9 @@ CMAKE_POLICY_WARNING_CMP<NNNN> ------------------------------ Explicitly enable or disable the warning when CMake Policy ``CMP<NNNN>`` -is not set. This is meaningful only for the few policies that do not -warn by default: +has not been set explicitly by :command:`cmake_policy` or implicitly +by :command:`cmake_minimum_required`. This is meaningful +only for the policies that do not warn by default: * ``CMAKE_POLICY_WARNING_CMP0025`` controls the warning for policy :policy:`CMP0025`. From 3b9e04accb46127b837bc93e90d32060c63349ee Mon Sep 17 00:00:00 2001 From: Cristian Adam <cristian.adam@gmail.com> Date: Tue, 14 Sep 2021 16:49:16 +0200 Subject: [PATCH 1224/1519] PCH: MSVC: Restrict OBJECT library INTERFACE_LINK_LIBRARIES usage The pch object file could cause problems when the reused pch is passed through an OBJECT library, which would use INTERFACE_LINK_LIBRARIES to link the pch object file. Fixes: #22630 --- Source/cmLocalGenerator.cxx | 3 ++- .../PrecompileHeaders/PchLibObjLibExe.cmake | 24 +++++++++++++++++++ .../PrecompileHeaders/RunCMakeTest.cmake | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 8be015e0c1c..5042874c5ef 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2654,7 +2654,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), true); - } else { + } else if (reuseTarget->GetType() == + cmStateEnums::OBJECT_LIBRARY) { target->Target->AppendProperty( "INTERFACE_LINK_LIBRARIES", cmStrCat("$<$<CONFIG:", config, diff --git a/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake b/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake new file mode 100644 index 00000000000..b4fdb712a52 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.16) +project(PchLibObjLibExe CXX) + +foreach(i 1 2 3) + file(WRITE ${CMAKE_BINARY_DIR}/empty${i}.cpp "void nothing${i}() {}\n") +endforeach() + +add_library(base_lib_static STATIC ${CMAKE_BINARY_DIR}/empty1.cpp) +target_precompile_headers(base_lib_static PRIVATE <vector>) + +add_library(object_lib OBJECT ${CMAKE_BINARY_DIR}/empty2.cpp) +target_precompile_headers(object_lib REUSE_FROM base_lib_static) + +add_library(mid_lib_static STATIC ${CMAKE_BINARY_DIR}/empty3.cpp) +target_link_libraries(mid_lib_static PRIVATE object_lib) + +add_executable(exec main.cpp) +target_link_libraries(exec PRIVATE mid_lib_static) +set_target_properties(exec PROPERTIES MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>) + +target_precompile_headers(exec PRIVATE <string>) + +enable_testing() +add_test(NAME exec COMMAND exec) diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index e723e03f1c0..ca5b52e87ce 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -29,3 +29,4 @@ if(RunCMake_GENERATOR MATCHES "Make|Ninja") endif() run_test(PchReuseFromObjLib) run_test(PchIncludedAllLanguages) +run_test(PchLibObjLibExe) From 8d0ae460de553afdf0a2b272a6aca01667c781da Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 14 Sep 2021 18:33:12 +0200 Subject: [PATCH 1225/1519] cmCTestGenericHandler::SetOption accepts cmProp or std::string --- Source/CTest/cmCTestGenericHandler.cxx | 26 ++++++++++++++++++++++++-- Source/CTest/cmCTestGenericHandler.h | 10 ++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index bd330558589..dc7103adee0 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -21,11 +21,12 @@ cmCTestGenericHandler::cmCTestGenericHandler() cmCTestGenericHandler::~cmCTestGenericHandler() = default; +namespace { /* Modify the given `map`, setting key `op` to `value` if `value` * is non-null, otherwise removing key `op` (if it exists). */ -static void SetMapValue(cmCTestGenericHandler::t_StringToString& map, - const std::string& op, const char* value) +void SetMapValue(cmCTestGenericHandler::t_StringToString& map, + const std::string& op, const char* value) { if (!value) { map.erase(op); @@ -34,11 +35,26 @@ static void SetMapValue(cmCTestGenericHandler::t_StringToString& map, map[op] = value; } +void SetMapValue(cmCTestGenericHandler::t_StringToString& map, + const std::string& op, cmProp value) +{ + if (!value) { + map.erase(op); + return; + } + + map[op] = *value; +} +} void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) { SetMapValue(this->Options, op, value); } +void cmCTestGenericHandler::SetOption(const std::string& op, cmProp value) +{ + SetMapValue(this->Options, op, value); +} void cmCTestGenericHandler::SetPersistentOption(const std::string& op, const char* value) @@ -46,6 +62,12 @@ void cmCTestGenericHandler::SetPersistentOption(const std::string& op, this->SetOption(op, value); SetMapValue(this->PersistentOptions, op, value); } +void cmCTestGenericHandler::SetPersistentOption(const std::string& op, + cmProp value) +{ + this->SetOption(op, value); + SetMapValue(this->PersistentOptions, op, value); +} void cmCTestGenericHandler::AddMultiOption(const std::string& op, const std::string& value) diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 0b8b224f0dd..852d4ea4a9c 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -87,7 +87,17 @@ class cmCTestGenericHandler * as a multi-value will return nullptr. */ void SetPersistentOption(const std::string& op, const char* value); + void SetPersistentOption(const std::string& op, const std::string& value) + { + this->SetPersistentOption(op, cmProp(value)); + } + void SetPersistentOption(const std::string& op, cmProp value); void SetOption(const std::string& op, const char* value); + void SetOption(const std::string& op, const std::string& value) + { + this->SetOption(op, cmProp(value)); + } + void SetOption(const std::string& op, cmProp value); cmProp GetOption(const std::string& op); /** From 8f5245168268c99f78074cde24f9dfe75cfaea93 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 14 Sep 2021 18:35:21 +0200 Subject: [PATCH 1226/1519] Use new SetOption signatures --- Source/CTest/cmCTestSubmitCommand.cxx | 8 ++++---- Source/CTest/cmCTestTestCommand.cxx | 20 ++++++++++---------- Source/CTest/cmCTestUpdateCommand.cxx | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 7aeb288435f..68247525c95 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -119,15 +119,15 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() handler->SetHttpHeaders(this->HttpHeaders); } - handler->SetOption("RetryDelay", this->RetryDelay.c_str()); - handler->SetOption("RetryCount", this->RetryCount.c_str()); + handler->SetOption("RetryDelay", this->RetryDelay); + handler->SetOption("RetryCount", this->RetryCount); handler->SetOption("InternalTest", this->InternalTest ? "ON" : "OFF"); handler->SetQuiet(this->Quiet); if (this->CDashUpload) { - handler->SetOption("CDashUploadFile", this->CDashUploadFile.c_str()); - handler->SetOption("CDashUploadType", this->CDashUploadType.c_str()); + handler->SetOption("CDashUploadFile", this->CDashUploadFile); + handler->SetOption("CDashUploadType", this->CDashUploadType); } return handler; } diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 67f49860863..80b8d4fafe9 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -64,13 +64,13 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) { handler->SetOption( "TestsToRunInformation", - cmStrCat(this->Start, ',', this->End, ',', this->Stride).c_str()); + cmStrCat(this->Start, ',', this->End, ',', this->Stride)); } if (!this->Exclude.empty()) { - handler->SetOption("ExcludeRegularExpression", this->Exclude.c_str()); + handler->SetOption("ExcludeRegularExpression", this->Exclude); } if (!this->Include.empty()) { - handler->SetOption("IncludeRegularExpression", this->Include.c_str()); + handler->SetOption("IncludeRegularExpression", this->Include); } if (!this->ExcludeLabel.empty()) { handler->AddMultiOption("ExcludeLabelRegularExpression", @@ -81,30 +81,30 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() } if (!this->ExcludeFixture.empty()) { handler->SetOption("ExcludeFixtureRegularExpression", - this->ExcludeFixture.c_str()); + this->ExcludeFixture); } if (!this->ExcludeFixtureSetup.empty()) { handler->SetOption("ExcludeFixtureSetupRegularExpression", - this->ExcludeFixtureSetup.c_str()); + this->ExcludeFixtureSetup); } if (!this->ExcludeFixtureCleanup.empty()) { handler->SetOption("ExcludeFixtureCleanupRegularExpression", - this->ExcludeFixtureCleanup.c_str()); + this->ExcludeFixtureCleanup); } if (this->StopOnFailure) { handler->SetOption("StopOnFailure", "ON"); } if (!this->ParallelLevel.empty()) { - handler->SetOption("ParallelLevel", this->ParallelLevel.c_str()); + handler->SetOption("ParallelLevel", this->ParallelLevel); } if (!this->Repeat.empty()) { - handler->SetOption("Repeat", this->Repeat.c_str()); + handler->SetOption("Repeat", this->Repeat); } if (!this->ScheduleRandom.empty()) { - handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str()); + handler->SetOption("ScheduleRandom", this->ScheduleRandom); } if (!this->ResourceSpecFile.empty()) { - handler->SetOption("ResourceSpecFile", this->ResourceSpecFile.c_str()); + handler->SetOption("ResourceSpecFile", this->ResourceSpecFile); } if (!this->StopTime.empty()) { this->CTest->SetStopTime(this->StopTime); diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 797cb014ea7..6655bf7245e 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -79,7 +79,7 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() this->SetError("source directory not specified. Please use SOURCE tag"); return nullptr; } - handler->SetOption("SourceDirectory", source_dir.c_str()); + handler->SetOption("SourceDirectory", source_dir); handler->SetQuiet(this->Quiet); return handler; } From 7aeb2622789d04e57051f3592908c5f27d31bb17 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 14 Sep 2021 18:41:44 +0200 Subject: [PATCH 1227/1519] cmCPackGenerator::SetOption accepts cmProp or std::string --- Source/CPack/cmCPackGenerator.cxx | 29 +++++++++++++++++++++++++---- Source/CPack/cmCPackGenerator.h | 16 ++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 4ad25ad66ed..f55b0689544 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -994,17 +994,29 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName) return retval; } -void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, - const char* value) +template <typename ValueType> +void cmCPackGenerator::StoreOptionIfNotSet(const std::string& op, + ValueType value) { cmProp def = this->MakefileMap->GetDefinition(op); if (cmNonempty(def)) { return; } - this->SetOption(op, value); + this->StoreOption(op, value); } -void cmCPackGenerator::SetOption(const std::string& op, const char* value) +void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, + const char* value) +{ + this->StoreOptionIfNotSet(op, value); +} +void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, cmProp value) +{ + this->StoreOptionIfNotSet(op, value); +} + +template <typename ValueType> +void cmCPackGenerator::StoreOption(const std::string& op, ValueType value) { if (!value) { this->MakefileMap->RemoveDefinition(op); @@ -1016,6 +1028,15 @@ void cmCPackGenerator::SetOption(const std::string& op, const char* value) this->MakefileMap->AddDefinition(op, value); } +void cmCPackGenerator::SetOption(const std::string& op, const char* value) +{ + this->StoreOption(op, value); +} +void cmCPackGenerator::SetOption(const std::string& op, cmProp value) +{ + this->StoreOption(op, value); +} + int cmCPackGenerator::DoPackage() { cmCPackLogger(cmCPackLog::LOG_OUTPUT, diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 1968c35585e..e63a830a937 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -85,7 +85,17 @@ class cmCPackGenerator //! Set and get the options void SetOption(const std::string& op, const char* value); + void SetOption(const std::string& op, const std::string& value) + { + this->SetOption(op, cmProp(value)); + } + void SetOption(const std::string& op, cmProp value); void SetOptionIfNotSet(const std::string& op, const char* value); + void SetOptionIfNotSet(const std::string& op, const std::string& value) + { + this->SetOptionIfNotSet(op, cmProp(value)); + } + void SetOptionIfNotSet(const std::string& op, cmProp value); cmProp GetOption(const std::string& op) const; std::vector<std::string> GetOptions() const; bool IsSet(const std::string& name) const; @@ -324,6 +334,12 @@ class cmCPackGenerator bool TraceExpand; cmMakefile* MakefileMap; + +private: + template <typename ValueType> + void StoreOption(const std::string& op, ValueType value); + template <typename ValueType> + void StoreOptionIfNotSet(const std::string& op, ValueType value); }; #define cmCPackTypeMacro(klass, superclass) \ From 7fce78982bbd199e2c34cfec75fca7605f32f43b Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 14 Sep 2021 18:47:30 +0200 Subject: [PATCH 1228/1519] Use new SetOption signatures --- Source/CPack/IFW/cmCPackIFWGenerator.cxx | 2 +- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 16 +++---- Source/CPack/cmCPackBundleGenerator.cxx | 2 +- Source/CPack/cmCPackDebGenerator.cxx | 22 ++++----- Source/CPack/cmCPackDragNDropGenerator.cxx | 6 +-- Source/CPack/cmCPackGenerator.cxx | 45 +++++++++---------- Source/CPack/cmCPackNSISGenerator.cxx | 42 ++++++++--------- Source/CPack/cmCPackNuGetGenerator.cxx | 9 ++-- Source/CPack/cmCPackOSXX11Generator.cxx | 8 ++-- Source/CPack/cmCPackPKGGenerator.cxx | 5 +-- Source/CPack/cmCPackPackageMakerGenerator.cxx | 8 ++-- Source/CPack/cmCPackProductBuildGenerator.cxx | 4 +- Source/CPack/cmCPackRPMGenerator.cxx | 26 +++++------ Source/CPack/cmCPackSTGZGenerator.cxx | 5 +-- 14 files changed, 88 insertions(+), 112 deletions(-) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 4993b40dd21..0e2aec0ab25 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -249,7 +249,7 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix() tmpPref += "packages/" + this->GetRootPackageName() + "/data"; } - this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); + this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref); return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX")->c_str(); } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 7ec2c3f1c45..e127c445528 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -159,7 +159,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() if (!GetOption("CPACK_WIX_PRODUCT_GUID")) { std::string guid = GenerateGUID(); - SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str()); + SetOption("CPACK_WIX_PRODUCT_GUID", guid); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "CPACK_WIX_PRODUCT_GUID implicitly set to " << guid << " . " @@ -168,7 +168,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() if (!GetOption("CPACK_WIX_UPGRADE_GUID")) { std::string guid = GenerateGUID(); - SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str()); + SetOption("CPACK_WIX_UPGRADE_GUID", guid); cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_WIX_UPGRADE_GUID implicitly set to " @@ -185,7 +185,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() if (!GetOption("CPACK_WIX_LICENSE_RTF")) { std::string licenseFilename = this->CPackTopLevel + "/License.rtf"; - SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str()); + SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename); if (!CreateLicenseFile()) { return false; @@ -194,7 +194,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() if (!GetOption("CPACK_PACKAGE_VENDOR")) { std::string defaultVendor = "Humanity"; - SetOption("CPACK_PACKAGE_VENDOR", defaultVendor.c_str()); + SetOption("CPACK_PACKAGE_VENDOR", defaultVendor); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "CPACK_PACKAGE_VENDOR implicitly set to " @@ -208,12 +208,12 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() defaultRef = "WixUI_FeatureTree"; } - SetOption("CPACK_WIX_UI_REF", defaultRef.c_str()); + SetOption("CPACK_WIX_UI_REF", defaultRef); } cmProp packageContact = GetOption("CPACK_PACKAGE_CONTACT"); if (packageContact && !GetOption("CPACK_WIX_PROPERTY_ARPCONTACT")) { - SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact->c_str()); + SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact); } CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions); @@ -336,7 +336,7 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH); CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH); SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", - GetOption("CPACK_PACKAGE_NAME").GetCStr()); + GetOption("CPACK_PACKAGE_NAME")); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); CopyDefinition(includeFile, "CPACK_WIX_UI_REF"); } @@ -1177,7 +1177,7 @@ void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, oss << " xmlns:" << ns.first << "=\"" << cmWIXSourceWriter::EscapeAttributeValue(ns.second) << '"'; } - SetOption("CPACK_WIX_CUSTOM_XMLNS_EXPANDED", oss.str().c_str()); + SetOption("CPACK_WIX_CUSTOM_XMLNS_EXPANDED", oss.str()); } void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index a2e0be491c8..d93ddb84060 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -34,7 +34,7 @@ int cmCPackBundleGenerator::InitializeInternal() "Cannot locate codesign command" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path.c_str()); + this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path); } return this->Superclass::InitializeInternal(); diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 52b94c49ece..91b6c12efc8 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -547,19 +547,17 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, localToplevel += "/" + packageName; /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str()); + this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel); packageFileName += "/" + outputFileName; /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str()); + this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName); /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); + this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName); // Tell CPackDeb.cmake the name of the component GROUP. - this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName.c_str()); + this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName); // Tell CPackDeb.cmake the path where the component is. std::string component_path = cmStrCat('/', packageName); - this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", - component_path.c_str()); + this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path); if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake" << std::endl); @@ -639,19 +637,17 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( } /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str()); + this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel); packageFileName += "/" + outputFileName; /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str()); + this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName); /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); + this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName); if (!compInstDirName.empty()) { // Tell CPackDeb.cmake the path where the component is. std::string component_path = cmStrCat('/', compInstDirName); - this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", - component_path.c_str()); + this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path); } if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index a4e4ab39f9f..36ab4144e5e 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -77,7 +77,7 @@ int cmCPackDragNDropGenerator::InitializeInternal() "Cannot locate hdiutil command" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str()); + this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path); const std::string setfile_path = cmSystemTools::FindProgram("SetFile", paths, false); @@ -86,7 +86,7 @@ int cmCPackDragNDropGenerator::InitializeInternal() "Cannot locate SetFile command" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str()); + this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path); const std::string rez_path = cmSystemTools::FindProgram("Rez", paths, false); if (rez_path.empty()) { @@ -94,7 +94,7 @@ int cmCPackDragNDropGenerator::InitializeInternal() "Cannot locate Rez command" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str()); + this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path); if (this->IsSet("CPACK_DMG_SLA_DIR")) { slaDirectory = this->GetOption("CPACK_DMG_SLA_DIR"); diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index f55b0689544..43efcf4d27a 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -107,21 +107,19 @@ int cmCPackGenerator::PrepareNames() } std::string destFile = pdir; - this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile.c_str()); + this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile); destFile += "/" + outName; std::string outFile = topDirectory + "/" + outName; - this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory.c_str()); - this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory.c_str()); - this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName.c_str()); - this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile.c_str()); - this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - outFile.c_str()); + this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory); + this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory); + this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName); + this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile); + this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME", outFile); this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath()); this->SetOptionIfNotSet( "CPACK_NATIVE_INSTALL_DIRECTORY", - cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str()); - this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY", - tempDirectory.c_str()); + cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath())); + this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY", tempDirectory); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl); @@ -150,7 +148,7 @@ int cmCPackGenerator::PrepareNames() while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) { ostr << cmXMLSafe(line) << std::endl; } - this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); + this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str()); cmProp defFileName = this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE"); if (defFileName && (defFileName == descFileName)) { @@ -503,7 +501,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( if (this->GetOption("CPACK_INSTALL_PREFIX")) { dir += *this->GetOption("CPACK_INSTALL_PREFIX"); } - this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str()); + this->SetOption("CMAKE_INSTALL_PREFIX", dir); cmCPackLogger( cmCPackLog::LOG_DEBUG, "- Using DESTDIR + CPACK_INSTALL_PREFIX... (this->SetOption)" @@ -512,7 +510,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'" << std::endl); } else { - this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str()); + this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory); cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Using non-DESTDIR install... (this->SetOption)" @@ -523,9 +521,9 @@ int cmCPackGenerator::InstallProjectViaInstallScript( } this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR", - tempInstallDirectory.c_str()); + tempInstallDirectory); this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR", - tempInstallDirectory.c_str()); + tempInstallDirectory); bool res = this->MakefileMap->ReadListFile(installScript); if (cmSystemTools::GetErrorOccuredFlag() || !res) { return 0; @@ -676,8 +674,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( this->CMakeProjects.emplace_back(std::move(project)); } } - this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", - absoluteDestFiles.c_str()); + this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", absoluteDestFiles); return 1; } @@ -789,9 +786,8 @@ int cmCPackGenerator::InstallCMakeProject( // I know this is tricky and awkward but it's the price for // CPACK_SET_DESTDIR backward compatibility. if (cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) { - this->SetOption( - "CPACK_INSTALL_PREFIX", - this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX").GetCStr()); + this->SetOption("CPACK_INSTALL_PREFIX", + this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); } std::string dir; if (this->GetOption("CPACK_INSTALL_PREFIX")) { @@ -970,11 +966,10 @@ int cmCPackGenerator::InstallCMakeProject( std::string absoluteDestFilesListComponent = cmStrCat(this->GetOption(absoluteDestFileComponent), ';', *d); this->SetOption(absoluteDestFileComponent, - absoluteDestFilesListComponent.c_str()); + absoluteDestFilesListComponent); } else { - this->SetOption( - absoluteDestFileComponent, - mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES").GetCStr()); + this->SetOption(absoluteDestFileComponent, + mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")); } } } @@ -1212,7 +1207,7 @@ int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf) this->MakefileMap = mf; this->Name = name; // set the running generator name - this->SetOption("CPACK_GENERATOR", this->Name.c_str()); + this->SetOption("CPACK_GENERATOR", this->Name); // Load the project specific config file cmProp config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); if (config) { diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index a3b59ca7887..f151ff1216a 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -85,7 +85,7 @@ int cmCPackNSISGenerator::PackageFiles() } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Files: " << str.str() << std::endl); - this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str().c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str()); std::vector<std::string> dirs; this->GetListOfSubdirectories(this->toplevel.c_str(), dirs); std::ostringstream dstr; @@ -121,7 +121,7 @@ int cmCPackNSISGenerator::PackageFiles() } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Dirs: " << dstr.str() << std::endl); - this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str().c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str()); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " << nsisInFileName << " to " << nsisFileName @@ -151,7 +151,7 @@ int cmCPackNSISGenerator::PackageFiles() std::string installerIconCode = cmStrCat( "!define MUI_HEADERIMAGE_BITMAP \"", installerHeaderImage, "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE", - installerIconCode.c_str()); + installerIconCode); } if (this->IsSet("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP")) { @@ -159,7 +159,7 @@ int cmCPackNSISGenerator::PackageFiles() "!define MUI_WELCOMEFINISHPAGE_BITMAP \"", this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE", - installerBitmapCode.c_str()); + installerBitmapCode); } if (this->IsSet("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP")) { @@ -167,7 +167,7 @@ int cmCPackNSISGenerator::PackageFiles() "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"", this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE", - installerBitmapCode.c_str()); + installerBitmapCode); } if (this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN")) { @@ -176,7 +176,7 @@ int cmCPackNSISGenerator::PackageFiles() this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"), '\\', this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE", - installerRunCode.c_str()); + installerRunCode); } if (this->IsSet("CPACK_NSIS_WELCOME_TITLE")) { @@ -184,7 +184,7 @@ int cmCPackNSISGenerator::PackageFiles() cmStrCat("!define MUI_WELCOMEPAGE_TITLE \"", this->GetOption("CPACK_NSIS_WELCOME_TITLE"), "\""); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE", - welcomeTitleCode.c_str()); + welcomeTitleCode); } if (this->IsSet("CPACK_NSIS_WELCOME_TITLE_3LINES")) { @@ -197,7 +197,7 @@ int cmCPackNSISGenerator::PackageFiles() cmStrCat("!define MUI_FINISHPAGE_TITLE \"", this->GetOption("CPACK_NSIS_FINISH_TITLE"), "\""); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE", - finishTitleCode.c_str()); + finishTitleCode); } if (this->IsSet("CPACK_NSIS_FINISH_TITLE_3LINES")) { @@ -232,15 +232,14 @@ int cmCPackNSISGenerator::PackageFiles() std::string brandingTextCode = cmStrCat("BrandingText /TRIM", brandingTextPosition, " \"", this->GetOption("CPACK_NSIS_BRANDING_TEXT"), "\"\n"); - this->SetOptionIfNotSet("CPACK_NSIS_BRANDING_TEXT_CODE", - brandingTextCode.c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_BRANDING_TEXT_CODE", brandingTextCode); } if (!this->IsSet("CPACK_NSIS_IGNORE_LICENSE_PAGE")) { std::string licenceCode = cmStrCat("!insertmacro MUI_PAGE_LICENSE \"", this->GetOption("CPACK_RESOURCE_FILE_LICENSE"), "\"\n"); - this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode.c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode); } // Setup all of the component sections @@ -335,7 +334,7 @@ int cmCPackNSISGenerator::PackageFiles() componentDescriptions + groupDescriptions + "!insertmacro MUI_FUNCTION_DESCRIPTION_END\n"; this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC", - componentDescriptions.c_str()); + componentDescriptions); } if (anyDownloadedComponents) { @@ -345,18 +344,15 @@ int cmCPackNSISGenerator::PackageFiles() } } - this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", - installTypesCode.c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", installTypesCode); this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS", "!insertmacro MUI_PAGE_COMPONENTS"); this->SetOptionIfNotSet("CPACK_NSIS_FULL_INSTALL", ""); - this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", - componentCode.c_str()); - this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", - sectionList.c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", componentCode); + this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", sectionList); this->SetOptionIfNotSet("CPACK_NSIS_SECTION_SELECTED_VARS", - selectedVarsList.c_str()); - this->SetOption("CPACK_NSIS_DEFINES", defines.c_str()); + selectedVarsList); + this->SetOption("CPACK_NSIS_DEFINES", defines); } this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions); @@ -511,7 +507,7 @@ int cmCPackNSISGenerator::InitializeInternal() cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: CVS " << versionRexCVS.match(1) << std::endl); } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str()); + this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath); this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin"); cmProp cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); @@ -579,8 +575,8 @@ int cmCPackNSISGenerator::InitializeInternal() } this->CreateMenuLinks(str, deleteStr); - this->SetOptionIfNotSet("CPACK_NSIS_CREATE_ICONS", str.str().c_str()); - this->SetOptionIfNotSet("CPACK_NSIS_DELETE_ICONS", deleteStr.str().c_str()); + this->SetOptionIfNotSet("CPACK_NSIS_CREATE_ICONS", str.str()); + this->SetOptionIfNotSet("CPACK_NSIS_DELETE_ICONS", deleteStr.str()); this->SetOptionIfNotSet("CPACK_NSIS_COMPRESSOR", "lzma"); diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx index 9e7f92aed7e..c268f271ab6 100644 --- a/Source/CPack/cmCPackNuGetGenerator.cxx +++ b/Source/CPack/cmCPackNuGetGenerator.cxx @@ -82,10 +82,10 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup) std::back_inserter(components), [](cmCPackComponent const* comp) { return comp->Name; }); this->SetOption("CPACK_NUGET_" + compGUp + "_GROUP_COMPONENTS", - cmJoin(components, ";").c_str()); + cmJoin(components, ";")); } if (!groups.empty()) { - this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";").c_str()); + this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";")); } // Handle Orphan components (components not belonging to any groups) @@ -103,8 +103,7 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup) } } if (!components.empty()) { - this->SetOption("CPACK_NUGET_COMPONENTS", - cmJoin(components, ";").c_str()); + this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";")); } } else { @@ -115,7 +114,7 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup) [](std::pair<std::string, cmCPackComponent> const& comp) { return comp.first; }); - this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";").c_str()); + this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";")); } } diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 262cc6e203e..82917520f41 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -46,8 +46,7 @@ int cmCPackOSXX11Generator::PackageFiles() it != cpackPackageExecutablesVector.end(); ++it) { std::string cpackExecutableName = *it; ++it; - this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME", - cpackExecutableName.c_str()); + this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME", cpackExecutableName); } } @@ -84,7 +83,7 @@ int cmCPackOSXX11Generator::PackageFiles() } std::string destFileName = resourcesDirectory + "/" + iconFileName; this->ConfigureFile(iconFile, destFileName, true); - this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName.c_str()); + this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName); } std::string applicationsLinkName = diskImageDirectory + "/Applications"; @@ -191,8 +190,7 @@ int cmCPackOSXX11Generator::InitializeInternal() "Cannot find hdiutil compiler" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", - pkgPath.c_str()); + this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath); return this->Superclass::InitializeInternal(); } diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index a1eba561cc2..171fbb2db91 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -167,7 +167,7 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile, // Dark Aqua this->CreateBackground("darkAqua", metapackageFile, genName, xout); - this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str()); + this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str()); // Create the distribution.dist file in the metapackage to turn it // into a distribution package. @@ -348,8 +348,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, // Set this so that distribution.dist gets the right name (without // the path). - this->SetOption("CPACK_RESOURCE_FILE_" + uname + "_NOPATH", - (name + ext).c_str()); + this->SetOption("CPACK_RESOURCE_FILE_" + uname + "_NOPATH", (name + ext)); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " << (inFileName ? *inFileName : "(NULL)") diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index 33b601c9006..291561680c4 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -362,7 +362,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal() "Cannot find PackageMaker compiler" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str()); + this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath); } // Get path to the real PackageMaker, not a symlink: @@ -455,8 +455,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal() "Cannot find hdiutil compiler" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", - pkgPath.c_str()); + this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath); return this->Superclass::InitializeInternal(); } @@ -544,8 +543,7 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage( // Create the Info.plist file for this component std::string moduleVersionSuffix = cmStrCat('.', component.Name); - this->SetOption("CPACK_MODULE_VERSION_SUFFIX", - moduleVersionSuffix.c_str()); + this->SetOption("CPACK_MODULE_VERSION_SUFFIX", moduleVersionSuffix); std::string infoFileName = cmStrCat(component.Name, "-Info.plist"); if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) { return false; diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 99c55a00fc9..614b538b263 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -123,7 +123,7 @@ int cmCPackProductBuildGenerator::InitializeInternal() "Cannot find pkgbuild executable" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program.c_str()); + this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program); program = cmSystemTools::FindProgram("productbuild", no_paths, false); if (program.empty()) { @@ -131,7 +131,7 @@ int cmCPackProductBuildGenerator::InitializeInternal() "Cannot find productbuild executable" << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program.c_str()); + this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program); return this->Superclass::InitializeInternal(); } diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 2765c58d3d4..47db5bbe644 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -33,13 +33,13 @@ int cmCPackRPMGenerator::InitializeInternal() if (this->GetOption("CPACK_PACKAGE_NAME")) { std::string packageName = this->GetOption("CPACK_PACKAGE_NAME"); std::replace(packageName.begin(), packageName.end(), ' ', '-'); - this->SetOption("CPACK_PACKAGE_NAME", packageName.c_str()); + this->SetOption("CPACK_PACKAGE_NAME", packageName); } /* same for CPACK_PACKAGE_FILE_NAME */ if (this->GetOption("CPACK_PACKAGE_FILE_NAME")) { std::string packageName = this->GetOption("CPACK_PACKAGE_FILE_NAME"); std::replace(packageName.begin(), packageName.end(), ' ', '-'); - this->SetOption("CPACK_PACKAGE_FILE_NAME", packageName.c_str()); + this->SetOption("CPACK_PACKAGE_FILE_NAME", packageName); } return this->Superclass::InitializeInternal(); } @@ -74,19 +74,17 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel, localToplevel += "/" + packageName; /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str()); + this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel); packageFileName += "/" + outputFileName; /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str()); + this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName); /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); + this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName); // Tell CPackRPM.cmake the name of the component NAME. - this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str()); + this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName); // Tell CPackRPM.cmake the path where the component is. std::string component_path = cmStrCat('/', packageName); - this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", - component_path.c_str()); + this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path); if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake" << std::endl); @@ -365,19 +363,17 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne( localToplevel += "/" + compInstDirName; /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str()); + this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel); packageFileName += "/" + outputFileName; /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str()); + this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName); /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); + this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName); if (!compInstDirName.empty()) { // Tell CPackRPM.cmake the path where the component is. std::string component_path = cmStrCat('/', compInstDirName); - this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", - component_path.c_str()); + this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path); } if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) { diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 7eb8cc31f86..4b34c087519 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -34,7 +34,7 @@ int cmCPackSTGZGenerator::InitializeInternal() "Cannot find template file: " << inFile << std::endl); return 0; } - this->SetOptionIfNotSet("CPACK_STGZ_HEADER_FILE", inFile.c_str()); + this->SetOptionIfNotSet("CPACK_STGZ_HEADER_FILE", inFile); this->SetOptionIfNotSet("CPACK_AT_SIGN", "@"); return this->Superclass::InitializeInternal(); @@ -79,8 +79,7 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os) while (cmSystemTools::GetLineFromStream(ilfs, line)) { licenseText += line + "\n"; } - this->SetOptionIfNotSet("CPACK_RESOURCE_FILE_LICENSE_CONTENT", - licenseText.c_str()); + this->SetOptionIfNotSet("CPACK_RESOURCE_FILE_LICENSE_CONTENT", licenseText); const char headerLengthTag[] = "###CPACK_HEADER_LENGTH###"; From f200f4d5a774ef83a938f0d99f80c2c8c83276b1 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Sep 2021 10:53:45 -0400 Subject: [PATCH 1229/1519] VS: Fix managed C++ project generation for VS 2022 VS 2022 expects managed `.vcxproj` files to have a `ManagedAssembly` element. Fixes: #22583 --- Source/cmVisualStudio10TargetGenerator.cxx | 4 ++++ Tests/VSWindowsFormsResx/CMakeLists.txt | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index bda2f914d21..97cb1bf1421 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -581,6 +581,10 @@ void cmVisualStudio10TargetGenerator::Generate() } if (this->Managed) { + if (this->LocalGenerator->GetVersion() >= + cmGlobalVisualStudioGenerator::VS17) { + e1.Element("ManagedAssembly", "true"); + } std::string outputType; switch (this->GeneratorTarget->GetType()) { case cmStateEnums::OBJECT_LIBRARY: diff --git a/Tests/VSWindowsFormsResx/CMakeLists.txt b/Tests/VSWindowsFormsResx/CMakeLists.txt index 43c4833830e..b9b216351eb 100644 --- a/Tests/VSWindowsFormsResx/CMakeLists.txt +++ b/Tests/VSWindowsFormsResx/CMakeLists.txt @@ -33,6 +33,12 @@ set(TARGET_RESX set(TARGET_LIBRARIES ${SYSLIBS}) add_executable(${PROJECT_NAME} ${TARGET_SRC} ${TARGET_H} ${TARGET_RESX}) +if(NOT CMAKE_GENERATOR MATCHES "Visual Studio 1[0-6]") + # VS 17 2022 and above require a global mark on managed assemblies. + # CMake adds this automatically when using COMMON_LANGUAGE_RUNTIME, + # but this test covers direct use of /clr. + set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_ManagedAssembly "true") +endif() # Note: The property VS_GLOBAL_KEYWORD must be set. set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_KEYWORD "ManagedCProj") From b6ac10394b88b476f069ba75426c1556ab8bfe00 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Sep 2021 12:24:07 -0400 Subject: [PATCH 1230/1519] VS: Update Visual Studio 17 2022 generator for Preview 4 --- Help/generator/Visual Studio 17 2022.rst | 4 ++-- Help/release/3.21.rst | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index 8b97b9f52af..708909ef91d 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -7,7 +7,7 @@ Generates Visual Studio 17 (VS 2022) project files. .. warning:: - This is experimental and based on "Visual Studio 2022 Preview 3.1". + This is experimental and based on "Visual Studio 2022 Preview 4". As of this version of CMake, VS 2022 has not been released. Project Types @@ -51,7 +51,7 @@ name (architecture). For example: Toolset Selection ^^^^^^^^^^^^^^^^^ -The ``v143`` toolset that comes with VS 17 2022 Preview 3.1 is selected by +The ``v143`` toolset that comes with VS 17 2022 Preview 4 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index a5125ac0c50..5d8c200277e 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -27,7 +27,7 @@ Generators ---------- * The :generator:`Visual Studio 17 2022` generator was added. This is - experimental and based on "Visual Studio 2022 Preview 3.1" because this + experimental and based on "Visual Studio 2022 Preview 4" because this version of VS has not been released. * The :ref:`Makefile Generators` and the :generator:`Ninja` generator @@ -313,3 +313,9 @@ Changes made since CMake 3.21.0 include the following. * The :generator:`Visual Studio 17 2022` generator is now based on "Visual Studio 2022 Preview 3.1". Previously it was based on "Preview 2". + +3.21.3 +------ + +* The :generator:`Visual Studio 17 2022` generator is now based on + "Visual Studio 2022 Preview 4". Previously it was based on "Preview 3.1". From 63b5a6869e1793e4aeb815f220dd41419344c802 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Sep 2021 14:56:14 -0400 Subject: [PATCH 1231/1519] cmCurl: Adopt helper to fix file:// URLs Migrate and generalize the helper added by commit e63dcb1378 (Encoding: Use encoding libcurl expects with file: urls., 2014-11-05, v3.2.0-rc1~420^2). --- Source/cmCurl.cxx | 35 +++++++++++++++++++++++++++++++++++ Source/cmCurl.h | 1 + Source/cmFileCommand.cxx | 37 ++----------------------------------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 233790e54df..7a6568e06e4 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -9,6 +9,14 @@ #endif #include "cmStringAlgorithms.h" +#if defined(_WIN32) +# include <vector> + +# include <windows.h> + +# include "cmsys/Encoding.hxx" +#endif + // curl versions before 7.21.5 did not provide this error code #if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505 # define CURLE_NOT_BUILT_IN 4 @@ -95,3 +103,30 @@ std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, } return e; } + +std::string cmCurlFixFileURL(std::string url) +{ + if (!cmHasLiteralPrefix(url, "file://")) { + return url; + } + +#if defined(_WIN32) + // libcurl doesn't support file:// urls for unicode filenames on Windows. + // Convert string from UTF-8 to ACP if this is a file:// URL. + std::wstring wurl = cmsys::Encoding::ToWide(url); + if (!wurl.empty()) { + int mblen = + WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, NULL, 0, NULL, NULL); + if (mblen > 0) { + std::vector<char> chars(mblen); + mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, &chars[0], + mblen, NULL, NULL); + if (mblen > 0) { + url = &chars[0]; + } + } + } +#endif + + return url; +} diff --git a/Source/cmCurl.h b/Source/cmCurl.h index fb716f80c99..9c1e33778e0 100644 --- a/Source/cmCurl.h +++ b/Source/cmCurl.h @@ -11,3 +11,4 @@ std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr); std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, const std::string& netrc_file); +std::string cmCurlFixFileURL(std::string url); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 2730a076e4b..1223d2a10b7 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -65,37 +65,8 @@ # include "cmFileLockResult.h" #endif -#if defined(_WIN32) -# include <windows.h> -#endif - namespace { -#if defined(_WIN32) -// libcurl doesn't support file:// urls for unicode filenames on Windows. -// Convert string from UTF-8 to ACP if this is a file:// URL. -std::string fix_file_url_windows(const std::string& url) -{ - std::string ret = url; - if (strncmp(url.c_str(), "file://", 7) == 0) { - std::wstring wurl = cmsys::Encoding::ToWide(url); - if (!wurl.empty()) { - int mblen = - WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, NULL, 0, NULL, NULL); - if (mblen > 0) { - std::vector<char> chars(mblen); - mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, &chars[0], - mblen, NULL, NULL); - if (mblen > 0) { - ret = &chars[0]; - } - } - } - } - return ret; -} -#endif - bool HandleWriteImpl(std::vector<std::string> const& args, bool append, cmExecutionStatus& status) { @@ -1976,9 +1947,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } } -# if defined(_WIN32) - url = fix_file_url_windows(url); -# endif + url = cmCurlFixFileURL(url); ::CURL* curl; ::curl_global_init(CURL_GLOBAL_DEFAULT); @@ -2292,9 +2261,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, unsigned long file_size = cmsys::SystemTools::FileLength(filename); -# if defined(_WIN32) - url = fix_file_url_windows(url); -# endif + url = cmCurlFixFileURL(url); ::CURL* curl; ::curl_global_init(CURL_GLOBAL_DEFAULT); From 3cfd89add5551242e3d1b69aadd2c5733db4b96f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Sep 2021 15:00:25 -0400 Subject: [PATCH 1232/1519] cmCurl: Fix file:// URLs with spaces for curl 7.78+ Since curl 7.78, URLs with spaces that are not encoded as `%20` or `+` are now correctly rejected with `CURLUE_MALFORMED_INPUT`. However, CMake has long accepted `file://` URLs with spaces in the path due to curl 7.77 and below accidentally allowing them. Preserve this by explicitly encoding spaces in such URLs before handing them to curl. See also upstream curl commit `b67d3ba73` (curl_url_set: reject spaces in URLs w/o CURLU_ALLOW_SPACE, 2021-05-31, curl-7_78_0~133). --- Source/cmCurl.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 7a6568e06e4..fa001d28250 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -5,9 +5,9 @@ #if !defined(CMAKE_USE_SYSTEM_CURL) && !defined(_WIN32) && \ !defined(__APPLE__) && !defined(CURL_CA_BUNDLE) && !defined(CURL_CA_PATH) # define CMAKE_FIND_CAFILE -# include "cmSystemTools.h" #endif #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #if defined(_WIN32) # include <vector> @@ -110,6 +110,11 @@ std::string cmCurlFixFileURL(std::string url) return url; } + // libcurl 7.77 and below accidentally allowed spaces in URLs in some cases. + // One such case was file:// URLs, which CMake has long accepted as a result. + // Explicitly encode spaces for a URL. + cmSystemTools::ReplaceString(url, " ", "%20"); + #if defined(_WIN32) // libcurl doesn't support file:// urls for unicode filenames on Windows. // Convert string from UTF-8 to ACP if this is a file:// URL. From a8ae9c7055fc5d7175a3082640733745248b4274 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Sep 2021 09:38:01 -0400 Subject: [PATCH 1233/1519] curl: Update script to get curl 7.79.0 --- Utilities/Scripts/update-curl.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash index 34ff4de5705..abd54f6f72d 100755 --- a/Utilities/Scripts/update-curl.bash +++ b/Utilities/Scripts/update-curl.bash @@ -8,7 +8,7 @@ readonly name="curl" readonly ownership="Curl Upstream <curl-library@cool.haxx.se>" readonly subtree="Utilities/cmcurl" readonly repo="https://github.com/curl/curl.git" -readonly tag="curl-7_77_0" +readonly tag="curl-7_79_0" readonly shortlog=false readonly paths=" CMake/* From 386467c9dc939cd20711c451dd7d60341fd0e802 Mon Sep 17 00:00:00 2001 From: Curl Upstream <curl-library@cool.haxx.se> Date: Tue, 14 Sep 2021 09:02:52 +0200 Subject: [PATCH 1234/1519] curl 2021-09-14 (8e82f2a0) Code extracted from: https://github.com/curl/curl.git at commit 8e82f2a04a238c54ba91e553e9a8452e6d405965 (curl-7_79_0). --- CMake/CurlTests.c | 75 +-- CMake/OtherTests.cmake | 170 +++--- CMake/Platforms/WindowsCache.cmake | 14 - CMakeLists.txt | 181 +++---- include/curl/curl.h | 19 +- include/curl/curlver.h | 6 +- include/curl/urlapi.h | 3 +- lib/altsvc.c | 12 +- lib/asyn-ares.c | 185 ++++++- lib/asyn-thread.c | 1 - lib/c-hyper.c | 257 +++++++-- lib/c-hyper.h | 1 + lib/conncache.c | 12 +- lib/connect.c | 84 +-- lib/cookie.c | 87 ++-- lib/cookie.h | 1 + lib/curl_addrinfo.c | 6 - lib/curl_config.h.cmake | 139 ++--- lib/curl_endian.c | 42 -- lib/curl_gssapi.c | 4 +- lib/curl_multibyte.c | 50 +- lib/curl_ntlm_core.c | 16 +- lib/curl_ntlm_wb.c | 9 +- lib/curl_range.c | 8 +- lib/curl_sasl.c | 10 +- lib/curl_setup.h | 91 ++-- lib/curl_setup_once.h | 20 - lib/dict.c | 4 +- lib/doh.c | 50 +- lib/doh.h | 2 +- lib/easy.c | 21 +- lib/formdata.c | 16 +- lib/ftp.c | 121 +++-- lib/hostasyn.c | 1 - lib/hostcheck.c | 12 +- lib/hostip.c | 185 +++++-- lib/hostip.h | 4 +- lib/hostip4.c | 3 +- lib/hostip6.c | 31 +- lib/hostsyn.c | 3 +- lib/hsts.c | 9 +- lib/http.c | 279 +++++----- lib/http.h | 3 + lib/http2.c | 195 ++++--- lib/http2.h | 5 +- lib/http_aws_sigv4.c | 12 +- lib/http_digest.c | 3 +- lib/http_negotiate.c | 6 +- lib/http_ntlm.c | 6 +- lib/http_proxy.c | 130 +++-- lib/http_proxy.h | 7 +- lib/imap.c | 55 +- lib/inet_ntop.c | 2 +- lib/krb5.c | 23 +- lib/ldap.c | 20 +- lib/md4.c | 6 +- lib/md5.c | 9 +- lib/mprintf.c | 4 +- lib/mqtt.c | 258 +++++++-- lib/multi.c | 152 ++++-- lib/multihandle.h | 3 + lib/netrc.c | 25 +- lib/non-ascii.c | 16 +- lib/openldap.c | 9 +- lib/pingpong.c | 4 +- lib/pop3.c | 57 +- lib/progress.c | 7 +- lib/quic.h | 2 +- lib/rand.c | 4 +- lib/rtsp.c | 6 +- lib/rtsp.h | 2 +- lib/select.h | 4 + lib/sendf.c | 26 +- lib/setopt.c | 14 +- lib/sha256.c | 17 +- lib/smb.c | 6 +- lib/smtp.c | 22 +- lib/socketpair.c | 36 +- lib/socks.c | 72 +-- lib/socks_gssapi.c | 6 +- lib/socks_sspi.c | 6 +- lib/strdup.c | 28 +- lib/strdup.h | 5 +- lib/strerror.c | 5 +- lib/telnet.c | 33 +- lib/tftp.c | 40 +- lib/transfer.c | 66 +-- lib/url.c | 149 +++--- lib/urlapi.c | 27 +- lib/urldata.h | 26 +- lib/vauth/digest_sspi.c | 12 +- lib/vauth/krb5_gssapi.c | 84 ++- lib/vauth/krb5_sspi.c | 82 ++- lib/vauth/ntlm.c | 8 +- lib/vauth/ntlm_sspi.c | 7 +- lib/vauth/spnego_gssapi.c | 5 +- lib/vauth/spnego_sspi.c | 5 +- lib/vauth/vauth.h | 1 + lib/version.c | 14 +- lib/vquic/ngtcp2.c | 205 +++----- lib/vquic/ngtcp2.h | 8 - lib/vquic/quiche.c | 32 +- lib/vssh/libssh.c | 65 ++- lib/vssh/libssh2.c | 132 ++--- lib/vssh/ssh.h | 2 +- lib/vssh/wolfssh.c | 42 +- lib/vtls/bearssl.c | 142 +++-- lib/vtls/gskit.c | 39 +- lib/vtls/gtls.c | 129 +++-- lib/vtls/mbedtls.c | 202 ++++--- lib/vtls/mbedtls_threadlock.c | 27 +- lib/vtls/mesalink.c | 18 +- lib/vtls/nss.c | 92 ++-- lib/vtls/openssl.c | 228 ++++---- lib/vtls/rustls.c | 66 ++- lib/vtls/schannel.c | 809 +++++++++++++++-------------- lib/vtls/schannel_verify.c | 10 +- lib/vtls/sectransp.c | 202 ++++--- lib/vtls/vtls.c | 65 ++- lib/vtls/vtls.h | 7 +- lib/vtls/wolfssl.c | 73 +-- lib/warnless.c | 106 +--- lib/x509asn1.c | 60 +-- lib/x509asn1.h | 5 +- 124 files changed, 3818 insertions(+), 3029 deletions(-) diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c index 2fcce1bb383..e418146b484 100644 --- a/CMake/CurlTests.c +++ b/CMake/CurlTests.c @@ -71,21 +71,15 @@ main () } #endif -/* tests for gethostbyaddr_r or gethostbyname_r */ -#if defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ - defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \ - defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \ - defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \ +/* tests for gethostbyname_r */ +#if defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \ defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) # define _REENTRANT /* no idea whether _REENTRANT is always set, just invent a new flag */ # define TEST_GETHOSTBYFOO_REENTRANT #endif -#if defined(HAVE_GETHOSTBYADDR_R_5) || \ - defined(HAVE_GETHOSTBYADDR_R_7) || \ - defined(HAVE_GETHOSTBYADDR_R_8) || \ - defined(HAVE_GETHOSTBYNAME_R_3) || \ +#if defined(HAVE_GETHOSTBYNAME_R_3) || \ defined(HAVE_GETHOSTBYNAME_R_5) || \ defined(HAVE_GETHOSTBYNAME_R_6) || \ defined(TEST_GETHOSTBYFOO_REENTRANT) @@ -98,18 +92,10 @@ int main(void) int type = 0; struct hostent h; int rc = 0; -#if defined(HAVE_GETHOSTBYADDR_R_5) || \ - defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ - \ - defined(HAVE_GETHOSTBYNAME_R_3) || \ +#if defined(HAVE_GETHOSTBYNAME_R_3) || \ defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) struct hostent_data hdata; -#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ - defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \ - defined(HAVE_GETHOSTBYADDR_R_8) || \ - defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \ - \ - defined(HAVE_GETHOSTBYNAME_R_5) || \ +#elif defined(HAVE_GETHOSTBYNAME_R_5) || \ defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ defined(HAVE_GETHOSTBYNAME_R_6) || \ defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) @@ -118,24 +104,6 @@ int main(void) struct hostent *hp; #endif -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif - -#if defined(HAVE_GETHOSTBYADDR_R_5) || \ - defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) - rc = gethostbyaddr_r(address, length, type, &h, &hdata); - (void)rc; -#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ - defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) - hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop); - (void)hp; -#elif defined(HAVE_GETHOSTBYADDR_R_8) || \ - defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) - rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop); - (void)rc; -#endif - #if defined(HAVE_GETHOSTBYNAME_R_3) || \ defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) rc = gethostbyname_r(address, &h, &hdata); @@ -214,37 +182,6 @@ if (sizeof (bool *) ) #include <float.h> int main() { return 0; } #endif -#ifdef HAVE_INET_NTOA_R_DECL -#include <arpa/inet.h> - -typedef void (*func_type)(); - -int main() -{ -#ifndef inet_ntoa_r - func_type func; - func = (func_type)inet_ntoa_r; - (void)func; -#endif - return 0; -} -#endif -#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT -#define _REENTRANT -#include <arpa/inet.h> - -typedef void (*func_type)(); - -int main() -{ -#ifndef inet_ntoa_r - func_type func; - func = (func_type)&inet_ntoa_r; - (void)func; -#endif - return 0; -} -#endif #ifdef HAVE_GETADDRINFO #include <netdb.h> #include <sys/types.h> @@ -361,7 +298,7 @@ main () /* IoctlSocket source code */ long flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) + if(0 != IoctlSocket(0, FIONBIO, &flags)) return 1; ; return 0; diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake index 80c0b72752e..5cddf4afa9b 100644 --- a/CMake/OtherTests.cmake +++ b/CMake/OtherTests.cmake @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. +# Copyright (C) 1998 - 2021, 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 @@ -47,6 +47,40 @@ endif() set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +function(curl_cv_func_recv_run_test recv_retv recv_arg1 recv_arg2 recv_arg3 recv_arg4) + unset(curl_cv_func_recv_test CACHE) + check_c_source_compiles(" + ${_source_epilogue} + #ifdef WINSOCK_API_LINKAGE + WINSOCK_API_LINKAGE + #endif + extern ${recv_retv} ${signature_call_conv} + recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4}); + int main(void) { + ${recv_arg1} s=0; + ${recv_arg2} buf=0; + ${recv_arg3} len=0; + ${recv_arg4} flags=0; + ${recv_retv} res = recv(s, buf, len, flags); + (void) res; + return 0; + }" + curl_cv_func_recv_test) + message(STATUS + "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})") + if(curl_cv_func_recv_test) + set(curl_cv_func_recv_args + "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}" PARENT_SCOPE) + set(RECV_TYPE_ARG1 "${recv_arg1}" PARENT_SCOPE) + set(RECV_TYPE_ARG2 "${recv_arg2}" PARENT_SCOPE) + set(RECV_TYPE_ARG3 "${recv_arg3}" PARENT_SCOPE) + set(RECV_TYPE_ARG4 "${recv_arg4}" PARENT_SCOPE) + set(RECV_TYPE_RETV "${recv_retv}" PARENT_SCOPE) + set(HAVE_RECV 1 PARENT_SCOPE) + set(curl_cv_func_recv_done 1 PARENT_SCOPE) + endif() +endfunction() + check_c_source_compiles("${_source_epilogue} int main(void) { recv(0, 0, 0, 0); @@ -54,43 +88,16 @@ int main(void) { }" curl_cv_recv) if(curl_cv_recv) if(NOT DEFINED curl_cv_func_recv_args OR curl_cv_func_recv_args STREQUAL "unknown") + if(APPLE) + curl_cv_func_recv_run_test("ssize_t" "int" "void *" "size_t" "int") + endif() foreach(recv_retv "int" "ssize_t" ) foreach(recv_arg1 "SOCKET" "int" ) foreach(recv_arg2 "char *" "void *" ) foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int") foreach(recv_arg4 "int" "unsigned int") if(NOT curl_cv_func_recv_done) - unset(curl_cv_func_recv_test CACHE) - check_c_source_compiles(" - ${_source_epilogue} - #ifdef WINSOCK_API_LINKAGE - WINSOCK_API_LINKAGE - #endif - extern ${recv_retv} ${signature_call_conv} - recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4}); - int main(void) { - ${recv_arg1} s=0; - ${recv_arg2} buf=0; - ${recv_arg3} len=0; - ${recv_arg4} flags=0; - ${recv_retv} res = recv(s, buf, len, flags); - (void) res; - return 0; - }" - curl_cv_func_recv_test) - message(STATUS - "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})") - if(curl_cv_func_recv_test) - set(curl_cv_func_recv_args - "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}") - set(RECV_TYPE_ARG1 "${recv_arg1}") - set(RECV_TYPE_ARG2 "${recv_arg2}") - set(RECV_TYPE_ARG3 "${recv_arg3}") - set(RECV_TYPE_ARG4 "${recv_arg4}") - set(RECV_TYPE_RETV "${recv_retv}") - set(HAVE_RECV 1) - set(curl_cv_func_recv_done 1) - endif() + curl_cv_func_recv_run_test(${recv_retv} ${recv_arg1} ${recv_arg2} ${recv_arg3} ${recv_arg4}) endif() endforeach() endforeach() @@ -114,6 +121,42 @@ endif() set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv") set(HAVE_RECV 1) +function(curl_cv_func_send_run_test send_retv send_arg1 send_arg2 send_arg3 send_arg4) + unset(curl_cv_func_send_test CACHE) + check_c_source_compiles(" + ${_source_epilogue} + #ifdef WINSOCK_API_LINKAGE + WINSOCK_API_LINKAGE + #endif + extern ${send_retv} ${signature_call_conv} + send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4}); + int main(void) { + ${send_arg1} s=0; + ${send_arg2} buf=0; + ${send_arg3} len=0; + ${send_arg4} flags=0; + ${send_retv} res = send(s, buf, len, flags); + (void) res; + return 0; + }" + curl_cv_func_send_test) + message(STATUS + "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})") + if(curl_cv_func_send_test) + string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}") + string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}") + set(curl_cv_func_send_args + "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}" PARENT_SCOPE) + set(SEND_TYPE_ARG1 "${send_arg1}" PARENT_SCOPE) + set(SEND_TYPE_ARG2 "${send_arg2}" PARENT_SCOPE) + set(SEND_TYPE_ARG3 "${send_arg3}" PARENT_SCOPE) + set(SEND_TYPE_ARG4 "${send_arg4}" PARENT_SCOPE) + set(SEND_TYPE_RETV "${send_retv}" PARENT_SCOPE) + set(HAVE_SEND 1 PARENT_SCOPE) + set(curl_cv_func_send_done 1 PARENT_SCOPE) + endif() +endfunction() + check_c_source_compiles("${_source_epilogue} int main(void) { send(0, 0, 0, 0); @@ -121,45 +164,16 @@ int main(void) { }" curl_cv_send) if(curl_cv_send) if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown") + if(APPLE) + curl_cv_func_send_run_test("ssize_t" "int" "const void *" "size_t" "int") + endif() foreach(send_retv "int" "ssize_t" ) foreach(send_arg1 "SOCKET" "int" "ssize_t" ) foreach(send_arg2 "const char *" "const void *" "void *" "char *") foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int") foreach(send_arg4 "int" "unsigned int") if(NOT curl_cv_func_send_done) - unset(curl_cv_func_send_test CACHE) - check_c_source_compiles(" - ${_source_epilogue} - #ifdef WINSOCK_API_LINKAGE - WINSOCK_API_LINKAGE - #endif - extern ${send_retv} ${signature_call_conv} - send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4}); - int main(void) { - ${send_arg1} s=0; - ${send_arg2} buf=0; - ${send_arg3} len=0; - ${send_arg4} flags=0; - ${send_retv} res = send(s, buf, len, flags); - (void) res; - return 0; - }" - curl_cv_func_send_test) - message(STATUS - "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})") - if(curl_cv_func_send_test) - string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}") - string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}") - set(curl_cv_func_send_args - "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}") - set(SEND_TYPE_ARG1 "${send_arg1}") - set(SEND_TYPE_ARG2 "${send_arg2}") - set(SEND_TYPE_ARG3 "${send_arg3}") - set(SEND_TYPE_ARG4 "${send_arg4}") - set(SEND_TYPE_RETV "${send_retv}") - set(HAVE_SEND 1) - set(curl_cv_func_send_done 1) - endif() + curl_cv_func_send_run_test("${send_retv}" "${send_arg1}" "${send_arg2}" "${send_arg3}" "${send_arg4}") endif() endforeach() endforeach() @@ -206,28 +220,6 @@ int main(void) { return 0; }" HAVE_STRUCT_TIMEVAL) -set(HAVE_SIG_ATOMIC_T 1) -set(CMAKE_REQUIRED_FLAGS) -if(HAVE_SIGNAL_H) - set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H") - set(CMAKE_EXTRA_INCLUDE_FILES "signal.h") -endif() -check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T) -if(HAVE_SIZEOF_SIG_ATOMIC_T) - check_c_source_compiles(" - #ifdef HAVE_SIGNAL_H - # include <signal.h> - #endif - int main(void) { - static volatile sig_atomic_t dummy = 0; - (void)dummy; - return 0; - }" HAVE_SIG_ATOMIC_T_NOT_VOLATILE) - if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE) - set(HAVE_SIG_ATOMIC_T_VOLATILE 1) - endif() -endif() - if(HAVE_WINDOWS_H) set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h) else() @@ -245,6 +237,9 @@ endif() unset(CMAKE_TRY_COMPILE_TARGET_TYPE) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # only try this on non-macOS + # if not cross-compilation... include(CheckCSourceRuns) set(CMAKE_REQUIRED_FLAGS "") @@ -287,5 +282,6 @@ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) } return 0; }" HAVE_POLL_FINE) + endif() endif() diff --git a/CMake/Platforms/WindowsCache.cmake b/CMake/Platforms/WindowsCache.cmake index 33c735a225f..fb803f8a6a0 100644 --- a/CMake/Platforms/WindowsCache.cmake +++ b/CMake/Platforms/WindowsCache.cmake @@ -46,7 +46,6 @@ if(NOT UNIX) set(HAVE_PROCESS_H 1) set(HAVE_PWD_H 0) set(HAVE_SETJMP_H 1) - set(HAVE_SGTTY_H 0) set(HAVE_SIGNAL_H 1) set(HAVE_SOCKIO_H 0) set(HAVE_STDINT_H 0) @@ -84,12 +83,8 @@ if(NOT UNIX) set(HAVE_STRCASECMP 0) set(HAVE_STRICMP 1) set(HAVE_STRCMPI 1) - set(HAVE_GETHOSTBYADDR 1) set(HAVE_GETTIMEOFDAY 0) set(HAVE_INET_ADDR 1) - set(HAVE_INET_NTOA 1) - set(HAVE_INET_NTOA_R 0) - set(HAVE_PERROR 1) set(HAVE_CLOSESOCKET 1) set(HAVE_SETVBUF 0) set(HAVE_SIGSETJMP 0) @@ -103,17 +98,10 @@ if(NOT UNIX) set(HAVE_RAND_STATUS 0) set(HAVE_GMTIME_R 0) set(HAVE_LOCALTIME_R 0) - set(HAVE_GETHOSTBYADDR_R 0) set(HAVE_GETHOSTBYNAME_R 0) set(HAVE_SIGNAL_FUNC 1) set(HAVE_SIGNAL_MACRO 0) - set(HAVE_GETHOSTBYADDR_R_5 0) - set(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0) - set(HAVE_GETHOSTBYADDR_R_7 0) - set(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0) - set(HAVE_GETHOSTBYADDR_R_8 0) - set(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0) set(HAVE_GETHOSTBYNAME_R_3 0) set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0) set(HAVE_GETHOSTBYNAME_R_5 0) @@ -124,8 +112,6 @@ if(NOT UNIX) set(TIME_WITH_SYS_TIME 0) set(HAVE_O_NONBLOCK 0) set(HAVE_IN_ADDR_T 0) - set(HAVE_INET_NTOA_R_DECL 0) - set(HAVE_INET_NTOA_R_DECL_REENTRANT 0) if(ENABLE_IPV6) set(HAVE_GETADDRINFO 1) else() diff --git a/CMakeLists.txt b/CMakeLists.txt index f5f560292f8..d8084de8e91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,43 +156,77 @@ endif() include(CurlSymbolHiding) -option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF) -mark_as_advanced(HTTP_ONLY) -option(CURL_DISABLE_FTP "disables FTP" OFF) -mark_as_advanced(CURL_DISABLE_FTP) -option(CURL_DISABLE_LDAP "disables LDAP" OFF) -mark_as_advanced(CURL_DISABLE_LDAP) -option(CURL_DISABLE_TELNET "disables Telnet" OFF) -mark_as_advanced(CURL_DISABLE_TELNET) +option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON) +mark_as_advanced(CURL_ENABLE_EXPORT_TARGET) + +option(CURL_DISABLE_ALTSVC "disables alt-svc support" OFF) +mark_as_advanced(CURL_DISABLE_ALTSVC) +option(CURL_DISABLE_COOKIES "disables cookies support" OFF) +mark_as_advanced(CURL_DISABLE_COOKIES) +option(CURL_DISABLE_CRYPTO_AUTH "disables cryptographic authentication" OFF) +mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH) option(CURL_DISABLE_DICT "disables DICT" OFF) mark_as_advanced(CURL_DISABLE_DICT) +option(CURL_DISABLE_DOH "disables DNS-over-HTTPS" OFF) +mark_as_advanced(CURL_DISABLE_DOH) option(CURL_DISABLE_FILE "disables FILE" OFF) mark_as_advanced(CURL_DISABLE_FILE) -option(CURL_DISABLE_TFTP "disables TFTP" OFF) -mark_as_advanced(CURL_DISABLE_TFTP) +option(CURL_DISABLE_FTP "disables FTP" OFF) +mark_as_advanced(CURL_DISABLE_FTP) +option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing options to curl_easy_setopt" OFF) +mark_as_advanced(CURL_DISABLE_GETOPTIONS) +option(CURL_DISABLE_GOPHER "disables Gopher" OFF) +mark_as_advanced(CURL_DISABLE_GOPHER) +option(CURL_DISABLE_HSTS "disables HSTS support" OFF) +mark_as_advanced(CURL_DISABLE_HSTS) option(CURL_DISABLE_HTTP "disables HTTP" OFF) mark_as_advanced(CURL_DISABLE_HTTP) - -option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF) +option(CURL_DISABLE_HTTP_AUTH "disables all HTTP authentication methods" OFF) +mark_as_advanced(CURL_DISABLE_HTTP_AUTH) +option(CURL_DISABLE_IMAP "disables IMAP" OFF) +mark_as_advanced(CURL_DISABLE_IMAP) +option(CURL_DISABLE_LDAP "disables LDAP" OFF) +mark_as_advanced(CURL_DISABLE_LDAP) +option(CURL_DISABLE_LDAPS "disables LDAPS" OFF) mark_as_advanced(CURL_DISABLE_LDAPS) - -option(CURL_DISABLE_RTSP "to disable RTSP" OFF) -mark_as_advanced(CURL_DISABLE_RTSP) -option(CURL_DISABLE_PROXY "to disable proxy" OFF) -mark_as_advanced(CURL_DISABLE_PROXY) -option(CURL_DISABLE_POP3 "to disable POP3" OFF) +option(CURL_DISABLE_LIBCURL_OPTION "disables --libcurl option from the curl tool" OFF) +mark_as_advanced(CURL_DISABLE_LIBCURL_OPTION) +option(CURL_DISABLE_MIME "disables MIME support" OFF) +mark_as_advanced(CURL_DISABLE_MIME) +option(CURL_DISABLE_MQTT "disables MQTT" OFF) +mark_as_advanced(CURL_DISABLE_MQTT) +option(CURL_DISABLE_NETRC "disables netrc parser" OFF) +mark_as_advanced(CURL_DISABLE_NETRC) +option(CURL_DISABLE_NTLM "disables NTLM support" OFF) +mark_as_advanced(CURL_DISABLE_NTLM) +option(CURL_DISABLE_PARSEDATE "disables date parsing" OFF) +mark_as_advanced(CURL_DISABLE_PARSEDATE) +option(CURL_DISABLE_POP3 "disables POP3" OFF) mark_as_advanced(CURL_DISABLE_POP3) -option(CURL_DISABLE_IMAP "to disable IMAP" OFF) -mark_as_advanced(CURL_DISABLE_IMAP) -option(CURL_DISABLE_SMTP "to disable SMTP" OFF) +option(CURL_DISABLE_PROGRESS_METER "disables built-in progress meter" OFF) +mark_as_advanced(CURL_DISABLE_PROGRESS_METER) +option(CURL_DISABLE_PROXY "disables proxy support" OFF) +mark_as_advanced(CURL_DISABLE_PROXY) +option(CURL_DISABLE_RTSP "disables RTSP" OFF) +mark_as_advanced(CURL_DISABLE_RTSP) +option(CURL_DISABLE_SHUFFLE_DNS "disables shuffle DNS feature" OFF) +mark_as_advanced(CURL_DISABLE_SHUFFLE_DNS) +option(CURL_DISABLE_SMB "disables SMB" OFF) +mark_as_advanced(CURL_DISABLE_SMB) +option(CURL_DISABLE_SMTP "disables SMTP" OFF) mark_as_advanced(CURL_DISABLE_SMTP) -option(CURL_DISABLE_GOPHER "to disable Gopher" OFF) -mark_as_advanced(CURL_DISABLE_GOPHER) -option(CURL_DISABLE_MQTT "to disable MQTT" OFF) -mark_as_advanced(CURL_DISABLE_MQTT) +option(CURL_DISABLE_SOCKETPAIR "disables use of socketpair for curl_multi_poll" OFF) +mark_as_advanced(CURL_DISABLE_SOCKETPAIR) +option(CURL_DISABLE_TELNET "disables Telnet" OFF) +mark_as_advanced(CURL_DISABLE_TELNET) +option(CURL_DISABLE_TFTP "disables TFTP" OFF) +mark_as_advanced(CURL_DISABLE_TFTP) +option(CURL_DISABLE_VERBOSE_STRINGS "disables verbose strings" OFF) +mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) -option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON) -mark_as_advanced(CURL_ENABLE_EXPORT_TARGET) +# Corresponds to HTTP_ONLY in lib/curl_setup.h +option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF) +mark_as_advanced(HTTP_ONLY) if(HTTP_ONLY) set(CURL_DISABLE_DICT ON) @@ -211,16 +245,6 @@ if(HTTP_ONLY) set(CURL_DISABLE_TFTP ON) endif() -option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF) -mark_as_advanced(CURL_DISABLE_ALTSVC) -option(CURL_DISABLE_HSTS "to disable HSTS support" OFF) -mark_as_advanced(CURL_DISABLE_HSTS) -option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) -mark_as_advanced(CURL_DISABLE_COOKIES) -option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) -mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH) -option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF) -mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON) mark_as_advanced(ENABLE_IPV6) if(ENABLE_IPV6 AND NOT WIN32) @@ -370,28 +394,29 @@ if(CMAKE_USE_DARWINSSL) message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.") endif() -if(CMAKE_USE_SECTRANSP) +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") if(NOT COREFOUNDATION_FRAMEWORK) message(FATAL_ERROR "CoreFoundation framework not found") endif() - find_library(SECURITY_FRAMEWORK "Security") - if(NOT SECURITY_FRAMEWORK) - message(FATAL_ERROR "Security framework not found") - endif() - - set(SSL_ENABLED ON) - set(USE_SECTRANSP ON) - list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}") -endif() - -if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration") if(NOT SYSTEMCONFIGURATION_FRAMEWORK) message(FATAL_ERROR "SystemConfiguration framework not found") endif() - list(APPEND CURL_LIBS "${SYSTEMCONFIGURATION_FRAMEWORK}") + + list(APPEND CURL_LIBS "-framework CoreFoundation" "-framework SystemConfiguration") + + if(CMAKE_USE_SECTRANSP) + find_library(SECURITY_FRAMEWORK "Security") + if(NOT SECURITY_FRAMEWORK) + message(FATAL_ERROR "Security framework not found") + endif() + + set(SSL_ENABLED ON) + set(USE_SECTRANSP ON) + list(APPEND CURL_LIBS "-framework Security") + endif() endif() if(CMAKE_USE_OPENSSL) @@ -713,15 +738,6 @@ if(CMAKE_USE_LIBSSH2) set(HAVE_LIBSSH2_H ON) set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h") set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H") - - # now check for specific libssh2 symbols as they were added in different versions - set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h") - check_function_exists(libssh2_version HAVE_LIBSSH2_VERSION) - check_function_exists(libssh2_init HAVE_LIBSSH2_INIT) - check_function_exists(libssh2_exit HAVE_LIBSSH2_EXIT) - check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64) - check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE) - set(CMAKE_EXTRA_INCLUDE_FILES "") unset(CMAKE_REQUIRED_LIBRARIES) endif() endif() @@ -804,7 +820,11 @@ endif() option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON) if(ENABLE_UNIX_SOCKETS) include(CheckStructHasMember) - check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) + if(WIN32) + set(USE_UNIX_SOCKETS ON) + else() + check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) + endif() else() unset(USE_UNIX_SOCKETS CACHE) endif() @@ -915,8 +935,6 @@ check_include_file_concat("alloca.h" HAVE_ALLOCA_H) check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H) check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H) check_include_file_concat("assert.h" HAVE_ASSERT_H) -check_include_file_concat("crypto.h" HAVE_CRYPTO_H) -check_include_file_concat("err.h" HAVE_ERR_H) check_include_file_concat("errno.h" HAVE_ERRNO_H) check_include_file_concat("fcntl.h" HAVE_FCNTL_H) check_include_file_concat("idn2.h" HAVE_IDN2_H) @@ -934,9 +952,7 @@ check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H) check_include_file_concat("pem.h" HAVE_PEM_H) check_include_file_concat("poll.h" HAVE_POLL_H) check_include_file_concat("pwd.h" HAVE_PWD_H) -check_include_file_concat("rsa.h" HAVE_RSA_H) check_include_file_concat("setjmp.h" HAVE_SETJMP_H) -check_include_file_concat("sgtty.h" HAVE_SGTTY_H) check_include_file_concat("signal.h" HAVE_SIGNAL_H) check_include_file_concat("ssl.h" HAVE_SSL_H) check_include_file_concat("stdbool.h" HAVE_STDBOOL_H) @@ -1017,12 +1033,8 @@ endif() check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID) check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES) -check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR) -check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R) check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY) check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR) -check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA) -check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R) check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET) check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP) check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R) @@ -1047,11 +1059,8 @@ check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL) check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64) check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R) check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT) -check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) -check_symbol_exists(fork "${CURL_INCLUDES}" HAVE_FORK) check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO) check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO) -check_symbol_exists(freeifaddrs "${CURL_INCLUDES}" HAVE_FREEIFADDRS) check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE) check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE) check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME) @@ -1118,12 +1127,6 @@ foreach(CURL_TEST HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID TIME_WITH_SYS_TIME HAVE_O_NONBLOCK - HAVE_GETHOSTBYADDR_R_5 - HAVE_GETHOSTBYADDR_R_7 - HAVE_GETHOSTBYADDR_R_8 - HAVE_GETHOSTBYADDR_R_5_REENTRANT - HAVE_GETHOSTBYADDR_R_7_REENTRANT - HAVE_GETHOSTBYADDR_R_8_REENTRANT HAVE_GETHOSTBYNAME_R_3 HAVE_GETHOSTBYNAME_R_5 HAVE_GETHOSTBYNAME_R_6 @@ -1133,8 +1136,6 @@ foreach(CURL_TEST HAVE_IN_ADDR_T HAVE_BOOL_T STDC_HEADERS - HAVE_INET_NTOA_R_DECL - HAVE_INET_NTOA_R_DECL_REENTRANT HAVE_GETADDRINFO HAVE_FILE_OFFSET_BITS HAVE_VARIADIC_MACROS_C99 @@ -1166,13 +1167,9 @@ endforeach() # Check for reentrant foreach(CURL_TEST - HAVE_GETHOSTBYADDR_R_5 - HAVE_GETHOSTBYADDR_R_7 - HAVE_GETHOSTBYADDR_R_8 HAVE_GETHOSTBYNAME_R_3 HAVE_GETHOSTBYNAME_R_5 - HAVE_GETHOSTBYNAME_R_6 - HAVE_INET_NTOA_R_DECL_REENTRANT) + HAVE_GETHOSTBYNAME_R_6) if(NOT ${CURL_TEST}) if(${CURL_TEST}_REENTRANT) set(NEED_REENTRANT 1) @@ -1182,9 +1179,6 @@ endforeach() if(NEED_REENTRANT) foreach(CURL_TEST - HAVE_GETHOSTBYADDR_R_5 - HAVE_GETHOSTBYADDR_R_7 - HAVE_GETHOSTBYADDR_R_8 HAVE_GETHOSTBYNAME_R_3 HAVE_GETHOSTBYNAME_R_5 HAVE_GETHOSTBYNAME_R_6) @@ -1195,11 +1189,6 @@ if(NEED_REENTRANT) endforeach() endif() -if(HAVE_INET_NTOA_R_DECL_REENTRANT) - set(HAVE_INET_NTOA_R_DECL 1) - set(NEED_REENTRANT 1) -endif() - # Check clock_gettime(CLOCK_MONOTONIC, x) support curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC) @@ -1380,8 +1369,8 @@ endmacro() # NTLM support requires crypto function adaptions from various SSL libs # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS -if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_MBEDTLS OR - USE_DARWINSSL OR USE_WIN32_CRYPTO)) +if(NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND + (USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO)) set(use_curl_ntlm_core ON) endif() @@ -1409,10 +1398,10 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) # NTLM support requires crypto function adaptions from various SSL libs # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS -_add_if("NTLM" NOT CURL_DISABLE_CRYPTO_AUTH AND +_add_if("NTLM" NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND (use_curl_ntlm_core OR USE_WINDOWS_SSPI)) # TODO missing option (autoconf: --enable-ntlm-wb) -_add_if("NTLM_WB" NOT CURL_DISABLE_CRYPTO_AUTH AND +_add_if("NTLM_WB" NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND (use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) # TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP diff --git a/include/curl/curl.h b/include/curl/curl.h index 97de8c88ae0..835c3d871bc 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -25,9 +25,6 @@ /* * If you have libcurl problems, all docs and details are found here: * https://curl.se/libcurl/ - * - * curl-library mailing list subscription and unsubscription web interface: - * https://cool.haxx.se/mailman/listinfo/curl-library/ */ #ifdef CURL_NO_OLDIES @@ -74,8 +71,9 @@ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ - defined(__CYGWIN__) || defined(AMIGA) || \ - (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) + defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ + defined(__VXWORKS__) #include <sys/select.h> #endif @@ -541,7 +539,7 @@ typedef enum { CURLE_OBSOLETE46, /* 46 - NOT USED */ CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ - CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */ CURLE_OBSOLETE50, /* 50 - NOT USED */ CURLE_OBSOLETE51, /* 51 - NOT USED */ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ @@ -636,6 +634,9 @@ typedef enum { /* The following were added in 7.21.5, April 2011 */ #define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION +/* Added for 7.78.0 */ +#define CURLE_TELNET_OPTION_SYNTAX CURLE_SETOPT_OPTION_SYNTAX + /* The following were added in 7.17.1 */ /* These are scheduled to disappear by 2009 */ #define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION @@ -2084,13 +2085,13 @@ typedef enum { /* Parameters for V4 signature */ CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), - /* Same as CURLOPT_SSL_VERIFYPEER but for DOH (DNS-over-HTTPS) servers. */ + /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */ CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), - /* Same as CURLOPT_SSL_VERIFYHOST but for DOH (DNS-over-HTTPS) servers. */ + /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */ CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), - /* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */ + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */ CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), /* The CA certificates as "blob" used to validate the peer certificate diff --git a/include/curl/curlver.h b/include/curl/curlver.h index 75fa93ca752..3e2de3e925d 100644 --- a/include/curl/curlver.h +++ b/include/curl/curlver.h @@ -30,12 +30,12 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.77.0-DEV" +#define LIBCURL_VERSION "7.79.0-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 77 +#define LIBCURL_VERSION_MINOR 79 #define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier @@ -57,7 +57,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 0x074d00 +#define LIBCURL_VERSION_NUM 0x074f00 /* * This is the date and time when the full source package was created. The diff --git a/include/curl/urlapi.h b/include/curl/urlapi.h index 7343cb659ec..1d70880117e 100644 --- a/include/curl/urlapi.h +++ b/include/curl/urlapi.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2018 - 2021, 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 @@ -79,6 +79,7 @@ typedef enum { #define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ #define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the scheme is unknown. */ +#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */ typedef struct Curl_URL CURLU; diff --git a/lib/altsvc.c b/lib/altsvc.c index 4ab77fdfc89..36acc3a5ef7 100644 --- a/lib/altsvc.c +++ b/lib/altsvc.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2019 - 2021, 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 @@ -460,7 +460,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, (void)data; #endif if(result) { - infof(data, "Excessive alt-svc header, ignoring...\n"); + infof(data, "Excessive alt-svc header, ignoring."); return CURLE_OK; } @@ -496,7 +496,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, p++; len = p - hostp; if(!len || (len >= MAX_ALTSVC_HOSTLEN)) { - infof(data, "Excessive alt-svc host name, ignoring...\n"); + infof(data, "Excessive alt-svc host name, ignoring."); dstalpnid = ALPN_none; } else { @@ -513,7 +513,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, /* a port number */ unsigned long port = strtoul(++p, &end_ptr, 10); if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') { - infof(data, "Unknown alt-svc port number, ignoring...\n"); + infof(data, "Unknown alt-svc port number, ignoring."); dstalpnid = ALPN_none; } p = end_ptr; @@ -579,12 +579,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, as->expires = maxage + time(NULL); as->persist = persist; Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); - infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, + infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport, Curl_alpnid2str(dstalpnid)); } } else { - infof(data, "Unknown alt-svc protocol \"%s\", skipping...\n", + infof(data, "Unknown alt-svc protocol \"%s\", skipping.", alpnbuf); } } diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 7827847350c..763a4aaa0ed 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -59,7 +59,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "multiif.h" #include "inet_pton.h" @@ -80,13 +79,33 @@ #define HAVE_CARES_CALLBACK_TIMEOUTS 1 #endif +#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 +#define HAVE_CARES_SET_LOCAL 1 +#endif + +#if ARES_VERSION >= 0x010b00 +#define HAVE_CARES_PORTS_CSV 1 +#endif + +#if ARES_VERSION >= 0x011000 +/* 1.16.0 or later has ares_getaddrinfo */ +#define HAVE_CARES_GETADDRINFO 1 +#endif + /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" struct thread_data { - int num_pending; /* number of ares_gethostbyname() requests */ + int num_pending; /* number of outstanding c-ares requests */ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ int last_status; @@ -206,7 +225,8 @@ static void destroy_async_data(struct Curl_async *async); */ void Curl_resolver_cancel(struct Curl_easy *data) { - if(data && data->state.async.resolver) + DEBUGASSERT(data); + if(data->state.async.resolver) ares_cancel((ares_channel)data->state.async.resolver); destroy_async_data(&data->state.async); } @@ -489,21 +509,37 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, return result; } +#ifndef HAVE_CARES_GETADDRINFO + /* Connects results to the list */ static void compound_results(struct thread_data *res, struct Curl_addrinfo *ai) { - struct Curl_addrinfo *ai_tail; if(!ai) return; - ai_tail = ai; - while(ai_tail->ai_next) - ai_tail = ai_tail->ai_next; +#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ + if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) { + /* We have results already, put the new IPv6 entries at the head of the + list. */ + struct Curl_addrinfo *temp_ai_tail = res->temp_ai; + + while(temp_ai_tail->ai_next) + temp_ai_tail = temp_ai_tail->ai_next; - /* Add the new results to the list of old results. */ - ai_tail->ai_next = res->temp_ai; - res->temp_ai = ai; + temp_ai_tail->ai_next = ai; + } + else +#endif /* CURLRES_IPV6 */ + { + /* Add the new results to the list of old results. */ + struct Curl_addrinfo *ai_tail = ai; + while(ai_tail->ai_next) + ai_tail = ai_tail->ai_next; + + ai_tail->ai_next = res->temp_ai; + res->temp_ai = ai; + } } /* @@ -605,7 +641,98 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ } } } +#else +/* c-ares 1.16.0 or later */ + +/* + * ares2addr() converts an address list provided by c-ares to an internal + * libcurl compatible list + */ +static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node) +{ + /* traverse the ares_addrinfo_node list */ + struct ares_addrinfo_node *ai; + struct Curl_addrinfo *cafirst = NULL; + struct Curl_addrinfo *calast = NULL; + int error = 0; + + 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. */ + if(ai->ai_family == AF_INET) + ss_size = sizeof(struct sockaddr_in); +#ifdef ENABLE_IPV6 + else if(ai->ai_family == AF_INET6) + ss_size = sizeof(struct sockaddr_in6); +#endif + else + continue; + + /* ignore elements without required address info */ + if(!ai->ai_addr || !(ai->ai_addrlen > 0)) + continue; + + /* ignore elements with bogus address size */ + if((size_t)ai->ai_addrlen < ss_size) + continue; + + ca = malloc(sizeof(struct Curl_addrinfo) + ss_size); + if(!ca) { + error = EAI_MEMORY; + break; + } + + /* 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; + ca->ai_socktype = ai->ai_socktype; + ca->ai_protocol = ai->ai_protocol; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_addr = NULL; + ca->ai_canonname = NULL; + ca->ai_next = NULL; + + ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); + memcpy(ca->ai_addr, ai->ai_addr, ss_size); + + /* if the return list is empty, this becomes the first element */ + if(!cafirst) + cafirst = ca; + + /* add this element last in the return list */ + if(calast) + calast->ai_next = ca; + calast = ca; + } + + /* if we failed, destroy the Curl_addrinfo list */ + if(error) { + Curl_freeaddrinfo(cafirst); + cafirst = NULL; + } + + return cafirst; +} + +static void addrinfo_cb(void *arg, int status, int timeouts, + struct ares_addrinfo *result) +{ + struct Curl_easy *data = (struct Curl_easy *)arg; + struct thread_data *res = data->state.async.tdata; + (void)timeouts; + if(ARES_SUCCESS == status) { + res->temp_ai = ares2addr(result->nodes); + res->last_status = CURL_ASYNC_SUCCESS; + ares_freeaddrinfo(result); + } + res->num_pending--; +} +#endif /* * Curl_resolver_getaddrinfo() - when using ares * @@ -643,8 +770,28 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, /* initial status - failed */ res->last_status = ARES_ENOTFOUND; -#if ARES_VERSION >= 0x010601 - /* IPv6 supported by c-ares since 1.6.1 */ +#ifdef HAVE_CARES_GETADDRINFO + { + struct ares_addrinfo_hints hints; + char service[12]; + int pf = PF_INET; + memset(&hints, 0, sizeof(hints)); +#ifdef CURLRES_IPV6 + if(Curl_ipv6works(data)) + /* The stack seems to be IPv6-enabled */ + pf = PF_UNSPEC; +#endif /* CURLRES_IPV6 */ + hints.ai_family = pf; + hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)? + SOCK_STREAM : SOCK_DGRAM; + msnprintf(service, sizeof(service), "%d", port); + res->num_pending = 1; + ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname, + service, &hints, addrinfo_cb, data); + } +#else + +#ifdef HAVE_CARES_IPV6 if(Curl_ipv6works(data)) { /* The stack seems to be IPv6-enabled */ res->num_pending = 2; @@ -656,7 +803,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, PF_INET6, query_completed_cb, data); } else -#endif /* ARES_VERSION >= 0x010601 */ +#endif { res->num_pending = 1; @@ -665,7 +812,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, hostname, PF_INET, query_completed_cb, data); } - +#endif *waitp = 1; /* expect asynchronous response */ } return NULL; /* no struct yet */ @@ -686,8 +833,8 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, if(!(servers && servers[0])) return CURLE_OK; -#if (ARES_VERSION >= 0x010704) -#if (ARES_VERSION >= 0x010b00) +#ifdef HAVE_CARES_SERVERS_CSV +#ifdef HAVE_CARES_PORTS_CSV ares_result = ares_set_servers_ports_csv(data->state.async.resolver, servers); #else @@ -717,7 +864,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, CURLcode Curl_set_dns_interface(struct Curl_easy *data, const char *interf) { -#if (ARES_VERSION >= 0x010704) +#ifdef HAVE_CARES_LOCAL_DEV if(!interf) interf = ""; @@ -734,7 +881,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data, CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, const char *local_ip4) { -#if (ARES_VERSION >= 0x010704) +#ifdef HAVE_CARES_SET_LOCAL struct in_addr a4; if((!local_ip4) || (local_ip4[0] == 0)) { @@ -760,7 +907,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, const char *local_ip6) { -#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) +#if defined(HAVE_CARES_SET_LOCAL) && defined(ENABLE_IPV6) unsigned char a6[INET6_ADDRSTRLEN]; if((!local_ip6) || (local_ip6[0] == 0)) { diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 36f68cb493f..149172ad3d3 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -68,7 +68,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "multiif.h" #include "inet_ntop.h" diff --git a/lib/c-hyper.c b/lib/c-hyper.c index 81f589eb9e6..26635cdc1e1 100644 --- a/lib/c-hyper.c +++ b/lib/c-hyper.c @@ -124,6 +124,17 @@ static int hyper_each_header(void *userdata, size_t len; char *headp; CURLcode result; + int writetype; + + if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) { + failf(data, "Too long response header"); + data->state.hresult = CURLE_OUT_OF_MEMORY; + return HYPER_ITER_BREAK; + } + + if(!data->req.bytecount) + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + Curl_dyn_reset(&data->state.headerb); if(name_len) { if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n", @@ -145,7 +156,10 @@ static int hyper_each_header(void *userdata, Curl_debug(data, CURLINFO_HEADER_IN, headp, len); - result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, len); + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + result = Curl_client_write(data, writetype, headp, len); if(result) { data->state.hresult = CURLE_ABORTED_BY_CALLBACK; return HYPER_ITER_BREAK; @@ -162,13 +176,43 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) size_t len = hyper_buf_len(chunk); struct Curl_easy *data = (struct Curl_easy *)userdata; struct SingleRequest *k = &data->req; - CURLcode result; + CURLcode result = CURLE_OK; if(0 == k->bodywrites++) { bool done = FALSE; - result = Curl_http_firstwrite(data, data->conn, &done); +#if defined(USE_NTLM) + struct connectdata *conn = data->conn; + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->http_ntlm_state == NTLMSTATE_TYPE2)) || + ((data->req.httpcode == 407) && + (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) { + infof(data, "Connection closed while negotiating NTLM"); + data->state.authproblem = TRUE; + Curl_safefree(data->req.newurl); + } +#endif + if(data->state.expect100header) { + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + if(data->req.httpcode < 400) { + k->exp100 = EXP100_SEND_DATA; + if(data->hyp.exp100_waker) { + hyper_waker_wake(data->hyp.exp100_waker); + data->hyp.exp100_waker = NULL; + } + } + else { /* >= 4xx */ + k->exp100 = EXP100_FAILED; + } + } + if(data->state.hconnect && (data->req.httpcode/100 != 2)) { + done = TRUE; + result = CURLE_OK; + } + else + result = Curl_http_firstwrite(data, data->conn, &done); if(result || done) { - infof(data, "Return early from hyper_body_chunk\n"); + infof(data, "Return early from hyper_body_chunk"); data->state.hresult = result; return HYPER_ITER_BREAK; } @@ -207,11 +251,15 @@ static CURLcode status_line(struct Curl_easy *data, CURLcode result; size_t len; const char *vstr; + int writetype; vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" : (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0"); conn->httpversion = http_version == HYPER_HTTP_VERSION_1_1 ? 11 : (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10); + if(http_version == HYPER_HTTP_VERSION_1_0) + data->state.httpwant = CURL_HTTP_VERSION_1_0; + data->req.httpcode = http_status; result = Curl_http_statusline(data, conn); @@ -229,7 +277,10 @@ static CURLcode status_line(struct Curl_easy *data, len = Curl_dyn_len(&data->state.headerb); Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - result = Curl_client_write(data, CLIENTWRITE_HEADER, + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + result = Curl_client_write(data, writetype, Curl_dyn_ptr(&data->state.headerb), len); if(result) { data->state.hresult = CURLE_ABORTED_BY_CALLBACK; @@ -270,8 +321,25 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, const uint8_t *reasonp; size_t reason_len; CURLcode result = CURLE_OK; + struct SingleRequest *k = &data->req; (void)conn; + if(k->exp100 > EXP100_SEND_DATA) { + struct curltime now = Curl_now(); + timediff_t ms = Curl_timediff(now, k->start100); + if(ms >= data->set.expect_100_timeout) { + /* we've waited long enough, continue anyway */ + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + infof(data, "Done waiting for 100-continue"); + if(data->hyp.exp100_waker) { + hyper_waker_wake(data->hyp.exp100_waker); + data->hyp.exp100_waker = NULL; + } + } + } + if(select_res & CURL_CSELECT_IN) { if(h->read_waker) hyper_waker_wake(h->read_waker); @@ -305,19 +373,22 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, hyper_task_free(task); if(t == HYPER_TASK_ERROR) { - hyper_code errnum = hyper_error_code(hypererr); - if(errnum == HYPERE_ABORTED_BY_CALLBACK) { + if(data->state.hresult) { /* override Hyper's view, might not even be an error */ result = data->state.hresult; - infof(data, "hyperstream is done (by early callback)\n"); + infof(data, "hyperstream is done (by early callback)"); } else { uint8_t errbuf[256]; size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf)); hyper_code code = hyper_error_code(hypererr); failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); - if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount) + if(code == HYPERE_ABORTED_BY_CALLBACK) + result = CURLE_OK; + else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount) result = CURLE_GOT_NOTHING; + else if(code == HYPERE_INVALID_PEER_MESSAGE) + result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */ else result = CURLE_RECV_ERROR; } @@ -328,10 +399,15 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, else if(h->endtask == task) { /* end of transfer */ *done = TRUE; - infof(data, "hyperstream is done!\n"); + infof(data, "hyperstream is done!"); + if(!k->bodywrites) { + /* hyper doesn't always call the body write callback */ + bool stilldone; + result = Curl_http_firstwrite(data, data->conn, &stilldone); + } break; } - else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) { + else if(t != HYPER_TASK_RESPONSE) { *didwhat = KEEP_RECV; break; } @@ -472,7 +548,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen, (uint8_t *)v, vlen)) { - failf(data, "hyper_headers_add host"); + failf(data, "hyper refused to add header '%s'", line); return CURLE_OUT_OF_MEMORY; } if(data->set.verbose) { @@ -485,7 +561,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, free(ptr); } else - Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen); + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen); } numh++; n += linelen; @@ -526,12 +602,32 @@ static int uploadpostfields(void *userdata, hyper_context *ctx, { struct Curl_easy *data = (struct Curl_easy *)userdata; (void)ctx; + if(data->req.exp100 > EXP100_SEND_DATA) { + if(data->req.exp100 == EXP100_FAILED) + return HYPER_POLL_ERROR; + + /* still waiting confirmation */ + if(data->hyp.exp100_waker) + hyper_waker_free(data->hyp.exp100_waker); + data->hyp.exp100_waker = hyper_context_waker(ctx); + return HYPER_POLL_PENDING; + } if(data->req.upload_done) *chunk = NULL; /* nothing more to deliver */ else { /* send everything off in a single go */ - *chunk = hyper_buf_copy(data->set.postfields, - (size_t)data->req.p.http->postsize); + hyper_buf *copy = hyper_buf_copy(data->set.postfields, + (size_t)data->req.p.http->postsize); + if(copy) + *chunk = copy; + else { + data->state.hresult = CURLE_OUT_OF_MEMORY; + return HYPER_POLL_ERROR; + } + /* increasing the writebytecount here is a little premature but we + don't know exactly when the body is sent*/ + data->req.writebytecount += (size_t)data->req.p.http->postsize; + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); data->req.upload_done = TRUE; } return HYPER_POLL_READY; @@ -542,16 +638,41 @@ static int uploadstreamed(void *userdata, hyper_context *ctx, { size_t fillcount; struct Curl_easy *data = (struct Curl_easy *)userdata; - CURLcode result = - Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); + CURLcode result; (void)ctx; - if(result) + + if(data->req.exp100 > EXP100_SEND_DATA) { + if(data->req.exp100 == EXP100_FAILED) + return HYPER_POLL_ERROR; + + /* still waiting confirmation */ + if(data->hyp.exp100_waker) + hyper_waker_free(data->hyp.exp100_waker); + data->hyp.exp100_waker = hyper_context_waker(ctx); + return HYPER_POLL_PENDING; + } + + result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); + if(result) { + data->state.hresult = result; return HYPER_POLL_ERROR; + } if(!fillcount) /* done! */ *chunk = NULL; - else - *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount); + else { + hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount); + if(copy) + *chunk = copy; + else { + data->state.hresult = CURLE_OUT_OF_MEMORY; + return HYPER_POLL_ERROR; + } + /* increasing the writebytecount here is a little premature but we + don't know exactly when the body is sent*/ + data->req.writebytecount += fillcount; + Curl_pgrsSetUploadCounter(data, fillcount); + } return HYPER_POLL_READY; } @@ -566,6 +687,7 @@ static CURLcode bodysend(struct Curl_easy *data, hyper_request *hyperreq, Curl_HttpReq httpreq) { + struct HTTP *http = data->req.p.http; CURLcode result = CURLE_OK; struct dynbuf req; if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) @@ -598,6 +720,7 @@ static CURLcode bodysend(struct Curl_easy *data, result = CURLE_OUT_OF_MEMORY; } } + http->sending = HTTPSEND_BODY; return result; } @@ -616,6 +739,48 @@ static CURLcode cookies(struct Curl_easy *data, return result; } +/* called on 1xx responses */ +static void http1xx_cb(void *arg, struct hyper_response *resp) +{ + struct Curl_easy *data = (struct Curl_easy *)arg; + hyper_headers *headers = NULL; + CURLcode result = CURLE_OK; + uint16_t http_status; + int http_version; + const uint8_t *reasonp; + size_t reason_len; + + infof(data, "Got HTTP 1xx informational"); + + http_status = hyper_response_status(resp); + http_version = hyper_response_version(resp); + reasonp = hyper_response_reason_phrase(resp); + reason_len = hyper_response_reason_phrase_len(resp); + + result = status_line(data, data->conn, + http_status, http_version, reasonp, reason_len); + if(!result) { + headers = hyper_response_headers(resp); + if(!headers) { + failf(data, "hyperstream: couldn't get 1xx response headers"); + result = CURLE_RECV_ERROR; + } + } + data->state.hresult = result; + + if(!result) { + /* the headers are already received */ + hyper_headers_foreach(headers, hyper_each_header, data); + /* this callback also sets data->state.hresult on error */ + + if(empty_header(data)) + result = CURLE_OUT_OF_MEMORY; + } + + if(data->state.hresult) + infof(data, "ERROR in 1xx, bail out!"); +} + /* * Curl_http() gets called from the generic multi_do() function when a HTTP * request is to be performed. This creates and sends a properly constructed @@ -633,20 +798,20 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) hyper_request *req = NULL; hyper_headers *headers = NULL; hyper_task *handshake = NULL; - hyper_error *hypererr = NULL; CURLcode result; const char *p_accept; /* Accept: string */ const char *method; Curl_HttpReq httpreq; bool h2 = FALSE; const char *te = NULL; /* transfer-encoding */ + hyper_code rc; /* Always consider the DO phase done after this function call, even if there may be parts of the request that is not yet sent, since we can deal with the rest of the request in the PERFORM phase. */ *done = TRUE; - infof(data, "Time for the Hyper dance\n"); + infof(data, "Time for the Hyper dance"); memset(h, 0, sizeof(struct hyptransfer)); result = Curl_http_host(data, conn); @@ -743,7 +908,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } - if(data->state.httpwant == CURL_HTTP_VERSION_1_0) { + if(!Curl_use_http_1_1plus(data, conn)) { if(HYPERE_OK != hyper_request_set_version(req, HYPER_HTTP_VERSION_1_0)) { failf(data, "error setting HTTP version"); @@ -766,6 +931,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) goto error; } + rc = hyper_request_on_informational(req, http1xx_cb, data); + if(rc) + return CURLE_OUT_OF_MEMORY; + result = Curl_http_body(data, conn, httpreq, &te); if(result) return result; @@ -830,6 +999,15 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) else Curl_safefree(data->state.aptr.accept_encoding); +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ + result = Curl_transferencode(data); + if(result) + return result; + if(Curl_hyper_header(data, headers, data->state.aptr.te)) + goto error; +#endif + result = cookies(data, conn, headers); if(result) return result; @@ -862,25 +1040,21 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) hyper_clientconn_free(client); - do { - task = hyper_executor_poll(h->exec); - if(task) { - bool error = hyper_task_type(task) == HYPER_TASK_ERROR; - if(error) - hypererr = hyper_task_value(task); - hyper_task_free(task); - if(error) - goto error; - } - } while(task); - if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) { /* HTTP GET/HEAD download */ Curl_pgrsSetUploadSize(data, 0); /* nothing */ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); } conn->datastream = Curl_hyper_stream; - + if(data->state.expect100header) + /* Timeout count starts now since with Hyper we don't know exactly when + the full request has been sent. */ + data->req.start100 = Curl_now(); + + /* clear userpwd and proxyuserpwd to avoid re-using old credentials + * from re-used connections */ + Curl_safefree(data->state.aptr.userpwd); + Curl_safefree(data->state.aptr.proxyuserpwd); return CURLE_OK; error: @@ -893,13 +1067,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(handshake) hyper_task_free(handshake); - if(hypererr) { - uint8_t errbuf[256]; - size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf)); - hyper_code code = hyper_error_code(hypererr); - failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); - hyper_error_free(hypererr); - } return CURLE_OUT_OF_MEMORY; } @@ -918,6 +1085,10 @@ void Curl_hyper_done(struct Curl_easy *data) hyper_waker_free(h->write_waker); h->write_waker = NULL; } + if(h->exp100_waker) { + hyper_waker_free(h->exp100_waker); + h->exp100_waker = NULL; + } } #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */ diff --git a/lib/c-hyper.h b/lib/c-hyper.h index d60ed78d1df..d63defeffec 100644 --- a/lib/c-hyper.h +++ b/lib/c-hyper.h @@ -33,6 +33,7 @@ struct hyptransfer { hyper_waker *read_waker; const hyper_executor *exec; hyper_task *endtask; + hyper_waker *exp100_waker; }; size_t Curl_hyper_recv(void *userp, hyper_context *ctx, diff --git a/lib/conncache.c b/lib/conncache.c index 5453c00f33e..f5ba8ff70a8 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -34,6 +34,7 @@ #include "share.h" #include "sigpipe.h" #include "connect.h" +#include "strcase.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -161,6 +162,7 @@ static void hashkey(struct connectdata *conn, char *buf, /* put the number first so that the hostname gets cut off if too long */ msnprintf(buf, len, "%ld%s", port, hostname); + Curl_strntolower(buf, buf, len); } /* Returns number of connections currently held in the connection cache. @@ -264,7 +266,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data) connc->num_conn++; DEBUGF(infof(data, "Added connection %ld. " - "The cache now contains %zu members\n", + "The cache now contains %zu members", conn->connection_id, connc->num_conn)); unlock: @@ -298,7 +300,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, conn->bundle = NULL; /* removed from it */ if(connc) { connc->num_conn--; - DEBUGF(infof(data, "The cache now contains %zu members\n", + DEBUGF(infof(data, "The cache now contains %zu members", connc->num_conn)); } if(lock) { @@ -408,7 +410,7 @@ bool Curl_conncache_return_conn(struct Curl_easy *data, conn->lastused = Curl_now(); /* it was used up until now */ if(maxconnects > 0 && Curl_conncache_size(data) > maxconnects) { - infof(data, "Connection cache is full, closing the oldest one.\n"); + infof(data, "Connection cache is full, closing the oldest one"); conn_candidate = Curl_conncache_extract_oldest(data); if(conn_candidate) { @@ -464,7 +466,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data, /* remove it to prevent another thread from nicking it */ bundle_remove_conn(bundle, conn_candidate); data->state.conn_cache->num_conn--; - DEBUGF(infof(data, "The cache now contains %zu members\n", + DEBUGF(infof(data, "The cache now contains %zu members", data->state.conn_cache->num_conn)); } @@ -526,7 +528,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) /* remove it to prevent another thread from nicking it */ bundle_remove_conn(bundle_candidate, conn_candidate); connc->num_conn--; - DEBUGF(infof(data, "The cache now contains %zu members\n", + DEBUGF(infof(data, "The cache now contains %zu members", connc->num_conn)); } CONNCACHE_UNLOCK(data); diff --git a/lib/connect.c b/lib/connect.c index d9317f3783c..d61b0374e38 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -111,7 +111,7 @@ tcpkeepalive(struct Curl_easy *data, /* only set IDLE and INTVL if setting KEEPALIVE is successful */ if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); + infof(data, "Failed to set SO_KEEPALIVE on fd %d", sockfd); } else { #if defined(SIO_KEEPALIVE_VALS) @@ -126,7 +126,7 @@ tcpkeepalive(struct Curl_easy *data, vals.keepaliveinterval = optval; if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals), NULL, 0, &dummy, NULL, NULL) != 0) { - infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n", + infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d", (int)sockfd, WSAGetLastError()); } #else @@ -135,7 +135,7 @@ tcpkeepalive(struct Curl_easy *data, KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); + infof(data, "Failed to set TCP_KEEPIDLE on fd %d", sockfd); } #endif #ifdef TCP_KEEPINTVL @@ -143,7 +143,7 @@ tcpkeepalive(struct Curl_easy *data, KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); + infof(data, "Failed to set TCP_KEEPINTVL on fd %d", sockfd); } #endif #ifdef TCP_KEEPALIVE @@ -152,7 +152,7 @@ tcpkeepalive(struct Curl_easy *data, KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd); + infof(data, "Failed to set TCP_KEEPALIVE on fd %d", sockfd); } #endif #endif @@ -331,7 +331,7 @@ static CURLcode bindlocal(struct Curl_easy *data, /* * We now have the numerical IP address in the 'myhost' buffer */ - infof(data, "Local Interface %s is ip %s using address family %i\n", + infof(data, "Local Interface %s is ip %s using address family %i", dev, myhost, af); done = 1; break; @@ -364,7 +364,7 @@ static CURLcode bindlocal(struct Curl_easy *data, if(h) { /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ Curl_printable_address(h->addr, myhost, sizeof(myhost)); - infof(data, "Name '%s' family %i resolved to '%s' family %i\n", + infof(data, "Name '%s' family %i resolved to '%s' family %i", dev, af, myhost, h->addr->ai_family); Curl_resolv_unlock(data, h); if(af != h->addr->ai_family) { @@ -458,13 +458,13 @@ static CURLcode bindlocal(struct Curl_easy *data, error, Curl_strerror(error, buffer, sizeof(buffer))); return CURLE_INTERFACE_FAILED; } - infof(data, "Local port: %hu\n", port); + infof(data, "Local port: %hu", port); conn->bits.bound = TRUE; return CURLE_OK; } if(--portnum > 0) { - infof(data, "Bind to local port %hu failed, trying next\n", port); + infof(data, "Bind to local port %hu failed, trying next", port); port++; /* try next port */ /* We re-use/clobber the port variable here below */ if(sock->sa_family == AF_INET) @@ -589,12 +589,10 @@ static CURLcode trynextip(struct Curl_easy *data, struct Curl_addrinfo *ai = conn->tempaddr[tempindex]; while(ai) { - if(ai) { - result = singleipconnect(data, conn, ai, tempindex); - if(result == CURLE_COULDNT_CONNECT) { - ai = ainext(conn, tempindex, TRUE); - continue; - } + result = singleipconnect(data, conn, ai, tempindex); + if(result == CURLE_COULDNT_CONNECT) { + ai = ainext(conn, tempindex, TRUE); + continue; } break; } @@ -753,10 +751,9 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn, int local_port = -1; if(conn->transport == TRNSPRT_TCP) { - if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { + if(!conn->bits.reuse && !conn->bits.tcp_fastopen) Curl_conninfo_remote(data, conn, sockfd); - Curl_conninfo_local(data, sockfd, local_ip, &local_port); - } + Curl_conninfo_local(data, sockfd, local_ip, &local_port); } /* end of TCP-only section */ /* persist connection info in session handle */ @@ -872,15 +869,6 @@ CURLcode Curl_is_connected(struct Curl_easy *data, now = Curl_now(); - /* figure out how long time we have left to connect */ - allow = Curl_timeleft(data, &now, TRUE); - - if(allow < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - if(SOCKS_STATE(conn->cnnct.state)) { /* still doing SOCKS */ result = connect_SOCKS(data, sockindex, connected); @@ -930,7 +918,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data, if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr[i]) { infof(data, "After %" CURL_FORMAT_TIMEDIFF_T - "ms connect time, move on!\n", conn->timeoutms_per_addr[i]); + "ms connect time, move on!", conn->timeoutms_per_addr[i]); error = ETIMEDOUT; } @@ -989,11 +977,12 @@ CURLcode Curl_is_connected(struct Curl_easy *data, char buffer[STRERROR_LEN]; Curl_printable_address(conn->tempaddr[i], ipaddress, sizeof(ipaddress)); - infof(data, "connect to %s port %ld failed: %s\n", + infof(data, "connect to %s port %u failed: %s", ipaddress, conn->port, Curl_strerror(error, buffer, sizeof(buffer))); #endif + allow = Curl_timeleft(data, &now, TRUE); conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ? allow : allow / 2; ainext(conn, i, TRUE); @@ -1006,6 +995,21 @@ CURLcode Curl_is_connected(struct Curl_easy *data, } } + /* + * Now that we've checked whether we are connected, check whether we've + * already timed out. + * + * First figure out how long time we have left to connect */ + + allow = Curl_timeleft(data, &now, TRUE); + + if(allow < 0) { + /* time-out, bail out, go home */ + failf(data, "Connection timeout after %ld ms", + Curl_timediff(now, data->progress.t_startsingle)); + return CURLE_OPERATION_TIMEDOUT; + } + if(result && (conn->tempsock[0] == CURL_SOCKET_BAD) && (conn->tempsock[1] == CURL_SOCKET_BAD)) { @@ -1031,9 +1035,11 @@ CURLcode Curl_is_connected(struct Curl_easy *data, else hostname = conn->host.name; - failf(data, "Failed to connect to %s port %ld: %s", - hostname, conn->port, - Curl_strerror(error, buffer, sizeof(buffer))); + failf(data, "Failed to connect to %s port %u after " + "%" CURL_FORMAT_TIMEDIFF_T " ms: %s", + hostname, conn->port, + Curl_timediff(now, data->progress.t_startsingle), + Curl_strerror(error, buffer, sizeof(buffer))); Curl_quic_disconnect(data, conn, 0); Curl_quic_disconnect(data, conn, 1); @@ -1065,7 +1071,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd) if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) - infof(data, "Could not set TCP_NODELAY: %s\n", + infof(data, "Could not set TCP_NODELAY: %s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); #else (void)data; @@ -1084,9 +1090,11 @@ static void nosigpipe(struct Curl_easy *data, int onoff = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, sizeof(onoff)) < 0) { +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) char buffer[STRERROR_LEN]; - infof(data, "Could not set SO_NOSIGPIPE: %s\n", + infof(data, "Could not set SO_NOSIGPIPE: %s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); +#endif } } #else @@ -1180,7 +1188,7 @@ static CURLcode singleipconnect(struct Curl_easy *data, Curl_closesocket(data, conn, sockfd); return CURLE_OK; } - infof(data, " Trying %s:%d...\n", ipaddress, port); + infof(data, " Trying %s:%d...", ipaddress, port); #ifdef ENABLE_IPV6 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) && @@ -1271,7 +1279,7 @@ static CURLcode singleipconnect(struct Curl_easy *data, #elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */ if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, (void *)&optval, sizeof(optval)) < 0) - infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd); + infof(data, "Failed to enable TCP Fast Open on fd %d", sockfd); rc = connect(sockfd, &addr.sa_addr, addr.addrlen); #elif defined(MSG_FASTOPEN) /* old Linux */ @@ -1321,7 +1329,7 @@ static CURLcode singleipconnect(struct Curl_easy *data, default: /* unknown error, fallthrough and try another address! */ - infof(data, "Immediate connect fail for %s: %s\n", + infof(data, "Immediate connect fail for %s: %s", ipaddress, Curl_strerror(error, buffer, sizeof(buffer))); data->state.os_errno = error; @@ -1394,7 +1402,7 @@ CURLcode Curl_connecthost(struct Curl_easy *data, ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */ - DEBUGF(infof(data, "family0 == %s, family1 == %s\n", + DEBUGF(infof(data, "family0 == %s, family1 == %s", conn->tempfamily[0] == AF_INET ? "v4" : "v6", conn->tempfamily[1] == AF_INET ? "v4" : "v6")); diff --git a/lib/cookie.c b/lib/cookie.c index 941623f9d28..b7531f74244 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -95,7 +95,6 @@ Example set of cookies: #include "strcase.h" #include "curl_get_line.h" #include "curl_memrchr.h" -#include "inet_pton.h" #include "parsedate.h" #include "rand.h" #include "rename.h" @@ -146,31 +145,6 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) return FALSE; } -/* - * isip - * - * Returns true if the given string is an IPv4 or IPv6 address (if IPv6 has - * been enabled while building libcurl, and false otherwise. - */ -static bool isip(const char *domain) -{ - struct in_addr addr; -#ifdef ENABLE_IPV6 - struct in6_addr addr6; -#endif - - if(Curl_inet_pton(AF_INET, domain, &addr) -#ifdef ENABLE_IPV6 - || Curl_inet_pton(AF_INET6, domain, &addr6) -#endif - ) { - /* domain name given as IP address */ - return TRUE; - } - - return FALSE; -} - /* * matching cookie path and url path * RFC6265 5.1.4 Paths and Path-Match @@ -303,7 +277,7 @@ static size_t cookiehash(const char * const domain) const char *top; size_t len; - if(!domain || isip(domain)) + if(!domain || Curl_host_is_ipnum(domain)) return 0; top = get_top_domain(domain, &len); @@ -366,7 +340,7 @@ void Curl_cookie_loadfiles(struct Curl_easy *data) * Failure may be due to OOM or a bad cookie; both are ignored * but only the first should be */ - infof(data, "ignoring failed cookie_init for %s\n", list->data); + infof(data, "ignoring failed cookie_init for %s", list->data); else data->cookies = newcookies; list = list->next; @@ -397,7 +371,9 @@ static void strstore(char **str, const char *newstr) * * Remove expired cookies from the hash by inspecting the expires timestamp on * each cookie in the hash, freeing and deleting any where the timestamp is in - * the past. + * the past. If the cookiejar has recorded the next timestamp at which one or + * more cookies expire, then processing will exit early in case this timestamp + * is in the future. */ static void remove_expired(struct CookieInfo *cookies) { @@ -405,6 +381,20 @@ static void remove_expired(struct CookieInfo *cookies) curl_off_t now = (curl_off_t)time(NULL); unsigned int i; + /* + * 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 won't 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. + */ + if(now < cookies->next_expiration && + cookies->next_expiration != CURL_OFF_T_MAX) + return; + else + cookies->next_expiration = CURL_OFF_T_MAX; + for(i = 0; i < COOKIE_HASH_SIZE; i++) { struct Cookie *pv = NULL; co = cookies->cookies[i]; @@ -421,6 +411,12 @@ static void remove_expired(struct CookieInfo *cookies) freecookie(co); } else { + /* + * If this cookie has an expiration timestamp earlier than what we've + * seen so far then record it for the next round of expirations. + */ + if(co->expires && co->expires < cookies->next_expiration) + cookies->next_expiration = co->expires; pv = co; } co = nx; @@ -524,7 +520,7 @@ Curl_cookie_add(struct Curl_easy *data, if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) || ((nlen + len) > MAX_NAME)) { freecookie(co); - infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n", + infof(data, "oversized cookie dropped, name/val %zu + %zu bytes", nlen, len); return NULL; } @@ -645,7 +641,7 @@ Curl_cookie_add(struct Curl_easy *data, domain = ":"; #endif - is_ip = isip(domain ? domain : whatptr); + is_ip = Curl_host_is_ipnum(domain ? domain : whatptr); if(!domain || (is_ip && !strcmp(whatptr, domain)) @@ -665,7 +661,7 @@ Curl_cookie_add(struct Curl_easy *data, * not a domain to which the current host belongs. Mark as bad. */ badcookie = TRUE; - infof(data, "skipped cookie with bad tailmatch domain: %s\n", + infof(data, "skipped cookie with bad tailmatch domain: %s", whatptr); } } @@ -996,7 +992,7 @@ Curl_cookie_add(struct Curl_easy *data, * must also check that the data handle isn't NULL since the psl code will * dereference it. */ - if(data && (domain && co->domain && !isip(co->domain))) { + if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) { const psl_ctx_t *psl = Curl_psl_use(data); int acceptable; @@ -1009,7 +1005,7 @@ Curl_cookie_add(struct Curl_easy *data, if(!acceptable) { infof(data, "cookie '%s' dropped, domain '%s' must not " - "set cookies for '%s'\n", co->name, domain, co->domain); + "set cookies for '%s'", co->name, domain, co->domain); freecookie(co); return NULL; } @@ -1121,7 +1117,7 @@ Curl_cookie_add(struct Curl_easy *data, if(c->running) /* Only show this when NOT reading the cookies from a file */ infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, " - "expire %" CURL_FORMAT_CURL_OFF_T "\n", + "expire %" CURL_FORMAT_CURL_OFF_T, replace_old?"Replaced":"Added", co->name, co->value, co->domain, co->path, co->expires); @@ -1134,6 +1130,13 @@ Curl_cookie_add(struct Curl_easy *data, c->numcookies++; /* one more cookie in the jar */ } + /* + * Now that we've added a new cookie to the jar, update the expiration + * tracker in case it is the next one to expire. + */ + if(co->expires && (co->expires < c->next_expiration)) + c->next_expiration = co->expires; + return co; } @@ -1169,6 +1172,11 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, c->filename = strdup(file?file:"none"); /* copy the name just in case */ if(!c->filename) goto fail; /* failed to get memory */ + /* + * Initialize the next_expiration time to signal that we don't have enough + * information yet. + */ + c->next_expiration = CURL_OFF_T_MAX; } else { /* we got an already existing one, use that */ @@ -1215,7 +1223,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, /* * Remove expired cookies from the hash. We must make sure to run this - * after reading the file, and not not on every cookie. + * after reading the file, and not on every cookie. */ remove_expired(c); @@ -1247,7 +1255,8 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, * * Helper function to sort cookies such that the longest path gets before the * shorter path. Path, domain and name lengths are considered in that order, - * with tge creationtime as the tiebreaker. + * with the creationtime as the tiebreaker. The creationtime is guaranteed to + * be unique per cookie, so we know we will get an ordering at that point. */ static int cookie_sort(const void *p1, const void *p2) { @@ -1355,7 +1364,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, remove_expired(c); /* check if host is an IP(v4|v6) address */ - is_ip = isip(host); + is_ip = Curl_host_is_ipnum(host); co = c->cookies[myhash]; @@ -1734,7 +1743,7 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) /* if we have a destination file for all the cookies to get dumped to */ res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]); if(res) - infof(data, "WARNING: failed to save cookies in %s: %s\n", + infof(data, "WARNING: failed to save cookies in %s: %s", data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res)); } else { diff --git a/lib/cookie.h b/lib/cookie.h index 460bbb10405..0ffe08e63a6 100644 --- a/lib/cookie.h +++ b/lib/cookie.h @@ -65,6 +65,7 @@ struct CookieInfo { bool running; /* state info, for cookie adding information */ bool newsession; /* new session, discard session cookies on load */ int lastct; /* last creation-time used in the jar */ + curl_off_t next_expiration; /* the next time at which expiration happens */ }; /* This is the maximum line length we accept for a cookie line. RFC 2109 diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index 1d5067bc00c..842fd7fe24b 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -50,12 +50,6 @@ # define in_addr_t unsigned long #endif -#if defined(USE_UNIX_SOCKETS) && defined(WINAPI_FAMILY) && \ - (WINAPI_FAMILY == WINAPI_FAMILY_APP) - /* Required for sockaddr_un type */ -# include <afunix.h> -#endif - #include <stddef.h> #include "curl_addrinfo.h" diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index 96a19afc51e..4ef4883b2ca 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -33,61 +33,91 @@ /* Location of default ca path */ #cmakedefine CURL_CA_PATH "${CURL_CA_PATH}" -/* to disable cookies support */ +/* disables alt-svc */ +#cmakedefine CURL_DISABLE_ALTSVC 1 + +/* disables cookies support */ #cmakedefine CURL_DISABLE_COOKIES 1 -/* to disable cryptographic authentication */ +/* disables cryptographic authentication */ #cmakedefine CURL_DISABLE_CRYPTO_AUTH 1 -/* to disable DICT */ +/* disables DICT */ #cmakedefine CURL_DISABLE_DICT 1 -/* to disable FILE */ +/* disables DNS-over-HTTPS */ +#cmakedefine CURL_DISABLE_DOH 1 + +/* disables FILE */ #cmakedefine CURL_DISABLE_FILE 1 -/* to disable FTP */ +/* disables FTP */ #cmakedefine CURL_DISABLE_FTP 1 -/* to disable GOPHER */ +/* disables GOPHER */ #cmakedefine CURL_DISABLE_GOPHER 1 -/* to disable IMAP */ -#cmakedefine CURL_DISABLE_IMAP 1 +/* disables HSTS support */ +#cmakedefine CURL_DISABLE_HSTS 1 -/* to disable HTTP */ +/* disables HTTP */ #cmakedefine CURL_DISABLE_HTTP 1 -/* to disable LDAP */ +/* disables IMAP */ +#cmakedefine CURL_DISABLE_IMAP 1 + +/* disables LDAP */ #cmakedefine CURL_DISABLE_LDAP 1 -/* to disable LDAPS */ +/* disables LDAPS */ #cmakedefine CURL_DISABLE_LDAPS 1 -/* to disable MQTT */ +/* disables --libcurl option from the curl tool */ +#cmakedefine CURL_DISABLE_LIBCURL_OPTION 1 + +/* disables MIME support */ +#cmakedefine CURL_DISABLE_MIME 1 + +/* disables MQTT */ #cmakedefine CURL_DISABLE_MQTT 1 -/* to disable POP3 */ +/* disables netrc parser */ +#cmakedefine CURL_DISABLE_NETRC 1 + +/* disables NTLM support */ +#cmakedefine CURL_DISABLE_NTLM 1 + +/* disables date parsing */ +#cmakedefine CURL_DISABLE_PARSEDATE 1 + +/* disables POP3 */ #cmakedefine CURL_DISABLE_POP3 1 -/* to disable proxies */ +/* disables built-in progress meter */ +#cmakedefine CURL_DISABLE_PROGRESS_METER 1 + +/* disables proxies */ #cmakedefine CURL_DISABLE_PROXY 1 -/* to disable RTSP */ +/* disables RTSP */ #cmakedefine CURL_DISABLE_RTSP 1 -/* to disable SMB */ +/* disables SMB */ #cmakedefine CURL_DISABLE_SMB 1 -/* to disable SMTP */ +/* disables SMTP */ #cmakedefine CURL_DISABLE_SMTP 1 -/* to disable TELNET */ +/* disables use of socketpair for curl_multi_poll */ +#cmakedefine CURL_DISABLE_SOCKETPAIR 1 + +/* disables TELNET */ #cmakedefine CURL_DISABLE_TELNET 1 -/* to disable TFTP */ +/* disables TFTP */ #cmakedefine CURL_DISABLE_TFTP 1 -/* to disable verbose strings */ +/* disables verbose strings */ #cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 /* to make a symbol visible */ @@ -112,12 +142,6 @@ /* Define if you want to enable IPv6 support */ #cmakedefine ENABLE_IPV6 1 -/* Specifies the number of arguments to getservbyport_r */ -#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS} - -/* Specifies the size of the buffer to pass to getservbyport_r */ -#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE} - /* Define to 1 if you have the alarm function. */ #cmakedefine HAVE_ALARM 1 @@ -151,18 +175,12 @@ /* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ #cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 -/* Define to 1 if you have the <crypto.h> header file. */ -#cmakedefine HAVE_CRYPTO_H 1 - /* Define to 1 if you have the <dlfcn.h> header file. */ #cmakedefine HAVE_DLFCN_H 1 /* Define to 1 if you have the <errno.h> header file. */ #cmakedefine HAVE_ERRNO_H 1 -/* Define to 1 if you have the <err.h> header file. */ -#cmakedefine HAVE_ERR_H 1 - /* Define to 1 if you have the fcntl function. */ #cmakedefine HAVE_FCNTL 1 @@ -172,18 +190,9 @@ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ #cmakedefine HAVE_FCNTL_O_NONBLOCK 1 -/* Define to 1 if you have the fdopen function. */ -#cmakedefine HAVE_FDOPEN 1 - -/* Define to 1 if you have the `fork' function. */ -#cmakedefine HAVE_FORK 1 - /* Define to 1 if you have the freeaddrinfo function. */ #cmakedefine HAVE_FREEADDRINFO 1 -/* Define to 1 if you have the freeifaddrs function. */ -#cmakedefine HAVE_FREEIFADDRS 1 - /* Define to 1 if you have the ftruncate function. */ #cmakedefine HAVE_FTRUNCATE 1 @@ -196,21 +205,6 @@ /* Define to 1 if you have the `getppid' function. */ #cmakedefine HAVE_GETPPID 1 -/* Define to 1 if you have the gethostbyaddr function. */ -#cmakedefine HAVE_GETHOSTBYADDR 1 - -/* Define to 1 if you have the gethostbyaddr_r function. */ -#cmakedefine HAVE_GETHOSTBYADDR_R 1 - -/* gethostbyaddr_r() takes 5 args */ -#cmakedefine HAVE_GETHOSTBYADDR_R_5 1 - -/* gethostbyaddr_r() takes 7 args */ -#cmakedefine HAVE_GETHOSTBYADDR_R_7 1 - -/* gethostbyaddr_r() takes 8 args */ -#cmakedefine HAVE_GETHOSTBYADDR_R_8 1 - /* Define to 1 if you have the gethostbyname function. */ #cmakedefine HAVE_GETHOSTBYNAME 1 @@ -259,9 +253,6 @@ /* Define to 1 if you have the `getrlimit' function. */ #cmakedefine HAVE_GETRLIMIT 1 -/* Define to 1 if you have the getservbyport_r function. */ -#cmakedefine HAVE_GETSERVBYPORT_R 1 - /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY 1 @@ -395,21 +386,6 @@ /* Define to 1 if you have the `ssh2' library (-lssh2). */ #cmakedefine HAVE_LIBSSH2 1 -/* Define to 1 if libssh2 provides `libssh2_version'. */ -#cmakedefine HAVE_LIBSSH2_VERSION 1 - -/* Define to 1 if libssh2 provides `libssh2_init'. */ -#cmakedefine HAVE_LIBSSH2_INIT 1 - -/* Define to 1 if libssh2 provides `libssh2_exit'. */ -#cmakedefine HAVE_LIBSSH2_EXIT 1 - -/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */ -#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1 - -/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */ -#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1 - /* Define to 1 if you have the <libssh2.h> header file. */ #cmakedefine HAVE_LIBSSH2_H 1 @@ -527,9 +503,6 @@ /* Define to 1 if you have the recvfrom function. */ #cmakedefine HAVE_RECVFROM 1 -/* Define to 1 if you have the <rsa.h> header file. */ -#cmakedefine HAVE_RSA_H 1 - /* Define to 1 if you have the select function. */ #cmakedefine HAVE_SELECT 1 @@ -563,9 +536,6 @@ /* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ #cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1 -/* Define to 1 if you have the <sgtty.h> header file. */ -#cmakedefine HAVE_SGTTY_H 1 - /* Define to 1 if you have the sigaction function. */ #cmakedefine HAVE_SIGACTION 1 @@ -581,12 +551,6 @@ /* Define to 1 if you have the sigsetjmp function or macro. */ #cmakedefine HAVE_SIGSETJMP 1 -/* Define to 1 if sig_atomic_t is an available typedef. */ -#cmakedefine HAVE_SIG_ATOMIC_T 1 - -/* Define to 1 if sig_atomic_t is already defined as volatile. */ -#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1 - /* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ #cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 @@ -991,9 +955,6 @@ ${SIZEOF_TIME_T_CODE} /* if Unix domain sockets are enabled */ #cmakedefine USE_UNIX_SOCKETS -/* to disable alt-svc */ -#cmakedefine CURL_DISABLE_ALTSVC 1 - /* Define to 1 if you are building a Windows target with large file support. */ #cmakedefine USE_WIN32_LARGE_FILES 1 diff --git a/lib/curl_endian.c b/lib/curl_endian.c index b6f107e10a4..ecde74bfb1d 100644 --- a/lib/curl_endian.c +++ b/lib/curl_endian.c @@ -80,45 +80,3 @@ unsigned short Curl_read16_be(const unsigned char *buf) return (unsigned short)(((unsigned short)buf[0] << 8) | ((unsigned short)buf[1])); } - -#if (SIZEOF_CURL_OFF_T > 4) -/* - * write32_le() - * - * This function converts a 32-bit integer from the native endian format, - * to little endian format ready for sending down the wire. - * - * Parameters: - * - * value [in] - The 32-bit integer value. - * buffer [in] - A pointer to the output buffer. - */ -static void write32_le(const int value, unsigned char *buffer) -{ - buffer[0] = (char)(value & 0x000000FF); - buffer[1] = (char)((value & 0x0000FF00) >> 8); - buffer[2] = (char)((value & 0x00FF0000) >> 16); - buffer[3] = (char)((value & 0xFF000000) >> 24); -} - -/* - * Curl_write64_le() - * - * This function converts a 64-bit integer from the native endian format, - * to little endian format ready for sending down the wire. - * - * Parameters: - * - * value [in] - The 64-bit integer value. - * buffer [in] - A pointer to the output buffer. - */ -#if defined(HAVE_LONGLONG) -void Curl_write64_le(const long long value, unsigned char *buffer) -#else -void Curl_write64_le(const __int64 value, unsigned char *buffer) -#endif -{ - write32_le((int)value, buffer); - write32_le((int)(value >> 32), buffer + 4); -} -#endif /* SIZEOF_CURL_OFF_T > 4 */ diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c index acaaa1c6831..5810dad14be 100644 --- a/lib/curl_gssapi.c +++ b/lib/curl_gssapi.c @@ -59,7 +59,7 @@ OM_uint32 Curl_gss_init_sec_context( req_flags |= GSS_C_DELEG_POLICY_FLAG; #else infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not " - "compiled in\n"); + "compiled in"); #endif } @@ -130,7 +130,7 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, display_gss_error(minor, GSS_C_MECH_CODE, buf, len); - infof(data, "%s%s\n", prefix, buf); + infof(data, "%s%s", prefix, buf); #ifdef CURL_DISABLE_VERBOSE_STRINGS (void)data; (void)prefix; diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c index 16418bee4c8..e9d2a8cb887 100644 --- a/lib/curl_multibyte.c +++ b/lib/curl_multibyte.c @@ -102,14 +102,16 @@ int curlx_win32_open(const char *filename, int oflag, ...) va_end(param); #ifdef _UNICODE - if(filename_w) + if(filename_w) { result = _wopen(filename_w, oflag, pmode); - free(filename_w); - if(result != -1) - return result; -#endif - + free(filename_w); + } + else + errno = EINVAL; + return result; +#else return (_open)(filename, oflag, pmode); +#endif } FILE *curlx_win32_fopen(const char *filename, const char *mode) @@ -120,19 +122,20 @@ FILE *curlx_win32_fopen(const char *filename, const char *mode) wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode); if(filename_w && mode_w) result = _wfopen(filename_w, mode_w); + else + errno = EINVAL; free(filename_w); free(mode_w); - if(result) - return result; -#endif - + return result; +#else return (fopen)(filename, mode); +#endif } int curlx_win32_stat(const char *path, struct_stat *buffer) { - int result = -1; #ifdef _UNICODE + int result = -1; wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); if(path_w) { #if defined(USE_WIN32_SMALL_FILES) @@ -141,31 +144,34 @@ int curlx_win32_stat(const char *path, struct_stat *buffer) result = _wstati64(path_w, buffer); #endif free(path_w); - if(result != -1) - return result; } -#endif /* _UNICODE */ - + else + errno = EINVAL; + return result; +#else #if defined(USE_WIN32_SMALL_FILES) - result = _stat(path, buffer); + return _stat(path, buffer); #else - result = _stati64(path, buffer); + return _stati64(path, buffer); +#endif #endif - return result; } int curlx_win32_access(const char *path, int mode) { #if defined(_UNICODE) + int result = -1; wchar_t *path_w = curlx_convert_UTF8_to_wchar(path); if(path_w) { - int result = _waccess(path_w, mode); + result = _waccess(path_w, mode); free(path_w); - if(result != -1) - return result; } -#endif /* _UNICODE */ + else + errno = EINVAL; + return result; +#else return _access(path, mode); +#endif } #endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */ diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 89d4ec872eb..749b44e4a92 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -86,7 +86,6 @@ #elif defined(USE_MBEDTLS) # include <mbedtls/des.h> -# include "curl_md4.h" #elif defined(USE_SECTRANSP) @@ -498,17 +497,14 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, * network encoding not the host encoding. */ result = Curl_convert_to_network(data, (char *)pw, len * 2); - if(result) - return result; - - /* Create NT hashed password. */ - Curl_md4it(ntbuffer, pw, 2 * len); - - memset(ntbuffer + 16, 0, 21 - 16); - + if(!result) { + /* Create NT hashed password. */ + Curl_md4it(ntbuffer, pw, 2 * len); + memset(ntbuffer + 16, 0, 21 - 16); + } free(pw); - return CURLE_OK; + return result; } #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c index 9af79fd66a0..5a3bc3c893f 100644 --- a/lib/curl_ntlm_wb.c +++ b/lib/curl_ntlm_wb.c @@ -355,17 +355,17 @@ CURLcode Curl_input_ntlm_wb(struct Curl_easy *data, } else { if(*state == NTLMSTATE_LAST) { - infof(data, "NTLM auth restarted\n"); + infof(data, "NTLM auth restarted"); Curl_http_auth_cleanup_ntlm_wb(conn); } else if(*state == NTLMSTATE_TYPE3) { - infof(data, "NTLM handshake rejected\n"); + infof(data, "NTLM handshake rejected"); Curl_http_auth_cleanup_ntlm_wb(conn); *state = NTLMSTATE_NONE; return CURLE_REMOTE_ACCESS_DENIED; } else if(*state >= NTLMSTATE_TYPE1) { - infof(data, "NTLM handshake failure (internal error)\n"); + infof(data, "NTLM handshake failure (internal error)"); return CURLE_REMOTE_ACCESS_DENIED; } @@ -426,7 +426,8 @@ CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn, /* Use Samba's 'winbind' daemon to support NTLM authentication, * by delegating the NTLM challenge/response protocol to a helper * in ntlm_auth. - * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * https://web.archive.org/web/20190925164737 + * /devel.squid-cache.org/ntlm/squid_helper_protocol.html * https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html * https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this diff --git a/lib/curl_range.c b/lib/curl_range.c index f7fb7c0824c..24bdb3052ed 100644 --- a/lib/curl_range.c +++ b/lib/curl_range.c @@ -53,14 +53,14 @@ CURLcode Curl_range(struct Curl_easy *data) if((to_t == CURL_OFFT_INVAL) && !from_t) { /* X - */ data->state.resume_from = from; - DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n", + DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file", from)); } else if((from_t == CURL_OFFT_INVAL) && !to_t) { /* -Y */ data->req.maxdownload = to; data->state.resume_from = -to; - DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n", + DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes", to)); } else { @@ -78,12 +78,12 @@ CURLcode Curl_range(struct Curl_easy *data) data->req.maxdownload = totalsize + 1; /* include last byte */ data->state.resume_from = from; DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T - " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", + " getting %" CURL_FORMAT_CURL_OFF_T " bytes", from, data->req.maxdownload)); } DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T " to %" CURL_FORMAT_CURL_OFF_T ", totally %" - CURL_FORMAT_CURL_OFF_T " bytes\n", + CURL_FORMAT_CURL_OFF_T " bytes", from, to, data->req.maxdownload)); } else diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index a4d1059cb94..4a2488720e6 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -234,7 +234,7 @@ static void state(struct SASL *sasl, struct Curl_easy *data, }; if(sasl->state != newstate) - infof(data, "SASL %p state change from %s to %s\n", + infof(data, "SASL %p state change from %s to %s", (void *)sasl, names[sasl->state], names[newstate]); #else (void) data; @@ -630,7 +630,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, } else /* Decode the security challenge and create the response message */ - result = Curl_auth_create_gssapi_security_message(data, &serverdata, + result = Curl_auth_create_gssapi_security_message(data, + conn->sasl_authzid, + &serverdata, &conn->krb5, &resp); } @@ -639,7 +641,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, /* Decode the security challenge and create the response message */ result = get_server_message(sasl, data, &serverdata); if(!result) - result = Curl_auth_create_gssapi_security_message(data, &serverdata, + result = Curl_auth_create_gssapi_security_message(data, + conn->sasl_authzid, + &serverdata, &conn->krb5, &resp); break; diff --git a/lib/curl_setup.h b/lib/curl_setup.h index be4a58d4b62..99048c489a3 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -166,41 +166,47 @@ */ #ifdef HTTP_ONLY -# ifndef CURL_DISABLE_TFTP -# define CURL_DISABLE_TFTP +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE # endif # ifndef CURL_DISABLE_FTP # define CURL_DISABLE_FTP # endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif # ifndef CURL_DISABLE_LDAP # define CURL_DISABLE_LDAP # endif -# ifndef CURL_DISABLE_TELNET -# define CURL_DISABLE_TELNET +# ifndef CURL_DISABLE_LDAPS +# define CURL_DISABLE_LDAPS # endif -# ifndef CURL_DISABLE_DICT -# define CURL_DISABLE_DICT +# ifndef CURL_DISABLE_MQTT +# define CURL_DISABLE_MQTT # endif -# ifndef CURL_DISABLE_FILE -# define CURL_DISABLE_FILE +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 # endif # ifndef CURL_DISABLE_RTSP # define CURL_DISABLE_RTSP # endif -# ifndef CURL_DISABLE_POP3 -# define CURL_DISABLE_POP3 -# endif -# ifndef CURL_DISABLE_IMAP -# define CURL_DISABLE_IMAP +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB # endif # ifndef CURL_DISABLE_SMTP # define CURL_DISABLE_SMTP # endif -# ifndef CURL_DISABLE_GOPHER -# define CURL_DISABLE_GOPHER +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET # endif -# ifndef CURL_DISABLE_SMB -# define CURL_DISABLE_SMB +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP # endif #endif @@ -456,6 +462,15 @@ #endif #endif +#ifndef SSIZE_T_MAX +/* some limits.h headers have this defined, some don't */ +#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) +#define SSIZE_T_MAX 9223372036854775807 +#else +#define SSIZE_T_MAX 2147483647 +#endif +#endif + /* * Arg 2 type for gethostname in case it hasn't been defined in config file. */ @@ -644,24 +659,16 @@ int netware_init(void); #endif /* Single point where USE_NTLM definition might be defined */ -#ifndef CURL_DISABLE_CRYPTO_AUTH -#if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \ - defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ - defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ - (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT)) - -#define USE_CURL_NTLM_CORE - -# if defined(USE_MBEDTLS) -/* Get definition of MBEDTLS_MD4_C */ -# include <mbedtls/md4.h> +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(CURL_DISABLE_NTLM) +# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ + (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT)) +# define USE_CURL_NTLM_CORE +# endif +# if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI) +# define USE_NTLM # endif - -#endif - -#if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI) -#define USE_NTLM -#endif #endif #ifdef CURL_WANTS_CA_BUNDLE_ENV @@ -819,4 +826,20 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #define ENABLE_QUIC #endif +#if defined(USE_UNIX_SOCKETS) && defined(WIN32) +# if defined(__MINGW32__) && !defined(LUP_SECURE) + typedef u_short ADDRESS_FAMILY; /* Classic mingw, 11y+ old mingw-w64 */ +# endif +# if !defined(UNIX_PATH_MAX) + /* Replicating logic present in afunix.h + (distributed with newer Windows 10 SDK versions only) */ +# define UNIX_PATH_MAX 108 + /* !checksrc! disable TYPEDEFSTRUCT 1 */ + typedef struct sockaddr_un { + ADDRESS_FAMILY sun_family; + char sun_path[UNIX_PATH_MAX]; + } SOCKADDR_UN, *PSOCKADDR_UN; +# endif +#endif + #endif /* HEADER_CURL_SETUP_H */ diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h index 22d0a063eff..38018d23c7a 100644 --- a/lib/curl_setup_once.h +++ b/lib/curl_setup_once.h @@ -323,26 +323,6 @@ struct timeval { #include "curl_ctype.h" -/* - * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. - */ - -#ifndef HAVE_SIG_ATOMIC_T -typedef int sig_atomic_t; -#define HAVE_SIG_ATOMIC_T -#endif - - -/* - * Convenience SIG_ATOMIC_T definition - */ - -#ifdef HAVE_SIG_ATOMIC_T_VOLATILE -#define SIG_ATOMIC_T static sig_atomic_t -#else -#define SIG_ATOMIC_T static volatile sig_atomic_t -#endif - /* * Macro used to include code only in debug builds. diff --git a/lib/dict.c b/lib/dict.c index 625b057774e..5d53b8f1ff1 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -216,7 +216,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } if(!word || (*word == (char)0)) { - infof(data, "lookup word is missing\n"); + infof(data, "lookup word is missing"); word = (char *)"default"; } if(!database || (*database == (char)0)) { @@ -267,7 +267,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } if(!word || (*word == (char)0)) { - infof(data, "lookup word is missing\n"); + infof(data, "lookup word is missing"); word = (char *)"default"; } if(!database || (*database == (char)0)) { diff --git a/lib/doh.c b/lib/doh.c index 36f8cd58dc5..de0c902b860 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -186,19 +186,19 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp) return realsize; } -/* called from multi.c when this DOH transfer is complete */ +/* called from multi.c when this DoH transfer is complete */ static int doh_done(struct Curl_easy *doh, CURLcode result) { struct Curl_easy *data = doh->set.dohfor; struct dohdata *dohp = data->req.doh; - /* so one of the DOH request done for the 'data' transfer is now complete! */ + /* so one of the DoH request done for the 'data' transfer is now complete! */ dohp->pending--; - infof(data, "a DOH request is completed, %u to go\n", dohp->pending); + infof(data, "a DoH request is completed, %u to go", dohp->pending); if(result) - infof(data, "DOH request %s\n", curl_easy_strerror(result)); + infof(data, "DoH request %s", curl_easy_strerror(result)); if(!dohp->pending) { - /* DOH completed */ + /* DoH completed */ curl_slist_free_all(dohp->headers); dohp->headers = NULL; Curl_expire(data, 0, EXPIRE_RUN_NOW); @@ -228,7 +228,7 @@ static CURLcode dohprobe(struct Curl_easy *data, DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer), &p->dohlen); if(d) { - failf(data, "Failed to encode DOH packet [%d]", d); + failf(data, "Failed to encode DoH packet [%d]", d); return CURLE_OUT_OF_MEMORY; } @@ -302,7 +302,7 @@ static CURLcode dohprobe(struct Curl_easy *data, /* Inherit *some* SSL options from the user's transfer. This is a best-guess as to which options are needed for compatibility. #3661 - Note DOH does not inherit the user's proxy server so proxy SSL settings + Note DoH does not inherit the user's proxy server so proxy SSL settings have no effect and are not inherited. If that changes then two new options should be added to check doh proxy insecure separately, CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER. @@ -359,17 +359,17 @@ static CURLcode dohprobe(struct Curl_easy *data, (data->set.ssl.auto_client_cert ? CURLSSLOPT_AUTO_CLIENT_CERT : 0); - curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask); + (void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask); } doh->set.fmultidone = doh_done; doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; - /* DOH private_data must be null because the user must have a way to - distinguish their transfer's handle from DOH handles in user + /* DoH private_data must be null because the user must have a way to + distinguish their transfer's handle from DoH handles in user callbacks (ie SSL CTX callback). */ - DEBUGASSERT(!data->set.private_data); + DEBUGASSERT(!doh->set.private_data); if(curl_multi_add_handle(multi, doh)) goto error; @@ -386,7 +386,7 @@ static CURLcode dohprobe(struct Curl_easy *data, } /* - * Curl_doh() resolves a name using DOH. It resolves a name and returns a + * Curl_doh() resolves a name using DoH. It resolves a name and returns a * 'Curl_addrinfo *' with the address information. */ @@ -420,7 +420,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, if(!dohp->headers) goto error; - /* create IPv4 DOH request */ + /* create IPv4 DoH request */ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], DNS_TYPE_A, hostname, data->set.str[STRING_DOH], data->multi, dohp->headers); @@ -429,7 +429,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, dohp->pending++; if(Curl_ipv6works(data)) { - /* create IPv6 DOH request */ + /* create IPv6 DoH request */ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH], data->multi, dohp->headers); @@ -764,11 +764,11 @@ static void showdoh(struct Curl_easy *data, const struct dohentry *d) { int i; - infof(data, "TTL: %u seconds\n", d->ttl); + infof(data, "TTL: %u seconds", d->ttl); for(i = 0; i < d->numaddr; i++) { const struct dohaddr *a = &d->addr[i]; if(a->type == DNS_TYPE_A) { - infof(data, "DOH A: %u.%u.%u.%u\n", + infof(data, "DoH A: %u.%u.%u.%u", a->ip.v4[0], a->ip.v4[1], a->ip.v4[2], a->ip.v4[3]); } @@ -777,7 +777,7 @@ static void showdoh(struct Curl_easy *data, char buffer[128]; char *ptr; size_t len; - msnprintf(buffer, 128, "DOH AAAA: "); + msnprintf(buffer, 128, "DoH AAAA: "); ptr = &buffer[10]; len = 118; for(j = 0; j < 16; j += 2) { @@ -788,11 +788,11 @@ static void showdoh(struct Curl_easy *data, len -= l; ptr += l; } - infof(data, "%s\n", buffer); + infof(data, "%s", buffer); } } for(i = 0; i < d->numcname; i++) { - infof(data, "CNAME: %s\n", Curl_dyn_ptr(&d->cname[i])); + infof(data, "CNAME: %s", Curl_dyn_ptr(&d->cname[i])); } } #else @@ -803,7 +803,7 @@ static void showdoh(struct Curl_easy *data, * doh2ai() * * This function returns a pointer to the first element of a newly allocated - * Curl_addrinfo struct linked list filled with the data from a set of DOH + * Curl_addrinfo struct linked list filled with the data from a set of DoH * lookups. Curl_addrinfo is meant to work like the addrinfo struct does for * a IPv6 stack, but usable also for IPv4, all hosts and environments. * @@ -931,7 +931,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy && !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { - failf(data, "Could not DOH-resolve: %s", data->state.async.hostname); + failf(data, "Could not DoH-resolve: %s", data->state.async.hostname); return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: CURLE_COULDNT_RESOLVE_HOST; } @@ -941,7 +941,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, }; struct dohentry de; int slot; - /* remove DOH handles from multi handle and close them */ + /* remove DoH handles from multi handle and close them */ for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { curl_multi_remove_handle(data->multi, dohp->probe[slot].easy); Curl_close(&dohp->probe[slot].easy); @@ -958,7 +958,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, &de); Curl_dyn_free(&p->serverdoh); if(rc[slot]) { - infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]), + infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]), type2name(p->dnstype), dohp->host); } } /* next slot */ @@ -969,7 +969,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry *dns; struct Curl_addrinfo *ai; - infof(data, "DOH Host name: %s\n", dohp->host); + infof(data, "DoH Host name: %s", dohp->host); showdoh(data, &de); ai = doh2ai(&de, dohp->host, dohp->port); @@ -1007,7 +1007,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, } /* !dohp->pending */ - /* else wait for pending DOH transactions to complete */ + /* else wait for pending DoH transactions to complete */ return CURLE_OK; } diff --git a/lib/doh.h b/lib/doh.h index b3584d1b271..70e96e012f7 100644 --- a/lib/doh.h +++ b/lib/doh.h @@ -101,7 +101,7 @@ void de_init(struct dohentry *d); void de_cleanup(struct dohentry *d); #endif -#else /* if DOH is disabled */ +#else /* if DoH is disabled */ #define Curl_doh(a,b,c,d) NULL #define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST #endif diff --git a/lib/easy.c b/lib/easy.c index 530b7c73f22..2aca93845b4 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -117,7 +117,7 @@ curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; #if defined(WIN32) && defined(UNICODE) -curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup; #endif #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) @@ -417,13 +417,13 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */ ev->list = nxt; free(m); m = nxt; - infof(easy, "socket cb: socket %d REMOVED\n", s); + infof(easy, "socket cb: socket %d REMOVED", s); } else { /* The socket 's' is already being monitored, update the activity mask. Convert from libcurl bitmask to the poll one. */ m->socket.events = socketcb2poll(what); - infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, + infof(easy, "socket cb: socket %d UPDATED as %s%s", s, (what&CURL_POLL_IN)?"IN":"", (what&CURL_POLL_OUT)?"OUT":""); } @@ -447,7 +447,7 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */ m->socket.events = socketcb2poll(what); m->socket.revents = 0; ev->list = m; - infof(easy, "socket cb: socket %d ADDED as %s%s\n", s, + infof(easy, "socket cb: socket %d ADDED as %s%s", s, (what&CURL_POLL_IN)?"IN":"", (what&CURL_POLL_OUT)?"OUT":""); } @@ -532,7 +532,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) if(fds[i].revents) { /* socket activity, tell libcurl */ int act = poll2cselect(fds[i].revents); /* convert */ - infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n", + infof(multi->easyp, "call curl_multi_socket_action(socket %d)", fds[i].fd); mcode = curl_multi_socket_action(multi, fds[i].fd, act, &ev->running_handles); @@ -1027,7 +1027,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) { /* Not changing any pause state, return */ - DEBUGF(infof(data, "pause: no change, early return\n")); + DEBUGF(infof(data, "pause: no change, early return")); return CURLE_OK; } @@ -1213,9 +1213,16 @@ static int conn_upkeep(struct Curl_easy *data, /* Param is unused. */ (void)param; - if(conn->handler->connection_check) + if(conn->handler->connection_check) { + /* briefly attach the connection to this transfer for the purpose of + checking it */ + Curl_attach_connnection(data, conn); + /* Do a protocol-specific keepalive check on the connection. */ conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE); + /* detach the connection again */ + Curl_detach_connnection(data); + } return 0; /* continue iteration */ } diff --git a/lib/formdata.c b/lib/formdata.c index 769f06a7059..ac7a0009cd7 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -865,8 +865,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data, if(post->flags & CURL_HTTPPOST_LARGE) clen = post->contentlen; - if(!clen) - clen = -1; if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) { if(!strcmp(file->contents, "-")) { @@ -888,13 +886,21 @@ CURLcode Curl_getformdata(struct Curl_easy *data, else if(post->flags & HTTPPOST_BUFFER) result = curl_mime_data(part, post->buffer, post->bufferlength? post->bufferlength: -1); - else if(post->flags & HTTPPOST_CALLBACK) + else if(post->flags & HTTPPOST_CALLBACK) { /* the contents should be read with the callback and the size is set with the contentslength */ + if(!clen) + clen = -1; result = curl_mime_data_cb(part, clen, fread_func, NULL, NULL, post->userp); + } else { - result = curl_mime_data(part, post->contents, (ssize_t) clen); + size_t uclen; + if(!clen) + uclen = CURL_ZERO_TERMINATED; + else + uclen = (size_t)clen; + result = curl_mime_data(part, post->contents, uclen); #ifdef CURL_DOES_CONVERSIONS /* Convert textual contents now. */ if(!result && data && part->datasize) diff --git a/lib/ftp.c b/lib/ftp.c index 444cf35f55b..0b9c9b7322b 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -289,7 +289,7 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data) failf(data, "Error accept()ing server connect"); return CURLE_FTP_PORT_FAILED; } - infof(data, "Connection accepted from server\n"); + infof(data, "Connection accepted from server"); /* when this happens within the DO state it is important that we mark us as not needing DO_MORE anymore */ conn->bits.do_more = FALSE; @@ -380,7 +380,7 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received) *received = FALSE; timeout_ms = ftp_timeleft_accept(data); - infof(data, "Checking for server connect\n"); + infof(data, "Checking for server connect"); if(timeout_ms < 0) { /* if a timeout was already reached, bail out */ failf(data, "Accept timeout occurred while waiting server connect"); @@ -390,7 +390,7 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received) /* First check whether there is a cached response from server */ if(pp->cache_size && pp->cache && pp->cache[0] > '3') { /* Data connection could not be established, let's return */ - infof(data, "There is negative response in cache while serv connect\n"); + infof(data, "There is negative response in cache while serv connect"); (void)Curl_GetFTPResponse(data, &nread, &ftpcode); return CURLE_FTP_ACCEPT_FAILED; } @@ -408,11 +408,11 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received) default: if(result & CURL_CSELECT_IN2) { - infof(data, "Ready to accept data connection from server\n"); + infof(data, "Ready to accept data connection from server"); *received = TRUE; } else if(result & CURL_CSELECT_IN) { - infof(data, "Ctrl conn has data while waiting for data conn\n"); + infof(data, "Ctrl conn has data while waiting for data conn"); (void)Curl_GetFTPResponse(data, &nread, &ftpcode); if(ftpcode/100 > 3) @@ -444,7 +444,7 @@ static CURLcode InitiateTransfer(struct Curl_easy *data) if(conn->bits.ftp_use_data_ssl) { /* since we only have a plaintext TCP connection here, we must now * do the TLS stuff */ - infof(data, "Doing the SSL/TLS handshake on the data stream\n"); + infof(data, "Doing the SSL/TLS handshake on the data stream"); result = Curl_ssl_connect(data, conn, SECONDARYSOCKET); if(result) return result; @@ -487,7 +487,7 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected) CURLcode result = CURLE_OK; *connected = FALSE; - infof(data, "Preparing for accepting server on data port\n"); + infof(data, "Preparing for accepting server on data port"); /* Save the time we start accepting server connect */ Curl_pgrsTime(data, TIMER_STARTACCEPT); @@ -592,7 +592,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data, * This response code can come at any point so having it treated * generically is a good idea. */ - infof(data, "We got a 421 - timeout!\n"); + infof(data, "We got a 421 - timeout!"); state(data, FTP_STOP); return CURLE_OPERATION_TIMEDOUT; } @@ -768,7 +768,7 @@ static void _state(struct Curl_easy *data, (void) lineno; #else if(ftpc->state != newstate) - infof(data, "FTP %p (line %d) state change from %s to %s\n", + infof(data, "FTP %p (line %d) state change from %s to %s", (void *)ftpc, lineno, ftp_state_names[ftpc->state], ftp_state_names[newstate]); #endif @@ -1139,7 +1139,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, /* The requested bind address is not local. Use the address used for * the control connection instead and restart the port loop */ - infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, + infof(data, "bind(port=%hu) on non-local address failed: %s", port, Curl_strerror(error, buffer, sizeof(buffer))); sslen = sizeof(ss); @@ -1341,7 +1341,7 @@ static CURLcode ftp_state_use_pasv(struct Curl_easy *data, if(!result) { ftpc->count1 = modeoff; state(data, FTP_PASV); - infof(data, "Connect data stream passively\n"); + infof(data, "Connect data stream passively"); } return result; } @@ -1648,7 +1648,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, data->state.infilesize -= data->state.resume_from; if(data->state.infilesize <= 0) { - infof(data, "File already completely uploaded\n"); + infof(data, "File already completely uploaded"); /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); @@ -1802,7 +1802,7 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data, return CURLE_WEIRD_SERVER_REPLY; } - infof(data, "Failed EPSV attempt. Disabling EPSV\n"); + infof(data, "Failed EPSV attempt. Disabling EPSV"); /* disable it for next transfer */ conn->bits.ftp_use_epsv = FALSE; data->state.errorbuf = FALSE; /* allow error message to get @@ -1921,7 +1921,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, if(data->set.ftp_skip_ip) { /* told to ignore the remotely given IP but instead use the host we used for the control connection */ - infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n", + infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead", ip[0], ip[1], ip[2], ip[3], conn->host.name); ftpc->newhost = strdup(control_address(conn)); @@ -2044,7 +2044,7 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data, /* the command failed */ if(EPRT == fcmd) { - infof(data, "disabling EPRT usage\n"); + infof(data, "disabling EPRT usage"); conn->bits.ftp_use_eprt = FALSE; } fcmd++; @@ -2058,7 +2058,7 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data, result = ftp_state_use_port(data, fcmd); } else { - infof(data, "Connect data stream actively\n"); + infof(data, "Connect data stream actively"); state(data, FTP_STOP); /* end of DO phase */ result = ftp_dophase_done(data, FALSE); } @@ -2128,7 +2128,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, } break; default: - infof(data, "unsupported MDTM reply format\n"); + infof(data, "unsupported MDTM reply format"); break; case 550: /* "No such file or directory" */ failf(data, "Given file does not exist"); @@ -2142,7 +2142,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, case CURL_TIMECOND_IFMODSINCE: default: if(data->info.filetime <= data->set.timevalue) { - infof(data, "The requested document is not new enough\n"); + infof(data, "The requested document is not new enough"); ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */ data->info.timecond = TRUE; state(data, FTP_STOP); @@ -2151,7 +2151,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, break; case CURL_TIMECOND_IFUNMODSINCE: if(data->info.filetime > data->set.timevalue) { - infof(data, "The requested document is not old enough\n"); + infof(data, "The requested document is not old enough"); ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */ data->info.timecond = TRUE; state(data, FTP_STOP); @@ -2161,7 +2161,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, } /* switch */ } else { - infof(data, "Skipping time comparison\n"); + infof(data, "Skipping time comparison"); } } @@ -2186,7 +2186,7 @@ static CURLcode ftp_state_type_resp(struct Curl_easy *data, return CURLE_FTP_COULDNT_SET_TYPE; } if(ftpcode != 200) - infof(data, "Got a %03d response code instead of the assumed 200\n", + infof(data, "Got a %03d response code instead of the assumed 200", ftpcode); if(instate == FTP_TYPE) @@ -2219,7 +2219,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data, /* We always (attempt to) get the size of downloads, so it is done before this even when not doing resumes. */ if(filesize == -1) { - infof(data, "ftp server doesn't support SIZE\n"); + infof(data, "ftp server doesn't support SIZE"); /* We couldn't get the size and therefore we can't know if there really is a part of the file left to get, although the server will just close the connection when we start the connection so it won't cause @@ -2256,7 +2256,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data, if(ftp->downloadsize == 0) { /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); - infof(data, "File already completely downloaded\n"); + infof(data, "File already completely downloaded"); /* Set ->transfer so that we won't get any error in ftp_done() * because we didn't transfer the any file */ @@ -2267,7 +2267,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data, /* Set resume file transfer offset */ infof(data, "Instructs server to resume from offset %" - CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + CURL_FORMAT_CURL_OFF_T, data->state.resume_from); result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, data->state.resume_from); @@ -2413,7 +2413,7 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data, if(!connected) { struct ftp_conn *ftpc = &conn->proto.ftpc; - infof(data, "Data conn was not available immediately\n"); + infof(data, "Data conn was not available immediately"); ftpc->wait_data_conn = TRUE; } @@ -2506,11 +2506,11 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, else if((instate != FTP_LIST) && (data->state.prefer_ascii)) size = -1; /* kludge for servers that understate ASCII mode file size */ - infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", + infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T, data->req.maxdownload); if(instate != FTP_LIST) - infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n", + infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T, size); /* FTP download: */ @@ -2526,7 +2526,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, if(!connected) { struct ftp_conn *ftpc = &conn->proto.ftpc; - infof(data, "Data conn was not available immediately\n"); + infof(data, "Data conn was not available immediately"); state(data, FTP_STOP); ftpc->wait_data_conn = TRUE; } @@ -2681,9 +2681,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, /* we have now received a full FTP server response */ switch(ftpc->state) { case FTP_WAIT220: - if(ftpcode == 230) - /* 230 User logged in - already! */ - return ftp_state_user_resp(data, ftpcode, ftpc->state); + if(ftpcode == 230) { + /* 230 User logged in - already! Take as 220 if TLS required. */ + if(data->set.use_ssl <= CURLUSESSL_TRY || + conn->bits.ftp_use_control_ssl) + return ftp_state_user_resp(data, ftpcode, ftpc->state); + } else if(ftpcode != 220) { failf(data, "Got a %03d ftp-server response when 220 was expected", ftpcode); @@ -2702,9 +2705,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); if(Curl_sec_login(data, conn)) - infof(data, "Logging in with password in cleartext!\n"); + infof(data, "Logging in with password in cleartext!"); else - infof(data, "Authentication successful\n"); + infof(data, "Authentication successful"); } #endif @@ -2740,6 +2743,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, case FTP_AUTH: /* we have gotten the response to a previous AUTH command */ + if(pp->cache_size) + return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */ + /* RFC2228 (page 5) says: * * If the server is willing to accept the named security mechanism, @@ -2895,7 +2901,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, } Curl_safefree(ftpc->entrypath); ftpc->entrypath = dir; /* remember this */ - infof(data, "Entry path is '%s'\n", ftpc->entrypath); + infof(data, "Entry path is '%s'", ftpc->entrypath); /* also save it where getinfo can access it: */ data->state.most_recent_ftp_entrypath = ftpc->entrypath; state(data, FTP_SYST); @@ -2904,18 +2910,18 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, Curl_safefree(ftpc->entrypath); ftpc->entrypath = dir; /* remember this */ - infof(data, "Entry path is '%s'\n", ftpc->entrypath); + infof(data, "Entry path is '%s'", ftpc->entrypath); /* also save it where getinfo can access it: */ data->state.most_recent_ftp_entrypath = ftpc->entrypath; } else { /* couldn't get the path */ free(dir); - infof(data, "Failed to figure out path\n"); + infof(data, "Failed to figure out path"); } } state(data, FTP_STOP); /* we are done with the CONNECT phase! */ - DEBUGF(infof(data, "protocol connect phase DONE\n")); + DEBUGF(infof(data, "protocol connect phase DONE")); break; case FTP_SYST: @@ -2962,7 +2968,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, } state(data, FTP_STOP); /* we are done with the CONNECT phase! */ - DEBUGF(infof(data, "protocol connect phase DONE\n")); + DEBUGF(infof(data, "protocol connect phase DONE")); break; case FTP_NAMEFMT: @@ -2973,7 +2979,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, } state(data, FTP_STOP); /* we are done with the CONNECT phase! */ - DEBUGF(infof(data, "protocol connect phase DONE\n")); + DEBUGF(infof(data, "protocol connect phase DONE")); break; case FTP_QUOTE: @@ -3272,7 +3278,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, } if(ftpc->prevpath) - infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); + infof(data, "Remembering we are in dir \"%s\"", ftpc->prevpath); } /* free the dir tree and file parts */ @@ -3338,7 +3344,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, if(ftpc->dont_check && data->req.maxdownload > 0) { /* we have just sent ABOR and there is no reliable way to check if it was * successful or not; we have to close the connection now */ - infof(data, "partial download completed, closing connection\n"); + infof(data, "partial download completed, closing connection"); connclose(conn, "Partial download with no ability to check"); return result; } @@ -3529,7 +3535,7 @@ ftp_pasv_verbose(struct Curl_easy *data, { char buf[256]; Curl_printable_address(ai, buf, sizeof(buf)); - infof(data, "Connecting to %s (%s) port %d\n", newhost, buf, port); + infof(data, "Connecting to %s (%s) port %d", newhost, buf, port); } #endif @@ -3569,7 +3575,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) /* Ready to do more? */ if(connected) { - DEBUGF(infof(data, "DO-MORE connected phase starts\n")); + DEBUGF(infof(data, "DO-MORE connected phase starts")); } else { if(result && (ftpc->count1 == 0)) { @@ -3644,8 +3650,13 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) return result; result = ftp_multi_statemach(data, &complete); - /* ftpc->wait_data_conn is always false here */ - *completep = (int)complete; + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + else + *completep = (int)complete; } else { /* download */ @@ -3692,7 +3703,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) if(!ftpc->wait_data_conn) { /* no waiting for the data connection so this is now complete */ *completep = 1; - DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); + DEBUGF(infof(data, "DO-MORE phase ends with %d", (int)result)); } return result; @@ -3717,7 +3728,7 @@ CURLcode ftp_perform(struct Curl_easy *data, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); if(data->set.opt_no_body) { /* requested no body means no transfer... */ @@ -3737,10 +3748,10 @@ CURLcode ftp_perform(struct Curl_easy *data, *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; - infof(data, "ftp_perform ends with SECONDARY: %d\n", *connected); + infof(data, "ftp_perform ends with SECONDARY: %d", *connected); if(*dophase_done) - DEBUGF(infof(data, "DO phase is complete1\n")); + DEBUGF(infof(data, "DO phase is complete1")); return result; } @@ -3834,7 +3845,7 @@ static CURLcode init_wc_data(struct Curl_easy *data) /* let the writefunc callback know the transfer */ data->set.out = data; - infof(data, "Wildcard - Parsing started\n"); + infof(data, "Wildcard - Parsing started"); return CURLE_OK; fail: @@ -3901,7 +3912,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) free(ftp->pathalloc); ftp->pathalloc = ftp->path = tmp_path; - infof(data, "Wildcard - START of \"%s\"\n", finfo->filename); + infof(data, "Wildcard - START of \"%s\"", finfo->filename); if(data->set.chunk_bgn) { long userresponse; Curl_set_in_callback(data, true); @@ -3910,7 +3921,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) Curl_set_in_callback(data, false); switch(userresponse) { case CURL_CHUNK_BGN_FUNC_SKIP: - infof(data, "Wildcard - \"%s\" skipped by user\n", + infof(data, "Wildcard - \"%s\" skipped by user", finfo->filename); wildcard->state = CURLWC_SKIP; continue; @@ -4233,7 +4244,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data) n -= ftpc->file?strlen(ftpc->file):0; if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) { - infof(data, "Request has same path as previous transfer\n"); + infof(data, "Request has same path as previous transfer"); ftpc->cwddone = TRUE; } } @@ -4279,11 +4290,11 @@ static CURLcode ftp_doing(struct Curl_easy *data, CURLcode result = ftp_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed")); else if(*dophase_done) { result = ftp_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(data, "DO phase is complete2\n")); + DEBUGF(infof(data, "DO phase is complete2")); } return result; } diff --git a/lib/hostasyn.c b/lib/hostasyn.c index b25de1d4176..f7d99ce9a61 100644 --- a/lib/hostasyn.c +++ b/lib/hostasyn.c @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "curl_memory.h" /* The last #include file should be: */ diff --git a/lib/hostcheck.c b/lib/hostcheck.c index 49dbab34721..cf267a76590 100644 --- a/lib/hostcheck.c +++ b/lib/hostcheck.c @@ -36,7 +36,7 @@ #include "hostcheck.h" #include "strcase.h" -#include "inet_pton.h" +#include "hostip.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -67,10 +67,6 @@ static int hostmatch(char *hostname, char *pattern) const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; int wildcard_enabled; size_t prefixlen, suffixlen; - struct in_addr ignored; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 si6; -#endif /* normalize pattern and hostname by stripping off trailing dots */ size_t len = strlen(hostname); @@ -86,12 +82,8 @@ static int hostmatch(char *hostname, char *pattern) CURL_HOST_MATCH : CURL_HOST_NOMATCH; /* detect IP address as hostname and fail the match if so */ - if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0) - return CURL_HOST_NOMATCH; -#ifdef ENABLE_IPV6 - if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0) + if(Curl_host_is_ipnum(hostname)) return CURL_HOST_NOMATCH; -#endif /* We require at least 2 dots in pattern to avoid too wide wildcard match. */ diff --git a/lib/hostip.c b/lib/hostip.c index e0e3cfc2cbd..117caa29578 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -56,13 +56,13 @@ #include "hash.h" #include "rand.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "inet_ntop.h" #include "inet_pton.h" #include "multiif.h" #include "doh.h" #include "warnless.h" +#include "strcase.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -289,7 +289,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data, user.cache_timeout = data->set.dns_cache_timeout; if(hostcache_timestamp_remove(&user, dns)) { - infof(data, "Hostname in DNS cache was stale, zapped\n"); + infof(data, "Hostname in DNS cache was stale, zapped"); dns = NULL; /* the memory deallocation is being handled by the hash */ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); } @@ -460,6 +460,127 @@ Curl_cache_addr(struct Curl_easy *data, return dns; } +#ifdef ENABLE_IPV6 +/* return a static IPv6 resolve for 'localhost' */ +static struct Curl_addrinfo *get_localhost6(int port) +{ + struct Curl_addrinfo *ca; + const size_t ss_size = sizeof(struct sockaddr_in6); + const size_t hostlen = strlen("localhost"); + struct sockaddr_in6 sa6; + unsigned char ipv6[16]; + unsigned short port16 = (unsigned short)(port & 0xffff); + ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); + if(!ca) + return NULL; + + sa6.sin6_family = AF_INET6; + sa6.sin6_port = htons(port16); + sa6.sin6_flowinfo = 0; + sa6.sin6_scope_id = 0; + if(Curl_inet_pton(AF_INET6, "::1", ipv6) < 1) + return NULL; + memcpy(&sa6.sin6_addr, ipv6, sizeof(ipv6)); + + ca->ai_flags = 0; + ca->ai_family = AF_INET6; + ca->ai_socktype = SOCK_STREAM; + ca->ai_protocol = IPPROTO_TCP; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_next = NULL; + ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); + memcpy(ca->ai_addr, &sa6, ss_size); + ca->ai_canonname = (char *)ca->ai_addr + ss_size; + strcpy(ca->ai_canonname, "localhost"); + return ca; +} +#else +#define get_localhost6(x) NULL +#endif + +/* return a static IPv4 resolve for 'localhost' */ +static struct Curl_addrinfo *get_localhost(int port) +{ + struct Curl_addrinfo *ca; + const size_t ss_size = sizeof(struct sockaddr_in); + const size_t hostlen = strlen("localhost"); + struct sockaddr_in sa; + unsigned int ipv4; + unsigned short port16 = (unsigned short)(port & 0xffff); + ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1); + if(!ca) + return NULL; + + /* memset to clear the sa.sin_zero field */ + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(port16); + if(Curl_inet_pton(AF_INET, "127.0.0.1", (char *)&ipv4) < 1) + return NULL; + memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4)); + + ca->ai_flags = 0; + ca->ai_family = AF_INET; + ca->ai_socktype = SOCK_STREAM; + ca->ai_protocol = IPPROTO_TCP; + ca->ai_addrlen = (curl_socklen_t)ss_size; + ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); + memcpy(ca->ai_addr, &sa, ss_size); + ca->ai_canonname = (char *)ca->ai_addr + ss_size; + strcpy(ca->ai_canonname, "localhost"); + ca->ai_next = get_localhost6(port); + return ca; +} + +#ifdef ENABLE_IPV6 +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(struct Curl_easy *data) +{ + if(data) { + /* the nature of most system is that IPv6 status doesn't come and go + during a program's lifetime so we only probe the first time and then we + have the info kept for fast re-use */ + DEBUGASSERT(data); + DEBUGASSERT(data->multi); + return data->multi->ipv6_works; + } + else { + int ipv6_works = -1; + /* probe to see if we have a working IPv6 stack */ + curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); + if(s == CURL_SOCKET_BAD) + /* an IPv6 address was requested but we can't get/use one */ + ipv6_works = 0; + else { + ipv6_works = 1; + sclose(s); + } + return (ipv6_works>0)?TRUE:FALSE; + } +} +#endif /* ENABLE_IPV6 */ + +/* + * Curl_host_is_ipnum() returns TRUE if the given string is a numerical IPv4 + * (or IPv6 if supported) address. + */ +bool Curl_host_is_ipnum(const char *hostname) +{ + struct in_addr in; +#ifdef ENABLE_IPV6 + struct in6_addr in6; +#endif + if(Curl_inet_pton(AF_INET, hostname, &in) > 0 +#ifdef ENABLE_IPV6 + || Curl_inet_pton(AF_INET6, hostname, &in6) > 0 +#endif + ) + return TRUE; + return FALSE; +} + /* * Curl_resolv() is the main name resolve function within libcurl. It resolves * a name and returns a pointer to the entry in the 'entry' argument (if one @@ -487,7 +608,6 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, CURLcode result; enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */ struct connectdata *conn = data->conn; - *entry = NULL; conn->bits.doh = FALSE; /* default is not */ @@ -497,7 +617,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, dns = fetch_addr(data, hostname, port); if(dns) { - infof(data, "Hostname %s was found in DNS cache\n", hostname); + infof(data, "Hostname %s was found in DNS cache", hostname); dns->inuse++; /* we use it! */ rc = CURLRESOLV_RESOLVED; } @@ -534,16 +654,20 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, } #if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES) - /* - * The automagic conversion from IPv4 literals to IPv6 literals only works - * if the SCDynamicStoreCopyProxies system function gets called first. As - * Curl currently doesn't support system-wide HTTP proxies, we therefore - * don't use any value this function might return. - * - * This function is only available on a macOS and is not needed for - * IPv4-only builds, hence the conditions above. - */ - SCDynamicStoreCopyProxies(NULL); + { + /* + * The automagic conversion from IPv4 literals to IPv6 literals only + * works if the SCDynamicStoreCopyProxies system function gets called + * first. As Curl currently doesn't support system-wide HTTP proxies, we + * therefore don't use any value this function might return. + * + * This function is only available on a macOS and is not needed for + * IPv4-only builds, hence the conditions above. + */ + CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL); + if(dict) + CFRelease(dict); + } #endif #ifndef USE_RESOLVE_ON_IPS @@ -579,15 +703,18 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, #endif /* !USE_RESOLVE_ON_IPS */ if(!addr) { - /* Check what IP specifics the app has requested and if we can provide - * it. If not, bail out. */ - if(!Curl_ipvalid(data, conn)) + if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data)) return CURLRESOLV_ERROR; - if(allowDOH && data->set.doh && !ipnum) { + if(strcasecompare(hostname, "localhost")) + addr = get_localhost(port); + else if(allowDOH && data->set.doh && !ipnum) addr = Curl_doh(data, hostname, port, &respwait); - } else { + /* Check what IP specifics the app has requested and if we can provide + * it. If not, bail out. */ + if(!Curl_ipvalid(data, conn)) + return CURLRESOLV_ERROR; /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ @@ -757,7 +884,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, #else #ifndef CURLRES_ASYNCH if(timeoutms) - infof(data, "timeout on name lookup is not supported\n"); + infof(data, "timeout on name lookup is not supported"); #else (void)timeoutms; /* timeoutms not used with an async resolver */ #endif @@ -895,7 +1022,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) size_t entry_len; if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { - infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", + infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'", hostp->data); continue; } @@ -984,7 +1111,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) #ifndef ENABLE_IPV6 if(strchr(address, ':')) { - infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n", + infof(data, "Ignoring resolve address '%s', missing IPv6 support.", address); continue; } @@ -992,7 +1119,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) ai = Curl_str2addr(address, port); if(!ai) { - infof(data, "Resolve address '%s' found illegal!\n", address); + infof(data, "Resolve address '%s' found illegal!", address); goto err; } @@ -1011,10 +1138,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) error = false; err: if(error) { - infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", + failf(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!", hostp->data); Curl_freeaddrinfo(head); - continue; + return CURLE_SETOPT_OPTION_SYNTAX; } /* Create an entry id, based upon the hostname and port */ @@ -1028,7 +1155,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); if(dns) { - infof(data, "RESOLVE %s:%d is - old addresses discarded!\n", + infof(data, "RESOLVE %s:%d is - old addresses discarded!", hostname, port); /* delete old entry, there are two reasons for this 1. old entry may have different addresses. @@ -1061,12 +1188,12 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) Curl_freeaddrinfo(head); return CURLE_OUT_OF_MEMORY; } - infof(data, "Added %s:%d:%s to DNS cache%s\n", + infof(data, "Added %s:%d:%s to DNS cache%s", hostname, port, addresses, permanent ? "" : " (non-permanent)"); /* Wildcard hostname */ if(hostname[0] == '*' && hostname[1] == '\0') { - infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n", + infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks", hostname, port); data->state.wildcard_resolve = true; } @@ -1094,7 +1221,7 @@ int Curl_resolv_getsock(struct Curl_easy *data, { #ifdef CURLRES_ASYNCH if(data->conn->bits.doh) - /* nothing to wait for during DOH resolve, those handles have their own + /* nothing to wait for during DoH resolve, those handles have their own sockets */ return GETSOCK_BLANK; return Curl_resolver_getsock(data, socks); diff --git a/lib/hostip.h b/lib/hostip.h index d178976aa17..67a688aebdc 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -71,6 +71,8 @@ struct Curl_dns_entry { long inuse; }; +bool Curl_host_is_ipnum(const char *hostname); + /* * Curl_resolv() returns an entry with the info for the specified host * and port. @@ -95,7 +97,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, struct Curl_dns_entry **dnsentry, timediff_t timeoutms); -#ifdef CURLRES_IPV6 +#ifdef ENABLE_IPV6 /* * Curl_ipv6works() returns TRUE if IPv6 seems to work. */ diff --git a/lib/hostip4.c b/lib/hostip4.c index d0754af2239..1fd791015c6 100644 --- a/lib/hostip4.c +++ b/lib/hostip4.c @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -104,7 +103,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, ai = Curl_ipv4_resolve_r(hostname, port); if(!ai) - infof(data, "Curl_ipv4_resolve_r failed for %s\n", hostname); + infof(data, "Curl_ipv4_resolve_r failed for %s", hostname); return ai; } diff --git a/lib/hostip6.c b/lib/hostip6.c index 9791d86468d..c2d5f08e325 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "inet_pton.h" #include "connect.h" @@ -59,34 +58,6 @@ #include "curl_memory.h" #include "memdebug.h" -/* - * Curl_ipv6works() returns TRUE if IPv6 seems to work. - */ -bool Curl_ipv6works(struct Curl_easy *data) -{ - if(data) { - /* the nature of most system is that IPv6 status doesn't come and go - during a program's lifetime so we only probe the first time and then we - have the info kept for fast re-use */ - DEBUGASSERT(data); - DEBUGASSERT(data->multi); - return data->multi->ipv6_works; - } - else { - int ipv6_works = -1; - /* probe to see if we have a working IPv6 stack */ - curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); - if(s == CURL_SOCKET_BAD) - /* an IPv6 address was requested but we can't get/use one */ - ipv6_works = 0; - else { - ipv6_works = 1; - sclose(s); - } - return (ipv6_works>0)?TRUE:FALSE; - } -} - /* * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've * been set and returns TRUE if they are OK. @@ -172,7 +143,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res); if(error) { - infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port); + infof(data, "getaddrinfo(3) failed for %s:%d", hostname, port); return NULL; } diff --git a/lib/hostsyn.c b/lib/hostsyn.c index 550b43a085f..c00c2744c43 100644 --- a/lib/hostsyn.c +++ b/lib/hostsyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -50,7 +50,6 @@ #include "hostip.h" #include "hash.h" #include "share.h" -#include "strerror.h" #include "url.h" #include "curl_memory.h" /* The last #include file should be: */ diff --git a/lib/hsts.c b/lib/hsts.c index ef166f196cd..853c7dfea5a 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -138,6 +138,11 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname, struct stsentry *sts; time_t now = time(NULL); + if(Curl_host_is_ipnum(hostname)) + /* "explicit IP address identification of all forms is excluded." + / RFC 6797 */ + return CURLE_OK; + do { while(*p && ISSPACE(*p)) p++; @@ -521,7 +526,9 @@ CURLcode Curl_hsts_loadfile(struct Curl_easy *data, */ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) { - return hsts_pull(data, h); + if(h) + return hsts_pull(data, h); + return CURLE_OK; } #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ diff --git a/lib/http.c b/lib/http.c index 628dd73703f..d5c36dd54a0 100644 --- a/lib/http.c +++ b/lib/http.c @@ -504,7 +504,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, /* rewind data when completely done sending! */ if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { conn->bits.rewindaftersend = TRUE; - infof(data, "Rewind stream after send\n"); + infof(data, "Rewind stream after send"); } return CURLE_OK; @@ -515,7 +515,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, return CURLE_OK; infof(data, "NTLM send, close instead of sending %" - CURL_FORMAT_CURL_OFF_T " bytes\n", + CURL_FORMAT_CURL_OFF_T " bytes", (curl_off_t)(expectsend - bytessent)); } #endif @@ -532,7 +532,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, /* rewind data when completely done sending! */ if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { conn->bits.rewindaftersend = TRUE; - infof(data, "Rewind stream after send\n"); + infof(data, "Rewind stream after send"); } return CURLE_OK; @@ -543,7 +543,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, return CURLE_OK; infof(data, "NEGOTIATE send, close instead of sending %" - CURL_FORMAT_CURL_OFF_T " bytes\n", + CURL_FORMAT_CURL_OFF_T " bytes", (curl_off_t)(expectsend - bytessent)); } #endif @@ -756,14 +756,14 @@ output_auth_headers(struct Curl_easy *data, if(auth) { #ifndef CURL_DISABLE_PROXY - infof(data, "%s auth using %s with user '%s'\n", + infof(data, "%s auth using %s with user '%s'", proxy ? "Proxy" : "Server", auth, proxy ? (data->state.aptr.proxyuser ? data->state.aptr.proxyuser : "") : (data->state.aptr.user ? data->state.aptr.user : "")); #else - infof(data, "Server auth using %s with user '%s'\n", + infof(data, "Server auth using %s with user '%s'", auth, data->state.aptr.user ? data->state.aptr.user : ""); #endif @@ -850,7 +850,9 @@ Curl_http_output_auth(struct Curl_easy *data, /* To prevent the user+password to get sent to other than the original host due to a location-follow, we do some weirdo checks here */ if(!data->state.this_is_a_follow || +#ifndef CURL_DISABLE_NETRC conn->bits.netrc || +#endif !data->state.first_host || data->set.allow_auth_to_other_hosts || strcasecompare(data->state.first_host, conn->host.name)) { @@ -995,14 +997,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, result = Curl_input_ntlm_wb(data, conn, proxy, auth); if(result) { - infof(data, "Authentication problem. Ignoring this.\n"); + infof(data, "Authentication problem. Ignoring this."); data->state.authproblem = TRUE; } } #endif } else { - infof(data, "Authentication problem. Ignoring this.\n"); + infof(data, "Authentication problem. Ignoring this."); data->state.authproblem = TRUE; } } @@ -1013,7 +1015,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, #ifndef CURL_DISABLE_CRYPTO_AUTH if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) { if((authp->avail & CURLAUTH_DIGEST) != 0) - infof(data, "Ignoring duplicate digest auth header.\n"); + infof(data, "Ignoring duplicate digest auth header."); else if(Curl_auth_is_digest_supported()) { CURLcode result; @@ -1026,7 +1028,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, * Digest */ result = Curl_input_digest(data, proxy, auth); if(result) { - infof(data, "Authentication problem. Ignoring this.\n"); + infof(data, "Authentication problem. Ignoring this."); data->state.authproblem = TRUE; } } @@ -1042,7 +1044,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, anyway, which basically means our name+password isn't valid. */ authp->avail = CURLAUTH_NONE; - infof(data, "Authentication problem. Ignoring this.\n"); + infof(data, "Authentication problem. Ignoring this."); data->state.authproblem = TRUE; } } @@ -1055,7 +1057,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy, /* We asked for Bearer authentication but got a 40X back anyway, which basically means our token isn't valid. */ authp->avail = CURLAUTH_NONE; - infof(data, "Authentication problem. Ignoring this.\n"); + infof(data, "Authentication problem. Ignoring this."); data->state.authproblem = TRUE; } } @@ -1177,6 +1179,7 @@ static size_t readmoredata(char *buffer, data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE; if(data->set.max_send_speed && + (data->set.max_send_speed < (curl_off_t)fullsize) && (data->set.max_send_speed < http->postsize)) /* speed limit */ fullsize = (size_t)data->set.max_send_speed; @@ -1537,38 +1540,35 @@ static int http_getsock_do(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY static CURLcode add_haproxy_protocol_header(struct Curl_easy *data) { - char proxy_header[128]; struct dynbuf req; CURLcode result; - char tcp_version[5]; + const char *tcp_version; DEBUGASSERT(data->conn); + Curl_dyn_init(&req, DYN_HAXPROXY); - /* Emit the correct prefix for IPv6 */ - if(data->conn->bits.ipv6) { - strcpy(tcp_version, "TCP6"); - } +#ifdef USE_UNIX_SOCKETS + if(data->conn->unix_domain_socket) + /* the buffer is large enough to hold this! */ + result = Curl_dyn_add(&req, "PROXY UNKNOWN\r\n"); else { - strcpy(tcp_version, "TCP4"); - } - - msnprintf(proxy_header, - sizeof(proxy_header), - "PROXY %s %s %s %i %i\r\n", - tcp_version, - data->info.conn_local_ip, - data->info.conn_primary_ip, - data->info.conn_local_port, - data->info.conn_primary_port); - - Curl_dyn_init(&req, DYN_HAXPROXY); +#endif + /* Emit the correct prefix for IPv6 */ + tcp_version = data->conn->bits.ipv6 ? "TCP6" : "TCP4"; - result = Curl_dyn_add(&req, proxy_header); - if(result) - return result; + result = Curl_dyn_addf(&req, "PROXY %s %s %s %i %i\r\n", + tcp_version, + data->info.conn_local_ip, + data->info.conn_primary_ip, + data->info.conn_local_port, + data->info.conn_primary_port); - result = Curl_buffer_send(&req, data, &data->info.request_size, - 0, FIRSTSOCKET); +#ifdef USE_UNIX_SOCKETS + } +#endif + if(!result) + result = Curl_buffer_send(&req, data, &data->info.request_size, + 0, FIRSTSOCKET); return result; } #endif @@ -1588,7 +1588,7 @@ static CURLcode https_connecting(struct Curl_easy *data, bool *done) #endif /* perform SSL initialization for this socket */ - result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, done); + result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, done); if(result) connclose(conn, "Failed HTTPS connection"); @@ -1669,8 +1669,8 @@ CURLcode Curl_http_done(struct Curl_easy *data, * - if any server previously contacted to handle this request only supports * 1.0. */ -static bool use_http_1_1plus(const struct Curl_easy *data, - const struct connectdata *conn) +bool Curl_use_http_1_1plus(const struct Curl_easy *data, + const struct connectdata *conn) { if((data->state.httpversion == 10) || (conn->httpversion == 10)) return FALSE; @@ -1696,7 +1696,7 @@ static const char *get_http_string(const struct Curl_easy *data, return "2"; #endif - if(use_http_1_1plus(data, conn)) + if(Curl_use_http_1_1plus(data, conn)) return "1.1"; return "1.0"; @@ -1711,7 +1711,7 @@ static CURLcode expect100(struct Curl_easy *data, CURLcode result = CURLE_OK; data->state.expect100header = FALSE; /* default to false unless it is set to TRUE below */ - if(!data->state.disableexpect && use_http_1_1plus(data, conn) && + if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) && (conn->httpversion < 20)) { /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an Expect: 100-continue to the headers which actually speeds up post @@ -2348,7 +2348,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, if(conn->bits.authneg) /* don't enable chunked during auth neg */ ; - else if(use_http_1_1plus(data, conn)) { + else if(Curl_use_http_1_1plus(data, conn)) { if(conn->httpversion < 20) /* HTTP, upload, unknown file size and not HTTP 1.0 */ data->req.upload_chunky = TRUE; @@ -2711,14 +2711,16 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, int count = 0; if(data->cookies && data->state.cookie_engine) { + const char *host = data->state.aptr.cookiehost ? + data->state.aptr.cookiehost : conn->host.name; + const bool secure_context = + conn->handler->protocol&CURLPROTO_HTTPS || + strcasecompare("localhost", host) || + !strcmp(host, "127.0.0.1") || + !strcmp(host, "[::1]") ? TRUE : FALSE; Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - co = Curl_cookie_getlist(data->cookies, - data->state.aptr.cookiehost? - data->state.aptr.cookiehost: - conn->host.name, - data->state.up.path, - (conn->handler->protocol&CURLPROTO_HTTPS)? - TRUE:FALSE); + co = Curl_cookie_getlist(data->cookies, host, data->state.up.path, + secure_context); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } if(co) { @@ -2901,6 +2903,20 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data, { struct SingleRequest *k = &data->req; DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)); + if(data->req.ignore_cl) { + k->size = k->maxdownload = -1; + } + else if(k->size != -1) { + /* We wait until after all headers have been received to set this so that + we know for sure Content-Length is valid. */ + if(data->set.max_filesize && + k->size > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + Curl_pgrsSetDownloadSize(data, k->size); + } + if(data->req.newurl) { if(conn->bits.close) { /* Abort after the headers if "follow Location" is set @@ -2912,7 +2928,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data, /* We have a new url to load, but since we want to be able to re-use this connection properly, we read the full response in "ignore more" */ k->ignorebody = TRUE; - infof(data, "Ignoring the response-body\n"); + infof(data, "Ignoring the response-body"); } if(data->state.resume_from && !k->content_range && (data->state.httpreq == HTTPREQ_GET) && @@ -2947,7 +2963,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data, /* We're simulating a http 304 from server so we return what should have been returned from the server */ data->info.httpcode = 304; - infof(data, "Simulate a HTTP 304 response!\n"); + infof(data, "Simulate a HTTP 304 response!"); /* we abort the transfer before it is completed == we ruin the re-use ability. Close the connection */ connclose(conn, "Simulated 304 handling"); @@ -2958,6 +2974,39 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data, return CURLE_OK; } +#ifdef HAVE_LIBZ +CURLcode Curl_transferencode(struct Curl_easy *data) +{ + if(!Curl_checkheaders(data, "TE") && + data->set.http_transfer_encoding) { + /* When we are to insert a TE: header in the request, we must also insert + TE in a Connection: header, so we need to merge the custom provided + Connection: header and prevent the original to get sent. Note that if + the user has inserted his/her own TE: header we don't do this magic + but then assume that the user will handle it all! */ + char *cptr = Curl_checkheaders(data, "Connection"); +#define TE_HEADER "TE: gzip\r\n" + + Curl_safefree(data->state.aptr.te); + + if(cptr) { + cptr = Curl_copy_header_value(cptr); + if(!cptr) + return CURLE_OUT_OF_MEMORY; + } + + /* Create the (updated) Connection: header */ + data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER, + cptr ? cptr : "", (cptr && *cptr) ? ", ":""); + + free(cptr); + if(!data->state.aptr.te) + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} +#endif + #ifndef USE_HYPER /* * Curl_http() gets called from the generic multi_do() function when a HTTP @@ -3004,11 +3053,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { /* We don't support HTTP/2 proxies yet. Also it's debatable whether or not this setting should apply to HTTP/2 proxies. */ - infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n"); + infof(data, "Ignoring HTTP/2 prior knowledge due to proxy"); break; } #endif - DEBUGF(infof(data, "HTTP/2 over clean TCP\n")); + DEBUGF(infof(data, "HTTP/2 over clean TCP")); conn->httpversion = 20; result = Curl_http2_switched(data, NULL, 0); @@ -3074,33 +3123,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) #ifdef HAVE_LIBZ /* we only consider transfer-encoding magic if libz support is built-in */ - - if(!Curl_checkheaders(data, "TE") && - data->set.http_transfer_encoding) { - /* When we are to insert a TE: header in the request, we must also insert - TE in a Connection: header, so we need to merge the custom provided - Connection: header and prevent the original to get sent. Note that if - the user has inserted his/her own TE: header we don't do this magic - but then assume that the user will handle it all! */ - char *cptr = Curl_checkheaders(data, "Connection"); -#define TE_HEADER "TE: gzip\r\n" - - Curl_safefree(data->state.aptr.te); - - if(cptr) { - cptr = Curl_copy_header_value(cptr); - if(!cptr) - return CURLE_OUT_OF_MEMORY; - } - - /* Create the (updated) Connection: header */ - data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER, - cptr ? cptr : "", (cptr && *cptr) ? ", ":""); - - free(cptr); - if(!data->state.aptr.te) - return CURLE_OUT_OF_MEMORY; - } + result = Curl_transferencode(data); + if(result) + return result; #endif result = Curl_http_body(data, conn, httpreq, &te); @@ -3253,7 +3278,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) /* already sent the entire request body, mark the "upload" as complete */ infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T - " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", + " out of %" CURL_FORMAT_CURL_OFF_T " bytes", data->req.writebytecount, http->postsize); data->req.upload_done = TRUE; data->req.keepon &= ~KEEP_SEND; /* we're done writing */ @@ -3392,17 +3417,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, NULL, 10, &contentlength); if(offt == CURL_OFFT_OK) { - if(data->set.max_filesize && - contentlength > data->set.max_filesize) { - failf(data, "Maximum file size exceeded"); - return CURLE_FILESIZE_EXCEEDED; - } k->size = contentlength; k->maxdownload = k->size; - /* we set the progress download size already at this point - just to make it easier for apps/callbacks to extract this - info as soon as possible */ - Curl_pgrsSetDownloadSize(data, k->size); } else if(offt == CURL_OFFT_FLOW) { /* out of range */ @@ -3411,7 +3427,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, return CURLE_FILESIZE_EXCEEDED; } streamclose(conn, "overflow content-length"); - infof(data, "Overflow Content-Length: value!\n"); + infof(data, "Overflow Content-Length: value!"); } else { /* negative or just rubbish - bad HTTP */ @@ -3443,7 +3459,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * Default action for 1.0 is to close. */ connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */ - infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); + infof(data, "HTTP/1.0 proxy connection set to keep alive!"); } else if((conn->httpversion == 11) && conn->bits.httpproxy && @@ -3453,7 +3469,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * close down after this transfer. */ connclose(conn, "Proxy-Connection: asked to close after done"); - infof(data, "HTTP/1.1 proxy connection set close!\n"); + infof(data, "HTTP/1.1 proxy connection set close!"); } #endif else if((conn->httpversion == 10) && @@ -3465,7 +3481,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, * * [RFC2068, section 19.7.1] */ connkeep(conn, "Connection keep-alive"); - infof(data, "HTTP/1.0 connection set to keep alive!\n"); + infof(data, "HTTP/1.0 connection set to keep alive!"); } else if(Curl_compareheader(headp, "Connection:", "close")) { /* @@ -3493,6 +3509,12 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, TRUE); if(result) return result; + if(!k->chunk) { + /* if this isn't chunked, only close can signal the end of this transfer + as Content-Length is said not to be trusted for transfer-encoding! */ + connclose(conn, "HTTP/1.1 transfer-encoding without chunks"); + k->ignore_cl = TRUE; + } } else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) && data->set.str[STRING_ENCODING]) { @@ -3555,18 +3577,21 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, #if !defined(CURL_DISABLE_COOKIES) else if(data->cookies && data->state.cookie_engine && checkprefix("Set-Cookie:", headp)) { + /* If there is a custom-set Host: name, use it here, or else use real peer + host name. */ + const char *host = data->state.aptr.cookiehost? + data->state.aptr.cookiehost:conn->host.name; + const bool secure_context = + conn->handler->protocol&CURLPROTO_HTTPS || + strcasecompare("localhost", host) || + !strcmp(host, "127.0.0.1") || + !strcmp(host, "[::1]") ? TRUE : FALSE; + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - Curl_cookie_add(data, - data->cookies, TRUE, FALSE, - headp + strlen("Set-Cookie:"), - /* If there is a custom-set Host: name, use it - here, or else use real peer host name. */ - data->state.aptr.cookiehost? - data->state.aptr.cookiehost:conn->host.name, - data->state.up.path, - (conn->handler->protocol&CURLPROTO_HTTPS)? - TRUE:FALSE); + Curl_cookie_add(data, data->cookies, TRUE, FALSE, + headp + strlen("Set-Cookie:"), host, + data->state.up.path, secure_context); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } #endif @@ -3646,10 +3671,10 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, Curl_hsts_parse(data->hsts, data->state.up.hostname, headp + strlen("Strict-Transport-Security:")); if(check) - infof(data, "Illegal STS header skipped\n"); + infof(data, "Illegal STS header skipped"); #ifdef DEBUGBUILD else - infof(data, "Parsed STS header fine (%zu entries)\n", + infof(data, "Parsed STS header fine (%zu entries)", data->hsts->list.size); #endif } @@ -3719,12 +3744,12 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, /* Default action for HTTP/1.0 must be to close, unless we get one of those fancy headers that tell us the server keeps it open for us! */ - infof(data, "HTTP 1.0, assume close after body\n"); + infof(data, "HTTP 1.0, assume close after body"); connclose(conn, "HTTP/1.0 close after body"); } else if(conn->httpversion == 20 || (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) { - DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n")); + DEBUGF(infof(data, "HTTP/2 found, allow multiplexing")); /* HTTP/2 cannot avoid multiplexing since it is a core functionality of the protocol */ conn->bundle->multiuse = BUNDLE_MULTIPLEX; @@ -3733,7 +3758,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, !conn->bits.close) { /* If HTTP version is >= 1.1 and connection is persistent */ DEBUGF(infof(data, - "HTTP 1.1 or later with persistent connection\n")); + "HTTP 1.1 or later with persistent connection")); } k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200; @@ -3911,7 +3936,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* Switching Protocols */ if(k->upgr101 == UPGR101_REQUESTED) { /* Switching to HTTP/2 */ - infof(data, "Received 101\n"); + infof(data, "Received 101"); k->upgr101 = UPGR101_RECEIVED; /* we'll get more headers (HTTP/2 response) */ @@ -3951,7 +3976,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, assume that the server will close the connection to signal the end of the document. */ infof(data, "no chunk, no close, no size. Assume close to " - "signal end\n"); + "signal end"); streamclose(conn, "HTTP: No end-of-message indicator"); } } @@ -3964,7 +3989,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, (conn->http_ntlm_state == NTLMSTATE_TYPE2)) || ((data->req.httpcode == 407) && (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) { - infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)"); data->state.authproblem = TRUE; } #endif @@ -3974,7 +3999,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, (conn->http_negotiate_state == GSS_AUTHRECV)) || ((data->req.httpcode == 407) && (conn->proxy_negotiate_state == GSS_AUTHRECV)))) { - infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)"); data->state.authproblem = TRUE; } if((conn->http_negotiate_state == GSS_AUTHDONE) && @@ -4054,21 +4079,21 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if((k->httpcode == 417) && data->state.expect100header) { /* 417 Expectation Failed - try again without the Expect header */ - infof(data, "Got 417 while waiting for a 100\n"); + infof(data, "Got 417 while waiting for a 100"); data->state.disableexpect = TRUE; DEBUGASSERT(!data->req.newurl); data->req.newurl = strdup(data->state.url); Curl_done_sending(data, k); } else if(data->set.http_keep_sending_on_error) { - infof(data, "HTTP error before end of send, keep sending\n"); + infof(data, "HTTP error before end of send, keep sending"); if(k->exp100 > EXP100_SEND_DATA) { k->exp100 = EXP100_SEND_DATA; k->keepon |= KEEP_SEND; } } else { - infof(data, "HTTP error before end of send, stop sending\n"); + infof(data, "HTTP error before end of send, stop sending"); streamclose(conn, "Stop sending data before everything sent"); result = Curl_done_sending(data, k); if(result) @@ -4088,7 +4113,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(conn->bits.rewindaftersend) { /* We rewind after a complete send, so thus we continue sending now */ - infof(data, "Keep sending data to get tossed away!\n"); + infof(data, "Keep sending data to get tossed away!"); k->keepon |= KEEP_SEND; } } @@ -4201,18 +4226,20 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * https://tools.ietf.org/html/rfc7230#section-3.1.2 * * The response code is always a three-digit number in HTTP as the spec - * says. We try to allow any number here, but we cannot make + * says. We allow any three-digit number here, but we cannot make * guarantees on future behaviors since it isn't within the protocol. */ char separator; char twoorthree[2]; int httpversion = 0; + int digit4 = -1; /* should remain untouched to be good */ nc = sscanf(HEADER1, - " HTTP/%1d.%1d%c%3d", + " HTTP/%1d.%1d%c%3d%1d", &httpversion_major, &httpversion, &separator, - &k->httpcode); + &k->httpcode, + &digit4); if(nc == 1 && httpversion_major >= 2 && 2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) { @@ -4221,6 +4248,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, separator = ' '; } + /* There can only be a 4th response code digit stored in 'digit4' if + all the other fields were parsed and stored first, so nc is 5 when + digit4 is not -1 */ + else if(digit4 != -1) { + failf(data, "Unsupported response code in HTTP response"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + if((nc == 4) && (' ' == separator)) { httpversion += 10 * httpversion_major; switch(httpversion) { @@ -4243,11 +4278,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(k->upgr101 == UPGR101_RECEIVED) { /* supposedly upgraded to http2 now */ if(conn->httpversion != 20) - infof(data, "Lying server, not serving HTTP/2\n"); + infof(data, "Lying server, not serving HTTP/2"); } if(conn->httpversion < 20) { conn->bundle->multiuse = BUNDLE_NO_MULTIUSE; - infof(data, "Mark bundle as not supporting multiuse\n"); + infof(data, "Mark bundle as not supporting multiuse"); } } else if(!nc) { diff --git a/lib/http.h b/lib/http.h index 2a3834ae11c..e4ab466c000 100644 --- a/lib/http.h +++ b/lib/http.h @@ -93,11 +93,14 @@ CURLcode Curl_http_statusline(struct Curl_easy *data, struct connectdata *conn); CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, char *headp); +CURLcode Curl_transferencode(struct Curl_easy *data); CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, Curl_HttpReq httpreq, const char **teep); CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, struct dynbuf *r, Curl_HttpReq httpreq); +bool Curl_use_http_1_1plus(const struct Curl_easy *data, + const struct connectdata *conn); #ifndef CURL_DISABLE_COOKIES CURLcode Curl_http_cookies(struct Curl_easy *data, struct connectdata *conn, diff --git a/lib/http2.c b/lib/http2.c index f194c18b230..a3de607c7d2 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -146,12 +146,12 @@ static CURLcode http2_disconnect(struct Curl_easy *data, (void)data; #endif - H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n")); + H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now")); nghttp2_session_del(c->h2); Curl_safefree(c->inbuf); - H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n")); + H2BUGF(infof(data, "HTTP/2 DISCONNECT done")); return CURLE_OK; } @@ -196,11 +196,13 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn) data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); if(nread != -1) { infof(data, - "%d bytes stray data read before trying h2 connection\n", + "%d bytes stray data read before trying h2 connection", (int)nread); httpc->nread_inbuf = 0; httpc->inbuflen = nread; - (void)h2_process_pending_input(data, httpc, &result); + if(h2_process_pending_input(data, httpc, &result) < 0) + /* immediate error, considered dead */ + dead = TRUE; } else /* the read failed so let's say this is dead anyway */ @@ -350,13 +352,12 @@ static const struct Curl_handler Curl_handler_http2_ssl = { }; /* - * Store nghttp2 version info in this buffer, Prefix with a space. Return - * total length written. + * Store nghttp2 version info in this buffer. */ -int Curl_http2_ver(char *p, size_t len) +void Curl_http2_ver(char *p, size_t len) { nghttp2_info *h2 = nghttp2_version(0); - return msnprintf(p, len, "nghttp2/%s", h2->version_str); + (void)msnprintf(p, len, "nghttp2/%s", h2->version_str); } /* @@ -551,7 +552,7 @@ static int push_promise(struct Curl_easy *data, const nghttp2_push_promise *frame) { int rv; /* one of the CURL_PUSH_* defines */ - H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n", + H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!", frame->promised_stream_id)); if(data->multi->push_cb) { struct HTTP *stream; @@ -563,7 +564,7 @@ static int push_promise(struct Curl_easy *data, /* clone the parent */ struct Curl_easy *newhandle = duphandle(data); if(!newhandle) { - infof(data, "failed to duplicate handle\n"); + infof(data, "failed to duplicate handle"); rv = CURL_PUSH_DENY; /* FAIL HARD */ goto fail; } @@ -571,7 +572,7 @@ static int push_promise(struct Curl_easy *data, heads.data = data; heads.frame = frame; /* ask the application */ - H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n")); + H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!")); stream = data->req.p.http; if(!stream) { @@ -619,7 +620,7 @@ static int push_promise(struct Curl_easy *data, state with the given connection !*/ rc = Curl_multi_add_perform(data->multi, newhandle, conn); if(rc) { - infof(data, "failed to add handle to multi\n"); + infof(data, "failed to add handle to multi"); http2_stream_free(newhandle->req.p.http); newhandle->req.p.http = NULL; Curl_close(&newhandle); @@ -632,15 +633,17 @@ static int push_promise(struct Curl_easy *data, frame->promised_stream_id, newhandle); if(rv) { - infof(data, "failed to set user_data for stream %d\n", + infof(data, "failed to set user_data for stream %d", frame->promised_stream_id); DEBUGASSERT(0); rv = CURL_PUSH_DENY; goto fail; } + Curl_dyn_init(&newstream->header_recvbuf, DYN_H2_HEADERS); + Curl_dyn_init(&newstream->trailer_recvbuf, DYN_H2_TRAILERS); } else { - H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n")); + H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!")); rv = CURL_PUSH_DENY; } fail: @@ -676,21 +679,21 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, /* stream ID zero is for connection-oriented stuff */ if(frame->hd.type == NGHTTP2_SETTINGS) { uint32_t max_conn = httpc->settings.max_concurrent_streams; - H2BUGF(infof(data, "Got SETTINGS\n")); + H2BUGF(infof(data, "Got SETTINGS")); httpc->settings.max_concurrent_streams = nghttp2_session_get_remote_settings( session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); httpc->settings.enable_push = nghttp2_session_get_remote_settings( session, NGHTTP2_SETTINGS_ENABLE_PUSH); - H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d\n", + H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d", httpc->settings.max_concurrent_streams)); - H2BUGF(infof(data, "ENABLE_PUSH == %s\n", + H2BUGF(infof(data, "ENABLE_PUSH == %s", httpc->settings.enable_push?"TRUE":"false")); if(max_conn != httpc->settings.max_concurrent_streams) { /* only signal change if the value actually changed */ infof(data, - "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", + "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!", httpc->settings.max_concurrent_streams); multi_connchanged(data->multi); } @@ -700,19 +703,19 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, data_s = nghttp2_session_get_stream_user_data(session, stream_id); if(!data_s) { H2BUGF(infof(data, - "No Curl_easy associated with stream: %x\n", + "No Curl_easy associated with stream: %x", stream_id)); return 0; } stream = data_s->req.p.http; if(!stream) { - H2BUGF(infof(data_s, "No proto pointer for stream: %x\n", + H2BUGF(infof(data_s, "No proto pointer for stream: %x", stream_id)); return NGHTTP2_ERR_CALLBACK_FAILURE; } - H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n", + H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x", frame->hd.type, stream_id)); switch(frame->hd.type) { @@ -760,7 +763,8 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, ncopy); stream->nread_header_recvbuf += ncopy; - H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n", + DEBUGASSERT(stream->mem); + H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p", ncopy, stream_id, stream->mem)); stream->len -= ncopy; @@ -782,13 +786,13 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, if(nghttp2_is_fatal(h2)) return NGHTTP2_ERR_CALLBACK_FAILURE; else if(rv == CURL_PUSH_ERROROUT) { - DEBUGF(infof(data_s, "Fail the parent stream (too)\n")); + DEBUGF(infof(data_s, "Fail the parent stream (too)")); return NGHTTP2_ERR_CALLBACK_FAILURE; } } break; default: - H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n", + H2BUGF(infof(data_s, "Got frame type %x for stream %u!", frame->hd.type, stream_id)); break; } @@ -833,7 +837,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, Curl_expire(data_s, 0, EXPIRE_RUN_NOW); H2BUGF(infof(data_s, "%zu data received for stream %u " - "(%zu left in buffer %p, total %zu)\n", + "(%zu left in buffer %p, total %zu)", nread, stream_id, stream->len, stream->mem, stream->memlen)); @@ -842,7 +846,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, stream->pausedata = mem + nread; stream->pauselen = len - nread; H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" - ", stream %u\n", + ", stream %u", len - nread, stream_id)); data_s->conn->proto.httpc.pause_stream_id = stream_id; @@ -880,7 +884,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, decided to reject stream (e.g., PUSH_PROMISE). */ return 0; } - H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", + H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u", nghttp2_http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.p.http; if(!stream) @@ -895,15 +899,15 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, /* remove the entry from the hash as the stream is now gone */ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0); if(rv) { - infof(data_s, "http/2: failed to clear user_data for stream %d!\n", + infof(data_s, "http/2: failed to clear user_data for stream %d!", stream_id); DEBUGASSERT(0); } if(stream_id == httpc->pause_stream_id) { - H2BUGF(infof(data_s, "Stopped the pause stream!\n")); + H2BUGF(infof(data_s, "Stopped the pause stream!")); httpc->pause_stream_id = 0; } - H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id)); + H2BUGF(infof(data_s, "Removed stream %u hash!", stream_id)); stream->stream_id = 0; /* cleared */ } return 0; @@ -921,7 +925,7 @@ static int on_begin_headers(nghttp2_session *session, return 0; } - H2BUGF(infof(data_s, "on_begin_headers() was called\n")); + H2BUGF(infof(data_s, "on_begin_headers() was called")); if(frame->hd.type != NGHTTP2_HEADERS) { return 0; @@ -1049,7 +1053,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(stream->bodystarted) { /* This is a trailer */ - H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, + H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s", namelen, name, valuelen, value)); result = Curl_dyn_addf(&stream->trailer_recvbuf, "%.*s: %.*s\r\n", namelen, name, @@ -1082,7 +1086,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n", + H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)", stream->status_code, data_s)); return 0; } @@ -1106,7 +1110,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, + H2BUGF(infof(data_s, "h2 header: %.*s: %.*s", namelen, name, valuelen, value)); return 0; /* 0 is successful */ @@ -1156,7 +1160,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session, return NGHTTP2_ERR_DEFERRED; H2BUGF(infof(data_s, "data_source_read_callback: " - "returns %zu bytes stream %u\n", + "returns %zu bytes stream %u", nread, stream_id)); return nread; @@ -1223,7 +1227,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) (void)nghttp2_session_send(httpc->h2); if(http->stream_id == httpc->pause_stream_id) { - infof(data, "stopped the pause stream!\n"); + infof(data, "stopped the pause stream!"); httpc->pause_stream_id = 0; } } @@ -1236,7 +1240,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) int rv = nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0); if(rv) { - infof(data, "http/2: failed to clear user_data for stream %d!\n", + infof(data, "http/2: failed to clear user_data for stream %d!", http->stream_id); DEBUGASSERT(0); } @@ -1383,7 +1387,7 @@ static int h2_process_pending_input(struct Curl_easy *data, if(nread == rv) { H2BUGF(infof(data, "h2_process_pending_input: All data in connection buffer " - "processed\n")); + "processed")); httpc->inbuflen = 0; httpc->nread_inbuf = 0; } @@ -1391,7 +1395,7 @@ static int h2_process_pending_input(struct Curl_easy *data, httpc->nread_inbuf += rv; H2BUGF(infof(data, "h2_process_pending_input: %zu bytes left in connection " - "buffer\n", + "buffer", httpc->inbuflen - httpc->nread_inbuf)); } @@ -1412,7 +1416,7 @@ static int h2_process_pending_input(struct Curl_easy *data, if(should_close_session(httpc)) { struct HTTP *stream = data->req.p.http; H2BUGF(infof(data, - "h2_process_pending_input: nothing to do in this session\n")); + "h2_process_pending_input: nothing to do in this session")); if(stream->error) *err = CURLE_HTTP2; else { @@ -1456,7 +1460,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data, struct SingleRequest *k = &data->req; int rv; - H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data)); + H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)", data)); /* and attempt to send the pending frames */ rv = h2_session_send(data, h2); @@ -1495,7 +1499,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ stream->closed = FALSE; if(stream->error == NGHTTP2_REFUSED_STREAM) { - H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", + H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!", stream->stream_id)); connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ data->state.refused_stream = TRUE; @@ -1544,7 +1548,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, stream->close_handled = TRUE; - H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n")); + H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close")); return 0; } @@ -1587,7 +1591,7 @@ static int h2_session_send(struct Curl_easy *data, h2_pri_spec(data, &pri_spec); - H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n", + H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)", stream->stream_id, data)); DEBUGASSERT(stream->stream_id != -1); rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id, @@ -1611,7 +1615,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, if(should_close_session(httpc)) { H2BUGF(infof(data, - "http2_recv: nothing to do in this session\n")); + "http2_recv: nothing to do in this session")); if(conn->bits.close) { /* already marked for closure, return OK and we're done */ *err = CURLE_OK; @@ -1621,10 +1625,6 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } - if(stream->closed) - /* closed overrides paused */ - return http2_handle_stream_close(conn, data, stream, err); - /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ stream->upload_mem = NULL; @@ -1645,12 +1645,12 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, stream->nread_header_recvbuf, ncopy); stream->nread_header_recvbuf += ncopy; - H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n", + H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf", (int)ncopy)); return ncopy; } - H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u\n", + H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u", data, stream->stream_id, nghttp2_session_get_local_window_size(httpc->h2), nghttp2_session_get_stream_local_window_size(httpc->h2, @@ -1658,7 +1658,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, )); if((data->state.drain) && stream->memlen) { - H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n", + H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)", stream->memlen, stream->stream_id, stream->mem, mem)); if(mem != stream->mem) { @@ -1686,7 +1686,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, stream->pauselen -= nread; if(stream->pauselen == 0) { - H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); + H2BUGF(infof(data, "Unpaused by stream %u", stream->stream_id)); DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); httpc->pause_stream_id = 0; @@ -1704,7 +1704,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } } - H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n", + H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u", nread, stream->stream_id)); return nread; } @@ -1720,7 +1720,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, if(stream->closed) /* closed overrides paused */ return 0; - H2BUGF(infof(data, "stream %x is paused, pause id: %x\n", + H2BUGF(infof(data, "stream %x is paused, pause id: %x", stream->stream_id, httpc->pause_stream_id)); *err = CURLE_AGAIN; return -1; @@ -1758,12 +1758,12 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } - H2BUGF(infof(data, "end of stream\n")); + H2BUGF(infof(data, "end of stream")); *err = CURLE_OK; return 0; } - H2BUGF(infof(data, "nread=%zd\n", nread)); + H2BUGF(infof(data, "nread=%zd", nread)); httpc->inbuflen = nread; @@ -1772,7 +1772,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, else { nread = httpc->inbuflen - httpc->nread_inbuf; (void)nread; /* silence warning, used in debug */ - H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n", + H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd", nread)); } @@ -1781,14 +1781,14 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, } if(stream->memlen) { ssize_t retlen = stream->memlen; - H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n", + H2BUGF(infof(data, "http2_recv: returns %zd for stream %u", retlen, stream->stream_id)); stream->memlen = 0; if(httpc->pause_stream_id == stream->stream_id) { /* data for this stream is returned now, but this stream caused a pause already so we need it called again asap */ - H2BUGF(infof(data, "Data returned for PAUSED stream %u\n", + H2BUGF(infof(data, "Data returned for PAUSED stream %u", stream->stream_id)); } else if(!stream->closed) { @@ -1803,7 +1803,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, if(stream->closed) return http2_handle_stream_close(conn, data, stream, err); *err = CURLE_AGAIN; - H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", + H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u", stream->stream_id)); return -1; } @@ -1907,11 +1907,11 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, (void)sockindex; - H2BUGF(infof(data, "http2_send len=%zu\n", len)); + H2BUGF(infof(data, "http2_send len=%zu", len)); if(stream->stream_id != -1) { if(stream->close_handled) { - infof(data, "stream %d closed\n", stream->stream_id); + infof(data, "stream %d closed", stream->stream_id); *err = CURLE_HTTP2_STREAM; return -1; } @@ -1940,7 +1940,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, stream->upload_len = 0; if(should_close_session(httpc)) { - H2BUGF(infof(data, "http2_send: nothing to do in this session\n")); + H2BUGF(infof(data, "http2_send: nothing to do in this session")); *err = CURLE_HTTP2; return -1; } @@ -1953,7 +1953,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, nghttp2_session_resume_data(h2, stream->stream_id); } - H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len, + H2BUGF(infof(data, "http2_send returns %zu for stream %u", len, stream->stream_id)); return len; } @@ -2116,7 +2116,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, for(i = 0; i < nheader; ++i) { acc += nva[i].namelen + nva[i].valuelen; - H2BUGF(infof(data, "h2 header: %.*s:%.*s\n", + H2BUGF(infof(data, "h2 header: %.*s:%.*s", nva[i].namelen, nva[i].name, nva[i].valuelen, nva[i].value)); } @@ -2124,13 +2124,13 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, if(acc > MAX_ACC) { infof(data, "http2_send: Warning: The cumulative length of all " "headers exceeds %d bytes and that could cause the " - "stream to be rejected.\n", MAX_ACC); + "stream to be rejected.", MAX_ACC); } } h2_pri_spec(data, &pri_spec); - H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n", + H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)", nghttp2_session_check_request_allowed(h2), (void *)data)); switch(data->state.httpreq) { @@ -2158,20 +2158,20 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, if(stream_id < 0) { H2BUGF(infof(data, - "http2_send() nghttp2_submit_request error (%s)%d\n", + "http2_send() nghttp2_submit_request error (%s)%d", nghttp2_strerror(stream_id), stream_id)); *err = CURLE_SEND_ERROR; return -1; } - infof(data, "Using Stream ID: %x (easy handle %p)\n", + infof(data, "Using Stream ID: %x (easy handle %p)", stream_id, (void *)data); stream->stream_id = stream_id; rv = h2_session_send(data, h2); if(rv) { H2BUGF(infof(data, - "http2_send() nghttp2_session_send error (%s)%d\n", + "http2_send() nghttp2_session_send error (%s)%d", nghttp2_strerror(rv), rv)); *err = CURLE_SEND_ERROR; @@ -2179,7 +2179,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, } if(should_close_session(httpc)) { - H2BUGF(infof(data, "http2_send: nothing to do in this session\n")); + H2BUGF(infof(data, "http2_send: nothing to do in this session")); *err = CURLE_HTTP2; return -1; } @@ -2215,6 +2215,22 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS); Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS); + stream->upload_left = 0; + stream->upload_mem = NULL; + stream->upload_len = 0; + stream->mem = data->state.buffer; + stream->len = data->set.buffer_size; + + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + + httpc->pause_stream_id = 0; + httpc->drain_total = 0; + + multi_connchanged(data->multi); + /* below this point only connection related inits are done, which only needs + to be done once per connection */ + if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) return CURLE_OK; /* already done */ @@ -2230,25 +2246,13 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, return result; } - infof(data, "Using HTTP2, server supports multi-use\n"); - stream->upload_left = 0; - stream->upload_mem = NULL; - stream->upload_len = 0; - stream->mem = data->state.buffer; - stream->len = data->set.buffer_size; - - httpc->inbuflen = 0; - httpc->nread_inbuf = 0; - - httpc->pause_stream_id = 0; - httpc->drain_total = 0; + infof(data, "Using HTTP2, server supports multiplexing"); conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ conn->httpversion = 20; conn->bundle->multiuse = BUNDLE_MULTIPLEX; - infof(data, "Connection state changed (HTTP/2 confirmed)\n"); - multi_connchanged(data->multi); + infof(data, "Connection state changed (HTTP/2 confirmed)"); return CURLE_OK; } @@ -2287,7 +2291,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, stream->stream_id, data); if(rv) { - infof(data, "http/2: failed to set user_data for stream %d!\n", + infof(data, "http/2: failed to set user_data for stream %d!", stream->stream_id); DEBUGASSERT(0); } @@ -2327,7 +2331,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, } infof(data, "Copying HTTP/2 data in stream buffer to connection buffer" - " after upgrade: len=%zu\n", + " after upgrade: len=%zu", nread); if(nread) @@ -2337,15 +2341,8 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, DEBUGASSERT(httpc->nread_inbuf == 0); - /* Good enough to call it an end once the remaining payload is copied to the - * connection buffer. - * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately - * following the protocol switch other than waiting for the client-side - * connection preface. If h2_process_pending_input is invoked here to parse - * the remaining payload, stream 1 would be marked as closed too early and - * thus ignored in http2_recv (following 252790c53). - * The logic in lib/http.c and lib/transfer.c guarantees a following - * http2_recv would be invoked very soon. */ + if(-1 == h2_process_pending_input(data, httpc, &result)) + return CURLE_HTTP2; return CURLE_OK; } @@ -2378,7 +2375,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) if(rv) return CURLE_SEND_ERROR; - DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u\n", + DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u", window, stream->stream_id)); #ifdef DEBUGBUILD @@ -2387,7 +2384,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) uint32_t window2 = nghttp2_session_get_stream_local_window_size(httpc->h2, stream->stream_id); - DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u\n", + DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u", window2, stream->stream_id)); } #endif diff --git a/lib/http2.h b/lib/http2.h index 21e2c086a38..d6986d97faf 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -32,10 +32,9 @@ #define DEFAULT_MAX_CONCURRENT_STREAMS 100 /* - * Store nghttp2 version info in this buffer, Prefix with a space. Return - * total length written. + * Store nghttp2 version info in this buffer. */ -int Curl_http2_ver(char *p, size_t len); +void Curl_http2_ver(char *p, size_t len); const char *Curl_http2_strerror(uint32_t err); diff --git a/lib/http_aws_sigv4.c b/lib/http_aws_sigv4.c index a04b46a3514..02663abd63d 100644 --- a/lib/http_aws_sigv4.c +++ b/lib/http_aws_sigv4.c @@ -126,7 +126,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) tmp1 = strchr(tmp0, ':'); len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0); if(len < 1) { - infof(data, "first provider can't be empty\n"); + infof(data, "first provider can't be empty"); ret = CURLE_BAD_FUNCTION_ARGUMENT; goto fail; } @@ -145,7 +145,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) tmp1 = strchr(tmp0, ':'); len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0); if(len < 1) { - infof(data, "second provider can't be empty\n"); + infof(data, "second provider can't be empty"); ret = CURLE_BAD_FUNCTION_ARGUMENT; goto fail; } @@ -165,7 +165,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) tmp1 = strchr(tmp0, ':'); len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0); if(len < 1) { - infof(data, "region can't be empty\n"); + infof(data, "region can't be empty"); ret = CURLE_BAD_FUNCTION_ARGUMENT; goto fail; } @@ -182,7 +182,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) goto fail; } if(strlen(service) < 1) { - infof(data, "service can't be empty\n"); + infof(data, "service can't be empty"); ret = CURLE_BAD_FUNCTION_ARGUMENT; goto fail; } @@ -203,7 +203,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) tmp1 = strchr(tmp0, '.'); len = tmp1 - tmp0; if(!tmp1 || len < 1) { - infof(data, "service missing in parameters or hostname\n"); + infof(data, "service missing in parameters or hostname"); ret = CURLE_URL_MALFORMAT; goto fail; } @@ -218,7 +218,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy) tmp1 = strchr(tmp0, '.'); len = tmp1 - tmp0; if(!tmp1 || len < 1) { - infof(data, "region missing in parameters or hostname\n"); + infof(data, "region missing in parameters or hostname"); ret = CURLE_URL_MALFORMAT; goto fail; } diff --git a/lib/http_digest.c b/lib/http_digest.c index 049b232e014..34bb5a8e081 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -146,7 +146,8 @@ CURLcode Curl_output_digest(struct Curl_easy *data, tmp = strchr((char *)uripath, '?'); if(tmp) { size_t urilen = tmp - (char *)uripath; - path = (unsigned char *) aprintf("%.*s", urilen, uripath); + /* typecast is fine here since the value is always less than 32 bits */ + path = (unsigned char *) aprintf("%.*s", (int)urilen, uripath); } } if(!tmp) diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index 68cce1bbb2b..5f764dc136b 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -89,7 +89,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, neg_ctx->havenegdata = len != 0; if(!len) { if(state == GSS_AUTHSUCC) { - infof(data, "Negotiate auth restarted\n"); + infof(data, "Negotiate auth restarted"); Curl_http_auth_cleanup_negotiate(conn); } else if(state != GSS_AUTHNONE) { @@ -142,11 +142,11 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data, } if(neg_ctx->noauthpersist || - (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) { + (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) { if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) { infof(data, "Curl_output_negotiate, " - "no persistent authentication: cleanup existing context"); + "no persistent authentication: cleanup existing context"); Curl_http_auth_cleanup_negotiate(conn); } if(!neg_ctx->context) { diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index e200fdb1dae..627a11c5af1 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -100,17 +100,17 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data, } else { if(*state == NTLMSTATE_LAST) { - infof(data, "NTLM auth restarted\n"); + infof(data, "NTLM auth restarted"); Curl_http_auth_cleanup_ntlm(conn); } else if(*state == NTLMSTATE_TYPE3) { - infof(data, "NTLM handshake rejected\n"); + infof(data, "NTLM handshake rejected"); Curl_http_auth_cleanup_ntlm(conn); *state = NTLMSTATE_NONE; return CURLE_REMOTE_ACCESS_DENIED; } else if(*state >= NTLMSTATE_TYPE1) { - infof(data, "NTLM handshake failure (internal error)\n"); + infof(data, "NTLM handshake failure (internal error)"); return CURLE_REMOTE_ACCESS_DENIED; } diff --git a/lib/http_proxy.c b/lib/http_proxy.c index a3a62c1cad4..58489abec1a 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -61,7 +61,7 @@ static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex) if(!conn->bits.proxy_ssl_connected[sockindex]) { /* perform SSL initialization for this socket */ result = - Curl_ssl_connect_nonblocking(data, conn, sockindex, + Curl_ssl_connect_nonblocking(data, conn, TRUE, sockindex, &conn->bits.proxy_ssl_connected[sockindex]); if(result) /* a failed connection is marked for closure to prevent (bad) re-use or @@ -129,13 +129,13 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex) bool Curl_connect_complete(struct connectdata *conn) { return !conn->connect_state || - (conn->connect_state->tunnel_state == TUNNEL_COMPLETE); + (conn->connect_state->tunnel_state >= TUNNEL_COMPLETE); } bool Curl_connect_ongoing(struct connectdata *conn) { return conn->connect_state && - (conn->connect_state->tunnel_state != TUNNEL_COMPLETE); + (conn->connect_state->tunnel_state <= TUNNEL_COMPLETE); } /* when we've sent a CONNECT to a proxy, we should rather either wait for the @@ -148,7 +148,7 @@ int Curl_connect_getsock(struct connectdata *conn) DEBUGASSERT(conn->connect_state); http = &conn->connect_state->http_proxy; - if(http->sending) + if(http->sending == HTTPSEND_REQUEST) return GETSOCK_WRITESOCK(0); return GETSOCK_READSOCK(0); @@ -169,7 +169,7 @@ static CURLcode connect_init(struct Curl_easy *data, bool reinit) s = calloc(1, sizeof(struct http_connect_state)); if(!s) return CURLE_OUT_OF_MEMORY; - infof(data, "allocate connect buffer!\n"); + infof(data, "allocate connect buffer!"); conn->connect_state = s; Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS); @@ -202,13 +202,16 @@ static void connect_done(struct Curl_easy *data) { struct connectdata *conn = data->conn; struct http_connect_state *s = conn->connect_state; - s->tunnel_state = TUNNEL_COMPLETE; - Curl_dyn_free(&s->rcvbuf); - Curl_dyn_free(&s->req); + if(s->tunnel_state != TUNNEL_EXIT) { + s->tunnel_state = TUNNEL_EXIT; + Curl_dyn_free(&s->rcvbuf); + Curl_dyn_free(&s->req); - /* retore the protocol pointer */ - data->req.p.http = s->prot_save; - infof(data, "CONNECT phase completed!\n"); + /* retore the protocol pointer */ + data->req.p.http = s->prot_save; + s->prot_save = NULL; + infof(data, "CONNECT phase completed!"); + } } static CURLcode CONNECT_host(struct Curl_easy *data, @@ -243,11 +246,11 @@ static CURLcode CONNECT_host(struct Curl_easy *data, return CURLE_OK; } +#ifndef USE_HYPER static CURLcode CONNECT(struct Curl_easy *data, int sockindex, const char *hostname, int remote_port) -#ifndef USE_HYPER { int subversion = 0; struct SingleRequest *k = &data->req; @@ -275,7 +278,7 @@ static CURLcode CONNECT(struct Curl_easy *data, char *hostheader = NULL; char *host = NULL; - infof(data, "Establish HTTP proxy tunnel to %s:%d\n", + infof(data, "Establish HTTP proxy tunnel to %s:%d", hostname, remote_port); /* This only happens if we've looped here due to authentication @@ -297,32 +300,27 @@ static CURLcode CONNECT(struct Curl_easy *data, hostheader, TRUE); if(!result) { - const char *proxyconn = ""; - const char *useragent = ""; const char *httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; - if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection")) - proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - - if(!Curl_checkProxyheaders(data, conn, "User-Agent") && - data->set.str[STRING_USERAGENT]) - useragent = data->state.aptr.uagent; - result = Curl_dyn_addf(req, "CONNECT %s HTTP/%s\r\n" "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ + "%s", /* Proxy-Authorization */ hostheader, httpv, host?host:"", data->state.aptr.proxyuserpwd? - data->state.aptr.proxyuserpwd:"", - useragent, - proxyconn); + data->state.aptr.proxyuserpwd:""); + + if(!result && !Curl_checkProxyheaders(data, conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) + result = Curl_dyn_addf(req, "User-Agent: %s\r\n", + data->set.str[STRING_USERAGENT]); + + if(!result && !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) + result = Curl_dyn_add(req, "Proxy-Connection: Keep-Alive\r\n"); if(!result) result = Curl_add_custom_headers(data, TRUE, req); @@ -387,6 +385,7 @@ static CURLcode CONNECT(struct Curl_easy *data, k->upload_fromhere += bytes_written; return result; } + http->sending = HTTPSEND_NADA; /* if nothing left to send, continue */ } { /* READING RESPONSE PHASE */ @@ -416,7 +415,7 @@ static CURLcode CONNECT(struct Curl_easy *data, /* proxy auth was requested and there was proxy auth available, then deem this as "mere" proxy disconnect */ conn->bits.proxy_connect_closed = TRUE; - infof(data, "Proxy CONNECT connection closed\n"); + infof(data, "Proxy CONNECT connection closed"); } else { error = SELECT_ERROR; @@ -451,7 +450,7 @@ static CURLcode CONNECT(struct Curl_easy *data, r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); + infof(data, "chunk reading DONE"); s->keepon = KEEPON_DONE; /* we did the full CONNECT treatment, go COMPLETE */ s->tunnel_state = TUNNEL_COMPLETE; @@ -510,13 +509,13 @@ static CURLcode CONNECT(struct Curl_easy *data, if(s->cl) { infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T - " bytes of response-body\n", s->cl); + " bytes of response-body", s->cl); } else if(s->chunked_encoding) { CHUNKcode r; CURLcode extra; - infof(data, "Ignore chunked response-body\n"); + infof(data, "Ignore chunked response-body"); /* We set ignorebody true here since the chunked decoder function will acknowledge that. Pay attention so that this is @@ -533,7 +532,7 @@ static CURLcode CONNECT(struct Curl_easy *data, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); + infof(data, "chunk reading DONE"); s->keepon = KEEPON_DONE; /* we did the full CONNECT treatment, go to COMPLETE */ s->tunnel_state = TUNNEL_COMPLETE; @@ -579,7 +578,7 @@ static CURLcode CONNECT(struct Curl_easy *data, /* A client MUST ignore any Content-Length or Transfer-Encoding header fields received in a successful response to CONNECT. "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ - infof(data, "Ignoring Content-Length in CONNECT %03d response\n", + infof(data, "Ignoring Content-Length in CONNECT %03d response", k->httpcode); } else { @@ -595,11 +594,11 @@ static CURLcode CONNECT(struct Curl_easy *data, header fields received in a successful response to CONNECT. "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ infof(data, "Ignoring Transfer-Encoding in " - "CONNECT %03d response\n", k->httpcode); + "CONNECT %03d response", k->httpcode); } else if(Curl_compareheader(linep, "Transfer-Encoding:", "chunked")) { - infof(data, "CONNECT responded chunked\n"); + infof(data, "CONNECT responded chunked"); s->chunked_encoding = TRUE; /* init our chunky engine */ Curl_httpchunk_init(data); @@ -657,7 +656,7 @@ static CURLcode CONNECT(struct Curl_easy *data, if(data->info.httpproxycode/100 != 2) { if(s->close_connection && data->req.newurl) { conn->bits.proxy_connect_closed = TRUE; - infof(data, "Connect me again please\n"); + infof(data, "Connect me again please"); connect_done(data); } else { @@ -692,7 +691,7 @@ static CURLcode CONNECT(struct Curl_easy *data, data->state.authproxy.done = TRUE; data->state.authproxy.multipass = FALSE; - infof(data, "Proxy replied %d to CONNECT request\n", + infof(data, "Proxy replied %d to CONNECT request", data->info.httpproxycode); data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the @@ -702,6 +701,10 @@ static CURLcode CONNECT(struct Curl_easy *data, } #else /* The Hyper version of CONNECT */ +static CURLcode CONNECT(struct Curl_easy *data, + int sockindex, + const char *hostname, + int remote_port) { struct connectdata *conn = data->conn; struct hyptransfer *h = &data->hyp; @@ -740,6 +743,8 @@ static CURLcode CONNECT(struct Curl_easy *data, hyper_io_set_write(io, Curl_hyper_send); conn->sockfd = tunnelsocket; + data->state.hconnect = TRUE; + /* create an executor to poll futures */ if(!h->exec) { h->exec = hyper_executor_new(); @@ -830,16 +835,26 @@ static CURLcode CONNECT(struct Curl_easy *data, Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd)) goto error; - if(data->set.str[STRING_USERAGENT] && - *data->set.str[STRING_USERAGENT] && - data->state.aptr.uagent && - Curl_hyper_header(data, headers, data->state.aptr.uagent)) - goto error; + if(!Curl_checkProxyheaders(data, conn, "User-Agent") && + data->set.str[STRING_USERAGENT]) { + struct dynbuf ua; + Curl_dyn_init(&ua, DYN_HTTP_REQUEST); + result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n", + data->set.str[STRING_USERAGENT]); + if(result) + goto error; + if(Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua))) + goto error; + Curl_dyn_free(&ua); + } if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") && Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive")) goto error; + if(Curl_add_custom_headers(data, TRUE, headers)) + goto error; + sendtask = hyper_clientconn_send(client, req); if(!sendtask) { failf(data, "hyper_clientconn_send"); @@ -875,7 +890,6 @@ static CURLcode CONNECT(struct Curl_easy *data, goto error; if(!done) break; - fprintf(stderr, "done\n"); s->tunnel_state = TUNNEL_COMPLETE; if(h->exec) { hyper_executor_free(h->exec); @@ -897,6 +911,33 @@ static CURLcode CONNECT(struct Curl_easy *data, } while(data->req.newurl); result = CURLE_OK; + if(s->tunnel_state == TUNNEL_COMPLETE) { + data->info.httpproxycode = data->req.httpcode; + if(data->info.httpproxycode/100 != 2) { + if(conn->bits.close && data->req.newurl) { + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Connect me again please"); + connect_done(data); + } + else { + free(data->req.newurl); + data->req.newurl = NULL; + /* failure, close this connection to avoid re-use */ + streamclose(conn, "proxy CONNECT failure"); + Curl_closesocket(data, conn, conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + } + + /* to back to init state */ + s->tunnel_state = TUNNEL_INIT; + + if(!conn->bits.proxy_connect_closed) { + failf(data, "Received HTTP code %d from proxy after CONNECT", + data->req.httpcode); + result = CURLE_RECV_ERROR; + } + } + } error: free(host); free(hostheader); @@ -917,7 +958,6 @@ static CURLcode CONNECT(struct Curl_easy *data, } return result; } - #endif void Curl_connect_free(struct Curl_easy *data) diff --git a/lib/http_proxy.h b/lib/http_proxy.h index f5a4cb07cf1..cdf8de4fba8 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -65,9 +65,10 @@ struct http_connect_state { } keepon; curl_off_t cl; /* size of content to read and ignore */ enum { - TUNNEL_INIT, /* init/default/no tunnel state */ - TUNNEL_CONNECT, /* CONNECT has been sent off */ - TUNNEL_COMPLETE /* CONNECT response received completely */ + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE, /* CONNECT response received completely */ + TUNNEL_EXIT } tunnel_state; BIT(chunked_encoding); BIT(close_connection); diff --git a/lib/imap.c b/lib/imap.c index d85bcc391da..6163899bbeb 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -74,7 +74,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "select.h" #include "multiif.h" #include "url.h" @@ -414,7 +413,7 @@ static void state(struct Curl_easy *data, imapstate newstate) }; if(imapc->state != newstate) - infof(data, "IMAP %p state change from %s to %s\n", + infof(data, "IMAP %p state change from %s to %s", (void *)imapc, names[imapc->state], names[newstate]); #endif @@ -475,8 +474,8 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data, { /* Start the SSL connection */ struct imap_conn *imapc = &conn->proto.imapc; - CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, - &imapc->ssldone); + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE, + FIRSTSOCKET, &imapc->ssldone); if(!result) { if(imapc->state != IMAP_UPGRADETLS) @@ -606,7 +605,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data, result = imap_perform_login(data, conn); else { /* Other mechanisms not supported */ - infof(data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!"); result = CURLE_LOGIN_DENIED; } } @@ -861,7 +860,7 @@ static CURLcode imap_state_servergreet_resp(struct Curl_easy *data, /* PREAUTH */ struct imap_conn *imapc = &conn->proto.imapc; imapc->preauth = TRUE; - infof(data, "PREAUTH connection, already authenticated!\n"); + infof(data, "PREAUTH connection, already authenticated!"); } else if(imapcode != IMAP_RESP_OK) { failf(data, "Got unexpected imap-server response"); @@ -935,22 +934,18 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, line += wordlen; } } - else if(imapcode == IMAP_RESP_OK) { - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested */ - if(imapc->tls_supported) - /* Switch to TLS connection now */ - result = imap_perform_starttls(data, conn); - else if(data->set.use_ssl == CURLUSESSL_TRY) - /* Fallback and carry on with authentication */ - result = imap_perform_authentication(data, conn); - else { - failf(data, "STARTTLS not supported."); - result = CURLE_USE_SSL_FAILED; - } + else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + /* PREAUTH is not compatible with STARTTLS. */ + if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) { + /* Switch to TLS connection now */ + result = imap_perform_starttls(data, conn); } - else + else if(data->set.use_ssl <= CURLUSESSL_TRY) result = imap_perform_authentication(data, conn); + else { + failf(data, "STARTTLS not available."); + result = CURLE_USE_SSL_FAILED; + } } else result = imap_perform_authentication(data, conn); @@ -968,6 +963,10 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data, (void)instate; /* no use for this yet */ + /* Pipelining in response is forbidden. */ + if(data->conn->proto.imapc.pp.cache_size) + return CURLE_WEIRD_SERVER_REPLY; + if(imapcode != IMAP_RESP_OK) { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied"); @@ -1143,7 +1142,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, } if(parsed) { - infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n", + infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download", size); Curl_pgrsSetDownloadSize(data, size); @@ -1169,7 +1168,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, data->req.bytecount += chunk; infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU - " bytes are left for transfer\n", chunk, size - chunk); + " bytes are left for transfer", chunk, size - chunk); /* Have we used the entire cache or just part of it?*/ if(pp->cache_size > chunk) { @@ -1369,7 +1368,7 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done) struct imap_conn *imapc = &conn->proto.imapc; if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { - result = Curl_ssl_connect_nonblocking(data, conn, + result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, &imapc->ssldone); if(result || !imapc->ssldone) return result; @@ -1543,7 +1542,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, struct imap_conn *imapc = &conn->proto.imapc; bool selected = FALSE; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); if(data->set.opt_no_body) { /* Requested no body means no transfer */ @@ -1590,7 +1589,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); return result; } @@ -1682,11 +1681,11 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done) CURLcode result = imap_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed")); else if(*dophase_done) { result = imap_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; @@ -2017,7 +2016,7 @@ static CURLcode imap_parse_url_path(struct Curl_easy *data) return result; } - DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'\n", name, value)); + DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'", name, value)); /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and PARTIAL) stripping of the trailing slash character if it is present. diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c index 4c3e9e4dadd..b5f9b808afd 100644 --- a/lib/inet_ntop.c +++ b/lib/inet_ntop.c @@ -40,7 +40,7 @@ #define INT16SZ 2 /* - * Format an IPv4 address, more or less like inet_ntoa(). + * Format an IPv4 address, more or less like inet_ntop(). * * Returns `dst' (as a const) * Note: diff --git a/lib/krb5.c b/lib/krb5.c index c8c4b6601bc..659947d9b84 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -263,7 +263,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) } /* We pass NULL as |output_name_type| to avoid a leak. */ gss_display_name(&min, gssname, &output_buffer, NULL); - Curl_infof(data, "Trying against %s\n", output_buffer.value); + infof(data, "Trying against %s", output_buffer.value); gssresp = GSS_C_NO_BUFFER; *context = GSS_C_NO_CONTEXT; @@ -290,7 +290,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) } if(GSS_ERROR(maj)) { - Curl_infof(data, "Error creating security context\n"); + infof(data, "Error creating security context"); ret = AUTH_ERROR; break; } @@ -301,8 +301,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) result = Curl_base64_encode(data, (char *)output_buffer.value, output_buffer.length, &p, &base64_sz); if(result) { - Curl_infof(data, "base64-encoding: %s\n", - curl_easy_strerror(result)); + infof(data, "base64-encoding: %s", curl_easy_strerror(result)); ret = AUTH_ERROR; break; } @@ -327,7 +326,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) } if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') { - Curl_infof(data, "Server didn't accept auth data\n"); + infof(data, "Server didn't accept auth data"); ret = AUTH_ERROR; break; } @@ -629,7 +628,7 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn, socket_write(data, fd, cmd_buffer, cmd_size); socket_write(data, fd, "\r\n", 2); - infof(data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, + infof(data, "Send: %s%s", prot_level == PROT_PRIVATE?enc:mic, cmd_buffer); free(cmd_buffer); } @@ -738,7 +737,7 @@ static int sec_set_protection_level(struct Curl_easy *data) if(!conn->sec_complete) { infof(data, "Trying to change the protection level after the" - " completion of the data exchange.\n"); + " completion of the data exchange."); return -1; } @@ -815,13 +814,13 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn) if(mech->init) { ret = mech->init(conn->app_data); if(ret) { - infof(data, "Failed initialization for %s. Skipping it.\n", + infof(data, "Failed initialization for %s. Skipping it.", mech->name); return CURLE_FAILED_INIT; } } - infof(data, "Trying mechanism %s...\n", mech->name); + infof(data, "Trying mechanism %s...", mech->name); ret = ftp_send_command(data, "AUTH %s", mech->name); if(ret < 0) return CURLE_COULDNT_CONNECT; @@ -830,15 +829,15 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn) switch(ret) { case 504: infof(data, "Mechanism %s is not supported by the server (server " - "returned ftp code: 504).\n", mech->name); + "returned ftp code: 504).", mech->name); break; case 534: infof(data, "Mechanism %s was rejected by the server (server returned " - "ftp code: 534).\n", mech->name); + "ftp code: 534).", mech->name); break; default: if(ret/100 == 5) { - infof(data, "server does not support the security extensions\n"); + infof(data, "server does not support the security extensions"); return CURLE_USE_SSL_FAILED; } break; diff --git a/lib/ldap.c b/lib/ldap.c index ed16423026c..1d9e44cc9c2 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -296,9 +296,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) char *passwd = NULL; *done = TRUE; /* unconditionally */ - infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", + infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d", LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); - infof(data, "LDAP local: %s\n", data->state.url); + infof(data, "LDAP local: %s", data->state.url); #ifdef HAVE_LDAP_URL_PARSE rc = ldap_url_parse(data->state.url, &ludp); @@ -314,7 +314,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) /* Get the URL scheme (either ldap or ldaps) */ if(conn->given->flags & PROTOPT_SSL) ldap_ssl = 1; - infof(data, "LDAP local: trying to establish %s connection\n", + infof(data, "LDAP local: trying to establish %s connection", ldap_ssl ? "encrypted" : "cleartext"); #if defined(USE_WIN32_LDAP) @@ -366,14 +366,14 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = CURLE_SSL_CERTPROBLEM; goto quit; } - infof(data, "LDAP local: using %s CA cert '%s'\n", - (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), - ldap_ca); + infof(data, "LDAP local: using %s CA cert '%s'", + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_ca); rc = ldapssl_add_trusted_cert(ldap_ca, cert_type); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting %s CA cert: %s", - (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), - ldap_err2string(rc)); + (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), + ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } @@ -409,7 +409,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = CURLE_SSL_CERTPROBLEM; goto quit; } - infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca); + infof(data, "LDAP local: using PEM CA cert: %s", ldap_ca); rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting PEM CA cert: %s", @@ -718,7 +718,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) LDAP_TRACE(("Received %d entries\n", num)); } if(rc == LDAP_SIZELIMIT_EXCEEDED) - infof(data, "There are more than %d entries\n", num); + infof(data, "There are more than %d entries", num); if(ludp) ldap_free_urldesc(ludp); if(server) diff --git a/lib/md4.c b/lib/md4.c index c651ddf6696..e7a428fc284 100644 --- a/lib/md4.c +++ b/lib/md4.c @@ -36,8 +36,12 @@ #endif /* USE_OPENSSL */ #ifdef USE_MBEDTLS -#include <mbedtls/config.h> #include <mbedtls/version.h> +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 +#include <mbedtls/mbedtls_config.h> +#else +#include <mbedtls/config.h> +#endif #if(MBEDTLS_VERSION_NUMBER >= 0x02070000) #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS diff --git a/lib/md5.c b/lib/md5.c index 7a24fd8cf48..983ed9746ed 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -33,7 +33,8 @@ #ifdef USE_MBEDTLS #include <mbedtls/version.h> -#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \ + (MBEDTLS_VERSION_NUMBER < 0x03000000) #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS #endif #endif /* USE_MBEDTLS */ @@ -85,7 +86,7 @@ typedef mbedtls_md5_context MD5_CTX; static void MD5_Init(MD5_CTX *ctx) { #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_md5_starts(ctx); + (void) mbedtls_md5_starts(ctx); #else (void) mbedtls_md5_starts_ret(ctx); #endif @@ -96,7 +97,7 @@ static void MD5_Update(MD5_CTX *ctx, unsigned int length) { #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_md5_update(ctx, data, length); + (void) mbedtls_md5_update(ctx, data, length); #else (void) mbedtls_md5_update_ret(ctx, data, length); #endif @@ -105,7 +106,7 @@ static void MD5_Update(MD5_CTX *ctx, static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) { #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_md5_finish(ctx, digest); + (void) mbedtls_md5_finish(ctx, digest); #else (void) mbedtls_md5_finish_ret(ctx, digest); #endif diff --git a/lib/mprintf.c b/lib/mprintf.c index 52920268615..7a1aec570e5 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -1017,9 +1017,11 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, retcode = dprintf_formatf(&info, addbyter, format, ap_save); if((retcode != -1) && info.max) { /* we terminate this with a zero byte */ - if(info.max == info.length) + if(info.max == info.length) { /* we're at maximum, scrap the last letter */ info.buffer[-1] = 0; + retcode--; /* don't count the nul byte */ + } else info.buffer[0] = 0; } diff --git a/lib/mqtt.c b/lib/mqtt.c index d88fa737df6..fcd40b41e60 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -128,6 +128,10 @@ static CURLcode mqtt_send(struct Curl_easy *data, mq->sendleftovers = sendleftovers; mq->nsend = nsend; } + else { + mq->sendleftovers = NULL; + mq->nsend = 0; + } return result; } @@ -143,32 +147,197 @@ static int mqtt_getsock(struct Curl_easy *data, return GETSOCK_READSOCK(FIRSTSOCKET); } +static int mqtt_encode_len(char *buf, size_t len) +{ + unsigned char encoded; + int i; + + for(i = 0; (len > 0) && (i<4); i++) { + encoded = len % 0x80; + len /= 0x80; + if(len) + encoded |= 0x80; + buf[i] = encoded; + } + + return i; +} + +/* add the passwd to the CONNECT packet */ +static int add_passwd(const char *passwd, const size_t plen, + char *pkt, const size_t start, int remain_pos) +{ + /* magic number that need to be set properly */ + const size_t conn_flags_pos = remain_pos + 8; + if(plen > 0xffff) + return 1; + + /* set password flag */ + pkt[conn_flags_pos] |= 0x40; + + /* length of password provided */ + pkt[start] = (char)((plen >> 8) & 0xFF); + pkt[start + 1] = (char)(plen & 0xFF); + memcpy(&pkt[start + 2], passwd, plen); + return 0; +} + +/* add user to the CONN packet */ +static int add_user(const char *username, const size_t ulen, + unsigned char *pkt, const size_t start, int remain_pos) +{ + /* magic number that need to be set properly */ + const size_t conn_flags_pos = remain_pos + 8; + if(ulen > 0xffff) + return 1; + + /* set username flag */ + pkt[conn_flags_pos] |= 0x80; + /* length of username provided */ + pkt[start] = (unsigned char)((ulen >> 8) & 0xFF); + pkt[start + 1] = (unsigned char)(ulen & 0xFF); + memcpy(&pkt[start + 2], username, ulen); + return 0; +} + +/* add client ID to the CONN packet */ +static int add_client_id(const char *client_id, const size_t client_id_len, + char *pkt, const size_t start) +{ + if(client_id_len != MQTT_CLIENTID_LEN) + return 1; + pkt[start] = 0x00; + pkt[start + 1] = MQTT_CLIENTID_LEN; + memcpy(&pkt[start + 2], client_id, MQTT_CLIENTID_LEN); + return 0; +} + +/* Set initial values of CONN packet */ +static int init_connpack(char *packet, char *remain, int remain_pos) +{ + /* Fixed header starts */ + /* packet type */ + packet[0] = MQTT_MSG_CONNECT; + /* remaining length field */ + memcpy(&packet[1], remain, remain_pos); + /* Fixed header ends */ + + /* Variable header starts */ + /* protocol length */ + packet[remain_pos + 1] = 0x00; + packet[remain_pos + 2] = 0x04; + /* protocol name */ + packet[remain_pos + 3] = 'M'; + packet[remain_pos + 4] = 'Q'; + packet[remain_pos + 5] = 'T'; + packet[remain_pos + 6] = 'T'; + /* protocol level */ + packet[remain_pos + 7] = 0x04; + /* CONNECT flag: CleanSession */ + packet[remain_pos + 8] = 0x02; + /* keep-alive 0 = disabled */ + packet[remain_pos + 9] = 0x00; + packet[remain_pos + 10] = 0x3c; + /*end of variable header*/ + return remain_pos + 10; +} + static CURLcode mqtt_connect(struct Curl_easy *data) { CURLcode result = CURLE_OK; - const size_t client_id_offset = 14; - const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN; + int pos = 0; + int rc = 0; + /*remain length*/ + int remain_pos = 0; + char remain[4] = {0}; + size_t packetlen = 0; + size_t payloadlen = 0; + size_t start_user = 0; + size_t start_pwd = 0; char client_id[MQTT_CLIENTID_LEN + 1] = "curl"; const size_t clen = strlen("curl"); - char packet[32] = { - MQTT_MSG_CONNECT, /* packet type */ - 0x00, /* remaining length */ - 0x00, 0x04, /* protocol length */ - 'M','Q','T','T', /* protocol name */ - 0x04, /* protocol level */ - 0x02, /* CONNECT flag: CleanSession */ - 0x00, 0x3c, /* keep-alive 0 = disabled */ - 0x00, 0x00 /* payload1 length */ - }; - packet[1] = (packetlen - 2) & 0x7f; - packet[client_id_offset - 1] = MQTT_CLIENTID_LEN; + char *packet = NULL; + + /* extracting username from request */ + const char *username = data->state.aptr.user ? + data->state.aptr.user : ""; + const size_t ulen = strlen(username); + /* extracting password from request */ + const char *passwd = data->state.aptr.passwd ? + data->state.aptr.passwd : ""; + const size_t plen = strlen(passwd); + + payloadlen = ulen + plen + MQTT_CLIENTID_LEN + 2; + /* The plus 2 are for the MSB and LSB describing the length of the string to + * be added on the payload. Refer to spec 1.5.2 and 1.5.4 */ + if(ulen) + payloadlen += 2; + if(plen) + payloadlen += 2; + + /* getting how much occupy the remain length */ + remain_pos = mqtt_encode_len(remain, payloadlen + 10); + + /* 10 length of variable header and 1 the first byte of the fixed header */ + packetlen = payloadlen + 10 + remain_pos + 1; + + /* allocating packet */ + if(packetlen > 268435455) + return CURLE_WEIRD_SERVER_REPLY; + packet = malloc(packetlen); + if(!packet) + return CURLE_OUT_OF_MEMORY; + memset(packet, 0, packetlen); + + /* set initial values for CONN pack */ + pos = init_connpack(packet, remain, remain_pos); result = Curl_rand_hex(data, (unsigned char *)&client_id[clen], MQTT_CLIENTID_LEN - clen + 1); - memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN); - infof(data, "Using client id '%s'\n", client_id); + /* add client id */ + rc = add_client_id(client_id, strlen(client_id), packet, pos + 1); + if(rc) { + failf(data, "Client ID length mismatched: [%lu]", strlen(client_id)); + result = CURLE_WEIRD_SERVER_REPLY; + goto end; + } + infof(data, "Using client id '%s'", client_id); + + /* position where starts the user payload */ + start_user = pos + 3 + MQTT_CLIENTID_LEN; + /* position where starts the password payload */ + start_pwd = start_user + ulen; + /* if user name was provided, add it to the packet */ + if(ulen) { + start_pwd += 2; + + rc = add_user(username, ulen, + (unsigned char *)packet, start_user, remain_pos); + if(rc) { + failf(data, "Username is too large: [%lu]", ulen); + result = CURLE_WEIRD_SERVER_REPLY; + goto end; + } + } + + /* if passwd was provided, add it to the packet */ + if(plen) { + rc = add_passwd(passwd, plen, packet, start_pwd, remain_pos); + if(rc) { + failf(data, "Password is too large: [%lu]", plen); + result = CURLE_WEIRD_SERVER_REPLY; + goto end; + } + } + if(!result) result = mqtt_send(data, packet, packetlen); + +end: + if(packet) + free(packet); + Curl_safefree(data->state.aptr.user); + Curl_safefree(data->state.aptr.passwd); return result; } @@ -213,35 +382,12 @@ static CURLcode mqtt_verify_connack(struct Curl_easy *data) static CURLcode mqtt_get_topic(struct Curl_easy *data, char **topic, size_t *topiclen) { - CURLcode result = CURLE_OK; char *path = data->state.up.path; - - if(strlen(path) > 1) { - result = Curl_urldecode(data, path + 1, 0, topic, topiclen, - REJECT_NADA); - } - else { - failf(data, "Error: No topic specified."); - result = CURLE_URL_MALFORMAT; - } - return result; -} - - -static int mqtt_encode_len(char *buf, size_t len) -{ - unsigned char encoded; - int i; - - for(i = 0; (len > 0) && (i<4); i++) { - encoded = len % 0x80; - len /= 0x80; - if(len) - encoded |= 0x80; - buf[i] = encoded; - } - - return i; + if(strlen(path) > 1) + return Curl_urldecode(data, path + 1, 0, topic, topiclen, + REJECT_NADA); + failf(data, "No MQTT topic found. Forgot to URL encode it?"); + return CURLE_URL_MALFORMAT; } static CURLcode mqtt_subscribe(struct Curl_easy *data) @@ -418,7 +564,7 @@ static void mqstate(struct Curl_easy *data, struct connectdata *conn = data->conn; struct mqtt_conn *mqtt = &conn->proto.mqtt; #ifdef CURLDEBUG - infof(data, "%s (from %s) (next is %s)\n", + infof(data, "%s (from %s) (next is %s)", statenames[state], statenames[mqtt->state], (state == MQTT_FIRST)? statenames[nextstate] : ""); @@ -465,7 +611,7 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) goto MQTT_SUBACK_COMING; } else if(packet == MQTT_MSG_DISCONNECT) { - infof(data, "Got DISCONNECT\n"); + infof(data, "Got DISCONNECT"); *done = TRUE; goto end; } @@ -476,7 +622,13 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) /* -- switched state -- */ remlen = mq->remaining_length; - infof(data, "Remaining length: %zd bytes\n", remlen); + infof(data, "Remaining length: %zd bytes", remlen); + if(data->set.max_filesize && + (curl_off_t)remlen > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + result = CURLE_FILESIZE_EXCEEDED; + goto end; + } Curl_pgrsSetDownloadSize(data, remlen); data->req.bytecount = 0; data->req.size = remlen; @@ -491,12 +643,12 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) result = Curl_read(data, sockfd, (char *)pkt, rest, &nread); if(result) { if(CURLE_AGAIN == result) { - infof(data, "EEEE AAAAGAIN\n"); + infof(data, "EEEE AAAAGAIN"); } goto end; } if(!nread) { - infof(data, "server disconnected\n"); + infof(data, "server disconnected"); result = CURLE_PARTIAL_FILE; goto end; } @@ -562,7 +714,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) return result; } - infof(data, "mqtt_doing: state [%d]\n", (int) mqtt->state); + infof(data, "mqtt_doing: state [%d]", (int) mqtt->state); switch(mqtt->state) { case MQTT_FIRST: /* Read the initial byte only */ @@ -582,6 +734,10 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1); pkt[mq->npacket++] = byte; } while((byte & 0x80) && (mq->npacket < 4)); + if(nread && (byte & 0x80)) + /* MQTT supports up to 127 * 128^0 + 127 * 128^1 + 127 * 128^2 + + 127 * 128^3 bytes. server tried to send more */ + result = CURLE_WEIRD_SERVER_REPLY; if(result) break; mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL); @@ -593,7 +749,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) mqstate(data, MQTT_FIRST, MQTT_FIRST); if(mq->firstbyte == MQTT_MSG_DISCONNECT) { - infof(data, "Got DISCONNECT\n"); + infof(data, "Got DISCONNECT"); *done = TRUE; } break; diff --git a/lib/multi.c b/lib/multi.c index 1b3e261c682..85097816db5 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -169,7 +169,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state connection_id = data->conn->connection_id; infof(data, - "STATE: %s => %s handle %p; line %d (connection #%ld)\n", + "STATE: %s => %s handle %p; line %d (connection #%ld)", statename[oldstate], statename[data->mstate], (void *)data, lineno, connection_id); } @@ -562,7 +562,7 @@ static CURLcode multi_done(struct Curl_easy *data, struct connectdata *conn = data->conn; unsigned int i; - DEBUGF(infof(data, "multi_done\n")); + DEBUGF(infof(data, "multi_done")); if(data->state.done) /* Stop if multi_done() has already been called */ @@ -610,7 +610,7 @@ static CURLcode multi_done(struct Curl_easy *data, /* Stop if still used. */ CONNCACHE_UNLOCK(data); DEBUGF(infof(data, "Connection still in use %zu, " - "no more multi_done now!\n", + "no more multi_done now!", conn->easyq.size)); return CURLE_OK; } @@ -687,7 +687,7 @@ static CURLcode multi_done(struct Curl_easy *data, if(Curl_conncache_return_conn(data, conn)) { /* remember the most recently used connection */ data->state.lastconnect_id = conn->connection_id; - infof(data, "%s\n", buffer); + infof(data, "%s", buffer); } else data->state.lastconnect_id = -1; @@ -709,7 +709,6 @@ static int close_connect_only(struct Curl_easy *data, return 1; connclose(conn, "Removing connect-only easy handle"); - conn->bits.connect_only = FALSE; return 1; } @@ -1043,7 +1042,12 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, data = multi->easyp; while(data) { - int bitmap = multi_getsock(data, sockbunch); + int bitmap; +#ifdef __clang_analyzer_ + /* to prevent "The left operand of '>=' is a garbage value" warnings */ + memset(sockbunch, 0, sizeof(sockbunch)); +#endif + bitmap = multi_getsock(data, sockbunch); for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; @@ -1096,6 +1100,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi, WSANETWORKEVENTS wsa_events; DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT); #endif +#ifndef ENABLE_WAKEUP + (void)use_wakeup; +#endif if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -1176,7 +1183,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, #ifdef USE_WINSOCK long mask = 0; #endif - if(bitmap & GETSOCK_READSOCK(i)) { + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { s = sockbunch[i]; #ifdef USE_WINSOCK mask |= FD_READ|FD_ACCEPT|FD_CLOSE; @@ -1185,7 +1192,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, ufds[nfds].events = POLLIN; ++nfds; } - if(bitmap & GETSOCK_WRITESOCK(i)) { + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { s = sockbunch[i]; #ifdef USE_WINSOCK mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; @@ -1539,6 +1546,58 @@ static CURLcode multi_do_more(struct Curl_easy *data, int *complete) return result; } +/* + * Check whether a timeout occurred, and handle it if it did + */ +static bool multi_handle_timeout(struct Curl_easy *data, + struct curltime *now, + bool *stream_error, + CURLcode *result, + bool connect_timeout) +{ + timediff_t timeout_ms; + timeout_ms = Curl_timeleft(data, now, connect_timeout); + + if(timeout_ms < 0) { + /* Handle timed out */ + if(data->mstate == MSTATE_RESOLVING) + failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds", + Curl_timediff(*now, data->progress.t_startsingle)); + else if(data->mstate == MSTATE_CONNECTING) + failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds", + Curl_timediff(*now, data->progress.t_startsingle)); + else { + struct SingleRequest *k = &data->req; + if(k->size != -1) { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %" + CURL_FORMAT_CURL_OFF_T " bytes received", + Curl_timediff(*now, data->progress.t_startsingle), + k->bytecount, k->size); + } + else { + failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T + " milliseconds with %" CURL_FORMAT_CURL_OFF_T + " bytes received", + Curl_timediff(*now, data->progress.t_startsingle), + k->bytecount); + } + } + + /* Force connection closed if the connection has indeed been used */ + if(data->mstate > MSTATE_DO) { + streamclose(data->conn, "Disconnected with pending data"); + *stream_error = TRUE; + } + *result = CURLE_OPERATION_TIMEDOUT; + (void)multi_done(data, *result, TRUE); + } + + return (timeout_ms < 0); +} + /* * We are doing protocol-specific connecting and this is being called over and * over from the multi interface until the connection phase is done on @@ -1670,7 +1729,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, bool done = FALSE; CURLMcode rc; CURLcode result = CURLE_OK; - timediff_t timeout_ms; timediff_t recv_timeout_ms; timediff_t send_timeout_ms; int control; @@ -1685,7 +1743,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, rc = CURLM_OK; if(multi_ischanged(multi, TRUE)) { - DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n")); + DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!")); process_pending_handles(multi); /* multiplexed */ } @@ -1700,47 +1758,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(data->conn && (data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED)) { + /* Check for overall operation timeout here but defer handling the + * connection timeout to later, to allow for a connection to be set up + * in the window since we last checked timeout. This prevents us + * tearing down a completed connection in the case where we were slow + * to check the timeout (e.g. process descheduled during this loop). + * We set connect_timeout=FALSE to do this. */ + /* we need to wait for the connect state as only then is the start time stored, but we must not check already completed handles */ - timeout_ms = Curl_timeleft(data, nowp, - (data->mstate <= MSTATE_DO)? - TRUE:FALSE); - - if(timeout_ms < 0) { - /* Handle timed out */ - if(data->mstate == MSTATE_RESOLVING) - failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T - " milliseconds", - Curl_timediff(*nowp, data->progress.t_startsingle)); - else if(data->mstate == MSTATE_CONNECTING) - failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T - " milliseconds", - Curl_timediff(*nowp, data->progress.t_startsingle)); - else { - struct SingleRequest *k = &data->req; - if(k->size != -1) { - failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T - " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %" - CURL_FORMAT_CURL_OFF_T " bytes received", - Curl_timediff(*nowp, data->progress.t_startsingle), - k->bytecount, k->size); - } - else { - failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T - " milliseconds with %" CURL_FORMAT_CURL_OFF_T - " bytes received", - Curl_timediff(*nowp, data->progress.t_startsingle), - k->bytecount); - } - } - - /* Force connection closed if the connection has indeed been used */ - if(data->mstate > MSTATE_DO) { - streamclose(data->conn, "Disconnected with pending data"); - stream_error = TRUE; - } - result = CURLE_OPERATION_TIMEDOUT; - (void)multi_done(data, result, TRUE); + if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) { /* Skip the statemachine and go directly to error handling section. */ goto statemachine_end; } @@ -1792,7 +1819,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } else if(data->state.previouslypending) { /* this transfer comes from the pending queue so try move another */ - infof(data, "Transfer was pending, now try another\n"); + infof(data, "Transfer was pending, now try another"); process_pending_handles(data->multi); } @@ -1847,7 +1874,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, data->state.async.done = TRUE; #endif result = CURLE_OK; - infof(data, "Hostname '%s' was found in DNS cache\n", hostname); + infof(data, "Hostname '%s' was found in DNS cache", hostname); } if(!dns) @@ -2279,7 +2306,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, CURLcode ret = Curl_retry_request(data, &newurl); if(!ret) { - infof(data, "Downgrades to HTTP/1.1!\n"); + infof(data, "Downgrades to HTTP/1.1!"); streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1"); data->state.httpwant = CURL_HTTP_VERSION_1_1; /* clear the error message bit too as we ignore the one we got */ @@ -2418,6 +2445,21 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, default: return CURLM_INTERNAL_ERROR; } + + if(data->conn && + data->mstate >= MSTATE_CONNECT && + data->mstate < MSTATE_DO && + rc != CURLM_CALL_MULTI_PERFORM && + !multi_ischanged(multi, false)) { + /* We now handle stream timeouts if and only if this will be the last + * loop iteration. We only check this on the last iteration to ensure + * that if we know we have additional work to do immediately + * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before + * declaring the connection timed out as we may almost have a completed + * connection. */ + multi_handle_timeout(data, nowp, &stream_error, &result, TRUE); + } + statemachine_end: if(data->mstate < MSTATE_COMPLETED) { @@ -3339,7 +3381,7 @@ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id) rc = Curl_splayremove(multi->timetree, &data->state.timenode, &multi->timetree); if(rc) - infof(data, "Internal error removing splay node = %d\n", rc); + infof(data, "Internal error removing splay node = %d", rc); } /* Indicate that we are in the splay tree and insert the new timer expiry @@ -3386,7 +3428,7 @@ void Curl_expire_clear(struct Curl_easy *data) rc = Curl_splayremove(multi->timetree, &data->state.timenode, &multi->timetree); if(rc) - infof(data, "Internal error clearing splay node = %d\n", rc); + infof(data, "Internal error clearing splay node = %d", rc); /* flush the timeout list too */ while(list->size > 0) { @@ -3394,7 +3436,7 @@ void Curl_expire_clear(struct Curl_easy *data) } #ifdef DEBUGBUILD - infof(data, "Expire cleared (transfer %p)\n", data); + infof(data, "Expire cleared (transfer %p)", data); #endif nowp->tv_sec = 0; nowp->tv_usec = 0; diff --git a/lib/multihandle.h b/lib/multihandle.h index 96b84749fca..2e4a6ffba5b 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -153,6 +153,9 @@ struct Curl_multi { bool recheckstate; /* see Curl_multi_connchanged */ bool in_callback; /* true while executing a callback */ bool ipv6_works; +#ifdef USE_OPENSSL + bool ssl_seeded; +#endif }; #endif /* HEADER_CURL_MULTIHANDLE_H */ diff --git a/lib/netrc.c b/lib/netrc.c index 13610bb070e..0a4ae2cdcaf 100644 --- a/lib/netrc.c +++ b/lib/netrc.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -42,7 +42,8 @@ enum host_lookup_state { NOTHING, HOSTFOUND, /* the 'machine' keyword was found */ - HOSTVALID /* this is "our" machine! */ + HOSTVALID, /* this is "our" machine! */ + MACDEF }; #define NETRC_FILE_MISSING 1 @@ -84,12 +85,17 @@ static int parsenetrc(const char *host, int netrcbuffsize = (int)sizeof(netrcbuffer); while(!done && fgets(netrcbuffer, netrcbuffsize, file)) { + if(state == MACDEF) { + if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r')) + state = NOTHING; + else + continue; + } tok = strtok_r(netrcbuffer, " \t\n", &tok_buf); if(tok && *tok == '#') /* treat an initial hash as a comment line */ continue; while(tok) { - if((login && *login) && (password && *password)) { done = TRUE; break; @@ -97,7 +103,13 @@ static int parsenetrc(const char *host, switch(state) { case NOTHING: - if(strcasecompare("machine", tok)) { + if(strcasecompare("macdef", tok)) { + /* Define a macro. A macro is defined with the specified name; its + contents begin with the next .netrc line and continue until a + null line (consecutive new-line characters) is encountered. */ + state = MACDEF; + } + else if(strcasecompare("machine", tok)) { /* the next tok is the machine name, this is in itself the delimiter that starts the stuff entered for this machine, after this we need to search for 'login' and @@ -109,6 +121,11 @@ static int parsenetrc(const char *host, retcode = NETRC_SUCCESS; /* we did find our host */ } break; + case MACDEF: + if(!strlen(tok)) { + state = NOTHING; + } + break; case HOSTFOUND: if(strcasecompare(host, tok)) { /* and yes, this is our host! */ diff --git a/lib/non-ascii.c b/lib/non-ascii.c index 932cf89eef6..3b77ae98d52 100644 --- a/lib/non-ascii.c +++ b/lib/non-ascii.c @@ -31,6 +31,7 @@ #include "sendf.h" #include "urldata.h" #include "multiif.h" +#include "strerror.h" #include "curl_memory.h" /* The last #include file should be: */ @@ -104,6 +105,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, iconv_t *cd = &tmpcd; char *input_ptr, *output_ptr; size_t in_bytes, out_bytes, rc; + char ebuffer[STRERROR_LEN]; /* open an iconv conversion descriptor if necessary */ if(data) @@ -116,7 +118,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", CURL_ICONV_CODESET_OF_NETWORK, CURL_ICONV_CODESET_OF_HOST, - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } } @@ -130,7 +132,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_to_network iconv call failed with errno %i: %s", - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } #else @@ -170,6 +172,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, iconv_t *cd = &tmpcd; char *input_ptr, *output_ptr; size_t in_bytes, out_bytes, rc; + char ebuffer[STRERROR_LEN]; /* open an iconv conversion descriptor if necessary */ if(data) @@ -182,7 +185,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", CURL_ICONV_CODESET_OF_HOST, CURL_ICONV_CODESET_OF_NETWORK, - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } } @@ -196,7 +199,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data, if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "Curl_convert_from_network iconv call failed with errno %i: %s", - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } #else @@ -237,6 +240,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, char *input_ptr; char *output_ptr; size_t in_bytes, out_bytes, rc; + char ebuffer[STRERROR_LEN]; /* open an iconv conversion descriptor if necessary */ if(data) @@ -249,7 +253,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", CURL_ICONV_CODESET_OF_HOST, CURL_ICONV_CODESET_FOR_UTF8, - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } } @@ -263,7 +267,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data, if((rc == ICONV_ERROR) || (in_bytes)) { failf(data, "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", - errno, strerror(errno)); + errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer))); return CURLE_CONV_FAILED; } if(output_ptr < input_ptr) { diff --git a/lib/openldap.c b/lib/openldap.c index 0b8bc34a038..fb5e743c279 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -247,7 +247,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) #ifdef USE_SSL if(conn->handler->flags & PROTOPT_SSL) { CURLcode result; - result = Curl_ssl_connect_nonblocking(data, conn, + result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, &li->ssldone); if(result) return result; @@ -270,7 +270,8 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done) if(conn->handler->flags & PROTOPT_SSL) { /* Is the SSL handshake complete yet? */ if(!li->ssldone) { - CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE, + FIRSTSOCKET, &li->ssldone); if(result || !li->ssldone) return result; @@ -399,7 +400,7 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done) connkeep(conn, "OpenLDAP do"); - infof(data, "LDAP local: %s\n", data->state.url); + infof(data, "LDAP local: %s", data->state.url); rc = ldap_url_parse(data->state.url, &ludp); if(rc != LDAP_URL_SUCCESS) { @@ -509,7 +510,7 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf, else { /* successful */ if(code == LDAP_SIZELIMIT_EXCEEDED) - infof(data, "There are more than %d entries\n", lr->nument); + infof(data, "There are more than %d entries", lr->nument); data->req.size = data->req.bytecount; *err = CURLE_OK; ret = 0; diff --git a/lib/pingpong.c b/lib/pingpong.c index 481173995f9..84c7f51de52 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -402,7 +402,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data, clipamount = gotbytes - i; restart = TRUE; DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing " - "server response left\n", + "server response left", (int)clipamount)); } else if(keepon) { @@ -412,7 +412,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data, with it. We keep the first bytes of the line then we throw away the rest. */ infof(data, "Excessive server response line length received, " - "%zd bytes. Stripping\n", gotbytes); + "%zd bytes. Stripping", gotbytes); restart = TRUE; /* we keep 40 bytes since all our pingpong protocols are only diff --git a/lib/pop3.c b/lib/pop3.c index 9b6ea64804c..d3f3de6d49a 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -75,7 +75,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "select.h" #include "multiif.h" #include "url.h" @@ -308,7 +307,7 @@ static void state(struct Curl_easy *data, pop3state newstate) }; if(pop3c->state != newstate) - infof(data, "POP3 %p state change from %s to %s\n", + infof(data, "POP3 %p state change from %s to %s", (void *)pop3c, names[pop3c->state], names[newstate]); #endif @@ -370,8 +369,9 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data, { /* Start the SSL connection */ struct pop3_conn *pop3c = &conn->proto.pop3c; - CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, - &pop3c->ssldone); + CURLcode result = + Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, + &pop3c->ssldone); if(!result) { if(pop3c->state != POP3_UPGRADETLS) @@ -551,7 +551,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data, result = pop3_perform_user(data, conn); else { /* Other mechanisms not supported */ - infof(data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!"); result = CURLE_LOGIN_DENIED; } } @@ -740,28 +740,23 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, } } } - else if(pop3code == '+') { - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested */ - if(pop3c->tls_supported) - /* Switch to TLS connection now */ - result = pop3_perform_starttls(data, conn); - else if(data->set.use_ssl == CURLUSESSL_TRY) - /* Fallback and carry on with authentication */ - result = pop3_perform_authentication(data, conn); - else { - failf(data, "STLS not supported."); - result = CURLE_USE_SSL_FAILED; - } - } - else - result = pop3_perform_authentication(data, conn); - } else { /* Clear text is supported when CAPA isn't recognised */ - pop3c->authtypes |= POP3_TYPE_CLEARTEXT; + if(pop3code != '+') + pop3c->authtypes |= POP3_TYPE_CLEARTEXT; - result = pop3_perform_authentication(data, conn); + if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use) + result = pop3_perform_authentication(data, conn); + else if(pop3code == '+' && pop3c->tls_supported) + /* Switch to TLS connection now */ + result = pop3_perform_starttls(data, conn); + else if(data->set.use_ssl <= CURLUSESSL_TRY) + /* Fallback and carry on with authentication */ + result = pop3_perform_authentication(data, conn); + else { + failf(data, "STLS not supported."); + result = CURLE_USE_SSL_FAILED; + } } return result; @@ -776,6 +771,10 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; /* no use for this yet */ + /* Pipelining in response is forbidden. */ + if(data->conn->proto.pop3c.pp.cache_size) + return CURLE_WEIRD_SERVER_REPLY; + if(pop3code != '+') { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied"); @@ -1031,7 +1030,7 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done) struct pop3_conn *pop3c = &conn->proto.pop3c; if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) { - result = Curl_ssl_connect_nonblocking(data, conn, + result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, &pop3c->ssldone); if(result || !pop3c->ssldone) return result; @@ -1172,7 +1171,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected, struct connectdata *conn = data->conn; struct POP3 *pop3 = data->req.p.pop3; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); if(data->set.opt_no_body) { /* Requested no body means no transfer */ @@ -1191,7 +1190,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); return result; } @@ -1274,11 +1273,11 @@ static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done) CURLcode result = pop3_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed")); else if(*dophase_done) { result = pop3_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; diff --git a/lib/progress.c b/lib/progress.c index 4bcd615ebaf..f5ef6bd5269 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -377,7 +377,12 @@ static curl_off_t trspeed(curl_off_t size, /* number of bytes */ { if(us < 1) return size * 1000000; - return (curl_off_t)((long double)size/us * 1000000); + else if(size < CURL_OFF_T_MAX/1000000) + return (size * 1000000) / us; + else if(us >= 1000000) + return size / (us / 1000000); + else + return CURL_OFF_T_MAX; } /* returns TRUE if it's time to show the progress meter */ diff --git a/lib/quic.h b/lib/quic.h index 947f13edcf7..b030359ddda 100644 --- a/lib/quic.h +++ b/lib/quic.h @@ -45,7 +45,7 @@ CURLcode Curl_quic_is_connected(struct Curl_easy *data, struct connectdata *conn, int sockindex, bool *connected); -int Curl_quic_ver(char *p, size_t len); +void Curl_quic_ver(char *p, size_t len); CURLcode Curl_quic_done_sending(struct Curl_easy *data); void Curl_quic_done(struct Curl_easy *data, bool premature); bool Curl_quic_data_pending(const struct Curl_easy *data); diff --git a/lib/rand.c b/lib/rand.c index 951fedb0a9d..8f2c1ba29e7 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -87,7 +87,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) if(!seeded) { struct curltime now = Curl_now(); - infof(data, "WARNING: Using weak random seed\n"); + infof(data, "WARNING: Using weak random seed"); randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; randseed = randseed * 1103515245 + 12345; randseed = randseed * 1103515245 + 12345; diff --git a/lib/rtsp.c b/lib/rtsp.c index 007d5c50b6a..30fefb9b829 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -231,7 +231,7 @@ static CURLcode rtsp_done(struct Curl_easy *data, } if(data->set.rtspreq == RTSPREQ_RECEIVE && (data->conn->proto.rtspc.rtp_channel == -1)) { - infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); + infof(data, "Got an RTP Receive with a CSeq of %ld", CSeq_recv); } } @@ -651,7 +651,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, } /* We have the full RTP interleaved packet * Write out the header including the leading '$' */ - DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n", + DEBUGF(infof(data, "RTP write channel %d rtp_length %d", rtspc->rtp_channel, rtp_length)); result = rtp_client_write(data, &rtp[0], rtp_length + 4); if(result) { @@ -682,7 +682,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, } if(rtp_dataleft && rtp[0] == '$') { - DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft, + DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft, *readmore ? "(READMORE)" : "")); /* Store the incomplete RTP packet for a "rewind" */ diff --git a/lib/rtsp.h b/lib/rtsp.h index 1e9cb7d2c96..da11ade0438 100644 --- a/lib/rtsp.h +++ b/lib/rtsp.h @@ -22,7 +22,7 @@ * ***************************************************************************/ #ifdef USE_HYPER -#define CURL_DISABLE_RTSP +#define CURL_DISABLE_RTSP 1 #endif #ifndef CURL_DISABLE_RTSP diff --git a/lib/select.h b/lib/select.h index 4db64877bb5..19da1e774be 100644 --- a/lib/select.h +++ b/lib/select.h @@ -106,7 +106,11 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, } \ } while(0) #else +#ifdef HAVE_POLL_FINE +#define VALID_SOCK(s) ((s) >= 0) /* FD_SETSIZE is irrelevant for poll */ +#else #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) +#endif #define VERIFY_SOCK(x) do { \ if(!VALID_SOCK(x)) { \ SET_SOCKERRNO(EINVAL); \ diff --git a/lib/sendf.c b/lib/sendf.c index e41bb805f5c..14ca84bfe5b 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -236,29 +236,21 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ /* Curl_infof() is for info message along the way */ +#define MAXINFO 2048 void Curl_infof(struct Curl_easy *data, const char *fmt, ...) { + DEBUGASSERT(!strchr(fmt, '\n')); if(data && data->set.verbose) { va_list ap; size_t len; - char print_buffer[2048 + 1]; + char buffer[MAXINFO + 2]; va_start(ap, fmt); - len = mvsnprintf(print_buffer, sizeof(print_buffer), fmt, ap); - /* - * Indicate truncation of the input by replacing the last 3 characters - * with "...", and transfer the newline over in case the format had one. - */ - if(len >= sizeof(print_buffer)) { - len = strlen(fmt); - if(fmt[--len] == '\n') - msnprintf(print_buffer + (sizeof(print_buffer) - 5), 5, "...\n"); - else - msnprintf(print_buffer + (sizeof(print_buffer) - 4), 4, "..."); - } + len = mvsnprintf(buffer, MAXINFO, fmt, ap); va_end(ap); - len = strlen(print_buffer); - Curl_debug(data, CURLINFO_TEXT, print_buffer, len); + buffer[len++] = '\n'; + buffer[len] = '\0'; + Curl_debug(data, CURLINFO_TEXT, buffer, len); } } @@ -274,14 +266,14 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) size_t len; char error[CURL_ERROR_SIZE + 2]; va_start(ap, fmt); - (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); - len = strlen(error); + len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); if(data->set.errorbuffer && !data->state.errorbuf) { strcpy(data->set.errorbuffer, error); data->state.errorbuf = TRUE; /* wrote error string */ } error[len++] = '\n'; + error[len] = '\0'; Curl_debug(data, CURLINFO_TEXT, error, len); va_end(ap); } diff --git a/lib/setopt.c b/lib/setopt.c index fb8b86d474a..08827d1ef9e 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -1689,7 +1689,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_SSLCERT_BLOB: /* - * Blob that holds file name of the SSL certificate to use + * Blob that holds file content of the SSL certificate to use */ result = Curl_setblobopt(&data->set.blobs[BLOB_CERT], va_arg(param, struct curl_blob *)); @@ -1704,7 +1704,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_PROXY_SSLCERT_BLOB: /* - * Blob that holds file name of the SSL certificate to use for proxy + * Blob that holds file content of the SSL certificate to use for proxy */ result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY], va_arg(param, struct curl_blob *)); @@ -1735,7 +1735,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_SSLKEY_BLOB: /* - * Blob that holds file name of the SSL key to use + * Blob that holds file content of the SSL key to use */ result = Curl_setblobopt(&data->set.blobs[BLOB_KEY], va_arg(param, struct curl_blob *)); @@ -1750,7 +1750,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_PROXY_SSLKEY_BLOB: /* - * Blob that holds file name of the SSL key to use for proxy + * Blob that holds file content of the SSL key to use for proxy */ result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY], va_arg(param, struct curl_blob *)); @@ -1872,7 +1872,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_DOH_SSL_VERIFYPEER: /* - * Enable peer SSL verifying for DOH. + * Enable peer SSL verifying for DoH. */ data->set.doh_verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE; @@ -1911,7 +1911,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_DOH_SSL_VERIFYHOST: /* - * Enable verification of the host name in the peer certificate for DOH + * Enable verification of the host name in the peer certificate for DoH */ arg = va_arg(param, long); @@ -1955,7 +1955,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) break; case CURLOPT_DOH_SSL_VERIFYSTATUS: /* - * Enable certificate status verifying for DOH. + * Enable certificate status verifying for DoH. */ if(!Curl_ssl_cert_status_request()) { result = CURLE_NOT_BUILT_IN; diff --git a/lib/sha256.c b/lib/sha256.c index c34f97e8f6c..a2e7e413161 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -42,8 +42,9 @@ #ifdef USE_MBEDTLS #include <mbedtls/version.h> -#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) - #define HAS_RESULT_CODE_BASED_FUNCTIONS +#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \ + (MBEDTLS_VERSION_NUMBER < 0x03000000) + #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS #endif #endif /* USE_MBEDTLS */ @@ -105,8 +106,8 @@ typedef mbedtls_sha256_context SHA256_CTX; static void SHA256_Init(SHA256_CTX *ctx) { -#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_sha256_starts(ctx, 0); +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + (void) mbedtls_sha256_starts(ctx, 0); #else (void) mbedtls_sha256_starts_ret(ctx, 0); #endif @@ -116,8 +117,8 @@ static void SHA256_Update(SHA256_CTX *ctx, const unsigned char *data, unsigned int length) { -#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_sha256_update(ctx, data, length); +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + (void) mbedtls_sha256_update(ctx, data, length); #else (void) mbedtls_sha256_update_ret(ctx, data, length); #endif @@ -125,8 +126,8 @@ static void SHA256_Update(SHA256_CTX *ctx, static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx) { -#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS) - mbedtls_sha256_finish(ctx, digest); +#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS) + (void) mbedtls_sha256_finish(ctx, digest); #else (void) mbedtls_sha256_finish_ret(ctx, digest); #endif diff --git a/lib/smb.c b/lib/smb.c index 39facb267d9..fd49cf6aaf6 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -204,7 +204,7 @@ static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate) }; if(smbc->state != newstate) - infof(data, "SMB conn %p state change from %s to %s\n", + infof(data, "SMB conn %p state change from %s to %s", (void *)smbc, names[smbc->state], names[newstate]); #endif @@ -230,7 +230,7 @@ static void request_state(struct Curl_easy *data, }; if(req->state != newstate) - infof(data, "SMB request %p state change from %s to %s\n", + infof(data, "SMB request %p state change from %s to %s", (void *)req, names[req->state], names[newstate]); #endif @@ -670,7 +670,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done) #ifdef USE_SSL if((conn->handler->flags & PROTOPT_SSL)) { bool ssl_done = FALSE; - result = Curl_ssl_connect_nonblocking(data, conn, + result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, &ssl_done); if(result && result != CURLE_AGAIN) return result; diff --git a/lib/smtp.c b/lib/smtp.c index feffc05bc9d..02ddaca0a27 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -78,7 +78,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "select.h" #include "multiif.h" #include "url.h" @@ -308,7 +307,7 @@ static void state(struct Curl_easy *data, smtpstate newstate) }; if(smtpc->state != newstate) - infof(data, "SMTP %p state change from %s to %s\n", + infof(data, "SMTP %p state change from %s to %s", (void *)smtpc, names[smtpc->state], names[newstate]); #endif @@ -397,7 +396,8 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data) /* Start the SSL connection */ struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; - CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, + CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE, + FIRSTSOCKET, &smtpc->ssldone); if(!result) { @@ -484,7 +484,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data) state(data, SMTP_AUTH); else { /* Other mechanisms not supported */ - infof(data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!"); result = CURLE_LOGIN_DENIED; } } @@ -834,6 +834,10 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; /* no use for this yet */ + /* Pipelining in response is forbidden. */ + if(data->conn->proto.smtpc.pp.cache_size) + return CURLE_WEIRD_SERVER_REPLY; + if(smtpcode != 220) { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied, code %d", smtpcode); @@ -1258,7 +1262,7 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done) struct smtp_conn *smtpc = &conn->proto.smtpc; if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) { - result = Curl_ssl_connect_nonblocking(data, conn, + result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, &smtpc->ssldone); if(result || !smtpc->ssldone) return result; @@ -1455,7 +1459,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected, struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); if(data->set.opt_no_body) { /* Requested no body means no transfer */ @@ -1495,7 +1499,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); return result; } @@ -1579,11 +1583,11 @@ static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done) CURLcode result = smtp_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed")); else if(*dophase_done) { result = smtp_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; diff --git a/lib/socketpair.c b/lib/socketpair.c index 2c580ad2dec..409d2ad6671 100644 --- a/lib/socketpair.c +++ b/lib/socketpair.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2019 - 2021, 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 @@ -48,6 +48,10 @@ #endif /* !INADDR_LOOPBACK */ #endif /* !WIN32 */ +#include "nonblock.h" /* for curlx_nonblock */ +#include "timeval.h" /* needed before select.h */ +#include "select.h" /* for Curl_poll */ + /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -59,12 +63,11 @@ int Curl_socketpair(int domain, int type, int protocol, union { struct sockaddr_in inaddr; struct sockaddr addr; - } a; + } a, a2; curl_socket_t listener; curl_socklen_t addrlen = sizeof(a.inaddr); int reuse = 1; - char data[2][12]; - ssize_t dlen; + struct pollfd pfd[1]; (void)domain; (void)type; (void)protocol; @@ -85,7 +88,8 @@ int Curl_socketpair(int domain, int type, int protocol, goto error; if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1) goto error; - if(getsockname(listener, &a.addr, &addrlen) == -1) + if(getsockname(listener, &a.addr, &addrlen) == -1 || + addrlen < (int)sizeof(a.inaddr)) goto error; if(listen(listener, 1) == -1) goto error; @@ -94,18 +98,30 @@ int Curl_socketpair(int domain, int type, int protocol, goto error; if(connect(socks[0], &a.addr, sizeof(a.inaddr)) == -1) goto error; + + /* use non-blocking accept to make sure we don't block forever */ + if(curlx_nonblock(listener, TRUE) < 0) + goto error; + pfd[0].fd = listener; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + (void)Curl_poll(pfd, 1, 10*1000); /* 10 seconds */ socks[1] = accept(listener, NULL, NULL); if(socks[1] == CURL_SOCKET_BAD) goto error; /* verify that nothing else connected */ - msnprintf(data[0], sizeof(data[0]), "%p", socks); - dlen = strlen(data[0]); - if(swrite(socks[0], data[0], dlen) != dlen) + addrlen = sizeof(a.inaddr); + if(getsockname(socks[0], &a.addr, &addrlen) == -1 || + addrlen < (int)sizeof(a.inaddr)) goto error; - if(sread(socks[1], data[1], sizeof(data[1])) != dlen) + addrlen = sizeof(a2.inaddr); + if(getpeername(socks[1], &a2.addr, &addrlen) == -1 || + addrlen < (int)sizeof(a2.inaddr)) goto error; - if(memcmp(data[0], data[1], dlen)) + if(a.inaddr.sin_family != a2.inaddr.sin_family || + a.inaddr.sin_addr.s_addr != a2.inaddr.sin_addr.s_addr || + a.inaddr.sin_port != a2.inaddr.sin_port) goto error; sclose(listener); diff --git a/lib/socks.c b/lib/socks.c index 5cde4a46a12..db4c80834e3 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -99,24 +99,24 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */ } #endif -#ifndef DEBUGBUILD -#define sxstate(x,y) socksstate(x,y) -#else +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#define DEBUG_AND_VERBOSE #define sxstate(x,y) socksstate(x,y, __LINE__) +#else +#define sxstate(x,y) socksstate(x,y) #endif - /* always use this function to change state, to make debugging easier */ static void socksstate(struct Curl_easy *data, enum connect_t state -#ifdef DEBUGBUILD +#ifdef DEBUG_AND_VERBOSE , int lineno #endif ) { struct connectdata *conn = data->conn; enum connect_t oldstate = conn->cnnct.state; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#ifdef DEBUG_AND_VERBOSE /* synced with the state list in urldata.h */ static const char * const statename[] = { "INIT", @@ -146,9 +146,9 @@ static void socksstate(struct Curl_easy *data, conn->cnnct.state = state; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#ifdef DEBUG_AND_VERBOSE infof(data, - "SXSTATE: %s => %s conn %p; line %d\n", + "SXSTATE: %s => %s conn %p; line %d", statename[oldstate], statename[conn->cnnct.state], conn, lineno); #endif @@ -214,10 +214,10 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, /* SOCKS4 can only do IPv4, insist! */ conn->ip_version = CURL_IPRESOLVE_V4; if(conn->bits.httpproxy) - infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d", protocol4a ? "a" : "", hostname, remote_port); - infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); + infof(data, "SOCKS4 communication to %s:%d", hostname, remote_port); /* * Compose socks4 request @@ -244,7 +244,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, return CURLPX_RESOLVE_HOST; else if(rc == CURLRESOLV_PENDING) { sxstate(data, CONNECT_RESOLVING); - infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname); + infof(data, "SOCKS4 non-blocking resolve of %s", hostname); return CURLPX_OK; } sxstate(data, CONNECT_RESOLVED); @@ -264,7 +264,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, data->state.async.dns = dns; data->state.async.done = TRUE; #endif - infof(data, "Hostname '%s' was found\n", hostname); + infof(data, "Hostname '%s' was found", hostname); sxstate(data, CONNECT_RESOLVED); } else { @@ -279,18 +279,21 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, CONNECT_RESOLVED: case CONNECT_RESOLVED: { struct Curl_addrinfo *hp = NULL; - char buf[64]; /* * We cannot use 'hostent' as a struct that Curl_resolv() returns. It * returns a Curl_addrinfo pointer that may not always look the same. */ - if(dns) + if(dns) { hp = dns->addr; - if(hp) { - Curl_printable_address(hp, buf, sizeof(buf)); - if(hp->ai_family == AF_INET) { + /* scan for the first IPv4 address */ + while(hp && (hp->ai_family != AF_INET)) + hp = hp->ai_next; + + if(hp) { struct sockaddr_in *saddr_in; + char buf[64]; + Curl_printable_address(hp, buf, sizeof(buf)); saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0]; @@ -298,20 +301,19 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2]; socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3]; - infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf); - } - else { - hp = NULL; /* fail! */ - failf(data, "SOCKS4 connection to %s not supported", buf); - } + infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)", buf); - Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + } + else + failf(data, "SOCKS4 connection to %s not supported", hostname); } - if(!hp) { + else failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", hostname); + + if(!hp) return CURLPX_RESOLVE_HOST; - } } /* FALLTHROUGH */ CONNECT_REQ_INIT: @@ -435,7 +437,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, /* Result */ switch(socksreq[1]) { case 90: - infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":""); + infof(data, "SOCKS4%s request granted.", protocol4a?"a":""); break; case 91: failf(data, @@ -528,19 +530,19 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, switch(sx->state) { case CONNECT_SOCKS_INIT: if(conn->bits.httpproxy) - infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n", + infof(data, "SOCKS5: connecting to HTTP proxy %s port %d", hostname, remote_port); /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ if(!socks5_resolve_local && hostname_len > 255) { infof(data, "SOCKS5: server resolving disabled for hostnames of " - "length > 255 [actual len=%zu]\n", hostname_len); + "length > 255 [actual len=%zu]", hostname_len); socks5_resolve_local = TRUE; } if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) infof(data, - "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n", + "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu", auth); if(!(auth & CURLAUTH_BASIC)) /* disable username/password auth */ @@ -778,7 +780,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, data->state.async.dns = dns; data->state.async.done = TRUE; #endif - infof(data, "SOCKS5: hostname '%s' found\n", hostname); + infof(data, "SOCKS5: hostname '%s' found", hostname); } if(!dns) { @@ -820,7 +822,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; } - infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest); + infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)", dest); } #ifdef ENABLE_IPV6 else if(hp->ai_family == AF_INET6) { @@ -834,7 +836,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; } - infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest); + infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)", dest); } #endif else { @@ -858,7 +860,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, socksreq[len++] = (char) hostname_len; /* one byte address length */ memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */ len += hostname_len; - infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n", + infof(data, "SOCKS5 connect to %s:%d (remotely resolved)", hostname, remote_port); } /* FALLTHROUGH */ @@ -1022,7 +1024,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, } sxstate(data, CONNECT_DONE); } - infof(data, "SOCKS5 request granted.\n"); + infof(data, "SOCKS5 request granted."); *done = TRUE; return CURLPX_OK; /* Proxy was successful! */ diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index 10b942a984b..34bfa37d7f6 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -328,7 +328,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, user[gss_send_token.length] = '\0'; gss_release_name(&gss_status, &gss_client_name); gss_release_buffer(&gss_status, &gss_send_token); - infof(data, "SOCKS5 server authenticated user %s with GSS-API.\n",user); + infof(data, "SOCKS5 server authenticated user %s with GSS-API.",user); free(user); user = NULL; @@ -344,7 +344,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, else if(gss_ret_flags & GSS_C_INTEG_FLAG) gss_enc = 1; - infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + infof(data, "SOCKS5 server supports GSS-API %s data protection.", (gss_enc == 0)?"no":((gss_enc==1)?"integrity":"confidentiality")); /* force for the moment to no data protection */ gss_enc = 0; @@ -518,7 +518,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, (void)curlx_nonblock(sock, TRUE); - infof(data, "SOCKS5 access with%s protection granted.\n", + infof(data, "SOCKS5 access with%s protection granted.", (socksreq[0] == 0)?"out GSS-API data": ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index 813c6be574e..cb225b9b5aa 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -327,7 +327,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, failf(data, "Failed to determine user name."); return CURLE_COULDNT_CONNECT; } - infof(data, "SOCKS5 server authenticated user %s with GSS-API.\n", + infof(data, "SOCKS5 server authenticated user %s with GSS-API.", names.sUserName); s_pSecFn->FreeContextBuffer(names.sUserName); @@ -343,7 +343,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, else if(sspi_ret_flags & ISC_REQ_INTEGRITY) gss_enc = 1; - infof(data, "SOCKS5 server supports GSS-API %s data protection.\n", + infof(data, "SOCKS5 server supports GSS-API %s data protection.", (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") ); /* force to no data protection, avoid encryption/decryption for now */ gss_enc = 0; @@ -591,7 +591,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, } (void)curlx_nonblock(sock, TRUE); - infof(data, "SOCKS5 access with%s protection granted.\n", + infof(data, "SOCKS5 access with%s protection granted.", (socksreq[0] == 0)?"out GSS-API data": ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality")); diff --git a/lib/strdup.c b/lib/strdup.c index 9af47ea4734..85cf33b3edb 100644 --- a/lib/strdup.c +++ b/lib/strdup.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -24,6 +24,10 @@ #include <curl/curl.h> +#ifdef WIN32 +#include <wchar.h> +#endif + #include "strdup.h" #include "curl_memory.h" @@ -50,6 +54,28 @@ char *curlx_strdup(const char *str) } #endif +#ifdef WIN32 +/*************************************************************************** + * + * Curl_wcsdup(source) + * + * Copies the 'source' wchar string to a newly allocated buffer (that is + * returned). + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +wchar_t *Curl_wcsdup(const wchar_t *src) +{ + size_t length = wcslen(src); + + if(length > (SIZE_T_MAX / sizeof(wchar_t)) - 1) + return (wchar_t *)NULL; /* integer overflow */ + + return (wchar_t *)Curl_memdup(src, (length + 1) * sizeof(wchar_t)); +} +#endif + /*************************************************************************** * * Curl_memdup(source, length) diff --git a/lib/strdup.h b/lib/strdup.h index 0936956f898..8c8a6f20e1c 100644 --- a/lib/strdup.h +++ b/lib/strdup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -26,6 +26,9 @@ #ifndef HAVE_STRDUP extern char *curlx_strdup(const char *str); #endif +#ifdef WIN32 +wchar_t* Curl_wcsdup(const wchar_t* src); +#endif void *Curl_memdup(const void *src, size_t buffer_length); void *Curl_saferealloc(void *ptr, size_t size); diff --git a/lib/strerror.c b/lib/strerror.c index 5298a0d76c1..431ff1c2fb0 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -188,8 +188,8 @@ curl_easy_strerror(CURLcode error) case CURLE_UNKNOWN_OPTION: return "An unknown option was passed in to libcurl"; - case CURLE_TELNET_OPTION_SYNTAX : - return "Malformed telnet option"; + case CURLE_SETOPT_OPTION_SYNTAX : + return "Malformed option provided in a setopt"; case CURLE_GOT_NOTHING: return "Server returned nothing (no headers, no data)"; @@ -731,6 +731,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) max = buflen - 1; *buf = '\0'; + /* !checksrc! disable STRERROR 2 */ #if defined(WIN32) || defined(_WIN32_WCE) #if defined(WIN32) /* 'sys_nerr' is the maximum errno number, it is not widely portable */ diff --git a/lib/telnet.c b/lib/telnet.c index fdd137fb0c0..a81bb81c367 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -268,9 +268,9 @@ static void printoption(struct Curl_easy *data, if(data->set.verbose) { if(cmd == CURL_IAC) { if(CURL_TELCMD_OK(option)) - infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); + infof(data, "%s IAC %s", direction, CURL_TELCMD(option)); else - infof(data, "%s IAC %d\n", direction, option); + infof(data, "%s IAC %d", direction, option); } else { const char *fmt = (cmd == CURL_WILL) ? "WILL" : @@ -287,12 +287,12 @@ static void printoption(struct Curl_easy *data, opt = NULL; if(opt) - infof(data, "%s %s %s\n", direction, fmt, opt); + infof(data, "%s %s %s", direction, fmt, opt); else - infof(data, "%s %s %d\n", direction, fmt, option); + infof(data, "%s %s %d", direction, fmt, option); } else - infof(data, "%s %d %d\n", direction, cmd, option); + infof(data, "%s %d %d", direction, cmd, option); } } } @@ -765,8 +765,6 @@ static void printsub(struct Curl_easy *data, break; } } - if(direction) - infof(data, "\n"); } } @@ -834,7 +832,7 @@ static CURLcode check_telnet_options(struct Curl_easy *data) tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; else { failf(data, "Syntax error in telnet option: %s", head->data); - result = CURLE_TELNET_OPTION_SYNTAX; + result = CURLE_SETOPT_OPTION_SYNTAX; break; } continue; @@ -855,7 +853,7 @@ static CURLcode check_telnet_options(struct Curl_easy *data) break; } failf(data, "Syntax error in telnet option: %s", head->data); - result = CURLE_TELNET_OPTION_SYNTAX; + result = CURLE_SETOPT_OPTION_SYNTAX; break; } @@ -922,12 +920,17 @@ static void suboption(struct Curl_easy *data) size_t tmplen = (strlen(v->data) + 1); /* Add the variable only if it fits */ if(len + tmplen < (int)sizeof(temp)-6) { - if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) { - msnprintf((char *)&temp[len], sizeof(temp) - len, - "%c%s%c%s", CURL_NEW_ENV_VAR, varname, - CURL_NEW_ENV_VALUE, varval); - len += tmplen; - } + int rv; + char sep[2] = ""; + varval[0] = 0; + rv = sscanf(v->data, "%127[^,]%1[,]%127s", varname, sep, varval); + if(rv == 1) + len += msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%s", CURL_NEW_ENV_VAR, varname); + else if(rv >= 2) + len += msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%s%c%s", CURL_NEW_ENV_VAR, varname, + CURL_NEW_ENV_VALUE, varval); } } msnprintf((char *)&temp[len], sizeof(temp) - len, diff --git a/lib/tftp.c b/lib/tftp.c index 11150af3614..aae997d0f1a 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -239,7 +239,7 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state) infof(state->data, "set timeouts for state %d; Total % " CURL_FORMAT_CURL_OFF_T - ", retry %d maxtry %d\n", + ", retry %d maxtry %d", (int)state->state, timeout_ms, state->retry_time, state->retry_max); /* init RX time */ @@ -325,7 +325,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, return CURLE_TFTP_ILLEGAL; } - infof(data, "got option=(%s) value=(%s)\n", option, value); + infof(data, "got option=(%s) value=(%s)", option, value); if(checkprefix(option, TFTP_OPTION_BLKSIZE)) { long blksize; @@ -356,14 +356,14 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, } state->blksize = (int)blksize; - infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK", + infof(data, "%s (%d) %s (%d)", "blksize parsed from OACK", state->blksize, "requested", state->requested_blksize); } else if(checkprefix(option, TFTP_OPTION_TSIZE)) { long tsize = 0; tsize = strtol(value, NULL, 10); - infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize); + infof(data, "%s (%ld)", "tsize parsed from OACK", tsize); /* tsize should be ignored on upload: Who cares about the size of the remote file? */ @@ -397,7 +397,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state, #ifndef CURL_DISABLE_VERBOSE_STRINGS struct Curl_easy *data = state->data; - infof(data, "%s\n", "Connected for transmit"); + infof(data, "%s", "Connected for transmit"); #endif state->state = TFTP_STATE_TX; result = tftp_set_timeouts(state); @@ -413,7 +413,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state, #ifndef CURL_DISABLE_VERBOSE_STRINGS struct Curl_easy *data = state->data; - infof(data, "%s\n", "Connected for receive"); + infof(data, "%s", "Connected for receive"); #endif state->state = TFTP_STATE_RX; result = tftp_set_timeouts(state); @@ -596,12 +596,12 @@ static CURLcode tftp_rx(struct tftp_state_data *state, else if(state->block == rblock) { /* This is the last recently received block again. Log it and ACK it again. */ - infof(data, "Received last DATA packet block %d again.\n", rblock); + infof(data, "Received last DATA packet block %d again.", rblock); } else { /* totally unexpected, just log it */ infof(data, - "Received unexpected DATA packet block %d, expecting block %d\n", + "Received unexpected DATA packet block %d, expecting block %d", rblock, NEXT_BLOCKNUM(state->block)); break; } @@ -653,7 +653,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state, /* Increment the retry count and fail if over the limit */ state->retries++; infof(data, - "Timeout waiting for block %d ACK. Retries = %d\n", + "Timeout waiting for block %d ACK. Retries = %d", NEXT_BLOCKNUM(state->block), state->retries); if(state->retries > state->retry_max) { state->error = TFTP_ERR_TIMEOUT; @@ -720,11 +720,11 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) /* There's a bug in tftpd-hpa that causes it to send us an ack for * 65535 when the block number wraps to 0. So when we're expecting * 0, also accept 65535. See - * http://syslinux.zytor.com/archives/2010-September/015253.html + * https://www.syslinux.org/archives/2010-September/015612.html * */ !(state->block == 0 && rblock == 65535)) { /* This isn't the expected block. Log it and up the retry counter */ - infof(data, "Received ACK for block %d, expecting %d\n", + infof(data, "Received ACK for block %d, expecting %d", rblock, state->block); state->retries++; /* Bail out if over the maximum */ @@ -797,7 +797,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) /* Increment the retry counter and log the timeout */ state->retries++; infof(data, "Timeout waiting for block %d ACK. " - " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries); + " Retries = %d", NEXT_BLOCKNUM(state->block), state->retries); /* Decide if we've had enough */ if(state->retries > state->retry_max) { state->error = TFTP_ERR_TIMEOUT; @@ -906,22 +906,22 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state, switch(state->state) { case TFTP_STATE_START: - DEBUGF(infof(data, "TFTP_STATE_START\n")); + DEBUGF(infof(data, "TFTP_STATE_START")); result = tftp_send_first(state, event); break; case TFTP_STATE_RX: - DEBUGF(infof(data, "TFTP_STATE_RX\n")); + DEBUGF(infof(data, "TFTP_STATE_RX")); result = tftp_rx(state, event); break; case TFTP_STATE_TX: - DEBUGF(infof(data, "TFTP_STATE_TX\n")); + DEBUGF(infof(data, "TFTP_STATE_TX")); result = tftp_tx(state, event); break; case TFTP_STATE_FIN: - infof(data, "%s\n", "TFTP finished"); + infof(data, "%s", "TFTP finished"); break; default: - DEBUGF(infof(data, "STATE: %d\n", state->state)); + DEBUGF(infof(data, "STATE: %d", state->state)); failf(data, "%s", "Internal state machine error"); result = CURLE_TFTP_ILLEGAL; break; @@ -1153,7 +1153,7 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data) size_t strn = state->rbytes - 4; state->error = (tftp_error_t)error; if(tftp_strnlen(str, strn) < strn) - infof(data, "TFTP error: %s\n", str); + infof(data, "TFTP error: %s", str); break; } case TFTP_EVENT_ACK: @@ -1288,7 +1288,7 @@ static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done) result = tftp_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } else if(!result) { /* The multi code doesn't have this logic for the DOING state so we @@ -1325,7 +1325,7 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done) tftp_multi_statemach(data, dophase_done); if(*dophase_done) - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); return result; } diff --git a/lib/transfer.c b/lib/transfer.c index bca4e548fae..3e650b5b9e5 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -188,7 +188,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, /* at this point we already verified that the callback exists so we compile and store the trailers buffer, then proceed */ infof(data, - "Moving trailers state machine from initialized to sending.\n"); + "Moving trailers state machine from initialized to sending."); data->state.trailers_state = TRAILERS_SENDING; Curl_dyn_init(&data->state.trailers_buf, DYN_TRAILERS); @@ -211,7 +211,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, curl_slist_free_all(trailers); return result; } - infof(data, "Successfully compiled trailers.\r\n"); + infof(data, "Successfully compiled trailers."); curl_slist_free_all(trailers); } #endif @@ -376,7 +376,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, data->set.trailer_callback = NULL; /* mark the transfer as done */ data->req.upload_done = TRUE; - infof(data, "Signaling end of chunked upload after trailers.\n"); + infof(data, "Signaling end of chunked upload after trailers."); } else #endif @@ -385,7 +385,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes, /* mark this as done once this chunk is transferred */ data->req.upload_done = TRUE; infof(data, - "Signaling end of chunked upload via terminating chunk.\n"); + "Signaling end of chunked upload via terminating chunk."); } if(added_crlf) @@ -463,7 +463,7 @@ CURLcode Curl_readrewind(struct Curl_easy *data) err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD, data->set.ioctl_client); Curl_set_in_callback(data, false); - infof(data, "the ioctl callback returned %d\n", (int)err); + infof(data, "the ioctl callback returned %d", (int)err); if(err) { failf(data, "ioctl callback returned error %d", (int)err); @@ -530,7 +530,7 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc) default: if(timeofdoc <= data->set.timevalue) { infof(data, - "The requested document is not new enough\n"); + "The requested document is not new enough"); data->info.timecond = TRUE; return FALSE; } @@ -538,7 +538,7 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc) case CURL_TIMECOND_IFUNMODSINCE: if(timeofdoc >= data->set.timevalue) { infof(data, - "The requested document is not old enough\n"); + "The requested document is not old enough"); data->info.timecond = TRUE; return FALSE; } @@ -615,7 +615,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, else { /* read nothing but since we wanted nothing we consider this an OK situation to proceed from */ - DEBUGF(infof(data, "readwrite_data: we're done!\n")); + DEBUGF(infof(data, "readwrite_data: we're done!")); nread = 0; } @@ -638,10 +638,10 @@ static CURLcode readwrite_data(struct Curl_easy *data, server closed the connection and we bail out from this! */ #ifdef USE_NGHTTP2 if(is_http2 && !nread) - DEBUGF(infof(data, "nread == 0, stream closed, bailing\n")); + DEBUGF(infof(data, "nread == 0, stream closed, bailing")); else #endif - DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n")); + DEBUGF(infof(data, "nread <= 0, server closed connection, bailing")); k->keepon &= ~KEEP_RECV; break; } @@ -684,7 +684,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, infof(data, "Excess found:" " excess = %zd" - " url = %s (zero-length body)\n", + " url = %s (zero-length body)", nread, data->state.up.path); } @@ -764,7 +764,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, written to the client. */ if(conn->chunk.datasize) { infof(data, "Leftovers after chunking: % " - CURL_FORMAT_CURL_OFF_T "u bytes\n", + CURL_FORMAT_CURL_OFF_T "u bytes", conn->chunk.datasize); } } @@ -775,7 +775,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, /* Account for body content stored in the header buffer */ if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) { size_t headlen = Curl_dyn_len(&data->state.headerb); - DEBUGF(infof(data, "Increasing bytecount by %zu\n", headlen)); + DEBUGF(infof(data, "Increasing bytecount by %zu", headlen)); k->bytecount += headlen; } @@ -789,7 +789,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, " excess = %zu" ", size = %" CURL_FORMAT_CURL_OFF_T ", maxdownload = %" CURL_FORMAT_CURL_OFF_T - ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n", + ", bytecount = %" CURL_FORMAT_CURL_OFF_T, excess, k->size, k->maxdownload, k->bytecount); connclose(conn, "excess found in a read"); } @@ -898,7 +898,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, /* When we've read the entire thing and the close bit is set, the server may now close the connection. If there's now any kind of sending going on from our side, we need to stop that immediately. */ - infof(data, "we are done reading and this is set to close, stop send\n"); + infof(data, "we are done reading and this is set to close, stop send"); k->keepon &= ~KEEP_SEND; /* no writing anymore either */ } @@ -923,7 +923,7 @@ CURLcode Curl_done_sending(struct Curl_easy *data, return CURLE_OK; } -#if defined(WIN32) && !defined(USE_LWIPSOCK) +#if defined(WIN32) && defined(USE_WINSOCK) #ifndef SIO_IDEAL_SEND_BACKLOG_QUERY #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B #endif @@ -1128,7 +1128,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, (k->writebytecount == data->state.infilesize)) { /* we have sent all data we were supposed to */ k->upload_done = TRUE; - infof(data, "We are completely uploaded and fine\n"); + infof(data, "We are completely uploaded and fine"); } if(k->upload_present != bytes_written) { @@ -1199,7 +1199,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, if(data->state.drain) { select_res |= CURL_CSELECT_IN; - DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n")); + DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data")); } if(!select_res) /* Call for select()/poll() only, if read/write/error @@ -1212,8 +1212,12 @@ CURLcode Curl_readwrite(struct connectdata *conn, } #ifdef USE_HYPER - if(conn->datastream) - return conn->datastream(data, conn, &didwhat, done, select_res); + if(conn->datastream) { + result = conn->datastream(data, conn, &didwhat, done, select_res); + if(result || *done) + return result; + } + else { #endif /* We go ahead and do a read if we have a readable socket or if the stream was rewound (in which case we have data in a @@ -1232,6 +1236,9 @@ CURLcode Curl_readwrite(struct connectdata *conn, if(result) return result; } +#ifdef USE_HYPER + } +#endif k->now = Curl_now(); if(!didwhat) { @@ -1256,7 +1263,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, k->exp100 = EXP100_SEND_DATA; k->keepon |= KEEP_SEND; Curl_expire_done(data, EXPIRE_100_TIMEOUT); - infof(data, "Done waiting for 100-continue\n"); + infof(data, "Done waiting for 100-continue"); } } } @@ -1632,7 +1639,8 @@ CURLcode Curl_follow(struct Curl_easy *data, DEBUGASSERT(data->state.uh); uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : - ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) ); + ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) | + CURLU_ALLOW_SPACE); if(uc) { if(type != FOLLOW_FAKE) return Curl_uc_to_curlcode(uc); @@ -1671,7 +1679,7 @@ CURLcode Curl_follow(struct Curl_easy *data, data->state.url = newurl; data->state.url_alloc = TRUE; - infof(data, "Issue another request to this URL: '%s'\n", data->state.url); + infof(data, "Issue another request to this URL: '%s'", data->state.url); /* * We get here when the HTTP code is 300-399 (and 401). We need to perform @@ -1714,7 +1722,7 @@ CURLcode Curl_follow(struct Curl_easy *data, || data->state.httpreq == HTTPREQ_POST_FORM || data->state.httpreq == HTTPREQ_POST_MIME) && !(data->set.keep_post & CURL_REDIR_POST_301)) { - infof(data, "Switch from POST to GET\n"); + infof(data, "Switch from POST to GET"); data->state.httpreq = HTTPREQ_GET; } break; @@ -1739,7 +1747,7 @@ CURLcode Curl_follow(struct Curl_easy *data, || data->state.httpreq == HTTPREQ_POST_FORM || data->state.httpreq == HTTPREQ_POST_MIME) && !(data->set.keep_post & CURL_REDIR_POST_302)) { - infof(data, "Switch from POST to GET\n"); + infof(data, "Switch from POST to GET"); data->state.httpreq = HTTPREQ_GET; } break; @@ -1757,7 +1765,7 @@ CURLcode Curl_follow(struct Curl_easy *data, !(data->set.keep_post & CURL_REDIR_POST_303))) { data->state.httpreq = HTTPREQ_GET; data->set.upload = false; - infof(data, "Switch to %s\n", + infof(data, "Switch to %s", data->set.opt_no_body?"HEAD":"GET"); } break; @@ -1818,7 +1826,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) to issue again, but the nghttp2 API can deliver the message to other streams as well, which is why this adds the check the data counters too. */ - infof(data, "REFUSED_STREAM, retrying a fresh connect\n"); + infof(data, "REFUSED_STREAM, retrying a fresh connect"); data->state.refused_stream = FALSE; /* clear again */ retry = TRUE; } @@ -1830,8 +1838,8 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) data->state.retrycount = 0; return CURLE_SEND_ERROR; } - infof(data, "Connection died, retrying a fresh connect\ -(retry count: %d)\n", data->state.retrycount); + infof(data, "Connection died, retrying a fresh connect (retry count: %d)", + data->state.retrycount); *url = strdup(data->state.url); if(!*url) return CURLE_OUT_OF_MEMORY; diff --git a/lib/url.c b/lib/url.c index 1ee38af0d56..37b6c0e844b 100644 --- a/lib/url.c +++ b/lib/url.c @@ -62,6 +62,14 @@ #ifdef USE_LIBIDN2 #include <idn2.h> +#if defined(WIN32) && defined(UNICODE) +#define IDN2_LOOKUP(name, host, flags) \ + idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags) +#else +#define IDN2_LOOKUP(name, host, flags) \ + idn2_lookup_ul((const char *)name, (char **)host, flags) +#endif + #elif defined(USE_WIN32_IDN) /* prototype for curl_win32_idn_to_ascii() */ bool curl_win32_idn_to_ascii(const char *in, char **out); @@ -92,7 +100,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "speedcheck.h" #include "warnless.h" #include "non-ascii.h" -#include "inet_pton.h" #include "getinfo.h" #include "urlapi-int.h" #include "system_win32.h" @@ -726,7 +733,16 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn) { DEBUGASSERT(conn); DEBUGASSERT(data); - infof(data, "Closing connection %ld\n", conn->connection_id); + infof(data, "Closing connection %ld", conn->connection_id); + +#ifndef USE_HYPER + if(conn->connect_state && conn->connect_state->prot_save) { + /* If this was closed with a CONNECT in progress, cleanup this temporary + struct arrangement */ + data->req.p.http = NULL; + Curl_safefree(conn->connect_state->prot_save); + } +#endif /* possible left-overs from the async name resolvers */ Curl_resolver_cancel(data); @@ -824,7 +840,7 @@ CURLcode Curl_disconnect(struct Curl_easy *data, * are other users of it */ if(CONN_INUSE(conn) && !dead_connection) { - DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn))); + DEBUGF(infof(data, "Curl_disconnect when inuse: %zu", CONN_INUSE(conn))); return CURLE_OK; } @@ -957,7 +973,7 @@ static bool conn_maxage(struct Curl_easy *data, idletime /= 1000; /* integer seconds is fine */ if(idletime > data->set.maxage_conn) { - infof(data, "Too old connection (%ld seconds), disconnect it\n", + infof(data, "Too old connection (%ld seconds), disconnect it", idletime); return TRUE; } @@ -1006,7 +1022,7 @@ static bool extract_if_dead(struct connectdata *conn, } if(dead) { - infof(data, "Connection %ld seems to be dead!\n", conn->connection_id); + infof(data, "Connection %ld seems to be dead!", conn->connection_id); Curl_conncache_remove_conn(data, conn, FALSE); return TRUE; } @@ -1122,7 +1138,7 @@ ConnectionExists(struct Curl_easy *data, /* Max pipe length is zero (unlimited) for multiplexed connections */ struct Curl_llist_element *curr; - infof(data, "Found bundle for host %s: %p [%s]\n", + infof(data, "Found bundle for host %s: %p [%s]", hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? "can multiplex" : "serially")); @@ -1130,22 +1146,22 @@ ConnectionExists(struct Curl_easy *data, if(canmultiplex) { if(bundle->multiuse == BUNDLE_UNKNOWN) { if(data->set.pipewait) { - infof(data, "Server doesn't support multiplex yet, wait\n"); + infof(data, "Server doesn't support multiplex yet, wait"); *waitpipe = TRUE; CONNCACHE_UNLOCK(data); return FALSE; /* no re-use */ } - infof(data, "Server doesn't support multiplex (yet)\n"); + infof(data, "Server doesn't support multiplex (yet)"); canmultiplex = FALSE; } if((bundle->multiuse == BUNDLE_MULTIPLEX) && !Curl_multiplex_wanted(data->multi)) { - infof(data, "Could multiplex, but not asked to!\n"); + infof(data, "Could multiplex, but not asked to!"); canmultiplex = FALSE; } if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { - infof(data, "Can not multiplex, even if we wanted to!\n"); + infof(data, "Can not multiplex, even if we wanted to!"); canmultiplex = FALSE; } } @@ -1193,7 +1209,7 @@ ConnectionExists(struct Curl_easy *data, completed yet and until then we don't re-use this connection */ if(!check->primary_ip[0]) { infof(data, - "Connection #%ld is still name resolving, can't reuse\n", + "Connection #%ld is still name resolving, can't reuse", check->connection_id); continue; } @@ -1202,7 +1218,7 @@ ConnectionExists(struct Curl_easy *data, if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) { foundPendingCandidate = TRUE; /* Don't pick a connection that hasn't connected yet */ - infof(data, "Connection #%ld isn't open enough, can't reuse\n", + infof(data, "Connection #%ld isn't open enough, can't reuse", check->connection_id); continue; } @@ -1357,7 +1373,7 @@ ConnectionExists(struct Curl_easy *data, &check->ssl_config)) { DEBUGF(infof(data, "Connection #%ld has different SSL parameters, " - "can't reuse\n", + "can't reuse", check->connection_id)); continue; } @@ -1365,7 +1381,7 @@ ConnectionExists(struct Curl_easy *data, foundPendingCandidate = TRUE; DEBUGF(infof(data, "Connection #%ld has not started SSL connect, " - "can't reuse\n", + "can't reuse", check->connection_id)); continue; } @@ -1452,14 +1468,14 @@ ConnectionExists(struct Curl_easy *data, /* Multiplexed connections can only be HTTP/2 for now */ struct http_conn *httpc = &check->proto.httpc; if(multiplexed >= httpc->settings.max_concurrent_streams) { - infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n", + infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", multiplexed); continue; } else if(multiplexed >= Curl_multi_max_concurrent_streams(data->multi)) { infof(data, "client side MAX_CONCURRENT_STREAMS reached" - ", skip (%zu)\n", + ", skip (%zu)", multiplexed); continue; } @@ -1467,7 +1483,7 @@ ConnectionExists(struct Curl_easy *data, #endif /* When not multiplexed, we have a match here! */ chosen = check; - infof(data, "Multiplexed connection found!\n"); + infof(data, "Multiplexed connection found!"); break; } else { @@ -1490,7 +1506,7 @@ ConnectionExists(struct Curl_easy *data, if(foundPendingCandidate && data->set.pipewait) { infof(data, - "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n"); + "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set"); *waitpipe = TRUE; } @@ -1505,7 +1521,7 @@ void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn) { if(data->set.verbose) - infof(data, "Connected to %s (%s) port %ld (#%ld)\n", + infof(data, "Connected to %s (%s) port %u (#%ld)", #ifndef CURL_DISABLE_PROXY conn->bits.socksproxy ? conn->socks_proxy.host.dispname : conn->bits.httpproxy ? conn->http_proxy.host.dispname : @@ -1577,12 +1593,12 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data, #else int flags = IDN2_NFC_INPUT; #endif - int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags); + int rc = IDN2_LOOKUP(host->name, &ace_hostname, flags); if(rc != IDN2_OK) /* fallback to TR46 Transitional mode for better IDNA2003 compatibility */ - rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, - IDN2_TRANSITIONAL); + rc = IDN2_LOOKUP(host->name, &ace_hostname, + IDN2_TRANSITIONAL); if(rc == IDN2_OK) { host->encalloc = (char *)ace_hostname; /* change the name pointer to point to the encoded hostname */ @@ -1609,7 +1625,7 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data, return CURLE_URL_MALFORMAT; } #else - infof(data, "IDN support not present, can't parse Unicode domains\n"); + infof(data, "IDN support not present, can't parse Unicode domains"); #endif } return CURLE_OK; @@ -1876,9 +1892,13 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, #else scopeidx = if_nametoindex(zoneid); #endif - if(!scopeidx) - infof(data, "Invalid zoneid: %s; %s\n", zoneid, - strerror(errno)); + if(!scopeidx) { +#ifndef CURL_DISABLE_VERBOSE_STRINGS + char buffer[STRERROR_LEN]; + infof(data, "Invalid zoneid: %s; %s", zoneid, + Curl_strerror(errno, buffer, sizeof(buffer))); +#endif + } else conn->scope_id = scopeidx; } @@ -1934,7 +1954,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, CURLU_DISALLOW_USER : 0) | (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)); if(uc) { - DEBUGF(infof(data, "curl_url_set rejected %s\n", data->state.url)); + DEBUGF(infof(data, "curl_url_set rejected %s", data->state.url)); return Curl_uc_to_curlcode(uc); } @@ -1979,7 +1999,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, } data->state.url = url; data->state.url_alloc = TRUE; - infof(data, "Switched from HTTP to HTTPS due to HSTS => %s\n", + infof(data, "Switched from HTTP to HTTPS due to HSTS => %s", data->state.url); } } @@ -2333,7 +2353,7 @@ static char *detect_proxy(struct Curl_easy *data, } } if(proxy) - infof(data, "Uses proxy env variable %s == '%s'\n", envp, proxy); + infof(data, "Uses proxy env variable %s == '%s'", envp, proxy); return proxy; } @@ -2448,7 +2468,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, conn->bits.proxy_user_passwd = TRUE; /* enable it */ } - curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); + (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); if(portptr) { port = (int)strtol(portptr, NULL, 10); @@ -2576,7 +2596,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, no_proxy = curl_getenv(p); } if(no_proxy) { - infof(data, "Uses proxy env variable %s == '%s'\n", p, no_proxy); + infof(data, "Uses proxy env variable %s == '%s'", p, no_proxy); } } @@ -2871,11 +2891,13 @@ static CURLcode override_login(struct Curl_easy *data, char **passwdp = &conn->passwd; char **optionsp = &conn->options; +#ifndef CURL_DISABLE_NETRC if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) { Curl_safefree(*userp); Curl_safefree(*passwdp); conn->bits.user_passwd = FALSE; /* disable user+password */ } +#endif if(data->set.str[STRING_OPTIONS]) { free(*optionsp); @@ -2884,6 +2906,7 @@ static CURLcode override_login(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } +#ifndef CURL_DISABLE_NETRC conn->bits.netrc = FALSE; if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) { bool netrc_user_changed = FALSE; @@ -2895,7 +2918,7 @@ static CURLcode override_login(struct Curl_easy *data, &netrc_user_changed, &netrc_passwd_changed, data->set.str[STRING_NETRC_FILE]); if(ret > 0) { - infof(data, "Couldn't find host %s in the %s file; using defaults\n", + infof(data, "Couldn't find host %s in the %s file; using defaults", conn->host.name, data->set.str[STRING_NETRC_FILE]); } else if(ret < 0) { @@ -2909,6 +2932,7 @@ static CURLcode override_login(struct Curl_easy *data, conn->bits.user_passwd = TRUE; /* enable user+password */ } } +#endif /* for updated strings, we update them in the URL */ if(*userp) { @@ -2996,6 +3020,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, char *host_portno; char *portptr; int port = -1; + CURLcode result = CURLE_OK; #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) data; @@ -3025,7 +3050,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, if(*ptr == '%') { /* There might be a zone identifier */ if(strncmp("%25", ptr, 3)) - infof(data, "Please URL encode %% as %%25, see RFC 6874.\n"); + infof(data, "Please URL encode %% as %%25, see RFC 6874."); ptr++; /* Allow unreserved characters as defined in RFC 3986 */ while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') || @@ -3036,7 +3061,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, /* yeps, it ended nicely with a bracket as well */ *ptr++ = '\0'; else - infof(data, "Invalid IPv6 address format\n"); + infof(data, "Invalid IPv6 address format"); portptr = ptr; /* Note that if this didn't end with a bracket, we still advanced the * hostptr first, but I can't see anything wrong with that as no host @@ -3044,8 +3069,8 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, */ #else failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!"); - free(host_dup); - return CURLE_NOT_BUILT_IN; + result = CURLE_NOT_BUILT_IN; + goto error; #endif } @@ -3058,10 +3083,10 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, if(*host_portno) { long portparse = strtol(host_portno, &endp, 10); if((endp && *endp) || (portparse < 0) || (portparse > 65535)) { - infof(data, "No valid port number in connect to host string (%s)\n", + failf(data, "No valid port number in connect to host string (%s)", host_portno); - hostptr = NULL; - port = -1; + result = CURLE_SETOPT_OPTION_SYNTAX; + goto error; } else port = (int)portparse; /* we know it will fit */ @@ -3072,15 +3097,16 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, if(hostptr) { *hostname_result = strdup(hostptr); if(!*hostname_result) { - free(host_dup); - return CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; + goto error; } } *port_result = port; + error: free(host_dup); - return CURLE_OK; + return result; } /* @@ -3176,7 +3202,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, conn->conn_to_host.name = host; conn->bits.conn_to_host = TRUE; - infof(data, "Connecting to hostname: %s\n", host); + infof(data, "Connecting to hostname: %s", host); } else { /* no "connect to host" */ @@ -3187,7 +3213,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, if(port >= 0) { conn->conn_to_port = port; conn->bits.conn_to_port = TRUE; - infof(data, "Connecting to port: %d\n", port); + infof(data, "Connecting to port: %d", port); } else { /* no "connect to port" */ @@ -3248,7 +3274,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, conn->conn_to_port = as->dst.port; conn->bits.conn_to_port = TRUE; conn->bits.altused = TRUE; - infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n", + infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d", Curl_alpnid2str(srcalpnid), host, conn->remote_port, Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port); if(srcalpnid != as->dst.alpnid) { @@ -3356,9 +3382,12 @@ static CURLcode resolve_server(struct Curl_easy *data, if(rc == CURLRESOLV_PENDING) *async = TRUE; - else if(rc == CURLRESOLV_TIMEDOUT) + else if(rc == CURLRESOLV_TIMEDOUT) { + failf(data, "Failed to resolve host '%s' with timeout after %ld ms", + connhost->dispname, + Curl_timediff(Curl_now(), data->progress.t_startsingle)); result = CURLE_OPERATION_TIMEDOUT; - + } else if(!hostaddr) { failf(data, "Could not resolve host: %s", connhost->dispname); result = CURLE_COULDNT_RESOLVE_HOST; @@ -3600,7 +3629,7 @@ static CURLcode create_conn(struct Curl_easy *data, if(result) goto out; - /* Check for overridden login details and set them accordingly so they + /* Check for overridden login details and set them accordingly so that they are known when protocol->setup_connection is called! */ result = override_login(data, conn); if(result) @@ -3736,6 +3765,8 @@ static CURLcode create_conn(struct Curl_easy *data, */ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; + data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; + data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; data->set.ssl.primary.cipher_list = @@ -3763,8 +3794,11 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; data->set.proxy_ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY]; + data->set.proxy_ssl.primary.issuercert = + data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.proxy_ssl.primary.issuercert_blob = + data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; - data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; @@ -3773,7 +3807,6 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; #endif data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; data->set.ssl.key = data->set.str[STRING_KEY]; data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; @@ -3787,9 +3820,7 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; #endif #endif - data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; - data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, &conn->ssl_config)) { @@ -3841,14 +3872,14 @@ static CURLcode create_conn(struct Curl_easy *data, *in_connect = conn; #ifndef CURL_DISABLE_PROXY - infof(data, "Re-using existing connection! (#%ld) with %s %s\n", + infof(data, "Re-using existing connection! (#%ld) with %s %s", conn->connection_id, conn->bits.proxy?"proxy":"host", conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname : conn->http_proxy.host.name ? conn->http_proxy.host.dispname : conn->host.dispname); #else - infof(data, "Re-using existing connection! (#%ld) with host %s\n", + infof(data, "Re-using existing connection! (#%ld) with host %s", conn->connection_id, conn->host.dispname); #endif } @@ -3888,7 +3919,7 @@ static CURLcode create_conn(struct Curl_easy *data, if(conn_candidate) (void)Curl_disconnect(data, conn_candidate, FALSE); else { - infof(data, "No more connections allowed to host %s: %zu\n", + infof(data, "No more connections allowed to host %s: %zu", bundlehost, max_host_connections); connections_available = FALSE; } @@ -3908,13 +3939,13 @@ static CURLcode create_conn(struct Curl_easy *data, if(conn_candidate) (void)Curl_disconnect(data, conn_candidate, FALSE); else { - infof(data, "No connections available in cache\n"); + infof(data, "No connections available in cache"); connections_available = FALSE; } } if(!connections_available) { - infof(data, "No connections available.\n"); + infof(data, "No connections available."); conn_free(conn); *in_connect = NULL; @@ -3939,14 +3970,14 @@ static CURLcode create_conn(struct Curl_easy *data, connection based. */ if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && data->state.authhost.done) { - infof(data, "NTLM picked AND auth done set, clear picked!\n"); + infof(data, "NTLM picked AND auth done set, clear picked!"); data->state.authhost.picked = CURLAUTH_NONE; data->state.authhost.done = FALSE; } if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) && data->state.authproxy.done) { - infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n"); + infof(data, "NTLM-proxy picked AND auth done set, clear picked!"); data->state.authproxy.picked = CURLAUTH_NONE; data->state.authproxy.done = FALSE; } diff --git a/lib/urlapi.c b/lib/urlapi.c index 6483208ec73..7f03862cfa2 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -131,7 +131,7 @@ static const char *find_host_sep(const char *url) */ static bool urlchar_needs_escaping(int c) { - return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c)); + return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c)); } /* @@ -580,7 +580,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, } /* scan for byte values < 31 or 127 */ -static CURLUcode junkscan(const char *part) +static bool junkscan(const char *part, unsigned int flags) { if(part) { static const char badbytes[]={ @@ -588,17 +588,18 @@ static CURLUcode junkscan(const char *part) 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x7f, - 0x00 /* null-terminate */ + 0x7f, 0x00 /* null-terminate */ }; size_t n = strlen(part); size_t nfine = strcspn(part, badbytes); if(nfine != n) /* since we don't know which part is scanned, return a generic error code */ - return CURLUE_MALFORMED_INPUT; + return TRUE; + if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' ')) + return TRUE; } - return CURLUE_OK; + return FALSE; } static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) @@ -769,8 +770,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) size_t schemelen = 0; size_t urllen; - if(!url) - return CURLUE_MALFORMED_INPUT; + DEBUGASSERT(url); /************************************************************* * Parse the URL. @@ -884,9 +884,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) !(flags & CURLU_NON_SUPPORT_SCHEME)) return CURLUE_UNSUPPORTED_SCHEME; - if(junkscan(schemep)) + if(junkscan(schemep, flags)) return CURLUE_MALFORMED_INPUT; - } else { /* no scheme! */ @@ -927,7 +926,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) } } - if(junkscan(path)) + if(junkscan(path, flags)) return CURLUE_MALFORMED_INPUT; if((flags & CURLU_URLENCODE) && path[0]) { @@ -991,7 +990,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) /* * Parse the login details and strip them out of the host name. */ - if(junkscan(hostname)) + if(junkscan(hostname, flags)) return CURLUE_MALFORMED_INPUT; result = parse_hostname_login(u, &hostname, flags); @@ -1155,7 +1154,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, const struct Curl_handler *h = Curl_builtin_scheme(u->scheme); if(h) { - msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport); + msnprintf(portbuf, sizeof(portbuf), "%u", h->defport); ptr = portbuf; } } @@ -1214,7 +1213,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, /* there's no stored port number, but asked to deliver a default one for the scheme */ if(h) { - msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport); + msnprintf(portbuf, sizeof(portbuf), "%u", h->defport); port = portbuf; } } diff --git a/lib/urldata.h b/lib/urldata.h index fb905c36c57..6ffd97621f8 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -246,6 +246,7 @@ struct ssl_primary_config { long version_max; /* max supported version the client wants to use*/ char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ + char *issuercert; /* optional issuer certificate filename */ char *clientcert; char *random_file; /* path to file containing "random" data */ char *egdsocket; /* path to file containing the EGD daemon socket */ @@ -254,6 +255,7 @@ struct ssl_primary_config { char *pinned_key; struct curl_blob *cert_blob; struct curl_blob *ca_info_blob; + struct curl_blob *issuercert_blob; char *curves; /* list of curves to use */ BIT(verifypeer); /* set TRUE if this is desired */ BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */ @@ -265,8 +267,6 @@ struct ssl_config_data { struct ssl_primary_config primary; long certverifyresult; /* result from the certificate verification */ char *CRLfile; /* CRL to check certificate revocation */ - char *issuercert;/* optional issuer certificate filename */ - struct curl_blob *issuercert_blob; curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ char *cert_type; /* format for certificate (default: PEM)*/ @@ -508,7 +508,9 @@ struct ConnectBits { BIT(ftp_use_data_ssl); /* Enabled SSL for the data connection */ BIT(ftp_use_control_ssl); /* Enabled SSL for the control connection */ #endif +#ifndef CURL_DISABLE_NETRC BIT(netrc); /* name+password provided by netrc */ +#endif BIT(bound); /* set true if bind() has already been done on this socket/ connection */ BIT(multiplex); /* connection is multiplexed */ @@ -702,14 +704,15 @@ struct SingleRequest { #ifndef CURL_DISABLE_DOH struct dohdata *doh; /* DoH specific data for this request */ #endif - BIT(header); /* incoming data has HTTP header */ + BIT(header); /* incoming data has HTTP header */ BIT(content_range); /* set TRUE if Content-Range: was found */ - BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding - upload and we're uploading the last chunk */ - BIT(ignorebody); /* we read a response-body but we ignore it! */ + BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + BIT(ignorebody); /* we read a response-body but we ignore it! */ BIT(http_bodyless); /* HTTP response status code is between 100 and 199, 204 or 304 */ - BIT(chunk); /* if set, this is a chunked transfer-encoding */ + BIT(chunk); /* if set, this is a chunked transfer-encoding */ + BIT(ignore_cl); /* ignore content-length */ BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding on upload */ BIT(getheader); /* TRUE if header parsing is wanted */ @@ -1411,6 +1414,7 @@ struct UrlState { trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ #ifdef USE_HYPER + bool hconnect; /* set if a CONNECT request */ CURLcode hresult; /* used to pass return codes back from hyper callbacks */ #endif @@ -1726,8 +1730,10 @@ struct UserDefined { */ curl_sshkeycallback ssh_keyfunc; /* key matching callback */ void *ssh_keyfunc_userp; /* custom pointer to callback */ +#ifndef CURL_DISABLE_NETRC enum CURL_NETRC_OPTION use_netrc; /* defined in include/curl.h */ +#endif curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or IMAP or POP3 or others! */ long new_file_perms; /* Permissions to use when creating remote files */ @@ -1847,9 +1853,9 @@ struct UserDefined { BIT(disallow_username_in_url); /* disallow username in url */ BIT(doh); /* DNS-over-HTTPS enabled */ BIT(doh_get); /* use GET for DoH requests, instead of POST */ - BIT(doh_verifypeer); /* DOH certificate peer verification */ - BIT(doh_verifyhost); /* DOH certificate hostname verification */ - BIT(doh_verifystatus); /* DOH certificate status verification */ + BIT(doh_verifypeer); /* DoH certificate peer verification */ + BIT(doh_verifyhost); /* DoH certificate hostname verification */ + BIT(doh_verifystatus); /* DoH certificate status verification */ BIT(http09_allowed); /* allow HTTP/0.9 responses */ BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some recipients */ diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c index 2602ffd363f..94f8f8c0dff 100644 --- a/lib/vauth/digest_sspi.c +++ b/lib/vauth/digest_sspi.c @@ -112,7 +112,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Ensure we have a valid challenge message */ if(!Curl_bufref_len(chlg)) { - infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n"); + infof(data, "DIGEST-MD5 handshake failure (empty challenge message)"); return CURLE_BAD_CONTENT_ENCODING; } @@ -197,7 +197,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, status == SEC_I_COMPLETE_AND_CONTINUE) s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) char buffer[STRERROR_LEN]; +#endif s_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); @@ -207,7 +209,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; - infof(data, "schannel: InitializeSecurityContext failed: %s\n", + infof(data, "schannel: InitializeSecurityContext failed: %s", Curl_sspi_strerror(status, buffer, sizeof(buffer))); return CURLE_AUTH_ERROR; @@ -461,7 +463,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, if(status == SEC_E_OK) output_token_len = chlg_buf[4].cbBuffer; else { /* delete the context so a new one can be made */ - infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx\n", + infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx", (long)status); s_pSecFn->DeleteSecurityContext(digest->http_context); Curl_safefree(digest->http_context); @@ -585,7 +587,9 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, status == SEC_I_COMPLETE_AND_CONTINUE) s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) char buffer[STRERROR_LEN]; +#endif s_pSecFn->FreeCredentialsHandle(&credentials); @@ -597,7 +601,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; - infof(data, "schannel: InitializeSecurityContext failed: %s\n", + infof(data, "schannel: InitializeSecurityContext failed: %s", Curl_sspi_strerror(status, buffer, sizeof(buffer))); return CURLE_AUTH_ERROR; diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c index b43982b9bd6..67d43bd567b 100644 --- a/lib/vauth/krb5_gssapi.c +++ b/lib/vauth/krb5_gssapi.c @@ -123,7 +123,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, if(chlg) { if(!Curl_bufref_len(chlg)) { - infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + infof(data, "GSSAPI handshake failure (empty challenge message)"); return CURLE_BAD_CONTENT_ENCODING; } input_token.value = (void *) Curl_bufref_ptr(chlg); @@ -170,6 +170,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. + * authzid [in] - The authorization identity if some. * chlg [in] - Optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. * out [out] - The result storage. @@ -177,6 +178,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *authzid, const struct bufref *chlg, struct kerberos5data *krb5, struct bufref *out) @@ -189,39 +191,17 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, OM_uint32 unused_status; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - unsigned int indata = 0; - unsigned int outdata = 0; + unsigned char *indata; gss_qop_t qop = GSS_C_QOP_DEFAULT; unsigned int sec_layer = 0; unsigned int max_size = 0; - gss_name_t username = GSS_C_NO_NAME; - gss_buffer_desc username_token; /* Ensure we have a valid challenge message */ if(!Curl_bufref_len(chlg)) { - infof(data, "GSSAPI handshake failure (empty security message)\n"); + infof(data, "GSSAPI handshake failure (empty security message)"); return CURLE_BAD_CONTENT_ENCODING; } - /* Get the fully qualified username back from the context */ - major_status = gss_inquire_context(&minor_status, krb5->context, - &username, NULL, NULL, NULL, NULL, - NULL, NULL); - if(GSS_ERROR(major_status)) { - Curl_gss_log_error(data, "gss_inquire_context() failed: ", - major_status, minor_status); - return CURLE_AUTH_ERROR; - } - - /* Convert the username from internal format to a displayable token */ - major_status = gss_display_name(&minor_status, username, - &username_token, NULL); - if(GSS_ERROR(major_status)) { - Curl_gss_log_error(data, "gss_display_name() failed: ", - major_status, minor_status); - return CURLE_AUTH_ERROR; - } - /* Setup the challenge "input" security buffer */ input_token.value = (void *) Curl_bufref_ptr(chlg); input_token.length = Curl_bufref_len(chlg); @@ -232,32 +212,32 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_unwrap() failed: ", major_status, minor_status); - gss_release_buffer(&unused_status, &username_token); return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(output_token.length != 4) { - infof(data, "GSSAPI handshake failure (invalid security data)\n"); - gss_release_buffer(&unused_status, &username_token); + infof(data, "GSSAPI handshake failure (invalid security data)"); return CURLE_BAD_CONTENT_ENCODING; } - /* Copy the data out and free the challenge as it is not required anymore */ - memcpy(&indata, output_token.value, 4); + /* Extract the security layer and the maximum message size */ + indata = output_token.value; + sec_layer = indata[0]; + max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3]; + + /* Free the challenge as it is not required anymore */ gss_release_buffer(&unused_status, &output_token); - /* Extract the security layer */ - sec_layer = indata & 0x000000FF; + /* Process the security layer */ if(!(sec_layer & GSSAUTH_P_NONE)) { - infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + infof(data, "GSSAPI handshake failure (invalid security layer)"); - gss_release_buffer(&unused_status, &username_token); return CURLE_BAD_CONTENT_ENCODING; } + sec_layer &= GSSAUTH_P_NONE; /* We do not support a security layer */ - /* Extract the maximum message size the server can receive */ - max_size = ntohl(indata & 0xFFFFFF00); + /* Process the maximum message size the server can receive */ if(max_size > 0) { /* The server has told us it supports a maximum receive buffer, however, as we don't require one unless we are encrypting data, we tell the server @@ -266,26 +246,24 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, } /* Allocate our message */ - messagelen = sizeof(outdata) + username_token.length + 1; + messagelen = 4; + if(authzid) + messagelen += strlen(authzid); message = malloc(messagelen); - if(!message) { - gss_release_buffer(&unused_status, &username_token); + if(!message) return CURLE_OUT_OF_MEMORY; - } - /* Populate the message with the security layer, client supported receive - message size and authorization identity including the 0x00 based - terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization - identity is not terminated with the zero-valued (%x00) octet." it seems - necessary to include it. */ - outdata = htonl(max_size) | sec_layer; - memcpy(message, &outdata, sizeof(outdata)); - memcpy(message + sizeof(outdata), username_token.value, - username_token.length); - message[messagelen - 1] = '\0'; - - /* Free the username token as it is not required anymore */ - gss_release_buffer(&unused_status, &username_token); + /* Populate the message with the security layer and client supported receive + message size. */ + message[0] = sec_layer & 0xFF; + message[1] = (max_size >> 16) & 0xFF; + message[2] = (max_size >> 8) & 0xFF; + message[3] = max_size & 0xFF; + + /* If given, append the authorization identity. */ + + if(authzid && *authzid) + memcpy(message + 4, authzid, messagelen - 4); /* Setup the "authentication data" security buffer */ input_token.value = message; diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c index e110644225d..c652fd73657 100644 --- a/lib/vauth/krb5_sspi.c +++ b/lib/vauth/krb5_sspi.c @@ -173,7 +173,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, if(chlg) { if(!Curl_bufref_len(chlg)) { - infof(data, "GSSAPI handshake failure (empty challenge message)\n"); + infof(data, "GSSAPI handshake failure (empty challenge message)"); return CURLE_BAD_CONTENT_ENCODING; } @@ -238,13 +238,15 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, * Parameters: * * data [in] - The session handle. - * chlg [in] - The optional challenge message. + * authzid [in] - The authorization identity if some. + * chlg [in] - The optional challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. * out [out] - The result storage. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *authzid, const struct bufref *chlg, struct kerberos5data *krb5, struct bufref *out) @@ -260,19 +262,20 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, SecBuffer wrap_buf[3]; SecBufferDesc input_desc; SecBufferDesc wrap_desc; - unsigned long indata = 0; - unsigned long outdata = 0; + unsigned char *indata; unsigned long qop = 0; unsigned long sec_layer = 0; unsigned long max_size = 0; SecPkgContext_Sizes sizes; - SecPkgCredentials_Names names; SECURITY_STATUS status; - char *user_name; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif /* Ensure we have a valid challenge message */ if(!Curl_bufref_len(chlg)) { - infof(data, "GSSAPI handshake failure (empty security message)\n"); + infof(data, "GSSAPI handshake failure (empty security message)"); return CURLE_BAD_CONTENT_ENCODING; } @@ -287,17 +290,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(status != SEC_E_OK) return CURLE_AUTH_ERROR; - /* Get the fully qualified username back from the context */ - status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials, - SECPKG_CRED_ATTR_NAMES, - &names); - - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; - - if(status != SEC_E_OK) - return CURLE_AUTH_ERROR; - /* Setup the "input" security buffer */ input_desc.ulVersion = SECBUFFER_VERSION; input_desc.cBuffers = 2; @@ -312,29 +304,32 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, /* Decrypt the inbound challenge and obtain the qop */ status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop); if(status != SEC_E_OK) { - infof(data, "GSSAPI handshake failure (empty security message)\n"); + infof(data, "GSSAPI handshake failure (empty security message)"); return CURLE_BAD_CONTENT_ENCODING; } /* Not 4 octets long so fail as per RFC4752 Section 3.1 */ if(input_buf[1].cbBuffer != 4) { - infof(data, "GSSAPI handshake failure (invalid security data)\n"); + infof(data, "GSSAPI handshake failure (invalid security data)"); return CURLE_BAD_CONTENT_ENCODING; } - /* Copy the data out and free the challenge as it is not required anymore */ - memcpy(&indata, input_buf[1].pvBuffer, 4); + /* Extract the security layer and the maximum message size */ + indata = input_buf[1].pvBuffer; + sec_layer = indata[0]; + max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3]; + + /* Free the challenge as it is not required anymore */ s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer); - /* Extract the security layer */ - sec_layer = indata & 0x000000FF; + /* Process the security layer */ if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) { - infof(data, "GSSAPI handshake failure (invalid security layer)\n"); + infof(data, "GSSAPI handshake failure (invalid security layer)"); return CURLE_BAD_CONTENT_ENCODING; } + sec_layer &= KERB_WRAP_NO_ENCRYPT; /* We do not support a security layer */ - /* Extract the maximum message size the server can receive */ - max_size = ntohl(indata & 0xFFFFFF00); + /* Process the maximum message size the server can receive */ if(max_size > 0) { /* The server has told us it supports a maximum receive buffer, however, as we don't require one unless we are encrypting data, we tell the server @@ -347,33 +342,28 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(!trailer) return CURLE_OUT_OF_MEMORY; - /* Convert the user name to UTF8 when operating with Unicode */ - user_name = curlx_convert_tchar_to_UTF8(names.sUserName); - if(!user_name) { - free(trailer); - - return CURLE_OUT_OF_MEMORY; - } - /* Allocate our message */ - messagelen = sizeof(outdata) + strlen(user_name) + 1; + messagelen = 4; + if(authzid) + messagelen += strlen(authzid); message = malloc(messagelen); if(!message) { free(trailer); - curlx_unicodefree(user_name); return CURLE_OUT_OF_MEMORY; } - /* Populate the message with the security layer, client supported receive - message size and authorization identity including the 0x00 based - terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization - identity is not terminated with the zero-valued (%x00) octet." it seems - necessary to include it. */ - outdata = htonl(max_size) | sec_layer; - memcpy(message, &outdata, sizeof(outdata)); - strcpy((char *) message + sizeof(outdata), user_name); - curlx_unicodefree(user_name); + /* Populate the message with the security layer and client supported receive + message size. */ + message[0] = sec_layer & 0xFF; + message[1] = (max_size >> 16) & 0xFF; + message[2] = (max_size >> 8) & 0xFF; + message[3] = max_size & 0xFF; + + /* If given, append the authorization identity. */ + + if(authzid && *authzid) + memcpy(message + 4, authzid, messagelen - 4); /* Allocate the padding */ padding = malloc(sizes.cbBlockSize); diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index 47e53572cb1..0aa3f1c8ca5 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -182,7 +182,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, (target_info_offset + target_info_len) > type2len || target_info_offset < 48) { infof(data, "NTLM handshake failure (bad type-2 message). " - "Target Info Offset Len is set incorrect by the peer\n"); + "Target Info Offset Len is set incorrect by the peer"); return CURLE_BAD_CONTENT_ENCODING; } @@ -286,7 +286,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { /* This was not a good enough type-2 message */ - infof(data, "NTLM handshake failure (bad type-2 message)\n"); + infof(data, "NTLM handshake failure (bad type-2 message)"); return CURLE_BAD_CONTENT_ENCODING; } @@ -296,7 +296,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { result = ntlm_decode_type2_target(data, type2ref, ntlm); if(result) { - infof(data, "NTLM handshake failure (bad type-2 message)\n"); + infof(data, "NTLM handshake failure (bad type-2 message)"); return result; } } @@ -533,7 +533,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, /* Get the machine's un-qualified host name as NTLM doesn't like the fully qualified domain name */ if(Curl_gethostname(host, sizeof(host))) { - infof(data, "gethostname() failed, continuing without!\n"); + infof(data, "gethostname() failed, continuing without!"); hostlen = 0; } else { diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c index 1b1a1763017..3e39dad315f 100644 --- a/lib/vauth/ntlm_sspi.c +++ b/lib/vauth/ntlm_sspi.c @@ -206,7 +206,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, /* Ensure we have a valid type-2 message */ if(!Curl_bufref_len(type2)) { - infof(data, "NTLM handshake failure (empty type-2 message)\n"); + infof(data, "NTLM handshake failure (empty type-2 message)"); return CURLE_BAD_CONTENT_ENCODING; } @@ -253,6 +253,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, unsigned long attrs; TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif (void) passwdp; (void) userp; @@ -309,7 +312,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, &type_3_desc, &attrs, &expiry); if(status != SEC_E_OK) { - infof(data, "NTLM handshake failure (type-3 message): Status=%x\n", + infof(data, "NTLM handshake failure (type-3 message): Status=%x", status); if(status == SEC_E_INSUFFICIENT_MEMORY) diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c index 120925ff331..8e8932bd03e 100644 --- a/lib/vauth/spnego_gssapi.c +++ b/lib/vauth/spnego_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -137,8 +137,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, /* Ensure we have a valid challenge message */ if(!chlg) { - infof(data, "SPNEGO handshake failure (empty challenge message)\n"); - + infof(data, "SPNEGO handshake failure (empty challenge message)"); return CURLE_BAD_CONTENT_ENCODING; } diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c index 4aa1ba9572c..68bb17da596 100644 --- a/lib/vauth/spnego_sspi.c +++ b/lib/vauth/spnego_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -191,8 +191,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, /* Ensure we have a valid challenge message */ if(!chlg) { - infof(data, "SPNEGO handshake failure (empty challenge message)\n"); - + infof(data, "SPNEGO handshake failure (empty challenge message)"); return CURLE_BAD_CONTENT_ENCODING; } diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h index ec5b0007f50..47a7c0bc813 100644 --- a/lib/vauth/vauth.h +++ b/lib/vauth/vauth.h @@ -194,6 +194,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, /* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security token message */ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *authzid, const struct bufref *chlg, struct kerberos5data *krb5, struct bufref *out); diff --git a/lib/version.c b/lib/version.c index b67b9a46605..c84ef85fb3c 100644 --- a/lib/version.c +++ b/lib/version.c @@ -75,28 +75,26 @@ #endif #ifdef HAVE_BROTLI -static size_t brotli_version(char *buf, size_t bufsz) +static void brotli_version(char *buf, size_t bufsz) { uint32_t brotli_version = BrotliDecoderVersion(); unsigned int major = brotli_version >> 24; unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12; unsigned int patch = brotli_version & 0x00000FFF; - - return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); + (void)msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); } #endif #ifdef HAVE_ZSTD -static size_t zstd_version(char *buf, size_t bufsz) +static void zstd_version(char *buf, size_t bufsz) { unsigned long zstd_version = (unsigned long)ZSTD_versionNumber(); unsigned int major = (unsigned int)(zstd_version / (100 * 100)); unsigned int minor = (unsigned int)((zstd_version - - (major * 100 * 100)) / 100); + (major * 100 * 100)) / 100); unsigned int patch = (unsigned int)(zstd_version - - (major * 100 * 100) - (minor * 100)); - - return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); + (major * 100 * 100) - (minor * 100)); + (void)msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); } #endif diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c index 7f076759b8f..9fcfe81a8cd 100644 --- a/lib/vquic/ngtcp2.c +++ b/lib/vquic/ngtcp2.c @@ -28,6 +28,9 @@ #include <nghttp3/nghttp3.h> #ifdef USE_OPENSSL #include <openssl/err.h> +#include <ngtcp2/ngtcp2_crypto_openssl.h> +#elif defined(USE_GNUTLS) +#include <ngtcp2/ngtcp2_crypto_gnutls.h> #endif #include "urldata.h" #include "sendf.h" @@ -86,7 +89,8 @@ struct h3out { #define QUIC_PRIORITY \ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \ "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \ - "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1" + "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \ + "%DISABLE_TLS13_COMPAT_MODE" #endif static CURLcode ng_process_ingress(struct Curl_easy *data, @@ -116,42 +120,6 @@ static void quic_printf(void *user_data, const char *fmt, ...) } #endif -#ifdef USE_OPENSSL -static ngtcp2_crypto_level -quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level) -{ - switch(ossl_level) { - case ssl_encryption_initial: - return NGTCP2_CRYPTO_LEVEL_INITIAL; - case ssl_encryption_early_data: - return NGTCP2_CRYPTO_LEVEL_EARLY; - case ssl_encryption_handshake: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; - case ssl_encryption_application: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; - default: - assert(0); - } -} -#elif defined(USE_GNUTLS) -static ngtcp2_crypto_level -quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level) -{ - switch(gtls_level) { - case GNUTLS_ENCRYPTION_LEVEL_INITIAL: - return NGTCP2_CRYPTO_LEVEL_INITIAL; - case GNUTLS_ENCRYPTION_LEVEL_EARLY: - return NGTCP2_CRYPTO_LEVEL_EARLY; - case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE: - return NGTCP2_CRYPTO_LEVEL_HANDSHAKE; - case GNUTLS_ENCRYPTION_LEVEL_APPLICATION: - return NGTCP2_CRYPTO_LEVEL_APPLICATION; - default: - assert(0); - } -} -#endif - static void qlog_callback(void *user_data, uint32_t flags, const void *data, size_t datalen) { @@ -222,27 +190,9 @@ static int write_client_handshake(struct quicsocket *qs, ngtcp2_crypto_level level, const uint8_t *data, size_t len) { - struct quic_handshake *crypto_data; int rv; - crypto_data = &qs->crypto_data[level]; - if(!crypto_data->buf) { - crypto_data->buf = malloc(4096); - if(!crypto_data->buf) - return 0; - crypto_data->alloclen = 4096; - } - - /* TODO Just pretend that handshake does not grow more than 4KiB for - now */ - assert(crypto_data->len + len <= crypto_data->alloclen); - - memcpy(&crypto_data->buf[crypto_data->len], data, len); - crypto_data->len += len; - - rv = ngtcp2_conn_submit_crypto_data( - qs->qconn, level, (uint8_t *)(&crypto_data->buf[crypto_data->len] - len), - len); + rv = ngtcp2_conn_submit_crypto_data(qs->qconn, level, data, len); if(rv) { H3BUGF(fprintf(stderr, "write_client_handshake failed\n")); } @@ -259,7 +209,7 @@ static int quic_set_encryption_secrets(SSL *ssl, size_t secretlen) { struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl); - int level = quic_from_ossl_level(ossl_level); + int level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); if(ngtcp2_crypto_derive_and_install_rx_key( qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0) @@ -281,7 +231,8 @@ static int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, const uint8_t *data, size_t len) { struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl); - ngtcp2_crypto_level level = quic_from_ossl_level(ossl_level); + ngtcp2_crypto_level level = + ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); return write_client_handshake(qs, level, data, len); } @@ -369,7 +320,8 @@ static int secret_func(gnutls_session_t ssl, const void *tx_secret, size_t secretlen) { struct quicsocket *qs = gnutls_session_get_ptr(ssl); - int level = quic_from_gtls_level(gtls_level); + int level = + ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level); if(level != NGTCP2_CRYPTO_LEVEL_EARLY && ngtcp2_crypto_derive_and_install_rx_key( @@ -394,7 +346,8 @@ static int read_func(gnutls_session_t ssl, size_t len) { struct quicsocket *qs = gnutls_session_get_ptr(ssl); - ngtcp2_crypto_level level = quic_from_gtls_level(gtls_level); + ngtcp2_crypto_level level = + ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level); int rv; if(htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC) @@ -542,22 +495,6 @@ static int quic_init_ssl(struct quicsocket *qs) } #endif -static int -cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level, - uint64_t offset, - const uint8_t *data, size_t datalen, - void *user_data) -{ - (void)offset; - (void)user_data; - - if(ngtcp2_crypto_read_write_crypto_data(tconn, crypto_level, data, - datalen) != 0) - return NGTCP2_ERR_CRYPTO; - - return 0; -} - static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data) { (void)user_data; @@ -622,8 +559,8 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, return 0; } -static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id, - uint64_t app_error_code, +static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, + int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data) { struct quicsocket *qs = (struct quicsocket *)user_data; @@ -632,6 +569,10 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id, (void)stream_user_data; /* stream is closed... */ + if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) { + app_error_code = NGHTTP3_H3_NO_ERROR; + } + rv = nghttp3_conn_close_stream(qs->h3conn, stream_id, app_error_code); if(rv) { @@ -652,7 +593,25 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, (void)app_error_code; (void)stream_user_data; - rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id); + rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id); + if(rv) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} + +static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id, + uint64_t app_error_code, void *user_data, + void *stream_user_data) +{ + struct quicsocket *qs = (struct quicsocket *)user_data; + int rv; + (void)tconn; + (void)app_error_code; + (void)stream_user_data; + + rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id); if(rv) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -712,14 +671,13 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid, static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_client_initial_cb, NULL, /* recv_client_initial */ - cb_recv_crypto_data, + ngtcp2_crypto_recv_crypto_data_cb, cb_handshake_completed, NULL, /* recv_version_negotiation */ ngtcp2_crypto_encrypt_cb, ngtcp2_crypto_decrypt_cb, ngtcp2_crypto_hp_mask_cb, cb_recv_stream_data, - NULL, /* acked_crypto_offset */ cb_acked_stream_data_offset, NULL, /* stream_open */ cb_stream_close, @@ -744,7 +702,9 @@ static ngtcp2_callbacks ng_callbacks = { ngtcp2_crypto_delete_crypto_cipher_ctx_cb, NULL, /* recv_datagram */ NULL, /* ack_datagram */ - NULL /* lost_datagram */ + NULL, /* lost_datagram */ + NULL, /* get_path_challenge_data */ + cb_stream_stop_sending }; /* @@ -778,7 +738,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, return CURLE_BAD_FUNCTION_ARGUMENT; } - infof(data, "Connect socket %d over QUIC to %s:%d\n", + infof(data, "Connect socket %d over QUIC to %s:%d", sockfd, ipbuf, port); qs->version = NGTCP2_PROTO_VER_MAX; @@ -827,15 +787,14 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, } /* - * Store ngtp2 version info in this buffer, Prefix with a space. Return total - * length written. + * Store ngtcp2 version info in this buffer. */ -int Curl_quic_ver(char *p, size_t len) +void Curl_quic_ver(char *p, size_t len) { const ngtcp2_info *ng2 = ngtcp2_version(0); nghttp3_info *ht3 = nghttp3_version(0); - return msnprintf(p, len, "ngtcp2/%s nghttp3/%s", - ng2->version_str, ht3->version_str); + (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s", + ng2->version_str, ht3->version_str); } static int ng_getsock(struct Curl_easy *data, struct connectdata *conn, @@ -859,7 +818,6 @@ static int ng_getsock(struct Curl_easy *data, struct connectdata *conn, static void qs_disconnect(struct quicsocket *qs) { - int i; if(!qs->conn) /* already closed */ return; qs->conn = NULL; @@ -880,8 +838,6 @@ static void qs_disconnect(struct quicsocket *qs) qs->cred = NULL; } #endif - for(i = 0; i < 3; i++) - Curl_safefree(qs->crypto_data[i].buf); nghttp3_conn_del(qs->h3conn); ngtcp2_conn_del(qs->qconn); #ifdef USE_OPENSSL @@ -951,7 +907,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id, (void)stream_id; (void)app_error_code; (void)user_data; - H3BUGF(infof(data, "cb_h3_stream_close CALLED\n")); + H3BUGF(infof(data, "cb_h3_stream_close CALLED")); stream->closed = TRUE; Curl_expire(data, 0, EXPIRE_QUIC); @@ -1143,14 +1099,10 @@ static nghttp3_callbacks ngh3_callbacks = { NULL, /* begin_trailers */ cb_h3_recv_header, NULL, /* end_trailers */ - NULL, /* http_begin_push_promise */ - NULL, /* http_recv_push_promise */ - NULL, /* http_end_push_promise */ - NULL, /* http_cancel_push */ cb_h3_send_stop_sending, - NULL, /* push_stream */ NULL, /* end_stream */ NULL, /* reset_stream */ + NULL /* shutdown */ }; static int init_ngh3_conn(struct quicsocket *qs) @@ -1287,7 +1239,7 @@ static ssize_t ngh3_stream_recv(struct Curl_easy *data, return 0; } - infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n"); + infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN"); *curlcode = CURLE_AGAIN; return -1; } @@ -1304,7 +1256,7 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id, if(!data->set.postfields) { stream->h3out->used -= datalen; H3BUGF(infof(data, - "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n", + "cb_h3_acked_stream_data, %zd bytes, %zd left unacked", datalen, stream->h3out->used)); DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE); @@ -1366,13 +1318,13 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id, if(!stream->upload_left) *pflags = NGHTTP3_DATA_FLAG_EOF; } - H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)\n", + H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)", nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"", out->used)); } if(stream->upload_done && !stream->upload_len && (stream->upload_left <= 0)) { - H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n")); + H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF")); *pflags = NGHTTP3_DATA_FLAG_EOF; return nread ? 1 : 0; } @@ -1565,7 +1517,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, if(acc > MAX_ACC) { infof(data, "http_request: Warning: The cumulative length of all " "headers exceeds %d bytes and that could cause the " - "stream to be rejected.\n", MAX_ACC); + "stream to be rejected.", MAX_ACC); } } @@ -1611,7 +1563,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, Curl_safefree(nva); - infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n", + infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)", stream3_id, (void *)data); return CURLE_OK; @@ -1641,7 +1593,7 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data, sent = len; } else { - H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n", + H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes", len)); if(!stream->upload_len) { stream->upload_mem = mem; @@ -1660,6 +1612,12 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data, return -1; } + /* Reset post upload buffer after resumed. */ + if(stream->upload_mem) { + stream->upload_mem = NULL; + stream->upload_len = 0; + } + *curlcode = CURLE_OK; return sent; } @@ -1758,8 +1716,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, int rv; ssize_t sent; ssize_t outlen; - uint8_t out[NGTCP2_MAX_PKTLEN_IPV4]; - size_t pktlen; + uint8_t out[NGTCP2_MAX_UDP_PAYLOAD_SIZE]; ngtcp2_path_storage ps; ngtcp2_tstamp ts = timestamp(); struct sockaddr_storage remote_addr; @@ -1772,19 +1729,6 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, ssize_t ndatalen; uint32_t flags; - switch(qs->local_addr.ss_family) { - case AF_INET: - pktlen = NGTCP2_MAX_PKTLEN_IPV4; - break; -#ifdef ENABLE_IPV6 - case AF_INET6: - pktlen = NGTCP2_MAX_PKTLEN_IPV6; - break; -#endif - default: - assert(0); - } - rv = ngtcp2_conn_handle_expiry(qs->qconn, ts); if(rv) { failf(data, "ngtcp2_conn_handle_expiry returned error: %s", @@ -1811,15 +1755,16 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, flags = NGTCP2_WRITE_STREAM_FLAG_MORE | (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0); - outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen, + outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, + sizeof(out), &ndatalen, flags, stream_id, (const ngtcp2_vec *)vec, veccnt, ts); if(outlen == 0) { break; } if(outlen < 0) { - if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED || - outlen == NGTCP2_ERR_STREAM_SHUT_WR) { + switch(outlen) { + case NGTCP2_ERR_STREAM_DATA_BLOCKED: assert(ndatalen == -1); rv = nghttp3_conn_block_stream(qs->h3conn, stream_id); if(rv) { @@ -1828,8 +1773,17 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, return CURLE_SEND_ERROR; } continue; - } - else if(outlen == NGTCP2_ERR_WRITE_MORE) { + case NGTCP2_ERR_STREAM_SHUT_WR: + assert(ndatalen == -1); + rv = nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id); + if(rv) { + failf(data, + "nghttp3_conn_shutdown_stream_write returned error: %s\n", + nghttp3_strerror(rv)); + return CURLE_SEND_ERROR; + } + continue; + case NGTCP2_ERR_WRITE_MORE: assert(ndatalen >= 0); rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); if(rv) { @@ -1838,8 +1792,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data, return CURLE_SEND_ERROR; } continue; - } - else { + default: assert(ndatalen == -1); failf(data, "ngtcp2_conn_writev_stream returned error: %s", ngtcp2_strerror((int)outlen)); diff --git a/lib/vquic/ngtcp2.h b/lib/vquic/ngtcp2.h index cbede451462..501453042b9 100644 --- a/lib/vquic/ngtcp2.h +++ b/lib/vquic/ngtcp2.h @@ -34,13 +34,6 @@ #include <gnutls/gnutls.h> #endif -struct quic_handshake { - char *buf; /* pointer to the buffer */ - size_t alloclen; /* size of allocation */ - size_t len; /* size of content in buffer */ - size_t nread; /* how many bytes have been read */ -}; - struct quicsocket { struct connectdata *conn; /* point back to the connection */ ngtcp2_conn *qconn; @@ -56,7 +49,6 @@ struct quicsocket { gnutls_certificate_credentials_t cred; gnutls_session_t ssl; #endif - struct quic_handshake crypto_data[3]; /* the last TLS alert description generated by the local endpoint */ uint8_t tls_alert; struct sockaddr_storage local_addr; diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c index b62d88437a1..f7577605c0c 100644 --- a/lib/vquic/quiche.c +++ b/lib/vquic/quiche.c @@ -258,7 +258,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, return CURLE_BAD_FUNCTION_ARGUMENT; } - infof(data, "Connect socket %d over QUIC to %s:%ld\n", + infof(data, "Connect socket %d over QUIC to %s:%ld", sockfd, ipbuf, port); Curl_persistconninfo(data, conn, NULL, -1); @@ -277,7 +277,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, offset += 1 + alpn_len; } - infof(data, "Sent QUIC client Initial, ALPN: %s\n", + infof(data, "Sent QUIC client Initial, ALPN: %s", alpn_protocols + 1); } @@ -345,7 +345,7 @@ CURLcode Curl_quic_is_connected(struct Curl_easy *data, if(quiche_conn_is_established(qs->conn)) { *done = TRUE; result = quiche_has_connected(conn, 0, sockindex); - DEBUGF(infof(data, "quiche established connection!\n")); + DEBUGF(infof(data, "quiche established connection!")); } return result; @@ -422,10 +422,9 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd, return CURLE_SEND_ERROR; } - sent = sendto(sockfd, out, sent, 0, - (struct sockaddr *)&send_info.to, send_info.to_len); + sent = send(sockfd, out, sent, 0); if(sent < 0) { - failf(data, "sendto() returned %zd", sent); + failf(data, "send() returned %zd", sent); return CURLE_SEND_ERROR; } } while(1); @@ -492,7 +491,7 @@ static ssize_t h3_stream_recv(struct Curl_easy *data, headers.nlen = 0; if(process_ingress(data, sockfd, qs)) { - infof(data, "h3_stream_recv returns on ingress\n"); + infof(data, "h3_stream_recv returns on ingress"); *curlcode = CURLE_RECV_ERROR; return -1; } @@ -505,7 +504,7 @@ static ssize_t h3_stream_recv(struct Curl_easy *data, if(s != stream->stream3_id) { /* another transfer, ignore for now */ - infof(data, "Got h3 for stream %u, expects %u\n", + infof(data, "Got h3 for stream %u, expects %u", s, stream->stream3_id); continue; } @@ -586,7 +585,7 @@ static ssize_t h3_stream_send(struct Curl_easy *data, sent = len; } else { - H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len)); + H3BUGF(infof(data, "Pass on %zd body bytes to quiche", len)); sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id, (uint8_t *)mem, len, FALSE); if(sent < 0) { @@ -605,12 +604,11 @@ static ssize_t h3_stream_send(struct Curl_easy *data, } /* - * Store quiche version info in this buffer, Prefix with a space. Return total - * length written. + * Store quiche version info in this buffer. */ -int Curl_quic_ver(char *p, size_t len) +void Curl_quic_ver(char *p, size_t len) { - return msnprintf(p, len, "quiche/%s", quiche_version()); + (void)msnprintf(p, len, "quiche/%s", quiche_version()); } /* Index where :authority header field will appear in request header @@ -780,7 +778,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, for(i = 0; i < nheader; ++i) { acc += nva[i].name_len + nva[i].value_len; - H3BUGF(infof(data, "h3 [%.*s: %.*s]\n", + H3BUGF(infof(data, "h3 [%.*s: %.*s]", nva[i].name_len, nva[i].name, nva[i].value_len, nva[i].value)); } @@ -788,7 +786,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, if(acc > MAX_ACC) { infof(data, "http_request: Warning: The cumulative length of all " "headers exceeds %d bytes and that could cause the " - "stream to be rejected.\n", MAX_ACC); + "stream to be rejected.", MAX_ACC); } } @@ -825,13 +823,13 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem, Curl_safefree(nva); if(stream3_id < 0) { - H3BUGF(infof(data, "quiche_h3_send_request returned %d\n", + H3BUGF(infof(data, "quiche_h3_send_request returned %d", stream3_id)); result = CURLE_SEND_ERROR; goto fail; } - infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n", + infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)", stream3_id, (void *)data); stream->stream3_id = stream3_id; diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c index d146d15fdfd..3e317e87c99 100644 --- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -74,7 +74,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "inet_ntop.h" #include "parsedate.h" /* for the week day and month names */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ @@ -303,7 +302,7 @@ static void mystate(struct Curl_easy *data, sshstate nowstate if(sshc->state != nowstate) { - infof(data, "SSH %p state change from %s to %s (line %d)\n", + infof(data, "SSH %p state change from %s to %s (line %d)", (void *) sshc, names[sshc->state], names[nowstate], lineno); } @@ -368,7 +367,7 @@ static int myssh_is_known(struct Curl_easy *data) for(i = 0; i < 16; i++) msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]); - infof(data, "SSH MD5 fingerprint: %s\n", md5buffer); + infof(data, "SSH MD5 fingerprint: %s", md5buffer); if(!strcasecompare(md5buffer, pubkey_md5)) { failf(data, @@ -732,7 +731,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == SSH_AUTH_SUCCESS) { sshc->authed = TRUE; - infof(data, "Authenticated with none\n"); + infof(data, "Authenticated with none"); state(data, SSH_AUTH_DONE); break; } @@ -744,7 +743,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { state(data, SSH_AUTH_PKEY_INIT); - infof(data, "Authentication using SSH public key file\n"); + infof(data, "Authentication using SSH public key file"); } else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { state(data, SSH_AUTH_GSSAPI); @@ -810,7 +809,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == SSH_AUTH_SUCCESS) { rc = SSH_OK; sshc->authed = TRUE; - infof(data, "Completed public key authentication\n"); + infof(data, "Completed public key authentication"); state(data, SSH_AUTH_DONE); break; } @@ -827,12 +826,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == SSH_AUTH_SUCCESS) { sshc->authed = TRUE; - infof(data, "Completed public key authentication\n"); + infof(data, "Completed public key authentication"); state(data, SSH_AUTH_DONE); break; } else { - infof(data, "Failed public key authentication (rc: %d)\n", rc); + infof(data, "Failed public key authentication (rc: %d)", rc); MOVE_TO_SECONDARY_AUTH; } break; @@ -852,7 +851,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == SSH_AUTH_SUCCESS) { rc = SSH_OK; sshc->authed = TRUE; - infof(data, "Completed gssapi authentication\n"); + infof(data, "Completed gssapi authentication"); state(data, SSH_AUTH_DONE); break; } @@ -878,7 +877,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } if(rc == SSH_OK) { sshc->authed = TRUE; - infof(data, "completed keyboard interactive authentication\n"); + infof(data, "completed keyboard interactive authentication"); } state(data, SSH_AUTH_DONE); break; @@ -901,7 +900,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == SSH_AUTH_SUCCESS) { sshc->authed = TRUE; - infof(data, "Completed password authentication\n"); + infof(data, "Completed password authentication"); state(data, SSH_AUTH_DONE); } else { @@ -919,7 +918,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) /* * At this point we have an authenticated ssh session. */ - infof(data, "Authentication complete\n"); + infof(data, "Authentication complete"); Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */ @@ -930,7 +929,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_INIT); break; } - infof(data, "SSH CONNECT phase done\n"); + infof(data, "SSH CONNECT phase done"); state(data, SSH_STOP); break; @@ -970,7 +969,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) we get the homedir here, we get the "workingpath" in the DO action since the homedir will remain the same between request but the working path will not. */ - DEBUGF(infof(data, "SSH CONNECT phase done\n")); + DEBUGF(infof(data, "SSH CONNECT phase done")); state(data, SSH_STOP); break; @@ -983,7 +982,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } if(data->set.quote) { - infof(data, "Sending quote commands\n"); + infof(data, "Sending quote commands"); sshc->quote_item = data->set.quote; state(data, SSH_SFTP_QUOTE); } @@ -994,7 +993,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_POSTQUOTE_INIT: if(data->set.postquote) { - infof(data, "Sending quote commands\n"); + infof(data, "Sending quote commands"); sshc->quote_item = data->set.postquote; state(data, SSH_SFTP_QUOTE); } @@ -1367,7 +1366,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(sshc->slash_pos) { *sshc->slash_pos = 0; - infof(data, "Creating directory '%s'\n", protop->path); + infof(data, "Creating directory '%s'", protop->path); state(data, SSH_SFTP_CREATE_DIRS_MKDIR); break; } @@ -1731,7 +1730,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(data->req.size == 0) { /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); - infof(data, "File already completely downloaded\n"); + infof(data, "File already completely downloaded"); state(data, SSH_STOP); break; } @@ -1764,7 +1763,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } Curl_safefree(protop->path); - DEBUGF(infof(data, "SFTP DONE done\n")); + DEBUGF(infof(data, "SFTP DONE done")); /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT After nextstate is executed, the control should come back to @@ -1933,7 +1932,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) break; } if(rc != SSH_OK) { - infof(data, "Failed to close libssh scp channel: %s\n", + infof(data, "Failed to close libssh scp channel: %s", ssh_get_error(sshc->ssh_session)); } } @@ -1946,7 +1945,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) ssh_scp_free(sshc->scp_session); sshc->scp_session = NULL; } - DEBUGF(infof(data, "SCP DONE phase complete\n")); + DEBUGF(infof(data, "SCP DONE phase complete")); ssh_set_blocking(sshc->ssh_session, 0); @@ -2213,7 +2212,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) } if(conn->user && conn->user[0] != '\0') { - infof(data, "User: %s\n", conn->user); + infof(data, "User: %s", conn->user); rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user); if(rc != SSH_OK) { failf(data, "Could not set user"); @@ -2222,7 +2221,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) } if(data->set.str[STRING_SSH_KNOWNHOSTS]) { - infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]); + infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]); rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS, data->set.str[STRING_SSH_KNOWNHOSTS]); if(rc != SSH_OK) { @@ -2279,7 +2278,7 @@ static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done) result = myssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; } @@ -2300,7 +2299,7 @@ CURLcode scp_perform(struct Curl_easy *data, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); *dophase_done = FALSE; /* not done yet */ @@ -2312,7 +2311,7 @@ CURLcode scp_perform(struct Curl_easy *data, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; @@ -2481,7 +2480,7 @@ CURLcode sftp_perform(struct Curl_easy *data, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); *dophase_done = FALSE; /* not done yet */ @@ -2494,7 +2493,7 @@ CURLcode sftp_perform(struct Curl_easy *data, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; @@ -2506,7 +2505,7 @@ static CURLcode sftp_doing(struct Curl_easy *data, { CURLcode result = myssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; } @@ -2521,7 +2520,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, CURLcode result = CURLE_OK; (void) dead_connection; - DEBUGF(infof(data, "SSH DISCONNECT starts now\n")); + DEBUGF(infof(data, "SSH DISCONNECT starts now")); if(conn->proto.sshc.ssh_session) { /* only if there's a session still around to use! */ @@ -2529,7 +2528,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, result = myssh_block_statemach(data, TRUE); } - DEBUGF(infof(data, "SSH DISCONNECT is done\n")); + DEBUGF(infof(data, "SSH DISCONNECT is done")); return result; @@ -2940,9 +2939,9 @@ void Curl_ssh_cleanup(void) (void)ssh_finalize(); } -size_t Curl_ssh_version(char *buffer, size_t buflen) +void Curl_ssh_version(char *buffer, size_t buflen) { - return msnprintf(buffer, buflen, "libssh/%s", CURL_LIBSSH_VERSION); + (void)msnprintf(buffer, buflen, "libssh/%s", CURL_LIBSSH_VERSION); } #endif /* USE_LIBSSH */ diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index 8a6345b9487..a772f1f9b7f 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -73,7 +73,6 @@ #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" -#include "strerror.h" #include "inet_ntop.h" #include "parsedate.h" /* for the week day and month names */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ @@ -378,7 +377,7 @@ static void state(struct Curl_easy *data, sshstate nowstate) DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); if(sshc->state != nowstate) { - infof(data, "SFTP %p state change from %s to %s\n", + infof(data, "SFTP %p state change from %s to %s", (void *)sshc, names[sshc->state], names[nowstate]); } #endif @@ -491,7 +490,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) break; #endif default: - infof(data, "unsupported key type, can't check knownhosts!\n"); + infof(data, "unsupported key type, can't check knownhosts!"); keybit = 0; break; } @@ -519,7 +518,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) &host); #endif - infof(data, "SSH host check: %d, key: %s\n", keycheck, + infof(data, "SSH host check: %d, key: %s", keycheck, (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? host->key:"<none>"); @@ -586,7 +585,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) LIBSSH2_KNOWNHOST_KEYENC_RAW| keybit, NULL); if(addrc) - infof(data, "Warning adding the known host %s failed!\n", + infof(data, "Warning adding the known host %s failed!", conn->host.name); else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE || rc == CURLKHSTAT_FINE_REPLACE) { @@ -597,7 +596,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(wrc) { - infof(data, "Warning, writing %s failed!\n", + infof(data, "Warning, writing %s failed!", data->set.str[STRING_SSH_KNOWNHOSTS]); } } @@ -626,7 +625,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data) int i; for(i = 0; i < 16; i++) msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]); - infof(data, "SSH MD5 fingerprint: %s\n", md5buffer); + infof(data, "SSH MD5 fingerprint: %s", md5buffer); } /* Before we authenticate we check the hostkey's MD5 fingerprint @@ -645,7 +644,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data) sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; return sshc->actualcode; } - infof(data, "MD5 checksum match!\n"); + infof(data, "MD5 checksum match!"); /* as we already matched, we skip the check for known hosts */ return CURLE_OK; } @@ -702,7 +701,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) if(store->name[0] == '[') { kh_name_end = strstr(store->name, "]:"); if(!kh_name_end) { - infof(data, "Invalid host pattern %s in %s\n", + infof(data, "Invalid host pattern %s in %s", store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); continue; } @@ -729,7 +728,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) } if(found) { - infof(data, "Found host %s in %s\n", + infof(data, "Found host %s in %s", conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) { @@ -768,13 +767,13 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) return CURLE_SSH; } - infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method); + infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method); result = libssh2_session_error_to_CURLE( libssh2_session_method_pref( sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method)); } else { - infof(data, "Did not find host %s in %s\n", + infof(data, "Did not find host %s in %s", conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); } } @@ -874,7 +873,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(!sshc->authlist) { if(libssh2_userauth_authenticated(sshc->ssh_session)) { sshc->authed = TRUE; - infof(data, "SSH user accepted with no authentication\n"); + infof(data, "SSH user accepted with no authentication"); state(data, SSH_AUTH_DONE); break; } @@ -887,7 +886,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) } break; } - infof(data, "SSH authentication methods available: %s\n", + infof(data, "SSH authentication methods available: %s", sshc->authlist); state(data, SSH_AUTH_PKEY_INIT); @@ -972,8 +971,8 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) sshc->passphrase = ""; if(sshc->rsa_pub) - infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); - infof(data, "Using SSH private key file '%s'\n", sshc->rsa); + infof(data, "Using SSH public key file '%s'", sshc->rsa_pub); + infof(data, "Using SSH private key file '%s'", sshc->rsa); state(data, SSH_AUTH_PKEY); } @@ -1000,14 +999,14 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == 0) { sshc->authed = TRUE; - infof(data, "Initialized SSH public key authentication\n"); + infof(data, "Initialized SSH public key authentication"); state(data, SSH_AUTH_DONE); } else { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "SSH public key authentication failed: %s\n", err_msg); + infof(data, "SSH public key authentication failed: %s", err_msg); state(data, SSH_AUTH_PASS_INIT); rc = 0; /* clear rc and continue */ } @@ -1035,7 +1034,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) } if(rc == 0) { sshc->authed = TRUE; - infof(data, "Initialized password authentication\n"); + infof(data, "Initialized password authentication"); state(data, SSH_AUTH_DONE); } else { @@ -1069,7 +1068,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(!sshc->ssh_agent) { sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session); if(!sshc->ssh_agent) { - infof(data, "Could not create agent object\n"); + infof(data, "Could not create agent object"); state(data, SSH_AUTH_KEY_INIT); break; @@ -1080,7 +1079,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) break; if(rc < 0) { - infof(data, "Failure connecting to agent\n"); + infof(data, "Failure connecting to agent"); state(data, SSH_AUTH_KEY_INIT); rc = 0; /* clear rc and continue */ } @@ -1100,7 +1099,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) break; if(rc < 0) { - infof(data, "Failure requesting identities to agent\n"); + infof(data, "Failure requesting identities to agent"); state(data, SSH_AUTH_KEY_INIT); rc = 0; /* clear rc and continue */ } @@ -1136,13 +1135,13 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) } if(rc < 0) - infof(data, "Failure requesting identities to agent\n"); + infof(data, "Failure requesting identities to agent"); else if(rc == 1) - infof(data, "No identity would match\n"); + infof(data, "No identity would match"); if(rc == LIBSSH2_ERROR_NONE) { sshc->authed = TRUE; - infof(data, "Agent based authentication successful\n"); + infof(data, "Agent based authentication successful"); state(data, SSH_AUTH_DONE); } else { @@ -1174,7 +1173,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) } if(rc == 0) { sshc->authed = TRUE; - infof(data, "Initialized keyboard interactive authentication\n"); + infof(data, "Initialized keyboard interactive authentication"); } state(data, SSH_AUTH_DONE); break; @@ -1190,7 +1189,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) /* * At this point we have an authenticated ssh session. */ - infof(data, "Authentication complete\n"); + infof(data, "Authentication complete"); Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */ @@ -1201,7 +1200,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_INIT); break; } - infof(data, "SSH CONNECT phase done\n"); + infof(data, "SSH CONNECT phase done"); state(data, SSH_STOP); break; @@ -1261,7 +1260,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) a time-out or similar */ result = CURLE_SSH; sshc->actualcode = result; - DEBUGF(infof(data, "error = %lu makes libcurl = %d\n", + DEBUGF(infof(data, "error = %lu makes libcurl = %d", sftperr, (int)result)); state(data, SSH_STOP); break; @@ -1271,7 +1270,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) we get the homedir here, we get the "workingpath" in the DO action since the homedir will remain the same between request but the working path will not. */ - DEBUGF(infof(data, "SSH CONNECT phase done\n")); + DEBUGF(infof(data, "SSH CONNECT phase done")); state(data, SSH_STOP); break; @@ -1285,7 +1284,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) } if(data->set.quote) { - infof(data, "Sending quote commands\n"); + infof(data, "Sending quote commands"); sshc->quote_item = data->set.quote; state(data, SSH_SFTP_QUOTE); } @@ -1296,7 +1295,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) case SSH_SFTP_POSTQUOTE_INIT: if(data->set.postquote) { - infof(data, "Sending quote commands\n"); + infof(data, "Sending quote commands"); sshc->quote_item = data->set.postquote; state(data, SSH_SFTP_QUOTE); } @@ -2048,7 +2047,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(sshc->slash_pos) { *sshc->slash_pos = 0; - infof(data, "Creating directory '%s'\n", sshp->path); + infof(data, "Creating directory '%s'", sshp->path); state(data, SSH_SFTP_CREATE_DIRS_MKDIR); break; } @@ -2411,7 +2410,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) if(data->req.size == 0) { /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); - infof(data, "File already completely downloaded\n"); + infof(data, "File already completely downloaded"); state(data, SSH_STOP); break; } @@ -2446,14 +2445,14 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg); + infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); } sshc->sftp_handle = NULL; } Curl_safefree(sshp->path); - DEBUGF(infof(data, "SFTP DONE done\n")); + DEBUGF(infof(data, "SFTP DONE done")); /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT After nextstate is executed, the control should come back to @@ -2483,7 +2482,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg); + infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); } sshc->sftp_handle = NULL; } @@ -2493,7 +2492,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) break; } if(rc < 0) { - infof(data, "Failed to stop libssh2 sftp subsystem\n"); + infof(data, "Failed to stop libssh2 sftp subsystem"); } sshc->sftp_session = NULL; } @@ -2668,7 +2667,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to send libssh2 channel EOF: %d %s\n", + infof(data, "Failed to send libssh2 channel EOF: %d %s", rc, err_msg); } } @@ -2685,7 +2684,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg); + infof(data, "Failed to get channel EOF: %d %s", rc, err_msg); } } state(data, SSH_SCP_WAIT_CLOSE); @@ -2701,7 +2700,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Channel failed to close: %d %s\n", rc, err_msg); + infof(data, "Channel failed to close: %d %s", rc, err_msg); } } state(data, SSH_SCP_CHANNEL_FREE); @@ -2717,12 +2716,12 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to free libssh2 scp subsystem: %d %s\n", + infof(data, "Failed to free libssh2 scp subsystem: %d %s", rc, err_msg); } sshc->ssh_channel = NULL; } - DEBUGF(infof(data, "SCP DONE phase complete\n")); + DEBUGF(infof(data, "SCP DONE phase complete")); #if 0 /* PREV */ state(data, SSH_SESSION_DISCONNECT); #endif @@ -2743,7 +2742,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to free libssh2 scp subsystem: %d %s\n", + infof(data, "Failed to free libssh2 scp subsystem: %d %s", rc, err_msg); } sshc->ssh_channel = NULL; @@ -2758,7 +2757,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to disconnect libssh2 session: %d %s\n", + infof(data, "Failed to disconnect libssh2 session: %d %s", rc, err_msg); } } @@ -2787,7 +2786,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to disconnect from libssh2 agent: %d %s\n", + infof(data, "Failed to disconnect from libssh2 agent: %d %s", rc, err_msg); } libssh2_agent_free(sshc->ssh_agent); @@ -2809,7 +2808,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); - infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg); + infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg); } sshc->ssh_session = NULL; } @@ -2938,6 +2937,7 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, { struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; + struct curltime dis = Curl_now(); while((sshc->state != SSH_STOP) && !result) { bool block; @@ -2962,6 +2962,12 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, return CURLE_OPERATION_TIMEDOUT; } } + else if(Curl_timediff(now, dis) > 1000) { + /* disconnect timeout */ + failf(data, "Disconnect timed out"); + result = CURLE_OK; + break; + } if(block) { int dir = libssh2_session_block_directions(sshc->ssh_session); @@ -3078,10 +3084,10 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) #ifdef CURL_LIBSSH2_DEBUG if(conn->user) { - infof(data, "User: %s\n", conn->user); + infof(data, "User: %s", conn->user); } if(conn->passwd) { - infof(data, "Password: %s\n", conn->passwd); + infof(data, "Password: %s", conn->passwd); } sock = conn->sock[FIRSTSOCKET]; #endif /* CURL_LIBSSH2_DEBUG */ @@ -3115,7 +3121,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) sshrecv.recvptr = ssh_tls_recv; sshsend.sendptr = ssh_tls_send; - infof(data, "Uses HTTPS proxy!\n"); + infof(data, "Uses HTTPS proxy!"); /* Setup libssh2 callbacks to make it read/write TLS from the socket. @@ -3153,7 +3159,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) #if LIBSSH2_VERSION_NUM >= 0x010208 if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) #endif - infof(data, "Failed to enable compression for ssh session\n"); + infof(data, "Failed to enable compression for ssh session"); } #ifdef HAVE_LIBSSH2_KNOWNHOST_API @@ -3171,14 +3177,14 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(rc < 0) - infof(data, "Failed to read known hosts from %s\n", + infof(data, "Failed to read known hosts from %s", data->set.str[STRING_SSH_KNOWNHOSTS]); } #endif /* HAVE_LIBSSH2_KNOWNHOST_API */ #ifdef CURL_LIBSSH2_DEBUG libssh2_trace(sshc->ssh_session, ~0); - infof(data, "SSH socket: %d\n", (int)sock); + infof(data, "SSH socket: %d", (int)sock); #endif /* CURL_LIBSSH2_DEBUG */ state(data, SSH_INIT); @@ -3205,7 +3211,7 @@ CURLcode scp_perform(struct Curl_easy *data, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); *dophase_done = FALSE; /* not done yet */ @@ -3218,7 +3224,7 @@ CURLcode scp_perform(struct Curl_easy *data, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; @@ -3232,7 +3238,7 @@ static CURLcode scp_doing(struct Curl_easy *data, result = ssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; } @@ -3394,7 +3400,7 @@ CURLcode sftp_perform(struct Curl_easy *data, { CURLcode result = CURLE_OK; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); *dophase_done = FALSE; /* not done yet */ @@ -3407,7 +3413,7 @@ CURLcode sftp_perform(struct Curl_easy *data, *connected = data->conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; @@ -3420,7 +3426,7 @@ static CURLcode sftp_doing(struct Curl_easy *data, CURLcode result = ssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; } @@ -3435,7 +3441,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, struct ssh_conn *sshc = &conn->proto.sshc; (void) dead_connection; - DEBUGF(infof(data, "SSH DISCONNECT starts now\n")); + DEBUGF(infof(data, "SSH DISCONNECT starts now")); if(sshc->ssh_session) { /* only if there's a session still around to use! */ @@ -3443,7 +3449,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, result = ssh_block_statemach(data, conn, TRUE); } - DEBUGF(infof(data, "SSH DISCONNECT is done\n")); + DEBUGF(infof(data, "SSH DISCONNECT is done")); return result; @@ -3602,9 +3608,9 @@ void Curl_ssh_cleanup(void) #endif } -size_t Curl_ssh_version(char *buffer, size_t buflen) +void Curl_ssh_version(char *buffer, size_t buflen) { - return msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION); + (void)msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION); } /* The SSH session is associated with the *CONNECTION* but the callback user diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h index 505b0787c5f..7972081ec61 100644 --- a/lib/vssh/ssh.h +++ b/lib/vssh/ssh.h @@ -262,7 +262,7 @@ extern const struct Curl_handler Curl_handler_sftp; /* generic SSH backend functions */ CURLcode Curl_ssh_init(void); void Curl_ssh_cleanup(void); -size_t Curl_ssh_version(char *buffer, size_t buflen); +void Curl_ssh_version(char *buffer, size_t buflen); void Curl_ssh_attach(struct Curl_easy *data, struct connectdata *conn); #else diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c index 9f3266a24d8..4b1e2ec5e34 100644 --- a/lib/vssh/wolfssh.c +++ b/lib/vssh/wolfssh.c @@ -205,7 +205,7 @@ static void state(struct Curl_easy *data, sshstate nowstate) DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); if(sshc->state != nowstate) { - infof(data, "wolfssh %p state change from %s to %s\n", + infof(data, "wolfssh %p state change from %s to %s", (void *)sshc, names[sshc->state], names[nowstate]); } #endif @@ -274,7 +274,7 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex, return -1; } DEBUGASSERT(rc == (int)len); - infof(data, "sent %zd bytes SFTP from offset %zd\n", + infof(data, "sent %zd bytes SFTP from offset %zd", len, sshc->offset); sshc->offset += len; return (ssize_t)rc; @@ -348,7 +348,7 @@ static int userauth(byte authtype, void *ctx) { struct Curl_easy *data = ctx; - DEBUGF(infof(data, "wolfssh callback: type %s\n", + DEBUGF(infof(data, "wolfssh callback: type %s", authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" : "PUBLICCKEY")); if(authtype == WOLFSSH_USERAUTH_PASSWORD) { @@ -468,7 +468,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) state(data, SSH_STOP); return CURLE_SSH; } - infof(data, "wolfssh connected!\n"); + infof(data, "wolfssh connected!"); state(data, SSH_STOP); break; case SSH_STOP: @@ -489,7 +489,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) return CURLE_OK; } else if(rc == WS_SUCCESS) { - infof(data, "wolfssh SFTP connected!\n"); + infof(data, "wolfssh SFTP connected!"); state(data, SSH_SFTP_REALPATH); } else { @@ -518,7 +518,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) else { memcpy(sshc->homedir, name->fName, name->fSz); sshc->homedir[name->fSz] = 0; - infof(data, "wolfssh SFTP realpath succeeded!\n"); + infof(data, "wolfssh SFTP realpath succeeded!"); } wolfSSH_SFTPNAME_list_free(name); state(data, SSH_STOP); @@ -536,7 +536,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) } if(data->set.quote) { - infof(data, "Sending quote commands\n"); + infof(data, "Sending quote commands"); sshc->quote_item = data->set.quote; state(data, SSH_SFTP_QUOTE); } @@ -616,7 +616,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) return CURLE_OK; } else if(rc == WS_SUCCESS) { - infof(data, "wolfssh SFTP open succeeded!\n"); + infof(data, "wolfssh SFTP open succeeded!"); } else { failf(data, "wolfssh SFTP upload open failed: %d", rc); @@ -727,7 +727,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) return CURLE_OK; } else if(rc == WS_SUCCESS) { - infof(data, "wolfssh SFTP open succeeded!\n"); + infof(data, "wolfssh SFTP open succeeded!"); state(data, SSH_SFTP_DOWNLOAD_STAT); return CURLE_OK; } @@ -753,7 +753,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) return CURLE_OK; } else if(rc == WS_SUCCESS) { - infof(data, "wolfssh STAT succeeded!\n"); + infof(data, "wolfssh STAT succeeded!"); } else { failf(data, "wolfssh SFTP open failed: %d", rc); @@ -769,12 +769,12 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) data->req.maxdownload = size; Curl_pgrsSetDownloadSize(data, size); - infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size); + infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes", size); /* We cannot seek with wolfSSH so resuming and range requests are not possible */ if(data->state.use_range || data->state.resume_from) { - infof(data, "wolfSSH cannot do range/seek on SFTP\n"); + infof(data, "wolfSSH cannot do range/seek on SFTP"); return CURLE_BAD_DOWNLOAD_RESUME; } @@ -782,7 +782,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) if(data->req.size == 0) { /* no data to transfer */ Curl_setup_transfer(data, -1, -1, FALSE, -1); - infof(data, "File already completely downloaded\n"); + infof(data, "File already completely downloaded"); state(data, SSH_STOP); break; } @@ -911,7 +911,7 @@ static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done) /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then try again */ if(*done) { - DEBUGF(infof(data, "wssh_statemach_act says DONE\n")); + DEBUGF(infof(data, "wssh_statemach_act says DONE")); } } while(!result && !*done && !block); @@ -937,7 +937,7 @@ CURLcode wsftp_perform(struct Curl_easy *data, CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - DEBUGF(infof(data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts")); *dophase_done = FALSE; /* not done yet */ @@ -950,7 +950,7 @@ CURLcode wsftp_perform(struct Curl_easy *data, *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; @@ -1107,7 +1107,7 @@ static CURLcode wsftp_doing(struct Curl_easy *data, CURLcode result = wssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete")); } return result; } @@ -1119,7 +1119,7 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)dead; - DEBUGF(infof(data, "SSH DISCONNECT starts now\n")); + DEBUGF(infof(data, "SSH DISCONNECT starts now")); if(conn->proto.sshc.ssh_session) { /* only if there's a session still around to use! */ @@ -1127,7 +1127,7 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data, result = wssh_block_statemach(data, TRUE); } - DEBUGF(infof(data, "SSH DISCONNECT is done\n")); + DEBUGF(infof(data, "SSH DISCONNECT is done")); return result; } @@ -1148,9 +1148,9 @@ static int wssh_getsock(struct Curl_easy *data, return bitmap; } -size_t Curl_ssh_version(char *buffer, size_t buflen) +void Curl_ssh_version(char *buffer, size_t buflen) { - return msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING); + (void)msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING); } CURLcode Curl_ssh_init(void) diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c index 7f729713d89..e87649e2a75 100644 --- a/lib/vtls/bearssl.c +++ b/lib/vtls/bearssl.c @@ -68,6 +68,14 @@ struct cafile_parser { size_t dn_len; }; +#define CAFILE_SOURCE_PATH 1 +#define CAFILE_SOURCE_BLOB 2 +struct cafile_source { + const int type; + const char * const data; + const size_t len; +}; + static void append_dn(void *ctx, const void *buf, size_t len) { struct cafile_parser *ca = ctx; @@ -90,7 +98,8 @@ static void x509_push(void *ctx, const void *buf, size_t len) br_x509_decoder_push(&ca->xc, buf, len); } -static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, +static CURLcode load_cafile(struct cafile_source *source, + br_x509_trust_anchor **anchors, size_t *anchors_len) { struct cafile_parser ca; @@ -100,13 +109,22 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, br_x509_trust_anchor *new_anchors; size_t new_anchors_len; br_x509_pkey *pkey; - FILE *fp; - unsigned char buf[BUFSIZ], *p; + FILE *fp = 0; + unsigned char buf[BUFSIZ]; + const unsigned char *p; const char *name; size_t n, i, pushed; - fp = fopen(path, "rb"); - if(!fp) + DEBUGASSERT(source->type == CAFILE_SOURCE_PATH + || source->type == CAFILE_SOURCE_BLOB); + + if(source->type == CAFILE_SOURCE_PATH) { + fp = fopen(source->data, "rb"); + if(!fp) + return CURLE_SSL_CACERT_BADFILE; + } + + if(source->type == CAFILE_SOURCE_BLOB && source->len > (size_t)INT_MAX) return CURLE_SSL_CACERT_BADFILE; ca.err = CURLE_OK; @@ -115,11 +133,17 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, ca.anchors_len = 0; br_pem_decoder_init(&pc); br_pem_decoder_setdest(&pc, x509_push, &ca); - for(;;) { - n = fread(buf, 1, sizeof(buf), fp); - if(n == 0) - break; - p = buf; + do { + if(source->type == CAFILE_SOURCE_PATH) { + n = fread(buf, 1, sizeof(buf), fp); + if(n == 0) + break; + p = buf; + } + else if(source->type == CAFILE_SOURCE_BLOB) { + n = source->len; + p = (unsigned char *) source->data; + } while(n) { pushed = br_pem_decoder_push(&pc, p, n); if(ca.err) @@ -211,12 +235,13 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, goto fail; } } - } - if(ferror(fp)) + } while(source->type != CAFILE_SOURCE_BLOB); + if(fp && ferror(fp)) ca.err = CURLE_READ_ERROR; fail: - fclose(fp); + if(fp) + fclose(fp); if(ca.err == CURLE_OK) { *anchors = ca.anchors; *anchors_len = ca.anchors_len; @@ -299,8 +324,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); - const char * const hostname = SSL_HOST_NAME(); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile)); + const char *hostname = SSL_HOST_NAME(); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const bool verifyhost = SSL_CONN_CONFIG(verifyhost); CURLcode ret; @@ -340,8 +368,30 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } + if(ca_info_blob) { + struct cafile_source source = { + CAFILE_SOURCE_BLOB, + ca_info_blob->data, + ca_info_blob->len, + }; + ret = load_cafile(&source, &backend->anchors, &backend->anchors_len); + if(ret != CURLE_OK) { + if(verifypeer) { + failf(data, "error importing CA certificate blob"); + return ret; + } + /* Only warn if no certificate verification is required. */ + infof(data, "error importing CA certificate blob, continuing anyway"); + } + } + if(ssl_cafile) { - ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len); + struct cafile_source source = { + CAFILE_SOURCE_PATH, + ssl_cafile, + 0, + }; + ret = load_cafile(&source, &backend->anchors, &backend->anchors_len); if(ret != CURLE_OK) { if(verifypeer) { failf(data, "error setting certificate verify locations." @@ -349,7 +399,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, return ret; } infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); + " continuing anyway:"); } } @@ -373,7 +423,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, &session, NULL, sockindex)) { br_ssl_engine_set_session_parameters(&backend->ctx.eng, session); - infof(data, "BearSSL: re-using session ID\n"); + infof(data, "BearSSL: re-using session ID"); } Curl_ssl_sessionid_unlock(data); } @@ -392,12 +442,12 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, #endif ) { backend->protocols[cur++] = ALPN_H2; - infof(data, "ALPN, offering %s\n", ALPN_H2); + infof(data, "ALPN, offering %s", ALPN_H2); } #endif backend->protocols[cur++] = ALPN_HTTP_1_1; - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s", ALPN_HTTP_1_1); br_ssl_engine_set_protocol_names(&backend->ctx.eng, backend->protocols, cur); @@ -538,7 +588,7 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng); if(protocol) { - infof(data, "ALPN, server accepted to use %s\n", protocol); + infof(data, "ALPN, server accepted to use %s", protocol); #ifdef USE_HTTP2 if(!strcmp(protocol, ALPN_H2)) @@ -548,12 +598,12 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, if(!strcmp(protocol, ALPN_HTTP_1_1)) conn->negnpn = CURL_HTTP_VERSION_1_1; else - infof(data, "ALPN, unrecognized protocol %s\n", protocol); + infof(data, "ALPN, unrecognized protocol %s", protocol); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } else - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); } if(SSL_SET_OPTION(primary.sessionid)) { @@ -840,30 +890,32 @@ static CURLcode bearssl_sha256sum(const unsigned char *input, } const struct Curl_ssl Curl_ssl_bearssl = { - { CURLSSLBACKEND_BEARSSL, "bearssl" }, - 0, + { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */ + SSLSUPP_CAINFO_BLOB, sizeof(struct ssl_backend_data), - Curl_none_init, - Curl_none_cleanup, - bearssl_version, - Curl_none_check_cxn, - Curl_none_shutdown, - bearssl_data_pending, - bearssl_random, - Curl_none_cert_status_request, - bearssl_connect, - bearssl_connect_nonblocking, - Curl_ssl_getsock, - bearssl_get_internals, - bearssl_close, - Curl_none_close_all, - bearssl_session_free, - Curl_none_set_engine, - Curl_none_set_engine_default, - Curl_none_engines_list, - Curl_none_false_start, - bearssl_sha256sum + Curl_none_init, /* init */ + Curl_none_cleanup, /* cleanup */ + bearssl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + bearssl_data_pending, /* data_pending */ + bearssl_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + bearssl_connect, /* connect */ + bearssl_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ + bearssl_get_internals, /* get_internals */ + bearssl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + bearssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + bearssl_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_BEARSSL */ diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c index ca953769d1b..e451f6aebeb 100644 --- a/lib/vtls/gskit.c +++ b/lib/vtls/gskit.c @@ -180,6 +180,7 @@ static bool is_separator(char c) static CURLcode gskit_status(struct Curl_easy *data, int rc, const char *procname, CURLcode defcode) { + char buffer[STRERROR_LEN]; /* Process GSKit status and map it to a CURLcode. */ switch(rc) { case GSK_OK: @@ -208,7 +209,8 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, case ENOMEM: return CURLE_OUT_OF_MEMORY; default: - failf(data, "%s I/O error: %s", procname, strerror(errno)); + failf(data, "%s I/O error: %s", procname, + Curl_strerror(errno, buffer, sizeof(buffer))); break; } break; @@ -223,13 +225,15 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_enum(h, id, value); switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: - failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); + failf(data, "gsk_attribute_set_enum() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); break; case GSK_ATTRIBUTE_INVALID_ID: if(unsupported_ok) @@ -245,13 +249,15 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, GSK_BUF_ID id, const char *buffer, bool unsupported_ok) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_buffer(h, id, buffer, 0); switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: - failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); + failf(data, "gsk_attribute_set_buffer() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); break; case GSK_ATTRIBUTE_INVALID_ID: if(unsupported_ok) @@ -267,6 +273,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, static CURLcode set_numeric(struct Curl_easy *data, gsk_handle h, GSK_NUM_ID id, int value) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_numeric_value(h, id, value); switch(rc) { @@ -274,7 +281,7 @@ static CURLcode set_numeric(struct Curl_easy *data, return CURLE_OK; case GSK_ERROR_IO: failf(data, "gsk_attribute_set_numeric_value() I/O error: %s", - strerror(errno)); + Curl_strerror(errno, buffer, sizeof(buffer))); break; default: failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc)); @@ -287,13 +294,15 @@ static CURLcode set_numeric(struct Curl_easy *data, static CURLcode set_callback(struct Curl_easy *data, gsk_handle h, GSK_CALLBACK_ID id, void *info) { + char buffer[STRERROR_LEN]; int rc = gsk_attribute_set_callback(h, id, info); switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: - failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno)); + failf(data, "gsk_attribute_set_callback() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); break; default: failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc)); @@ -966,7 +975,9 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data, continue; /* Retry. */ } if(errno != ETIME) { - failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno)); + char buffer[STRERROR_LEN]; + failf(data, "QsoWaitForIOCompletion() I/O error: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); cancel_async_handshake(conn, sockindex); close_async_handshake(connssl); return CURLE_SSL_CONNECT_ERROR; @@ -1011,7 +1022,7 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, CURLE_OK) { int i; - infof(data, "Server certificate:\n"); + infof(data, "Server certificate:"); p = cdev; for(i = 0; i++ < cdec; p++) switch(p->cert_data_id) { @@ -1020,16 +1031,16 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, certend = cert + cdev->cert_data_l; break; case CERT_DN_PRINTABLE: - infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p); + infof(data, "\t subject: %.*s", p->cert_data_l, p->cert_data_p); break; case CERT_ISSUER_DN_PRINTABLE: - infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p); + infof(data, "\t issuer: %.*s", p->cert_data_l, p->cert_data_p); break; case CERT_VALID_FROM: - infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p); + infof(data, "\t start date: %.*s", p->cert_data_l, p->cert_data_p); break; case CERT_VALID_TO: - infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p); + infof(data, "\t expire date: %.*s", p->cert_data_l, p->cert_data_p); break; } } @@ -1192,6 +1203,7 @@ static int gskit_shutdown(struct Curl_easy *data, int what; int rc; char buf[120]; + int loop = 10; /* don't get stuck */ if(!BACKEND->handle) return 0; @@ -1206,7 +1218,7 @@ static int gskit_shutdown(struct Curl_easy *data, what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); - for(;;) { + while(loop--) { ssize_t nread; if(what < 0) { @@ -1228,7 +1240,8 @@ static int gskit_shutdown(struct Curl_easy *data, nread = read(conn->sock[sockindex], buf, sizeof(buf)); if(nread < 0) { - failf(data, "read: %s", strerror(errno)); + char buffer[STRERROR_LEN]; + failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer))); rc = -1; } diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index ecde5c44dee..1b145d8ebb6 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -147,7 +147,7 @@ static void showtime(struct Curl_easy *data, msnprintf(str, sizeof(str), - "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", + " %s: %s, %02d %s %4d %02d:%02d:%02d GMT", text, Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -156,7 +156,7 @@ static void showtime(struct Curl_easy *data, tm->tm_hour, tm->tm_min, tm->tm_sec); - infof(data, "%s\n", str); + infof(data, "%s", str); } #endif @@ -266,7 +266,7 @@ static CURLcode handshake(struct Curl_easy *data, if(!strerr) strerr = gnutls_strerror(rc); - infof(data, "gnutls_handshake() warning: %s\n", strerr); + infof(data, "gnutls_handshake() warning: %s", strerr); continue; } else if(rc < 0) { @@ -330,6 +330,9 @@ set_ssl_version_min_max(struct Curl_easy *data, ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; } } + else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) { + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3; + } switch(ssl_version | ssl_version_max) { case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: @@ -338,11 +341,11 @@ set_ssl_version_min_max(struct Curl_easy *data, return CURLE_OK; case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:+VERS-TLS1.1"; + "+VERS-TLS1.1:+VERS-TLS1.0"; return CURLE_OK; case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2"; + "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0"; return CURLE_OK; case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" @@ -350,7 +353,7 @@ set_ssl_version_min_max(struct Curl_easy *data, return CURLE_OK; case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.1:+VERS-TLS1.2"; + "+VERS-TLS1.2:+VERS-TLS1.1"; return CURLE_OK; case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" @@ -360,25 +363,16 @@ set_ssl_version_min_max(struct Curl_easy *data, *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.3"; return CURLE_OK; - case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2" - ":+VERS-TLS1.3"; - return CURLE_OK; - case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT: - *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.1:+VERS-TLS1.2" - ":+VERS-TLS1.3"; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0"; return CURLE_OK; - case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT: + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.2" - ":+VERS-TLS1.3"; + "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1"; return CURLE_OK; - case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT: + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.2" - ":+VERS-TLS1.3"; + "+VERS-TLS1.3:+VERS-TLS1.2"; return CURLE_OK; } @@ -438,7 +432,7 @@ gtls_connect_step1(struct Curl_easy *data, #ifdef HAVE_GNUTLS_SRP if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); + infof(data, "Using TLS-SRP username: %s", SSL_SET_OPTION(username)); rc = gnutls_srp_allocate_client_credentials( &backend->srp_client_cred); @@ -468,7 +462,7 @@ gtls_connect_step1(struct Curl_easy *data, SSL_CONN_CONFIG(CAfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)\n", + infof(data, "error reading ca cert file %s (%s)", SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc)); if(SSL_CONN_CONFIG(verifypeer)) { *certverifyresult = rc; @@ -476,7 +470,7 @@ gtls_connect_step1(struct Curl_easy *data, } } else - infof(data, "found %d certificates in %s\n", rc, + infof(data, "found %d certificates in %s", rc, SSL_CONN_CONFIG(CAfile)); } @@ -486,7 +480,7 @@ gtls_connect_step1(struct Curl_easy *data, SSL_CONN_CONFIG(CApath), GNUTLS_X509_FMT_PEM); if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)\n", + infof(data, "error reading ca cert file %s (%s)", SSL_CONN_CONFIG(CApath), gnutls_strerror(rc)); if(SSL_CONN_CONFIG(verifypeer)) { *certverifyresult = rc; @@ -494,7 +488,7 @@ gtls_connect_step1(struct Curl_easy *data, } } else - infof(data, "found %d certificates in %s\n", + infof(data, "found %d certificates in %s", rc, SSL_CONN_CONFIG(CApath)); } @@ -517,7 +511,7 @@ gtls_connect_step1(struct Curl_easy *data, return CURLE_SSL_CRL_BADFILE; } else - infof(data, "found %d CRL in %s\n", + infof(data, "found %d CRL in %s", rc, SSL_SET_OPTION(CRLfile)); } @@ -550,7 +544,7 @@ gtls_connect_step1(struct Curl_easy *data, (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, strlen(hostname)) < 0)) infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); + "TLS extension"); /* Use default priorities */ rc = gnutls_set_default_priority(session); @@ -603,11 +597,12 @@ gtls_connect_step1(struct Curl_easy *data, free(prioritysrp); if((rc == GNUTLS_E_INVALID_REQUEST) && err) { - infof(data, "This GnuTLS does not support SRP\n"); + infof(data, "This GnuTLS does not support SRP"); } } else { #endif + infof(data, "GnuTLS ciphers: %s", prioritylist); rc = gnutls_priority_set_direct(session, prioritylist, &err); #ifdef HAVE_GNUTLS_SRP } @@ -632,14 +627,14 @@ gtls_connect_step1(struct Curl_easy *data, protocols[cur].data = (unsigned char *)ALPN_H2; protocols[cur].size = ALPN_H2_LENGTH; cur++; - infof(data, "ALPN, offering %.*s\n", ALPN_H2_LENGTH, ALPN_H2); + infof(data, "ALPN, offering %.*s", ALPN_H2_LENGTH, ALPN_H2); } #endif protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; protocols[cur].size = ALPN_HTTP_1_1_LENGTH; cur++; - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s", ALPN_HTTP_1_1); gnutls_alpn_set_protocols(session, protocols, cur, 0); } @@ -745,7 +740,7 @@ gtls_connect_step1(struct Curl_easy *data, gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ - infof(data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID"); } Curl_ssl_sessionid_unlock(data); } @@ -848,7 +843,7 @@ gtls_connect_step3(struct Curl_easy *data, gnutls_cipher_get(session), gnutls_mac_get(session)); - infof(data, "SSL connection using %s / %s\n", + infof(data, "SSL connection using %s / %s", gnutls_protocol_get_name(version), ptr); /* This function will return the peer's raw certificate (chain) as sent by @@ -861,7 +856,7 @@ gtls_connect_step3(struct Curl_easy *data, if(!chainp) { if(SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost) || - SSL_SET_OPTION(issuercert)) { + SSL_CONN_CONFIG(issuercert)) { #ifdef HAVE_GNUTLS_SRP if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP && SSL_SET_OPTION(username) != NULL @@ -879,7 +874,7 @@ gtls_connect_step3(struct Curl_easy *data, } #endif } - infof(data, "\t common name: WARNING couldn't obtain\n"); + infof(data, " common name: WARNING couldn't obtain"); } if(data->set.ssl.certinfo && chainp) { @@ -926,13 +921,13 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_PEER_FAILED_VERIFICATION; } else - infof(data, "\t server certificate verification FAILED\n"); + infof(data, " server certificate verification FAILED"); } else - infof(data, "\t server certificate verification OK\n"); + infof(data, " server certificate verification OK"); } else - infof(data, "\t server certificate verification SKIPPED\n"); + infof(data, " server certificate verification SKIPPED"); if(SSL_CONN_CONFIG(verifystatus)) { if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { @@ -944,7 +939,7 @@ gtls_connect_step3(struct Curl_easy *data, rc = gnutls_ocsp_status_request_get(session, &status_request); - infof(data, "\t server certificate status verification FAILED\n"); + infof(data, " server certificate status verification FAILED"); if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { failf(data, "No OCSP response received"); @@ -1032,10 +1027,10 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_SSL_INVALIDCERTSTATUS; } else - infof(data, "\t server certificate status verification OK\n"); + infof(data, " server certificate status verification OK"); } else - infof(data, "\t server certificate status verification SKIPPED\n"); + infof(data, " server certificate status verification SKIPPED"); /* initialize an X.509 certificate structure. */ gnutls_x509_crt_init(&x509_cert); @@ -1045,21 +1040,21 @@ gtls_connect_step3(struct Curl_easy *data, gnutls_x509_crt_t format */ gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); - if(SSL_SET_OPTION(issuercert)) { + if(SSL_CONN_CONFIG(issuercert)) { gnutls_x509_crt_init(&x509_issuer); - issuerp = load_file(SSL_SET_OPTION(issuercert)); + issuerp = load_file(SSL_CONN_CONFIG(issuercert)); gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); gnutls_x509_crt_deinit(x509_issuer); unload_file(issuerp); if(rc <= 0) { failf(data, "server certificate issuer check failed (IssuerCert: %s)", - SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); + SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_ISSUER_ERROR; } - infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", - SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); + infof(data, " server certificate issuer check OK (Issuer Cert: %s)", + SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none"); } size = sizeof(certname); @@ -1069,7 +1064,7 @@ gtls_connect_step3(struct Curl_easy *data, certname, &size); if(rc) { - infof(data, "error fetching CN from cert:%s\n", + infof(data, "error fetching CN from cert:%s", gnutls_strerror(rc)); } @@ -1129,11 +1124,11 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_PEER_FAILED_VERIFICATION; } else - infof(data, "\t common name: %s (does not match '%s')\n", + infof(data, " common name: %s (does not match '%s')", certname, SSL_HOST_DISPNAME()); } else - infof(data, "\t common name: %s (matched)\n", certname); + infof(data, " common name: %s (matched)", certname); /* Check for time-based validity */ certclock = gnutls_x509_crt_get_expiration_time(x509_cert); @@ -1146,7 +1141,7 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } else - infof(data, "\t server certificate expiration date verify FAILED\n"); + infof(data, " server certificate expiration date verify FAILED"); } else { if(certclock < time(NULL)) { @@ -1157,10 +1152,10 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_PEER_FAILED_VERIFICATION; } else - infof(data, "\t server certificate expiration date FAILED\n"); + infof(data, " server certificate expiration date FAILED"); } else - infof(data, "\t server certificate expiration date OK\n"); + infof(data, " server certificate expiration date OK"); } certclock = gnutls_x509_crt_get_activation_time(x509_cert); @@ -1173,7 +1168,7 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } else - infof(data, "\t server certificate activation date verify FAILED\n"); + infof(data, " server certificate activation date verify FAILED"); } else { if(certclock > time(NULL)) { @@ -1184,10 +1179,10 @@ gtls_connect_step3(struct Curl_easy *data, return CURLE_PEER_FAILED_VERIFICATION; } else - infof(data, "\t server certificate activation date FAILED\n"); + infof(data, " server certificate activation date FAILED"); } else - infof(data, "\t server certificate activation date OK\n"); + infof(data, " server certificate activation date OK"); } ptr = SSL_PINNED_PUB_KEY(); @@ -1213,19 +1208,19 @@ gtls_connect_step3(struct Curl_easy *data, #ifndef CURL_DISABLE_VERBOSE_STRINGS /* public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); - infof(data, "\t certificate public key: %s\n", + infof(data, " certificate public key: %s", gnutls_pk_algorithm_get_name(algo)); /* version of the X.509 certificate. */ - infof(data, "\t certificate version: #%d\n", + infof(data, " certificate version: #%d", gnutls_x509_crt_get_version(x509_cert)); rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields); if(rc) - infof(data, "Failed to get certificate name\n"); + infof(data, "Failed to get certificate name"); else { - infof(data, "\t subject: %s\n", certfields.data); + infof(data, " subject: %s", certfields.data); certclock = gnutls_x509_crt_get_activation_time(x509_cert); showtime(data, "start date", certclock); @@ -1238,9 +1233,9 @@ gtls_connect_step3(struct Curl_easy *data, rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields); if(rc) - infof(data, "Failed to get certificate issuer\n"); + infof(data, "Failed to get certificate issuer"); else { - infof(data, "\t issuer: %s\n", certfields.data); + infof(data, " issuer: %s", certfields.data); gnutls_free(certfields.data); } @@ -1251,7 +1246,7 @@ gtls_connect_step3(struct Curl_easy *data, if(conn->bits.tls_enable_alpn) { rc = gnutls_alpn_get_selected_protocol(session, &proto); if(rc == 0) { - infof(data, "ALPN, server accepted to use %.*s\n", proto.size, + infof(data, "ALPN, server accepted to use %.*s", proto.size, proto.data); #ifdef USE_HTTP2 @@ -1268,7 +1263,7 @@ gtls_connect_step3(struct Curl_easy *data, } } else - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); @@ -1438,6 +1433,10 @@ static void close_one(struct ssl_connect_data *connssl) { struct ssl_backend_data *backend = connssl->backend; if(backend->session) { + char buf[32]; + /* Maybe the server has already sent a close notify alert. + Read it to avoid an RST on the TCP connection. */ + (void)gnutls_record_recv(backend->session, buf, sizeof(buf)); gnutls_bye(backend->session, GNUTLS_SHUT_WR); gnutls_deinit(backend->session); backend->session = NULL; @@ -1506,7 +1505,7 @@ static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn, break; case GNUTLS_E_AGAIN: case GNUTLS_E_INTERRUPTED: - infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); + infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED"); break; default: retval = -1; @@ -1620,7 +1619,7 @@ static bool gtls_cert_status_request(void) } static void *gtls_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) + CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; (void)info; diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 3a0be0f04b4..780d13e1886 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -41,7 +41,9 @@ #include <mbedtls/net.h> #endif #include <mbedtls/ssl.h> +#if MBEDTLS_VERSION_NUMBER < 0x03000000 #include <mbedtls/certs.h> +#endif #include <mbedtls/x509.h> #include <mbedtls/error.h> @@ -89,6 +91,10 @@ struct ssl_backend_data { #define THREADING_SUPPORT #endif +#ifndef MBEDTLS_ERROR_C +#define mbedtls_strerror(a,b,c) b[0] = 0 +#endif + #if defined(THREADING_SUPPORT) static mbedtls_entropy_context ts_entropy; @@ -179,6 +185,17 @@ static Curl_send mbed_send; static CURLcode mbedtls_version_from_curl(int *mbedver, long version) { +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + switch(version) { + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } +#else switch(version) { case CURL_SSLVERSION_TLSv1_0: *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; @@ -192,6 +209,8 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version) case CURL_SSLVERSION_TLSv1_3: break; } +#endif + return CURLE_SSL_CONNECT_ERROR; } @@ -201,8 +220,13 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn, { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3; + int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3; +#else int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; +#endif long ssl_version = SSL_CONN_CONFIG(version); long ssl_version_max = SSL_CONN_CONFIG(version_max); CURLcode result = CURLE_OK; @@ -250,12 +274,14 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); + const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); const char * const hostname = SSL_HOST_NAME(); +#ifndef CURL_DISABLE_VERBOSE_STRINGS const long int port = SSL_HOST_PORT(); +#endif int ret = -1; char errorbuf[128]; - errorbuf[0] = 0; if((SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) || (SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)) { @@ -270,9 +296,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, &ts_entropy, NULL, 0); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s", -ret, errorbuf); } @@ -283,9 +307,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, &backend->entropy, NULL, 0); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s", -ret, errorbuf); } @@ -298,9 +320,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile); if(ret<0) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", ssl_cafile, -ret, errorbuf); @@ -313,9 +333,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath); if(ret<0) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", ssl_capath, -ret, errorbuf); @@ -331,9 +349,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", ssl_cert, -ret, errorbuf); @@ -341,27 +357,72 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, } } - /* Load the client private key */ - mbedtls_pk_init(&backend->pk); - - if(SSL_SET_OPTION(key)) { - ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key), - SSL_SET_OPTION(key_passwd)); - if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || - mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) - ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; + if(ssl_cert_blob) { + const unsigned char *blob_data = + (const unsigned char *)ssl_cert_blob->data; + ret = mbedtls_x509_crt_parse(&backend->clicert, blob_data, + ssl_cert_blob->len); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", SSL_SET_OPTION(key), -ret, errorbuf); - return CURLE_SSL_CERTPROBLEM; } } + /* Load the client private key */ + mbedtls_pk_init(&backend->pk); + + if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) { + if(SSL_SET_OPTION(key)) { +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd), + mbedtls_ctr_drbg_random, + &backend->ctr_drbg); +#else + ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); +#endif + + if(ret) { + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", + SSL_SET_OPTION(key), -ret, errorbuf); + return CURLE_SSL_CERTPROBLEM; + } + } + else { + const struct curl_blob *ssl_key_blob = SSL_SET_OPTION(key_blob); + const unsigned char *key_data = + (const unsigned char *)ssl_key_blob->data; + const char *passwd = SSL_SET_OPTION(key_passwd); +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, + (const unsigned char *)passwd, + passwd ? strlen(passwd) : 0, + mbedtls_ctr_drbg_random, + &backend->ctr_drbg); +#else + ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, + (const unsigned char *)passwd, + passwd ? strlen(passwd) : 0); +#endif + + if(ret) { + mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); + failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s", + -ret, errorbuf); + return CURLE_SSL_CERTPROBLEM; + } + } + + if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || + mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) + ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + /* Load the CRL */ mbedtls_x509_crl_init(&backend->crl); @@ -369,9 +430,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", ssl_crlfile, -ret, errorbuf); @@ -379,7 +438,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, } } - infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port); + infof(data, "mbedTLS: Connecting to %s:%ld", hostname, port); mbedtls_ssl_config_init(&backend->config); @@ -404,10 +463,12 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: +#if MBEDTLS_VERSION_NUMBER < 0x03000000 mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); - infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); + infof(data, "mbedTLS: Set min SSL version to TLS 1.0"); break; +#endif case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: @@ -459,7 +520,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } - infof(data, "mbedTLS re-using session\n"); + infof(data, "mbedTLS re-using session"); } Curl_ssl_sessionid_unlock(data); } @@ -468,7 +529,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, &backend->cacert, &backend->crl); - if(SSL_SET_OPTION(key)) { + if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) { mbedtls_ssl_conf_own_cert(&backend->config, &backend->clicert, &backend->pk); } @@ -497,7 +558,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } for(p = &backend->protocols[0]; *p; ++p) - infof(data, "ALPN, offering %s\n", *p); + infof(data, "ALPN, offering %s", *p); } #endif @@ -553,18 +614,14 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, } else if(ret) { char errorbuf[128]; - errorbuf[0] = 0; -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CONNECT_ERROR; } - infof(data, "mbedTLS: Handshake complete, cipher is %s\n", - mbedtls_ssl_get_ciphersuite(&backend->ssl) - ); + infof(data, "mbedTLS: Handshake complete, cipher is %s", + mbedtls_ssl_get_ciphersuite(&backend->ssl)); ret = mbedtls_ssl_get_verify_result(&backend->ssl); @@ -601,9 +658,9 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, return CURLE_OUT_OF_MEMORY; if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) - infof(data, "Dumping cert info:\n%s\n", buffer); + infof(data, "Dumping cert info: %s", buffer); else - infof(data, "Unable to dump certificate information.\n"); + infof(data, "Unable to dump certificate information"); free(buffer); } @@ -611,10 +668,15 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(pinnedpubkey) { int size; CURLcode result; - mbedtls_x509_crt *p; - unsigned char pubkey[PUB_DER_MAX_BYTES]; + mbedtls_x509_crt *p = NULL; + unsigned char *pubkey = NULL; +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) || + !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) { +#else if(!peercert || !peercert->raw.p || !peercert->raw.len) { +#endif failf(data, "Failed due to missing peer certificate"); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } @@ -624,39 +686,54 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(!p) return CURLE_OUT_OF_MEMORY; + pubkey = malloc(PUB_DER_MAX_BYTES); + + if(!pubkey) { + result = CURLE_OUT_OF_MEMORY; + goto pinnedpubkey_error; + } + mbedtls_x509_crt_init(p); /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der needs a non-const key, for now. https://github.com/ARMmbed/mbedtls/issues/396 */ +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + if(mbedtls_x509_crt_parse_der(p, + peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), + peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) { +#else if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { +#endif failf(data, "Failed copying peer certificate"); - mbedtls_x509_crt_free(p); - free(p); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto pinnedpubkey_error; } +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey, + PUB_DER_MAX_BYTES); +#else size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); +#endif if(size <= 0) { failf(data, "Failed copying public key from peer certificate"); - mbedtls_x509_crt_free(p); - free(p); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto pinnedpubkey_error; } /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); + pinnedpubkey_error: + mbedtls_x509_crt_free(p); + free(p); + free(pubkey); if(result) { - mbedtls_x509_crt_free(p); - free(p); return result; } - - mbedtls_x509_crt_free(p); - free(p); } #ifdef HAS_ALPN @@ -664,7 +741,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl); if(next_protocol) { - infof(data, "ALPN, server accepted to use %s\n", next_protocol); + infof(data, "ALPN, server accepted to use %s", next_protocol); #ifdef USE_NGHTTP2 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN) && @@ -679,7 +756,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, } } else { - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); } Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); @@ -687,7 +764,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn, #endif connssl->connecting_state = ssl_connect_3; - infof(data, "SSL connected\n"); + infof(data, "SSL connected"); return CURLE_OK; } @@ -775,8 +852,13 @@ static void mbedtls_close(struct Curl_easy *data, { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - + char buf[32]; (void) data; + + /* Maybe the server has already sent a close notify alert. + Read it to avoid an RST on the TCP connection. */ + (void)mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, sizeof(buf)); + mbedtls_pk_free(&backend->pk); mbedtls_x509_crt_free(&backend->clicert); mbedtls_x509_crt_free(&backend->cacert); @@ -844,15 +926,12 @@ static CURLcode mbedtls_random(struct Curl_easy *data, mbedtls_ctr_drbg_context ctr_drbg; mbedtls_entropy_init(&ctr_entropy); mbedtls_ctr_drbg_init(&ctr_drbg); - errorbuf[0] = 0; ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &ctr_entropy, NULL, 0); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s", -ret, errorbuf); } @@ -860,9 +939,7 @@ static CURLcode mbedtls_random(struct Curl_easy *data, ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); if(ret) { -#ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); -#endif /* MBEDTLS_ERROR_C */ failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s", -ret, errorbuf); } @@ -1046,12 +1123,17 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input, unsigned char *sha256sum, size_t sha256len UNUSED_PARAM) { + /* TODO: explain this for different mbedtls 2.x vs 3 version */ (void)sha256len; #if MBEDTLS_VERSION_NUMBER < 0x02070000 mbedtls_sha256(input, inputlen, sha256sum, 0); #else /* returns 0 on success, otherwise failure */ +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0) +#else if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) +#endif return CURLE_BAD_FUNCTION_ARGUMENT; #endif return CURLE_OK; diff --git a/lib/vtls/mbedtls_threadlock.c b/lib/vtls/mbedtls_threadlock.c index 473f5171e2c..751755c239f 100644 --- a/lib/vtls/mbedtls_threadlock.c +++ b/lib/vtls/mbedtls_threadlock.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2013 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> * * This software is licensed as described in the file COPYING, which @@ -55,10 +55,8 @@ int Curl_mbedtlsthreadlock_thread_setup(void) return 0; /* error, no number of threads defined */ for(i = 0; i < NUMT; i++) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_init(&mutex_buf[i], NULL); - if(ret) + if(pthread_mutex_init(&mutex_buf[i], NULL)) return 0; /* pthread_mutex_init failed */ #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) mutex_buf[i] = CreateMutex(0, FALSE, 0); @@ -78,14 +76,11 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void) return 0; /* error, no threads locks defined */ for(i = 0; i < NUMT; i++) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_destroy(&mutex_buf[i]); - if(ret) + if(pthread_mutex_destroy(&mutex_buf[i])) return 0; /* pthread_mutex_destroy failed */ #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) - ret = CloseHandle(mutex_buf[i]); - if(!ret) + if(!CloseHandle(mutex_buf[i])) return 0; /* CloseHandle failed */ #endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ } @@ -98,17 +93,14 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void) int Curl_mbedtlsthreadlock_lock_function(int n) { if(n < NUMT) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_lock(&mutex_buf[n]); - if(ret) { + if(pthread_mutex_lock(&mutex_buf[n])) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_lock_function failed\n")); return 0; /* pthread_mutex_lock failed */ } #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) - ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0); - if(ret) { + if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_lock_function failed\n")); return 0; /* pthread_mutex_lock failed */ @@ -121,17 +113,14 @@ int Curl_mbedtlsthreadlock_lock_function(int n) int Curl_mbedtlsthreadlock_unlock_function(int n) { if(n < NUMT) { - int ret; #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - ret = pthread_mutex_unlock(&mutex_buf[n]); - if(ret) { + if(pthread_mutex_unlock(&mutex_buf[n])) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_unlock_function failed\n")); return 0; /* pthread_mutex_unlock failed */ } #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H) - ret = ReleaseMutex(mutex_buf[n]); - if(!ret) { + if(!ReleaseMutex(mutex_buf[n])) { DEBUGF(fprintf(stderr, "Error: mbedtlsthreadlock_unlock_function failed\n")); return 0; /* pthread_mutex_lock failed */ diff --git a/lib/vtls/mesalink.c b/lib/vtls/mesalink.c index bf8600d3230..3db9184f795 100644 --- a/lib/vtls/mesalink.c +++ b/lib/vtls/mesalink.c @@ -167,14 +167,14 @@ mesalink_connect_step1(struct Curl_easy *data, } infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); + " continuing anyway:"); } else { - infof(data, "successfully set certificate verify locations:\n"); + infof(data, "successfully set certificate verify locations:"); } - infof(data, " CAfile: %s\n", + infof(data, " CAfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none"); - infof(data, " CApath: %s\n", + infof(data, " CApath: %s", SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none"); } @@ -196,7 +196,7 @@ mesalink_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } infof(data, - "client cert: %s\n", + "client cert: %s", SSL_CONN_CONFIG(clientcert)? SSL_CONN_CONFIG(clientcert): "none"); } @@ -209,7 +209,7 @@ mesalink_connect_step1(struct Curl_easy *data, return CURLE_SSL_CIPHER; } #endif - infof(data, "Cipher selection: %s\n", ciphers); + infof(data, "Cipher selection: %s", ciphers); } if(BACKEND->handle) @@ -273,7 +273,7 @@ mesalink_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof(data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID"); } Curl_ssl_sessionid_unlock(data); } @@ -326,7 +326,7 @@ mesalink_connect_step2(struct Curl_easy *data, connssl->connecting_state = ssl_connect_3; infof(data, - "SSL connection using %s / %s\n", + "SSL connection using %s / %s", SSL_get_version(BACKEND->handle), SSL_get_cipher_name(BACKEND->handle)); @@ -356,7 +356,7 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex) sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); + infof(data, "old SSL session ID is stale, removing"); Curl_ssl_delsessionid(data, old_ssl_sessionid); incache = FALSE; } diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 1582b1e580a..cf657895f6f 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -433,7 +433,7 @@ static char *dup_nickname(struct Curl_easy *data, const char *str) n = strchr(str, '/'); if(!n) { infof(data, "warning: certificate file name \"%s\" handled as nickname; " - "please use \"./%s\" to force file name\n", str, str); + "please use \"./%s\" to force file name", str, str); return strdup(str); } @@ -824,7 +824,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, #endif if(!SSL_CONN_CONFIG(verifypeer)) { - infof(data, "skipping SSL peer certificate verification\n"); + infof(data, "skipping SSL peer certificate verification"); return SECSuccess; } @@ -857,15 +857,15 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) #endif case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_OVERLAP: - infof(data, "ALPN/NPN, server did not agree to a protocol\n"); + infof(data, "ALPN/NPN, server did not agree to a protocol"); return; #ifdef SSL_ENABLE_ALPN case SSL_NEXT_PROTO_SELECTED: - infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf); + infof(data, "ALPN, server accepted to use %.*s", buflen, buf); break; #endif case SSL_NEXT_PROTO_NEGOTIATED: - infof(data, "NPN, server accepted to use %.*s\n", buflen, buf); + infof(data, "NPN, server accepted to use %.*s", buflen, buf); break; } @@ -937,7 +937,7 @@ static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, *canFalseStart = PR_TRUE; - infof(data, "Trying TLS False Start\n"); + infof(data, "Trying TLS False Start"); end: return SECSuccess; @@ -955,17 +955,17 @@ static void display_cert_info(struct Curl_easy *data, subject = CERT_NameToAscii(&cert->subject); issuer = CERT_NameToAscii(&cert->issuer); common_name = CERT_GetCommonName(&cert->subject); - infof(data, "\tsubject: %s\n", subject); + infof(data, "subject: %s\n", subject); CERT_GetCertTimes(cert, ¬Before, ¬After); PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); - infof(data, "\tstart date: %s\n", timeString); + infof(data, " start date: %s", timeString); PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime); PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); - infof(data, "\texpire date: %s\n", timeString); - infof(data, "\tcommon name: %s\n", common_name); - infof(data, "\tissuer: %s\n", issuer); + infof(data, " expire date: %s", timeString); + infof(data, " common name: %s", common_name); + infof(data, " issuer: %s", issuer); PR_Free(subject); PR_Free(issuer); @@ -987,13 +987,13 @@ static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock) channel.cipherSuite) { if(SSL_GetCipherSuiteInfo(channel.cipherSuite, &suite, sizeof(suite)) == SECSuccess) { - infof(data, "SSL connection using %s\n", suite.cipherSuiteName); + infof(data, "SSL connection using %s", suite.cipherSuiteName); } } cert = SSL_PeerCertificate(sock); if(cert) { - infof(data, "Server certificate:\n"); + infof(data, "Server certificate:"); if(!data->set.ssl.certinfo) { display_cert_info(data, cert); @@ -1058,7 +1058,7 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) /* print only info about the cert, the error is printed off the callback */ cert = SSL_PeerCertificate(sock); if(cert) { - infof(data, "Server certificate:\n"); + infof(data, "Server certificate:"); display_cert_info(data, cert); CERT_DestroyCertificate(cert); } @@ -1132,7 +1132,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, /* report the resulting status */ switch(result) { case CURLE_OK: - infof(data, "pinned public key verified successfully!\n"); + infof(data, "pinned public key verified successfully!"); break; case CURLE_SSL_PINNEDPUBKEYNOTMATCH: failf(data, "failed to verify pinned public key"); @@ -1196,7 +1196,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, return SECFailure; } - infof(data, "NSS: client certificate from file\n"); + infof(data, "NSS: client certificate from file"); display_cert_info(data, cert); *pRetCert = cert; @@ -1234,7 +1234,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, return SECFailure; } - infof(data, "NSS: using client certificate: %s\n", nickname); + infof(data, "NSS: using client certificate: %s", nickname); display_cert_info(data, *pRetCert); return SECSuccess; } @@ -1355,7 +1355,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) if(!certpath) return CURLE_OUT_OF_MEMORY; - infof(data, "Initializing NSS with certpath: %s\n", certpath); + infof(data, "Initializing NSS with certpath: %s", certpath); nss_context = NSS_InitContext(certpath, "", "", "", &initparams, NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); free(certpath); @@ -1365,10 +1365,10 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) err = PR_GetError(); err_name = nss_error_to_name(err); - infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name); + infof(data, "Unable to initialize NSS database: %d (%s)", err, err_name); } - infof(data, "Initializing NSS with certpath: none\n"); + infof(data, "Initializing NSS with certpath: none"); nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); @@ -1546,6 +1546,14 @@ static void close_one(struct ssl_connect_data *connssl) const bool client_cert = (backend->client_nickname != NULL) || (backend->obj_clicert != NULL); + if(backend->handle) { + char buf[32]; + /* Maybe the server has already sent a close notify alert. + Read it to avoid an RST on the TCP connection. */ + (void)PR_Recv(backend->handle, buf, (int)sizeof(buf), 0, + PR_INTERVAL_NO_WAIT); + } + free(backend->client_nickname); backend->client_nickname = NULL; @@ -1650,8 +1658,8 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data, if(capath && !capath[0]) capath = NULL; - infof(data, " CAfile: %s\n", cafile ? cafile : "none"); - infof(data, " CApath: %s\n", capath ? capath : "none"); + infof(data, " CAfile: %s", cafile ? cafile : "none"); + infof(data, " CApath: %s", capath ? capath : "none"); /* load libnssckbi.so if no other trust roots were specified */ use_trust_module = !cafile && !capath; @@ -1660,7 +1668,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data, if(use_trust_module && !trust_module) { /* libnssckbi.so needed but not yet loaded --> load it! */ result = nss_load_module(&trust_module, trust_library, "trust"); - infof(data, "%s %s\n", (result) ? "failed to load" : "loaded", + infof(data, "%s %s", (result) ? "failed to load" : "loaded", trust_library); if(result == CURLE_FAILED_INIT) /* If libnssckbi.so is not available (or fails to load), one can still @@ -1669,7 +1677,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data, } else if(!use_trust_module && trust_module) { /* libnssckbi.so not needed but already loaded --> unload it! */ - infof(data, "unloading %s\n", trust_library); + infof(data, "unloading %s", trust_library); nss_unload_module(&trust_module); } PR_Unlock(nss_trustload_lock); @@ -1702,7 +1710,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data, if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) /* This is purposefully tolerant of errors so non-PEM files can * be in the same directory */ - infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); + infof(data, "failed to load '%s' from CURLOPT_CAPATH", fullpath); free(fullpath); } @@ -1710,7 +1718,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data, PR_CloseDir(dir); } else - infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); + infof(data, "warning: CURLOPT_CAPATH not a directory (%s)", capath); } return CURLE_OK; @@ -1813,7 +1821,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, curlerr = CURLE_SSL_CERTPROBLEM; /* print the error number and error string */ - infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); + infof(data, "NSS error %d (%s)", err, nss_error_to_name(err)); /* print a human-readable message describing the error if available */ nss_print_error_message(data, err); @@ -1887,7 +1895,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, PR_Unlock(nss_initlock); if(result == CURLE_FAILED_INIT) infof(data, "WARNING: failed to load NSS PEM library %s. Using " - "OpenSSL PEM certificates will not work.\n", pem_library); + "OpenSSL PEM certificates will not work.", pem_library); else if(result) goto error; @@ -1922,8 +1930,8 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, sslver_req_str = nss_sslver_to_name(sslver.max); sslver_supp_str = nss_sslver_to_name(sslver_supported.max); if(sslver_req_str && sslver_supp_str) - infof(data, "Falling back from %s to max supported SSL version (%s)\n", - sslver_req_str, sslver_supp_str); + infof(data, "Falling back from %s to max supported SSL version (%s)", + sslver_req_str, sslver_supp_str); free(sslver_req_str); free(sslver_supp_str); sslver.max = sslver_supported.max; @@ -1936,11 +1944,11 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, /* unless the user explicitly asks to allow the protocol vulnerability, we use the work-around */ if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess) - infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n", + infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d", ssl_cbc_random_iv); #else if(ssl_cbc_random_iv) - infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); + infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in"); #endif if(SSL_CONN_CONFIG(cipher_list)) { @@ -1951,7 +1959,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, } if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost)) - infof(data, "warning: ignoring value of ssl.verifyhost\n"); + infof(data, "warning: ignoring value of ssl.verifyhost"); /* bypass the default SSL_AuthCertificate() hook in case we do not want to * verify peer */ @@ -1971,7 +1979,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex); if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer)) /* not a fatal error because we are not going to verify the peer */ - infof(data, "warning: CA certificates failed to load\n"); + infof(data, "warning: CA certificates failed to load"); else if(rv) { result = rv; goto error; @@ -1984,7 +1992,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, result = rv; goto error; } - infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile)); + infof(data, " CRLfile: %s", SSL_SET_OPTION(CRLfile)); } if(SSL_SET_OPTION(primary.clientcert)) { @@ -2179,9 +2187,9 @@ static CURLcode nss_do_connect(struct Curl_easy *data, if(result) goto error; - if(SSL_SET_OPTION(issuercert)) { + if(SSL_CONN_CONFIG(issuercert)) { SECStatus ret = SECFailure; - char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); + char *nickname = dup_nickname(data, SSL_CONN_CONFIG(issuercert)); if(nickname) { /* we support only nicknames in case of issuercert for now */ ret = check_issuer_cert(backend->handle, nickname); @@ -2189,12 +2197,12 @@ static CURLcode nss_do_connect(struct Curl_easy *data, } if(SECFailure == ret) { - infof(data, "SSL certificate issuer check failed\n"); + infof(data, "SSL certificate issuer check failed"); result = CURLE_SSL_ISSUER_ERROR; goto error; } else { - infof(data, "SSL certificate issuer check ok\n"); + infof(data, "SSL certificate issuer check ok"); } } @@ -2306,7 +2314,7 @@ static ssize_t nss_send(struct Curl_easy *data, /* transfer */ else { /* print the error number and error string */ const char *err_name = nss_error_to_name(err); - infof(data, "SSL write: error %d (%s)\n", err, err_name); + infof(data, "SSL write: error %d (%s)", err, err_name); /* print a human-readable message describing the error if available */ nss_print_error_message(data, err); @@ -2348,7 +2356,7 @@ static ssize_t nss_recv(struct Curl_easy *data, /* transfer */ else { /* print the error number and error string */ const char *err_name = nss_error_to_name(err); - infof(data, "SSL read: errno %d (%s)\n", err, err_name); + infof(data, "SSL read: errno %d (%s)", err, err_name); /* print a human-readable message describing the error if available */ nss_print_error_message(data, err); @@ -2427,7 +2435,7 @@ static bool nss_false_start(void) } static void *nss_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) + CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; (void)info; diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index ebd7abc3b4a..87f4b02b715 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -194,7 +194,7 @@ !defined(OPENSSL_IS_BORINGSSL)) #define HAVE_SSL_CTX_SET_CIPHERSUITES #define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH -/* SET_EC_CURVES available under the same preconditions: see +/* SET_EC_CURVES is available under the same preconditions: see * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html */ #define HAVE_SSL_CTX_SET_EC_CURVES @@ -209,8 +209,8 @@ #endif #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) -/* up2date versions of OpenSSL maintain the default reasonably secure without - * breaking compatibility, so it is better not to override the default by curl +/* up2date versions of OpenSSL maintain reasonably secure defaults without + * breaking compatibility, so it is better not to override the defaults in curl */ #define DEFAULT_CIPHER_SELECTION NULL #else @@ -435,17 +435,16 @@ static bool rand_enough(void) static CURLcode ossl_seed(struct Curl_easy *data) { - /* we have the "SSL is seeded" boolean static to prevent multiple - time-consuming seedings in vain */ - static bool ssl_seeded = FALSE; char fname[256]; - if(ssl_seeded) + /* This might get called before it has been added to a multi handle */ + if(data->multi && data->multi->ssl_seeded) return CURLE_OK; if(rand_enough()) { /* OpenSSL 1.1.0+ will return here */ - ssl_seeded = TRUE; + if(data->multi) + data->multi->ssl_seeded = TRUE; return CURLE_OK; } @@ -518,7 +517,7 @@ static CURLcode ossl_seed(struct Curl_easy *data) return CURLE_OK; } - infof(data, "libcurl is now using a weak random seed!\n"); + infof(data, "libcurl is now using a weak random seed!"); return (rand_enough() ? CURLE_OK : CURLE_SSL_CONNECT_ERROR /* confusing error code */); } @@ -1193,7 +1192,7 @@ static int ossl_init(void) CONF_MFLAGS_IGNORE_MISSING_FILE); #endif - /* Lets get nice error messages */ + /* Let's get nice error messages */ SSL_load_error_strings(); /* Init the global ciphers and digests */ @@ -1354,7 +1353,7 @@ static CURLcode ossl_set_engine_default(struct Curl_easy *data) #ifdef USE_OPENSSL_ENGINE if(data->state.engine) { if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { - infof(data, "set default crypto engine '%s'\n", + infof(data, "set default crypto engine '%s'", ENGINE_get_id(data->state.engine)); } else { @@ -1400,7 +1399,13 @@ static void ossl_closeone(struct Curl_easy *data, { struct ssl_backend_data *backend = connssl->backend; if(backend->handle) { + char buf[32]; set_logger(conn, data); + + /* Maybe the server has already sent a close notify alert. + Read it to avoid an RST on the TCP connection. */ + (void)SSL_read(backend->handle, buf, (int)sizeof(buf)); + (void)SSL_shutdown(backend->handle); SSL_set_connect_state(backend->handle); @@ -1442,6 +1447,7 @@ static int ossl_shutdown(struct Curl_easy *data, int err; bool done = FALSE; struct ssl_backend_data *backend = connssl->backend; + int loop = 10; #ifndef CURL_DISABLE_FTP /* This has only been tested on the proftpd server, and the mod_tls code @@ -1455,7 +1461,7 @@ static int ossl_shutdown(struct Curl_easy *data, if(backend->handle) { buffsize = (int)sizeof(buf); - while(!done) { + while(!done && loop--) { int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); if(what > 0) { @@ -1475,11 +1481,11 @@ static int ossl_shutdown(struct Curl_easy *data, break; case SSL_ERROR_WANT_READ: /* there's data pending, re-invoke SSL_read() */ - infof(data, "SSL_ERROR_WANT_READ\n"); + infof(data, "SSL_ERROR_WANT_READ"); break; case SSL_ERROR_WANT_WRITE: /* SSL wants a write. Really odd. Let's bail out. */ - infof(data, "SSL_ERROR_WANT_WRITE\n"); + infof(data, "SSL_ERROR_WANT_WRITE"); done = TRUE; break; default: @@ -1511,14 +1517,14 @@ static int ossl_shutdown(struct Curl_easy *data, #ifdef HAVE_SSL_GET_SHUTDOWN switch(SSL_get_shutdown(backend->handle)) { case SSL_SENT_SHUTDOWN: - infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); + infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN"); break; case SSL_RECEIVED_SHUTDOWN: - infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n"); + infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN"); break; case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN: infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|" - "SSL_RECEIVED__SHUTDOWN\n"); + "SSL_RECEIVED__SHUTDOWN"); break; } #endif @@ -1585,7 +1591,7 @@ static bool subj_alt_hostcheck(struct Curl_easy *data, if(Curl_cert_hostcheck(match_pattern2, hostname)) { res = TRUE; infof(data, - " subjectAltName: host \"%s\" matched cert's \"%s\"\n", + " subjectAltName: host \"%s\" matched cert's \"%s\"", dispname, match_pattern2); } } @@ -1604,7 +1610,7 @@ static bool subj_alt_hostcheck(struct Curl_easy *data, (void)data; #endif if(Curl_cert_hostcheck(match_pattern, hostname)) { - infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", + infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"", dispname, match_pattern); return TRUE; } @@ -1724,7 +1730,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn, if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) { ipmatched = TRUE; infof(data, - " subjectAltName: host \"%s\" matched cert's IP address!\n", + " subjectAltName: host \"%s\" matched cert's IP address!", dispname); } break; @@ -1741,7 +1747,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn, /* an alternative name matched */ ; else if(dNSName || iPAddress) { - infof(data, " subjectAltName does not match %s\n", dispname); + infof(data, " subjectAltName does not match %s", dispname); failf(data, "SSL: no alternative certificate subject name matches " "target host name '%s'", dispname); result = CURLE_PEER_FAILED_VERIFICATION; @@ -1763,7 +1769,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn, /* we have the name entry and we will now convert this to a string that we can use for comparison. Doing this we support BMPstring, - UTF8 etc. */ + UTF8, etc. */ if(i >= 0) { ASN1_STRING *tmp = @@ -1823,7 +1829,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn, result = CURLE_PEER_FAILED_VERIFICATION; } else { - infof(data, " common name: %s (matched)\n", peer_CN); + infof(data, " common name: %s (matched)", peer_CN); } if(peer_CN) OPENSSL_free(peer_CN); @@ -1959,7 +1965,7 @@ static CURLcode verifystatus(struct Curl_easy *data, goto end; } - infof(data, "SSL certificate status: %s (%d)\n", + infof(data, "SSL certificate status: %s (%d)", OCSP_cert_status_str(cert_status), cert_status); switch(cert_status) { @@ -2054,6 +2060,10 @@ static const char *ssl_msg_type(int ssl_ver, int msg) case SSL3_MT_ENCRYPTED_EXTENSIONS: return "Encrypted Extensions"; #endif +#ifdef SSL3_MT_SUPPLEMENTAL_DATA + case SSL3_MT_SUPPLEMENTAL_DATA: + return "Supplemental data"; +#endif #ifdef SSL3_MT_END_OF_EARLY_DATA case SSL3_MT_END_OF_EARLY_DATA: return "End of early data"; @@ -2152,7 +2162,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, /* Log progress for interesting records only (like Handshake or Alert), skip * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). - * For TLS 1.3, skip notification of the decrypted inner Content Type. + * For TLS 1.3, skip notification of the decrypted inner Content-Type. */ if(ssl_ver #ifdef SSL3_RT_INNER_CONTENT_TYPE @@ -2263,7 +2273,7 @@ select_next_proto_cb(SSL *ssl, #ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2 && !select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) { - infof(data, "NPN, negotiated HTTP2 (%s)\n", ALPN_H2); + infof(data, "NPN, negotiated HTTP2 (%s)", ALPN_H2); conn->negnpn = CURL_HTTP_VERSION_2; return SSL_TLSEXT_ERR_OK; } @@ -2271,12 +2281,12 @@ select_next_proto_cb(SSL *ssl, if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { - infof(data, "NPN, negotiated HTTP1.1\n"); + infof(data, "NPN, negotiated HTTP1.1"); conn->negnpn = CURL_HTTP_VERSION_1_1; return SSL_TLSEXT_ERR_OK; } - infof(data, "NPN, no overlap, use HTTP1.1\n"); + infof(data, "NPN, no overlap, use HTTP1.1"); *out = (unsigned char *)ALPN_HTTP_1_1; *outlen = ALPN_HTTP_1_1_LENGTH; conn->negnpn = CURL_HTTP_VERSION_1_1; @@ -2293,7 +2303,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) long curl_ssl_version_min = SSL_CONN_CONFIG(version); long curl_ssl_version_max; - /* convert cURL min SSL version option to OpenSSL constant */ + /* convert curl min SSL version option to OpenSSL constant */ #if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER) uint16_t ossl_ssl_version_min = 0; uint16_t ossl_ssl_version_max = 0; @@ -2323,7 +2333,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) We don't want to pass 0 to SSL_CTX_set_min_proto_version as it would enable all versions down to the lowest supported by the library. - So we skip this, and stay with the OS default + So we skip this, and stay with the library default */ if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) { if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) { @@ -2334,7 +2344,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) /* ... then, TLS max version */ curl_ssl_version_max = SSL_CONN_CONFIG(version_max); - /* convert cURL max SSL version option to OpenSSL constant */ + /* convert curl max SSL version option to OpenSSL constant */ switch(curl_ssl_version_max) { case CURL_SSLVERSION_MAX_TLSv1_0: ossl_ssl_version_max = TLS1_VERSION; @@ -2493,7 +2503,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) &old_ssl_sessionid, NULL, sockindex)); if(incache) { if(old_ssl_sessionid != ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); + infof(data, "old SSL session ID is stale, removing"); Curl_ssl_delsessionid(data, old_ssl_sessionid); incache = FALSE; } @@ -2517,7 +2527,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) static CURLcode load_cacert_from_memory(SSL_CTX *ctx, const struct curl_blob *ca_info_blob) { - /* these need freed at the end */ + /* these need to be freed at the end */ BIO *cbio = NULL; STACK_OF(X509_INFO) *inf = NULL; @@ -2652,8 +2662,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } - if(backend->ctx) - SSL_CTX_free(backend->ctx); + DEBUGASSERT(!backend->ctx); backend->ctx = SSL_CTX_new(req_method); if(!backend->ctx) { @@ -2675,23 +2684,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } #endif - /* OpenSSL contains code to work-around lots of bugs and flaws in various + /* OpenSSL contains code to work around lots of bugs and flaws in various SSL-implementations. SSL_CTX_set_options() is used to enabled those work-arounds. The man page for this option states that SSL_OP_ALL enables all the work-arounds and that "It is usually safe to use SSL_OP_ALL to enable the bug workaround options if compatibility with somewhat broken implementations is desired." - The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to + The "-no_ticket" option was introduced in OpenSSL 0.9.8j. It's a flag to disable "rfc4507bis session ticket support". rfc4507bis was later turned into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077 The enabled extension concerns the session management. I wonder how often - libcurl stops a connection and then resumes a TLS session. also, sending - the session data is some overhead. .I suggest that you just use your + libcurl stops a connection and then resumes a TLS session. Also, sending + the session data is some overhead. I suggest that you just use your proposed patch (which explicitly disables TICKET). - If someone writes an application with libcurl and openssl who wants to + If someone writes an application with libcurl and OpenSSL who wants to enable the feature, one can do this in the SSL callback. SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper @@ -2727,7 +2736,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - /* unless the user explicitly ask to allow the protocol vulnerability we + /* unless the user explicitly asks to allow the protocol vulnerability we use the work-around */ if(!SSL_SET_OPTION(enable_beast)) ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; @@ -2787,14 +2796,14 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH); cur += ALPN_H2_LENGTH; - infof(data, "ALPN, offering %s\n", ALPN_H2); + infof(data, "ALPN, offering %s", ALPN_H2); } #endif protocols[cur++] = ALPN_HTTP_1_1_LENGTH; memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); cur += ALPN_HTTP_1_1_LENGTH; - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s", ALPN_HTTP_1_1); /* expects length prefixed preference ordered list of protocols in wire * format @@ -2826,7 +2835,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, failf(data, "failed setting cipher list: %s", ciphers); return CURLE_SSL_CIPHER; } - infof(data, "Cipher selection: %s\n", ciphers); + infof(data, "Cipher selection: %s", ciphers); } #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES @@ -2837,7 +2846,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13); return CURLE_SSL_CIPHER; } - infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13); + infof(data, "TLS 1.3 cipher selection: %s", ciphers13); } } #endif @@ -2863,7 +2872,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, if(ssl_authtype == CURL_TLSAUTH_SRP) { char * const ssl_username = SSL_SET_OPTION(username); - infof(data, "Using TLS-SRP username: %s\n", ssl_username); + infof(data, "Using TLS-SRP username: %s", ssl_username); if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) { failf(data, "Unable to set SRP user name"); @@ -2874,7 +2883,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return CURLE_BAD_FUNCTION_ARGUMENT; } if(!SSL_CONN_CONFIG(cipher_list)) { - infof(data, "Setting cipher list SRP\n"); + infof(data, "Setting cipher list SRP"); if(!SSL_CTX_set_cipher_list(backend->ctx, "SRP")) { failf(data, "failed setting SRP cipher list"); @@ -2927,7 +2936,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, NULL, cert_name, sizeof(cert_name))) { strcpy(cert_name, "Unknown"); } - infof(data, "SSL: Checking cert \"%s\"\n", cert_name); + infof(data, "SSL: Checking cert %s\"\n", cert_name); #endif encoded_cert = (const unsigned char *)pContext->pbCertEncoded; @@ -3009,7 +3018,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, OpenSSL. */ if(X509_STORE_add_cert(store, x509) == 1) { #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - infof(data, "SSL: Imported cert \"%s\"\n", cert_name); + infof(data, "SSL: Imported cert \"%s\"", cert_name); #endif imported_native_ca = true; } @@ -3024,9 +3033,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return result; } if(imported_native_ca) - infof(data, "successfully imported windows ca store\n"); + infof(data, "successfully imported Windows CA store"); else - infof(data, "error importing windows ca store, continuing anyway\n"); + infof(data, "error importing Windows CA store, continuing anyway"); } #endif @@ -3038,8 +3047,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, failf(data, "error importing CA certificate blob"); return result; } - /* Only warning if no certificate verification is required. */ - infof(data, "error importing CA certificate blob, continuing anyway\n"); + /* Only warn if no certificate verification is required. */ + infof(data, "error importing CA certificate blob, continuing anyway"); } } @@ -3053,10 +3062,10 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, failf(data, "error setting certificate file: %s", ssl_cafile); return CURLE_SSL_CACERT_BADFILE; } - /* Continue with a warning if no certificate verif is required. */ - infof(data, "error setting certificate file, continuing anyway\n"); + /* Continue with warning if certificate verification isn't required. */ + infof(data, "error setting certificate file, continuing anyway"); } - infof(data, " CAfile: %s\n", ssl_cafile); + infof(data, " CAfile: %s", ssl_cafile); } if(ssl_capath) { if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) { @@ -3065,16 +3074,16 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, failf(data, "error setting certificate path: %s", ssl_capath); return CURLE_SSL_CACERT_BADFILE; } - /* Continue with a warning if no certificate verif is required. */ - infof(data, "error setting certificate path, continuing anyway\n"); + /* Continue with warning if certificate verification isn't required. */ + infof(data, "error setting certificate path, continuing anyway"); } - infof(data, " CApath: %s\n", ssl_capath); + infof(data, " CApath: %s", ssl_capath); } } #else if(ssl_cafile || ssl_capath) { /* tell SSL where to find CA certificates that are used to verify - the servers certificate. */ + the server's certificate. */ if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) { if(verifypeer && !imported_native_ca) { /* Fail if we insist on successfully verifying the server. */ @@ -3087,14 +3096,14 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, /* Just continue with a warning if no strict certificate verification is required. */ infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); + " continuing anyway:"); } else { /* Everything is fine. */ - infof(data, "successfully set certificate verify locations:\n"); + infof(data, "successfully set certificate verify locations:"); } - infof(data, " CAfile: %s\n", ssl_cafile ? ssl_cafile : "none"); - infof(data, " CApath: %s\n", ssl_capath ? ssl_capath : "none"); + infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); + infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none"); } #endif @@ -3102,13 +3111,13 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, if(verifypeer && !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) { /* verifying the peer without any CA certificates won't - work so use openssl's built in default as fallback */ + work so use openssl's built-in default as fallback */ SSL_CTX_set_default_verify_paths(backend->ctx); } #endif if(ssl_crlfile) { - /* tell SSL where to find CRL file that is used to check certificate + /* tell OpenSSL where to find CRL file that is used to check certificate * revocation */ lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx), X509_LOOKUP_file()); @@ -3118,11 +3127,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CRL_BADFILE; } /* Everything is fine. */ - infof(data, "successfully load CRL file:\n"); + infof(data, "successfully loaded CRL file:"); X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); - infof(data, " CRLfile: %s\n", ssl_crlfile); + infof(data, " CRLfile: %s", ssl_crlfile); } if(verifypeer) { @@ -3144,7 +3153,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, only, instead of needing the whole chain. Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we - cannot do partial chains with CRL check. + cannot do partial chains with a CRL check. */ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx), X509_V_FLAG_PARTIAL_CHAIN); @@ -3152,7 +3161,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif } - /* SSL always tries to verify the peer, this only says whether it should + /* OpenSSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ @@ -3167,7 +3176,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, #endif /* Enable the session cache because it's a prerequisite for the "new session" - * callback. Use the "external storage" mode to avoid that OpenSSL creates + * callback. Use the "external storage" mode to prevent OpenSSL from creating * an internal session cache. */ SSL_CTX_set_session_cache_mode(backend->ctx, @@ -3186,7 +3195,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, } } - /* Lets make an SSL structure */ + /* Let's make an SSL structure */ if(backend->handle) SSL_free(backend->handle); backend->handle = SSL_new(backend->ctx); @@ -3226,7 +3235,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, data->state.buffer[nlen] = 0; if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer)) infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); + "TLS extension"); } #endif @@ -3244,7 +3253,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof(data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID"); } Curl_ssl_sessionid_unlock(data); @@ -3326,7 +3335,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, /* the connection failed, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_2; - /* Get the earliest error code from the thread's error queue and removes + /* Get the earliest error code from the thread's error queue and remove the entry. */ errdetail = ERR_get_error(); @@ -3355,7 +3364,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, !defined(LIBRESSL_VERSION_NUMBER) && \ !defined(OPENSSL_IS_BORINGSSL)) /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on - OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */ + OpenSSL version above v1.1.1, not LibreSSL nor BoringSSL */ else if((lib == ERR_LIB_SSL) && (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) { /* If client certificate is required, communicate the @@ -3372,7 +3381,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, /* detail is already set to the SSL error above */ /* If we e.g. use SSLv2 request-method and the server doesn't like us - * (RST connection etc.), OpenSSL gives no explanation whatsoever and + * (RST connection, etc.), OpenSSL gives no explanation whatsoever and * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { @@ -3395,11 +3404,11 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, } } else { - /* we have been connected fine, we're not waiting for anything else. */ + /* we connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; /* Informational message */ - infof(data, "SSL connection using %s / %s\n", + infof(data, "SSL connection using %s / %s", SSL_get_version(backend->handle), SSL_get_cipher(backend->handle)); @@ -3412,7 +3421,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, unsigned int len; SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len); if(len) { - infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol); + infof(data, "ALPN, server accepted to use %.*s", len, neg_protocol); #ifdef USE_HTTP2 if(len == ALPN_H2_LENGTH && @@ -3427,7 +3436,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data, } } else - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); @@ -3637,7 +3646,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data, pubkey = X509_get_pubkey(x); if(!pubkey) - infof(data, " Unable to load public key\n"); + infof(data, " Unable to load public key"); else { int pktype; #ifdef HAVE_OPAQUE_EVP_PKEY @@ -3814,7 +3823,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, } /* - * Get the server cert, verify it and show it etc, only call failf() if the + * Get the server cert, verify it and show it, etc., only call failf() if the * 'strict' argument is TRUE as otherwise all this is for informational * purposes only! * @@ -3851,23 +3860,23 @@ static CURLcode servercert(struct Curl_easy *data, return CURLE_PEER_FAILED_VERIFICATION; } - infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); + infof(data, "%s certificate:", SSL_IS_PROXY() ? "Proxy" : "Server"); rc = x509_name_oneline(X509_get_subject_name(backend->server_cert), buffer, sizeof(buffer)); - infof(data, " subject: %s\n", rc?"[NONE]":buffer); + infof(data, " subject: %s", rc?"[NONE]":buffer); #ifndef CURL_DISABLE_VERBOSE_STRINGS { long len; ASN1_TIME_print(mem, X509_get0_notBefore(backend->server_cert)); len = BIO_get_mem_data(mem, (char **) &ptr); - infof(data, " start date: %.*s\n", len, ptr); + infof(data, " start date: %.*s", (int)len, ptr); (void)BIO_reset(mem); ASN1_TIME_print(mem, X509_get0_notAfter(backend->server_cert)); len = BIO_get_mem_data(mem, (char **) &ptr); - infof(data, " expire date: %.*s\n", len, ptr); + infof(data, " expire date: %.*s", (int)len, ptr); (void)BIO_reset(mem); } #endif @@ -3891,16 +3900,16 @@ static CURLcode servercert(struct Curl_easy *data, result = CURLE_PEER_FAILED_VERIFICATION; } else { - infof(data, " issuer: %s\n", buffer); + infof(data, " issuer: %s", buffer); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ /* e.g. match issuer name with provided issuer certificate */ - if(SSL_SET_OPTION(issuercert) || SSL_SET_OPTION(issuercert_blob)) { - if(SSL_SET_OPTION(issuercert_blob)) - fp = BIO_new_mem_buf(SSL_SET_OPTION(issuercert_blob)->data, - (int)SSL_SET_OPTION(issuercert_blob)->len); + if(SSL_CONN_CONFIG(issuercert) || SSL_CONN_CONFIG(issuercert_blob)) { + if(SSL_CONN_CONFIG(issuercert_blob)) + fp = BIO_new_mem_buf(SSL_CONN_CONFIG(issuercert_blob)->data, + (int)SSL_CONN_CONFIG(issuercert_blob)->len); else { fp = BIO_new(BIO_s_file()); if(!fp) { @@ -3914,10 +3923,10 @@ static CURLcode servercert(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } - if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) { + if(BIO_read_filename(fp, SSL_CONN_CONFIG(issuercert)) <= 0) { if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", - SSL_SET_OPTION(issuercert)); + SSL_CONN_CONFIG(issuercert)); BIO_free(fp); X509_free(backend->server_cert); backend->server_cert = NULL; @@ -3929,7 +3938,7 @@ static CURLcode servercert(struct Curl_easy *data, if(!issuer) { if(strict) failf(data, "SSL: Unable to read issuer cert (%s)", - SSL_SET_OPTION(issuercert)); + SSL_CONN_CONFIG(issuercert)); BIO_free(fp); X509_free(issuer); X509_free(backend->server_cert); @@ -3940,7 +3949,7 @@ static CURLcode servercert(struct Curl_easy *data, if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", - SSL_SET_OPTION(issuercert)); + SSL_CONN_CONFIG(issuercert)); BIO_free(fp); X509_free(issuer); X509_free(backend->server_cert); @@ -3948,8 +3957,8 @@ static CURLcode servercert(struct Curl_easy *data, return CURLE_SSL_ISSUER_ERROR; } - infof(data, " SSL certificate issuer check ok (%s)\n", - SSL_SET_OPTION(issuercert)); + infof(data, " SSL certificate issuer check ok (%s)", + SSL_CONN_CONFIG(issuercert)); BIO_free(fp); X509_free(issuer); } @@ -3967,11 +3976,11 @@ static CURLcode servercert(struct Curl_easy *data, } else infof(data, " SSL certificate verify result: %s (%ld)," - " continuing anyway.\n", + " continuing anyway.", X509_verify_cert_error_string(lerr), lerr); } else - infof(data, " SSL certificate verify ok.\n"); + infof(data, " SSL certificate verify ok."); } #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ @@ -4015,7 +4024,7 @@ static CURLcode ossl_connect_step3(struct Curl_easy *data, /* * We check certificates to authenticate the server; otherwise we risk * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to - * verify the peer ignore faults and failures from the server cert + * verify the peer, ignore faults and failures from the server cert * operations. */ @@ -4053,7 +4062,7 @@ static CURLcode ossl_connect_common(struct Curl_easy *data, const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); if(timeout_ms < 0) { - /* no need to continue if time already is up */ + /* no need to continue if time is already up */ failf(data, "SSL connection timeout"); return CURLE_OPERATION_TIMEDOUT; } @@ -4244,7 +4253,7 @@ static ssize_t ossl_send(struct Curl_easy *data, #endif ) { char ver[120]; - ossl_version(ver, 120); + (void)ossl_version(ver, sizeof(ver)); failf(data, "Error: %s does not support double SSL tunneling.", ver); } else @@ -4534,9 +4543,6 @@ static void ossl_disassociate_connection(struct Curl_easy *data, return; if(SSL_SET_OPTION(primary.sessionid)) { - bool isproxy = FALSE; - bool incache; - void *old_ssl_sessionid = NULL; int data_idx = ossl_get_ssl_data_index(); int connectdata_idx = ossl_get_ssl_conn_index(); int sockindex_idx = ossl_get_ssl_sockindex_index(); @@ -4544,9 +4550,6 @@ static void ossl_disassociate_connection(struct Curl_easy *data, if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && proxy_idx >= 0) { - /* Invalidate the session cache entry, if any */ - isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE; - /* Disable references to data in "new session" callback to avoid * accessing a stale pointer. */ SSL_set_ex_data(backend->handle, data_idx, NULL); @@ -4554,13 +4557,6 @@ static void ossl_disassociate_connection(struct Curl_easy *data, SSL_set_ex_data(backend->handle, sockindex_idx, NULL); SSL_set_ex_data(backend->handle, proxy_idx, NULL); } - - Curl_ssl_sessionid_lock(data); - incache = !(Curl_ssl_getsessionid(data, conn, isproxy, - &old_ssl_sessionid, NULL, sockindex)); - if(incache) - Curl_ssl_delsessionid(data, old_ssl_sessionid); - Curl_ssl_sessionid_unlock(data); } } diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index d5247f936ad..2ac97ce28e7 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -34,7 +34,7 @@ #include "sendf.h" #include "vtls.h" #include "select.h" - +#include "strerror.h" #include "multiif.h" struct ssl_backend_data @@ -73,7 +73,7 @@ cr_connect(struct Curl_easy *data UNUSED_PARAM, struct connectdata *conn UNUSED_PARAM, int sockindex UNUSED_PARAM) { - infof(data, "rustls_connect: unimplemented\n"); + infof(data, "rustls_connect: unimplemented"); return CURLE_SSL_CONNECT_ERROR; } @@ -129,10 +129,12 @@ cr_recv(struct Curl_easy *data, int sockindex, io_error = rustls_connection_read_tls(rconn, read_cb, &conn->sock[sockindex], &tls_bytes_read); if(io_error == EAGAIN || io_error == EWOULDBLOCK) { - infof(data, "sread: EAGAIN or EWOULDBLOCK\n"); + infof(data, "sread: EAGAIN or EWOULDBLOCK"); } else if(io_error) { - failf(data, "reading from socket: %s", strerror(io_error)); + char buffer[STRERROR_LEN]; + failf(data, "reading from socket: %s", + Curl_strerror(io_error, buffer, sizeof(buffer))); *err = CURLE_READ_ERROR; return -1; } @@ -142,7 +144,7 @@ cr_recv(struct Curl_easy *data, int sockindex, return -1; } - infof(data, "cr_recv read %ld bytes from the network\n", tls_bytes_read); + infof(data, "cr_recv read %ld bytes from the network", tls_bytes_read); rresult = rustls_connection_process_new_packets(rconn); if(rresult != RUSTLS_RESULT_OK) { @@ -173,12 +175,12 @@ cr_recv(struct Curl_easy *data, int sockindex, available data has been read." If we bring in more ciphertext with read_tls, more plaintext will become available. So don't tell curl this is an EOF. Instead, say "come back later." */ - infof(data, "cr_recv got 0 bytes of plaintext\n"); + infof(data, "cr_recv got 0 bytes of plaintext"); backend->data_pending = FALSE; break; } else { - infof(data, "cr_recv copied out %ld bytes of plaintext\n", n); + infof(data, "cr_recv copied out %ld bytes of plaintext", n); plain_bytes_copied += n; } } @@ -218,7 +220,7 @@ cr_send(struct Curl_easy *data, int sockindex, rustls_result rresult; rustls_io_result io_error; - infof(data, "cr_send %ld bytes of plaintext\n", plainlen); + infof(data, "cr_send %ld bytes of plaintext", plainlen); if(plainlen > 0) { rresult = rustls_connection_write(rconn, plainbuf, plainlen, @@ -239,12 +241,14 @@ cr_send(struct Curl_easy *data, int sockindex, io_error = rustls_connection_write_tls(rconn, write_cb, &conn->sock[sockindex], &tlswritten); if(io_error == EAGAIN || io_error == EWOULDBLOCK) { - infof(data, "swrite: EAGAIN after %ld bytes\n", tlswritten_total); + infof(data, "swrite: EAGAIN after %ld bytes", tlswritten_total); *err = CURLE_AGAIN; return -1; } else if(io_error) { - failf(data, "writing to socket: %s", strerror(io_error)); + char buffer[STRERROR_LEN]; + failf(data, "writing to socket: %s", + Curl_strerror(io_error, buffer, sizeof(buffer))); *err = CURLE_WRITE_ERROR; return -1; } @@ -253,7 +257,7 @@ cr_send(struct Curl_easy *data, int sockindex, *err = CURLE_WRITE_ERROR; return -1; } - infof(data, "cr_send wrote %ld bytes to network\n", tlswritten); + infof(data, "cr_send wrote %ld bytes to network", tlswritten); tlswritten_total += tlswritten; } @@ -304,10 +308,10 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn, config_builder = rustls_client_config_builder_new(); #ifdef USE_HTTP2 - infof(data, "offering ALPN for HTTP/1.1 and HTTP/2\n"); + infof(data, "offering ALPN for HTTP/1.1 and HTTP/2"); rustls_client_config_builder_set_protocols(config_builder, alpn, 2); #else - infof(data, "offering ALPN for HTTP/1.1 only\n"); + infof(data, "offering ALPN for HTTP/1.1 only"); rustls_client_config_builder_set_protocols(config_builder, alpn, 1); #endif if(!verifypeer) { @@ -332,15 +336,6 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CACERT_BADFILE; } } - else { - result = rustls_client_config_builder_load_native_roots(config_builder); - if(result != RUSTLS_RESULT_OK) { - failf(data, "failed to load trusted certificates"); - rustls_client_config_free( - rustls_client_config_builder_build(config_builder)); - return CURLE_SSL_CACERT_BADFILE; - } - } backend->config = rustls_client_config_builder_build(config_builder); DEBUGASSERT(rconn == NULL); @@ -364,24 +359,24 @@ cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn, rustls_connection_get_alpn_protocol(rconn, &protocol, &len); if(NULL == protocol) { - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); return; } #ifdef USE_HTTP2 if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) { - infof(data, "ALPN, negotiated h2\n"); + infof(data, "ALPN, negotiated h2"); conn->negnpn = CURL_HTTP_VERSION_2; } else #endif if(len == ALPN_HTTP_1_1_LENGTH && 0 == memcmp(ALPN_HTTP_1_1, protocol, len)) { - infof(data, "ALPN, negotiated http/1.1\n"); + infof(data, "ALPN, negotiated http/1.1"); conn->negnpn = CURL_HTTP_VERSION_1_1; } else { - infof(data, "ALPN, negotiated an unrecognized protocol\n"); + infof(data, "ALPN, negotiated an unrecognized protocol"); } Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? @@ -424,7 +419,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, * once the handshake is done. */ if(!rustls_connection_is_handshaking(rconn)) { - infof(data, "Done handshaking\n"); + infof(data, "Done handshaking"); /* Done with the handshake. Set up callbacks to send/receive data. */ connssl->state = ssl_connection_complete; @@ -449,22 +444,19 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } if(0 == what) { - infof(data, "Curl_socket_check: %s would block\n", - wants_read&&wants_write ? - "writing and reading" : - wants_write ? - "writing" : - "reading"); + infof(data, "Curl_socket_check: %s would block", + wants_read&&wants_write ? "writing and reading" : + wants_write ? "writing" : "reading"); *done = FALSE; return CURLE_OK; } /* socket is readable or writable */ if(wants_write) { - infof(data, "rustls_connection wants us to write_tls.\n"); + infof(data, "rustls_connection wants us to write_tls."); cr_send(data, sockindex, NULL, 0, &tmperr); if(tmperr == CURLE_AGAIN) { - infof(data, "writing would block\n"); + infof(data, "writing would block"); /* fall through */ } else if(tmperr != CURLE_OK) { @@ -473,11 +465,11 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, } if(wants_read) { - infof(data, "rustls_connection wants us to read_tls.\n"); + infof(data, "rustls_connection wants us to read_tls."); cr_recv(data, sockindex, NULL, 0, &tmperr); if(tmperr == CURLE_AGAIN) { - infof(data, "reading would block\n"); + infof(data, "reading would block"); /* fall through */ } else if(tmperr != CURLE_OK) { diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 2bcf11db257..722a937c42a 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -141,6 +141,12 @@ # define CALG_SHA_256 0x0000800c #endif +/* Work around typo in classic MinGW's w32api up to version 5.0, + see https://osdn.net/projects/mingw/ticket/38391 */ +#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH) +#define ALG_CLASS_DHASH ALG_CLASS_HASH +#endif + #define BACKEND connssl->backend static Curl_recv schannel_recv; @@ -279,13 +285,7 @@ get_alg_id_by_name(char *name) #ifdef CALG_HMAC CIPHEROPTION(CALG_HMAC); #endif -#if !defined(__W32API_MAJOR_VERSION) || \ - !defined(__W32API_MINOR_VERSION) || \ - defined(__MINGW64_VERSION_MAJOR) || \ - (__W32API_MAJOR_VERSION > 5) || \ - ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0)) - /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0, - see https://osdn.net/projects/mingw/ticket/38391 */ +#ifdef CALG_TLS1PRF CIPHEROPTION(CALG_TLS1PRF); #endif #ifdef CALG_HASH_REPLACE_OWF @@ -372,23 +372,23 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, store_name_len = sep - path; - if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0) + if(_tcsncmp(path, TEXT("CurrentUser"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_CURRENT_USER; - else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0) + else if(_tcsncmp(path, TEXT("LocalMachine"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE; - else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0) + else if(_tcsncmp(path, TEXT("CurrentService"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE; - else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0) + else if(_tcsncmp(path, TEXT("Services"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_SERVICES; - else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0) + else if(_tcsncmp(path, TEXT("Users"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_USERS; - else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"), + else if(_tcsncmp(path, TEXT("CurrentUserGroupPolicy"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; - else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"), + else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; - else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"), + else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; else @@ -413,6 +413,341 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, return CURLE_OK; } #endif +static CURLcode +schannel_acquire_credential_handle(struct Curl_easy *data, + struct connectdata *conn, + int sockindex) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SCHANNEL_CRED schannel_cred; + PCCERT_CONTEXT client_certs[1] = { NULL }; + SECURITY_STATUS sspi_status = SEC_E_OK; + CURLcode result; + + /* setup Schannel API options */ + memset(&schannel_cred, 0, sizeof(schannel_cred)); + schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; + + if(conn->ssl_config.verifypeer) { +#ifdef HAS_MANUAL_VERIFY_API + if(BACKEND->use_manual_cred_validation) + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; + else +#endif + schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; + + if(SSL_SET_OPTION(no_revoke)) { + schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + + DEBUGF(infof(data, "schannel: disabled server certificate revocation " + "checks")); + } + else if(SSL_SET_OPTION(revoke_best_effort)) { + schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; + + DEBUGF(infof(data, "schannel: ignore revocation offline errors")); + } + else { + schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + + DEBUGF(infof(data, + "schannel: checking server certificate revocation")); + } + } + else { + schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + DEBUGF(infof(data, + "schannel: disabled server cert revocation checks")); + } + + if(!conn->ssl_config.verifyhost) { + schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates.")); + } + + if(!SSL_SET_OPTION(auto_client_cert)) { + schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS; + schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + infof(data, "schannel: disabled automatic use of client certificate"); + } + else + infof(data, "schannel: enabled automatic use of client certificate"); + + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + result = set_ssl_version_min_max(&schannel_cred, data, conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: + case CURL_SSLVERSION_SSLv2: + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(SSL_CONN_CONFIG(cipher_list)) { + result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list), + BACKEND->algIds); + if(CURLE_OK != result) { + failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); + return result; + } + } + + +#ifdef HAS_CLIENT_CERT_PATH + /* client certificate */ + if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { + DWORD cert_store_name = 0; + TCHAR *cert_store_path = NULL; + TCHAR *cert_thumbprint_str = NULL; + CRYPT_HASH_BLOB cert_thumbprint; + BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; + HCERTSTORE cert_store = NULL; + FILE *fInCert = NULL; + void *certdata = NULL; + size_t certsize = 0; + bool blob = data->set.ssl.primary.cert_blob != NULL; + TCHAR *cert_path = NULL; + if(blob) { + certdata = data->set.ssl.primary.cert_blob->data; + certsize = data->set.ssl.primary.cert_blob->len; + } + else { + cert_path = curlx_convert_UTF8_to_tchar( + data->set.ssl.primary.clientcert); + if(!cert_path) + return CURLE_OUT_OF_MEMORY; + + result = get_cert_location(cert_path, &cert_store_name, + &cert_store_path, &cert_thumbprint_str); + + if(result && (data->set.ssl.primary.clientcert[0]!='\0')) + fInCert = fopen(data->set.ssl.primary.clientcert, "rb"); + + if(result && !fInCert) { + failf(data, "schannel: Failed to get certificate location" + " or file for %s", + data->set.ssl.primary.clientcert); + curlx_unicodefree(cert_path); + return result; + } + } + + if((fInCert || blob) && (data->set.ssl.cert_type) && + (!strcasecompare(data->set.ssl.cert_type, "P12"))) { + failf(data, "schannel: certificate format compatibility error " + " for %s", + blob ? "(memory blob)" : data->set.ssl.primary.clientcert); + curlx_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + + if(fInCert || blob) { + /* Reading a .P12 or .pfx file, like the example at bottom of + https://social.msdn.microsoft.com/Forums/windowsdesktop/ + en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5 + */ + CRYPT_DATA_BLOB datablob; + WCHAR* pszPassword; + size_t pwd_len = 0; + int str_w_len = 0; + const char *cert_showfilename_error = blob ? + "(memory blob)" : data->set.ssl.primary.clientcert; + curlx_unicodefree(cert_path); + if(fInCert) { + long cert_tell = 0; + bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0; + if(continue_reading) + cert_tell = ftell(fInCert); + if(cert_tell < 0) + continue_reading = FALSE; + else + certsize = (size_t)cert_tell; + if(continue_reading) + continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; + if(continue_reading) + certdata = malloc(certsize + 1); + if((!certdata) || + ((int) fread(certdata, certsize, 1, fInCert) != 1)) + continue_reading = FALSE; + fclose(fInCert); + if(!continue_reading) { + failf(data, "schannel: Failed to read cert file %s", + data->set.ssl.primary.clientcert); + free(certdata); + return CURLE_SSL_CERTPROBLEM; + } + } + + /* Convert key-pair data to the in-memory certificate store */ + datablob.pbData = (BYTE*)certdata; + datablob.cbData = (DWORD)certsize; + + if(data->set.ssl.key_passwd != NULL) + pwd_len = strlen(data->set.ssl.key_passwd); + pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1)); + if(pszPassword) { + if(pwd_len > 0) + str_w_len = MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + data->set.ssl.key_passwd, (int)pwd_len, + pszPassword, (int)(pwd_len + 1)); + + if((str_w_len >= 0) && (str_w_len <= (int)pwd_len)) + pszPassword[str_w_len] = 0; + else + pszPassword[0] = 0; + + cert_store = PFXImportCertStore(&datablob, pszPassword, 0); + free(pszPassword); + } + if(!blob) + free(certdata); + if(!cert_store) { + DWORD errorcode = GetLastError(); + if(errorcode == ERROR_INVALID_PASSWORD) + failf(data, "schannel: Failed to import cert file %s, " + "password is bad", + cert_showfilename_error); + else + failf(data, "schannel: Failed to import cert file %s, " + "last error is 0x%x", + cert_showfilename_error, errorcode); + return CURLE_SSL_CERTPROBLEM; + } + + client_certs[0] = CertFindCertificateInStore( + cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_ANY, NULL, NULL); + + if(!client_certs[0]) { + failf(data, "schannel: Failed to get certificate from file %s" + ", last error is 0x%x", + cert_showfilename_error, GetLastError()); + CertCloseStore(cert_store, 0); + return CURLE_SSL_CERTPROBLEM; + } + + schannel_cred.cCreds = 1; + schannel_cred.paCred = client_certs; + } + else { + cert_store = + CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, + (HCRYPTPROV)NULL, + CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, + cert_store_path); + if(!cert_store) { + failf(data, "schannel: Failed to open cert store %x %s, " + "last error is 0x%x", + cert_store_name, cert_store_path, GetLastError()); + free(cert_store_path); + curlx_unicodefree(cert_path); + return CURLE_SSL_CERTPROBLEM; + } + free(cert_store_path); + + cert_thumbprint.pbData = cert_thumbprint_data; + cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; + + if(!CryptStringToBinary(cert_thumbprint_str, + CERT_THUMBPRINT_STR_LEN, + CRYPT_STRING_HEX, + cert_thumbprint_data, + &cert_thumbprint.cbData, + NULL, NULL)) { + curlx_unicodefree(cert_path); + CertCloseStore(cert_store, 0); + return CURLE_SSL_CERTPROBLEM; + } + + client_certs[0] = CertFindCertificateInStore( + cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_HASH, &cert_thumbprint, NULL); + + curlx_unicodefree(cert_path); + + if(client_certs[0]) { + schannel_cred.cCreds = 1; + schannel_cred.paCred = client_certs; + } + else { + /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ + CertCloseStore(cert_store, 0); + return CURLE_SSL_CERTPROBLEM; + } + } + CertCloseStore(cert_store, 0); + } +#else + if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { + failf(data, "schannel: client cert support not built in"); + return CURLE_NOT_BUILT_IN; + } +#endif + + /* allocate memory for the re-usable credential handle */ + BACKEND->cred = (struct Curl_schannel_cred *) + calloc(1, sizeof(struct Curl_schannel_cred)); + if(!BACKEND->cred) { + failf(data, "schannel: unable to allocate memory"); + + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); + + return CURLE_OUT_OF_MEMORY; + } + BACKEND->cred->refcount = 1; + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx + */ + sspi_status = + s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, + SECPKG_CRED_OUTBOUND, NULL, + &schannel_cred, NULL, NULL, + &BACKEND->cred->cred_handle, + &BACKEND->cred->time_stamp); + + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); + + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; + failf(data, "schannel: AcquireCredentialsHandle failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + Curl_safefree(BACKEND->cred); + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + return CURLE_OUT_OF_MEMORY; + case SEC_E_NO_CREDENTIALS: + case SEC_E_SECPKG_NOT_FOUND: + case SEC_E_NOT_OWNER: + case SEC_E_UNKNOWN_CREDENTIALS: + case SEC_E_INTERNAL_ERROR: + default: + return CURLE_SSL_CONNECT_ERROR; + } + } + + return CURLE_OK; +} static CURLcode schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, @@ -427,8 +762,6 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #ifdef HAS_ALPN unsigned char alpn_buffer[128]; #endif - SCHANNEL_CRED schannel_cred; - PCCERT_CONTEXT client_certs[1] = { NULL }; SECURITY_STATUS sspi_status = SEC_E_OK; struct Curl_schannel_cred *old_cred = NULL; struct in_addr addr; @@ -440,7 +773,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, char * const hostname = SSL_HOST_NAME(); DEBUGF(infof(data, - "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + "schannel: SSL/TLS connection with %s port %hu (step 1/3)", hostname, conn->remote_port)); if(curlx_verify_windows_version(5, 1, PLATFORM_WINNT, @@ -448,7 +781,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and algorithms that may not be supported by all servers. */ infof(data, "schannel: Windows version is old and may not be able to " - "connect to some servers due to lack of SNI, algorithms, etc.\n"); + "connect to some servers due to lack of SNI, algorithms, etc."); } #ifdef HAS_ALPN @@ -503,338 +836,21 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, SSL_IS_PROXY() ? TRUE : FALSE, (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; - DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); + DEBUGF(infof(data, "schannel: re-using existing credential handle")); /* increment the reference counter of the credential/session handle */ BACKEND->cred->refcount++; DEBUGF(infof(data, - "schannel: incremented credential handle refcount = %d\n", + "schannel: incremented credential handle refcount = %d", BACKEND->cred->refcount)); } Curl_ssl_sessionid_unlock(data); } if(!BACKEND->cred) { - /* setup Schannel API options */ - memset(&schannel_cred, 0, sizeof(schannel_cred)); - schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; - - if(conn->ssl_config.verifypeer) { -#ifdef HAS_MANUAL_VERIFY_API - if(BACKEND->use_manual_cred_validation) - schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; - else -#endif - schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - - if(SSL_SET_OPTION(no_revoke)) { - schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; - - DEBUGF(infof(data, "schannel: disabled server certificate revocation " - "checks\n")); - } - else if(SSL_SET_OPTION(revoke_best_effort)) { - schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; - - DEBUGF(infof(data, "schannel: ignore revocation offline errors")); - } - else { - schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - - DEBUGF(infof(data, - "schannel: checking server certificate revocation\n")); - } - } - else { - schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | - SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; - DEBUGF(infof(data, - "schannel: disabled server cert revocation checks\n")); - } - - if(!conn->ssl_config.verifyhost) { - schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " - "comparing the supplied target name with the subject " - "names in server certificates.\n")); - } - - if(!SSL_SET_OPTION(auto_client_cert)) { - schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS; - schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; - infof(data, "schannel: disabled automatic use of client certificate\n"); - } - else - infof(data, "schannel: enabled automatic use of client certificate\n"); - - switch(conn->ssl_config.version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { - result = set_ssl_version_min_max(&schannel_cred, data, conn); - if(result != CURLE_OK) - return result; - break; - } - case CURL_SSLVERSION_SSLv3: - case CURL_SSLVERSION_SSLv2: - failf(data, "SSL versions not supported"); - return CURLE_NOT_BUILT_IN; - default: - failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); - return CURLE_SSL_CONNECT_ERROR; - } - - if(SSL_CONN_CONFIG(cipher_list)) { - result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list), - BACKEND->algIds); - if(CURLE_OK != result) { - failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); - return result; - } - } - - -#ifdef HAS_CLIENT_CERT_PATH - /* client certificate */ - if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { - DWORD cert_store_name = 0; - TCHAR *cert_store_path = NULL; - TCHAR *cert_thumbprint_str = NULL; - CRYPT_HASH_BLOB cert_thumbprint; - BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN]; - HCERTSTORE cert_store = NULL; - FILE *fInCert = NULL; - void *certdata = NULL; - size_t certsize = 0; - bool blob = data->set.ssl.primary.cert_blob != NULL; - TCHAR *cert_path = NULL; - if(blob) { - certdata = data->set.ssl.primary.cert_blob->data; - certsize = data->set.ssl.primary.cert_blob->len; - } - else { - cert_path = curlx_convert_UTF8_to_tchar( - data->set.ssl.primary.clientcert); - if(!cert_path) - return CURLE_OUT_OF_MEMORY; - - result = get_cert_location(cert_path, &cert_store_name, - &cert_store_path, &cert_thumbprint_str); - - if(result && (data->set.ssl.primary.clientcert[0]!='\0')) - fInCert = fopen(data->set.ssl.primary.clientcert, "rb"); - - if(result && !fInCert) { - failf(data, "schannel: Failed to get certificate location" - " or file for %s", - data->set.ssl.primary.clientcert); - curlx_unicodefree(cert_path); - return result; - } - } - - if((fInCert || blob) && (data->set.ssl.cert_type) && - (!strcasecompare(data->set.ssl.cert_type, "P12"))) { - failf(data, "schannel: certificate format compatibility error " - " for %s", - blob ? "(memory blob)" : data->set.ssl.primary.clientcert); - curlx_unicodefree(cert_path); - return CURLE_SSL_CERTPROBLEM; - } - - if(fInCert || blob) { - /* Reading a .P12 or .pfx file, like the example at bottom of - https://social.msdn.microsoft.com/Forums/windowsdesktop/ - en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5 - */ - CRYPT_DATA_BLOB datablob; - WCHAR* pszPassword; - size_t pwd_len = 0; - int str_w_len = 0; - const char *cert_showfilename_error = blob ? - "(memory blob)" : data->set.ssl.primary.clientcert; - curlx_unicodefree(cert_path); - if(fInCert) { - long cert_tell = 0; - bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0; - if(continue_reading) - cert_tell = ftell(fInCert); - if(cert_tell < 0) - continue_reading = FALSE; - else - certsize = (size_t)cert_tell; - if(continue_reading) - continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; - if(continue_reading) - certdata = malloc(certsize + 1); - if((!certdata) || - ((int) fread(certdata, certsize, 1, fInCert) != 1)) - continue_reading = FALSE; - fclose(fInCert); - if(!continue_reading) { - failf(data, "schannel: Failed to read cert file %s", - data->set.ssl.primary.clientcert); - free(certdata); - return CURLE_SSL_CERTPROBLEM; - } - } - - /* Convert key-pair data to the in-memory certificate store */ - datablob.pbData = (BYTE*)certdata; - datablob.cbData = (DWORD)certsize; - - if(data->set.ssl.key_passwd != NULL) - pwd_len = strlen(data->set.ssl.key_passwd); - pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1)); - if(pszPassword) { - if(pwd_len > 0) - str_w_len = MultiByteToWideChar(CP_UTF8, - MB_ERR_INVALID_CHARS, - data->set.ssl.key_passwd, (int)pwd_len, - pszPassword, (int)(pwd_len + 1)); - - if((str_w_len >= 0) && (str_w_len <= (int)pwd_len)) - pszPassword[str_w_len] = 0; - else - pszPassword[0] = 0; - - cert_store = PFXImportCertStore(&datablob, pszPassword, 0); - free(pszPassword); - } - if(!blob) - free(certdata); - if(!cert_store) { - DWORD errorcode = GetLastError(); - if(errorcode == ERROR_INVALID_PASSWORD) - failf(data, "schannel: Failed to import cert file %s, " - "password is bad", - cert_showfilename_error); - else - failf(data, "schannel: Failed to import cert file %s, " - "last error is 0x%x", - cert_showfilename_error, errorcode); - return CURLE_SSL_CERTPROBLEM; - } - - client_certs[0] = CertFindCertificateInStore( - cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - CERT_FIND_ANY, NULL, NULL); - - if(!client_certs[0]) { - failf(data, "schannel: Failed to get certificate from file %s" - ", last error is 0x%x", - cert_showfilename_error, GetLastError()); - CertCloseStore(cert_store, 0); - return CURLE_SSL_CERTPROBLEM; - } - - schannel_cred.cCreds = 1; - schannel_cred.paCred = client_certs; - } - else { - cert_store = - CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0, - (HCRYPTPROV)NULL, - CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name, - cert_store_path); - if(!cert_store) { - failf(data, "schannel: Failed to open cert store %x %s, " - "last error is 0x%x", - cert_store_name, cert_store_path, GetLastError()); - free(cert_store_path); - curlx_unicodefree(cert_path); - return CURLE_SSL_CERTPROBLEM; - } - free(cert_store_path); - - cert_thumbprint.pbData = cert_thumbprint_data; - cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; - - if(!CryptStringToBinary(cert_thumbprint_str, - CERT_THUMBPRINT_STR_LEN, - CRYPT_STRING_HEX, - cert_thumbprint_data, - &cert_thumbprint.cbData, - NULL, NULL)) { - curlx_unicodefree(cert_path); - CertCloseStore(cert_store, 0); - return CURLE_SSL_CERTPROBLEM; - } - - client_certs[0] = CertFindCertificateInStore( - cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - CERT_FIND_HASH, &cert_thumbprint, NULL); - - curlx_unicodefree(cert_path); - - if(client_certs[0]) { - schannel_cred.cCreds = 1; - schannel_cred.paCred = client_certs; - } - else { - /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ - CertCloseStore(cert_store, 0); - return CURLE_SSL_CERTPROBLEM; - } - } - CertCloseStore(cert_store, 0); - } -#else - if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { - failf(data, "schannel: client cert support not built in"); - return CURLE_NOT_BUILT_IN; - } -#endif - - /* allocate memory for the re-usable credential handle */ - BACKEND->cred = (struct Curl_schannel_cred *) - calloc(1, sizeof(struct Curl_schannel_cred)); - if(!BACKEND->cred) { - failf(data, "schannel: unable to allocate memory"); - - if(client_certs[0]) - CertFreeCertificateContext(client_certs[0]); - - return CURLE_OUT_OF_MEMORY; - } - BACKEND->cred->refcount = 1; - - /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx - */ - sspi_status = - s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, - SECPKG_CRED_OUTBOUND, NULL, - &schannel_cred, NULL, NULL, - &BACKEND->cred->cred_handle, - &BACKEND->cred->time_stamp); - - if(client_certs[0]) - CertFreeCertificateContext(client_certs[0]); - - if(sspi_status != SEC_E_OK) { - char buffer[STRERROR_LEN]; - failf(data, "schannel: AcquireCredentialsHandle failed: %s", - Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); - Curl_safefree(BACKEND->cred); - switch(sspi_status) { - case SEC_E_INSUFFICIENT_MEMORY: - return CURLE_OUT_OF_MEMORY; - case SEC_E_NO_CREDENTIALS: - case SEC_E_SECPKG_NOT_FOUND: - case SEC_E_NOT_OWNER: - case SEC_E_UNKNOWN_CREDENTIALS: - case SEC_E_INTERNAL_ERROR: - default: - return CURLE_SSL_CONNECT_ERROR; - } + result = schannel_acquire_credential_handle(data, conn, sockindex); + if(result != CURLE_OK) { + return result; } } @@ -844,7 +860,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, || Curl_inet_pton(AF_INET6, hostname, &addr6) #endif ) { - infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); + infof(data, "schannel: using IP address, SNI is not supported by OS."); } #ifdef HAS_ALPN @@ -874,16 +890,17 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2) { + alpn_buffer[cur++] = ALPN_H2_LENGTH; memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH); cur += ALPN_H2_LENGTH; - infof(data, "schannel: ALPN, offering %s\n", ALPN_H2); + infof(data, "schannel: ALPN, offering %s", ALPN_H2); } #endif alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH; memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); cur += ALPN_HTTP_1_1_LENGTH; - infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "schannel: ALPN, offering %s", ALPN_HTTP_1_1); *list_len = curlx_uitous(cur - list_start_index); *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short); @@ -971,7 +988,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, } DEBUGF(infof(data, "schannel: sending initial handshake data: " - "sending %lu bytes...\n", outbuf.cbBuffer)); + "sending %lu bytes.", outbuf.cbBuffer)); /* send initial handshake data which is now stored in output buffer */ result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer, @@ -984,7 +1001,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, } DEBUGF(infof(data, "schannel: sent initial handshake data: " - "sent %zd bytes\n", written)); + "sent %zd bytes", written)); BACKEND->recv_unrecoverable_err = CURLE_OK; BACKEND->recv_sspi_close_notify = false; @@ -1018,7 +1035,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; DEBUGF(infof(data, - "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + "schannel: SSL/TLS connection with %s port %hu (step 2/3)", hostname, conn->remote_port)); if(!BACKEND->cred || !BACKEND->ctxt) @@ -1080,7 +1097,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, if(connssl->connecting_state != ssl_connect_2_writing) connssl->connecting_state = ssl_connect_2_reading; DEBUGF(infof(data, "schannel: failed to receive handshake, " - "need more data\n")); + "need more data")); return CURLE_OK; } else if((result != CURLE_OK) || (nread == 0)) { @@ -1092,11 +1109,11 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, /* increase encrypted data buffer offset */ BACKEND->encdata_offset += nread; BACKEND->encdata_is_incomplete = false; - DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); + DEBUGF(infof(data, "schannel: encrypted data got %zd", nread)); } DEBUGF(infof(data, - "schannel: encrypted data buffer: offset %zu length %zu\n", + "schannel: encrypted data buffer: offset %zu length %zu", BACKEND->encdata_offset, BACKEND->encdata_length)); /* setup input buffers */ @@ -1141,7 +1158,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, BACKEND->encdata_is_incomplete = true; connssl->connecting_state = ssl_connect_2_reading; DEBUGF(infof(data, - "schannel: received incomplete message, need more data\n")); + "schannel: received incomplete message, need more data")); return CURLE_OK; } @@ -1153,7 +1170,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; connssl->connecting_state = ssl_connect_2_writing; DEBUGF(infof(data, - "schannel: a client certificate has been requested\n")); + "schannel: a client certificate has been requested")); return CURLE_OK; } @@ -1163,7 +1180,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, /* search for handshake tokens that need to be send */ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { DEBUGF(infof(data, "schannel: sending next handshake data: " - "sending %lu bytes...\n", outbuf[i].cbBuffer)); + "sending %lu bytes.", outbuf[i].cbBuffer)); /* send handshake token to server */ result = Curl_write_plain(data, conn->sock[sockindex], @@ -1218,7 +1235,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, /* check if there was additional remaining encrypted data */ if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { - DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + DEBUGF(infof(data, "schannel: encrypted data length: %lu", inbuf[1].cbBuffer)); /* There are two cases where we could be getting extra data here: @@ -1258,7 +1275,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, /* check if the handshake is complete */ if(sspi_status == SEC_E_OK) { connssl->connecting_state = ssl_connect_3; - DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); + DEBUGF(infof(data, "schannel: SSL/TLS handshake complete")); } pubkey_ptr = SSL_PINNED_PUB_KEY(); @@ -1347,7 +1364,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; bool isproxy = SSL_IS_PROXY(); -#ifdef DEBUGBUILD +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) const char * const hostname = SSL_HOST_NAME(); #endif #ifdef HAS_ALPN @@ -1357,7 +1374,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); DEBUGF(infof(data, - "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + "schannel: SSL/TLS connection with %s port %hu (step 3/3)", hostname, conn->remote_port)); if(!BACKEND->cred) @@ -1393,7 +1410,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, if(alpn_result.ProtoNegoStatus == SecApplicationProtocolNegotiationStatus_Success) { - infof(data, "schannel: ALPN, server accepted to use %.*s\n", + infof(data, "schannel: ALPN, server accepted to use %.*s", alpn_result.ProtocolIdSize, alpn_result.ProtocolId); #ifdef USE_HTTP2 @@ -1410,7 +1427,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, } } else - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } @@ -1427,7 +1444,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, if(incache) { if(old_cred != BACKEND->cred) { DEBUGF(infof(data, - "schannel: old credential handle is stale, removing\n")); + "schannel: old credential handle is stale, removing")); /* we're not taking old_cred ownership here, no refcount++ is needed */ Curl_ssl_delsessionid(data, (void *)old_cred); incache = FALSE; @@ -1446,7 +1463,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, /* this cred session is now also referenced by sessionid cache */ BACKEND->cred->refcount++; DEBUGF(infof(data, - "schannel: stored credential handle in session cache\n")); + "schannel: stored credential handle in session cache")); } } Curl_ssl_sessionid_unlock(data); @@ -1777,21 +1794,21 @@ schannel_recv(struct Curl_easy *data, int sockindex, * handled in the cleanup. */ - DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); + DEBUGF(infof(data, "schannel: client wants to read %zu bytes", len)); *err = CURLE_OK; if(len && len <= BACKEND->decdata_offset) { - infof(data, "schannel: enough decrypted data is already available\n"); + infof(data, "schannel: enough decrypted data is already available"); goto cleanup; } else if(BACKEND->recv_unrecoverable_err) { *err = BACKEND->recv_unrecoverable_err; - infof(data, "schannel: an unrecoverable error occurred in a prior call\n"); + infof(data, "schannel: an unrecoverable error occurred in a prior call"); goto cleanup; } else if(BACKEND->recv_sspi_close_notify) { /* once a server has indicated shutdown there is no more encrypted data */ - infof(data, "schannel: server indicated shutdown in a prior call\n"); + infof(data, "schannel: server indicated shutdown in a prior call"); goto cleanup; } @@ -1820,12 +1837,12 @@ schannel_recv(struct Curl_easy *data, int sockindex, BACKEND->encdata_buffer = reallocated_buffer; BACKEND->encdata_length = reallocated_length; size = BACKEND->encdata_length - BACKEND->encdata_offset; - DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", + DEBUGF(infof(data, "schannel: encdata_buffer resized %zu", BACKEND->encdata_length)); } DEBUGF(infof(data, - "schannel: encrypted data buffer: offset %zu length %zu\n", + "schannel: encrypted data buffer: offset %zu length %zu", BACKEND->encdata_offset, BACKEND->encdata_length)); /* read encrypted data from socket */ @@ -1837,25 +1854,25 @@ schannel_recv(struct Curl_easy *data, int sockindex, nread = -1; if(*err == CURLE_AGAIN) DEBUGF(infof(data, - "schannel: Curl_read_plain returned CURLE_AGAIN\n")); + "schannel: Curl_read_plain returned CURLE_AGAIN")); else if(*err == CURLE_RECV_ERROR) - infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); + infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR"); else - infof(data, "schannel: Curl_read_plain returned error %d\n", *err); + infof(data, "schannel: Curl_read_plain returned error %d", *err); } else if(nread == 0) { BACKEND->recv_connection_closed = true; - DEBUGF(infof(data, "schannel: server closed the connection\n")); + DEBUGF(infof(data, "schannel: server closed the connection")); } else if(nread > 0) { BACKEND->encdata_offset += (size_t)nread; BACKEND->encdata_is_incomplete = false; - DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); + DEBUGF(infof(data, "schannel: encrypted data got %zd", nread)); } } DEBUGF(infof(data, - "schannel: encrypted data buffer: offset %zu length %zu\n", + "schannel: encrypted data buffer: offset %zu length %zu", BACKEND->encdata_offset, BACKEND->encdata_length)); /* decrypt loop */ @@ -1884,7 +1901,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, /* check for successfully decrypted data, even before actual renegotiation or shutdown of the connection context */ if(inbuf[1].BufferType == SECBUFFER_DATA) { - DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", + DEBUGF(infof(data, "schannel: decrypted data length: %lu", inbuf[1].cbBuffer)); /* increase buffer in order to fit the received amount of data */ @@ -1917,15 +1934,15 @@ schannel_recv(struct Curl_easy *data, int sockindex, BACKEND->decdata_offset += size; } - DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); + DEBUGF(infof(data, "schannel: decrypted data added: %zu", size)); DEBUGF(infof(data, - "schannel: decrypted cached: offset %zu length %zu\n", + "schannel: decrypted cached: offset %zu length %zu", BACKEND->decdata_offset, BACKEND->decdata_length)); } /* check for remaining encrypted data */ if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { - DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + DEBUGF(infof(data, "schannel: encrypted data length: %lu", inbuf[3].cbBuffer)); /* check if the remaining data is less than the total amount @@ -1941,7 +1958,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } DEBUGF(infof(data, - "schannel: encrypted cached: offset %zu length %zu\n", + "schannel: encrypted cached: offset %zu length %zu", BACKEND->encdata_offset, BACKEND->encdata_length)); } else { @@ -1951,29 +1968,29 @@ schannel_recv(struct Curl_easy *data, int sockindex, /* check if server wants to renegotiate the connection context */ if(sspi_status == SEC_I_RENEGOTIATE) { - infof(data, "schannel: remote party requests renegotiation\n"); + infof(data, "schannel: remote party requests renegotiation"); if(*err && *err != CURLE_AGAIN) { - infof(data, "schannel: can't renogotiate, an error is pending\n"); + infof(data, "schannel: can't renogotiate, an error is pending"); goto cleanup; } if(BACKEND->encdata_offset) { *err = CURLE_RECV_ERROR; infof(data, "schannel: can't renogotiate, " - "encrypted data available\n"); + "encrypted data available"); goto cleanup; } /* begin renegotiation */ - infof(data, "schannel: renegotiating SSL/TLS connection\n"); + infof(data, "schannel: renegotiating SSL/TLS connection"); connssl->state = ssl_connection_negotiating; connssl->connecting_state = ssl_connect_2_writing; *err = schannel_connect_common(data, conn, sockindex, FALSE, &done); if(*err) { - infof(data, "schannel: renegotiation failed\n"); + infof(data, "schannel: renegotiation failed"); goto cleanup; } /* now retry receiving data */ sspi_status = SEC_E_OK; - infof(data, "schannel: SSL/TLS connection renegotiated\n"); + infof(data, "schannel: SSL/TLS connection renegotiated"); continue; } /* check if the server closed the connection */ @@ -1983,7 +2000,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, BACKEND->recv_sspi_close_notify = true; if(!BACKEND->recv_connection_closed) { BACKEND->recv_connection_closed = true; - infof(data, "schannel: server closed the connection\n"); + infof(data, "schannel: server closed the connection"); } goto cleanup; } @@ -1992,7 +2009,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, BACKEND->encdata_is_incomplete = true; if(!*err) *err = CURLE_AGAIN; - infof(data, "schannel: failed to decrypt data, need more data\n"); + infof(data, "schannel: failed to decrypt data, need more data"); goto cleanup; } else { @@ -2000,23 +2017,23 @@ schannel_recv(struct Curl_easy *data, int sockindex, char buffer[STRERROR_LEN]; #endif *err = CURLE_RECV_ERROR; - infof(data, "schannel: failed to read data from server: %s\n", + infof(data, "schannel: failed to read data from server: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); goto cleanup; } } DEBUGF(infof(data, - "schannel: encrypted data buffer: offset %zu length %zu\n", + "schannel: encrypted data buffer: offset %zu length %zu", BACKEND->encdata_offset, BACKEND->encdata_length)); DEBUGF(infof(data, - "schannel: decrypted data buffer: offset %zu length %zu\n", + "schannel: decrypted data buffer: offset %zu length %zu", BACKEND->decdata_offset, BACKEND->decdata_length)); cleanup: /* Warning- there is no guarantee the encdata state is valid at this point */ - DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); + DEBUGF(infof(data, "schannel: schannel_recv cleanup")); /* Error if the connection has closed without a close_notify. @@ -2038,7 +2055,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, BACKEND->recv_sspi_close_notify = true; else { *err = CURLE_RECV_ERROR; - infof(data, "schannel: server closed abruptly (missing close_notify)\n"); + infof(data, "schannel: server closed abruptly (missing close_notify)"); } } @@ -2052,9 +2069,9 @@ schannel_recv(struct Curl_easy *data, int sockindex, memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, BACKEND->decdata_offset - size); BACKEND->decdata_offset -= size; - DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); + DEBUGF(infof(data, "schannel: decrypted data returned %zu", size)); DEBUGF(infof(data, - "schannel: decrypted data buffer: offset %zu length %zu\n", + "schannel: decrypted data buffer: offset %zu length %zu", BACKEND->decdata_offset, BACKEND->decdata_length)); *err = CURLE_OK; return (ssize_t)size; @@ -2138,7 +2155,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, DEBUGASSERT(data); - infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu", hostname, conn->remote_port); if(BACKEND->cred && BACKEND->ctxt) { @@ -2196,14 +2213,14 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, s_pSecFn->FreeContextBuffer(outbuf.pvBuffer); if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) { infof(data, "schannel: failed to send close msg: %s" - " (bytes written: %zd)\n", curl_easy_strerror(result), written); + " (bytes written: %zd)", curl_easy_strerror(result), written); } } } /* free SSPI Schannel API security context handle */ if(BACKEND->ctxt) { - DEBUGF(infof(data, "schannel: clear security context handle\n")); + DEBUGF(infof(data, "schannel: clear security context handle")); s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); Curl_safefree(BACKEND->ctxt); } diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index 25d47b8087f..1b283d0453b 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -80,7 +80,7 @@ static int is_cr_or_lf(char c) /* Search the substring needle,needlelen into string haystack,haystacklen * Strings don't need to be terminated by a '\0'. * Similar of OSX/Linux memmem (not available on Visual Studio). - * Return position of beginning of first occurence or NULL if not found + * Return position of beginning of first occurrence or NULL if not found */ static const char *c_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) @@ -204,12 +204,12 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, if(result == CURLE_OK) { if(!num_certs) { infof(data, - "schannel: did not add any certificates from CA file '%s'\n", + "schannel: did not add any certificates from CA file '%s'", ca_file_text); } else { infof(data, - "schannel: added %d certificate(s) from CA file '%s'\n", + "schannel: added %d certificate(s) from CA file '%s'", num_certs, ca_file_text); } } @@ -526,7 +526,7 @@ static CURLcode verify_host(struct Curl_easy *data, if(match_result == CURL_HOST_MATCH) { infof(data, "schannel: connection hostname (%s) validated " - "against certificate name (%s)\n", + "against certificate name (%s)", conn_hostname, cert_hostname); result = CURLE_OK; } @@ -535,7 +535,7 @@ static CURLcode verify_host(struct Curl_easy *data, infof(data, "schannel: connection hostname (%s) did not match " - "against certificate name (%s)\n", + "against certificate name (%s)", conn_hostname, cert_hostname); cert_hostname_len = diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c index edd375ea7d7..1e6ed5f06d6 100644 --- a/lib/vtls/sectransp.c +++ b/lib/vtls/sectransp.c @@ -32,6 +32,9 @@ #include "curl_base64.h" #include "strtok.h" #include "multiif.h" +#include "strcase.h" +#include "x509asn1.h" +#include "strerror.h" #ifdef USE_SECTRANSP @@ -1644,7 +1647,7 @@ static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data, } } /* All cipher suites in the list are found. Report to logs as-is */ - infof(data, "SSL: Setting cipher suites list \"%s\"\n", ciphers); + infof(data, "SSL: Setting cipher suites list \"%s\"", ciphers); err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count); if(err != noErr) { @@ -1840,19 +1843,19 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, #endif ) { CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2)); - infof(data, "ALPN, offering %s\n", ALPN_H2); + infof(data, "ALPN, offering %s", ALPN_H2); } #endif CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1)); - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s", ALPN_HTTP_1_1); /* expects length prefixed preference ordered list of protocols in wire * format */ err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr); if(err != noErr) - infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", + infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d", err); CFRelease(alpnArr); } @@ -1861,7 +1864,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, if(SSL_SET_OPTION(key)) { infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " - "Transport. The private key must be in the Keychain.\n"); + "Transport. The private key must be in the Keychain."); } if(ssl_cert || ssl_cert_blob) { @@ -1869,24 +1872,28 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, bool is_cert_file = (!is_cert_data) && is_file(ssl_cert); SecIdentityRef cert_and_key = NULL; - /* User wants to authenticate with a client cert. Look for it: - If we detect that this is a file on disk, then let's load it. - Otherwise, assume that the user wants to use an identity loaded - from the Keychain. */ - if(is_cert_file || is_cert_data) { + /* User wants to authenticate with a client cert. Look for it. Assume that + the user wants to use an identity loaded from the Keychain. If not, try + it as a file on disk */ + + if(!is_cert_data) + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); + else + err = !noErr; + if((err != noErr) && (is_cert_file || is_cert_data)) { if(!SSL_SET_OPTION(cert_type)) - infof(data, "WARNING: SSL: Certificate type not set, assuming " - "PKCS#12 format.\n"); - else if(strncmp(SSL_SET_OPTION(cert_type), "P12", - strlen(SSL_SET_OPTION(cert_type))) != 0) - infof(data, "WARNING: SSL: The Security framework only supports " - "loading identities that are in PKCS#12 format.\n"); + infof(data, "SSL: Certificate type not set, assuming " + "PKCS#12 format."); + else if(!strcasecompare(SSL_SET_OPTION(cert_type), "P12")) { + failf(data, "SSL: The Security framework only supports " + "loading identities that are in PKCS#12 format."); + return CURLE_SSL_CERTPROBLEM; + } err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob, - SSL_SET_OPTION(key_passwd), &cert_and_key); + SSL_SET_OPTION(key_passwd), + &cert_and_key); } - else - err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); if(err == noErr && cert_and_key) { SecCertificateRef cert = NULL; @@ -1899,7 +1906,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, char *certp; CURLcode result = CopyCertSubject(data, cert, &certp); if(!result) { - infof(data, "Client certificate: %s\n", certp); + infof(data, "Client certificate: %s", certp); free(certp); } @@ -2025,7 +2032,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, strlen(hostname)); if(err != noErr) { - infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", + infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d", err); } @@ -2035,11 +2042,11 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, #endif ) { infof(data, "WARNING: using IP address, SNI is being disabled by " - "the OS.\n"); + "the OS."); } } else { - infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); + infof(data, "WARNING: disabling hostname validation also disables SNI."); } ciphers = SSL_CONN_CONFIG(cipher_list); @@ -2082,7 +2089,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof(data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID"); } /* If there isn't one, then let's make one up! This has to be done prior to starting the handshake. */ @@ -2487,7 +2494,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, spkiHeaderLength = 23; break; default: - infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); + infof(data, "SSL: unhandled public key length: %d", pubkeylen); #elif SECTRANSP_PINNEDPUBKEY_V2 default: /* ecDSA secp256r1 pubkeylen == 91 header already included? @@ -2778,35 +2785,35 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol); switch(protocol) { case kSSLProtocol2: - infof(data, "SSL 2.0 connection using %s\n", + infof(data, "SSL 2.0 connection using %s", TLSCipherNameForNumber(cipher)); break; case kSSLProtocol3: - infof(data, "SSL 3.0 connection using %s\n", + infof(data, "SSL 3.0 connection using %s", TLSCipherNameForNumber(cipher)); break; case kTLSProtocol1: - infof(data, "TLS 1.0 connection using %s\n", + infof(data, "TLS 1.0 connection using %s", TLSCipherNameForNumber(cipher)); break; #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS case kTLSProtocol11: - infof(data, "TLS 1.1 connection using %s\n", + infof(data, "TLS 1.1 connection using %s", TLSCipherNameForNumber(cipher)); break; case kTLSProtocol12: - infof(data, "TLS 1.2 connection using %s\n", + infof(data, "TLS 1.2 connection using %s", TLSCipherNameForNumber(cipher)); break; #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 case kTLSProtocol13: - infof(data, "TLS 1.3 connection using %s\n", + infof(data, "TLS 1.3 connection using %s", TLSCipherNameForNumber(cipher)); break; #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ default: - infof(data, "Unknown protocol connection\n"); + infof(data, "Unknown protocol connection"); break; } @@ -2832,7 +2839,7 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, conn->negnpn = CURL_HTTP_VERSION_1_1; } else - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); @@ -2849,13 +2856,60 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn, } } +static CURLcode +add_cert_to_certinfo(struct Curl_easy *data, + SecCertificateRef server_cert, + int idx) +{ + CURLcode result = CURLE_OK; + const char *beg; + const char *end; + CFDataRef cert_data = SecCertificateCopyData(server_cert); + + if(!cert_data) + return CURLE_PEER_FAILED_VERIFICATION; + + beg = (const char *)CFDataGetBytePtr(cert_data); + end = beg + CFDataGetLength(cert_data); + result = Curl_extract_certinfo(data, idx, beg, end); + CFRelease(cert_data); + return result; +} + +static CURLcode +collect_server_cert_single(struct Curl_easy *data, + SecCertificateRef server_cert, + CFIndex idx) +{ + CURLcode result = CURLE_OK; #ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) { + char *certp; + result = CopyCertSubject(data, server_cert, &certp); + if(!result) { + infof(data, "Server certificate: %s", certp); + free(certp); + } + } +#endif + if(data->set.ssl.certinfo) + result = add_cert_to_certinfo(data, server_cert, (int)idx); + return result; +} + /* This should be called during step3 of the connection at the earliest */ -static void -show_verbose_server_cert(struct Curl_easy *data, - struct connectdata *conn, - int sockindex) +static CURLcode +collect_server_cert(struct Curl_easy *data, + struct connectdata *conn, + int sockindex) { +#ifndef CURL_DISABLE_VERBOSE_STRINGS + const bool show_verbose_server_cert = data->set.verbose; +#else + const bool show_verbose_server_cert = false; +#endif + CURLcode result = data->set.ssl.certinfo ? + CURLE_PEER_FAILED_VERIFICATION : CURLE_OK; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; CFArrayRef server_certs = NULL; @@ -2864,8 +2918,11 @@ show_verbose_server_cert(struct Curl_easy *data, CFIndex i, count; SecTrustRef trust = NULL; + if(!show_verbose_server_cert && !data->set.ssl.certinfo) + return CURLE_OK; + if(!backend->ssl_ctx) - return; + return result; #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS #if CURL_BUILD_IOS @@ -2875,15 +2932,11 @@ show_verbose_server_cert(struct Curl_easy *data, a null trust, so be on guard for that: */ if(err == noErr && trust) { count = SecTrustGetCertificateCount(trust); - for(i = 0L ; i < count ; i++) { - CURLcode result; - char *certp; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = SecTrustGetCertificateAtIndex(trust, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(trust); } @@ -2901,15 +2954,11 @@ show_verbose_server_cert(struct Curl_easy *data, a null trust, so be on guard for that: */ if(err == noErr && trust) { count = SecTrustGetCertificateCount(trust); - for(i = 0L ; i < count ; i++) { - char *certp; - CURLcode result; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = SecTrustGetCertificateAtIndex(trust, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(trust); } @@ -2920,16 +2969,12 @@ show_verbose_server_cert(struct Curl_easy *data, /* Just in case SSLCopyPeerCertificates() returns null too... */ if(err == noErr && server_certs) { count = CFArrayGetCount(server_certs); - for(i = 0L ; i < count ; i++) { - char *certp; - CURLcode result; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(server_certs); } @@ -2941,21 +2986,17 @@ show_verbose_server_cert(struct Curl_easy *data, err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs); if(err == noErr) { count = CFArrayGetCount(server_certs); - for(i = 0L ; i < count ; i++) { - CURLcode result; - char *certp; + if(data->set.ssl.certinfo) + result = Curl_ssl_init_certinfo(data, (int)count); + for(i = 0L ; !result && (i < count) ; i++) { server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); - result = CopyCertSubject(data, server_cert, &certp); - if(!result) { - infof(data, "Server certificate: %s\n", certp); - free(certp); - } + result = collect_server_cert_single(data, server_cert, i); } CFRelease(server_certs); } #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ + return result; } -#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ static CURLcode sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn, @@ -2964,12 +3005,11 @@ sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; /* There is no step 3! - * Well, okay, if verbose mode is on, let's print the details of the - * server certificates. */ -#ifndef CURL_DISABLE_VERBOSE_STRINGS - if(data->set.verbose) - show_verbose_server_cert(data, conn, sockindex); -#endif + * Well, okay, let's collect server certificates, and if verbose mode is on, + * let's print the details of the server certificates. */ + const CURLcode result = collect_server_cert(data, conn, sockindex); + if(result) + return result; connssl->connecting_state = ssl_connect_done; return CURLE_OK; @@ -3148,6 +3188,7 @@ static int sectransp_shutdown(struct Curl_easy *data, int what; int rc; char buf[120]; + int loop = 10; /* avoid getting stuck */ if(!backend->ssl_ctx) return 0; @@ -3163,7 +3204,7 @@ static int sectransp_shutdown(struct Curl_easy *data, what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); - for(;;) { + while(loop--) { if(what < 0) { /* anything that gets here is fatally bad */ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); @@ -3182,7 +3223,9 @@ static int sectransp_shutdown(struct Curl_easy *data, nread = read(conn->sock[sockindex], buf, sizeof(buf)); if(nread < 0) { - failf(data, "read: %s", strerror(errno)); + char buffer[STRERROR_LEN]; + failf(data, "read: %s", + Curl_strerror(errno, buffer, sizeof(buffer))); rc = -1; } @@ -3427,6 +3470,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ SSLSUPP_CAINFO_BLOB | + SSLSUPP_CERTINFO | #ifdef SECTRANSP_PINNEDPUBKEY SSLSUPP_PINNEDPUBKEY, #else diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 65f4f773dd6..e5bbe1f5f09 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -125,6 +125,16 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second) return !memcmp(first->data, second->data, first->len); /* same data */ } +static bool safecmp(char *a, char *b) +{ + if(a && b) + return !strcmp(a, b); + else if(!a && !b) + return TRUE; /* match */ + return FALSE; /* no match */ +} + + bool Curl_ssl_config_matches(struct ssl_primary_config *data, struct ssl_primary_config *needle) @@ -136,11 +146,13 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, (data->verifystatus == needle->verifystatus) && blobcmp(data->cert_blob, needle->cert_blob) && blobcmp(data->ca_info_blob, needle->ca_info_blob) && - Curl_safe_strcasecompare(data->CApath, needle->CApath) && - Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && - Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && - Curl_safe_strcasecompare(data->random_file, needle->random_file) && - Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) && + blobcmp(data->issuercert_blob, needle->issuercert_blob) && + safecmp(data->CApath, needle->CApath) && + safecmp(data->CAfile, needle->CAfile) && + safecmp(data->issuercert, needle->issuercert) && + safecmp(data->clientcert, needle->clientcert) && + safecmp(data->random_file, needle->random_file) && + safecmp(data->egdsocket, needle->egdsocket) && Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) && Curl_safe_strcasecompare(data->curves, needle->curves) && @@ -163,8 +175,10 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, CLONE_BLOB(cert_blob); CLONE_BLOB(ca_info_blob); + CLONE_BLOB(issuercert_blob); CLONE_STRING(CApath); CLONE_STRING(CAfile); + CLONE_STRING(issuercert); CLONE_STRING(clientcert); CLONE_STRING(random_file); CLONE_STRING(egdsocket); @@ -180,6 +194,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) { Curl_safefree(sslc->CApath); Curl_safefree(sslc->CAfile); + Curl_safefree(sslc->issuercert); Curl_safefree(sslc->clientcert); Curl_safefree(sslc->random_file); Curl_safefree(sslc->egdsocket); @@ -188,6 +203,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) Curl_safefree(sslc->pinned_key); Curl_safefree(sslc->cert_blob); Curl_safefree(sslc->ca_info_blob); + Curl_safefree(sslc->issuercert_blob); Curl_safefree(sslc->curves); } @@ -326,7 +342,7 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, - int sockindex, bool *done) + bool isproxy, int sockindex, bool *done) { CURLcode result; @@ -345,7 +361,7 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done); if(result) conn->ssl[sockindex].use = FALSE; - else if(*done) + else if(*done && !isproxy) Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ return result; } @@ -407,8 +423,9 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data, DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); - if(!SSL_SET_OPTION(primary.sessionid)) - /* session ID re-use is disabled */ + if(!SSL_SET_OPTION(primary.sessionid) || !data->state.session) + /* session ID re-use is disabled or the session cache has not been + setup */ return TRUE; /* Lock if shared */ @@ -443,6 +460,10 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data, } } + DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d", + no_match? "Didn't find": "Found", + isProxy ? "proxy" : "host", + conn->handler->scheme, name, port)); return no_match; } @@ -492,14 +513,14 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid) */ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, struct connectdata *conn, - bool isProxy, + const bool isProxy, void *ssl_sessionid, size_t idsize, int sockindex) { size_t i; - struct Curl_ssl_session *store = &data->state.session[0]; - long oldest_age = data->state.session[0].age; /* zero if unused */ + struct Curl_ssl_session *store; + long oldest_age; char *clone_host; char *clone_conn_to_host; int conn_to_port; @@ -515,6 +536,11 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, const char *hostname = conn->host.name; #endif (void)sockindex; + if(!data->state.session) + return CURLE_OK; + + store = &data->state.session[0]; + oldest_age = data->state.session[0].age; /* zero if unused */ DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); clone_host = strdup(hostname); @@ -583,6 +609,9 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } + DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]", + store->scheme, store->name, store->remote_port, + isProxy ? "PROXY" : "server")); return CURLE_OK; } @@ -708,12 +737,12 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount) static size_t multissl_version(char *buffer, size_t size); -size_t Curl_ssl_version(char *buffer, size_t size) +void Curl_ssl_version(char *buffer, size_t size) { #ifdef CURL_WITH_MULTI_SSL - return multissl_version(buffer, size); + (void)multissl_version(buffer, size); #else - return Curl_ssl->version(buffer, size); + (void)Curl_ssl->version(buffer, size); #endif } @@ -940,7 +969,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, if(encode) return encode; - infof(data, "\t public key hash: sha256//%s\n", encoded); + infof(data, " public key hash: sha256//%s", encoded); /* it starts with sha256//, copy so we can modify it */ pinkeylen = strlen(pinnedpubkey) + 1; @@ -1374,7 +1403,7 @@ static int multissl_setup(const struct Curl_ssl *backend) for(i = 0; available_backends[i]; i++) { if(strcasecompare(env, available_backends[i]->info.name)) { Curl_ssl = available_backends[i]; - curl_free(env_tmp); + free(env_tmp); return 0; } } @@ -1382,7 +1411,7 @@ static int multissl_setup(const struct Curl_ssl *backend) /* Fall back to first available backend */ Curl_ssl = available_backends[0]; - curl_free(env_tmp); + free(env_tmp); return 0; } diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 7f93e7aedb2..beaa83d9e3d 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -193,6 +193,7 @@ CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, int sockindex); CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, + bool isproxy, int sockindex, bool *done); /* tell the SSL stuff to close down all open information regarding @@ -209,7 +210,7 @@ struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data); /* init the SSL session ID cache */ CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t); -size_t Curl_ssl_version(char *buffer, size_t size); +void Curl_ssl_version(char *buffer, size_t size); bool Curl_ssl_data_pending(const struct connectdata *conn, int connindex); int Curl_ssl_check_cxn(struct connectdata *conn); @@ -246,7 +247,7 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data); */ bool Curl_ssl_getsessionid(struct Curl_easy *data, struct connectdata *conn, - const bool isproxy, + const bool isProxy, void **ssl_sessionid, size_t *idsize, /* set 0 if unknown */ int sockindex); @@ -313,7 +314,7 @@ void Curl_ssl_detach_conn(struct Curl_easy *data, #define Curl_ssl_data_pending(x,y) 0 #define Curl_ssl_check_cxn(x) 0 #define Curl_ssl_free_certinfo(x) Curl_nop_stmt -#define Curl_ssl_connect_nonblocking(x,y,z,w) CURLE_NOT_BUILT_IN +#define Curl_ssl_connect_nonblocking(x,y,z,w,a) CURLE_NOT_BUILT_IN #define Curl_ssl_kill_session(x) Curl_nop_stmt #define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) #define Curl_ssl_cert_status_request() FALSE diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 60e27e36625..16fbb89288e 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -239,7 +239,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, req_method = SSLv23_client_method(); #else infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " - "TLS 1.0 is used exclusively\n"); + "TLS 1.0 is used exclusively"); req_method = TLSv1_client_method(); #endif use_sni(TRUE); @@ -324,7 +324,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, failf(data, "failed setting cipher list: %s", ciphers); return CURLE_SSL_CIPHER; } - infof(data, "Cipher selection: %s\n", ciphers); + infof(data, "Cipher selection: %s", ciphers); } #ifndef NO_FILESYSTEM @@ -347,16 +347,16 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, /* Just continue with a warning if no strict certificate verification is required. */ infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); + " continuing anyway:"); } } else { /* Everything is fine. */ - infof(data, "successfully set certificate verify locations:\n"); + infof(data, "successfully set certificate verify locations:"); } - infof(data, " CAfile: %s\n", + infof(data, " CAfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none"); - infof(data, " CApath: %s\n", + infof(data, " CApath: %s", SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none"); } @@ -406,7 +406,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, (wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, hostname, (unsigned short)hostname_len) != 1)) { infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); + "TLS extension"); } } #endif @@ -450,12 +450,12 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, #ifdef USE_HTTP2 if(data->state.httpwant >= CURL_HTTP_VERSION_2) { strcpy(protocols + strlen(protocols), ALPN_H2 ","); - infof(data, "ALPN, offering %s\n", ALPN_H2); + infof(data, "ALPN, offering %s", ALPN_H2); } #endif strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s", ALPN_HTTP_1_1); if(wolfSSL_UseALPN(backend->handle, protocols, (unsigned)strlen(protocols), @@ -494,15 +494,11 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(backend->handle, ssl_sessionid)) { - char error_buffer[WOLFSSL_MAX_ERROR_SZ]; - Curl_ssl_sessionid_unlock(data); - failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(SSL_get_error(backend->handle, 0), - error_buffer)); - return CURLE_SSL_CONNECT_ERROR; + Curl_ssl_delsessionid(data, ssl_sessionid); + infof(data, "Can't use session ID, going on without\n"); } - /* Informational message */ - infof(data, "SSL re-using session ID\n"); + else + infof(data, "SSL re-using session ID"); } Curl_ssl_sessionid_unlock(data); } @@ -529,6 +525,8 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, const char * const dispname = SSL_HOST_DISPNAME(); const char * const pinnedpubkey = SSL_PINNED_PUB_KEY(); + ERR_clear_error(); + conn->recv[sockindex] = wolfssl_recv; conn->send[sockindex] = wolfssl_send; @@ -582,7 +580,7 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, * as also mismatching CN fields */ else if(DOMAIN_NAME_MISMATCH == detail) { #if 1 - failf(data, "\tsubject alt name(s) or common name do not match \"%s\"", + failf(data, " subject alt name(s) or common name do not match \"%s\"", dispname); return CURLE_PEER_FAILED_VERIFICATION; #else @@ -594,13 +592,13 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, * 'conn->ssl_config.verifyhost' value. */ if(SSL_CONN_CONFIG(verifyhost)) { failf(data, - "\tsubject alt name(s) or common name do not match \"%s\"\n", + " subject alt name(s) or common name do not match \"%s\"\n", dispname); return CURLE_PEER_FAILED_VERIFICATION; } else { infof(data, - "\tsubject alt name(s) and/or common name do not match \"%s\"\n", + " subject alt name(s) and/or common name do not match \"%s\"", dispname); return CURLE_OK; } @@ -609,14 +607,14 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, #if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ else if(ASN_NO_SIGNER_E == detail) { if(SSL_CONN_CONFIG(verifypeer)) { - failf(data, "\tCA signer not available for verification"); + failf(data, " CA signer not available for verification"); return CURLE_SSL_CACERT_BADFILE; } else { /* Just continue with a warning if no strict certificate verification is required. */ infof(data, "CA signer not available for verification, " - "continuing anyway\n"); + "continuing anyway"); } } #endif @@ -681,7 +679,7 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len); if(rc == SSL_SUCCESS) { - infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, + infof(data, "ALPN, server accepted to use %.*s", protocol_len, protocol); if(protocol_len == ALPN_HTTP_1_1_LENGTH && @@ -694,13 +692,13 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, conn->negnpn = CURL_HTTP_VERSION_2; #endif else - infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, + infof(data, "ALPN, unrecognized protocol %.*s", protocol_len, protocol); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } else if(rc == SSL_ALPN_NOT_FOUND) - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); else { failf(data, "ALPN, failure getting protocol, error %d", rc); return CURLE_SSL_CONNECT_ERROR; @@ -710,11 +708,11 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn, connssl->connecting_state = ssl_connect_3; #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010) - infof(data, "SSL connection using %s / %s\n", + infof(data, "SSL connection using %s / %s", wolfSSL_get_version(backend->handle), wolfSSL_get_cipher_name(backend->handle)); #else - infof(data, "SSL connected\n"); + infof(data, "SSL connected"); #endif return CURLE_OK; @@ -743,7 +741,7 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn, &old_ssl_sessionid, NULL, sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); + infof(data, "old SSL session ID is stale, removing"); Curl_ssl_delsessionid(data, old_ssl_sessionid); incache = FALSE; } @@ -779,7 +777,11 @@ static ssize_t wolfssl_send(struct Curl_easy *data, struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - int rc = SSL_write(backend->handle, mem, memlen); + int rc; + + ERR_clear_error(); + + rc = SSL_write(backend->handle, mem, memlen); if(rc <= 0) { int err = SSL_get_error(backend->handle, rc); @@ -810,6 +812,10 @@ static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn, (void) data; if(backend->handle) { + char buf[32]; + /* Maybe the server has already sent a close notify alert. + Read it to avoid an RST on the TCP connection. */ + (void)SSL_read(backend->handle, buf, (int)sizeof(buf)); (void)SSL_shutdown(backend->handle); SSL_free(backend->handle); backend->handle = NULL; @@ -831,7 +837,11 @@ static ssize_t wolfssl_recv(struct Curl_easy *data, struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - int nread = SSL_read(backend->handle, buf, buffsize); + int nread; + + ERR_clear_error(); + + nread = SSL_read(backend->handle, buf, buffsize); if(nread < 0) { int err = SSL_get_error(backend->handle, nread); @@ -916,6 +926,7 @@ static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn, (void) data; if(backend->handle) { + ERR_clear_error(); SSL_free(backend->handle); backend->handle = NULL; } @@ -1089,7 +1100,7 @@ static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */ } static void *wolfssl_get_internals(struct ssl_connect_data *connssl, - CURLINFO info UNUSED_PARAM) + CURLINFO info UNUSED_PARAM) { struct ssl_backend_data *backend = connssl->backend; (void)info; diff --git a/lib/warnless.c b/lib/warnless.c index c0764c42d0b..15c8156d1c9 100644 --- a/lib/warnless.c +++ b/lib/warnless.c @@ -37,85 +37,23 @@ #include "warnless.h" -#define CURL_MASK_SCHAR 0x7F -#define CURL_MASK_UCHAR 0xFF - -#if (SIZEOF_SHORT == 2) -# define CURL_MASK_SSHORT 0x7FFF -# define CURL_MASK_USHORT 0xFFFF -#elif (SIZEOF_SHORT == 4) -# define CURL_MASK_SSHORT 0x7FFFFFFF -# define CURL_MASK_USHORT 0xFFFFFFFF -#elif (SIZEOF_SHORT == 8) -# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF -# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF -#else -# error "SIZEOF_SHORT not defined" -#endif - -#if (SIZEOF_INT == 2) -# define CURL_MASK_SINT 0x7FFF -# define CURL_MASK_UINT 0xFFFF -#elif (SIZEOF_INT == 4) -# define CURL_MASK_SINT 0x7FFFFFFF -# define CURL_MASK_UINT 0xFFFFFFFF -#elif (SIZEOF_INT == 8) -# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF -# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF -#elif (SIZEOF_INT == 16) -# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -#else -# error "SIZEOF_INT not defined" -#endif - -#if (SIZEOF_LONG == 2) -# define CURL_MASK_SLONG 0x7FFFL -# define CURL_MASK_ULONG 0xFFFFUL -#elif (SIZEOF_LONG == 4) -# define CURL_MASK_SLONG 0x7FFFFFFFL -# define CURL_MASK_ULONG 0xFFFFFFFFUL -#elif (SIZEOF_LONG == 8) -# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL -# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL -#elif (SIZEOF_LONG == 16) -# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL -# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL -#else -# error "SIZEOF_LONG not defined" -#endif - -#if (SIZEOF_CURL_OFF_T == 2) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF) -#elif (SIZEOF_CURL_OFF_T == 4) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF) -#elif (SIZEOF_CURL_OFF_T == 8) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF) -#elif (SIZEOF_CURL_OFF_T == 16) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) -#else -# error "SIZEOF_CURL_OFF_T not defined" -#endif - -#if (SIZEOF_SIZE_T == SIZEOF_SHORT) -# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT -# define CURL_MASK_USIZE_T CURL_MASK_USHORT -#elif (SIZEOF_SIZE_T == SIZEOF_INT) -# define CURL_MASK_SSIZE_T CURL_MASK_SINT -# define CURL_MASK_USIZE_T CURL_MASK_UINT -#elif (SIZEOF_SIZE_T == SIZEOF_LONG) -# define CURL_MASK_SSIZE_T CURL_MASK_SLONG -# define CURL_MASK_USIZE_T CURL_MASK_ULONG -#elif (SIZEOF_SIZE_T == SIZEOF_CURL_OFF_T) -# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT -# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT -#else -# error "SIZEOF_SIZE_T not defined" -#endif +#define CURL_MASK_UCHAR ((unsigned char)~0) +#define CURL_MASK_SCHAR (CURL_MASK_UCHAR >> 1) + +#define CURL_MASK_USHORT ((unsigned short)~0) +#define CURL_MASK_SSHORT (CURL_MASK_USHORT >> 1) + +#define CURL_MASK_UINT ((unsigned int)~0) +#define CURL_MASK_SINT (CURL_MASK_UINT >> 1) + +#define CURL_MASK_ULONG ((unsigned long)~0) +#define CURL_MASK_SLONG (CURL_MASK_ULONG >> 1) + +#define CURL_MASK_UCOFFT ((unsigned CURL_TYPEOF_CURL_OFF_T)~0) +#define CURL_MASK_SCOFFT (CURL_MASK_UCOFFT >> 1) + +#define CURL_MASK_USIZE_T ((size_t)~0) +#define CURL_MASK_SSIZE_T (CURL_MASK_USIZE_T >> 1) /* ** unsigned long to unsigned short @@ -207,7 +145,7 @@ unsigned long curlx_uztoul(size_t uznum) # pragma warning(disable:810) /* conversion may lose significant bits */ #endif -#if (SIZEOF_LONG < SIZEOF_SIZE_T) +#if ULONG_MAX < SIZE_T_MAX DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG); #endif return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG); @@ -228,7 +166,7 @@ unsigned int curlx_uztoui(size_t uznum) # pragma warning(disable:810) /* conversion may lose significant bits */ #endif -#if (SIZEOF_INT < SIZEOF_SIZE_T) +#if UINT_MAX < SIZE_T_MAX DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT); #endif return (unsigned int)(uznum & (size_t) CURL_MASK_UINT); @@ -250,7 +188,7 @@ int curlx_sltosi(long slnum) #endif DEBUGASSERT(slnum >= 0); -#if (SIZEOF_INT < SIZEOF_LONG) +#if INT_MAX < LONG_MAX DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT); #endif return (int)(slnum & (long) CURL_MASK_SINT); @@ -272,7 +210,7 @@ unsigned int curlx_sltoui(long slnum) #endif DEBUGASSERT(slnum >= 0); -#if (SIZEOF_INT < SIZEOF_LONG) +#if UINT_MAX < LONG_MAX DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT); #endif return (unsigned int)(slnum & (long) CURL_MASK_UINT); @@ -352,7 +290,7 @@ int curlx_sztosi(ssize_t sznum) #endif DEBUGASSERT(sznum >= 0); -#if (SIZEOF_INT < SIZEOF_SIZE_T) +#if INT_MAX < SSIZE_T_MAX DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT); #endif return (int)(sznum & (ssize_t) CURL_MASK_SINT); diff --git a/lib/x509asn1.c b/lib/x509asn1.c index 281c97248b2..1bdaeadc809 100644 --- a/lib/x509asn1.c +++ b/lib/x509asn1.c @@ -23,7 +23,7 @@ #include "curl_setup.h" #if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ - defined(USE_WOLFSSL) || defined(USE_SCHANNEL) + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) #include <curl/curl.h> #include "urldata.h" @@ -34,6 +34,7 @@ #include "inet_pton.h" #include "curl_base64.h" #include "x509asn1.h" +#include "dynbuf.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -205,16 +206,16 @@ static const char *bool2str(const char *beg, const char *end) */ static const char *octet2str(const char *beg, const char *end) { - size_t n = end - beg; - char *buf = NULL; + struct dynbuf buf; + CURLcode result; - if(n <= (SIZE_T_MAX - 1) / 3) { - buf = malloc(3 * n + 1); - if(buf) - for(n = 0; beg < end; n += 3) - msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); - } - return buf; + Curl_dyn_init(&buf, 3 * CURL_ASN1_MAX + 1); + result = Curl_dyn_addn(&buf, "", 0); + + while(!result && beg < end) + result = Curl_dyn_addf(&buf, "%02x:", (unsigned char) *beg++); + + return Curl_dyn_ptr(&buf); } static const char *bit2str(const char *beg, const char *end) @@ -517,8 +518,8 @@ static const char *GTime2str(const char *beg, const char *end) return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s", beg, beg + 4, beg + 6, beg + 8, beg + 10, sec1, sec2, - fracl? ".": "", fracl, fracp, - sep, tzl, tzp); + fracl? ".": "", (int)fracl, fracp, + sep, (int)tzl, tzp); } /* @@ -558,7 +559,7 @@ static const char *UTime2str(const char *beg, const char *end) return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s", 20 - (*beg >= '5'), beg, beg + 2, beg + 4, beg + 6, beg + 8, sec, - tzl, tzp); + (int)tzl, tzp); } /* @@ -866,7 +867,7 @@ static void do_pubkey_field(struct Curl_easy *data, int certnum, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, label, output); if(!certnum) - infof(data, " %s: %s\n", label, output); + infof(data, " %s: %s", label, output); free((char *) output); } } @@ -905,7 +906,7 @@ static void do_pubkey(struct Curl_easy *data, int certnum, if(len > 32) elem.beg = q; /* Strip leading zero bytes. */ if(!certnum) - infof(data, " RSA Public Key (%lu bits)\n", len); + infof(data, " RSA Public Key (%lu bits)", len); if(data->set.ssl.certinfo) { q = curl_maprintf("%lu", len); if(q) { @@ -978,7 +979,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Subject", ccp); if(!certnum) - infof(data, "%2d Subject: %s\n", certnum, ccp); + infof(data, "%2d Subject: %s", certnum, ccp); free((char *) ccp); /* Issuer. */ @@ -988,7 +989,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp); if(!certnum) - infof(data, " Issuer: %s\n", ccp); + infof(data, " Issuer: %s", ccp); free((char *) ccp); /* Version (always fits in less than 32 bits). */ @@ -1003,7 +1004,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, free((char *) ccp); } if(!certnum) - infof(data, " Version: %lu (0x%lx)\n", version + 1, version); + infof(data, " Version: %lu (0x%lx)", version + 1, version); /* Serial number. */ ccp = ASN1tostr(&cert.serialNumber, 0); @@ -1012,7 +1013,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp); if(!certnum) - infof(data, " Serial Number: %s\n", ccp); + infof(data, " Serial Number: %s", ccp); free((char *) ccp); /* Signature algorithm .*/ @@ -1023,7 +1024,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp); if(!certnum) - infof(data, " Signature Algorithm: %s\n", ccp); + infof(data, " Signature Algorithm: %s", ccp); free((char *) ccp); /* Start Date. */ @@ -1033,7 +1034,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp); if(!certnum) - infof(data, " Start Date: %s\n", ccp); + infof(data, " Start Date: %s", ccp); free((char *) ccp); /* Expire Date. */ @@ -1043,7 +1044,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp); if(!certnum) - infof(data, " Expire Date: %s\n", ccp); + infof(data, " Expire Date: %s", ccp); free((char *) ccp); /* Public Key Algorithm. */ @@ -1054,7 +1055,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp); if(!certnum) - infof(data, " Public Key Algorithm: %s\n", ccp); + infof(data, " Public Key Algorithm: %s", ccp); do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey); free((char *) ccp); @@ -1065,7 +1066,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Signature", ccp); if(!certnum) - infof(data, " Signature: %s\n", ccp); + infof(data, " Signature: %s", ccp); free((char *) ccp); /* Generate PEM certificate. */ @@ -1098,12 +1099,13 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(data->set.ssl.certinfo) Curl_ssl_push_certinfo(data, certnum, "Cert", cp2); if(!certnum) - infof(data, "%s\n", cp2); + infof(data, "%s", cp2); free(cp2); return CURLE_OK; } -#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL + * or USE_SECTRANSP */ #if defined(USE_GSKIT) @@ -1220,12 +1222,12 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, switch(matched) { case 1: /* an alternative name matched the server hostname */ - infof(data, "\t subjectAltName: %s matched\n", dispname); + infof(data, " subjectAltName: %s matched", dispname); return CURLE_OK; case 0: /* an alternative name field existed, but didn't match and then we MUST fail */ - infof(data, "\t subjectAltName does not match %s\n", dispname); + infof(data, " subjectAltName does not match %s", dispname); return CURLE_PEER_FAILED_VERIFICATION; } @@ -1262,7 +1264,7 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ failf(data, "SSL: illegal cert name field"); else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) { - infof(data, "\t common name: %s (matched)\n", dnsname); + infof(data, " common name: %s (matched)", dnsname); free(dnsname); return CURLE_OK; } diff --git a/lib/x509asn1.h b/lib/x509asn1.h index 326e32d5881..3b51eeef8de 100644 --- a/lib/x509asn1.h +++ b/lib/x509asn1.h @@ -26,7 +26,7 @@ #include "curl_setup.h" #if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ - defined(USE_WOLFSSL) || defined(USE_SCHANNEL) + defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) #include "urldata.h" @@ -129,5 +129,6 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum, const char *beg, const char *end); CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn, const char *beg, const char *end); -#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */ +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL + * or USE_SECTRANSP */ #endif /* HEADER_CURL_X509ASN1_H */ From 412189bce78a9862e22853ec29ae73de4885eb27 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Sep 2021 10:05:12 -0400 Subject: [PATCH 1235/1519] curl: Set build options the way we need for CMake --- Utilities/cmcurl/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 6bf0d6a0ab7..9eef01aaf07 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -12,20 +12,32 @@ set(CURL_DISABLE_ALTSVC ON) set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support") set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth") set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?") +set(CURL_DISABLE_DOH OFF) set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?") set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?") +set(CURL_DISABLE_GETOPTIONS OFF) set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?") set(CURL_DISABLE_HSTS ON) +set(CURL_DISABLE_HTTP_AUTH OFF) set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?") set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?") set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?") set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?") +set(CURL_DISABLE_LIBCURL_OPTION OFF) +set(CURL_DISABLE_MIME OFF) set(CURL_DISABLE_MQTT ON) +set(CURL_DISABLE_NETRC OFF) +set(CURL_DISABLE_NTLM OFF) set(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG OFF) +set(CURL_DISABLE_PARSEDATE OFF) set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?") +set(CURL_DISABLE_PROGRESS_METER OFF) set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy") set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?") +set(CURL_DISABLE_SHUFFLE_DNS OFF) +set(CURL_DISABLE_SMB OFF) set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?") +set(CURL_DISABLE_SOCKETPAIR OFF) set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?") set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?") set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity") From 038c416f93bb53a8d2a353474d7c41cea773a30b Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 16 Sep 2021 00:01:13 -0400 Subject: [PATCH 1236/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 55a76f959c3..7fdda7bbc92 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210915) +set(CMake_VERSION_PATCH 20210916) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f77ffbc0e3933dd1247fb20c364452fe0f4f1505 Mon Sep 17 00:00:00 2001 From: Jean-Marc Hengen <jean-marc.hengen@zuehlke.com> Date: Wed, 15 Sep 2021 21:56:33 +0200 Subject: [PATCH 1237/1519] IAR: Restore support for projects not enabling policy CMP0057 Since commit 5b9bfe738c (IAR: Moved search logic to BinUtils., 2021-07-19, v3.21.1~14^2), we use the `IN_LIST` operator in the `CMakeFindBinUtils` module. Set policy `CMP0057` to ensure it is available regardless of the project's policy settings. Fixes: #22640 --- Modules/CMakeFindBinUtils.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index bb97f4a2253..27d9131c837 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -20,6 +20,9 @@ # on UNIX, cygwin and mingw +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + # Resolve full path of CMAKE_TOOL from user-defined name and SEARCH_PATH. function(__resolve_tool_path CMAKE_TOOL SEARCH_PATH DOCSTRING) @@ -240,3 +243,5 @@ if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$") set(CMAKE_IAR_LINKER "${CMAKE_LINKER}" CACHE FILEPATH "The IAR ILINK linker") mark_as_advanced(CMAKE_IAR_LINKER CMAKE_IAR_AR) endif() + +cmake_policy(POP) From 94f37767749a602d3471e7a1ee2772357a444385 Mon Sep 17 00:00:00 2001 From: hhb <haibohuang2010@gmail.com> Date: Thu, 16 Sep 2021 04:11:48 -0400 Subject: [PATCH 1238/1519] Android: Restore searching PATH for executables Since commit a7f41a7ee4 (Android: Fix find_* search order within NDK for unified toolchains, 2020-10-13, v3.20.0-rc1~610^2), we turn off `CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`. This breaks `find_program` searching `PATH` for host executables. Fortunately, the setting turns out not to be necessary, perhaps since commit cbc51a8be3 (Android: restructure android search paths, 2020-11-06, v3.20.0-rc1~509^2). Without it, none of NDK tests fail, so remove it to restore pre-3.20 behavior. Fixes: #22634 --- Modules/Platform/Android-Initialize.cmake | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake index 50f06209f10..63bc949170f 100644 --- a/Modules/Platform/Android-Initialize.cmake +++ b/Modules/Platform/Android-Initialize.cmake @@ -56,11 +56,6 @@ if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) endif() - # Don't search paths in PATH environment variable. - if(NOT DEFINED CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH) - set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) - endif() - # Allows CMake to find headers in the architecture-specific include directories. set(CMAKE_LIBRARY_ARCHITECTURE "${CMAKE_ANDROID_ARCH_TRIPLE}") From 0b7ae84a963307706adaa07d03967db380b98716 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 16 Sep 2021 09:50:25 -0400 Subject: [PATCH 1239/1519] Cygwin: Remove redundant definitions of CYGWIN and UNIX variables These are set by modules loaded for `CMAKE_SYSTEM_NAME`. We do not need to set them again if the compiler defines `__CYGWIN__`. Also remove the now-unused undocumented `CMAKE_COMPILER_IS_CYGWIN` internal variable. --- Modules/CMakeCCompiler.cmake.in | 5 ----- Modules/CMakeCXXCompiler.cmake.in | 5 ----- Modules/CMakeDetermineCCompiler.cmake | 2 -- Modules/CMakeDetermineCXXCompiler.cmake | 2 -- Modules/CMakeDetermineFortranCompiler.cmake | 2 -- Modules/CMakeFortranCompiler.cmake.in | 5 ----- 6 files changed, 21 deletions(-) diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 754f235bae9..075a71319ba 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -31,11 +31,6 @@ set(CMAKE_C_COMPILER_LOADED 1) set(CMAKE_C_COMPILER_WORKS @CMAKE_C_COMPILER_WORKS@) set(CMAKE_C_ABI_COMPILED @CMAKE_C_ABI_COMPILED@) set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) -set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() set(CMAKE_C_COMPILER_ENV_VAR "CC") diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index d0ce77a7ee7..99f92656571 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -32,11 +32,6 @@ set(CMAKE_CXX_COMPILER_LOADED 1) set(CMAKE_CXX_COMPILER_WORKS @CMAKE_CXX_COMPILER_WORKS@) set(CMAKE_CXX_ABI_COMPILED @CMAKE_CXX_ABI_COMPILED@) set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) -set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 0f80f9cffc1..8709fe04014 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -130,8 +130,6 @@ if(NOT CMAKE_C_COMPILER_ID_RUN) endif() if(CMAKE_C_PLATFORM_ID MATCHES "MinGW") set(CMAKE_COMPILER_IS_MINGW 1) - elseif(CMAKE_C_PLATFORM_ID MATCHES "Cygwin") - set(CMAKE_COMPILER_IS_CYGWIN 1) endif() else() if(NOT DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT) diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 556518f496f..a8f6cf1b9db 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -127,8 +127,6 @@ if(NOT CMAKE_CXX_COMPILER_ID_RUN) endif() if(CMAKE_CXX_PLATFORM_ID MATCHES "MinGW") set(CMAKE_COMPILER_IS_MINGW 1) - elseif(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") - set(CMAKE_COMPILER_IS_CYGWIN 1) endif() else() if(NOT DEFINED CMAKE_CXX_COMPILER_FRONTEND_VARIANT) diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index d7d032c01ba..90500375e3e 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -237,8 +237,6 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN) endif() if(CMAKE_Fortran_PLATFORM_ID MATCHES "MinGW") set(CMAKE_COMPILER_IS_MINGW 1) - elseif(CMAKE_Fortran_PLATFORM_ID MATCHES "Cygwin") - set(CMAKE_COMPILER_IS_CYGWIN 1) endif() endif() diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 06ee5286d35..1036655fe0b 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -19,11 +19,6 @@ set(CMAKE_Fortran_COMPILER_LOADED 1) set(CMAKE_Fortran_COMPILER_WORKS @CMAKE_Fortran_COMPILER_WORKS@) set(CMAKE_Fortran_ABI_COMPILED @CMAKE_Fortran_ABI_COMPILED@) set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) -set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() set(CMAKE_Fortran_COMPILER_ENV_VAR "FC") From 735f41fc2d91bac11506ebf355136b0dbd8ac8c7 Mon Sep 17 00:00:00 2001 From: Zack Galbreath <zack.galbreath@kitware.com> Date: Wed, 15 Sep 2021 16:33:41 -0400 Subject: [PATCH 1240/1519] HIP: Use 'rocm_agent_enumerator' to determine CMAKE_HIP_ARCHITECTURES --- Help/variable/CMAKE_HIP_ARCHITECTURES.rst | 3 +- Modules/CMakeDetermineHIPCompiler.cmake | 37 +++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Help/variable/CMAKE_HIP_ARCHITECTURES.rst b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst index 0cf020136c6..bcc6b35cddb 100644 --- a/Help/variable/CMAKE_HIP_ARCHITECTURES.rst +++ b/Help/variable/CMAKE_HIP_ARCHITECTURES.rst @@ -5,7 +5,8 @@ CMAKE_HIP_ARCHITECTURES Default value for :prop_tgt:`HIP_ARCHITECTURES` property of targets. -This is initialized to the default architecture chosen by the compiler. +This is initialized to the architectures reported by ``rocm_agent_enumerator``, +if available, and otherwise to the default chosen by the compiler. This variable is used to initialize the :prop_tgt:`HIP_ARCHITECTURES` property on all targets. See the target property for additional information. diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake index ed0110ae2ca..4f0b75445bd 100644 --- a/Modules/CMakeDetermineHIPCompiler.cmake +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -85,12 +85,43 @@ if(MSVC_HIP_ARCHITECTURE_ID) endif() if(NOT DEFINED CMAKE_HIP_ARCHITECTURES) - # Analyze output from hipcc to get the current GPU architecture. - if(CMAKE_HIP_COMPILER_PRODUCED_OUTPUT MATCHES " -target-cpu ([a-z0-9]+) ") + # Use 'rocm_agent_enumerator' to get the current GPU architecture. + set(_CMAKE_HIP_ARCHITECTURES) + find_program(_CMAKE_HIP_ROCM_AGENT_ENUMERATOR + NAMES rocm_agent_enumerator + NO_CACHE) + if(_CMAKE_HIP_ROCM_AGENT_ENUMERATOR) + execute_process(COMMAND "${_CMAKE_HIP_ROCM_AGENT_ENUMERATOR}" -t GPU + RESULT_VARIABLE _CMAKE_ROCM_AGENT_ENUMERATOR_RESULT + OUTPUT_VARIABLE _CMAKE_ROCM_AGENT_ENUMERATOR_STDOUT + ERROR_VARIABLE _CMAKE_ROCM_AGENT_ENUMERATOR_STDERR + ) + if(_CMAKE_ROCM_AGENT_ENUMERATOR_RESULT EQUAL 0) + separate_arguments(_hip_archs NATIVE_COMMAND "${_CMAKE_ROCM_AGENT_ENUMERATOR_STDOUT}") + foreach(_hip_arch ${_hip_archs}) + if(_hip_arch STREQUAL "gfx000") + continue() + endif() + string(FIND ${_hip_arch} ":" pos) + if(NOT pos STREQUAL "-1") + string(SUBSTRING ${_hip_arch} 0 ${pos} _hip_arch) + endif() + list(APPEND _CMAKE_HIP_ARCHITECTURES "${_hip_arch}") + endforeach() + endif() + unset(_CMAKE_ROCM_AGENT_ENUMERATOR_RESULT) + unset(_CMAKE_ROCM_AGENT_ENUMERATOR_STDOUT) + unset(_CMAKE_ROCM_AGENT_ENUMERATOR_STDERR) + endif() + unset(_CMAKE_HIP_ROCM_AGENT_ENUMERATOR) + if(_CMAKE_HIP_ARCHITECTURES) + set(CMAKE_HIP_ARCHITECTURES "${_CMAKE_HIP_ARCHITECTURES}" CACHE STRING "HIP architectures") + elseif(CMAKE_HIP_COMPILER_PRODUCED_OUTPUT MATCHES " -target-cpu ([a-z0-9]+) ") set(CMAKE_HIP_ARCHITECTURES "${CMAKE_MATCH_1}" CACHE STRING "HIP architectures") else() - message(FATAL_ERROR "Failed to find a working HIP architecture.") + message(FATAL_ERROR "Failed to find a default HIP architecture.") endif() + unset(_CMAKE_HIP_ARCHITECTURES) endif() # configure variables set in this file for fast reload later on From b125e9809a1a3f3e28fc1682c8a33c3a928f79b5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 16 Sep 2021 13:36:40 -0400 Subject: [PATCH 1241/1519] HIP: Detect ROCm path earlier Fail early if it is not found. Use the detected location as a hint to find `rocm_agent_enumerator`. Also remove the leading `_` prefix in case we want to document this publicly later. --- Modules/CMakeDetermineCompilerId.cmake | 11 ----------- Modules/CMakeDetermineHIPCompiler.cmake | 14 ++++++++++++++ Modules/CMakeHIPRuntime.cmake.in | 8 ++++---- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index e933cf4e854..65e72364829 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -172,17 +172,6 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) set(CMAKE_${lang}_COMPILER "${output}/clang++" PARENT_SCOPE) endif() endif() - if(lang STREQUAL "HIP") - execute_process( - COMMAND "${_hipcc_dir}/hipconfig" - --rocmpath - OUTPUT_VARIABLE output - RESULT_VARIABLE result - ) - if(result EQUAL 0) - set(_CMAKE_HIP_COMPILER_ROCM_ROOT "${output}" PARENT_SCOPE) - endif() - endif() endif() if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake index 4f0b75445bd..394f8e2be0b 100644 --- a/Modules/CMakeDetermineHIPCompiler.cmake +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -52,7 +52,20 @@ if(NOT CMAKE_HIP_COMPILER_ID_RUN) CMAKE_DETERMINE_COMPILER_ID(HIP HIPFLAGS CMakeHIPCompilerId.hip) _cmake_find_compiler_sysroot(HIP) +endif() +if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT) + execute_process( + COMMAND hipconfig --rocmpath + OUTPUT_VARIABLE _CMAKE_HIPCONFIG_ROCMPATH + RESULT_VARIABLE _CMAKE_HIPCONFIG_RESULT + ) + if(_CMAKE_HIPCONFIG_RESULT EQUAL 0 AND EXISTS "${_CMAKE_HIPCONFIG_ROCMPATH}") + set(CMAKE_HIP_COMPILER_ROCM_ROOT "${_CMAKE_HIPCONFIG_ROCMPATH}") + endif() +endif() +if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT) + message(FATAL_ERROR "Failed to find ROCm root directory.") endif() if (NOT _CMAKE_TOOLCHAIN_LOCATION) @@ -89,6 +102,7 @@ if(NOT DEFINED CMAKE_HIP_ARCHITECTURES) set(_CMAKE_HIP_ARCHITECTURES) find_program(_CMAKE_HIP_ROCM_AGENT_ENUMERATOR NAMES rocm_agent_enumerator + HINTS "${CMAKE_HIP_COMPILER_ROCM_ROOT}/bin" NO_CACHE) if(_CMAKE_HIP_ROCM_AGENT_ENUMERATOR) execute_process(COMMAND "${_CMAKE_HIP_ROCM_AGENT_ENUMERATOR}" -t GPU diff --git a/Modules/CMakeHIPRuntime.cmake.in b/Modules/CMakeHIPRuntime.cmake.in index ade26bb9b17..3b345aa078a 100644 --- a/Modules/CMakeHIPRuntime.cmake.in +++ b/Modules/CMakeHIPRuntime.cmake.in @@ -4,7 +4,7 @@ function(_CMAKE_FIND_HIP_RUNTIME ) # Determined when hipcc is the HIP compiler - set(_CMAKE_HIP_COMPILER_ROCM_ROOT "@_CMAKE_HIP_COMPILER_ROCM_ROOT@") + set(CMAKE_HIP_COMPILER_ROCM_ROOT "@CMAKE_HIP_COMPILER_ROCM_ROOT@") # Forward facing value that can be provided by the user set(CMAKE_HIP_COMPILER_TOOLKIT_ROOT @CMAKE_HIP_COMPILER_TOOLKIT_ROOT@) @@ -24,10 +24,10 @@ function(_CMAKE_FIND_HIP_RUNTIME ) set(explicit_search_only TRUE) set(error_message_location "CMAKE_HIP_COMPILER_TOOLKIT_ROOT") set(error_message_location "the environment variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]") - elseif(DEFINED _CMAKE_HIP_COMPILER_ROCM_ROOT) - set(rocm_root_dirs "${_CMAKE_HIP_COMPILER_ROCM_ROOT}") + elseif(DEFINED CMAKE_HIP_COMPILER_ROCM_ROOT) + set(rocm_root_dirs "${CMAKE_HIP_COMPILER_ROCM_ROOT}") set(explicit_search_only TRUE) - set(error_message_location "the associated hipconfig --rocmpath [\"${_CMAKE_HIP_COMPILER_ROCM_ROOT}\"]") + set(error_message_location "the associated hipconfig --rocmpath [\"${CMAKE_HIP_COMPILER_ROCM_ROOT}\"]") endif() # Guess on where rocm is installed From a71f0fc9c7762a06d0bfdd64d0d490919e12357a Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 13 Sep 2021 17:31:28 +0000 Subject: [PATCH 1242/1519] HIP: Remove ROMClang compiler id and use Clang directly Since commit bd844387df (ROCMClang: Add the ROCm toolkit derived clang compiler to CMake, 2020-08-28, v3.21.0-rc1~66^2~6) and commit ff0d2858e1 (HIP: Extract clang compiler details from hipcc, 2020-10-21, v3.21.0-rc1~66^2~5), the separate `ROCMClang` compiler id for `hipcc` has caused a few problems: * The compiler id changed from behavior of CMake 3.20 and below, breaking projects that already built with `hipcc` treated as `Clang`. * The implementation of `target_compile_features` was incomplete for the `ROCMClang` identity. * Only `hipcc` was identified as `ROCMClang`, so after it is unwrapped to the underlying `clang++`, future runs of new CMake versions on an existing build tree would not repeat this. * Clang should be usable as a HIP compiler without the `hipcc` wrapper. Remove the `ROMClang` compiler identity, and revise HIP language support to work directly with a Clang compiler. Reject direct `hipcc` usage as a HIP compiler. For now it cannot be supported because it interferes with flags CMake needs to pass to Clang. Fixes: #22536, #22460, #22593 --- Help/release/3.21.rst | 10 ++++ Help/variable/CMAKE_LANG_COMPILER_ID.rst | 1 - Modules/CMakeCompilerIdDetection.cmake | 3 -- Modules/CMakeDetermineCompiler.cmake | 2 +- Modules/CMakeDetermineCompilerId.cmake | 24 --------- Modules/CMakeDetermineHIPCompiler.cmake | 24 ++++++++- Modules/Compiler/ROCMClang-ASM.cmake | 2 - Modules/Compiler/ROCMClang-C.cmake | 7 --- Modules/Compiler/ROCMClang-CXX.cmake | 7 --- .../ROCMClang-DetermineCompiler.cmake | 19 ------- Modules/Compiler/ROCMClang-FindBinUtils.cmake | 1 - Modules/Compiler/ROCMClang-HIP.cmake | 49 ------------------- Modules/Compiler/ROCMClang-OBJC.cmake | 7 --- Modules/Compiler/ROCMClang-OBJCXX.cmake | 7 --- Modules/Compiler/ROCMClang.cmake | 35 ------------- Modules/WriteCompilerDetectionHeader.cmake | 1 - Tests/HIP/WithDefs/CMakeLists.txt | 2 +- 17 files changed, 35 insertions(+), 166 deletions(-) delete mode 100644 Modules/Compiler/ROCMClang-ASM.cmake delete mode 100644 Modules/Compiler/ROCMClang-C.cmake delete mode 100644 Modules/Compiler/ROCMClang-CXX.cmake delete mode 100644 Modules/Compiler/ROCMClang-DetermineCompiler.cmake delete mode 100644 Modules/Compiler/ROCMClang-FindBinUtils.cmake delete mode 100644 Modules/Compiler/ROCMClang-HIP.cmake delete mode 100644 Modules/Compiler/ROCMClang-OBJC.cmake delete mode 100644 Modules/Compiler/ROCMClang-OBJCXX.cmake delete mode 100644 Modules/Compiler/ROCMClang.cmake diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 5d8c200277e..a468817f0b7 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -319,3 +319,13 @@ Changes made since CMake 3.21.0 include the following. * The :generator:`Visual Studio 17 2022` generator is now based on "Visual Studio 2022 Preview 4". Previously it was based on "Preview 3.1". + +* The AMD ROCm Platform ``hipcc`` compiler was identifed by CMake 3.21.0 + through 3.21.2 as a distinct compiler with id ``ROCMClang``. This has + been removed because it caused regressions. Instead: + + * ``hipcc`` may no longer be used as a ``HIP`` compiler because it + interferes with flags CMake needs to pass to Clang. Use Clang directly. + + * ``hipcc`` may once again be used as a ``CXX`` compiler, and is treated as + whatever compiler it selects underneath, as CMake 3.20 and below did. diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index f23b7a214a9..0abedde6a56 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -34,7 +34,6 @@ include: OpenWatcom = Open Watcom (openwatcom.org) PGI = The Portland Group (pgroup.com) PathScale = PathScale (pathscale.com) - ROCMClang = ROCm Toolkit Clang-based Compiler (rocmdocs.amd.com) SDCC = Small Device C Compiler (sdcc.sourceforge.net) SunPro = Oracle Solaris Studio (oracle.com) TI = Texas Instruments (ti.com) diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index dd70d828f5d..e6b3ee32e68 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -82,9 +82,6 @@ function(compiler_id_detection outvar lang) AppleClang ARMClang ) - if(NOT __skip_rocmclang) - list(APPEND ordered_compilers ROCMClang) - endif() list(APPEND ordered_compilers Clang GNU diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake index 6430793baa0..c967ab7c249 100644 --- a/Modules/CMakeDetermineCompiler.cmake +++ b/Modules/CMakeDetermineCompiler.cmake @@ -32,7 +32,7 @@ macro(_cmake_find_compiler lang) endif() # Look for directories containing compilers of reference languages. - set(_${lang}_COMPILER_HINTS) + set(_${lang}_COMPILER_HINTS "${CMAKE_${lang}_COMPILER_HINTS}") foreach(l ${_languages}) if(CMAKE_${l}_COMPILER AND IS_ABSOLUTE "${CMAKE_${l}_COMPILER}") get_filename_component(_hint "${CMAKE_${l}_COMPILER}" PATH) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 65e72364829..30b4aec90b6 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -150,30 +150,6 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() endif() - # When invoked with HIPCC we need to extract the path to the underlying - # clang compiler when possible. This fixes the following issues: - # env variables can change how hipcc behaves - # allows us to properly find the binutils bundled with hip - if(CMAKE_${lang}_COMPILER_ID STREQUAL "ROCMClang" - AND CMAKE_${lang}_COMPILER MATCHES ".*hipcc") - get_filename_component(_hipcc_dir "${CMAKE_${lang}_COMPILER}" DIRECTORY) - execute_process( - COMMAND "${_hipcc_dir}/hipconfig" - --hipclangpath - OUTPUT_VARIABLE output - RESULT_VARIABLE result - ) - if(result EQUAL 0 AND EXISTS "${output}") - if(lang STREQUAL "C") - set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${output}/clang") - set(CMAKE_${lang}_COMPILER "${output}/clang" PARENT_SCOPE) - else() - set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${output}/clang++") - set(CMAKE_${lang}_COMPILER "${output}/clang++" PARENT_SCOPE) - endif() - endif() - endif() - if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake index 394f8e2be0b..5c8849e6ae8 100644 --- a/Modules/CMakeDetermineHIPCompiler.cmake +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -15,6 +15,13 @@ if(NOT CMAKE_HIP_COMPILER) # prefer the environment variable HIPCXX if(NOT $ENV{HIPCXX} STREQUAL "") + if("$ENV{HIPCXX}" MATCHES "hipcc") + message(FATAL_ERROR + "The HIPCXX environment variable is set to the hipcc wrapper:\n" + " $ENV{HIPCXX}\n" + "This is not supported. Use Clang directly, or let CMake pick a default." + ) + endif() get_filename_component(CMAKE_HIP_COMPILER_INIT $ENV{HIPCXX} PROGRAM PROGRAM_ARGS CMAKE_HIP_FLAGS_ENV_INIT) if(CMAKE_HIP_FLAGS_ENV_INIT) set(CMAKE_HIP_COMPILER_ARG1 "${CMAKE_HIP_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CXX compiler") @@ -26,10 +33,25 @@ if(NOT CMAKE_HIP_COMPILER) # finally list compilers to try if(NOT CMAKE_HIP_COMPILER_INIT) - set(CMAKE_HIP_COMPILER_LIST hipcc clang++) + set(CMAKE_HIP_COMPILER_LIST clang++) + + # Look for the Clang coming with ROCm to support HIP. + execute_process(COMMAND hipconfig --hipclangpath + OUTPUT_VARIABLE _CMAKE_HIPCONFIG_CLANGPATH + RESULT_VARIABLE _CMAKE_HIPCONFIG_RESULT + ) + if(_CMAKE_HIPCONFIG_RESULT EQUAL 0 AND EXISTS "${_CMAKE_HIPCONFIG_CLANGPATH}") + set(CMAKE_HIP_COMPILER_HINTS "${_CMAKE_HIPCONFIG_CLANGPATH}") + endif() endif() _cmake_find_compiler(HIP) +elseif(CMAKE_HIP_COMPILER MATCHES "hipcc") + message(FATAL_ERROR + "CMAKE_HIP_COMPILER is set to the hipcc wrapper:\n" + " ${CMAKE_HIP_COMPILER}\n" + "This is not supported. Use Clang directly, or let CMake pick a default." + ) else() _cmake_find_compiler_path(HIP) endif() diff --git a/Modules/Compiler/ROCMClang-ASM.cmake b/Modules/Compiler/ROCMClang-ASM.cmake deleted file mode 100644 index 85d1110a5e7..00000000000 --- a/Modules/Compiler/ROCMClang-ASM.cmake +++ /dev/null @@ -1,2 +0,0 @@ -include(Compiler/ROCMClang) -__compiler_rocmclang(ASM) diff --git a/Modules/Compiler/ROCMClang-C.cmake b/Modules/Compiler/ROCMClang-C.cmake deleted file mode 100644 index cdfa95d9eac..00000000000 --- a/Modules/Compiler/ROCMClang-C.cmake +++ /dev/null @@ -1,7 +0,0 @@ -include(Compiler/ROCMClang) -__compiler_rocmclang(C) - -set(_rocm_clang_ver "${CMAKE_C_COMPILER_VERSION_INTERNAL}") -set(CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION_INTERNAL}") -include(Compiler/Clang-C) -set(CMAKE_C_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang-CXX.cmake b/Modules/Compiler/ROCMClang-CXX.cmake deleted file mode 100644 index 5739c8e5942..00000000000 --- a/Modules/Compiler/ROCMClang-CXX.cmake +++ /dev/null @@ -1,7 +0,0 @@ -include(Compiler/ROCMClang) -__compiler_rocmclang(CXX) - -set(_rocm_clang_ver "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") -set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION_INTERNAL}") -include(Compiler/Clang-CXX) -set(CMAKE_CXX_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang-DetermineCompiler.cmake b/Modules/Compiler/ROCMClang-DetermineCompiler.cmake deleted file mode 100644 index c2fc99b6bde..00000000000 --- a/Modules/Compiler/ROCMClang-DetermineCompiler.cmake +++ /dev/null @@ -1,19 +0,0 @@ - -set(_compiler_id_pp_test "defined(__clang__) && __has_include(<hip/hip_version.h>)") - -set(_compiler_id_version_compute " -# if defined(__clang__) && __has_include(<hip/hip_version.h>) -# include <hip/hip_version.h> -# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(HIP_VERSION_MAJOR) -# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(HIP_VERSION_MINOR) -# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(HIP_VERSION_PATCH) -# endif") - -set(_compiler_id_simulate " -# if defined(_MSC_VER) -# define @PREFIX@SIMULATE_ID \"MSVC\" -# elif defined(__clang__) -# define @PREFIX@SIMULATE_ID \"Clang\" -# elif defined(__GNUC__) -# define @PREFIX@SIMULATE_ID \"GNU\" -# endif") diff --git a/Modules/Compiler/ROCMClang-FindBinUtils.cmake b/Modules/Compiler/ROCMClang-FindBinUtils.cmake deleted file mode 100644 index e721c8708ea..00000000000 --- a/Modules/Compiler/ROCMClang-FindBinUtils.cmake +++ /dev/null @@ -1 +0,0 @@ -include(Compiler/Clang-FindBinUtils) diff --git a/Modules/Compiler/ROCMClang-HIP.cmake b/Modules/Compiler/ROCMClang-HIP.cmake deleted file mode 100644 index 7af769987fd..00000000000 --- a/Modules/Compiler/ROCMClang-HIP.cmake +++ /dev/null @@ -1,49 +0,0 @@ -include(Compiler/ROCMClang) -__compiler_rocmclang(HIP) - -set(_CMAKE_COMPILE_AS_HIP_FLAG "-x hip") -set(_CMAKE_HIP_RDC_FLAG "-fgpu-rdc") - -if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC") - set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") - string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -O") -endif() - -if(CMAKE_HIP_SIMULATE_ID STREQUAL "GNU") - set(CMAKE_HIP_LINKER_WRAPPER_FLAG "-Wl,") - set(CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP ",") -elseif(CMAKE_HIP_SIMULATE_ID STREQUAL "Clang") - set(CMAKE_HIP_LINKER_WRAPPER_FLAG "-Xlinker" " ") - set(CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP) -endif() - -if(NOT CMAKE_HIP_COMPILER_VERSION VERSION_LESS 1.0) - set(CMAKE_HIP98_STANDARD_COMPILE_OPTION "-std=c++98") - set(CMAKE_HIP98_EXTENSION_COMPILE_OPTION "-std=gnu++98") - set(CMAKE_HIP98_STANDARD__HAS_FULL_SUPPORT ON) - - set(CMAKE_HIP11_STANDARD_COMPILE_OPTION "-std=c++11") - set(CMAKE_HIP11_EXTENSION_COMPILE_OPTION "-std=gnu++11") - set(CMAKE_HIP11_STANDARD__HAS_FULL_SUPPORT ON) - - set(CMAKE_HIP14_STANDARD_COMPILE_OPTION "-std=c++14") - set(CMAKE_HIP14_EXTENSION_COMPILE_OPTION "-std=gnu++14") - set(CMAKE_HIP14_STANDARD__HAS_FULL_SUPPORT ON) - - set(CMAKE_HIP17_STANDARD_COMPILE_OPTION "-std=c++17") - set(CMAKE_HIP17_EXTENSION_COMPILE_OPTION "-std=gnu++17") - set(CMAKE_HIP17_STANDARD__HAS_FULL_SUPPORT ON) - - set(CMAKE_HIP20_STANDARD_COMPILE_OPTION "-std=c++20") - set(CMAKE_HIP20_EXTENSION_COMPILE_OPTION "-std=gnu++20") -endif() - -set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") -set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "") -set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "") - -# Populated by CMakeHIPRuntime.cmake -set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC "") -set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED "") - -__compiler_check_default_language_standard(HIP 3.5 11) diff --git a/Modules/Compiler/ROCMClang-OBJC.cmake b/Modules/Compiler/ROCMClang-OBJC.cmake deleted file mode 100644 index 794973d33ea..00000000000 --- a/Modules/Compiler/ROCMClang-OBJC.cmake +++ /dev/null @@ -1,7 +0,0 @@ -include(Compiler/ROCMClang) -__compiler_rocmclang(OBJC) - -set(_rocm_clang_ver "${CMAKE_OBJC_COMPILER_VERSION_INTERNAL}") -set(CMAKE_OBJC_COMPILER_VERSION "${CMAKE_OBJC_COMPILER_VERSION_INTERNAL}") -include(Compiler/Clang-OBJC) -set(CMAKE_OBJC_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang-OBJCXX.cmake b/Modules/Compiler/ROCMClang-OBJCXX.cmake deleted file mode 100644 index 82238e16793..00000000000 --- a/Modules/Compiler/ROCMClang-OBJCXX.cmake +++ /dev/null @@ -1,7 +0,0 @@ -include(Compiler/ROCMClang) -__compiler_rocmclang(OBJCXX) - -set(_rocm_clang_ver "${CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL}") -set(CMAKE_OBJCXX_COMPILER_VERSION "${CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL}") -include(Compiler/Clang-OBJCXX) -set(CMAKE_OBJCXX_COMPILER_VERSION "${_rocm_clang_ver}") diff --git a/Modules/Compiler/ROCMClang.cmake b/Modules/Compiler/ROCMClang.cmake deleted file mode 100644 index 6b38c2d400d..00000000000 --- a/Modules/Compiler/ROCMClang.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - - -# This module is shared by multiple languages; use include blocker. -include_guard() - -include(Compiler/CMakeCommonCompilerMacros) - -macro(__compiler_rocmclang lang) - - set(CMAKE_${lang}_VERBOSE_FLAG "-v") - - if(NOT "x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC") - # Feature flags. - set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") - set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") - set(CMAKE_HIP_COMPILE_OPTIONS_VISIBILITY -fvisibility=) - - string(APPEND CMAKE_HIP_FLAGS_INIT " ") - string(APPEND CMAKE_HIP_FLAGS_DEBUG_INIT " -g") - string(APPEND CMAKE_HIP_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") - string(APPEND CMAKE_HIP_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG") - string(APPEND CMAKE_HIP_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") - endif() - - set(CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS -shared) - set(CMAKE_INCLUDE_SYSTEM_FLAG_HIP "-isystem ") - - set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1) - set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1) - set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1) - set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@") - set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@") -endmacro() diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index 54eb40ed2de..0e4e0280510 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -384,7 +384,6 @@ elseif(_WCDH_policy STREQUAL "") ) endif() -set(__skip_rocmclang TRUE) include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake) function(_load_compiler_variables CompilerId lang) diff --git a/Tests/HIP/WithDefs/CMakeLists.txt b/Tests/HIP/WithDefs/CMakeLists.txt index e2db1820a74..270f95701b5 100644 --- a/Tests/HIP/WithDefs/CMakeLists.txt +++ b/Tests/HIP/WithDefs/CMakeLists.txt @@ -19,7 +19,7 @@ target_compile_options(HIPOnlyWithDefs PRIVATE --offload-arch=gfx900 -DFLAG_COMPILE_LANG_$<COMPILE_LANGUAGE> - $<$<HIP_COMPILER_ID:ROCMClang>:-DFLAG_LANG_IS_HIP=$<COMPILE_LANGUAGE:HIP>> # Host-only defines are possible only on NVCC. + $<$<HIP_COMPILER_ID:Clang>:-DFLAG_LANG_IS_HIP=$<COMPILE_LANGUAGE:HIP>> # Host-only defines are possible only on NVCC. ) target_compile_definitions(HIPOnlyWithDefs From cb93f7262469d0f7e1b7da01ad3586d001234af2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 14 Sep 2021 17:14:22 +0000 Subject: [PATCH 1243/1519] HIP: Simplify detection of HIP runtime CMake package It only makes sense to use the CMake package from the same ROCm installation that the compiler uses. Ask the HIP compiler to report the location of the ROCm installation. Verify up front that it contains the expected CMake package file. --- Modules/CMakeDetermineHIPCompiler.cmake | 20 +++++ Modules/CMakeHIPCompiler.cmake.in | 1 + Modules/CMakeHIPInformation.cmake | 11 ++- Modules/CMakeHIPRuntime.cmake.in | 99 ------------------------- Modules/CMakeTestHIPCompiler.cmake | 21 ------ Modules/Compiler/Clang-HIP.cmake | 2 +- 6 files changed, 29 insertions(+), 125 deletions(-) delete mode 100644 Modules/CMakeHIPRuntime.cmake.in diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake index 5c8849e6ae8..7b7d7a3b4a8 100644 --- a/Modules/CMakeDetermineHIPCompiler.cmake +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -76,6 +76,18 @@ if(NOT CMAKE_HIP_COMPILER_ID_RUN) _cmake_find_compiler_sysroot(HIP) endif() +if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT AND CMAKE_HIP_COMPILER_ID STREQUAL "Clang") + execute_process(COMMAND "${CMAKE_HIP_COMPILER}" -v -print-targets + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _CMAKE_HIP_COMPILER_RESULT + OUTPUT_VARIABLE _CMAKE_HIP_COMPILER_STDOUT + ERROR_VARIABLE _CMAKE_HIP_COMPILER_STDERR + ) + + if(_CMAKE_HIP_COMPILER_RESULT EQUAL 0 AND _CMAKE_HIP_COMPILER_STDERR MATCHES "Found HIP installation: *([^,]*)[,\n]") + set(CMAKE_HIP_COMPILER_ROCM_ROOT "${CMAKE_MATCH_1}") + endif() +endif() if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT) execute_process( COMMAND hipconfig --rocmpath @@ -89,6 +101,14 @@ endif() if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT) message(FATAL_ERROR "Failed to find ROCm root directory.") endif() +if(NOT EXISTS "${CMAKE_HIP_COMPILER_ROCM_ROOT}/lib/cmake/hip-lang/hip-lang-config.cmake") + message(FATAL_ERROR + "The ROCm root directory:\n" + " ${CMAKE_HIP_COMPILER_ROCM_ROOT}\n" + "does not contain the HIP runtime CMake package, expected at:\n" + " ${CMAKE_HIP_COMPILER_ROCM_ROOT}/lib/cmake/hip-lang/hip-lang-config.cmake\n" + ) +endif() if (NOT _CMAKE_TOOLCHAIN_LOCATION) get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_HIP_COMPILER}" PATH) diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in index 9a30a45b3af..17633a86c41 100644 --- a/Modules/CMakeHIPCompiler.cmake.in +++ b/Modules/CMakeHIPCompiler.cmake.in @@ -16,6 +16,7 @@ set(CMAKE_HIP_COMPILER_FRONTEND_VARIANT "@CMAKE_HIP_COMPILER_FRONTEND_VARIANT@") set(CMAKE_HIP_SIMULATE_VERSION "@CMAKE_HIP_SIMULATE_VERSION@") @SET_MSVC_HIP_ARCHITECTURE_ID@ @_SET_CMAKE_HIP_COMPILER_SYSROOT@ +set(CMAKE_HIP_COMPILER_ROCM_ROOT "@CMAKE_HIP_COMPILER_ROCM_ROOT@") set(CMAKE_HIP_COMPILER_ENV_VAR "HIPCXX") diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake index ec37e1c91ae..28c5f184a6e 100644 --- a/Modules/CMakeHIPInformation.cmake +++ b/Modules/CMakeHIPInformation.cmake @@ -132,8 +132,11 @@ endif() set(CMAKE_HIP_INFORMATION_LOADED 1) # Load the file and find the relevant HIP runtime. -# This file will only exist after all compiler detection has finished -include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake OPTIONAL) -if(COMMAND _CMAKE_FIND_HIP_RUNTIME) - _CMAKE_FIND_HIP_RUNTIME() +if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) + set(hip-lang_DIR "${CMAKE_HIP_COMPILER_ROCM_ROOT}/lib/cmake/hip-lang") + find_package(hip-lang CONFIG QUIET NO_DEFAULT_PATH) +endif() +if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) + list(APPEND CMAKE_HIP_RUNTIME_LIBRARIES_STATIC ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET}) + list(APPEND CMAKE_HIP_RUNTIME_LIBRARIES_SHARED ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET}) endif() diff --git a/Modules/CMakeHIPRuntime.cmake.in b/Modules/CMakeHIPRuntime.cmake.in deleted file mode 100644 index 3b345aa078a..00000000000 --- a/Modules/CMakeHIPRuntime.cmake.in +++ /dev/null @@ -1,99 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - - -function(_CMAKE_FIND_HIP_RUNTIME ) - # Determined when hipcc is the HIP compiler - set(CMAKE_HIP_COMPILER_ROCM_ROOT "@CMAKE_HIP_COMPILER_ROCM_ROOT@") - - # Forward facing value that can be provided by the user - set(CMAKE_HIP_COMPILER_TOOLKIT_ROOT @CMAKE_HIP_COMPILER_TOOLKIT_ROOT@) - - if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) - set(message_on_found TRUE) - endif() - - set(explicit_search_only FALSE) - set(rocm_root_dirs ) - if(DEFINED CMAKE_HIP_COMPILER_TOOLKIT_ROOT) - set(rocm_root_dirs "${CMAKE_HIP_COMPILER_TOOLKIT_ROOT}") - set(explicit_search_only TRUE) - set(error_message_location "the variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"${CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]") - elseif(DEFINED ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}) - set(rocm_root_dirs "$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}") - set(explicit_search_only TRUE) - set(error_message_location "CMAKE_HIP_COMPILER_TOOLKIT_ROOT") - set(error_message_location "the environment variable CMAKE_HIP_COMPILER_TOOLKIT_ROOT [\"$ENV{CMAKE_HIP_COMPILER_TOOLKIT_ROOT}\"]") - elseif(DEFINED CMAKE_HIP_COMPILER_ROCM_ROOT) - set(rocm_root_dirs "${CMAKE_HIP_COMPILER_ROCM_ROOT}") - set(explicit_search_only TRUE) - set(error_message_location "the associated hipconfig --rocmpath [\"${CMAKE_HIP_COMPILER_ROCM_ROOT}\"]") - endif() - - # Guess on where rocm is installed - if(NOT rocm_root_dirs AND (UNIX AND NOT APPLE)) - set(platform_base "/opt/rocm-") - - # Finad all default rocm installations - file(GLOB possible_paths "${platform_base}*") - - set(versions) - foreach(p ${possible_paths}) - # Extract version number from end of string - string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+$" p_version ${p}) - if(IS_DIRECTORY ${p} AND p_version) - list(APPEND versions ${p_version}) - endif() - endforeach() - - # Sort numerically in descending order, so we try the newest versions first. - list(SORT versions COMPARE NATURAL ORDER DESCENDING) - - # With a descending list of versions, populate possible paths to search. - set(rocm_root_dirs "/opt/rocm") - foreach(v IN LISTS versions) - list(APPEND rocm_root_dirs "${platform_base}${v}") - endforeach() - endif() - - set(search_rel_path "/lib/cmake/hip-lang/") - list(TRANSFORM rocm_root_dirs APPEND "${search_rel_path}") - - find_package(hip-lang - CONFIG - PATHS ${rocm_root_dirs} - QUIET - NO_DEFAULT_PATH - ) - if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET AND NOT explicit_search_only) - find_package(hip-lang CONFIG QUIET) - endif() - - if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) - set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC - ${CMAKE_HIP_RUNTIME_LIBRARIES_STATIC} - ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET} PARENT_SCOPE) - set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED - ${CMAKE_HIP_RUNTIME_LIBRARIES_SHARED} - ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET} PARENT_SCOPE) - endif() - - if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET AND message_on_found) - message(STATUS "Found HIP runtime: ${hip-lang_DIR}") - elseif(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) - if(explicit_search_only) - set(error_message "Failed to find the HIP runtime, Could not find hip-lang-config.cmake at the following location(s):\n") - foreach(p IN LISTS rocm_root_dirs) - string(APPEND error_message "\t${p}\n") - endforeach() - string(APPEND "which are computed from the location specified by ${error_message_location}. \ - Please specify CMAKE_HIP_COMPILER_TOOLKIT_ROOT to the location of") - message(FATAL_ERROR "${error_message}") - else() - message(FATAL_ERROR - "Failed to find the HIP runtime, Could not find hip-lang-config.cmake.\ - Try setting CMAKE_HIP_COMPILER_TOOLKIT_ROOT") - endif() - endif() - -endfunction() diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake index 62f06573ad3..5acd8062404 100644 --- a/Modules/CMakeTestHIPCompiler.cmake +++ b/Modules/CMakeTestHIPCompiler.cmake @@ -81,20 +81,6 @@ unset(__CMAKE_HIP_FLAGS) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake) CMAKE_DETERMINE_COMPILE_FEATURES(HIP) - -# Setup the following: -# Configure the new template file CMakeHipRuntime.cmake to -# - ${CMAKE_PLATFORM_INFO_DIR}/ -# This file will do the actual find_package query. We than have -# CMakeHIPInformation.cmake include `CMakeHipRuntime` -# So it is included once system information has been finished -# -configure_file( - ${CMAKE_ROOT}/Modules/CMakeHIPRuntime.cmake.in - ${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake - @ONLY -) - # Re-configure to save learned information. configure_file( ${CMAKE_ROOT}/Modules/CMakeHIPCompiler.cmake.in @@ -113,10 +99,3 @@ endif() set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE}) unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE) unset(__CMAKE_HIP_COMPILER_OUTPUT) - -# Load the file and find the relevant HIP runtime. -# This file will only exist after all compiler detection has finished -include(${CMAKE_PLATFORM_INFO_DIR}/CMakeHIPRuntime.cmake) -if(COMMAND _CMAKE_FIND_HIP_RUNTIME) - _CMAKE_FIND_HIP_RUNTIME() -endif() diff --git a/Modules/Compiler/Clang-HIP.cmake b/Modules/Compiler/Clang-HIP.cmake index 1030a43cdae..4dbe2e8c014 100644 --- a/Modules/Compiler/Clang-HIP.cmake +++ b/Modules/Compiler/Clang-HIP.cmake @@ -15,6 +15,6 @@ set(CMAKE_HIP_RUNTIME_LIBRARY_DEFAULT "SHARED") set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "") set(CMAKE_HIP_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "") -# Populated by CMakeHIPRuntime.cmake +# Populated by CMakeHIPInformation.cmake set(CMAKE_HIP_RUNTIME_LIBRARIES_STATIC "") set(CMAKE_HIP_RUNTIME_LIBRARIES_SHARED "") From b73857561fe3ffb8ee0ce3057706c51faabf2e4d Mon Sep 17 00:00:00 2001 From: Thomas Bernard <thomas@famillebernardgouriou.fr> Date: Fri, 17 Sep 2021 00:24:42 +0200 Subject: [PATCH 1244/1519] Clang: embed windows manifests with GNU interface Solves: #22611 --- Modules/Platform/Windows-Clang.cmake | 6 ++++-- Source/cmCommonTargetGenerator.cxx | 13 +++++++++---- Tests/MSManifest/Subdir/CMakeLists.txt | 4 ++++ Tests/MSManifest/Subdir2/CMakeLists.txt | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 373be760d8e..1c32018f374 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -38,6 +38,8 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ") set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP) + set(CMAKE_${lang}_LINKER_MANIFEST_FLAG " -Xlinker /MANIFESTINPUT:") + if("${CMAKE_${lang}_SIMULATE_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)") math(EXPR MSVC_VERSION "${CMAKE_MATCH_1}*100 + ${CMAKE_MATCH_2}") endif() @@ -66,10 +68,10 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>") set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <OBJECTS> <LINK_LIBRARIES>") + "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <OBJECTS> <LINK_LIBRARIES> <MANIFESTS>") set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY}) set(CMAKE_${lang}_LINK_EXECUTABLE - "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>") + "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES> <MANIFESTS>") set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows") set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console") diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 59e41419e55..4e7f50df24a 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -240,11 +240,16 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config) std::vector<std::string> manifests; manifests.reserve(manifest_srcs.size()); + + std::string lang = this->GeneratorTarget->GetLinkerLanguage(config); + std::string const& manifestFlag = + this->Makefile->GetDefinition("CMAKE_" + lang + "_LINKER_MANIFEST_FLAG"); for (cmSourceFile const* manifest_src : manifest_srcs) { - manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat( - this->LocalCommonGenerator->MaybeRelativeToWorkDir( - manifest_src->GetFullPath()), - cmOutputConverter::SHELL)); + manifests.push_back(manifestFlag + + this->LocalCommonGenerator->ConvertToOutputFormat( + this->LocalCommonGenerator->MaybeRelativeToWorkDir( + manifest_src->GetFullPath()), + cmOutputConverter::SHELL)); } return cmJoin(manifests, " "); diff --git a/Tests/MSManifest/Subdir/CMakeLists.txt b/Tests/MSManifest/Subdir/CMakeLists.txt index 8664572c694..3b4fccc1bd9 100644 --- a/Tests/MSManifest/Subdir/CMakeLists.txt +++ b/Tests/MSManifest/Subdir/CMakeLists.txt @@ -7,4 +7,8 @@ if(MSVC AND NOT MSVC_VERSION LESS 1400) -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) add_executable(MSManifestNone main.c) set_property(TARGET MSManifestNone PROPERTY LINK_FLAGS "/MANIFEST:NO") +elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang") + add_test(NAME MSManifest.Single COMMAND + ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSManifest> + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) endif() diff --git a/Tests/MSManifest/Subdir2/CMakeLists.txt b/Tests/MSManifest/Subdir2/CMakeLists.txt index 19d8de73a19..0d960ad5164 100644 --- a/Tests/MSManifest/Subdir2/CMakeLists.txt +++ b/Tests/MSManifest/Subdir2/CMakeLists.txt @@ -6,7 +6,7 @@ add_executable(MSMultipleManifest main.c ${CMAKE_CURRENT_BINARY_DIR}/test_manifest2.manifest ${CMAKE_CURRENT_BINARY_DIR}/test_manifest3.manifest) -if(MSVC AND NOT MSVC_VERSION LESS 1400) +if((MSVC AND NOT MSVC_VERSION LESS 1400) OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang") ) add_test(NAME MSManifest.Multiple COMMAND ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSMultipleManifest> -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) From 241048d6ceb5dd4a16950c29286aebbcc46e565c Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 17 Sep 2021 00:01:19 -0400 Subject: [PATCH 1245/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7fdda7bbc92..3f270cae65c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210916) +set(CMake_VERSION_PATCH 20210917) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 7e154ebd59724d43bf29a8e1c648d6cf7f0e61e4 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 17 Sep 2021 11:56:48 +0200 Subject: [PATCH 1246/1519] cmSystemTools::VersionCompare: use std::string for arguments --- Source/CPack/IFW/cmCPackIFWCommon.cxx | 8 ++- Source/cmConditionEvaluator.cxx | 7 ++- Source/cmGeneratorExpressionNode.cxx | 6 +-- Source/cmGlobalNMakeMakefileGenerator.cxx | 2 +- Source/cmGlobalNinjaGenerator.cxx | 59 +++++++++++------------ Source/cmLocalGenerator.cxx | 12 ++--- Source/cmMakefile.cxx | 3 +- Source/cmSystemTools.cxx | 28 ++++++++--- Source/cmSystemTools.h | 5 +- 9 files changed, 69 insertions(+), 61 deletions(-) diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index 177a959a226..c7ab99469b4 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -51,7 +51,7 @@ bool cmCPackIFWCommon::IsVersionLess(const char* version) const } return cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->Generator->FrameworkVersion.data(), version); + cmSystemTools::OP_LESS, this->Generator->FrameworkVersion, version); } bool cmCPackIFWCommon::IsVersionGreater(const char* version) const @@ -61,8 +61,7 @@ bool cmCPackIFWCommon::IsVersionGreater(const char* version) const } return cmSystemTools::VersionCompare( - cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion.data(), - version); + cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion, version); } bool cmCPackIFWCommon::IsVersionEqual(const char* version) const @@ -72,8 +71,7 @@ bool cmCPackIFWCommon::IsVersionEqual(const char* version) const } return cmSystemTools::VersionCompare( - cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion.data(), - version); + cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion, version); } void cmCPackIFWCommon::ExpandListArgument( diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 68bc4d81fe5..1d7696dbb90 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -729,10 +729,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, keyVERSION_LESS_EQUAL, keyVERSION_GREATER, keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) { const auto op = MATCH2CMPOP[matchNo - 1]; - const cmProp lhs = this->GetVariableOrString(*args.current); - const cmProp rhs = this->GetVariableOrString(*args.nextnext); - const auto result = - cmSystemTools::VersionCompare(op, lhs->c_str(), rhs->c_str()); + const std::string& lhs = this->GetVariableOrString(*args.current); + const std::string& rhs = this->GetVariableOrString(*args.nextnext); + const auto result = cmSystemTools::VersionCompare(op, lhs, rhs); newArgs.ReduceTwoArgs(result, args); } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 3e90eaded89..4e06a0753a9 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -771,8 +771,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode } return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, - parameters.front().c_str(), - compilerVersion.c_str()) + parameters.front(), compilerVersion) ? "1" : "0"; } @@ -830,8 +829,7 @@ struct VersionNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - return cmSystemTools::VersionCompare(Op, parameters.front().c_str(), - parameters[1].c_str()) + return cmSystemTools::VersionCompare(Op, parameters.front(), parameters[1]) ? "1" : "0"; } diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index f08b1da36aa..5ca8d527f90 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -70,7 +70,7 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures() { this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9"); + cmSystemTools::OP_LESS, this->NMakeVersion, "9"); } void cmGlobalNMakeMakefileGenerator::GetDocumentation( diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index c6f82f9337d..6279d68c098 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -558,9 +558,8 @@ void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry) void cmGlobalNinjaGenerator::Generate() { // Check minimum Ninja version. - if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, - this->NinjaVersion.c_str(), - RequiredNinjaVersion().c_str())) { + if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersion())) { std::ostringstream msg; msg << "The detected version of Ninja (" << this->NinjaVersion; msg << ") is less than the version of Ninja required by CMake ("; @@ -721,21 +720,21 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) void cmGlobalNinjaGenerator::CheckNinjaFeatures() { - this->NinjaSupportsConsolePool = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForConsolePool().c_str()); + this->NinjaSupportsConsolePool = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForConsolePool()); this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts().c_str()); - this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForManifestRestat().c_str()); - this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForMultilineDepfile().c_str()); - this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForDyndeps().c_str()); + cmSystemTools::OP_LESS, this->NinjaVersion, + cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts()); + this->NinjaSupportsManifestRestat = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForManifestRestat()); + this->NinjaSupportsMultilineDepfile = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForMultilineDepfile()); + this->NinjaSupportsDyndeps = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForDyndeps()); if (!this->NinjaSupportsDyndeps) { // The ninja version number is not new enough to have upstream support. // Our ninja branch adds ".dyndep-#" to its version number, @@ -753,21 +752,21 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() } this->NinjaSupportsUnconditionalRecompactTool = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForUnconditionalRecompactTool().c_str()); - this->NinjaSupportsRestatTool = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForRestatTool().c_str()); - this->NinjaSupportsMultipleOutputs = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForMultipleOutputs().c_str()); + cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForUnconditionalRecompactTool()); + this->NinjaSupportsRestatTool = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForRestatTool()); + this->NinjaSupportsMultipleOutputs = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForMultipleOutputs()); this->NinjaSupportsMetadataOnRegeneration = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForMetadataOnRegeneration().c_str()); + cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForMetadataOnRegeneration()); #ifdef _WIN32 - this->NinjaSupportsCodePage = !cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), - RequiredNinjaVersionForCodePage().c_str()); + this->NinjaSupportsCodePage = + !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion, + RequiredNinjaVersionForCodePage()); if (this->NinjaSupportsCodePage) { this->CheckNinjaCodePage(); } else { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 5042874c5ef..4c3e8ec8f6b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1961,10 +1961,10 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, cmStrCat("CMAKE_", lang, "_SIMULATE_ID")); if (lang == "Swift") { if (cmProp v = target->GetProperty("Swift_LANGUAGE_VERSION")) { - if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL, - cmToCStr(this->Makefile->GetDefinition( - "CMAKE_Swift_COMPILER_VERSION")), - "4.2")) { + if (cmSystemTools::VersionCompare( + cmSystemTools::OP_GREATER_EQUAL, + this->Makefile->GetDefinition("CMAKE_Swift_COMPILER_VERSION"), + "4.2")) { this->AppendFlags(flags, "-swift-version " + *v); } } @@ -2622,8 +2622,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) // MSVC 2008 is producing both .pdb and .idb files with /Zi. bool msvc2008OrLess = - cmSystemTools::VersionCompare( - cmSystemTools::OP_LESS, compilerVersion.c_str(), "16.0") && + cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + compilerVersion, "16.0") && compilerId == "MSVC"; // but not when used via toolset -Tv90 if (this->Makefile->GetSafeDefinition( diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ef31d76a211..f9b256224aa 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -926,8 +926,7 @@ void cmMakefile::Generate(cmLocalGenerator& lg) this->DoGenerate(lg); cmProp oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); if (oldValue && - cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue->c_str(), - "2.4")) { + cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { this->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, "You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less " diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index a20e787346c..27cb90fa581 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2885,8 +2885,9 @@ bool cmSystemTools::SetRPath(std::string const& file, return false; } -bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, - const char* lhss, const char* rhss) +namespace { +bool VersionCompare(cmSystemTools::CompareOp op, const char* lhss, + const char* rhss) { const char* endl = lhss; const char* endr = rhss; @@ -2919,26 +2920,37 @@ bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, // lhs == rhs, so true if operation is EQUAL return (op & cmSystemTools::OP_EQUAL) != 0; } +} + +bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, + const std::string& lhs, + const std::string& rhs) +{ + return ::VersionCompare(op, lhs.c_str(), rhs.c_str()); +} +bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, + const std::string& lhs, const char rhs[]) +{ + return ::VersionCompare(op, lhs.c_str(), rhs); +} bool cmSystemTools::VersionCompareEqual(std::string const& lhs, std::string const& rhs) { - return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, lhs.c_str(), - rhs.c_str()); + return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, lhs, rhs); } bool cmSystemTools::VersionCompareGreater(std::string const& lhs, std::string const& rhs) { - return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, lhs.c_str(), - rhs.c_str()); + return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, lhs, rhs); } bool cmSystemTools::VersionCompareGreaterEq(std::string const& lhs, std::string const& rhs) { - return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL, - lhs.c_str(), rhs.c_str()); + return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL, lhs, + rhs); } static size_t cm_strverscmp_find_first_difference_or_end(const char* lhs, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index be817b14801..715724c3c8e 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -284,7 +284,10 @@ class cmSystemTools : public cmsys::SystemTools /** * Compare versions */ - static bool VersionCompare(CompareOp op, const char* lhs, const char* rhs); + static bool VersionCompare(CompareOp op, const std::string& lhs, + const std::string& rhs); + static bool VersionCompare(CompareOp op, const std::string& lhs, + const char rhs[]); static bool VersionCompareEqual(std::string const& lhs, std::string const& rhs); static bool VersionCompareGreater(std::string const& lhs, From 6ea883d652a64dc94931c15c2a5c00ed4a9c6b8e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 17 Sep 2021 09:28:57 -0400 Subject: [PATCH 1247/1519] Tests: Avoid output when running symlink check Since commit 58d10cf6f1 (Alternative symlink-creating mode for file(INSTALL ...), 2021-08-02) we test creating a symlink during configuration to decide whether to activate some tests. Capture the process output during the check to avoid leaking the error message on failure. --- Tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 4ccbfebf46c..da6b6704bcc 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1656,6 +1656,8 @@ if(BUILD_TESTING) "${CMake_SOURCE_DIR}/Tests/CMakeLists.txt" # random source file that exists "${CMake_BINARY_DIR}/Tests/try_to_create_symlink" # random target file in existing directory RESULT_VARIABLE _symlink_result + OUTPUT_VARIABLE _symlink_stdout + ERROR_VARIABLE _symlink_stderr ) if(_symlink_result EQUAL 0) file(REMOVE "${CMake_BINARY_DIR}/Tests/try_to_create_symlink") From 39c5dad0cb67f75e745551ef393316725a4124db Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 16 Sep 2021 10:40:40 -0400 Subject: [PATCH 1248/1519] Ninja: Remove redundant check for GNU-like compiler on Windows Update the Ninja generator's check to work using whatever language is being enabled instead of hard-coding C and CXX. With that, the undocumented internal `CMAKE_COMPILER_IS_MINGW` variable is only set by compilers already covered by other alternatives in the condition. See commit b3de0dfe93 (Ninja: Use forward slashes for any GCC on Windows, 2015-05-07, v3.3.0-rc1~93^2~3). --- Source/cmGlobalNinjaGenerator.cxx | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index c6f82f9337d..e2f195fad8a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -929,29 +929,21 @@ void cmGlobalNinjaGenerator::EnableLanguage( continue; } this->ResolveLanguageCompiler(l, mf, optional); - } #ifdef _WIN32 - const bool clangGnuMode = - ((mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") && - (mf->GetSafeDefinition("CMAKE_C_COMPILER_FRONTEND_VARIANT") == "GNU")) || - ((mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") && - (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_FRONTEND_VARIANT") == "GNU")); - - if (clangGnuMode || - ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") && - (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") && - (mf->IsOn("CMAKE_COMPILER_IS_MINGW") || - (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") || - (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") || - (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") || - (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") || - (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "ARMClang") || - (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "ARMClang") || - (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") || - (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) { - this->UsingGCCOnWindows = true; - } + std::string const& compilerId = + mf->GetSafeDefinition(cmStrCat("CMAKE_", l, "_COMPILER_ID")); + std::string const& simulateId = + mf->GetSafeDefinition(cmStrCat("CMAKE_", l, "_SIMULATE_ID")); + std::string const& compilerFrontendVariant = mf->GetSafeDefinition( + cmStrCat("CMAKE_", l, "_COMPILER_FRONTEND_VARIANT")); + if ((compilerId == "Clang" && compilerFrontendVariant == "GNU") || + (simulateId != "MSVC" && + (compilerId == "GNU" || compilerId == "QCC" || + cmHasLiteralSuffix(compilerId, "Clang")))) { + this->UsingGCCOnWindows = true; + } #endif + } } // Implemented by: From a136b6ec986b3e69184d7b07997d81a7cdd720dd Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 17 Sep 2021 11:07:40 -0400 Subject: [PATCH 1249/1519] MINGW: Define variable only when targeting Windows platforms The `MINGW` variable indicates that the compiler targets MinGW, a GNU ABI on Windows. Since commit aff3147917 (Modernize GNU compiler info on Windows, 2009-12-02, v2.8.2~636), we load the `Platform/Windows-GNU` module for compilers targetin MinGW, so set the variable there instead. This is equivalent to `Platform/Windows-MSVC` setting the `MSVC` variable. Also remove `if(MINGW)` checks from the module, which have not been necessary since the enclosed logic was moved to that module. The undocumented `CMAKE_COMPILER_IS_MINGW` internal variable is now unused, so remove it too. Fixes: #22647 --- Modules/CMakeCCompiler.cmake.in | 4 -- Modules/CMakeCXXCompiler.cmake.in | 4 -- Modules/CMakeDetermineCCompiler.cmake | 3 -- Modules/CMakeDetermineCXXCompiler.cmake | 3 -- Modules/CMakeDetermineFortranCompiler.cmake | 3 -- Modules/CMakeFortranCompiler.cmake.in | 4 -- Modules/Platform/Windows-GNU.cmake | 44 ++++++++++----------- 7 files changed, 20 insertions(+), 45 deletions(-) diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 075a71319ba..68183815033 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -30,13 +30,9 @@ set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@) set(CMAKE_C_COMPILER_LOADED 1) set(CMAKE_C_COMPILER_WORKS @CMAKE_C_COMPILER_WORKS@) set(CMAKE_C_ABI_COMPILED @CMAKE_C_ABI_COMPILED@) -set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) set(CMAKE_C_COMPILER_ENV_VAR "CC") -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() set(CMAKE_C_COMPILER_ID_RUN 1) set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 99f92656571..7aad9e2a3e0 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -31,13 +31,9 @@ set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@) set(CMAKE_CXX_COMPILER_LOADED 1) set(CMAKE_CXX_COMPILER_WORKS @CMAKE_CXX_COMPILER_WORKS@) set(CMAKE_CXX_ABI_COMPILED @CMAKE_CXX_ABI_COMPILED@) -set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() set(CMAKE_CXX_COMPILER_ID_RUN 1) set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 8709fe04014..15eab0f5e9b 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -128,9 +128,6 @@ if(NOT CMAKE_C_COMPILER_ID_RUN) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") set(CMAKE_COMPILER_IS_GNUCC 1) endif() - if(CMAKE_C_PLATFORM_ID MATCHES "MinGW") - set(CMAKE_COMPILER_IS_MINGW 1) - endif() else() if(NOT DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT) # Some toolchain files set our internal CMAKE_C_COMPILER_ID_RUN diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index a8f6cf1b9db..72dc8d3d57d 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -125,9 +125,6 @@ if(NOT CMAKE_CXX_COMPILER_ID_RUN) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(CMAKE_COMPILER_IS_GNUCXX 1) endif() - if(CMAKE_CXX_PLATFORM_ID MATCHES "MinGW") - set(CMAKE_COMPILER_IS_MINGW 1) - endif() else() if(NOT DEFINED CMAKE_CXX_COMPILER_FRONTEND_VARIANT) # Some toolchain files set our internal CMAKE_CXX_COMPILER_ID_RUN diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 90500375e3e..6a8984b2bd5 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -235,9 +235,6 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN) if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") set(CMAKE_COMPILER_IS_GNUG77 1) endif() - if(CMAKE_Fortran_PLATFORM_ID MATCHES "MinGW") - set(CMAKE_COMPILER_IS_MINGW 1) - endif() endif() if (NOT _CMAKE_TOOLCHAIN_LOCATION) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 1036655fe0b..f690eb21a04 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -18,15 +18,11 @@ set(CMAKE_COMPILER_IS_GNUG77 @CMAKE_COMPILER_IS_GNUG77@) set(CMAKE_Fortran_COMPILER_LOADED 1) set(CMAKE_Fortran_COMPILER_WORKS @CMAKE_Fortran_COMPILER_WORKS@) set(CMAKE_Fortran_ABI_COMPILED @CMAKE_Fortran_ABI_COMPILED@) -set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@) set(CMAKE_Fortran_COMPILER_ENV_VAR "FC") set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 @CMAKE_Fortran_COMPILER_SUPPORTS_F90@) -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() set(CMAKE_Fortran_COMPILER_ID_RUN 1) set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95) set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index d0003803bde..3ca5053dae2 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -8,6 +8,8 @@ if(__WINDOWS_GNU) endif() set(__WINDOWS_GNU 1) +set(MINGW 1) + set(CMAKE_IMPORT_LIBRARY_PREFIX "lib") set(CMAKE_SHARED_LIBRARY_PREFIX "lib") set(CMAKE_SHARED_MODULE_PREFIX "lib") @@ -19,16 +21,12 @@ set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") set(CMAKE_SHARED_MODULE_SUFFIX ".dll") set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") -if(MSYS OR MINGW) - set(CMAKE_EXTRA_LINK_EXTENSIONS ".lib") # MinGW can also link to a MS .lib -endif() +set(CMAKE_EXTRA_LINK_EXTENSIONS ".lib") # MinGW can also link to a MS .lib -if(MINGW) - set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a" ".lib") - set(CMAKE_C_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32") - set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") -endif() +set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a" ".lib") +set(CMAKE_C_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32") +set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") set(CMAKE_DL_LIBS "") set(CMAKE_LIBRARY_PATH_FLAG "-L") @@ -48,21 +46,19 @@ endif() macro(__windows_compiler_gnu lang) - if(MSYS OR MINGW) - # Create archiving rules to support large object file lists for static libraries. - set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>") - - # Initialize C link type selection flags. These flags are used when - # building a shared library, shared module, or executable that links - # to other libraries to select whether to use the static or shared - # versions of the libraries. - foreach(type SHARED_LIBRARY SHARED_MODULE EXE) - set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic") - set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic") - endforeach() - endif() + # Create archiving rules to support large object file lists for static libraries. + set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>") + + # Initialize C link type selection flags. These flags are used when + # building a shared library, shared module, or executable that links + # to other libraries to select whether to use the static or shared + # versions of the libraries. + foreach(type SHARED_LIBRARY SHARED_MODULE EXE) + set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic") + set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic") + endforeach() # No -fPIC on Windows set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "") From 0723b2c93590b45a9f551c2ece2d2b80a2a2ae1d Mon Sep 17 00:00:00 2001 From: Helmut Grohne <helmut@subdivi.de> Date: Fri, 17 Sep 2021 16:11:58 +0200 Subject: [PATCH 1250/1519] MPI: Add fallback detection code for MPI when cross compiling The MPI libraries use a compiler wrapper to automatically inject required flags and libraries into the compiler argument list. However, the wrapper does not support cross-compiling: the wrapper will try to invoke the native compiler which cannot handle the cross architecture MPI libraries and fail. This MR adds some fallback code for this case, which tries to bypass the faulty wrapper and determine the necessary flags and libraries directly from the MPI pkg-config files. The patch tries to be as unintrusive as possible and should not break any existing use-cases. Fixes: #22650 --- Modules/FindMPI.cmake | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index d4b4a34af07..62412aeec58 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -267,6 +267,7 @@ cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindPkgConfig.cmake) # Generic compiler names set(_MPI_C_GENERIC_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r) @@ -1572,7 +1573,40 @@ foreach(LANG IN ITEMS C CXX Fortran) if(NOT MPI_PINNED_COMPILER AND NOT MPI_${LANG}_WRAPPER_FOUND) # If MPI_PINNED_COMPILER wasn't given, and the MPI compiler we potentially found didn't work, we withdraw it. set(MPI_${LANG}_COMPILER "MPI_${LANG}_COMPILER-NOTFOUND" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE) - if(NOT MPI_SKIP_GUESSING) + + if(LANG STREQUAL "C") + set(_MPI_PKG "mpi-c") + elseif(LANG STREQUAL "CXX") + set(_MPI_PKG "mpi-cxx") + elseif(LANG STREQUAL "Fortran") + set(_MPI_PKG "mpi-fort") + else() + set(_MPI_PKG "") + endif() + if(_MPI_PKG) + pkg_check_modules("MPI_${LANG}_PKG" "${_MPI_PKG}") + if("${MPI_${LANG}_PKG_FOUND}") + set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_${LANG}_PKG_CFLAGS} CACHE STRING "MPI ${LANG} compilation options" FORCE) + set(MPI_${LANG}_INCLUDE_PATH ${MPI_${LANG}_PKG_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} include directories" FORCE) + set(MPI_${LANG}_LINK_FLAGS ${MPI_${LANG}_PKG_LDFLAGS} CACHE STRING "MPI ${LANG} linker flags" FORCE) + set(MPI_${LANG}_LIB_NAMES ${MPI_${LANG}_PKG_LIBRARIES} CACHE STRING "MPI ${LANG} libraries to link against" FORCE) + foreach(_MPI_LIB IN LISTS MPI_${LANG}_LIB_NAMES) + if(_MPI_LIB) + get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB}" NAME_WE) + get_filename_component(_MPI_LIB_NAME "${_MPI_LIB}" NAME) + get_filename_component(_MPI_LIB_DIR "${_MPI_LIB}" DIRECTORY) + find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY + NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}" + HINTS ${_MPI_LIB_DIR} + DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" + ) + mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) + endif() + endforeach() + endif() + endif() + + if(NOT MPI_SKIP_GUESSING AND NOT "${MPI_${LANG}_PKG_FOUND}") # For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the # settings for C. An MPI distribution that is in this situation would be IBM Platform MPI. if("${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND) From 4c54b2662387a34e1dbe7f238f805ed22f0297f2 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 18 Sep 2021 00:01:14 -0400 Subject: [PATCH 1251/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3f270cae65c..bbc32b3020a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210917) +set(CMake_VERSION_PATCH 20210918) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0b4a56e64b52ac050e42192c635bd59527cd98b7 Mon Sep 17 00:00:00 2001 From: Johnny Jazeix <jazeix@gmail.com> Date: Sat, 18 Sep 2021 18:52:28 +0200 Subject: [PATCH 1252/1519] cmake: -E cat stops when an empty file is encountered Fixes: #22652 --- Source/cmcmd.cxx | 2 ++ Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 1e0f497d7c7..3e36f978594 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1068,6 +1068,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } else if (!cmSystemTools::FileExists(arg)) { cmSystemTools::Error(arg + ": no such file or directory (ignoring)"); return_value = 1; + } else if (cmSystemTools::FileLength(arg) == 0) { + // Ignore empty files, this is not an error } else { // Destroy console buffers to drop cout/cerr encoding transform. consoleBuf.reset(); diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index cea5b1b1f73..dc066f1d1f4 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -647,9 +647,10 @@ run_cmake_command(E_cat_directory file(WRITE "${out}/first_file.txt" "first file to append\n") file(WRITE "${out}/second_file.txt" "second file to append\n") +file(WRITE "${out}/empty_file.txt" "") file(WRITE "${out}/unicode_file.txt" "àéùç - 한국어") # Korean in Korean run_cmake_command(E_cat_good_cat - ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/unicode_file.txt") + ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/empty_file.txt" "${out}/unicode_file.txt") unset(out) run_cmake_command(E_cat_good_binary_cat From b07812c6de51840a0dc6d3486d4a814fa7ef37f4 Mon Sep 17 00:00:00 2001 From: Pino Toscano <toscano.pino@tiscali.it> Date: Sat, 18 Sep 2021 21:49:46 +0200 Subject: [PATCH 1253/1519] Tests: fix RunCMake.CPack_DEB.EXTRA on Debian non-Linux OSes The generated path with the packages uses $CPACK_TOPLEVEL_TAG, which by default is $CPACK_SYSTEM_NAME, thus the OS name. To make the expected stderr match also non-Linux OSes, accept any non-slash characters in place of "Linux", so it works also on other Debian OSes (e.g. Debian/Hurd). --- Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt b/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt index 37360e8f235..8b6ca94d0a3 100644 --- a/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt +++ b/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt @@ -1,6 +1,6 @@ CPack Warning: Adding file to tar: -#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/Linux/DEB/extra-0.1.1-Linux/bas +#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/[^/]+/DEB/extra-0.1.1-[^/]+/bas #missing file: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/conffiles CPack Warning: Adding file to tar: -#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/Linux/DEB/extra-0.1.1-Linux/foo +#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/[^/]+/DEB/extra-0.1.1-[^/]+/foo #missing file: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/conffiles From 96c38493849f05724ec5c2b2e0152c5c86c3b5b0 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 19 Sep 2021 00:01:37 -0400 Subject: [PATCH 1254/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bbc32b3020a..e8faa7c69a6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210918) +set(CMake_VERSION_PATCH 20210919) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 062432a6bc1f334f17200a88a04d3c8e02a4fd94 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sat, 18 Sep 2021 11:02:44 +0200 Subject: [PATCH 1255/1519] cmCurlSetCAInfo: use std::string as argument --- Source/cmCurl.cxx | 6 +++--- Source/cmCurl.h | 2 +- Source/cmFileCommand.cxx | 4 ++-- Source/cmGetPropertyCommand.cxx | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index fa001d28250..28ee24dfe99 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -31,11 +31,11 @@ } \ } while (false) -std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile) +std::string cmCurlSetCAInfo(::CURL* curl, const std::string& cafile) { std::string e; - if (cafile && *cafile) { - ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile); + if (!cafile.empty()) { + ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile.c_str()); check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); } #ifdef CMAKE_FIND_CAFILE diff --git a/Source/cmCurl.h b/Source/cmCurl.h index 9c1e33778e0..b5134f466e5 100644 --- a/Source/cmCurl.h +++ b/Source/cmCurl.h @@ -8,7 +8,7 @@ #include <cm3p/curl/curl.h> -std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr); +std::string cmCurlSetCAInfo(::CURL* curl, const std::string& cafile = {}); std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, const std::string& netrc_file); std::string cmCurlFixFileURL(std::string url); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1223d2a10b7..bdfec029979 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1986,7 +1986,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, // check to see if a CAINFO file has been specified // command arg comes first - std::string const& cainfo_err = cmCurlSetCAInfo(curl, cmToCStr(cainfo)); + std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); if (!cainfo_err.empty()) { status.SetError(cainfo_err); return false; @@ -2304,7 +2304,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, // check to see if a CAINFO file has been specified // command arg comes first - std::string const& cainfo_err = cmCurlSetCAInfo(curl, cmToCStr(cainfo)); + std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); if (!cainfo_err.empty()) { status.SetError(cainfo_err); return false; diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 4b380c05b85..c976ddae571 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGetPropertyCommand.h" +#include <cstddef> + #include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmInstalledFile.h" From dffa3f485ce5a2336a7fd06c94522e53b0cab37e Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sat, 18 Sep 2021 11:05:36 +0200 Subject: [PATCH 1256/1519] cmGlobalGenerator::PrintCompilerAdvice: use cmProp as augment --- Source/cmGlobalGenerator.cxx | 4 ++-- Source/cmGlobalGenerator.h | 2 +- Source/cmGlobalJOMMakefileGenerator.cxx | 5 +++-- Source/cmGlobalJOMMakefileGenerator.h | 2 +- Source/cmGlobalNMakeMakefileGenerator.cxx | 2 +- Source/cmGlobalNMakeMakefileGenerator.h | 2 +- Source/cmGlobalVisualStudioGenerator.h | 2 +- Source/cmGlobalXCodeGenerator.h | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index fd1a197ce38..1c3d2c2e528 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -838,7 +838,7 @@ void cmGlobalGenerator::EnableLanguage( cmSystemTools::RemoveFile(compilerLangFile); if (!this->CMakeInstance->GetIsInTryCompile()) { this->PrintCompilerAdvice(noCompiler, lang, - cmToCStr(mf->GetDefinition(compilerEnv))); + mf->GetDefinition(compilerEnv)); mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str()); fatalError = true; } @@ -922,7 +922,7 @@ void cmGlobalGenerator::EnableLanguage( void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os, std::string const& lang, - const char* envVar) const + cmProp envVar) const { // Subclasses override this method if they do not support this advice. os << "Tell CMake where to find the compiler by setting "; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 34646d9f969..49a1a26cf08 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -550,7 +550,7 @@ class cmGlobalGenerator virtual bool CheckLanguages(std::vector<std::string> const& languages, cmMakefile* mf) const; virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - const char* envVar) const; + cmProp envVar) const; virtual bool ComputeTargetDepends(); diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index fc3123a44da..0d474e50d1e 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -39,8 +39,9 @@ void cmGlobalJOMMakefileGenerator::GetDocumentation( entry.Brief = "Generates JOM makefiles."; } -void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice( - std::ostream& os, std::string const& lang, const char* envVar) const +void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os, + std::string const& lang, + cmProp envVar) const { if (lang == "CXX" || lang == "C") { /* clang-format off */ diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index 2d58f91195a..cc581df166a 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -50,5 +50,5 @@ class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3 private: void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - const char* envVar) const override; + cmProp envVar) const override; }; diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 5ca8d527f90..2bc668c3c8c 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -81,7 +81,7 @@ void cmGlobalNMakeMakefileGenerator::GetDocumentation( } void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice( - std::ostream& os, std::string const& lang, const char* envVar) const + std::ostream& os, std::string const& lang, cmProp envVar) const { if (lang == "CXX" || lang == "C") { /* clang-format off */ diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index 402b89fda9e..a48a55e95e7 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -61,5 +61,5 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 void CheckNMakeFeatures(); void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - const char* envVar) const override; + cmProp envVar) const override; }; diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 151f39f12da..57ada62dde6 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -201,7 +201,7 @@ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator private: virtual std::string GetVSMakeProgram() = 0; void PrintCompilerAdvice(std::ostream&, std::string const&, - const char*) const override + cmProp) const override { } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1e1b344c9b5..e54818eae11 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -327,7 +327,7 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator bool XcodeBuildCommandInitialized; void PrintCompilerAdvice(std::ostream&, std::string const&, - const char*) const override + cmProp) const override { } From 3a1e6f5f59a38ecbaf8f1dcc8872324a73687f02 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Sat, 18 Sep 2021 11:07:48 +0200 Subject: [PATCH 1257/1519] remove cmToCStr function --- Source/cmCPluginAPI.cxx | 6 +++--- Source/cmGeneratorTarget.cxx | 2 +- Source/cmGetPropertyCommand.cxx | 13 ++++++------- Source/cmLocalGenerator.cxx | 9 ++++----- Source/cmMakefile.cxx | 4 ++-- Source/cmProperty.h | 8 -------- 6 files changed, 16 insertions(+), 26 deletions(-) diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index e922ee587fb..e4600311764 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -140,7 +140,7 @@ const char* CCONV cmGetCurrentOutputDirectory(void* arg) const char* CCONV cmGetDefinition(void* arg, const char* def) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - return cmToCStr(mf->GetDefinition(def)); + return mf->GetDefinition(def).GetCStr(); } int CCONV cmIsOn(void* arg, const char* name) @@ -592,12 +592,12 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) { cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg); if (cmSourceFile* rsf = sf->RealSourceFile) { - return cmToCStr(rsf->GetProperty(prop)); + return rsf->GetProperty(prop).GetCStr(); } if (!strcmp(prop, "LOCATION")) { return sf->FullPath.c_str(); } - return cmToCStr(sf->Properties.GetPropertyValue(prop)); + return sf->Properties.GetPropertyValue(prop).GetCStr(); } int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 4bad7abe9f6..d52dfafa0a7 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5727,7 +5727,7 @@ const char* getTypedProperty<const char*>( cmProp value = tgt->GetProperty(prop); if (genexInterpreter == nullptr) { - return cmToCStr(value); + return value.GetCStr(); } return genexInterpreter->Evaluate(value ? *value : "", prop).c_str(); diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index c976ddae571..5f2007566f1 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -34,10 +34,6 @@ enum OutType OutSet }; -// Implementation of result storage. -bool StoreResult(OutType infoType, cmMakefile& makefile, - const std::string& variable, const char* value); - // Implementation of each property type. bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, OutType infoType, const std::string& variable, @@ -255,8 +251,10 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, namespace { +// Implementation of result storage. +template <typename ValueType> bool StoreResult(OutType infoType, cmMakefile& makefile, - const std::string& variable, const char* value) + const std::string& variable, ValueType value) { if (infoType == OutSet) { makefile.AddDefinition(variable, value ? "1" : "0"); @@ -270,10 +268,11 @@ bool StoreResult(OutType infoType, cmMakefile& makefile, } return true; } +template <> bool StoreResult(OutType infoType, cmMakefile& makefile, - const std::string& variable, cmProp value) + const std::string& variable, std::nullptr_t value) { - return StoreResult(infoType, makefile, variable, value.GetCStr()); + return StoreResult(infoType, makefile, variable, cmProp(value)); } bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4c3e8ec8f6b..e2e0d8e67bd 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -856,19 +856,18 @@ std::string cmLocalGenerator::GetIncludeFlags( std::string const& includeFlag = this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_", lang)); - const char* sep = cmToCStr( - this->Makefile->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang))); bool quotePaths = false; if (this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS")) { quotePaths = true; } + std::string sep = " "; bool repeatFlag = true; // should the include flag be repeated like ie. -IA -IB - if (!sep) { - sep = " "; - } else { + if (cmProp incSep = this->Makefile->GetDefinition( + cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang))) { // if there is a separator then the flag is not repeated but is only // given once i.e. -classpath a:b:c + sep = incSep; repeatFlag = false; } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f9b256224aa..78c7246f496 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2453,7 +2453,7 @@ const char* cmMakefile::GetSONameFlag(const std::string& language) const name += language; } name += "_FLAG"; - return cmToCStr(this->GetDefinition(name)); + return this->GetDefinition(name).GetCStr(); } bool cmMakefile::CanIWriteThisFile(std::string const& fileName) const @@ -2531,7 +2531,7 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const vv->VariableAccessed(name, def ? cmVariableWatch::VARIABLE_READ_ACCESS : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS, - cmToCStr(def), this); + def.GetCStr(), this); if (watch_function_executed) { // A callback was executed and may have caused re-allocation of the diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 4179187170e..9d83df4ee27 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -229,11 +229,3 @@ inline bool operator>=(cmProp l, std::nullptr_t) noexcept { return l.Compare(cmProp{}) >= 0; } - -/** - * Temporary wrapper - */ -inline const char* cmToCStr(cmProp p) -{ - return p.GetCStr(); -} From ed0139e60637ad3f00373ec1c7c0efbd302fc073 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 20 Sep 2021 00:02:28 -0400 Subject: [PATCH 1258/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e8faa7c69a6..8626aa5bf9c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210919) +set(CMake_VERSION_PATCH 20210920) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2266e223c56be365cadfdf9f394009c095a37c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20B=C3=B6ger?= <mail@lboeger.de> Date: Sun, 19 Sep 2021 17:15:21 +0100 Subject: [PATCH 1259/1519] macOS: Speed up rpath install name dir lookup with a cache Fixes: #20602 --- Source/cmGeneratorTarget.cxx | 15 +++++++++++++++ Source/cmGeneratorTarget.h | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 4bad7abe9f6..30c022f55fc 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2169,6 +2169,21 @@ bool cmGeneratorTarget::IsImportedSharedLibWithoutSOName( bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir( const std::string& config) const +{ + TargetPtrToBoolMap& cache = this->MacOSXRpathInstallNameDirCache[config]; + const auto lookup = cache.find(this->Target); + + if (lookup != cache.cend()) { + return lookup->second; + } + + const bool result = this->DetermineHasMacOSXRpathInstallNameDir(config); + cache[this->Target] = result; + return result; +} + +bool cmGeneratorTarget::DetermineHasMacOSXRpathInstallNameDir( + const std::string& config) const { bool install_name_is_rpath = false; bool macosx_rpath = false; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 007608552a7..85b4ea0343b 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -866,6 +866,11 @@ class cmGeneratorTarget mutable std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; + using TargetPtrToBoolMap = std::unordered_map<cmTarget*, bool>; + mutable std::unordered_map<std::string, TargetPtrToBoolMap> + MacOSXRpathInstallNameDirCache; + bool DetermineHasMacOSXRpathInstallNameDir(const std::string& config) const; + // "config/language" is the key mutable std::map<std::string, std::vector<std::string>> SystemIncludesCache; From 0d3bfda22ad3327a7921caa464741394d58f3d34 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 20 Sep 2021 11:28:01 -0400 Subject: [PATCH 1260/1519] CMake 3.20.6 --- Help/release/3.20.rst | 4 ++-- Source/CMakeVersion.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst index da27174d7bc..42e95beec4f 100644 --- a/Help/release/3.20.rst +++ b/Help/release/3.20.rst @@ -363,8 +363,8 @@ Changes made since CMake 3.20.0 include the following. The oneAPI 2021.2 Fortran compiler defines the proper identification macro and so is identified as ``IntelLLVM`` by all CMake 3.20 versions. -3.20.3, 3.20.4, 3.20.5 ----------------------- +3.20.3, 3.20.4, 3.20.5, 3.20.6 +------------------------------ These versions made no changes to documented features or interfaces. Some implementation updates were made to support ecosystem changes diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1e17de9229c..35f53f6cb1b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 20) -set(CMake_VERSION_PATCH 5) +set(CMake_VERSION_PATCH 6) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 7612abd52f192a13848a4d74191633a008892449 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 20 Sep 2021 12:43:52 -0400 Subject: [PATCH 1261/1519] CMake 3.21.3 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3ed80c3c01d..264cb9cd2ea 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 3) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 6261210a671aa20d691b816df6a2237777995b06 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 21 Sep 2021 00:01:14 -0400 Subject: [PATCH 1262/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8626aa5bf9c..caa48066ce0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210920) +set(CMake_VERSION_PATCH 20210921) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 9254e7ddf2d3be2dd97fb30ae79cf3fe1fbbda2a Mon Sep 17 00:00:00 2001 From: Rainer Keller <Rainer.Keller@qt.io> Date: Tue, 21 Sep 2021 07:41:57 +0200 Subject: [PATCH 1263/1519] IAR: Use same executable suffix as try_compile There was a mismatch in the executable suffix between the compiler detection and try_compile. This resulted in the generated executable having a different suffix than what try_compile was looking for. The IAR module is changed to use the same suffix as try_compile. Fixes: #22567 --- Modules/Compiler/IAR.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index 2200a21a760..dc48cda037b 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -41,7 +41,7 @@ include_guard() macro(__compiler_iar_ilink lang) - set(CMAKE_EXECUTABLE_SUFFIX_${lang} ".elf") + set(CMAKE_EXECUTABLE_SUFFIX ".elf") set(CMAKE_${lang}_OUTPUT_EXTENSION ".o") if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX") set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") @@ -74,7 +74,7 @@ macro(__compiler_iar_ilink lang) endmacro() macro(__compiler_iar_xlink lang) - set(CMAKE_EXECUTABLE_SUFFIX_${lang} ".bin") + set(CMAKE_EXECUTABLE_SUFFIX ".bin") if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX") set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") From 7c3684b35671f9879ecbf0bb442c7b4828cce224 Mon Sep 17 00:00:00 2001 From: Felipe Torrezan <felipe.torrezan@iar.com> Date: Tue, 21 Sep 2021 11:45:22 +0200 Subject: [PATCH 1264/1519] IAR: fix assembler detection for RISC-V --- Modules/CMakeFindBinUtils.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 27d9131c837..05d244affcc 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -117,7 +117,7 @@ elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$") endfunction() __resolve_IAR_hints("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" _CMAKE_TOOLCHAIN_LOCATION) - set(_CMAKE_IAR_ITOOLS "ARM" "RX" "RH850" "RL78" "RISCV" "STM8") + set(_CMAKE_IAR_ITOOLS "ARM" "RX" "RH850" "RL78" "RISCV" "RISC-V" "STM8") set(_CMAKE_IAR_XTOOLS "AVR" "MSP430" "V850" "8051") if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS) From b8d10c27d12bc1c43056956abfb8b341f50c1124 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Tue, 21 Sep 2021 22:22:59 +1000 Subject: [PATCH 1265/1519] Help: Restructure build type docs and clarify case sensitivity Fixes: #22591 --- Help/manual/cmake-buildsystem.7.rst | 153 +++++++++++++++----- Help/variable/CMAKE_BUILD_TYPE.rst | 37 ++--- Help/variable/CMAKE_CONFIGURATION_TYPES.rst | 18 ++- 3 files changed, 140 insertions(+), 68 deletions(-) diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 70083833d72..2f430705e4a 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -21,9 +21,9 @@ Binary Targets Executables and libraries are defined using the :command:`add_executable` and :command:`add_library` commands. The resulting binary files have -appropriate :prop_tgt:`PREFIX`, :prop_tgt:`SUFFIX` and extensions for the platform targeted. -Dependencies between binary targets are expressed using the -:command:`target_link_libraries` command: +appropriate :prop_tgt:`PREFIX`, :prop_tgt:`SUFFIX` and extensions for the +platform targeted. Dependencies between binary targets are expressed using +the :command:`target_link_libraries` command: .. code-block:: cmake @@ -530,38 +530,6 @@ the calculated "compatible" value of a property may be read with the In this case, the ``exe1`` source files will be compiled with ``-DCONTAINER_SIZE=200``. -Configuration determined build specifications may be conveniently set using -the ``CONFIG`` generator expression. - -.. code-block:: cmake - - target_compile_definitions(exe1 PRIVATE - $<$<CONFIG:Debug>:DEBUG_BUILD> - ) - -The ``CONFIG`` parameter is compared case-insensitively with the configuration -being built. In the presence of :prop_tgt:`IMPORTED` targets, the content of -:prop_tgt:`MAP_IMPORTED_CONFIG_DEBUG <MAP_IMPORTED_CONFIG_<CONFIG>>` is also -accounted for by this expression. - -Some buildsystems generated by :manual:`cmake(1)` have a predetermined -build-configuration set in the :variable:`CMAKE_BUILD_TYPE` variable. The -buildsystem for the IDEs such as Visual Studio and Xcode are generated -independent of the build-configuration, and the actual build configuration -is not known until build-time. Therefore, code such as - -.. code-block:: cmake - - string(TOLOWER ${CMAKE_BUILD_TYPE} _type) - if (_type STREQUAL debug) - target_compile_definitions(exe1 PRIVATE DEBUG_BUILD) - endif() - -may appear to work for :ref:`Makefile Generators` and :generator:`Ninja` -generators, but is not portable to IDE generators. Additionally, -the :prop_tgt:`IMPORTED` configuration-mappings are not accounted for -with code like this, so it should be avoided. - The unary ``TARGET_PROPERTY`` generator expression and the ``TARGET_POLICY`` generator expression are evaluated with the consuming target context. This means that a usage requirement specification may be evaluated differently based @@ -840,6 +808,121 @@ target at a time. The commands :command:`add_compile_definitions`, a similar function, but operate at directory scope instead of target scope for convenience. +.. _`Build Configurations`: + +Build Configurations +==================== + +Configurations determine specifications for a certain type of build, such +as ``Release`` or ``Debug``. The way this is specified depends on the type +of :manual:`generator <cmake-generators(7)>` being used. For single +configuration generators like :ref:`Makefile Generators` and +:generator:`Ninja`, the configuration is specified at configure time by the +:variable:`CMAKE_BUILD_TYPE` variable. For multi-configuration generators +like :ref:`Visual Studio <Visual Studio Generators>`, :generator:`Xcode`, and +:generator:`Ninja Multi-Config`, the configuration is chosen by the user at +build time and :variable:`CMAKE_BUILD_TYPE` is ignored. In the +multi-configuration case, the set of *available* configurations is specified +at configure time by the :variable:`CMAKE_CONFIGURATION_TYPES` variable, +but the actual configuration used cannot be known until the build stage. +This difference is often misunderstood, leading to problematic code like the +following: + +.. code-block:: cmake + + # WARNING: This is wrong for multi-config generators because they don't use + # and typically don't even set CMAKE_BUILD_TYPE + string(TOLOWER ${CMAKE_BUILD_TYPE} build_type) + if (build_type STREQUAL debug) + target_compile_definitions(exe1 PRIVATE DEBUG_BUILD) + endif() + +:manual:`Generator expressions <cmake-generator-expressions(7)>` should be +used instead to handle configuration-specific logic correctly, regardless of +the generator used. For example: + +.. code-block:: cmake + + # Works correctly for both single and multi-config generators + target_compile_definitions(exe1 PRIVATE + $<$<CONFIG:Debug>:DEBUG_BUILD> + ) + +In the presence of :prop_tgt:`IMPORTED` targets, the content of +:prop_tgt:`MAP_IMPORTED_CONFIG_DEBUG <MAP_IMPORTED_CONFIG_<CONFIG>>` is also +accounted for by the above ``$<CONFIG:Debug>`` expression. + + +Case Sensitivity +---------------- + +:variable:`CMAKE_BUILD_TYPE` and :variable:`CMAKE_CONFIGURATION_TYPES` are +just like other variables in that any string comparisons made with their +values will be case-sensitive. The ``$<CONFIG>`` generator expression also +preserves the casing of the configuration as set by the user or CMake defaults. +For example: + +.. code-block:: cmake + + # NOTE: Don't use these patterns, they are for illustration purposes only. + + set(CMAKE_BUILD_TYPE Debug) + if(CMAKE_BUILD_TYPE STREQUAL DEBUG) + # ... will never get here, "Debug" != "DEBUG" + endif() + add_custom_target(print_config ALL + # Prints "Config is Debug" in this single-config case + COMMAND ${CMAKE_COMMAND} -E echo "Config is $<CONFIG>" + VERBATIM + ) + + set(CMAKE_CONFIGURATION_TYPES Debug Release) + if(DEBUG IN_LIST CMAKE_CONFIGURATION_TYPES) + # ... will never get here, "Debug" != "DEBUG" + endif() + +In contrast, CMake treats the configuration type case-insensitively when +using it internally in places that modify behavior based on the configuration. +For example, the ``$<CONFIG:Debug>`` generator expression will evaluate to 1 +for a configuration of not only ``Debug``, but also ``DEBUG``, ``debug`` or +even ``DeBuG``. Therefore, you can specify configuration types in +:variable:`CMAKE_BUILD_TYPE` and :variable:`CMAKE_CONFIGURATION_TYPES` with +any mixture of upper and lowercase, although there are strong conventions +(see the next section). If you must test the value in string comparisons, +always convert the value to upper or lowercase first and adjust the test +accordingly. + +Default And Custom Configurations +--------------------------------- + +By default, CMake defines a number of standard configurations: + +* ``Debug`` +* ``Release`` +* ``RelWithDebInfo`` +* ``MinSizeRel`` + +In multi-config generators, the :variable:`CMAKE_CONFIGURATION_TYPES` variable +will be populated with (potentially a subset of) the above list by default, +unless overridden by the project or user. The actual configuration used is +selected by the user at build time. + +For single-config generators, the configuration is specified with the +:variable:`CMAKE_BUILD_TYPE` variable at configure time and cannot be changed +at build time. The default value will often be none of the above standard +configurations and will instead be an empty string. A common misunderstanding +is that this is the same as ``Debug``, but that is not the case. Users should +always explicitly specify the build type instead to avoid this common problem. + +The above standard configuration types provide reasonable behavior on most +platforms, but they can be extended to provide other types. Each configuration +defines a set of compiler and linker flag variables for the language in use. +These variables follow the convention :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>`, +where ``<CONFIG>`` is always the uppercase configuration name. When defining +a custom configuration type, make sure these variables are set appropriately, +typically as cache variables. + + Pseudo Targets ============== diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst index 9ad1481e4ba..bb95436ad35 100644 --- a/Help/variable/CMAKE_BUILD_TYPE.rst +++ b/Help/variable/CMAKE_BUILD_TYPE.rst @@ -1,34 +1,21 @@ CMAKE_BUILD_TYPE ---------------- -Specifies the build type on single-configuration generators. - -This statically specifies what build type (configuration) will be -built in this build tree. Possible values are empty, ``Debug``, ``Release``, -``RelWithDebInfo``, ``MinSizeRel``, ... This variable is only meaningful to -single-configuration generators (such as :ref:`Makefile Generators` and -:generator:`Ninja`) i.e. those which choose a single configuration when CMake -runs to generate a build tree as opposed to multi-configuration generators -which offer selection of the build configuration within the generated build -environment. There are many per-config properties and variables -(usually following clean ``SOME_VAR_<CONFIG>`` order conventions), such as -``CMAKE_C_FLAGS_<CONFIG>``, specified as uppercase: -``CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL|...]``. For example, -in a build tree configured to build type ``Debug``, CMake will see to -having :variable:`CMAKE_C_FLAGS_DEBUG <CMAKE_<LANG>_FLAGS_DEBUG>` settings get -added to the :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` settings. See -also :variable:`CMAKE_CONFIGURATION_TYPES`. - -Note that configuration names are case-insensitive. The value of this -variable will be the same as it is specified when invoking CMake. -For instance, if ``-DCMAKE_BUILD_TYPE=ReLeAsE`` is specified, then the -value of ``CMAKE_BUILD_TYPE`` will be ``ReLeAsE``. +Specifies the build type on single-configuration generators (e.g. +:ref:`Makefile Generators` or :generator:`Ninja`). Typical values include +``Debug``, ``Release``, ``RelWithDebInfo`` and ``MinSizeRel``, but custom +build types can also be defined. This variable is initialized by the first :command:`project` or :command:`enable_language` command called in a project when a new build tree is first created. If the :envvar:`CMAKE_BUILD_TYPE` environment variable is set, its value is used. Otherwise, a toolchain-specific -default is chosen when a language is enabled. +default is chosen when a language is enabled. The default value is often +an empty string, but this is usually not desirable and one of the other +standard build types is usually more appropriate. + +Depending on the situation, the value of this variable may be treated +case-sensitively or case-insensitively. See :ref:`Build Configurations` +for discussion of this and other related topics. -See :variable:`CMAKE_CONFIGURATION_TYPES` for specifying the configuration -with multi-config generators. +For multi-config generators, see :variable:`CMAKE_CONFIGURATION_TYPES`. diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst index 5298a725308..75ff8a12a74 100644 --- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst +++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst @@ -1,12 +1,11 @@ CMAKE_CONFIGURATION_TYPES ------------------------- -Specifies the available build types on multi-config generators. - -This specifies what build types (configurations) will be available -such as ``Debug``, ``Release``, ``RelWithDebInfo`` etc. This has reasonable -defaults on most platforms, but can be extended to provide other build -types. +Specifies the available build types (configurations) on multi-config +generators (e.g. :ref:`Visual Studio <Visual Studio Generators>`, +:generator:`Xcode`, or :generator:`Ninja Multi-Config`). Typical values +include ``Debug``, ``Release``, ``RelWithDebInfo`` and ``MinSizeRel``, +but custom build types can also be defined. This variable is initialized by the first :command:`project` or :command:`enable_language` command called in a project when a new build @@ -14,5 +13,8 @@ tree is first created. If the :envvar:`CMAKE_CONFIGURATION_TYPES` environment variable is set, its value is used. Otherwise, the default value is generator-specific. -See :variable:`CMAKE_BUILD_TYPE` for specifying the configuration with -single-config generators. +Depending on the situation, the values in this variable may be treated +case-sensitively or case-insensitively. See :ref:`Build Configurations` +for discussion of this and other related topics. + +For single-config generators, see :variable:`CMAKE_BUILD_TYPE`. From 8954f9354359c6a8a272e73961d0606c948dcc9e Mon Sep 17 00:00:00 2001 From: Felipe Torrezan <felipe.torrezan@iar.com> Date: Tue, 21 Sep 2021 14:34:16 +0200 Subject: [PATCH 1266/1519] IAR: emit fatal message for RL78 XLINK --- Modules/Compiler/IAR-C.cmake | 8 ++++++-- Modules/Compiler/IAR-CXX.cmake | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index 054ee74c173..7b2e5569512 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -28,7 +28,7 @@ endif() # Architecture specific if("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_LESS 7) - # IAR ARM 4.X uses xlink.exe, detection is not yet implemented + # IAR ARM 4.X uses xlink.exe, detection is not implemented message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") endif() __compiler_iar_ilink(C) @@ -43,8 +43,12 @@ elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850") __compiler_check_default_language_standard(C 1.10 90 1.10 99 2.10 11) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78") + if(CMAKE_C_COMPILER_VERSION VERSION_LESS 2) + # IAR RL78 1.X uses xlink.exe, detection is not implemented + message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") + endif() __compiler_iar_ilink(C) - __compiler_check_default_language_standard(C 1.10 90 1.10 99 4.10 11) + __compiler_check_default_language_standard(C 2.10 90 1.10 99 4.10 11) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV") __compiler_iar_ilink(C) diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index d93b27289f6..4909cc51540 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -37,7 +37,7 @@ endif() # Architecture specific if("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_LESS 7) - # IAR ARM 4.X uses xlink.exe, detection is not yet implemented + # IAR ARM 4.X uses xlink.exe, detection is not implemented message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") endif() __compiler_iar_ilink(CXX) @@ -52,8 +52,12 @@ elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850") __compiler_check_default_language_standard(CXX 1.10 98 2.10 14) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2) + # IAR RL78 1.X uses xlink.exe, detection is not implemented + message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") + endif() __compiler_iar_ilink(CXX) - __compiler_check_default_language_standard(CXX 1.10 98 4.10 14) + __compiler_check_default_language_standard(CXX 2.10 98 4.10 14) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV") __compiler_iar_ilink(CXX) From cc56dc7468bfee49dedbf395d6fca5c372d200fe Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 21 Sep 2021 17:12:35 +0200 Subject: [PATCH 1267/1519] Rename cmProp in cmValue --- Source/CMakeLists.txt | 3 +- Source/CPack/IFW/cmCPackIFWCommon.cxx | 2 +- Source/CPack/IFW/cmCPackIFWCommon.h | 4 +- Source/CPack/IFW/cmCPackIFWGenerator.cxx | 34 +-- Source/CPack/IFW/cmCPackIFWInstaller.cxx | 61 ++--- Source/CPack/IFW/cmCPackIFWPackage.cxx | 60 ++--- Source/CPack/IFW/cmCPackIFWRepository.cxx | 14 +- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 42 +-- Source/CPack/cmCPackArchiveGenerator.cxx | 4 +- Source/CPack/cmCPackBundleGenerator.cxx | 17 +- Source/CPack/cmCPackCygwinBinaryGenerator.cxx | 4 +- Source/CPack/cmCPackCygwinSourceGenerator.cxx | 6 +- Source/CPack/cmCPackDebGenerator.cxx | 62 ++--- Source/CPack/cmCPackDragNDropGenerator.cxx | 14 +- Source/CPack/cmCPackExternalGenerator.cxx | 18 +- Source/CPack/cmCPackFreeBSDGenerator.cxx | 2 +- Source/CPack/cmCPackGenerator.cxx | 96 +++---- Source/CPack/cmCPackGenerator.h | 12 +- Source/CPack/cmCPackNSISGenerator.cxx | 16 +- Source/CPack/cmCPackNuGetGenerator.cxx | 4 +- Source/CPack/cmCPackOSXX11Generator.cxx | 6 +- Source/CPack/cmCPackPKGGenerator.cxx | 8 +- Source/CPack/cmCPackPackageMakerGenerator.cxx | 14 +- Source/CPack/cmCPackProductBuildGenerator.cxx | 16 +- Source/CPack/cmCPackProductBuildGenerator.h | 4 +- Source/CPack/cmCPackRPMGenerator.cxx | 4 +- Source/CPack/cmCPackSTGZGenerator.cxx | 2 +- Source/CPack/cpack.cxx | 16 +- Source/CTest/cmCTestBuildCommand.cxx | 12 +- Source/CTest/cmCTestBuildHandler.cxx | 6 +- Source/CTest/cmCTestConfigureCommand.cxx | 12 +- Source/CTest/cmCTestGenericHandler.cxx | 10 +- Source/CTest/cmCTestGenericHandler.h | 12 +- Source/CTest/cmCTestHandlerCommand.cxx | 6 +- Source/CTest/cmCTestScriptHandler.cxx | 10 +- Source/CTest/cmCTestStartCommand.cxx | 12 +- Source/CTest/cmCTestSubmitCommand.cxx | 10 +- Source/CTest/cmCTestSubmitHandler.cxx | 10 +- Source/CTest/cmCTestTestCommand.cxx | 10 +- Source/CTest/cmCTestTestHandler.cxx | 10 +- Source/CTest/cmCTestTestHandler.h | 4 +- Source/CTest/cmCTestUpdateHandler.cxx | 4 +- .../cmCursesCacheEntryComposite.cxx | 6 +- Source/CursesDialog/cmCursesMainForm.cxx | 20 +- Source/QtDialog/QCMake.cxx | 16 +- Source/cmBuildCommand.cxx | 4 +- Source/cmBuildNameCommand.cxx | 4 +- Source/cmCMakePathCommand.cxx | 4 +- Source/cmCMakePolicyCommand.cxx | 2 +- Source/cmCTest.cxx | 14 +- Source/cmCacheManager.cxx | 28 +- Source/cmCacheManager.h | 24 +- Source/cmCommandArgumentParserHelper.cxx | 7 +- Source/cmCommonTargetGenerator.cxx | 14 +- Source/cmCommonTargetGenerator.h | 4 +- Source/cmComputeLinkDepends.cxx | 6 +- Source/cmComputeLinkInformation.cxx | 37 +-- Source/cmComputeLinkInformation.h | 4 +- Source/cmComputeTargetDepends.cxx | 4 +- Source/cmConditionEvaluator.cxx | 38 +-- Source/cmConditionEvaluator.h | 6 +- Source/cmCoreTryCompile.cxx | 30 +-- Source/cmCustomCommandGenerator.cxx | 4 +- Source/cmDefinitions.cxx | 6 +- Source/cmDefinitions.h | 4 +- Source/cmDepends.cxx | 4 +- Source/cmDependsC.cxx | 6 +- Source/cmDependsFortran.cxx | 4 +- Source/cmExportBuildFileGenerator.cxx | 2 +- Source/cmExportFileGenerator.cxx | 30 +-- Source/cmExportInstallFileGenerator.cxx | 2 +- Source/cmExportLibraryDependenciesCommand.cxx | 4 +- Source/cmExportTryCompileFileGenerator.cxx | 4 +- Source/cmExtraCodeBlocksGenerator.cxx | 6 +- Source/cmExtraEclipseCDT4Generator.cxx | 16 +- Source/cmExtraKateGenerator.cxx | 4 +- Source/cmExtraSublimeTextGenerator.cxx | 14 +- Source/cmFileAPICache.cxx | 4 +- Source/cmFileAPICodemodel.cxx | 18 +- Source/cmFileAPIToolchains.cxx | 4 +- Source/cmFileCommand.cxx | 10 +- Source/cmFileCopier.cxx | 4 +- Source/cmFindBase.cxx | 6 +- Source/cmFindCommon.cxx | 14 +- Source/cmFindLibraryCommand.cxx | 8 +- Source/cmFindPackageCommand.cxx | 22 +- Source/cmForEachCommand.cxx | 2 +- Source/cmGeneratorExpressionNode.cxx | 21 +- Source/cmGeneratorTarget.cxx | 251 +++++++++--------- Source/cmGeneratorTarget.h | 34 +-- Source/cmGetCMakePropertyCommand.cxx | 8 +- Source/cmGetDirectoryPropertyCommand.cxx | 6 +- Source/cmGetFilenameComponentCommand.cxx | 4 +- Source/cmGetPropertyCommand.cxx | 7 +- Source/cmGetSourceFilePropertyCommand.cxx | 4 +- Source/cmGetTargetPropertyCommand.cxx | 4 +- Source/cmGetTestPropertyCommand.cxx | 4 +- Source/cmGhsMultiTargetGenerator.cxx | 10 +- Source/cmGlobalCommonGenerator.cxx | 6 +- Source/cmGlobalGenerator.cxx | 46 ++-- Source/cmGlobalGenerator.h | 6 +- Source/cmGlobalGhsMultiGenerator.cxx | 26 +- Source/cmGlobalJOMMakefileGenerator.cxx | 2 +- Source/cmGlobalJOMMakefileGenerator.h | 2 +- Source/cmGlobalNMakeMakefileGenerator.cxx | 4 +- Source/cmGlobalNMakeMakefileGenerator.h | 2 +- Source/cmGlobalNinjaGenerator.cxx | 4 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 4 +- Source/cmGlobalVisualStudio14Generator.cxx | 2 +- Source/cmGlobalVisualStudio71Generator.cxx | 8 +- Source/cmGlobalVisualStudio71Generator.h | 2 +- Source/cmGlobalVisualStudio7Generator.cxx | 20 +- Source/cmGlobalVisualStudio7Generator.h | 4 +- Source/cmGlobalVisualStudio8Generator.cxx | 8 +- Source/cmGlobalVisualStudioGenerator.cxx | 4 +- Source/cmGlobalVisualStudioGenerator.h | 2 +- Source/cmGlobalXCodeGenerator.cxx | 58 ++-- Source/cmGlobalXCodeGenerator.h | 2 +- Source/cmGraphVizWriter.cxx | 6 +- Source/cmIncludeGuardCommand.cxx | 2 +- Source/cmInstallCommand.cxx | 4 +- Source/cmInstallTargetGenerator.cxx | 6 +- Source/cmLinkLineDeviceComputer.cxx | 4 +- Source/cmListCommand.cxx | 4 +- Source/cmLocalCommonGenerator.cxx | 4 +- Source/cmLocalGenerator.cxx | 163 ++++++------ Source/cmLocalGenerator.h | 20 +- Source/cmLocalNinjaGenerator.cxx | 8 +- Source/cmLocalUnixMakefileGenerator3.cxx | 30 +-- Source/cmLocalVisualStudio7Generator.cxx | 42 +-- Source/cmLocalVisualStudioGenerator.cxx | 3 +- Source/cmMakefile.cxx | 81 +++--- Source/cmMakefile.h | 14 +- .../cmMakefileExecutableTargetGenerator.cxx | 12 +- Source/cmMakefileLibraryTargetGenerator.cxx | 12 +- Source/cmMakefileTargetGenerator.cxx | 71 ++--- Source/cmMarkAsAdvancedCommand.cxx | 2 +- Source/cmNinjaNormalTargetGenerator.cxx | 26 +- Source/cmNinjaTargetGenerator.cxx | 54 ++-- Source/cmNinjaUtilityTargetGenerator.cxx | 4 +- Source/cmOptionCommand.cxx | 4 +- Source/cmOutputRequiredFilesCommand.cxx | 4 +- Source/cmParseArgumentsCommand.cxx | 4 +- Source/cmPolicies.cxx | 2 +- Source/cmProjectCommand.cxx | 6 +- Source/cmProperty.h | 209 --------------- Source/cmPropertyMap.cxx | 6 +- Source/cmPropertyMap.h | 8 +- Source/cmQtAutoGenGlobalInitializer.cxx | 4 +- Source/cmQtAutoGenInitializer.cxx | 12 +- Source/cmRemoveCommand.cxx | 4 +- Source/cmSearchPath.cxx | 8 +- Source/cmSeparateArgumentsCommand.cxx | 4 +- Source/cmSetCommand.cxx | 4 +- Source/cmSetPropertyCommand.cxx | 5 +- Source/cmSiteNameCommand.cxx | 6 +- Source/cmSourceFile.cxx | 29 +- Source/cmSourceFile.h | 10 +- Source/cmStandardLevelResolver.cxx | 30 +-- Source/cmStandardLevelResolver.h | 8 +- Source/cmState.cxx | 36 +-- Source/cmState.h | 19 +- Source/cmStateDirectory.cxx | 40 +-- Source/cmStateDirectory.h | 8 +- Source/cmStateSnapshot.cxx | 6 +- Source/cmStateSnapshot.h | 4 +- Source/cmStringAlgorithms.h | 36 +-- Source/cmStringCommand.cxx | 4 +- Source/cmTarget.cxx | 99 +++---- Source/cmTarget.h | 16 +- Source/cmTargetLinkLibrariesCommand.cxx | 4 +- Source/cmTargetPropCommandBase.cxx | 4 +- Source/cmTargetPropertyComputer.h | 26 +- Source/cmTest.cxx | 9 +- Source/cmTest.h | 8 +- Source/cmTestGenerator.cxx | 4 +- Source/cmTryRunCommand.cxx | 8 +- Source/cmUtilitySourceCommand.cxx | 6 +- Source/{cmProperty.cxx => cmValue.cxx} | 16 +- Source/cmValue.h | 214 +++++++++++++++ Source/cmVariableRequiresCommand.cxx | 4 +- Source/cmVariableWatchCommand.cxx | 4 +- Source/cmVisualStudio10TargetGenerator.cxx | 182 ++++++------- Source/cmXCodeScheme.cxx | 8 +- Source/cmake.cxx | 56 ++-- Source/cmake.h | 16 +- Source/cmakemain.cxx | 6 +- bootstrap | 2 +- 188 files changed, 1762 insertions(+), 1734 deletions(-) rename Source/{cmProperty.cxx => cmValue.cxx} (87%) create mode 100644 Source/cmValue.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8dc44a02c9f..c8498a991fb 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -381,7 +381,8 @@ set(SRCS cmProcessOutput.h cmProcessTools.cxx cmProcessTools.h - cmProperty.cxx + cmValue.cxx + cmValue.h cmProperty.h cmPropertyDefinition.cxx cmPropertyDefinition.h diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index c7ab99469b4..f6b8a8a5371 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -21,7 +21,7 @@ cmCPackIFWCommon::cmCPackIFWCommon() { } -cmProp cmCPackIFWCommon::GetOption(const std::string& op) const +cmValue cmCPackIFWCommon::GetOption(const std::string& op) const { return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op) : nullptr; diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h index cf243dcb6ce..f2e6b889c9a 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.h +++ b/Source/CPack/IFW/cmCPackIFWCommon.h @@ -7,7 +7,7 @@ #include <map> #include <string> -#include "cmProperty.h" +#include "cmValue.h" class cmCPackIFWGenerator; class cmXMLWriter; @@ -28,7 +28,7 @@ class cmCPackIFWCommon public: // Internal implementation - cmProp GetOption(const std::string& op) const; + cmValue GetOption(const std::string& op) const; bool IsOn(const std::string& op) const; bool IsSetToOff(const std::string& op) const; bool IsSetToEmpty(const std::string& op) const; diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 0e2aec0ab25..b375ba605ee 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -14,9 +14,9 @@ #include "cmCPackLog.h" // IWYU pragma: keep #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCPackIFWGenerator::cmCPackIFWGenerator() { @@ -274,7 +274,7 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'binarycreator' executable (needs) - cmProp BinCreatorStr = this->GetOption(BinCreatorOpt); + cmValue BinCreatorStr = this->GetOption(BinCreatorOpt); if (!BinCreatorStr || cmIsNOTFOUND(BinCreatorStr)) { this->BinCreator.clear(); } else { @@ -291,7 +291,7 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'repogen' executable (optional) - cmProp repoGen = this->GetOption(RepoGenOpt); + cmValue repoGen = this->GetOption(RepoGenOpt); if (!repoGen || cmIsNOTFOUND(repoGen)) { this->RepoGen.clear(); } else { @@ -299,7 +299,7 @@ int cmCPackIFWGenerator::InitializeInternal() } // Framework version - if (cmProp frameworkVersion = this->GetOption(FrameworkVersionOpt)) { + if (cmValue frameworkVersion = this->GetOption(FrameworkVersionOpt)) { this->FrameworkVersion = *frameworkVersion; } else { this->FrameworkVersion = "1.9.9"; @@ -313,13 +313,13 @@ int cmCPackIFWGenerator::InitializeInternal() // Additional packages dirs this->PkgsDirsVector.clear(); - if (cmProp dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { + if (cmValue dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { cmExpandList(dirs, this->PkgsDirsVector); } // Additional repositories dirs this->RepoDirsVector.clear(); - if (cmProp dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { + if (cmValue dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { cmExpandList(dirs, this->RepoDirsVector); } @@ -330,22 +330,23 @@ int cmCPackIFWGenerator::InitializeInternal() // Repository this->Repository.Generator = this; this->Repository.Name = "Unspecified"; - if (cmProp site = this->GetOption("CPACK_DOWNLOAD_SITE")) { + if (cmValue site = this->GetOption("CPACK_DOWNLOAD_SITE")) { this->Repository.Url = *site; this->Installer.RemoteRepositories.push_back(&this->Repository); } // Repositories - if (cmProp RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { + if (cmValue RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr); for (std::string const& r : RepoAllVector) { this->GetRepository(r); } } - if (cmProp ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { + if (cmValue ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { this->OnlineOnly = cmIsOn(ifwDownloadAll); - } else if (cmProp cpackDownloadAll = this->GetOption("CPACK_DOWNLOAD_ALL")) { + } else if (cmValue cpackDownloadAll = + this->GetOption("CPACK_DOWNLOAD_ALL")) { this->OnlineOnly = cmIsOn(cpackDownloadAll); } else { this->OnlineOnly = false; @@ -373,7 +374,8 @@ int cmCPackIFWGenerator::InitializeInternal() } // Output extension - if (cmProp optOutExt = this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) { + if (cmValue optOutExt = + this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) { this->OutputExtension = *optOutExt; } else if (sysName == "Darwin") { this->OutputExtension = ".dmg"; @@ -506,18 +508,18 @@ std::string cmCPackIFWGenerator::GetRootPackageName() { // Default value std::string name = "root"; - if (cmProp optIFW_PACKAGE_GROUP = + if (cmValue optIFW_PACKAGE_GROUP = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { // Configure from root group cmCPackIFWPackage package; package.Generator = this; package.ConfigureFromGroup(optIFW_PACKAGE_GROUP); name = package.Name; - } else if (cmProp optIFW_PACKAGE_NAME = + } else if (cmValue optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { // Configure from root package name name = *optIFW_PACKAGE_NAME; - } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { + } else if (cmValue optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { // Configure from package name name = *optPACKAGE_NAME; } @@ -534,7 +536,7 @@ std::string cmCPackIFWGenerator::GetGroupPackageName( if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) { return package->Name; } - cmProp option = + cmValue option = this->GetOption("CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(group->Name) + "_NAME"); name = option ? *option : group->Name; @@ -560,7 +562,7 @@ std::string cmCPackIFWGenerator::GetComponentPackageName( } std::string prefix = "CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_"; - cmProp option = this->GetOption(prefix + "NAME"); + cmValue option = this->GetOption(prefix + "NAME"); name = option ? *option : component->Name; if (component->Group) { cmCPackIFWPackage* package = this->GetGroupPackage(component->Group); diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 23b73ff163c..7ee6300b808 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -12,9 +12,9 @@ #include "cmCPackIFWRepository.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" @@ -34,19 +34,20 @@ void cmCPackIFWInstaller::printSkippedOptionWarning( void cmCPackIFWInstaller::ConfigureFromOptions() { // Name; - if (cmProp optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { + if (cmValue optIFW_PACKAGE_NAME = + this->GetOption("CPACK_IFW_PACKAGE_NAME")) { this->Name = *optIFW_PACKAGE_NAME; - } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { + } else if (cmValue optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { this->Name = *optPACKAGE_NAME; } else { this->Name = "Your package"; } // Title; - if (cmProp optIFW_PACKAGE_TITLE = + if (cmValue optIFW_PACKAGE_TITLE = this->GetOption("CPACK_IFW_PACKAGE_TITLE")) { this->Title = *optIFW_PACKAGE_TITLE; - } else if (cmProp optPACKAGE_DESCRIPTION_SUMMARY = + } else if (cmValue optPACKAGE_DESCRIPTION_SUMMARY = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { this->Title = *optPACKAGE_DESCRIPTION_SUMMARY; } else { @@ -54,28 +55,28 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Version; - if (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) { + if (cmValue option = this->GetOption("CPACK_PACKAGE_VERSION")) { this->Version = *option; } else { this->Version = "1.0.0"; } // Publisher - if (cmProp optIFW_PACKAGE_PUBLISHER = + if (cmValue optIFW_PACKAGE_PUBLISHER = this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { this->Publisher = *optIFW_PACKAGE_PUBLISHER; - } else if (cmProp optPACKAGE_VENDOR = + } else if (cmValue optPACKAGE_VENDOR = this->GetOption("CPACK_PACKAGE_VENDOR")) { this->Publisher = *optPACKAGE_VENDOR; } // ProductUrl - if (cmProp option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { + if (cmValue option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { this->ProductUrl = *option; } // ApplicationIcon - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { if (cmSystemTools::FileExists(option)) { this->InstallerApplicationIcon = *option; } else { @@ -84,7 +85,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // WindowIcon - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { if (cmSystemTools::FileExists(option)) { this->InstallerWindowIcon = *option; } else { @@ -102,7 +103,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Logo - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { if (cmSystemTools::FileExists(option)) { this->Logo = *option; } else { @@ -111,7 +112,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Watermark - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { if (cmSystemTools::FileExists(option)) { this->Watermark = *option; } else { @@ -120,7 +121,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Banner - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { if (cmSystemTools::FileExists(option)) { this->Banner = *option; } else { @@ -129,7 +130,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Background - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { if (cmSystemTools::FileExists(option)) { this->Background = *option; } else { @@ -138,7 +139,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // WizardStyle - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { // Setting the user value in any case this->WizardStyle = *option; // Check known values @@ -153,7 +154,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // StyleSheet - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) { if (cmSystemTools::FileExists(option)) { this->StyleSheet = *option; } else { @@ -162,19 +163,19 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // WizardDefaultWidth - if (cmProp option = + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { this->WizardDefaultWidth = *option; } // WizardDefaultHeight - if (cmProp option = + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { this->WizardDefaultHeight = *option; } // WizardShowPageList - if (cmProp option = + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) { if (!this->IsVersionLess("4.0")) { if (this->IsSetToOff("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) { @@ -203,12 +204,12 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // TitleColor - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { this->TitleColor = *option; } // Start menu - if (cmProp optIFW_START_MENU_DIR = + if (cmValue optIFW_START_MENU_DIR = this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) { this->StartMenuDir = *optIFW_START_MENU_DIR; } else { @@ -216,10 +217,10 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Default target directory for installation - if (cmProp optIFW_TARGET_DIRECTORY = + if (cmValue optIFW_TARGET_DIRECTORY = this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) { this->TargetDir = *optIFW_TARGET_DIRECTORY; - } else if (cmProp optPACKAGE_INSTALL_DIRECTORY = + } else if (cmValue optPACKAGE_INSTALL_DIRECTORY = this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { this->TargetDir = cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY); @@ -228,18 +229,18 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Default target directory for installation with administrator rights - if (cmProp option = this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { + if (cmValue option = this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { this->AdminTargetDir = *option; } // Maintenance tool - if (cmProp optIFW_MAINTENANCE_TOOL = + if (cmValue optIFW_MAINTENANCE_TOOL = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) { this->MaintenanceToolName = *optIFW_MAINTENANCE_TOOL; } // Maintenance tool ini file - if (cmProp optIFW_MAINTENANCE_TOOL_INI = + if (cmValue optIFW_MAINTENANCE_TOOL_INI = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) { this->MaintenanceToolIniFile = *optIFW_MAINTENANCE_TOOL_INI; } @@ -263,13 +264,13 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Control script - if (cmProp optIFW_CONTROL_SCRIPT = + if (cmValue optIFW_CONTROL_SCRIPT = this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) { this->ControlScript = *optIFW_CONTROL_SCRIPT; } // Resources - if (cmProp optIFW_PACKAGE_RESOURCES = + if (cmValue optIFW_PACKAGE_RESOURCES = this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { this->Resources.clear(); cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources); @@ -539,7 +540,7 @@ void cmCPackIFWInstaller::GeneratePackageFiles() package.Generator = this->Generator; package.Installer = this; // Check package group - if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { + if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { package.ConfigureFromGroup(option); std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION"; diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index c1e11d27c33..c2109c967e6 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -15,10 +15,10 @@ #include "cmCPackIFWInstaller.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" +#include "cmValue.h" #include "cmXMLWriter.h" //---------------------------------------------------------- CompareStruct --- @@ -125,7 +125,7 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component) if (!component) { return ""; } - cmProp option = + cmValue option = this->GetOption("CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_NAME"); return option ? *option : component->Name; @@ -160,21 +160,21 @@ int cmCPackIFWPackage::ConfigureFromOptions() this->Name = this->Generator->GetRootPackageName(); // Display name - if (cmProp option = this->GetOption("CPACK_PACKAGE_NAME")) { + if (cmValue option = this->GetOption("CPACK_PACKAGE_NAME")) { this->DisplayName[""] = *option; } else { this->DisplayName[""] = "Your package"; } // Description - if (cmProp option = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + if (cmValue option = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { this->Description[""] = *option; } else { this->Description[""] = "Your package description"; } // Version - if (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) { + if (cmValue option = this->GetOption("CPACK_PACKAGE_VERSION")) { this->Version = *option; } else { this->Version = "1.0.0"; @@ -204,9 +204,9 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) this->Description[""] = component->Description; // Version - if (cmProp optVERSION = this->GetOption(prefix + "VERSION")) { + if (cmValue optVERSION = this->GetOption(prefix + "VERSION")) { this->Version = *optVERSION; - } else if (cmProp optPACKAGE_VERSION = + } else if (cmValue optPACKAGE_VERSION = this->GetOption("CPACK_PACKAGE_VERSION")) { this->Version = *optPACKAGE_VERSION; } else { @@ -214,12 +214,12 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Script - if (cmProp option = this->GetOption(prefix + "SCRIPT")) { + if (cmValue option = this->GetOption(prefix + "SCRIPT")) { this->Script = *option; } // User interfaces - if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) { + if (cmValue option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); cmExpandList(option, this->UserInterfaces); } @@ -232,7 +232,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Licenses - if (cmProp option = this->GetOption(prefix + "LICENSES")) { + if (cmValue option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { @@ -246,7 +246,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Priority - if (cmProp option = this->GetOption(prefix + "PRIORITY")) { + if (cmValue option = this->GetOption(prefix + "PRIORITY")) { this->SortingPriority = *option; cmCPackIFWLogger( WARNING, @@ -289,9 +289,9 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) this->Description[""] = group->Description; // Version - if (cmProp optVERSION = this->GetOption(prefix + "VERSION")) { + if (cmValue optVERSION = this->GetOption(prefix + "VERSION")) { this->Version = *optVERSION; - } else if (cmProp optPACKAGE_VERSION = + } else if (cmValue optPACKAGE_VERSION = this->GetOption("CPACK_PACKAGE_VERSION")) { this->Version = *optPACKAGE_VERSION; } else { @@ -299,18 +299,18 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) } // Script - if (cmProp option = this->GetOption(prefix + "SCRIPT")) { + if (cmValue option = this->GetOption(prefix + "SCRIPT")) { this->Script = *option; } // User interfaces - if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) { + if (cmValue option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); cmExpandList(option, this->UserInterfaces); } // Licenses - if (cmProp option = this->GetOption(prefix + "LICENSES")) { + if (cmValue option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { @@ -324,7 +324,7 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) } // Priority - if (cmProp option = this->GetOption(prefix + "PRIORITY")) { + if (cmValue option = this->GetOption(prefix + "PRIORITY")) { this->SortingPriority = *option; cmCPackIFWLogger( WARNING, @@ -346,13 +346,13 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName) std::string prefix = "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_"; - if (cmProp option = this->GetOption(prefix + "DISPLAY_NAME")) { + if (cmValue option = this->GetOption(prefix + "DISPLAY_NAME")) { group.DisplayName = *option; } else { group.DisplayName = group.Name; } - if (cmProp option = this->GetOption(prefix + "DESCRIPTION")) { + if (cmValue option = this->GetOption(prefix + "DESCRIPTION")) { group.Description = *option; } group.IsBold = this->IsOn(prefix + "BOLD_TITLE"); @@ -381,7 +381,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DISPLAY_NAME"; if (this->IsSetToEmpty(option)) { this->DisplayName.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName); } @@ -389,7 +389,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DESCRIPTION"; if (this->IsSetToEmpty(option)) { this->Description.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { cmCPackIFWPackage::ExpandListArgument(value, this->Description); } @@ -397,7 +397,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "RELEASE_DATE"; if (this->IsSetToEmpty(option)) { this->ReleaseDate.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { this->ReleaseDate = *value; } @@ -405,7 +405,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "SORTING_PRIORITY"; if (this->IsSetToEmpty(option)) { this->SortingPriority.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { this->SortingPriority = *value; } @@ -413,7 +413,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "UPDATE_TEXT"; if (this->IsSetToEmpty(option)) { this->UpdateText.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { this->UpdateText = *value; } @@ -421,7 +421,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "TRANSLATIONS"; if (this->IsSetToEmpty(option)) { this->Translations.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { this->Translations.clear(); cmExpandList(value, this->Translations); } @@ -429,11 +429,11 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) // QtIFW dependencies std::vector<std::string> deps; option = prefix + "DEPENDS"; - if (cmProp value = this->GetOption(option)) { + if (cmValue value = this->GetOption(option)) { cmExpandList(value, deps); } option = prefix + "DEPENDENCIES"; - if (cmProp value = this->GetOption(option)) { + if (cmValue value = this->GetOption(option)) { cmExpandList(value, deps); } for (std::string const& d : deps) { @@ -454,7 +454,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "AUTO_DEPEND_ON"; if (this->IsSetToEmpty(option)) { this->AlienAutoDependOn.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { std::vector<std::string> depsOn = cmExpandedList(value); for (std::string const& d : depsOn) { DependenceStruct dep(d); @@ -483,7 +483,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DEFAULT"; if (this->IsSetToEmpty(option)) { this->Default.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { std::string lowerValue = cmsys::SystemTools::LowerCase(value); if (lowerValue == "true") { this->Default = "true"; @@ -510,7 +510,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "REPLACES"; if (this->IsSetToEmpty(option)) { this->Replaces.clear(); - } else if (cmProp value = this->GetOption(option)) { + } else if (cmValue value = this->GetOption(option)) { this->Replaces.clear(); cmExpandList(value, this->Replaces); } diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index cc64e936195..f25d2d28c0b 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -6,8 +6,8 @@ #include "cmCPackIFWGenerator.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" @@ -56,21 +56,21 @@ bool cmCPackIFWRepository::ConfigureFromOptions() } // Url - if (cmProp url = this->GetOption(prefix + "URL")) { + if (cmValue url = this->GetOption(prefix + "URL")) { this->Url = *url; } else { this->Url.clear(); } // Old url - if (cmProp oldUrl = this->GetOption(prefix + "OLD_URL")) { + if (cmValue oldUrl = this->GetOption(prefix + "OLD_URL")) { this->OldUrl = *oldUrl; } else { this->OldUrl.clear(); } // New url - if (cmProp newUrl = this->GetOption(prefix + "NEW_URL")) { + if (cmValue newUrl = this->GetOption(prefix + "NEW_URL")) { this->NewUrl = *newUrl; } else { this->NewUrl.clear(); @@ -84,21 +84,21 @@ bool cmCPackIFWRepository::ConfigureFromOptions() } // Username - if (cmProp username = this->GetOption(prefix + "USERNAME")) { + if (cmValue username = this->GetOption(prefix + "USERNAME")) { this->Username = *username; } else { this->Username.clear(); } // Password - if (cmProp password = this->GetOption(prefix + "PASSWORD")) { + if (cmValue password = this->GetOption(prefix + "PASSWORD")) { this->Password = *password; } else { this->Password.clear(); } // DisplayName - if (cmProp displayName = this->GetOption(prefix + "DISPLAY_NAME")) { + if (cmValue displayName = this->GetOption(prefix + "DISPLAY_NAME")) { this->DisplayName = *displayName; } else { this->DisplayName.clear(); diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index e127c445528..d03239b521f 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -18,10 +18,10 @@ #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUuid.h" +#include "cmValue.h" #include "cmWIXDirectoriesSourceWriter.h" #include "cmWIXFeaturesSourceWriter.h" #include "cmWIXFilesSourceWriter.h" @@ -126,7 +126,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles) command << " -ext " << QuotePath(ext); } - cmProp const cultures = GetOption("CPACK_WIX_CULTURES"); + cmValue const cultures = GetOption("CPACK_WIX_CULTURES"); if (cultures) { command << " -cultures:" << cultures; } @@ -211,7 +211,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() SetOption("CPACK_WIX_UI_REF", defaultRef); } - cmProp packageContact = GetOption("CPACK_PACKAGE_CONTACT"); + cmValue packageContact = GetOption("CPACK_PACKAGE_CONTACT"); if (packageContact && !GetOption("CPACK_WIX_PROPERTY_ARPCONTACT")) { SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact); } @@ -224,7 +224,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces); - cmProp patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); + cmValue patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if (patchFilePath) { std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath); @@ -296,7 +296,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl() void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() { - cmProp cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); + cmValue cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); if (!cpackWixExtraSources) return; @@ -305,7 +305,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) { - cmProp cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); + cmValue cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); if (!cpackWixExtraObjects) return; @@ -406,7 +406,7 @@ void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source, std::string const& name, DefinitionType type) { - cmProp value = GetOption(name); + cmValue value = GetOption(name); if (value) { if (type == DefinitionType::PATH) { AddDefinition(source, name, CMakeToWixPath(value)); @@ -486,17 +486,17 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } std::string featureTitle = cpackPackageName; - if (cmProp title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) { + if (cmValue title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) { featureTitle = *title; } featureDefinitions.AddAttribute("Title", featureTitle); - if (cmProp desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) { + if (cmValue desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) { featureDefinitions.AddAttribute("Description", desc); } featureDefinitions.AddAttribute("Level", "1"); this->Patch->ApplyFragment("#PRODUCTFEATURE", featureDefinitions); - cmProp package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); + cmValue package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); if (package) { featureDefinitions.CreateCMakePackageRegistryEntry( package, GetOption("CPACK_WIX_UPGRADE_GUID")); @@ -541,7 +541,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } bool emitUninstallShortcut = true; - cmProp cpackWixProgramMenuFolder = + cmValue cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") { emitUninstallShortcut = false; @@ -595,7 +595,7 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const std::string result = "ProgramFiles<64>Folder"; - cmProp rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); + cmValue rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); if (rootFolderId) { result = *rootFolderId; } @@ -612,7 +612,7 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() { std::string wixTemplate = FindTemplate("WIX.template.in"); - if (cmProp wixtpl = GetOption("CPACK_WIX_TEMPLATE")) { + if (cmValue wixtpl = GetOption("CPACK_WIX_TEMPLATE")) { wixTemplate = *wixtpl; } @@ -669,7 +669,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( featureDefinitions.AddAttribute("Id", featureId); std::vector<std::string> cpackPackageExecutablesList; - cmProp cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); + cmValue cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList); if (cpackPackageExecutablesList.size() % 2 != 0) { @@ -683,7 +683,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( } std::vector<std::string> cpackPackageDesktopLinksList; - cmProp cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS"); + cmValue cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS"); if (cpackPackageDesktopLinks) { cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList); } @@ -742,7 +742,7 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType( std::string directoryId; switch (type) { case cmWIXShortcuts::START_MENU: { - cmProp cpackWixProgramMenuFolder = + cmValue cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") { directoryId = "ProgramMenuFolder"; @@ -803,7 +803,7 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType( fileDefinitions); if (type == cmWIXShortcuts::START_MENU) { - cmProp cpackWixProgramMenuFolder = + cmValue cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder != ".") { fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" + @@ -970,7 +970,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions( bool cmCPackWIXGenerator::RequireOption(std::string const& name, std::string& value) const { - cmProp tmp = GetOption(name); + cmValue tmp = GetOption(name); if (tmp) { value = *tmp; @@ -1143,7 +1143,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c) void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, extension_set_t& extensions) { - cmProp variableContent = GetOption(variableName); + cmValue variableContent = GetOption(variableName); if (!variableContent) return; @@ -1154,7 +1154,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, xmlns_map_t& namespaces) { - cmProp variableContent = GetOption(variableName); + cmValue variableContent = GetOption(variableName); if (!variableContent) { return; } @@ -1183,7 +1183,7 @@ void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, std::ostream& stream) { - cmProp variableContent = GetOption(variableName); + cmValue variableContent = GetOption(variableName); if (!variableContent) return; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 4f90ba28c9c..56e8463c1c0 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -12,9 +12,9 @@ #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmWorkingDirectory.h" cmCPackGenerator* cmCPackArchiveGenerator::Create7ZGenerator() @@ -118,7 +118,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/'); } - cmProp installPrefix = this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + cmValue installPrefix = this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); if (installPrefix && installPrefix->size() > 1 && (*installPrefix)[0] == '/') { // add to file prefix and remove the leading '/' diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index d93ddb84060..b3d425aa51c 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -6,9 +6,9 @@ #include <vector> #include "cmCPackLog.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCPackBundleGenerator::cmCPackBundleGenerator() = default; @@ -16,7 +16,7 @@ cmCPackBundleGenerator::~cmCPackBundleGenerator() = default; int cmCPackBundleGenerator::InitializeInternal() { - cmProp name = this->GetOption("CPACK_BUNDLE_NAME"); + cmValue name = this->GetOption("CPACK_BUNDLE_NAME"); if (!name) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set to use the Bundle generator." @@ -52,7 +52,7 @@ int cmCPackBundleGenerator::ConstructBundle() { // Get required arguments ... - cmProp cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME"); + cmValue cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME"); if (cpack_bundle_name->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set." << std::endl); @@ -60,7 +60,7 @@ int cmCPackBundleGenerator::ConstructBundle() return 0; } - cmProp cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST"); + cmValue cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST"); if (cpack_bundle_plist->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set." << std::endl); @@ -68,7 +68,7 @@ int cmCPackBundleGenerator::ConstructBundle() return 0; } - cmProp cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON"); + cmValue cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON"); if (cpack_bundle_icon->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set." << std::endl); @@ -77,7 +77,7 @@ int cmCPackBundleGenerator::ConstructBundle() } // Get optional arguments ... - cmProp cpack_bundle_startup_command = + cmValue cpack_bundle_startup_command = this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND"); // The staging directory contains everything that will end-up inside the @@ -173,7 +173,8 @@ bool cmCPackBundleGenerator::SupportsComponentInstallation() const int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) { - cmProp cpack_apple_cert_app = this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP"); + cmValue cpack_apple_cert_app = + this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP"); // codesign the application. if (!cpack_apple_cert_app->empty()) { @@ -188,7 +189,7 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) ? *this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") : "--deep -f"; - cmProp sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES"); + cmValue sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES"); std::vector<std::string> relFiles = cmExpandedList(sign_files); diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx index 1de5e1c07f6..484db003801 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx @@ -8,8 +8,8 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator() @@ -60,7 +60,7 @@ int cmCPackCygwinBinaryGenerator::PackageFiles() const char* cmCPackCygwinBinaryGenerator::GetOutputExtension() { this->OutputExtension = "-"; - cmProp patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmValue patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patchNumber) { this->OutputExtension += "1"; cmCPackLogger(cmCPackLog::LOG_WARNING, diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx index 684a98845cc..59df380c5f0 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx +++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx @@ -8,8 +8,8 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" // Includes needed for implementation of RenameFile. This is not in @@ -95,7 +95,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles() } std::string outerTarFile = cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-'); - cmProp patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmValue patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER" @@ -147,7 +147,7 @@ const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix() const char* cmCPackCygwinSourceGenerator::GetOutputExtension() { this->OutputExtension = "-"; - cmProp patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmValue patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER" diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 91b6c12efc8..06869578b51 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -20,9 +20,9 @@ #include "cmCPackLog.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { @@ -31,12 +31,12 @@ class DebGenerator public: DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir, std::string topLevelDir, std::string temporaryDir, - cmProp debianCompressionType, cmProp numThreads, - cmProp debianArchiveType, + cmValue debianCompressionType, 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, - cmProp controlExtra, bool permissionStrctPolicy, + cmValue controlExtra, bool permissionStrctPolicy, std::vector<std::string> packageFiles); bool generate() const; @@ -64,22 +64,20 @@ class DebGenerator const std::string PostInst; const bool GenPostRm; const std::string PostRm; - cmProp ControlExtra; + cmValue ControlExtra; const bool PermissionStrictPolicy; const std::vector<std::string> PackageFiles; cmArchiveWrite::Compress TarCompressionType; }; -DebGenerator::DebGenerator(cmCPackLog* logger, std::string outputName, - std::string workDir, std::string topLevelDir, - std::string temporaryDir, cmProp debCompressionType, - cmProp numThreads, cmProp debianArchiveType, - std::map<std::string, std::string> controlValues, - bool genShLibs, std::string shLibsFilename, - bool genPostInst, std::string postInst, - bool genPostRm, std::string postRm, - cmProp controlExtra, bool permissionStrictPolicy, - std::vector<std::string> packageFiles) +DebGenerator::DebGenerator( + cmCPackLog* logger, std::string outputName, std::string workDir, + std::string topLevelDir, std::string temporaryDir, + cmValue debCompressionType, 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::vector<std::string> packageFiles) : Logger(logger) , OutputName(std::move(outputName)) , WorkDir(std::move(workDir)) @@ -703,7 +701,7 @@ bool cmCPackDebGenerator::createDebPackages() bool retval = make_package(this->GetOption("GEN_WDIR"), "GEN_CPACK_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDeb); - cmProp dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); + cmValue dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && dbgsymdir_path) { retval = make_package(dbgsymdir_path, "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDbgsymDDeb) && @@ -732,54 +730,56 @@ bool cmCPackDebGenerator::createDeb() controlValues["Description"] = *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); - cmProp debian_pkg_source = + cmValue debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); if (cmNonempty(debian_pkg_source)) { controlValues["Source"] = *debian_pkg_source; } - cmProp debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); + cmValue debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); if (cmNonempty(debian_pkg_dep)) { controlValues["Depends"] = *debian_pkg_dep; } - cmProp debian_pkg_rec = + cmValue debian_pkg_rec = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS"); if (cmNonempty(debian_pkg_rec)) { controlValues["Recommends"] = *debian_pkg_rec; } - cmProp debian_pkg_sug = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); + cmValue debian_pkg_sug = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); if (cmNonempty(debian_pkg_sug)) { controlValues["Suggests"] = *debian_pkg_sug; } - cmProp debian_pkg_url = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); + cmValue debian_pkg_url = + this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); if (cmNonempty(debian_pkg_url)) { controlValues["Homepage"] = *debian_pkg_url; } - cmProp debian_pkg_predep = + cmValue debian_pkg_predep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS"); if (cmNonempty(debian_pkg_predep)) { controlValues["Pre-Depends"] = *debian_pkg_predep; } - cmProp debian_pkg_enhances = + cmValue debian_pkg_enhances = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES"); if (cmNonempty(debian_pkg_enhances)) { controlValues["Enhances"] = *debian_pkg_enhances; } - cmProp debian_pkg_breaks = + cmValue debian_pkg_breaks = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS"); if (cmNonempty(debian_pkg_breaks)) { controlValues["Breaks"] = *debian_pkg_breaks; } - cmProp debian_pkg_conflicts = + cmValue debian_pkg_conflicts = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS"); if (cmNonempty(debian_pkg_conflicts)) { controlValues["Conflicts"] = *debian_pkg_conflicts; } - cmProp debian_pkg_provides = + cmValue debian_pkg_provides = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES"); if (cmNonempty(debian_pkg_provides)) { controlValues["Provides"] = *debian_pkg_provides; } - cmProp debian_pkg_replaces = + cmValue debian_pkg_replaces = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES"); if (cmNonempty(debian_pkg_replaces)) { controlValues["Replaces"] = *debian_pkg_replaces; @@ -788,7 +788,7 @@ bool cmCPackDebGenerator::createDeb() const std::string strGenWDIR(this->GetOption("GEN_WDIR")); const std::string shlibsfilename = strGenWDIR + "/shlibs"; - cmProp debian_pkg_shlibs = + cmValue debian_pkg_shlibs = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS"); const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") && cmNonempty(debian_pkg_shlibs); @@ -845,7 +845,7 @@ bool cmCPackDebGenerator::createDbgsymDDeb() // debian policy enforce lower case for package name std::string packageNameLower = cmsys::SystemTools::LowerCase( this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); - cmProp debian_pkg_version = + cmValue debian_pkg_version = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); controlValues["Package"] = packageNameLower + "-dbgsym"; @@ -864,12 +864,12 @@ bool cmCPackDebGenerator::createDbgsymDDeb() controlValues["Description"] = std::string("debug symbols for ") + packageNameLower; - cmProp debian_pkg_source = + cmValue debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); if (cmNonempty(debian_pkg_source)) { controlValues["Source"] = *debian_pkg_source; } - cmProp debian_build_ids = this->GetOption("GEN_BUILD_IDS"); + cmValue debian_build_ids = this->GetOption("GEN_BUILD_IDS"); if (cmNonempty(debian_build_ids)) { controlValues["Build-Ids"] = *debian_build_ids; } diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 36ab4144e5e..9385a5a3e7a 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -18,9 +18,9 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" #ifdef HAVE_CoreServices @@ -261,7 +261,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, const std::string& output_file) { // Get optional arguments ... - cmProp cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON"); + cmValue cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON"); const std::string cpack_dmg_volume_name = this->GetOption("CPACK_DMG_VOLUME_NAME") @@ -281,14 +281,14 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::string cpack_license_file = *this->GetOption("CPACK_RESOURCE_FILE_LICENSE"); - cmProp cpack_dmg_background_image = + cmValue cpack_dmg_background_image = this->GetOption("CPACK_DMG_BACKGROUND_IMAGE"); - cmProp cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE"); + cmValue cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE"); - cmProp cpack_dmg_languages = this->GetOption("CPACK_DMG_SLA_LANGUAGES"); + cmValue cpack_dmg_languages = this->GetOption("CPACK_DMG_SLA_LANGUAGES"); - cmProp cpack_dmg_ds_store_setup_script = + cmValue cpack_dmg_ds_store_setup_script = this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT"); const bool cpack_dmg_disable_applications_symlink = @@ -706,7 +706,7 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( // the current COMPONENT belongs to. std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; - cmProp _groupName = this->GetOption(groupVar); + cmValue _groupName = this->GetOption(groupVar); if (_groupName) { std::string groupName = _groupName; diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 9cdaafe8749..157ee1de225 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -16,9 +16,9 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" int cmCPackExternalGenerator::InitializeInternal() { @@ -61,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - cmProp packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); + cmValue packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); if (cmNonempty(packageScript)) { if (!cmSystemTools::FileIsFullPath(packageScript)) { cmCPackLogger( @@ -77,7 +77,7 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - cmProp builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); + cmValue builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); if (builtPackages) { cmExpandList(builtPackages, this->packageFileNames, false); } @@ -181,34 +181,34 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( return 0; } - cmProp packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); + cmValue packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); if (packageName) { root["packageName"] = *packageName; } - cmProp packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION"); + cmValue packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION"); if (packageVersion) { root["packageVersion"] = *packageVersion; } - cmProp packageDescriptionFile = + cmValue packageDescriptionFile = this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); if (packageDescriptionFile) { root["packageDescriptionFile"] = *packageDescriptionFile; } - cmProp packageDescriptionSummary = + cmValue packageDescriptionSummary = this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY"); if (packageDescriptionSummary) { root["packageDescriptionSummary"] = *packageDescriptionSummary; } - cmProp buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); + cmValue buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); if (buildConfigCstr) { root["buildConfig"] = *buildConfigCstr; } - cmProp defaultDirectoryPermissions = + cmValue defaultDirectoryPermissions = this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(defaultDirectoryPermissions)) { root["defaultDirectoryPermissions"] = *defaultDirectoryPermissions; diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 39ec3c83ed2..30b6b0d7fbc 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -203,7 +203,7 @@ cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s, // basically a wrapper that handles the NULL-ptr return from GetOption(). std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name) { - cmProp pv = this->GetOption(var_name); + cmValue pv = this->GetOption(var_name); if (!pv) { return std::string(); } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 43efcf4d27a..2f700b40127 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -20,11 +20,11 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmWorkingDirectory.h" #include "cmXMLSafe.h" @@ -78,14 +78,14 @@ int cmCPackGenerator::PrepareNames() std::string tempDirectory = cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/"); - cmProp toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); + cmValue toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); if (toplevelTag) { tempDirectory += *toplevelTag; tempDirectory += "/"; } tempDirectory += *this->GetOption("CPACK_GENERATOR"); std::string topDirectory = tempDirectory; - cmProp pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME"); + cmValue pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME"); if (!pfname) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_FILE_NAME not specified" << std::endl); @@ -99,7 +99,7 @@ int cmCPackGenerator::PrepareNames() return 0; } outName += this->GetOutputExtension(); - cmProp pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY"); + cmValue pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY"); if (!pdir) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_DIRECTORY not specified" << std::endl); @@ -123,7 +123,7 @@ int cmCPackGenerator::PrepareNames() cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl); - cmProp descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); + cmValue descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName << std::endl); @@ -149,7 +149,7 @@ int cmCPackGenerator::PrepareNames() ostr << cmXMLSafe(line) << std::endl; } this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str()); - cmProp defFileName = + cmValue defFileName = this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE"); if (defFileName && (defFileName == descFileName)) { this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON"); @@ -163,7 +163,7 @@ int cmCPackGenerator::PrepareNames() << std::endl); return 0; } - cmProp algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); + cmValue algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); if (algoSignature) { if (!cmCryptoHash::New(*algoSignature)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -213,7 +213,7 @@ int cmCPackGenerator::InstallProject() // prepare default created directory permissions mode_t default_dir_mode_v = 0; mode_t* default_dir_mode = nullptr; - cmProp default_dir_install_permissions = + cmValue default_dir_install_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_install_permissions)) { std::vector<std::string> items = @@ -264,7 +264,7 @@ int cmCPackGenerator::InstallProject() } // Run pre-build actions - cmProp preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); + cmValue preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); if (preBuildScripts) { const auto scripts = cmExpandedList(preBuildScripts, false); for (const auto& script : scripts) { @@ -291,7 +291,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( bool setDestDir, const std::string& tempInstallDirectory) { (void)setDestDir; - cmProp installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); + cmValue installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); if (cmNonempty(installCommands)) { std::string tempInstallDirectoryEnv = cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory); @@ -331,7 +331,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( (void)setDestDir; (void)tempInstallDirectory; std::vector<cmsys::RegularExpression> ignoreFilesRegex; - cmProp cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); + cmValue cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); if (cpackIgnoreFiles) { std::vector<std::string> ignoreFilesRegexString = cmExpandedList(cpackIgnoreFiles); @@ -341,7 +341,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( ignoreFilesRegex.emplace_back(ifr); } } - cmProp installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); + cmValue installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); if (cmNonempty(installDirectories)) { std::vector<std::string> installDirectoriesVector = cmExpandedList(installDirectories); @@ -469,9 +469,9 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( int cmCPackGenerator::InstallProjectViaInstallScript( bool setDestDir, const std::string& tempInstallDirectory) { - cmProp cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); + cmValue cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); { - cmProp const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); + cmValue const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); if (cmakeScript && cmakeScripts) { cmCPackLogger( cmCPackLog::LOG_WARNING, @@ -537,8 +537,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( bool setDestDir, const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode) { - cmProp cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); - cmProp cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); + cmValue cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); + cmValue cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); std::string absoluteDestFiles; if (cmNonempty(cmakeProjects)) { if (!cmakeGenerator) { @@ -592,7 +592,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // Determine the installation types for this project (if provided). std::string installTypesVar = "CPACK_" + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; - cmProp installTypes = this->GetOption(installTypesVar); + cmValue installTypes = this->GetOption(installTypesVar); if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); @@ -605,7 +605,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // Determine the set of components that will be used in this project std::string componentsVar = "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); - cmProp components = this->GetOption(componentsVar); + cmValue components = this->GetOption(componentsVar); if (cmNonempty(components)) { cmExpandList(components, componentsVector); for (std::string const& comp : componentsVector) { @@ -762,7 +762,7 @@ int cmCPackGenerator::InstallCMakeProject( } } - cmProp default_dir_inst_permissions = + cmValue default_dir_inst_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_inst_permissions)) { mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", @@ -915,7 +915,7 @@ int cmCPackGenerator::InstallCMakeProject( // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES // to CPack (may be used by generators like CPack RPM or DEB) // in order to transparently handle ABSOLUTE PATH - if (cmProp def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { + if (cmValue def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", *def); } @@ -949,7 +949,7 @@ int cmCPackGenerator::InstallCMakeProject( } } - if (cmProp d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) { + if (cmValue d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) { if (!absoluteDestFiles.empty()) { absoluteDestFiles += ";"; } @@ -993,7 +993,7 @@ template <typename ValueType> void cmCPackGenerator::StoreOptionIfNotSet(const std::string& op, ValueType value) { - cmProp def = this->MakefileMap->GetDefinition(op); + cmValue def = this->MakefileMap->GetDefinition(op); if (cmNonempty(def)) { return; } @@ -1005,7 +1005,7 @@ void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, { this->StoreOptionIfNotSet(op, value); } -void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, cmProp value) +void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, cmValue value) { this->StoreOptionIfNotSet(op, value); } @@ -1027,7 +1027,7 @@ void cmCPackGenerator::SetOption(const std::string& op, const char* value) { this->StoreOption(op, value); } -void cmCPackGenerator::SetOption(const std::string& op, cmProp value) +void cmCPackGenerator::SetOption(const std::string& op, cmValue value) { this->StoreOption(op, value); } @@ -1049,7 +1049,7 @@ int cmCPackGenerator::DoPackage() } if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) { - cmProp toplevelDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + cmValue toplevelDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); if (cmSystemTools::FileExists(toplevelDirectory)) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove toplevel directory: " << toplevelDirectory @@ -1070,9 +1070,9 @@ int cmCPackGenerator::DoPackage() } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl); - cmProp tempPackageFileName = + cmValue tempPackageFileName = this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME"); - cmProp tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); + cmValue tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); cmsys::Glob gl; @@ -1124,7 +1124,7 @@ int cmCPackGenerator::DoPackage() } } // Run post-build actions - cmProp postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); + cmValue postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); if (postBuildScripts) { this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES", cmJoin(this->packageFileNames, ";")); @@ -1144,7 +1144,7 @@ int cmCPackGenerator::DoPackage() } /* Prepare checksum algorithm*/ - cmProp algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); + cmValue algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(*algo); /* @@ -1160,7 +1160,7 @@ int cmCPackGenerator::DoPackage() for (std::string const& pkgFileName : this->packageFileNames) { std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX")); std::string filename(cmSystemTools::GetFilenameName(pkgFileName)); - tempPackageFileName = cmProp(pkgFileName); + tempPackageFileName = cmValue(pkgFileName); tmpPF += "/" + filename; const char* packageFileName = tmpPF.c_str(); cmCPackLogger(cmCPackLog::LOG_DEBUG, @@ -1209,7 +1209,7 @@ int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf) // set the running generator name this->SetOption("CPACK_GENERATOR", this->Name); // Load the project specific config file - cmProp config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); + cmValue config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); if (config) { mf->ReadListFile(config); } @@ -1243,7 +1243,7 @@ bool cmCPackGenerator::IsOn(const std::string& name) const bool cmCPackGenerator::IsSetToOff(const std::string& op) const { - cmProp ret = this->MakefileMap->GetDefinition(op); + cmValue ret = this->MakefileMap->GetDefinition(op); if (cmNonempty(ret)) { return cmIsOff(*ret); } @@ -1252,16 +1252,16 @@ bool cmCPackGenerator::IsSetToOff(const std::string& op) const bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const { - cmProp ret = this->MakefileMap->GetDefinition(op); + cmValue ret = this->MakefileMap->GetDefinition(op); if (ret) { return ret->empty(); } return false; } -cmProp cmCPackGenerator::GetOption(const std::string& op) const +cmValue cmCPackGenerator::GetOption(const std::string& op) const { - cmProp ret = this->MakefileMap->GetDefinition(op); + cmValue ret = this->MakefileMap->GetDefinition(op); if (!ret) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Warning, GetOption return NULL for: " << op << std::endl); @@ -1481,7 +1481,7 @@ std::string cmCPackGenerator::GetComponentPackageFileName( if (isGroupName) { std::string groupDispVar = "CPACK_COMPONENT_GROUP_" + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME"; - cmProp groupDispName = this->GetOption(groupDispVar); + cmValue groupDispName = this->GetOption(groupDispVar); if (groupDispName) { suffix = "-" + *groupDispName; } @@ -1490,7 +1490,7 @@ std::string cmCPackGenerator::GetComponentPackageFileName( else { std::string dispVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME"; - cmProp dispName = this->GetOption(dispVar); + cmValue dispName = this->GetOption(dispVar); if (dispName) { suffix = "-" + *dispName; } @@ -1535,7 +1535,7 @@ cmCPackInstallationType* cmCPackGenerator::GetInstallationType( "CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name); installType->Name = name; - cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmValue displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { installType->DisplayName = *displayName; } else { @@ -1557,7 +1557,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( std::string macroPrefix = "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name); component->Name = name; - cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmValue displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { component->DisplayName = *displayName; } else { @@ -1569,17 +1569,17 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") || cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); - cmProp archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); + cmValue archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); if (cmNonempty(archiveFile)) { component->ArchiveFile = *archiveFile; } - cmProp plist = this->GetOption(macroPrefix + "_PLIST"); + cmValue plist = this->GetOption(macroPrefix + "_PLIST"); if (cmNonempty(plist)) { component->Plist = *plist; } - cmProp groupName = this->GetOption(macroPrefix + "_GROUP"); + cmValue groupName = this->GetOption(macroPrefix + "_GROUP"); if (cmNonempty(groupName)) { component->Group = this->GetComponentGroup(projectName, groupName); component->Group->Components.push_back(component); @@ -1587,13 +1587,13 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->Group = nullptr; } - cmProp description = this->GetOption(macroPrefix + "_DESCRIPTION"); + cmValue description = this->GetOption(macroPrefix + "_DESCRIPTION"); if (cmNonempty(description)) { component->Description = *description; } // Determine the installation types. - cmProp installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); + cmValue installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); @@ -1604,7 +1604,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( } // Determine the component dependencies. - cmProp depends = this->GetOption(macroPrefix + "_DEPENDS"); + cmValue depends = this->GetOption(macroPrefix + "_DEPENDS"); if (cmNonempty(depends)) { std::vector<std::string> dependsVector = cmExpandedList(depends); for (std::string const& depend : dependsVector) { @@ -1628,20 +1628,20 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup( if (!hasGroup) { // Define the group group->Name = name; - cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmValue displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { group->DisplayName = *displayName; } else { group->DisplayName = group->Name; } - cmProp description = this->GetOption(macroPrefix + "_DESCRIPTION"); + cmValue description = this->GetOption(macroPrefix + "_DESCRIPTION"); if (cmNonempty(description)) { group->Description = *description; } group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE"); group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED"); - cmProp parentGroupName = this->GetOption(macroPrefix + "_PARENT_GROUP"); + cmValue parentGroupName = this->GetOption(macroPrefix + "_PARENT_GROUP"); if (cmNonempty(parentGroupName)) { group->ParentGroup = this->GetComponentGroup(projectName, parentGroupName); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index e63a830a937..65156ab253d 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -12,8 +12,8 @@ #include "cm_sys_stat.h" #include "cmCPackComponentGroup.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" class cmCPackLog; class cmGlobalGenerator; @@ -87,16 +87,16 @@ class cmCPackGenerator void SetOption(const std::string& op, const char* value); void SetOption(const std::string& op, const std::string& value) { - this->SetOption(op, cmProp(value)); + this->SetOption(op, cmValue(value)); } - void SetOption(const std::string& op, cmProp value); + void SetOption(const std::string& op, cmValue value); void SetOptionIfNotSet(const std::string& op, const char* value); void SetOptionIfNotSet(const std::string& op, const std::string& value) { - this->SetOptionIfNotSet(op, cmProp(value)); + this->SetOptionIfNotSet(op, cmValue(value)); } - void SetOptionIfNotSet(const std::string& op, cmProp value); - cmProp GetOption(const std::string& op) const; + void SetOptionIfNotSet(const std::string& op, cmValue value); + cmValue GetOption(const std::string& op) const; std::vector<std::string> GetOptions() const; bool IsSet(const std::string& name) const; bool IsOn(const std::string& name) const; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index f151ff1216a..ecc5e084996 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -19,9 +19,9 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" /* NSIS uses different command line syntax on Windows and others */ #ifdef _WIN32 @@ -476,7 +476,7 @@ int cmCPackNSISGenerator::InitializeInternal() cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs"); if (!resS || retVal || (!versionRex.find(output) && !versionRexCVS.find(output))) { - cmProp topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + cmValue topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string tmpFile = cmStrCat(topDir ? *topDir : ".", "/NSISOutput.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << nsisCmd << std::endl @@ -509,11 +509,11 @@ int cmCPackNSISGenerator::InitializeInternal() } this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath); this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin"); - cmProp cpackPackageExecutables = + cmValue cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); - cmProp cpackPackageDeskTopLinks = + cmValue cpackPackageDeskTopLinks = this->GetOption("CPACK_CREATE_DESKTOP_LINKS"); - cmProp cpackNsisExecutablesDirectory = + cmValue cpackNsisExecutablesDirectory = this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"); std::vector<std::string> cpackPackageDesktopLinksVector; if (cpackPackageDeskTopLinks) { @@ -586,7 +586,7 @@ int cmCPackNSISGenerator::InitializeInternal() void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, std::ostream& deleteStr) { - cmProp cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS"); + cmValue cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS"); if (!cpackMenuLinks) { return; } @@ -725,7 +725,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( } // Create the directory for the upload area - cmProp userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); + cmValue userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; if (cmNonempty(userUploadDirectory)) { uploadDirectory = *userUploadDirectory; @@ -964,7 +964,7 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription( std::string cmCPackNSISGenerator::CustomComponentInstallDirectory( cm::string_view componentName) { - cmProp outputDir = this->GetOption( + cmValue outputDir = this->GetOption( cmStrCat("CPACK_NSIS_", componentName, "_INSTALL_DIRECTORY")); return outputDir ? *outputDir : "$INSTDIR"; } diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx index c268f271ab6..5de817937f0 100644 --- a/Source/CPack/cmCPackNuGetGenerator.cxx +++ b/Source/CPack/cmCPackNuGetGenerator.cxx @@ -12,9 +12,9 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" bool cmCPackNuGetGenerator::SupportsComponentInstallation() const { @@ -120,7 +120,7 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup) void cmCPackNuGetGenerator::AddGeneratedPackageNames() { - cmProp const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES"); + cmValue const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES"); if (!files_list) { cmCPackLogger( cmCPackLog::LOG_ERROR, diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 82917520f41..7bf1dc7352b 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -10,9 +10,9 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCPackOSXX11Generator::cmCPackOSXX11Generator() = default; @@ -23,7 +23,7 @@ int cmCPackOSXX11Generator::PackageFiles() // TODO: Use toplevel ? // It is used! Is this an obsolete comment? - cmProp cpackPackageExecutables = + cmValue cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { cmCPackLogger(cmCPackLog::LOG_DEBUG, @@ -70,7 +70,7 @@ int cmCPackOSXX11Generator::PackageFiles() const char* scrDir = scriptDirectory.c_str(); const char* contDir = contentsDirectory.c_str(); const char* rsrcFile = resourceFileName.c_str(); - cmProp iconFile = this->GetOption("CPACK_PACKAGE_ICON"); + cmValue iconFile = this->GetOption("CPACK_PACKAGE_ICON"); if (iconFile) { std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile); if (!cmSystemTools::FileExists(iconFile)) { diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index 171fbb2db91..91adf321e77 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -7,9 +7,9 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" cmCPackPKGGenerator::cmCPackPKGGenerator() @@ -57,7 +57,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName, std::string opt = (themeName == nullptr) ? cmStrCat("CPACK_", genName, "_BACKGROUND") : cmStrCat("CPACK_", genName, "_BACKGROUND_", paramSuffix); - cmProp bgFileName = this->GetOption(opt); + cmValue bgFileName = this->GetOption(opt); if (bgFileName == nullptr) { return; } @@ -79,7 +79,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName, xout.Attribute("file", bgFileName); - cmProp param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); + cmValue param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); if (param != nullptr) { xout.Attribute("alignment", param); } @@ -316,7 +316,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, { std::string uname = cmSystemTools::UpperCase(name); std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname; - cmProp inFileName = this->GetOption(cpackVar); + cmValue inFileName = this->GetOption(cpackVar); if (!inFileName) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str() diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index 291561680c4..a8cf1fad957 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -16,9 +16,9 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" static inline unsigned int getVersion(unsigned int major, unsigned int minor) @@ -80,9 +80,9 @@ int cmCPackPackageMakerGenerator::PackageFiles() resDir += "/en.lproj"; } - cmProp preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); - cmProp postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); - cmProp postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); + cmValue preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); + cmValue postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); + cmValue postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); if (this->Components.empty()) { // Create directory structure @@ -168,7 +168,7 @@ int cmCPackPackageMakerGenerator::PackageFiles() // Create the directory where downloaded component packages will // be placed. - cmProp userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); + cmValue userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; if (userUploadDirectory && !userUploadDirectory->empty()) { uploadDirectory = userUploadDirectory; @@ -352,7 +352,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal() "/PackageMaker.app/Contents/MacOS"); std::string pkgPath; - cmProp inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); + cmValue inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); if (inst_program && !inst_program->empty()) { pkgPath = inst_program; } else { @@ -427,7 +427,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal() // Determine the package compatibility version. If it wasn't // specified by the user, we define it based on which features the // user requested. - cmProp packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); + cmValue packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); if (packageCompat && !packageCompat->empty()) { unsigned int majorVersion = 10; unsigned int minorVersion = 5; diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 614b538b263..f55b8def05c 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -10,9 +10,9 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCPackProductBuildGenerator::cmCPackProductBuildGenerator() { @@ -88,11 +88,11 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); std::string identityName; - if (cmProp n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { + if (cmValue n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { identityName = n; } std::string keychainPath; - if (cmProp p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { + if (cmValue p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { keychainPath = p; } @@ -174,8 +174,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( const char* comp_name = component ? component->Name.c_str() : nullptr; - cmProp preflight = this->GetComponentScript("PREFLIGHT", comp_name); - cmProp postflight = this->GetComponentScript("POSTFLIGHT", comp_name); + cmValue preflight = this->GetComponentScript("PREFLIGHT", comp_name); + cmValue postflight = this->GetComponentScript("POSTFLIGHT", comp_name); std::string resDir = packageFileDir; if (component) { @@ -214,11 +214,11 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); std::string identityName; - if (cmProp n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { + if (cmValue n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { identityName = n; } std::string keychainPath; - if (cmProp p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { + if (cmValue p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { keychainPath = p; } @@ -240,7 +240,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( return RunProductBuild(pkgCmd.str()); } -cmProp cmCPackProductBuildGenerator::GetComponentScript( +cmValue cmCPackProductBuildGenerator::GetComponentScript( const char* script, const char* component_name) { std::string scriptname = std::string("CPACK_") + script + "_"; diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h index 8f169b0c6e4..31cfafadf10 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.h +++ b/Source/CPack/cmCPackProductBuildGenerator.h @@ -8,7 +8,7 @@ #include "cmCPackGenerator.h" #include "cmCPackPKGGenerator.h" -#include "cmProperty.h" +#include "cmValue.h" class cmCPackComponent; @@ -46,5 +46,5 @@ class cmCPackProductBuildGenerator : public cmCPackPKGGenerator const std::string& packageDir, const cmCPackComponent* component); - cmProp GetComponentScript(const char* script, const char* script_component); + cmValue GetComponentScript(const char* script, const char* script_component); }; diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 47db5bbe644..9e50700c608 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -12,9 +12,9 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCPackRPMGenerator::cmCPackRPMGenerator() = default; @@ -102,7 +102,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) this->packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - cmProp mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); + cmValue mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") && !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) { diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 4b34c087519..1340fb59f23 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -14,8 +14,8 @@ #include "cmArchiveWrite.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCPackSTGZGenerator::cmCPackSTGZGenerator() : cmCPackArchiveGenerator(cmArchiveWrite::CompressGZip, "paxr", ".sh") diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index a7789390339..54fd3587cf5 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -22,11 +22,11 @@ #include "cmDocumentationFormatter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -326,11 +326,11 @@ int main(int argc, char const* const* argv) cmSystemTools::CollapseFullPath(cpackProjectDirectory); globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); - cmProp cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); + cmValue cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); if (cpackModulesPath) { globalMF.AddDefinition("CMAKE_MODULE_PATH", *cpackModulesPath); } - cmProp genList = globalMF.GetDefinition("CPACK_GENERATOR"); + cmValue genList = globalMF.GetDefinition("CPACK_GENERATOR"); if (!genList) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified" << std::endl); @@ -408,20 +408,20 @@ int main(int argc, char const* const* argv) parsed = 0; } if (parsed) { - cmProp projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); + cmValue projName = mf->GetDefinition("CPACK_PACKAGE_NAME"); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: " << cpackGenerator->GetNameOfClass() << std::endl); cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "For project: " << *projName << std::endl); - cmProp projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION"); + cmValue projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION"); if (!projVersion) { - cmProp projVersionMajor = + cmValue projVersionMajor = mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR"); - cmProp projVersionMinor = + cmValue projVersionMinor = mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR"); - cmProp projVersionPatch = + cmValue projVersionPatch = mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH"); std::ostringstream ostr; ostr << *projVersionMajor << "." << *projVersionMinor << "." diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 483c316a639..6e7c9e10f46 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -11,9 +11,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" class cmExecutionStatus; @@ -39,13 +39,13 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() this->Handler = handler; - cmProp ctestBuildCommand = + cmValue ctestBuildCommand = this->Makefile->GetDefinition("CTEST_BUILD_COMMAND"); if (cmNonempty(ctestBuildCommand)) { this->CTest->SetCTestConfiguration("MakeCommand", *ctestBuildCommand, this->Quiet); } else { - cmProp cmakeGeneratorName = + cmValue cmakeGeneratorName = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR"); // Build configuration is determined by: CONFIGURATION argument, @@ -53,7 +53,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() // CTEST_CONFIGURATION_TYPE script variable, or ctest -C command // line argument... in that order. // - cmProp ctestBuildConfiguration = + cmValue ctestBuildConfiguration = this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION"); std::string cmakeBuildConfiguration = cmNonempty(this->Configuration) ? this->Configuration @@ -119,13 +119,13 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() } } - if (cmProp useLaunchers = + if (cmValue useLaunchers = this->Makefile->GetDefinition("CTEST_USE_LAUNCHERS")) { this->CTest->SetCTestConfiguration("UseLaunchers", *useLaunchers, this->Quiet); } - if (cmProp labelsForSubprojects = + if (cmValue labelsForSubprojects = this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) { this->CTest->SetCTestConfiguration("LabelsForSubprojects", *labelsForSubprojects, this->Quiet); diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 03caa6372ab..f9c4a8e35b0 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -19,10 +19,10 @@ #include "cmGeneratedFileStream.h" #include "cmMakefile.h" #include "cmProcessOutput.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" static const char* cmCTestErrorMatches[] = { @@ -249,11 +249,11 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile* mf) } // Record the user-specified custom warning rules. - if (cmProp customWarningMatchers = + if (cmValue customWarningMatchers = mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH")) { cmExpandList(*customWarningMatchers, this->ReallyCustomWarningMatches); } - if (cmProp customWarningExceptions = + if (cmValue customWarningExceptions = mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION")) { cmExpandList(*customWarningExceptions, this->ReallyCustomWarningExceptions); diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index db9923e95fc..fd20398d273 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -12,9 +12,9 @@ #include "cmCTestConfigureHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" void cmCTestConfigureCommand::BindArguments() @@ -39,14 +39,14 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() return nullptr; } - cmProp ctestConfigureCommand = + cmValue ctestConfigureCommand = this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND"); if (cmNonempty(ctestConfigureCommand)) { this->CTest->SetCTestConfiguration("ConfigureCommand", *ctestConfigureCommand, this->Quiet); } else { - cmProp cmakeGeneratorName = + cmValue cmakeGeneratorName = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR"); if (cmNonempty(cmakeGeneratorName)) { const std::string& source_dir = @@ -106,7 +106,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() cmakeConfigureCommand += *cmakeGeneratorName; cmakeConfigureCommand += "\""; - cmProp cmakeGeneratorPlatform = + cmValue cmakeGeneratorPlatform = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM"); if (cmNonempty(cmakeGeneratorPlatform)) { cmakeConfigureCommand += " \"-A"; @@ -114,7 +114,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() cmakeConfigureCommand += "\""; } - cmProp cmakeGeneratorToolset = + cmValue cmakeGeneratorToolset = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET"); if (cmNonempty(cmakeGeneratorToolset)) { cmakeConfigureCommand += " \"-T"; @@ -137,7 +137,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() } } - if (cmProp labelsForSubprojects = + if (cmValue labelsForSubprojects = this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) { this->CTest->SetCTestConfiguration("LabelsForSubprojects", *labelsForSubprojects, this->Quiet); diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index dc7103adee0..9800192ca0f 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -36,7 +36,7 @@ void SetMapValue(cmCTestGenericHandler::t_StringToString& map, map[op] = value; } void SetMapValue(cmCTestGenericHandler::t_StringToString& map, - const std::string& op, cmProp value) + const std::string& op, cmValue value) { if (!value) { map.erase(op); @@ -51,7 +51,7 @@ void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) { SetMapValue(this->Options, op, value); } -void cmCTestGenericHandler::SetOption(const std::string& op, cmProp value) +void cmCTestGenericHandler::SetOption(const std::string& op, cmValue value) { SetMapValue(this->Options, op, value); } @@ -63,7 +63,7 @@ void cmCTestGenericHandler::SetPersistentOption(const std::string& op, SetMapValue(this->PersistentOptions, op, value); } void cmCTestGenericHandler::SetPersistentOption(const std::string& op, - cmProp value) + cmValue value) { this->SetOption(op, value); SetMapValue(this->PersistentOptions, op, value); @@ -94,13 +94,13 @@ void cmCTestGenericHandler::Initialize() this->MultiOptions = this->PersistentMultiOptions; } -cmProp cmCTestGenericHandler::GetOption(const std::string& op) +cmValue cmCTestGenericHandler::GetOption(const std::string& op) { auto remit = this->Options.find(op); if (remit == this->Options.end()) { return nullptr; } - return cmProp(remit->second); + return cmValue(remit->second); } std::vector<std::string> cmCTestGenericHandler::GetMultiOption( diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 852d4ea4a9c..b4b0ad8a2a7 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -11,8 +11,8 @@ #include <stddef.h> #include "cmCTest.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" class cmGeneratedFileStream; class cmMakefile; @@ -89,16 +89,16 @@ class cmCTestGenericHandler void SetPersistentOption(const std::string& op, const char* value); void SetPersistentOption(const std::string& op, const std::string& value) { - this->SetPersistentOption(op, cmProp(value)); + this->SetPersistentOption(op, cmValue(value)); } - void SetPersistentOption(const std::string& op, cmProp value); + void SetPersistentOption(const std::string& op, cmValue value); void SetOption(const std::string& op, const char* value); void SetOption(const std::string& op, const std::string& value) { - this->SetOption(op, cmProp(value)); + this->SetOption(op, cmValue(value)); } - void SetOption(const std::string& op, cmProp value); - cmProp GetOption(const std::string& op); + void SetOption(const std::string& op, cmValue value); + cmValue GetOption(const std::string& op); /** * Multi-Options collect one or more values from flags; passing diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 731932e38ca..ea8feaa9ff1 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -14,9 +14,9 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmWorkingDirectory.h" namespace { @@ -126,7 +126,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, // CTEST_CONFIGURATION_TYPE script variable if it is defined. // The current script value trumps the -C argument on the command // line. - cmProp ctestConfigType = + cmValue ctestConfigType = this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE"); if (ctestConfigType) { this->CTest->SetConfigType(*ctestConfigType); @@ -161,7 +161,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, this->Quiet); } - if (cmProp changeId = this->Makefile->GetDefinition("CTEST_CHANGE_ID")) { + if (cmValue changeId = this->Makefile->GetDefinition("CTEST_CHANGE_ID")) { this->CTest->SetCTestConfiguration("ChangeId", *changeId, this->Quiet); } diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index d2cad3992a7..f685f66812e 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -34,12 +34,12 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" #ifdef _WIN32 @@ -372,8 +372,8 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) int cmCTestScriptHandler::ExtractVariables() { // Temporary variables - cmProp minInterval; - cmProp contDuration; + cmValue minInterval; + cmValue contDuration; this->SourceDir = this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); @@ -412,7 +412,7 @@ int cmCTestScriptHandler::ExtractVariables() int i; for (i = 1; i < 10; ++i) { sprintf(updateVar, "CTEST_EXTRA_UPDATES_%i", i); - cmProp updateVal = this->Makefile->GetDefinition(updateVar); + cmValue updateVal = this->Makefile->GetDefinition(updateVar); if (updateVal) { if (this->UpdateCmd.empty()) { cmSystemTools::Error( @@ -930,7 +930,7 @@ cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed() return cmCTest::MaxDuration(); } - cmProp timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT"); + cmValue timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT"); if (!timelimitS) { return cmCTest::MaxDuration(); diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index a8c24037316..84d12d77b08 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -9,8 +9,8 @@ #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" class cmExecutionStatus; @@ -30,8 +30,8 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, size_t cnt = 0; const char* smodel = nullptr; - cmProp src_dir; - cmProp bld_dir; + cmValue src_dir; + cmValue bld_dir; while (cnt < args.size()) { if (args[cnt] == "GROUP" || args[cnt] == "TRACK") { @@ -55,10 +55,10 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, smodel = args[cnt].c_str(); cnt++; } else if (!src_dir) { - src_dir = cmProp(args[cnt]); + src_dir = cmValue(args[cnt]); cnt++; } else if (!bld_dir) { - bld_dir = cmProp(args[cnt]); + bld_dir = cmValue(args[cnt]); cnt++; } else { this->SetError("Too many arguments"); @@ -162,7 +162,7 @@ bool cmCTestStartCommand::InitialCheckout(std::ostream& ofs, std::string const& sourceDir) { // Use the user-provided command to create the source tree. - cmProp initialCheckoutCommand = + cmValue initialCheckoutCommand = this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND"); if (!initialCheckoutCommand) { initialCheckoutCommand = diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 68247525c95..c4f87e993ce 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -16,10 +16,10 @@ #include "cmCommand.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" class cmExecutionStatus; @@ -36,8 +36,8 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone() cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() { - cmProp submitURL = !this->SubmitURL.empty() - ? cmProp(this->SubmitURL) + cmValue submitURL = !this->SubmitURL.empty() + ? cmValue(this->SubmitURL) : this->Makefile->GetDefinition("CTEST_SUBMIT_URL"); if (submitURL) { @@ -59,14 +59,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet); - cmProp notesFilesVariable = + cmValue notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); if (notesFilesVariable) { std::vector<std::string> notesFiles = cmExpandedList(*notesFilesVariable); this->CTest->GenerateNotesFile(notesFiles); } - cmProp extraFilesVariable = + cmValue extraFilesVariable = this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES"); if (extraFilesVariable) { std::vector<std::string> extraFiles = cmExpandedList(*extraFilesVariable); diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 9322bd572de..b99bb79d131 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -21,10 +21,10 @@ #include "cmCurl.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLParser.h" #include "cmake.h" @@ -261,7 +261,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( cmCTestScriptHandler* ch = this->CTest->GetScriptHandler(); cmake* cm = ch->GetCMake(); if (cm) { - cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject"); + cmValue subproject = cm->GetState()->GetGlobalProperty("SubProject"); if (subproject) { upload_as += "&subproject="; upload_as += ctest_curl.Escape(*subproject); @@ -548,7 +548,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, // a "&subproject=subprojectname" to the first POST. cmCTestScriptHandler* ch = this->CTest->GetScriptHandler(); cmake* cm = ch->GetCMake(); - cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject"); + cmValue subproject = cm->GetState()->GetGlobalProperty("SubProject"); // TODO: Encode values for a URL instead of trusting caller. std::ostringstream str; if (subproject) { @@ -708,8 +708,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, int cmCTestSubmitHandler::ProcessHandler() { - cmProp cdashUploadFile = this->GetOption("CDashUploadFile"); - cmProp cdashUploadType = this->GetOption("CDashUploadType"); + cmValue cdashUploadFile = this->GetOption("CDashUploadFile"); + cmValue cdashUploadType = this->GetOption("CDashUploadType"); if (cdashUploadFile && cdashUploadType) { return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType); } diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 80b8d4fafe9..5488388c820 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -12,8 +12,8 @@ #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" void cmCTestTestCommand::BindArguments() { @@ -40,7 +40,7 @@ void cmCTestTestCommand::BindArguments() cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() { - cmProp ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT"); + cmValue ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT"); cmDuration timeout; if (ctestTimeout) { @@ -54,7 +54,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() } this->CTest->SetTimeOut(timeout); - cmProp resourceSpecFile = + cmValue resourceSpecFile = this->Makefile->GetDefinition("CTEST_RESOURCE_SPEC_FILE"); if (this->ResourceSpecFile.empty() && resourceSpecFile) { this->ResourceSpecFile = *resourceSpecFile; @@ -114,7 +114,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() // or CTEST_TEST_LOAD script variable, or ctest --test-load // command line argument... in that order. unsigned long testLoad; - cmProp ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); + cmValue ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); if (!this->TestLoad.empty()) { if (!cmStrToULong(this->TestLoad, &testLoad)) { testLoad = 0; @@ -134,7 +134,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() } handler->SetTestLoad(testLoad); - if (cmProp labelsForSubprojects = + if (cmValue labelsForSubprojects = this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) { this->CTest->SetCTestConfiguration("LabelsForSubprojects", *labelsForSubprojects, this->Quiet); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index c41b661783a..6e97a834577 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -38,12 +38,12 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" +#include "cmValue.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -521,7 +521,7 @@ bool cmCTestTestHandler::ProcessOptions() if (cmIsOn(this->GetOption("ScheduleRandom"))) { this->CTest->SetScheduleType("Random"); } - if (cmProp repeat = this->GetOption("Repeat")) { + if (cmValue repeat = this->GetOption("Repeat")) { cmsys::RegularExpression repeatRegex( "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$"); if (repeatRegex.find(repeat)) { @@ -557,7 +557,7 @@ bool cmCTestTestHandler::ProcessOptions() this->IncludeLabelRegularExpressions); BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), this->ExcludeLabelRegularExpressions); - cmProp val = this->GetOption("IncludeRegularExpression"); + cmValue val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -1829,7 +1829,7 @@ bool cmCTestTestHandler::GetListOfTests() // SEND_ERROR or FATAL_ERROR in CTestTestfile or TEST_INCLUDE_FILES return false; } - cmProp specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); + cmValue specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE"); if (this->ResourceSpecFile.empty() && specFile) { this->ResourceSpecFile = *specFile; } @@ -2091,7 +2091,7 @@ void cmCTestTestHandler::SetExcludeRegExp(const std::string& arg) this->ExcludeRegExp = arg; } -void cmCTestTestHandler::SetTestsToRunInformation(cmProp in) +void cmCTestTestHandler::SetTestsToRunInformation(cmValue in) { if (!in) { return; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 585a3365758..3ac05e7bfed 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -22,7 +22,7 @@ #include "cmCTestResourceSpec.h" #include "cmDuration.h" #include "cmListFileCache.h" -#include "cmProperty.h" +#include "cmValue.h" class cmMakefile; class cmXMLWriter; @@ -82,7 +82,7 @@ class cmCTestTestHandler : public cmCTestGenericHandler } //! pass the -I argument down - void SetTestsToRunInformation(cmProp); + void SetTestsToRunInformation(cmValue); cmCTestTestHandler(); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 7c7c380e578..d448c769e45 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -17,9 +17,9 @@ #include "cmCTestSVN.h" #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmXMLWriter.h" @@ -109,7 +109,7 @@ int cmCTestUpdateHandler::ProcessHandler() static_cast<void>(fixLocale); // Get source dir - cmProp sourceDirectory = this->GetOption("SourceDirectory"); + cmValue sourceDirectory = this->GetOption("SourceDirectory"); if (!sourceDirectory) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find SourceDirectory key in the DartConfiguration.tcl" diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx index 35f09fd6a37..e9ec09ee28f 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx @@ -15,11 +15,11 @@ #include "cmCursesPathWidget.h" #include "cmCursesStringWidget.h" #include "cmCursesWidget.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( const std::string& key, int labelwidth, int entrywidth) @@ -49,7 +49,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " "); } - cmProp value = state->GetCacheEntryValue(key); + cmValue value = state->GetCacheEntryValue(key); assert(value); switch (state->GetCacheEntryType(key)) { case cmStateEnums::BOOL: { @@ -72,7 +72,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( break; } case cmStateEnums::STRING: { - cmProp stringsProp = state->GetCacheEntryProperty(key, "STRINGS"); + cmValue stringsProp = state->GetCacheEntryProperty(key, "STRINGS"); if (stringsProp) { auto ow = cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1); diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 069c02ef83f..b28c5b7ac47 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -17,11 +17,11 @@ #include "cmCursesStandardIncludes.h" #include "cmCursesStringWidget.h" #include "cmCursesWidget.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -162,7 +162,7 @@ void cmCursesMainForm::RePost() // If normal mode, count only non-advanced entries this->NumberOfVisibleEntries = 0; for (cmCursesCacheEntryComposite& entry : this->Entries) { - cmProp existingValue = + cmValue existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -183,7 +183,7 @@ void cmCursesMainForm::RePost() // Assign fields for (cmCursesCacheEntryComposite& entry : this->Entries) { - cmProp existingValue = + cmValue existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -242,7 +242,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height) // If normal, display only non-advanced entries this->NumberOfVisibleEntries = 0; for (cmCursesCacheEntryComposite& entry : this->Entries) { - cmProp existingValue = + cmValue existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -260,7 +260,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height) bool isNewPage; int i = 0; for (cmCursesCacheEntryComposite& entry : this->Entries) { - cmProp existingValue = + cmValue existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue()); bool advanced = this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool( @@ -406,9 +406,9 @@ void cmCursesMainForm::UpdateStatusBar(cm::optional<std::string> message) // Get the help string of the current entry // and add it to the help string auto* cmakeState = this->CMakeInstance->GetState(); - cmProp existingValue = cmakeState->GetCacheEntryValue(labelValue); + cmValue existingValue = cmakeState->GetCacheEntryValue(labelValue); if (existingValue) { - cmProp help = + cmValue help = cmakeState->GetCacheEntryProperty(labelValue, "HELPSTRING"); if (help) { bar += *help; @@ -618,7 +618,7 @@ void cmCursesMainForm::FillCacheManagerFromUI() { for (cmCursesCacheEntryComposite& entry : this->Entries) { const std::string& cacheKey = entry.Key; - cmProp existingValue = + cmValue existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey); if (existingValue) { std::string oldValue = *existingValue; @@ -804,9 +804,9 @@ void cmCursesMainForm::HandleInput() cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>( field_userptr(this->Fields[findex - 2])); const char* curField = lbl->GetValue(); - cmProp helpString = nullptr; + cmValue helpString = nullptr; - cmProp existingValue = + cmValue existingValue = this->CMakeInstance->GetState()->GetCacheEntryValue(curField); if (existingValue) { helpString = this->CMakeInstance->GetState()->GetCacheEntryProperty( diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 41e8a559451..8ab86564cb7 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -122,13 +122,13 @@ void QCMake::setBinaryDirectory(const QString& _dir) QCMakePropertyList props = this->properties(); emit this->propertiesChanged(props); - cmProp homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); + cmValue homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); if (homeDir) { setSourceDirectory(QString::fromLocal8Bit(homeDir->c_str())); } - cmProp gen = state->GetCacheEntryValue("CMAKE_GENERATOR"); + cmValue gen = state->GetCacheEntryValue("CMAKE_GENERATOR"); if (gen) { - cmProp extraGen = + cmValue extraGen = state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string curGen = cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*gen, @@ -136,12 +136,12 @@ void QCMake::setBinaryDirectory(const QString& _dir) this->setGenerator(QString::fromLocal8Bit(curGen.c_str())); } - cmProp platform = state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); + cmValue platform = state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); if (platform) { this->setPlatform(QString::fromLocal8Bit(platform->c_str())); } - cmProp toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); + cmValue toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (toolset) { this->setToolset(QString::fromLocal8Bit(toolset->c_str())); } @@ -396,11 +396,11 @@ QCMakePropertyList QCMake::properties() const continue; } - cmProp cachedValue = state->GetCacheEntryValue(key); + cmValue cachedValue = state->GetCacheEntryValue(key); QCMakeProperty prop; prop.Key = QString::fromLocal8Bit(key.c_str()); - if (cmProp hs = state->GetCacheEntryProperty(key, "HELPSTRING")) { + if (cmValue hs = state->GetCacheEntryProperty(key, "HELPSTRING")) { prop.Help = QString::fromLocal8Bit(hs->c_str()); } prop.Value = QString::fromLocal8Bit(cachedValue->c_str()); @@ -414,7 +414,7 @@ QCMakePropertyList QCMake::properties() const prop.Type = QCMakeProperty::FILEPATH; } else if (t == cmStateEnums::STRING) { prop.Type = QCMakeProperty::STRING; - cmProp stringsProperty = state->GetCacheEntryProperty(key, "STRINGS"); + cmValue stringsProperty = state->GetCacheEntryProperty(key, "STRINGS"); if (stringsProperty) { prop.Strings = QString::fromLocal8Bit(stringsProperty->c_str()).split(";"); diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 56b080aa6c3..415a1244721 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -6,10 +6,10 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { @@ -102,7 +102,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args, cmMakefile& mf = status.GetMakefile(); std::string const& define = args[0]; - cmProp cacheValue = mf.GetDefinition(define); + cmValue cacheValue = mf.GetDefinition(define); std::string configType; if (!cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType) || diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index f9b8f8f5d4c..20d6089b9fc 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -8,9 +8,9 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmSystemTools.h" +#include "cmValue.h" bool cmBuildNameCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -20,7 +20,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, return false; } cmMakefile& mf = status.GetMakefile(); - cmProp cacheValue = mf.GetDefinition(args[0]); + cmValue cacheValue = mf.GetDefinition(args[0]); if (cacheValue) { // do we need to correct the value? cmsys::RegularExpression reg("[()/]"); diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx index 9a5fa7bfc3e..bf94c2dcefa 100644 --- a/Source/cmCMakePathCommand.cxx +++ b/Source/cmCMakePathCommand.cxx @@ -18,11 +18,11 @@ #include "cmCMakePath.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSubcommandTable.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { // Helper classes for argument parsing @@ -150,7 +150,7 @@ class NormalizeParser : public CMakePathArgumentParser<NormalizeOption> bool getInputPath(const std::string& arg, cmExecutionStatus& status, std::string& path) { - cmProp def = status.GetMakefile().GetDefinition(arg); + cmValue def = status.GetMakefile().GetDefinition(arg); if (!def) { status.SetError("undefined variable for input path."); return false; diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index b2830e2c33d..ebf639b7443 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -6,10 +6,10 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" namespace { bool HandleSetMode(std::vector<std::string> const& args, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 7c469c84a4d..bc6abb5f7f2 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -56,12 +56,12 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmProcessOutput.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmVersionConfig.h" #include "cmXMLWriter.h" @@ -1457,11 +1457,11 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml) return; } // This code should go when cdash is changed to use labels only - cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject"); + cmValue subproject = cm->GetState()->GetGlobalProperty("SubProject"); if (subproject) { xml.StartElement("Subproject"); xml.Attribute("name", *subproject); - cmProp labels = + cmValue labels = ch->GetCMake()->GetState()->GetGlobalProperty("SubProjectLabels"); if (labels) { xml.StartElement("Labels"); @@ -1475,7 +1475,7 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml) } // This code should stay when cdash only does label based sub-projects - cmProp label = cm->GetState()->GetGlobalProperty("Label"); + cmValue label = cm->GetState()->GetGlobalProperty("Label"); if (label) { xml.StartElement("Labels"); xml.Element("Label", *label); @@ -3056,7 +3056,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const std::string& dir, void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def, std::vector<std::string>& vec) { - cmProp dval = mf->GetDefinition(def); + cmValue dval = mf->GetDefinition(def); if (!dval) { return; } @@ -3073,7 +3073,7 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def, void cmCTest::PopulateCustomInteger(cmMakefile* mf, const std::string& def, int& val) { - cmProp dval = mf->GetDefinition(def); + cmValue dval = mf->GetDefinition(def); if (!dval) { return; } @@ -3407,7 +3407,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable( cmMakefile* mf, const char* dconfig, const std::string& cmake_var, bool suppress) { - cmProp ctvar = mf->GetDefinition(cmake_var); + cmValue ctvar = mf->GetDefinition(cmake_var); if (!ctvar) { return false; } diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 17369c8d3f4..b9d1f66d2ac 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -118,13 +118,13 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } this->CacheMajorVersion = 0; this->CacheMinorVersion = 0; - if (cmProp cmajor = + if (cmValue cmajor = this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) { unsigned int v = 0; if (sscanf(cmajor->c_str(), "%u", &v) == 1) { this->CacheMajorVersion = v; } - if (cmProp cminor = + if (cmValue cminor = this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) { if (sscanf(cminor->c_str(), "%u", &v) == 1) { this->CacheMinorVersion = v; @@ -144,7 +144,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, } // check to make sure the cache directory has not // been moved - cmProp oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + cmValue oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); if (internal && oldDir) { std::string currentcwd = path; std::string oldcwd = *oldDir; @@ -152,7 +152,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, currentcwd += "/CMakeCache.txt"; oldcwd += "/CMakeCache.txt"; if (!cmSystemTools::SameFile(oldcwd, currentcwd)) { - cmProp dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); + cmValue dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); std::ostringstream message; message << "The current CMakeCache.txt directory " << currentcwd << " is different than the directory " << (dir ? *dir : "") @@ -203,7 +203,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, cmMessenger* messenger) const { for (const char* p : cmCacheManager::PersistentProperties) { - if (cmProp value = e.GetProperty(p)) { + if (cmValue value = e.GetProperty(p)) { std::string helpstring = cmStrCat(p, " property for variable: ", entryKey); cmCacheManager::OutputHelpString(os, helpstring); @@ -296,7 +296,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) */ } else if (t != cmStateEnums::INTERNAL) { // Format is key:type=value - if (cmProp help = ce.GetProperty("HELPSTRING")) { + if (cmValue help = ce.GetProperty("HELPSTRING")) { cmCacheManager::OutputHelpString(fout, *help); } else { cmCacheManager::OutputHelpString(fout, "Missing description"); @@ -326,7 +326,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) this->WritePropertyEntries(fout, i.first, i.second, messenger); if (t == cmStateEnums::INTERNAL) { // Format is key:type=value - if (cmProp help = i.second.GetProperty("HELPSTRING")) { + if (cmValue help = i.second.GetProperty("HELPSTRING")) { cmCacheManager::OutputHelpString(fout, *help); } cmCacheManager::OutputKey(fout, i.first); @@ -496,11 +496,11 @@ const cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry( return nullptr; } -cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const +cmValue cmCacheManager::GetInitializedCacheValue(const std::string& key) const { if (const auto* entry = this->GetCacheEntry(key)) { if (entry->Initialized) { - return cmProp(entry->GetValue()); + return cmValue(entry->GetValue()); } } return nullptr; @@ -521,7 +521,7 @@ void cmCacheManager::PrintCache(std::ostream& out) const "=================================================\n"; } -void cmCacheManager::AddCacheEntry(const std::string& key, cmProp value, +void cmCacheManager::AddCacheEntry(const std::string& key, cmValue value, const char* helpString, cmStateEnums::CacheEntryType type) { @@ -550,7 +550,7 @@ void cmCacheManager::AddCacheEntry(const std::string& key, cmProp value, : "(This variable does not exist and should not be used)"); } -void cmCacheManager::CacheEntry::SetValue(cmProp value) +void cmCacheManager::CacheEntry::SetValue(cmValue value) { if (value) { this->Value = *value; @@ -565,13 +565,13 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const return this->Properties.GetKeys(); } -cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const +cmValue cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const { if (prop == "TYPE") { - return cmProp(cmState::CacheEntryTypeToString(this->Type)); + return cmValue(cmState::CacheEntryTypeToString(this->Type)); } if (prop == "VALUE") { - return cmProp(this->Value); + return cmValue(this->Value); } return this->Properties.GetPropertyValue(prop); } diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index eca7150d3d4..bc3fb510a4b 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -11,9 +11,9 @@ #include <utility> #include <vector> -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmStateTypes.h" +#include "cmValue.h" class cmMessenger; @@ -31,13 +31,13 @@ class cmCacheManager public: const std::string& GetValue() const { return this->Value; } - void SetValue(cmProp); + void SetValue(cmValue); cmStateEnums::CacheEntryType GetType() const { return this->Type; } void SetType(cmStateEnums::CacheEntryType ty) { this->Type = ty; } std::vector<std::string> GetPropertyList() const; - cmProp GetProperty(const std::string& property) const; + cmValue GetProperty(const std::string& property) const; bool GetPropertyAsBool(const std::string& property) const; void SetProperty(const std::string& property, const char* value); void SetProperty(const std::string& property, bool value); @@ -70,12 +70,12 @@ class cmCacheManager bool IsCacheLoaded() const { return this->CacheLoaded; } //! Get a value from the cache given a key - cmProp GetInitializedCacheValue(const std::string& key) const; + cmValue GetInitializedCacheValue(const std::string& key) const; - cmProp GetCacheEntryValue(const std::string& key) const + cmValue GetCacheEntryValue(const std::string& key) const { if (const auto* entry = this->GetCacheEntry(key)) { - return cmProp(entry->GetValue()); + return cmValue(entry->GetValue()); } return nullptr; } @@ -83,7 +83,7 @@ class cmCacheManager void SetCacheEntryValue(std::string const& key, std::string const& value) { if (auto* entry = this->GetCacheEntry(key)) { - entry->SetValue(cmProp(value)); + entry->SetValue(cmValue(value)); } } @@ -104,8 +104,8 @@ class cmCacheManager return {}; } - cmProp GetCacheEntryProperty(std::string const& key, - std::string const& propName) const + cmValue GetCacheEntryProperty(std::string const& key, + std::string const& propName) const { if (const auto* entry = this->GetCacheEntry(key)) { return entry->GetProperty(propName); @@ -176,15 +176,15 @@ class cmCacheManager const char* helpString, cmStateEnums::CacheEntryType type) { this->AddCacheEntry(key, - value ? cmProp(std::string(value)) : cmProp(nullptr), + value ? cmValue(std::string(value)) : cmValue(nullptr), helpString, type); } void AddCacheEntry(const std::string& key, const std::string& value, const char* helpString, cmStateEnums::CacheEntryType type) { - this->AddCacheEntry(key, cmProp(value), helpString, type); + this->AddCacheEntry(key, cmValue(value), helpString, type); } - void AddCacheEntry(const std::string& key, cmProp value, + void AddCacheEntry(const std::string& key, cmValue value, const char* helpString, cmStateEnums::CacheEntryType type); diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 415f0c0c4d7..2ed04e5c493 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -14,10 +14,10 @@ #include "cmCommandArgumentLexer.h" #include "cmListFileCache.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" int cmCommandArgument_yyparse(yyscan_t yyscanner); // @@ -73,7 +73,8 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable( return ""; } if (strcmp(key, "CACHE") == 0) { - if (cmProp c = this->Makefile->GetState()->GetInitializedCacheValue(var)) { + if (cmValue c = + this->Makefile->GetState()->GetInitializedCacheValue(var)) { if (this->EscapeQuotes) { return this->AddString(cmEscapeQuotes(*c)); } @@ -103,7 +104,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) } return this->AddString(line); } - cmProp value = this->Makefile->GetDefinition(var); + cmValue value = this->Makefile->GetDefinition(var); if (!value) { this->Makefile->MaybeWarnUninitialized(var, this->FileName); if (!this->RemoveEmpty) { diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 4e7f50df24a..8d5ce7ed080 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -14,12 +14,12 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" +#include "cmValue.h" cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) : GeneratorTarget(gt) @@ -39,8 +39,8 @@ std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const return this->ConfigNames; } -cmProp cmCommonTargetGenerator::GetFeature(const std::string& feature, - const std::string& config) +cmValue cmCommonTargetGenerator::GetFeature(const std::string& feature, + const std::string& config) { return this->GeneratorTarget->GetFeature(feature, config); } @@ -56,7 +56,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag( } // TODO: Create a per-language flag variable. - cmProp defFileFlag = + cmValue defFileFlag = this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG"); if (!defFileFlag) { return; @@ -259,7 +259,7 @@ std::string cmCommonTargetGenerator::GetAIXExports(std::string const&) { std::string aixExports; if (this->GeneratorTarget->Target->IsAIX()) { - if (cmProp exportAll = + if (cmValue exportAll = this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) { if (cmIsOff(*exportAll)) { aixExports = "-n"; @@ -275,7 +275,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, { // Lookup the flag to specify the version. std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG"); - cmProp flag = this->Makefile->GetDefinition(fvar); + cmValue flag = this->Makefile->GetDefinition(fvar); // Skip if no such flag. if (!flag) { @@ -302,7 +302,7 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher( const std::string& config) { std::string lang = this->GeneratorTarget->GetLinkerLanguage(config); - cmProp launcherProp = + cmValue launcherProp = this->GeneratorTarget->GetProperty(lang + "_LINKER_LAUNCHER"); if (cmNonempty(launcherProp)) { // Convert ;-delimited list to single string diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 463a445a275..baa36c9e208 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -8,7 +8,7 @@ #include <string> #include <vector> -#include "cmProperty.h" +#include "cmValue.h" class cmGeneratorTarget; class cmGlobalCommonGenerator; @@ -30,7 +30,7 @@ class cmCommonTargetGenerator protected: // Feature query methods. - cmProp GetFeature(const std::string& feature, const std::string& config); + cmValue GetFeature(const std::string& feature, const std::string& config); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 15a12ba2438..370ddff5c89 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -18,11 +18,11 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" /* @@ -322,7 +322,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) } else { // Look for an old-style <item>_LIB_DEPENDS variable. std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS"); - if (cmProp val = this->Makefile->GetDefinition(var)) { + if (cmValue val = this->Makefile->GetDefinition(var)) { // The item dependencies are known. Follow them. BFSEntry qe = { index, val->c_str() }; this->BFSQueue.push(qe); @@ -489,7 +489,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // lower. if (!haveLLT) { std::string var = cmStrCat(d, "_LINK_TYPE"); - if (cmProp val = this->Makefile->GetDefinition(var)) { + if (cmValue val = this->Makefile->GetDefinition(var)) { if (*val == "debug") { llt = DEBUG_LibraryType; } else if (*val == "optimized") { diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index eda0722d0a7..a3e346c00e8 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -20,12 +20,12 @@ #include "cmOrderDirectories.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" //#define CM_COMPUTE_LINK_INFO_DEBUG @@ -286,28 +286,28 @@ cmComputeLinkInformation::cmComputeLinkInformation( } // Get options needed to link libraries. - if (cmProp flag = this->Makefile->GetDefinition( + if (cmValue flag = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FLAG")) { this->LibLinkFlag = *flag; } else { this->LibLinkFlag = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG"); } - if (cmProp flag = this->Makefile->GetDefinition( + if (cmValue flag = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FILE_FLAG")) { this->LibLinkFileFlag = *flag; } else { this->LibLinkFileFlag = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FILE_FLAG"); } - if (cmProp suffix = this->Makefile->GetDefinition( + if (cmValue suffix = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_SUFFIX")) { this->LibLinkSuffix = *suffix; } else { this->LibLinkSuffix = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); } - if (cmProp flag = this->Makefile->GetDefinition( + if (cmValue flag = this->Makefile->GetDefinition( "CMAKE_" + this->LinkLanguage + "_LINK_OBJECT_FILE_FLAG")) { this->ObjLinkFileFlag = *flag; } else { @@ -526,7 +526,7 @@ bool cmComputeLinkInformation::Compute() // Restore the target link type so the correct system runtime // libraries are found. - cmProp lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC"); + cmValue lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC"); if (cmIsOn(lss)) { this->SetCurrentLinkType(LinkStatic); } else { @@ -605,7 +605,7 @@ void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang) if (runtimeLibrary.empty()) { return; } - if (cmProp runtimeLinkOptions = this->Makefile->GetDefinition( + if (cmValue runtimeLinkOptions = this->Makefile->GetDefinition( "CMAKE_" + lang + "_RUNTIME_LIBRARY_LINK_OPTIONS_" + runtimeLibrary)) { std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions); for (std::string const& i : libsVec) { @@ -621,7 +621,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // Add libraries for this language that are not implied by the // linker language. std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES"); - if (cmProp libs = this->Makefile->GetDefinition(libVar)) { + if (cmValue libs = this->Makefile->GetDefinition(libVar)) { std::vector<std::string> libsVec = cmExpandedList(*libs); for (std::string const& i : libsVec) { if (!cm::contains(this->ImplicitLinkLibs, i)) { @@ -633,7 +633,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // Add linker search paths for this language that are not // implied by the linker language. std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES"); - if (cmProp dirs = this->Makefile->GetDefinition(dirVar)) { + if (cmValue dirs = this->Makefile->GetDefinition(dirVar)) { std::vector<std::string> dirsVec = cmExpandedList(*dirs); this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec); } @@ -836,8 +836,8 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() this->LinkTypeEnabled = false; // Lookup link type selection flags. - cmProp static_link_type_flag = nullptr; - cmProp shared_link_type_flag = nullptr; + cmValue static_link_type_flag = nullptr; + cmValue shared_link_type_flag = nullptr; const char* target_type_str = nullptr; switch (this->Target->GetType()) { case cmStateEnums::EXECUTABLE: @@ -875,7 +875,7 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() } // Lookup the starting link type from the target (linked statically?). - cmProp lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC"); + cmValue lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC"); this->StartLinkType = cmIsOn(lss) ? LinkStatic : LinkShared; this->CurrentLinkType = this->StartLinkType; } @@ -897,13 +897,14 @@ void cmComputeLinkInformation::ComputeItemParserInfo() LinkShared); this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"), LinkUnknown); - if (cmProp linkSuffixes = mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) { + if (cmValue linkSuffixes = + mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) { std::vector<std::string> linkSuffixVec = cmExpandedList(*linkSuffixes); for (std::string const& i : linkSuffixVec) { this->AddLinkExtension(i, LinkUnknown); } } - if (cmProp sharedSuffixes = + if (cmValue sharedSuffixes = mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) { std::vector<std::string> sharedSuffixVec = cmExpandedList(*sharedSuffixes); for (std::string const& i : sharedSuffixVec) { @@ -1589,7 +1590,7 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() // Append library architecture to all implicit platform directories // and add them to the set - if (cmProp libraryArch = + if (cmValue libraryArch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { for (std::string const& i : implicitDirVec) { this->ImplicitLinkDirs.insert(i + "/" + *libraryArch); @@ -1782,13 +1783,13 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, } if (use_build_rpath || use_link_rpath) { std::string rootPath; - if (cmProp sysrootLink = + if (cmValue sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { rootPath = *sysrootLink; } else { rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); } - cmProp stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + cmValue stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); std::string const& installPrefix = this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); cmSystemTools::ConvertToUnixSlashes(rootPath); @@ -1856,7 +1857,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, "CMAKE_" + li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH"; if (this->Makefile->IsOn(useVar)) { std::string dirVar = "CMAKE_" + li + "_IMPLICIT_LINK_DIRECTORIES"; - if (cmProp dirs = this->Makefile->GetDefinition(dirVar)) { + if (cmValue dirs = this->Makefile->GetDefinition(dirVar)) { cmCLI_ExpandListUnique(*dirs, runtimeDirs, emitted); } } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index c3ae3452564..90a699ebbd7 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -14,7 +14,7 @@ #include "cmsys/RegularExpression.hxx" #include "cmListFileCache.h" -#include "cmProperty.h" +#include "cmValue.h" class cmGeneratorTarget; class cmGlobalGenerator; @@ -138,7 +138,7 @@ class cmComputeLinkInformation SharedDepModeLink // List file on link line }; - cmProp LoaderFlag; + cmValue LoaderFlag; std::string LibLinkFlag; std::string LibLinkFileFlag; std::string ObjLinkFileFlag; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 5d3e04f7923..d85dea33f6d 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -17,7 +17,6 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmSourceFileLocationKind.h" @@ -27,6 +26,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" +#include "cmValue.h" #include "cmake.h" /* @@ -469,7 +469,7 @@ void cmComputeTargetDepends::ComputeIntermediateGraph() gt->GetType() != cmStateEnums::OBJECT_LIBRARY) { intermediateEdges = initialEdges; } else { - if (cmProp optimizeDependencies = + if (cmValue optimizeDependencies = gt->GetProperty("OPTIMIZE_DEPENDENCIES")) { if (cmIsOn(optimizeDependencies)) { this->OptimizeLinkDependencies(gt, intermediateEdges, initialEdges); diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 1d7696dbb90..913b532e8fa 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -19,10 +19,10 @@ #include "cmExpandedCommandArgument.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -285,7 +285,7 @@ bool cmConditionEvaluator::IsTrue( } //========================================================================= -cmProp cmConditionEvaluator::GetDefinitionIfUnquoted( +cmValue cmConditionEvaluator::GetDefinitionIfUnquoted( cmExpandedCommandArgument const& argument) const { if ((this->Policy54Status != cmPolicies::WARN && @@ -294,7 +294,7 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted( return nullptr; } - cmProp def = this->Makefile.GetDefinition(argument.GetValue()); + cmValue def = this->Makefile.GetDefinition(argument.GetValue()); if (def && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { @@ -317,13 +317,13 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted( } //========================================================================= -cmProp cmConditionEvaluator::GetVariableOrString( +cmValue cmConditionEvaluator::GetVariableOrString( const cmExpandedCommandArgument& argument) const { - cmProp def = this->GetDefinitionIfUnquoted(argument); + cmValue def = this->GetDefinitionIfUnquoted(argument); if (!def) { - def = cmProp(argument.GetValue()); + def = cmValue(argument.GetValue()); } return def; @@ -386,7 +386,7 @@ bool cmConditionEvaluator::GetBooleanValue( } // Check definition. - cmProp def = this->GetDefinitionIfUnquoted(arg); + cmValue def = this->GetDefinitionIfUnquoted(arg); return !cmIsOff(def); } @@ -403,13 +403,13 @@ bool cmConditionEvaluator::GetBooleanValueOld( if (arg == "1") { return true; } - cmProp def = this->GetDefinitionIfUnquoted(arg); + cmValue def = this->GetDefinitionIfUnquoted(arg); return !cmIsOff(def); } // Old GetVariableOrNumber behavior. - cmProp def = this->GetDefinitionIfUnquoted(arg); + cmValue def = this->GetDefinitionIfUnquoted(arg); if (!def && std::atoi(arg.GetValue().c_str())) { - def = cmProp(arg.GetValue()); + def = cmValue(arg.GetValue()); } return !cmIsOff(def); } @@ -651,17 +651,17 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, } else if (this->IsKeyword(keyMATCHES, *args.next)) { - cmProp def = this->GetDefinitionIfUnquoted(*args.current); + cmValue def = this->GetDefinitionIfUnquoted(*args.current); std::string def_buf; if (!def) { - def = cmProp(args.current->GetValue()); + def = cmValue(args.current->GetValue()); } else if (cmHasLiteralPrefix(args.current->GetValue(), "CMAKE_MATCH_")) { // The string to match is owned by our match result variables. // Move it to our own buffer before clearing them. def_buf = *def; - def = cmProp(def_buf); + def = cmValue(def_buf); } this->Makefile.ClearMatches(); @@ -687,8 +687,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, this->matchKeys(*args.next, keyLESS, keyLESS_EQUAL, keyGREATER, keyGREATER_EQUAL, keyEQUAL))) { - cmProp ldef = this->GetVariableOrString(*args.current); - cmProp rdef = this->GetVariableOrString(*args.nextnext); + cmValue ldef = this->GetVariableOrString(*args.current); + cmValue rdef = this->GetVariableOrString(*args.nextnext); double lhs; double rhs; @@ -711,8 +711,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, keySTRLESS_EQUAL, keySTRGREATER, keySTRGREATER_EQUAL, keySTREQUAL))) { - const cmProp lhs = this->GetVariableOrString(*args.current); - const cmProp rhs = this->GetVariableOrString(*args.nextnext); + const cmValue lhs = this->GetVariableOrString(*args.current); + const cmValue rhs = this->GetVariableOrString(*args.nextnext); const auto val = (*lhs).compare(*rhs); // clang-format off const auto result = cmRt2CtSelector< @@ -749,8 +749,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, if (this->Policy57Status != cmPolicies::OLD && this->Policy57Status != cmPolicies::WARN) { - cmProp lhs = this->GetVariableOrString(*args.current); - cmProp rhs = this->Makefile.GetDefinition(args.nextnext->GetValue()); + cmValue lhs = this->GetVariableOrString(*args.current); + cmValue rhs = this->Makefile.GetDefinition(args.nextnext->GetValue()); newArgs.ReduceTwoArgs( rhs && cm::contains(cmExpandedList(*rhs, true), *lhs), args); diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 00d896b82e2..37b7825b30a 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -12,7 +12,7 @@ #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" +#include "cmValue.h" class cmExpandedCommandArgument; class cmMakefile; @@ -32,10 +32,10 @@ class cmConditionEvaluator class cmArgumentList; // Filter the given variable definition based on policy CMP0054. - cmProp GetDefinitionIfUnquoted( + cmValue GetDefinitionIfUnquoted( const cmExpandedCommandArgument& argument) const; - cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const; + cmValue GetVariableOrString(const cmExpandedCommandArgument& argument) const; bool IsKeyword(cm::static_string_view keyword, const cmExpandedCommandArgument& argument) const; diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 0c85d287252..02d559be509 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -19,11 +19,11 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -246,7 +246,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->SrcFileSignature = true; cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE; - cmProp tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); + cmValue tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); if (!isTryRun && cmNonempty(tt)) { if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) { targetType = cmStateEnums::EXECUTABLE; @@ -540,7 +540,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, return -1; } - cmProp def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH"); + cmValue def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH"); fprintf(fout, "cmake_minimum_required(VERSION %u.%u.%u.%u)\n", cmVersion::GetMajorVersion(), cmVersion::GetMinorVersion(), cmVersion::GetPatchVersion(), cmVersion::GetTweakVersion()); @@ -549,7 +549,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } /* Set MSVC runtime library policy to match our selection. */ - if (cmProp msvcRuntimeLibraryDefault = + if (cmValue msvcRuntimeLibraryDefault = this->Makefile->GetDefinition(kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)) { fprintf(fout, "cmake_policy(SET CMP0091 %s)\n", !msvcRuntimeLibraryDefault->empty() ? "NEW" : "OLD"); @@ -564,7 +564,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } /* Set ARMClang cpu/arch policy to match outer project. */ - if (cmProp cmp0123 = + if (cmValue cmp0123 = this->Makefile->GetDefinition(kCMAKE_ARMClang_CMP0123)) { fprintf(fout, "cmake_policy(SET CMP0123 %s)\n", *cmp0123 == "NEW"_s ? "NEW" : "OLD"); @@ -582,11 +582,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, projectLangs += " " + li; std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE"; std::string rulesOverrideLang = cmStrCat(rulesOverrideBase, "_", li); - if (cmProp rulesOverridePath = + if (cmValue rulesOverridePath = this->Makefile->GetDefinition(rulesOverrideLang)) { fprintf(fout, "set(%s \"%s\")\n", rulesOverrideLang.c_str(), rulesOverridePath->c_str()); - } else if (cmProp rulesOverridePath2 = + } else if (cmValue rulesOverridePath2 = this->Makefile->GetDefinition(rulesOverrideBase)) { fprintf(fout, "set(%s \"%s\")\n", rulesOverrideBase.c_str(), rulesOverridePath2->c_str()); @@ -604,7 +604,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n"); for (std::string const& li : testLangs) { std::string langFlags = "CMAKE_" + li + "_FLAGS"; - cmProp flags = this->Makefile->GetDefinition(langFlags); + cmValue flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(), cmOutputConverter::EscapeForCMake(*flags).c_str()); fprintf(fout, @@ -643,7 +643,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, for (std::string const& li : testLangs) { std::string const langFlagsCfg = cmStrCat("CMAKE_", li, "_FLAGS_", cfg); - cmProp flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); + cmValue flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(), cmOutputConverter::EscapeForCMake(*flagsCfg).c_str()); } @@ -675,7 +675,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, case cmPolicies::NEW: // NEW behavior is to pass linker flags. { - cmProp exeLinkFlags = + cmValue exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", cmOutputConverter::EscapeForCMake(*exeLinkFlags).c_str()); @@ -760,7 +760,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_WARN_DEPRECATED); vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); - if (cmProp varListStr = this->Makefile->GetDefinition( + if (cmValue varListStr = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { std::vector<std::string> varList = cmExpandedList(*varListStr); vars.insert(varList.begin(), varList.end()); @@ -799,7 +799,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmLocalGenerator doesn't allow building for "the other" architecture only via CMAKE_OSX_ARCHITECTURES. */ - if (cmProp tcArchs = this->Makefile->GetDefinition( + if (cmValue tcArchs = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { vars.erase(kCMAKE_OSX_ARCHITECTURES); std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; @@ -807,7 +807,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } for (std::string const& var : vars) { - if (cmProp val = this->Makefile->GetDefinition(var)) { + if (cmValue val = this->Makefile->GetDefinition(var)) { std::string flag = "-D" + var + "=" + *val; cmakeFlags.push_back(std::move(flag)); } @@ -952,7 +952,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, if (this->Makefile->GetState()->UseGhsMultiIDE()) { // Forward the GHS variables to the inner project cache. for (std::string const& var : ghs_platform_vars) { - if (cmProp val = this->Makefile->GetDefinition(var)) { + if (cmValue val = this->Makefile->GetDefinition(var)) { std::string flag = "-D" + var + "=" + "'" + *val + "'"; cmakeFlags.push_back(std::move(flag)); } @@ -1094,7 +1094,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, std::vector<std::string> searchDirs; searchDirs.emplace_back(); - cmProp config = + cmValue config = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); // if a config was specified try that first if (cmNonempty(config)) { diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 5a2683bb8b1..04d09d4d62d 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -19,11 +19,11 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTransformDepfile.h" +#include "cmValue.h" namespace { std::string EvaluateSplitConfigGenex( @@ -284,7 +284,7 @@ void cmCustomCommandGenerator::FillEmulatorsWithArguments() if (target && target->GetType() == cmStateEnums::EXECUTABLE && !target->IsImported()) { - cmProp emulator_property = + cmValue emulator_property = target->GetProperty("CROSSCOMPILING_EMULATOR"); if (!emulator_property) { continue; diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 9e2d7b9e03c..a5f8aabec6f 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -34,11 +34,11 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, return begin->Map.emplace(key, def).first->second; } -cmProp cmDefinitions::Get(const std::string& key, StackIter begin, - StackIter end) +cmValue cmDefinitions::Get(const std::string& key, StackIter begin, + StackIter end) { Def const& def = cmDefinitions::GetInternal(key, begin, end, false); - return def.Value ? cmProp(def.Value.str_if_stable()) : nullptr; + return def.Value ? cmValue(def.Value.str_if_stable()) : nullptr; } void cmDefinitions::Raise(const std::string& key, StackIter begin, diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index ee1db7ada2e..22fef807af2 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -12,8 +12,8 @@ #include <cm/string_view> #include "cmLinkedTree.h" -#include "cmProperty.h" #include "cmString.hxx" +#include "cmValue.h" /** \class cmDefinitions * \brief Store a scope of variable definitions for CMake language. @@ -29,7 +29,7 @@ class cmDefinitions public: // -- Static member functions - static cmProp Get(const std::string& key, StackIter begin, StackIter end); + static cmValue Get(const std::string& key, StackIter begin, StackIter end); static void Raise(const std::string& key, StackIter begin, StackIter end); diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 46c7e3e773a..eca1abdaae5 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -11,9 +11,9 @@ #include "cmGeneratedFileStream.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmDepends::cmDepends(cmLocalUnixMakefileGenerator3* lg, std::string targetDir) : LocalGenerator(lg) @@ -232,7 +232,7 @@ void cmDepends::SetIncludePathFromLanguage(const std::string& lang) std::string includePathVar = cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH"); cmMakefile* mf = this->LocalGenerator->GetMakefile(); - cmProp includePath = mf->GetDefinition(includePathVar); + cmValue includePath = mf->GetDefinition(includePathVar); if (includePath) { cmExpandList(*includePath, this->IncludePath); } else { diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index da37d4531ce..25278090a4b 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -10,9 +10,9 @@ #include "cmGlobalUnixMakefileGenerator3.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #define INCLUDE_REGEX_LINE \ "^[ \t]*[#%][ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])" @@ -40,12 +40,12 @@ cmDependsC::cmDependsC(cmLocalUnixMakefileGenerator3* lg, std::string complainRegex = "^$"; { std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN"); - if (cmProp sr = mf->GetDefinition(scanRegexVar)) { + if (cmValue sr = mf->GetDefinition(scanRegexVar)) { scanRegex = *sr; } std::string complainRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN"); - if (cmProp cr = mf->GetDefinition(complainRegexVar)) { + if (cmValue cr = mf->GetDefinition(complainRegexVar)) { complainRegex = *cr; } } diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 6024cf62400..8456776c001 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -16,9 +16,9 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // TODO: Test compiler for the case of the mod file. Some always // use lower case and some always use upper case. I do not know if any @@ -416,7 +416,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile << ' ' << stampFileForShell; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - cmProp cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID"); + cmValue cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID"); if (cmNonempty(cid)) { makeDepends << ' ' << *cid; } diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 6e3f918d6c0..aa968dc3897 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -18,11 +18,11 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmTargetExport.h" +#include "cmValue.h" #include "cmake.h" class cmSourceFile; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 8b06a158149..8ca9a66cd17 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -21,12 +21,12 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" static std::string cmExportFileGeneratorEscape(std::string const& str) { @@ -125,7 +125,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty( const std::string& propName, cmGeneratorTarget const* target, ImportPropertyMap& properties) { - cmProp input = target->GetProperty(propName); + cmValue input = target->GetProperty(propName); if (input) { properties[propName] = *input; } @@ -137,7 +137,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty( cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets) { - cmProp input = target->GetProperty(propName); + cmValue input = target->GetProperty(propName); if (input) { if (input->empty()) { // Set to empty @@ -174,7 +174,7 @@ bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty( if (!target->IsLinkable()) { return false; } - cmProp input = target->GetProperty("INTERFACE_LINK_LIBRARIES"); + cmValue input = target->GetProperty("INTERFACE_LINK_LIBRARIES"); if (input) { std::string prepro = cmGeneratorExpression::Preprocess(*input, preprocessRule); @@ -341,7 +341,7 @@ void cmExportFileGenerator::PopulateSourcesInterface( assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_SOURCES"; - cmProp input = gt->GetProperty(propName); + cmValue input = gt->GetProperty(propName); if (!input) { return; @@ -372,7 +372,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_INCLUDE_DIRECTORIES"; - cmProp input = target->GetProperty(propName); + cmValue input = target->GetProperty(propName); cmGeneratorExpression ge; @@ -431,7 +431,7 @@ void cmExportFileGenerator::PopulateLinkDependsInterface( assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_LINK_DEPENDS"; - cmProp input = gt->GetProperty(propName); + cmValue input = gt->GetProperty(propName); if (!input) { return; @@ -462,7 +462,7 @@ void cmExportFileGenerator::PopulateLinkDirectoriesInterface( assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char* propName = "INTERFACE_LINK_DIRECTORIES"; - cmProp input = gt->GetProperty(propName); + cmValue input = gt->GetProperty(propName); if (!input) { return; @@ -497,7 +497,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty( void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop, std::set<std::string>& ifaceProperties) { - cmProp p = tgt->GetProperty(prop); + cmValue p = tgt->GetProperty(prop); if (!p) { return; } @@ -761,12 +761,12 @@ void cmExportFileGenerator::SetImportLinkInterface( return; } - cmProp propContent; + cmValue propContent; - if (cmProp prop_suffixed = + if (cmValue prop_suffixed = target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) { propContent = prop_suffixed; - } else if (cmProp prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) { + } else if (cmValue prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) { propContent = prop; } else { return; @@ -854,7 +854,7 @@ void cmExportFileGenerator::SetImportDetailProperties( cmGeneratorTarget::ManagedType::Native) { std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix); std::string propval; - if (cmProp p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) { + if (cmValue p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) { propval = *p; } else if (target->IsCSharpOnly()) { // C# projects do not have the /clr flag, so we set the property @@ -1215,7 +1215,7 @@ bool cmExportFileGenerator::PopulateExportProperties( std::string& errorMessage) { const auto& targetProperties = gte->Target->GetProperties(); - if (cmProp exportProperties = + if (cmValue exportProperties = targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) { for (auto& prop : cmExpandedList(*exportProperties)) { /* Black list reserved properties */ @@ -1228,7 +1228,7 @@ bool cmExportFileGenerator::PopulateExportProperties( errorMessage = e.str(); return false; } - cmProp propertyValue = targetProperties.GetPropertyValue(prop); + cmValue propertyValue = targetProperties.GetPropertyValue(prop); if (!propertyValue) { // Asked to export a property that isn't defined on the target. Do not // consider this an error, there's just nothing to export. diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 46d2d31cff5..e9ac8752feb 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -16,12 +16,12 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" +#include "cmValue.h" cmExportInstallFileGenerator::cmExportInstallFileGenerator( cmInstallExportGenerator* iegen) diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 7f31dd218d7..8aec12b6605 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -14,12 +14,12 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" +#include "cmValue.h" #include "cmake.h" class cmListFileBacktrace; @@ -96,7 +96,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename, // Handle simple output name changes. This command is // deprecated so we do not support full target name // translation (which requires per-configuration info). - if (cmProp outname = libtgt->GetProperty("OUTPUT_NAME")) { + if (cmValue outname = libtgt->GetProperty("OUTPUT_NAME")) { lib = *outname; } } diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index f89d0ada483..cbe3c4dc7df 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -13,10 +13,10 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" +#include "cmValue.h" cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator( cmGlobalGenerator* gg, const std::vector<std::string>& targets, @@ -60,7 +60,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets( const std::string& propName, cmGeneratorTarget const* tgt, std::string const& language, std::set<cmGeneratorTarget const*>& emitted) { - cmProp prop = tgt->GetProperty(propName); + cmValue prop = tgt->GetProperty(propName); if (!prop) { return std::string(); } diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index df1426104bb..9ad8876fc87 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -16,12 +16,12 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -499,12 +499,12 @@ void cmExtraCodeBlocksGenerator::AppendTarget( if (target->GetType() == cmStateEnums::EXECUTABLE) { // Determine the directory where the executable target is created, and // set the working directory to this dir. - cmProp runtimeOutputDir = + cmValue runtimeOutputDir = makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"); if (runtimeOutputDir) { workingDir = *runtimeOutputDir; } else { - cmProp executableOutputDir = + cmValue executableOutputDir = makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"); if (executableOutputDir) { workingDir = *executableOutputDir; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 672089c7362..d9d5a4b506a 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -19,13 +19,13 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -189,7 +189,7 @@ void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile() } fout << "eclipse.preferences.version=1\n"; - cmProp encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING"); + cmValue encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING"); if (encoding) { fout << "encoding/<project>=" << *encoding << '\n'; } @@ -244,7 +244,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue); std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar); - cmProp cacheValue = lg.GetState()->GetInitializedCacheValue(cacheEntryName); + cmValue cacheValue = lg.GetState()->GetInitializedCacheValue(cacheEntryName); // now we have both, decide which one to use std::string valueToUse; @@ -415,7 +415,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() xml.Element("nature", n); } - if (cmProp extraNaturesProp = + if (cmValue extraNaturesProp = mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) { std::vector<std::string> extraNatures = cmExpandedList(*extraNaturesProp); for (std::string const& n : extraNatures) { @@ -754,7 +754,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const emitted.clear(); for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { - if (cmProp cdefs = + if (cmValue cdefs = lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) { // Expand the list. std::vector<std::string> defs; @@ -793,7 +793,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } } // add system defined c macros - cmProp cDefs = + cmValue cDefs = mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS"); if (this->CEnabled && cDefs) { // Expand the list. @@ -825,7 +825,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const } } // add system defined c++ macros - cmProp cxxDefs = + cmValue cxxDefs = mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS"); if (this->CXXEnabled && cxxDefs) { // Expand the list. @@ -1032,7 +1032,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const xml.EndElement(); // storageModule // Append additional cproject contents without applying any XML formatting - if (cmProp extraCProjectContents = + if (cmValue extraCProjectContents = mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) { fout << *extraCProjectContents; } diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index 9153119c4bb..eec43c4736d 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -13,11 +13,11 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmExtraKateGenerator::cmExtraKateGenerator() = default; @@ -128,7 +128,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg, // only add the "edit_cache" target if it's not ccmake, because // this will not work within the IDE if (targetName == "edit_cache") { - cmProp editCommand = + cmValue editCommand = localGen->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND"); if (!editCommand || strstr(editCommand->c_str(), "ccmake") != nullptr) { diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 52965bb579b..fa93b04d2ee 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -17,11 +17,11 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" /* @@ -364,12 +364,12 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (cmProp cflags = source->GetProperty(COMPILE_FLAGS)) { + if (cmValue cflags = source->GetProperty(COMPILE_FLAGS)) { lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS)); } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (cmProp coptions = source->GetProperty(COMPILE_OPTIONS)) { + if (cmValue coptions = source->GetProperty(COMPILE_OPTIONS)) { lg->AppendCompileOptions( flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS)); } @@ -393,14 +393,14 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( // Add preprocessor definitions for this target and configuration. lg->GetTargetDefines(target, config, language, defines); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - if (cmProp compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { + if (cmValue compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { lg->AppendDefines( defines, genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS)); } std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); - if (cmProp config_compile_defs = source->GetProperty(defPropName)) { + if (cmValue config_compile_defs = source->GetProperty(defPropName)) { lg->AppendDefines( defines, genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS)); @@ -425,7 +425,7 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes( // Add include directories for this source file const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (cmProp cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { + if (cmValue cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { lg->AppendIncludeDirectories( includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), *source); @@ -445,7 +445,7 @@ bool cmExtraSublimeTextGenerator::Open(const std::string& bindir, const std::string& projectName, bool dryRun) { - cmProp sublExecutable = + cmValue sublExecutable = this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition( "CMAKE_SUBLIMETEXT_EXECUTABLE"); if (!sublExecutable) { diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx index ddae5273b0e..ba38ef7981c 100644 --- a/Source/cmFileAPICache.cxx +++ b/Source/cmFileAPICache.cxx @@ -10,8 +10,8 @@ #include <cm3p/json/value.h> #include "cmFileAPI.h" -#include "cmProperty.h" #include "cmState.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -95,7 +95,7 @@ Json::Value Cache::DumpEntryProperty(std::string const& name, { Json::Value property = Json::objectValue; property["name"] = prop; - cmProp p = this->State->GetCacheEntryProperty(name, prop); + cmValue p = this->State->GetCacheEntryProperty(name, prop); property["value"] = p ? *p : ""; return property; } diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index adeba74895d..147181e3f04 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -41,7 +41,6 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" @@ -53,6 +52,7 @@ #include "cmTarget.h" #include "cmTargetDepend.h" #include "cmTargetExport.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -813,7 +813,7 @@ Json::Value CodemodelConfig::DumpProject(Project& p) Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) { Json::Value minimumCMakeVersion; - if (cmProp def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { + if (cmValue def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { minimumCMakeVersion = Json::objectValue; minimumCMakeVersion["string"] = *def; } @@ -1187,10 +1187,10 @@ void Target::ProcessLanguage(std::string const& lang) { CompileData& cd = this->CompileDataMap[lang]; cd.Language = lang; - if (cmProp sysrootCompile = + if (cmValue sysrootCompile = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { cd.Sysroot = *sysrootCompile; - } else if (cmProp sysroot = + } else if (cmValue sysroot = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) { cd.Sysroot = *sysroot; } @@ -1259,7 +1259,7 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) fd.Language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) { + if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) { std::string flags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS); fd.Flags.emplace_back(std::move(flags), JBTIndex()); } @@ -1353,7 +1353,7 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) std::set<std::string> configFileDefines; const std::string defPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config); - if (cmProp config_defs = sf->GetProperty(defPropName)) { + if (cmValue config_defs = sf->GetProperty(defPropName)) { lg->AppendDefines( configFileDefines, genexInterpreter.Evaluate(*config_defs, COMPILE_DEFINITIONS)); @@ -1739,10 +1739,10 @@ Json::Value Target::DumpLink() link["commandFragments"] = std::move(commandFragments); } } - if (cmProp sysrootLink = + if (cmValue sysrootLink = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { link["sysroot"] = this->DumpSysroot(*sysrootLink); - } else if (cmProp sysroot = + } else if (cmValue sysroot = this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) { link["sysroot"] = this->DumpSysroot(*sysroot); } @@ -1868,7 +1868,7 @@ Json::Value Target::DumpDependency(cmTargetDepend const& td) Json::Value Target::DumpFolder() { Json::Value folder; - if (cmProp f = this->GT->GetProperty("FOLDER")) { + if (cmValue f = this->GT->GetProperty("FOLDER")) { folder = Json::objectValue; folder["name"] = *f; } diff --git a/Source/cmFileAPIToolchains.cxx b/Source/cmFileAPIToolchains.cxx index 722c1145eca..b3540c97b29 100644 --- a/Source/cmFileAPIToolchains.cxx +++ b/Source/cmFileAPIToolchains.cxx @@ -11,9 +11,9 @@ #include "cmFileAPI.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -136,7 +136,7 @@ void Toolchains::DumpToolchainVariable(cmMakefile const* mf, object[variable.ObjectKey] = jsonArray; } } else { - cmProp def = mf->GetDefinition(variableName); + cmValue def = mf->GetDefinition(variableName); if (def) { object[variable.ObjectKey] = *def; } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index bdfec029979..4eb632d0419 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -47,7 +47,6 @@ #include "cmMessageType.h" #include "cmNewLineStyle.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmRuntimeDependencyArchive.h" #include "cmState.h" @@ -55,6 +54,7 @@ #include "cmSubcommandTable.h" #include "cmSystemTools.h" #include "cmTimestamp.h" +#include "cmValue.h" #include "cmWorkingDirectory.h" #include "cmake.h" @@ -1766,7 +1766,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, std::string logVar; std::string statusVar; bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY"); - cmProp cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); + cmValue cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); std::string netrc_level = status.GetMakefile().GetSafeDefinition("CMAKE_NETRC"); std::string netrc_file = @@ -1821,7 +1821,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } else if (*i == "TLS_CAINFO") { ++i; if (i != args.end()) { - cainfo = cmProp(*i); + cainfo = cmValue(*i); } else { status.SetError("DOWNLOAD missing file value for TLS_CAINFO."); return false; @@ -2152,7 +2152,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, std::string statusVar; bool showProgress = false; bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY"); - cmProp cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); + cmValue cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); std::string userpwd; std::string netrc_level = status.GetMakefile().GetSafeDefinition("CMAKE_NETRC"); @@ -2205,7 +2205,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, } else if (*i == "TLS_CAINFO") { ++i; if (i != args.end()) { - cainfo = cmProp(*i); + cainfo = cmValue(*i); } else { status.SetError("UPLOAD missing file value for TLS_CAINFO."); return false; diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 48fc2868296..00254a06a5f 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -10,9 +10,9 @@ #include "cmFSPermissions.h" #include "cmFileTimes.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #ifdef _WIN32 # include "cmsys/FStream.hxx" @@ -172,7 +172,7 @@ void cmFileCopier::DefaultDirectoryPermissions() bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode) { // check if default dir creation permissions were set - cmProp default_dir_install_permissions = this->Makefile->GetDefinition( + cmValue default_dir_install_permissions = this->Makefile->GetDefinition( "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_install_permissions)) { std::vector<std::string> items = diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 37f95727011..a123e4408d1 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -13,13 +13,13 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSearchPath.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" class cmExecutionStatus; @@ -301,9 +301,9 @@ void cmFindBase::FillUserGuessPath() bool cmFindBase::CheckForVariableDefined() { - if (cmProp value = this->Makefile->GetDefinition(this->VariableName)) { + if (cmValue value = this->Makefile->GetDefinition(this->VariableName)) { cmState* state = this->Makefile->GetState(); - cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName); + cmValue cacheEntry = state->GetCacheEntryValue(this->VariableName); bool found = !cmIsNOTFOUND(*value); bool cached = cacheEntry != nullptr; auto cacheType = cached ? state->GetCacheEntryType(this->VariableName) diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index d2f96197b83..bdc92077279 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -11,9 +11,9 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL"); @@ -183,7 +183,7 @@ void cmFindCommon::SelectDefaultSearchModes() }; for (auto const& path : search_paths) { - cmProp def = this->Makefile->GetDefinition(path.second); + cmValue def = this->Makefile->GetDefinition(path.second); if (def) { path.first = !cmIsOn(*def); } @@ -203,11 +203,11 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) return; } - cmProp sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT"); - cmProp sysrootCompile = + cmValue sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT"); + cmValue sysrootCompile = this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE"); - cmProp sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK"); - cmProp rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); + cmValue sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK"); + cmValue rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); const bool noSysroot = !cmNonempty(sysroot); const bool noCompileSysroot = !cmNonempty(sysrootCompile); const bool noLinkSysroot = !cmNonempty(sysrootLink); @@ -234,7 +234,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) cmSystemTools::ConvertToUnixSlashes(r); } - cmProp stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + cmValue stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); // Copy the original set of unrooted paths. std::vector<std::string> unrootedPaths = paths; diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index ef960d18f36..bfa007cc741 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -12,11 +12,11 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" class cmExecutionStatus; @@ -46,7 +46,7 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) // add custom lib<qual> paths instead of using fixed lib32, lib64 or // libx32 - if (cmProp customLib = this->Makefile->GetDefinition( + if (cmValue customLib = this->Makefile->GetDefinition( "CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX")) { this->AddArchitecturePaths(customLib->c_str()); } @@ -268,7 +268,7 @@ std::string const& get_prefixes(cmMakefile* mf) #else static std::string defaultPrefix = "lib"; #endif - cmProp prefixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_PREFIXES"); + cmValue prefixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_PREFIXES"); return (prefixProp) ? *prefixProp : defaultPrefix; } @@ -283,7 +283,7 @@ std::string const& get_suffixes(cmMakefile* mf) #else static std::string defaultSuffix = ".so;.a"; #endif - cmProp suffixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_SUFFIXES"); + cmValue suffixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_SUFFIXES"); return (suffixProp) ? *suffixProp : defaultSuffix; } } diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index a0de74c8dc2..335ebbe4e68 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -25,13 +25,13 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSearchPath.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #if defined(__HAIKU__) @@ -137,7 +137,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } // Lookup required version of CMake. - if (cmProp rv = + if (cmValue rv = this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { unsigned int v[3] = { 0, 0, 0 }; sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]); @@ -148,7 +148,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->DebugBuffer.clear(); // Lookup target architecture, if any. - if (cmProp arch = + if (cmValue arch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { this->LibraryArchitecture = *arch; } @@ -177,7 +177,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Check if User Package Registry should be disabled // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY - if (cmProp def = + if (cmValue def = this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) { this->NoUserRegistry = !cmIsOn(*def); } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { @@ -187,7 +187,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Check if System Package Registry should be disabled // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY - if (cmProp def = this->Makefile->GetDefinition( + if (cmValue def = this->Makefile->GetDefinition( "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) { this->NoSystemRegistry = !cmIsOn(*def); } else if (this->Makefile->IsOn( @@ -201,7 +201,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } // Check if Sorting should be enabled - if (cmProp so = + if (cmValue so = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) { if (*so == "NAME") { @@ -212,7 +212,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->SortOrder = None; } } - if (cmProp sd = + if (cmValue sd = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) { this->SortDirection = (*sd == "ASC") ? Asc : Dec; } @@ -753,7 +753,7 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) void cmFindPackageCommand::AddFindDefinition(const std::string& var, cm::string_view value) { - if (cmProp old = this->Makefile->GetDefinition(var)) { + if (cmValue old = this->Makefile->GetDefinition(var)) { this->OriginalDefs[var].exists = true; this->OriginalDefs[var].value = *old; } else { @@ -846,7 +846,7 @@ bool cmFindPackageCommand::HandlePackageMode( this->ConsideredConfigs.clear(); // Try to find the config file. - cmProp def = this->Makefile->GetDefinition(this->Variable); + cmValue def = this->Makefile->GetDefinition(this->Variable); // Try to load the config file if the directory is known bool fileFound = false; @@ -1206,7 +1206,7 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f, void cmFindPackageCommand::AppendToFoundProperty(bool found) { std::vector<std::string> foundContents; - cmProp foundProp = + cmValue foundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND"); if (cmNonempty(foundProp)) { cmExpandList(*foundProp, foundContents, false); @@ -1218,7 +1218,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) } std::vector<std::string> notFoundContents; - cmProp notFoundProp = + cmValue notFoundProp = this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND"); if (cmNonempty(notFoundProp)) { cmExpandList(*notFoundProp, notFoundContents, false); diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index b44f79716c4..dcb362654ca 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -27,10 +27,10 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { class cmForEachFunctionBlocker : public cmFunctionBlocker diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 4e06a0753a9..c357ee145cf 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -37,7 +37,6 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStandardLevelResolver.h" #include "cmState.h" @@ -46,6 +45,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" std::string cmGeneratorExpressionNode::EvaluateDependentExpression( @@ -914,8 +914,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode } if (context->CurrentTarget && context->CurrentTarget->IsImported()) { - cmProp loc = nullptr; - cmProp imp = nullptr; + cmValue loc = nullptr; + cmValue imp = nullptr; std::string suffix; if (context->CurrentTarget->Target->GetMappedConfig(context->Config, loc, imp, suffix)) { @@ -925,7 +925,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode std::vector<std::string> mappedConfigs; std::string mapProp = cmStrCat( "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config)); - if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) { + if (cmValue mapValue = context->CurrentTarget->GetProperty(mapProp)) { cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs); for (auto const& param : parameters) { @@ -1502,7 +1502,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode std::string result; bool haveProp = false; - if (cmProp p = target->GetProperty(propertyName)) { + if (cmValue p = target->GetProperty(propertyName)) { result = *p; haveProp = true; } else if (evaluatingLinkLibraries) { @@ -1652,8 +1652,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode std::vector<std::string> objects; if (gt->IsImported()) { - cmProp loc = nullptr; - cmProp imp = nullptr; + cmValue loc = nullptr; + cmValue imp = nullptr; std::string suffix; if (gt->Target->GetMappedConfig(context->Config, loc, imp, suffix)) { cmExpandList(*loc, objects); @@ -1775,7 +1775,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode testedFeatures[lang].push_back(p); if (availableFeatures.find(lang) == availableFeatures.end()) { - cmProp featuresKnown = + cmValue featuresKnown = standardResolver.CompileFeaturesAvailable(lang, &error); if (!featuresKnown) { reportError(context, content->GetOriginalExpression(), error); @@ -1790,7 +1790,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode for (auto const& lit : testedFeatures) { std::vector<std::string> const& langAvailable = availableFeatures[lit.first]; - cmProp standardDefault = context->LG->GetMakefile()->GetDefinition( + cmValue standardDefault = context->LG->GetMakefile()->GetDefinition( "CMAKE_" + lit.first + "_STANDARD_DEFAULT"); for (std::string const& it : lit.second) { if (!cm::contains(langAvailable, it)) { @@ -1804,7 +1804,8 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode if (!standardResolver.HaveStandardAvailable(target, lit.first, context->Config, it)) { if (evalLL) { - cmProp l = target->GetLanguageStandard(lit.first, context->Config); + cmValue l = + target->GetLanguageStandard(lit.first, context->Config); if (!l) { l = standardDefault; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f80b4d93758..ef1f8716fcc 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -58,7 +58,7 @@ const cmsys::RegularExpression FrameworkRegularExpression( } template <> -cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( +cmValue cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, cmListFileBacktrace const& /* context */) { @@ -322,7 +322,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) cmGeneratorTarget::~cmGeneratorTarget() = default; -cmProp cmGeneratorTarget::GetSourcesProperty() const +cmValue cmGeneratorTarget::GetSourcesProperty() const { std::vector<std::string> values; for (auto const& se : this->SourceEntries) { @@ -331,7 +331,7 @@ cmProp cmGeneratorTarget::GetSourcesProperty() const static std::string value; value.clear(); value = cmJoin(values, ";"); - return cmProp(value); + return cmValue(value); } cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const @@ -356,7 +356,7 @@ const std::string& cmGeneratorTarget::GetName() const std::string cmGeneratorTarget::GetExportName() const { - cmProp exportName = this->GetProperty("EXPORT_NAME"); + cmValue exportName = this->GetProperty("EXPORT_NAME"); if (cmNonempty(exportName)) { if (!cmGeneratorExpression::IsValidTargetName(*exportName)) { @@ -371,9 +371,9 @@ std::string cmGeneratorTarget::GetExportName() const return this->GetName(); } -cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const +cmValue cmGeneratorTarget::GetProperty(const std::string& prop) const { - if (cmProp result = cmTargetPropertyComputer::GetProperty( + if (cmValue result = cmTargetPropertyComputer::GetProperty( this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) { return result; } @@ -475,7 +475,7 @@ std::string cmGeneratorTarget::GetOutputName( std::string outName; for (std::string const& p : props) { - if (cmProp outNameProp = this->GetProperty(p)) { + if (cmValue outNameProp = this->GetProperty(p)) { outName = *outNameProp; break; } @@ -503,7 +503,7 @@ std::string cmGeneratorTarget::GetFilePrefix( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - cmProp prefix = this->GetFilePrefixInternal(config, artifact); + cmValue prefix = this->GetFilePrefixInternal(config, artifact); return prefix ? *prefix : std::string(); } @@ -517,7 +517,7 @@ std::string cmGeneratorTarget::GetFileSuffix( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - cmProp suffix = this->GetFileSuffixInternal(config, artifact); + cmValue suffix = this->GetFileSuffixInternal(config, artifact); return suffix ? *suffix : std::string(); } @@ -530,7 +530,7 @@ std::string cmGeneratorTarget::GetFileSuffix( std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const { - cmProp postfix = nullptr; + cmValue postfix = nullptr; std::string frameworkPostfix; if (!config.empty()) { std::string configProp = @@ -548,7 +548,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const // framework postfix. frameworkPostfix = this->GetFrameworkMultiConfigPostfix(config); if (!frameworkPostfix.empty()) { - postfix = cmProp(frameworkPostfix); + postfix = cmValue(frameworkPostfix); } } return postfix ? *postfix : std::string(); @@ -557,7 +557,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix( const std::string& config) const { - cmProp postfix = nullptr; + cmValue postfix = nullptr; if (!config.empty()) { std::string configProp = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_", cmSystemTools::UpperCase(config)); @@ -572,7 +572,7 @@ std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix( return postfix ? *postfix : std::string(); } -cmProp cmGeneratorTarget::GetFilePrefixInternal( +cmValue cmGeneratorTarget::GetFilePrefixInternal( std::string const& config, cmStateEnums::ArtifactType artifact, const std::string& language) const { @@ -602,7 +602,7 @@ cmProp cmGeneratorTarget::GetFilePrefixInternal( } // Compute prefix value. - cmProp targetPrefix = + cmValue targetPrefix = (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX") : this->GetProperty("PREFIX")); @@ -623,7 +623,7 @@ cmProp cmGeneratorTarget::GetFilePrefixInternal( return targetPrefix; } -cmProp cmGeneratorTarget::GetFileSuffixInternal( +cmValue cmGeneratorTarget::GetFileSuffixInternal( std::string const& config, cmStateEnums::ArtifactType artifact, const std::string& language) const { @@ -653,7 +653,7 @@ cmProp cmGeneratorTarget::GetFileSuffixInternal( } // Compute suffix value. - cmProp targetSuffix = + cmValue targetSuffix = (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX") : this->GetProperty("SUFFIX")); @@ -738,7 +738,7 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, std::vector<std::string>& result, bool excludeImported, std::string const& language) { - if (cmProp dirs = + if (cmValue dirs = depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) { cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget, dagChecker, depTgt, language), @@ -748,7 +748,7 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, return; } - if (cmProp dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { + if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget, dagChecker, depTgt, language), result); @@ -800,17 +800,17 @@ void cmGeneratorTarget::ComputeObjectMapping() } } -cmProp cmGeneratorTarget::GetFeature(const std::string& feature, - const std::string& config) const +cmValue cmGeneratorTarget::GetFeature(const std::string& feature, + const std::string& config) const { if (!config.empty()) { std::string featureConfig = cmStrCat(feature, '_', cmSystemTools::UpperCase(config)); - if (cmProp value = this->GetProperty(featureConfig)) { + if (cmValue value = this->GetProperty(featureConfig)) { return value; } } - if (cmProp value = this->GetProperty(feature)) { + if (cmValue value = this->GetProperty(feature)) { return value; } return this->LocalGenerator->GetFeature(feature, config); @@ -838,7 +838,7 @@ const char* cmGeneratorTarget::GetLinkPIEProperty( bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, std::string const& config) const { - cmProp feature = this->GetFeature("INTERPROCEDURAL_OPTIMIZATION", config); + cmValue feature = this->GetFeature("INTERPROCEDURAL_OPTIMIZATION", config); if (!cmIsOn(feature)) { // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies @@ -946,23 +946,23 @@ BTs<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty( cmStrCat(lang, "_STANDARD")); } -cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang, - std::string const& config) const +cmValue cmGeneratorTarget::GetLanguageStandard(std::string const& lang, + std::string const& config) const { BTs<std::string> const* languageStandard = this->GetLanguageStandardProperty(lang, config); if (languageStandard) { - return cmProp(languageStandard->Value); + return cmValue(languageStandard->Value); } return nullptr; } -cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( +cmValue cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( std::string const& lang, const char* suffix) const { - cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix)); + cmValue propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix)); if (!propertyValue) { // Check if we should use the value set by another language. if (lang == "OBJC") { @@ -975,7 +975,7 @@ cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport( return propertyValue; } -cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const +cmValue cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const { return this->GetPropertyWithPairedLanguageSupport(lang, "_EXTENSIONS"); } @@ -1170,7 +1170,7 @@ const std::string& cmGeneratorTarget::GetLocationForBuild() const // Now handle the deprecated build-time configuration location. std::string const noConfig; location = this->GetDirectory(noConfig); - cmProp cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); + cmValue cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); if (cfgid && (*cfgid != ".")) { location += "/"; location += *cfgid; @@ -1330,7 +1330,7 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( cmGeneratorTarget const* headTarget = context->HeadTarget ? context->HeadTarget : this; - if (cmProp p = this->GetProperty(prop)) { + if (cmValue p = this->GetProperty(prop)) { result = cmGeneratorExpressionNode::EvaluateDependentExpression( *p, context->LG, context, headTarget, &dagChecker, this); } @@ -1453,7 +1453,7 @@ void AddLangSpecificImplicitIncludeDirectories( auto* lg = dependency->GetLocalGenerator(); EvaluatedTargetPropertyEntry entry{ library, library.Backtrace }; - if (cmProp val = dependency->GetProperty(propertyName)) { + if (cmValue val = dependency->GetProperty(propertyName)) { entry.Values.emplace_back(*val); } else { if (mode == IncludeDirectoryFallBack::BINARY) { @@ -1985,12 +1985,12 @@ std::string cmGeneratorTarget::GetCompilePDBName( // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(config); std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper); - cmProp config_name = this->GetProperty(configProp); + cmValue config_name = this->GetProperty(configProp); if (cmNonempty(config_name)) { return prefix + *config_name + ".pdb"; } - cmProp name = this->GetProperty("COMPILE_PDB_NAME"); + cmValue name = this->GetProperty("COMPILE_PDB_NAME"); if (cmNonempty(name)) { return prefix + *name + ".pdb"; } @@ -2135,11 +2135,11 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const if (!ll.empty()) { std::string sepVar = cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP"); - cmProp sep = this->Makefile->GetDefinition(sepVar); + cmValue sep = this->Makefile->GetDefinition(sepVar); if (cmNonempty(sep)) { // TODO: Add binary format check to ABI detection and get rid of // CMAKE_EXECUTABLE_FORMAT. - if (cmProp fmt = + if (cmValue fmt = this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) { if (*fmt == "ELF") { return true; @@ -2192,7 +2192,7 @@ bool cmGeneratorTarget::DetermineHasMacOSXRpathInstallNameDir( if (this->GetType() != cmStateEnums::SHARED_LIBRARY) { return false; } - cmProp install_name = this->GetProperty("INSTALL_NAME_DIR"); + cmValue install_name = this->GetProperty("INSTALL_NAME_DIR"); bool use_install_name = this->MacOSXUseInstallNameDir(); if (install_name && use_install_name && *install_name == "@rpath") { install_name_is_rpath = true; @@ -2250,7 +2250,7 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const return false; } - cmProp macosx_rpath_str = this->GetProperty("MACOSX_RPATH"); + cmValue macosx_rpath_str = this->GetProperty("MACOSX_RPATH"); if (macosx_rpath_str) { return this->GetPropertyAsBool("MACOSX_RPATH"); } @@ -2267,7 +2267,7 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const bool cmGeneratorTarget::MacOSXUseInstallNameDir() const { - cmProp build_with_install_name = + cmValue build_with_install_name = this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR"); if (build_with_install_name) { return cmIsOn(*build_with_install_name); @@ -2360,7 +2360,7 @@ std::string cmGeneratorTarget::GetAppBundleDirectory( { std::string fpath = cmStrCat( this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); - cmProp ext = this->GetProperty("BUNDLE_EXTENSION"); + cmValue ext = this->GetProperty("BUNDLE_EXTENSION"); fpath += (ext ? *ext : "app"); if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleEmbedded()) { @@ -2390,7 +2390,7 @@ std::string cmGeneratorTarget::GetCFBundleDirectory( std::string fpath = cmStrCat( this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); std::string ext; - if (cmProp p = this->GetProperty("BUNDLE_EXTENSION")) { + if (cmValue p = this->GetProperty("BUNDLE_EXTENSION")) { ext = *p; } else { if (this->IsXCTestOnApple()) { @@ -2415,7 +2415,7 @@ std::string cmGeneratorTarget::GetFrameworkDirectory( { std::string fpath = cmStrCat( this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); - cmProp ext = this->GetProperty("BUNDLE_EXTENSION"); + cmValue ext = this->GetProperty("BUNDLE_EXTENSION"); fpath += (ext ? *ext : "framework"); if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleEmbedded()) { @@ -2467,7 +2467,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree( { if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { std::string dir; - cmProp install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); + cmValue install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (cmNonempty(install_name_dir)) { @@ -2516,7 +2516,7 @@ const std::string* cmGeneratorTarget::GetExportMacro() const if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->GetType() == cmStateEnums::MODULE_LIBRARY || this->IsExecutableWithExports()) { - if (cmProp custom_export_name = this->GetProperty("DEFINE_SYMBOL")) { + if (cmValue custom_export_name = this->GetProperty("DEFINE_SYMBOL")) { this->ExportMacro = *custom_export_name; } else { std::string in = cmStrCat(this->GetName(), "_EXPORTS"); @@ -2814,7 +2814,7 @@ std::string cmGeneratorTarget::GetEffectiveFolderName() const return effectiveFolder; } - cmProp targetFolder = this->GetProperty("FOLDER"); + cmValue targetFolder = this->GetProperty("FOLDER"); if (targetFolder) { effectiveFolder += *targetFolder; } @@ -3042,7 +3042,7 @@ void cmTargetTraceDependencies::Trace() this->CurrentEntry = &this->GeneratorTarget->SourceDepends[sf]; // Queue dependencies added explicitly by the user. - if (cmProp additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) { + if (cmValue additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> objDeps = cmExpandedList(*additionalDeps); for (std::string& objDep : objDeps) { if (cmSystemTools::FileIsFullPath(objDep)) { @@ -3240,7 +3240,7 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, if (!this->Makefile->IsOn("APPLE")) { return; } - cmProp archs = nullptr; + cmValue archs = nullptr; if (!config.empty()) { std::string defVarName = cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config)); @@ -3260,7 +3260,7 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags, cmSourceFile const& sf) const { - cmProp lang = sf.GetProperty("LANGUAGE"); + cmValue lang = sf.GetProperty("LANGUAGE"); if (!lang) { return; } @@ -3641,7 +3641,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( // If this target has ISPC sources make sure to add the header // directory to other compilation units if (cm::contains(this->GetAllConfigCompileLanguages(), "ISPC")) { - if (cmProp val = this->GetProperty(propertyName)) { + if (cmValue val = this->GetProperty(propertyName)) { includes.emplace_back(*val); } else { includes.emplace_back(this->GetObjectDirectory(config)); @@ -3971,7 +3971,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( if (!config.empty()) { std::string configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); - cmProp configProp = this->GetProperty(configPropName); + cmValue configProp = this->GetProperty(configPropName); if (configProp) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) { case cmPolicies::WARN: { @@ -4046,7 +4046,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, return std::string(); } const cmGeneratorTarget* generatorTarget = this; - cmProp pchReuseFrom = + cmValue pchReuseFrom = generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); const auto inserted = @@ -4087,8 +4087,10 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, const std::string filename_tmp = cmStrCat(filename, ".tmp"); if (!pchReuseFrom) { - cmProp pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); - cmProp pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); + cmValue pchPrologue = + this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); + cmValue pchEpilogue = + this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); std::string firstHeaderOnDisk; { @@ -4159,7 +4161,7 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, std::string& filename = inserted.first->second; const cmGeneratorTarget* generatorTarget = this; - cmProp pchReuseFrom = + cmValue pchReuseFrom = generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); if (pchReuseFrom) { generatorTarget = @@ -4257,7 +4259,7 @@ std::string cmGeneratorTarget::GetPchFile(const std::string& config, }; cmGeneratorTarget* generatorTarget = this; - cmProp pchReuseFrom = + cmValue pchReuseFrom = generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); if (pchReuseFrom) { generatorTarget = @@ -4553,7 +4555,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( nullptr, nullptr); EvaluatedTargetPropertyEntries entries; - if (cmProp linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { + if (cmValue linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { std::vector<std::string> options = cmExpandedList(*linkOptions); for (const auto& option : options) { std::unique_ptr<TargetPropertyEntry> entry = @@ -4704,7 +4706,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( nullptr); EvaluatedTargetPropertyEntries entries; - if (cmProp linkDepends = this->GetProperty("LINK_DEPENDS")) { + if (cmValue linkDepends = this->GetProperty("LINK_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(*linkDepends); for (const auto& depend : depends) { std::unique_ptr<TargetPropertyEntry> entry = @@ -4785,7 +4787,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const } std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang); - cmProp currentLanguageStandard = this->GetLanguageStandard(lang, config); + cmValue currentLanguageStandard = this->GetLanguageStandard(lang, config); std::string newRequiredStandard; if (!standardResolver.GetNewRequiredStandard( @@ -4825,7 +4827,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures( this->LanguageStandardMap[key] = *standardToCopy; generatorTargetLanguageStandard = &this->LanguageStandardMap[key]; } else { - cmProp defaultStandard = this->Makefile->GetDefinition( + cmValue defaultStandard = this->Makefile->GetDefinition( cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT")); if (defaultStandard) { this->LanguageStandardMap[key] = BTs<std::string>(*defaultStandard); @@ -4928,8 +4930,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames( } // Check for library version properties. - cmProp version = this->GetProperty("VERSION"); - cmProp soversion = this->GetProperty("SOVERSION"); + cmValue version = this->GetProperty("VERSION"); + cmValue soversion = this->GetProperty("SOVERSION"); if (!this->HasSOName(config) || this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") || this->IsFrameworkOnApple()) { @@ -5007,10 +5009,10 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames( // This versioning is supported only for executables and then only // when the platform supports symbolic links. #if defined(_WIN32) && !defined(__CYGWIN__) - cmProp version; + cmValue version; #else // Check for executable version properties. - cmProp version = this->GetProperty("VERSION"); + cmValue version = this->GetProperty("VERSION"); if (this->GetType() != cmStateEnums::EXECUTABLE || this->Makefile->IsOn("XCODE")) { version = nullptr; @@ -5104,8 +5106,8 @@ void cmGeneratorTarget::GetFullNameInternal( // retrieve prefix and suffix std::string ll = this->GetLinkerLanguage(config); - cmProp targetPrefix = this->GetFilePrefixInternal(config, artifact, ll); - cmProp targetSuffix = this->GetFileSuffixInternal(config, artifact, ll); + cmValue targetPrefix = this->GetFilePrefixInternal(config, artifact, ll); + cmValue targetSuffix = this->GetFileSuffixInternal(config, artifact, ll); // The implib option is only allowed for shared libraries, module // libraries, and executables. @@ -5123,13 +5125,13 @@ void cmGeneratorTarget::GetFullNameInternal( if (this->IsFrameworkOnApple()) { fw_prefix = cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/'); - targetPrefix = cmProp(fw_prefix); + targetPrefix = cmValue(fw_prefix); targetSuffix = nullptr; } if (this->IsCFBundleOnApple()) { fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/'); - targetPrefix = cmProp(fw_prefix); + targetPrefix = cmValue(fw_prefix); targetSuffix = nullptr; } @@ -5145,13 +5147,13 @@ void cmGeneratorTarget::GetFullNameInternal( // EXECUTABLE_SUFFIX attribute. if (this->IsFrameworkOnApple() && this->GetGlobalGenerator()->GetName() == "Xcode") { - targetSuffix = cmProp(configPostfix); + targetSuffix = cmValue(configPostfix); } else { outBase += configPostfix; } // Name shared libraries with their version number on some platforms. - if (cmProp soversion = this->GetProperty("SOVERSION")) { + if (cmValue soversion = this->GetProperty("SOVERSION")) { if (this->GetType() == cmStateEnums::SHARED_LIBRARY && !isImportedLibraryArtifact && this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) { @@ -5187,7 +5189,7 @@ std::string cmGeneratorTarget::GetPDBOutputName( props.emplace_back("PDB_NAME"); for (std::string const& p : props) { - if (cmProp outName = this->GetProperty(p)) { + if (cmValue outName = this->GetProperty(p)) { base = *outName; break; } @@ -5214,7 +5216,7 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const props.emplace_back("PDB_NAME"); for (std::string const& p : props) { - if (cmProp outName = this->GetProperty(p)) { + if (cmValue outName = this->GetProperty(p)) { base = *outName; break; } @@ -5297,7 +5299,7 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const } else { // Handle the MACOSX_PACKAGE_LOCATION property on source files that // were not listed in one of the other lists. - if (cmProp location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) { + if (cmValue location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) { flags.MacFolder = location->c_str(); const bool stripResources = this->GlobalGenerator->ShouldStripResourcePath(this->Makefile); @@ -5327,7 +5329,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const this->SourceFileFlagsConstructed = true; // Process public headers to mark the source files. - if (cmProp files = this->GetProperty("PUBLIC_HEADER")) { + if (cmValue files = this->GetProperty("PUBLIC_HEADER")) { std::vector<std::string> relFiles = cmExpandedList(*files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { @@ -5340,7 +5342,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process private headers after public headers so that they take // precedence if a file is listed in both. - if (cmProp files = this->GetProperty("PRIVATE_HEADER")) { + if (cmValue files = this->GetProperty("PRIVATE_HEADER")) { std::vector<std::string> relFiles = cmExpandedList(*files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { @@ -5352,7 +5354,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const } // Mark sources listed as resources. - if (cmProp files = this->GetProperty("RESOURCE")) { + if (cmValue files = this->GetProperty("RESOURCE")) { std::vector<std::string> relFiles = cmExpandedList(*files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { @@ -5380,7 +5382,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const this->GetLinkImplementationClosure(config); for (cmGeneratorTarget const* li : deps) { #define CM_READ_COMPATIBLE_INTERFACE(X, x) \ - if (cmProp prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \ + if (cmValue prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \ std::vector<std::string> props; \ cmExpandList(*prop, props); \ compat.Props##x.insert(props.begin(), props.end()); \ @@ -5490,7 +5492,7 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, const std::string& config, CompatibleType t, PropertyType* /*unused*/) { - cmProp prop = dependee->GetProperty(propName); + cmValue prop = dependee->GetProperty(propName); if (!prop) { return; } @@ -5676,7 +5678,7 @@ std::string valueAsString<std::string>(std::string value) return value; } template <> -std::string valueAsString<cmProp>(cmProp value) +std::string valueAsString<cmValue>(cmValue value) { return value ? value : std::string("(unset)"); } @@ -5730,7 +5732,7 @@ bool getTypedProperty<bool>(cmGeneratorTarget const* tgt, return tgt->GetPropertyAsBool(prop); } - cmProp value = tgt->GetProperty(prop); + cmValue value = tgt->GetProperty(prop); return cmIsOn(genexInterpreter->Evaluate(value ? *value : "", prop)); } @@ -5739,7 +5741,7 @@ const char* getTypedProperty<const char*>( cmGeneratorTarget const* tgt, const std::string& prop, cmGeneratorExpressionInterpreter* genexInterpreter) { - cmProp value = tgt->GetProperty(prop); + cmValue value = tgt->GetProperty(prop); if (genexInterpreter == nullptr) { return value.GetCStr(); @@ -5753,7 +5755,7 @@ std::string getTypedProperty<std::string>( cmGeneratorTarget const* tgt, const std::string& prop, cmGeneratorExpressionInterpreter* genexInterpreter) { - cmProp value = tgt->GetProperty(prop); + cmValue value = tgt->GetProperty(prop); if (genexInterpreter == nullptr) { return valueAsString(value); @@ -6130,7 +6132,7 @@ void cmGeneratorTarget::GetTargetVersion(const std::string& property, assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY); - if (cmProp version = this->GetProperty(property)) { + if (cmValue version = this->GetProperty(property)) { // Try to parse the version number and store the results that were // successfully parsed. int parsed_major; @@ -6158,12 +6160,12 @@ std::string cmGeneratorTarget::GetRuntimeLinkLibrary( { // This is activated by the presence of a default selection whether or // not it is overridden by a property. - cmProp runtimeLibraryDefault = this->Makefile->GetDefinition( + cmValue runtimeLibraryDefault = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT")); if (!cmNonempty(runtimeLibraryDefault)) { return std::string(); } - cmProp runtimeLibraryValue = + cmValue runtimeLibraryValue = this->Target->GetProperty(cmStrCat(lang, "_RUNTIME_LIBRARY")); if (!runtimeLibraryValue) { runtimeLibraryValue = runtimeLibraryDefault; @@ -6186,7 +6188,8 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory( bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const { - if (cmProp prop = this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) { + if (cmValue prop = + this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) { return cmIsOn(*prop); } return false; @@ -6197,7 +6200,7 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory( { std::string mod_dir; std::string target_mod_dir; - if (cmProp prop = this->GetProperty("Fortran_MODULE_DIRECTORY")) { + if (cmValue prop = this->GetProperty("Fortran_MODULE_DIRECTORY")) { target_mod_dir = *prop; } else { std::string const& default_mod_dir = @@ -6206,7 +6209,7 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory( target_mod_dir = default_mod_dir; } } - cmProp moddir_flag = + cmValue moddir_flag = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG"); if (!target_mod_dir.empty() && moddir_flag) { // Compute the full path to the module directory. @@ -6289,10 +6292,10 @@ std::string cmGeneratorTarget::GetFrameworkVersion() const { assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY); - if (cmProp fversion = this->GetProperty("FRAMEWORK_VERSION")) { + if (cmValue fversion = this->GetProperty("FRAMEWORK_VERSION")) { return *fversion; } - if (cmProp tversion = this->GetProperty("VERSION")) { + if (cmValue tversion = this->GetProperty("VERSION")) { return *tversion; } return "A"; @@ -6300,7 +6303,7 @@ std::string cmGeneratorTarget::GetFrameworkVersion() const void cmGeneratorTarget::ComputeVersionedName( std::string& vName, std::string const& prefix, std::string const& base, - std::string const& suffix, std::string const& name, cmProp version) const + std::string const& suffix, std::string const& name, cmValue version) const { vName = this->Makefile->IsOn("APPLE") ? (prefix + base) : name; if (version) { @@ -6548,9 +6551,9 @@ void cmGeneratorTarget::ComputeLinkInterface( // How many repetitions are needed if this library has cyclic // dependencies? std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix); - if (cmProp config_reps = this->GetProperty(propName)) { + if (cmValue config_reps = this->GetProperty(propName)) { sscanf(config_reps->c_str(), "%u", &iface.Multiplicity); - } else if (cmProp reps = + } else if (cmValue reps = this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) { sscanf(reps->c_str(), "%u", &iface.Multiplicity); } @@ -6707,14 +6710,14 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config, } // Select an output directory. - if (cmProp config_outdir = this->GetProperty(configProp)) { + if (cmValue config_outdir = this->GetProperty(configProp)) { // Use the user-specified per-configuration output directory. out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator, config, this); // Skip per-configuration subdirectory. conf.clear(); - } else if (cmProp outdir = this->GetProperty(propertyName)) { + } else if (cmValue outdir = this->GetProperty(propertyName)) { // Use the user-specified output directory. out = cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator, config, this); @@ -6777,14 +6780,14 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind, } // Select an output directory. - if (cmProp config_outdir = this->GetProperty(configProp)) { + if (cmValue config_outdir = this->GetProperty(configProp)) { // Use the user-specified per-configuration output directory. out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator, config); // Skip per-configuration subdirectory. conf.clear(); - } else if (cmProp outdir = this->GetProperty(propertyName)) { + } else if (cmValue outdir = this->GetProperty(propertyName)) { // Use the user-specified output directory. out = cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator, config); @@ -6837,7 +6840,7 @@ bool cmGeneratorTarget::GetRPATH(const std::string& config, const std::string& prop, std::string& rpath) const { - cmProp value = this->GetProperty(prop); + cmValue value = this->GetProperty(prop); if (!value) { return false; } @@ -6862,7 +6865,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // An explicit list of interface libraries may be set for shared // libraries and executables that export symbols. - cmProp explicitLibraries = nullptr; + cmValue explicitLibraries = nullptr; std::string linkIfaceProp; bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && this->GetPolicyStatusCMP0022() != cmPolicies::WARN); @@ -6891,7 +6894,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( !this->PolicyWarnedCMP0022) { // Compare the explicitly set old link interface properties to the // preferred new link interface property one and warn if different. - cmProp newExplicitLibraries = + cmValue newExplicitLibraries = this->GetProperty("INTERFACE_LINK_LIBRARIES"); if (newExplicitLibraries && (*newExplicitLibraries != *explicitLibraries)) { @@ -6948,7 +6951,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // preferred new link interface property and warn if different. cmLinkInterface ifaceNew; static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; - if (cmProp newExplicitLibraries = this->GetProperty(newProp)) { + if (cmValue newExplicitLibraries = this->GetProperty(newProp)) { this->ExpandLinkItems(newProp, *newExplicitLibraries, config, headTarget, usage_requirements_only, ifaceNew); } @@ -7016,7 +7019,7 @@ std::vector<ValueType> computeImplicitLanguageTargets( std::string const& runtimeLibrary = currentTarget->GetRuntimeLinkLibrary(lang, config); - if (cmProp runtimeLinkOptions = currentTarget->Makefile->GetDefinition( + if (cmValue runtimeLinkOptions = currentTarget->Makefile->GetDefinition( "CMAKE_" + lang + "_RUNTIME_LIBRARIES_" + runtimeLibrary)) { std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions); result.reserve(libsVec.size()); @@ -7154,8 +7157,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Initialize members. info.NoSOName = false; - cmProp loc = nullptr; - cmProp imp = nullptr; + cmValue loc = nullptr; + cmValue imp = nullptr; std::string suffix; if (!this->Target->GetMappedConfig(desired_config, loc, imp, suffix)) { return; @@ -7164,7 +7167,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the link interface. { std::string linkProp = "INTERFACE_LINK_LIBRARIES"; - cmProp propertyLibs = this->GetProperty(linkProp); + cmValue propertyLibs = this->GetProperty(linkProp); if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { if (!propertyLibs) { @@ -7197,9 +7200,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, info.Location = *loc; } else { std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); - if (cmProp config_location = this->GetProperty(impProp)) { + if (cmValue config_location = this->GetProperty(impProp)) { info.Location = *config_location; - } else if (cmProp location = this->GetProperty("IMPORTED_LOCATION")) { + } else if (cmValue location = this->GetProperty("IMPORTED_LOCATION")) { info.Location = *location; } } @@ -7207,9 +7210,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the soname. if (this->GetType() == cmStateEnums::SHARED_LIBRARY) { std::string soProp = cmStrCat("IMPORTED_SONAME", suffix); - if (cmProp config_soname = this->GetProperty(soProp)) { + if (cmValue config_soname = this->GetProperty(soProp)) { info.SOName = *config_soname; - } else if (cmProp soname = this->GetProperty("IMPORTED_SONAME")) { + } else if (cmValue soname = this->GetProperty("IMPORTED_SONAME")) { info.SOName = *soname; } } @@ -7217,9 +7220,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the "no-soname" mark. if (this->GetType() == cmStateEnums::SHARED_LIBRARY) { std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix); - if (cmProp config_no_soname = this->GetProperty(soProp)) { + if (cmValue config_no_soname = this->GetProperty(soProp)) { info.NoSOName = cmIsOn(*config_no_soname); - } else if (cmProp no_soname = this->GetProperty("IMPORTED_NO_SONAME")) { + } else if (cmValue no_soname = this->GetProperty("IMPORTED_NO_SONAME")) { info.NoSOName = cmIsOn(*no_soname); } } @@ -7230,9 +7233,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); - if (cmProp config_implib = this->GetProperty(impProp)) { + if (cmValue config_implib = this->GetProperty(impProp)) { info.ImportLibrary = *config_implib; - } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) { + } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) { info.ImportLibrary = *implib; } } @@ -7241,9 +7244,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, { std::string linkProp = cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix); - if (cmProp config_libs = this->GetProperty(linkProp)) { + if (cmValue config_libs = this->GetProperty(linkProp)) { info.SharedDeps = *config_libs; - } else if (cmProp libs = + } else if (cmValue libs = this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) { info.SharedDeps = *libs; } @@ -7253,9 +7256,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, if (this->LinkLanguagePropagatesToDependents()) { std::string linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix); - if (cmProp config_libs = this->GetProperty(linkProp)) { + if (cmValue config_libs = this->GetProperty(linkProp)) { info.Languages = *config_libs; - } else if (cmProp libs = + } else if (cmValue libs = this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES")) { info.Languages = *libs; } @@ -7264,9 +7267,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get information if target is managed assembly. { std::string linkProp = "IMPORTED_COMMON_LANGUAGE_RUNTIME"; - if (cmProp pc = this->GetProperty(linkProp + suffix)) { + if (cmValue pc = this->GetProperty(linkProp + suffix)) { info.Managed = this->CheckManagedType(*pc); - } else if (cmProp p = this->GetProperty(linkProp)) { + } else if (cmValue p = this->GetProperty(linkProp)) { info.Managed = this->CheckManagedType(*p); } } @@ -7275,9 +7278,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, if (this->GetType() == cmStateEnums::STATIC_LIBRARY) { std::string linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); - if (cmProp config_reps = this->GetProperty(linkProp)) { + if (cmValue config_reps = this->GetProperty(linkProp)) { sscanf(config_reps->c_str(), "%u", &info.Multiplicity); - } else if (cmProp reps = + } else if (cmValue reps = this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) { sscanf(reps->c_str(), "%u", &info.Multiplicity); } @@ -7456,14 +7459,14 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const bool cmGeneratorTarget::IsDeprecated() const { - cmProp deprecation = this->GetProperty("DEPRECATION"); + cmValue deprecation = this->GetProperty("DEPRECATION"); return cmNonempty(deprecation); } std::string cmGeneratorTarget::GetDeprecation() const { // find DEPRECATION property - if (cmProp deprecation = this->GetProperty("DEPRECATION")) { + if (cmValue deprecation = this->GetProperty("DEPRECATION")) { return *deprecation; } return std::string(); @@ -7534,7 +7537,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const std::set<std::string> languages = this->GetAllConfigCompileLanguages(); // Consider an explicit linker language property, but *not* the // computed linker language that may depend on linked targets. - cmProp linkLang = this->GetProperty("LINKER_LANGUAGE"); + cmValue linkLang = this->GetProperty("LINKER_LANGUAGE"); if (cmNonempty(linkLang)) { languages.insert(*linkLang); } @@ -7943,7 +7946,7 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType( } // Check for explicitly set clr target property. - if (cmProp clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) { + if (cmValue clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) { return this->CheckManagedType(*clr); } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 85b4ea0343b..e9ce9623de6 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -19,8 +19,8 @@ #include "cmLinkItem.h" #include "cmListFileCache.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" +#include "cmValue.h" class cmComputeLinkInformation; class cmCustomCommand; @@ -89,7 +89,7 @@ class cmGeneratorTarget std::vector<std::string> GetPropertyKeys() const; //! Might return a nullptr if the property is not set or invalid - cmProp GetProperty(const std::string& prop) const; + cmValue GetProperty(const std::string& prop) const; //! Always returns a valid pointer std::string const& GetSafeProperty(std::string const& prop) const; bool GetPropertyAsBool(const std::string& prop) const; @@ -163,10 +163,10 @@ class cmGeneratorTarget BTs<std::string> const* GetLanguageStandardProperty( std::string const& lang, std::string const& config) const; - cmProp GetLanguageStandard(std::string const& lang, - std::string const& config) const; + cmValue GetLanguageStandard(std::string const& lang, + std::string const& config) const; - cmProp GetLanguageExtensions(std::string const& lang) const; + cmValue GetLanguageExtensions(std::string const& lang) const; bool GetLanguageStandardRequired(std::string const& lang) const; @@ -187,8 +187,8 @@ class cmGeneratorTarget void ComputeObjectMapping(); - cmProp GetFeature(const std::string& feature, - const std::string& config) const; + cmValue GetFeature(const std::string& feature, + const std::string& config) const; const char* GetLinkPIEProperty(const std::string& config) const; @@ -835,7 +835,7 @@ class cmGeneratorTarget std::string GetFortranModuleDirectory(std::string const& working_dir) const; bool IsFortranBuildingInstrinsicModules() const; - cmProp GetSourcesProperty() const; + cmValue GetSourcesProperty() const; void AddISPCGeneratedHeader(std::string const& header, std::string const& config); @@ -884,12 +884,12 @@ class cmGeneratorTarget bool NeedImportLibraryName(std::string const& config) const; - cmProp GetFilePrefixInternal(std::string const& config, - cmStateEnums::ArtifactType artifact, - const std::string& language = "") const; - cmProp GetFileSuffixInternal(std::string const& config, - cmStateEnums::ArtifactType artifact, - const std::string& language = "") const; + cmValue GetFilePrefixInternal(std::string const& config, + cmStateEnums::ArtifactType artifact, + const std::string& language = "") const; + cmValue GetFileSuffixInternal(std::string const& config, + cmStateEnums::ArtifactType artifact, + const std::string& language = "") const; std::string GetFullNameInternal(const std::string& config, cmStateEnums::ArtifactType artifact) const; @@ -908,7 +908,7 @@ class cmGeneratorTarget void ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, std::string const& suffix, - std::string const& name, cmProp version) const; + std::string const& name, cmValue version) const; struct CompatibleInterfacesBase { @@ -1116,8 +1116,8 @@ class cmGeneratorTarget mutable std::map<std::string, BTs<std::string>> LanguageStandardMap; - cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang, - const char* suffix) const; + cmValue GetPropertyWithPairedLanguageSupport(std::string const& lang, + const char* suffix) const; void ComputeLinkImplementationRuntimeLibraries( const std::string& config, cmOptionalLinkImplementation& impl) const; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index 79cbe443ce2..42bd206f7c4 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -7,9 +7,9 @@ #include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" // cmGetCMakePropertyCommand bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, @@ -24,12 +24,12 @@ bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, std::string output = "NOTFOUND"; if (args[1] == "VARIABLES") { - if (cmProp varsProp = status.GetMakefile().GetProperty("VARIABLES")) { + if (cmValue varsProp = status.GetMakefile().GetProperty("VARIABLES")) { output = *varsProp; } } else if (args[1] == "MACROS") { output.clear(); - if (cmProp macrosProp = status.GetMakefile().GetProperty("MACROS")) { + if (cmValue macrosProp = status.GetMakefile().GetProperty("MACROS")) { output = *macrosProp; } } else if (args[1] == "COMPONENTS") { @@ -37,7 +37,7 @@ bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, status.GetMakefile().GetGlobalGenerator()->GetInstallComponents(); output = cmJoin(*components, ";"); } else { - cmProp prop = nullptr; + cmValue prop = nullptr; if (!args[1].empty()) { prop = status.GetMakefile().GetState()->GetGlobalProperty(args[1]); } diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index d98f95cd0d0..d892cfa756b 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -7,14 +7,14 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { void StoreResult(cmMakefile& makefile, std::string const& variable, const char* prop); void StoreResult(cmMakefile& makefile, std::string const& variable, - cmProp prop); + cmValue prop); } // cmGetDirectoryPropertyCommand @@ -106,7 +106,7 @@ void StoreResult(cmMakefile& makefile, std::string const& variable, makefile.AddDefinition(variable, prop ? prop : ""); } void StoreResult(cmMakefile& makefile, std::string const& variable, - cmProp prop) + cmValue prop) { makefile.AddDefinition(variable, prop); } diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 40e8a05d657..abe7d32a70d 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -4,10 +4,10 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // cmGetFilenameComponentCommand bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, @@ -22,7 +22,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, // Check and see if the value has been stored in the cache // already, if so use that value if (args.size() >= 4 && args.back() == "CACHE") { - cmProp cacheValue = status.GetMakefile().GetDefinition(args.front()); + cmValue cacheValue = status.GetMakefile().GetDefinition(args.front()); if (cacheValue && !cmIsNOTFOUND(*cacheValue)) { return true; } diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 5f2007566f1..162860a0005 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -20,6 +20,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTest.h" +#include "cmValue.h" #include "cmake.h" class cmMessenger; @@ -272,7 +273,7 @@ template <> bool StoreResult(OutType infoType, cmMakefile& makefile, const std::string& variable, std::nullptr_t value) { - return StoreResult(infoType, makefile, variable, cmProp(value)); + return StoreResult(infoType, makefile, variable, cmValue(value)); } bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, @@ -366,7 +367,7 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, } cmListFileBacktrace bt = status.GetMakefile().GetBacktrace(); cmMessenger* messenger = status.GetMakefile().GetMessenger(); - cmProp prop = target->GetComputedProperty(propertyName, messenger, bt); + cmValue prop = target->GetComputedProperty(propertyName, messenger, bt); if (!prop) { prop = target->GetProperty(propertyName); } @@ -445,7 +446,7 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, return false; } - cmProp value = nullptr; + cmValue value = nullptr; if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) { value = status.GetMakefile().GetState()->GetCacheEntryProperty( name, propertyName); diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index 5301b6618b6..40ae1126cf4 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -4,9 +4,9 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSetPropertyCommand.h" #include "cmSourceFile.h" +#include "cmValue.h" bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -58,7 +58,7 @@ bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args, } if (sf) { - cmProp prop = nullptr; + cmValue prop = nullptr; if (!args[property_arg_index].empty()) { prop = sf->GetPropertyForUser(args[property_arg_index]); } diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 78a17d2c3ec..9c5a2fc36ad 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -10,8 +10,8 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmTarget.h" +#include "cmValue.h" class cmMessenger; @@ -42,7 +42,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, } } } else if (!args[2].empty()) { - cmProp prop_cstr = nullptr; + cmValue prop_cstr = nullptr; cmListFileBacktrace bt = mf.GetBacktrace(); cmMessenger* messenger = mf.GetMessenger(); prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt); diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx index 077353e3f09..a4ac9f686b5 100644 --- a/Source/cmGetTestPropertyCommand.cxx +++ b/Source/cmGetTestPropertyCommand.cxx @@ -4,8 +4,8 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmTest.h" +#include "cmValue.h" bool cmGetTestPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -20,7 +20,7 @@ bool cmGetTestPropertyCommand(std::vector<std::string> const& args, cmMakefile& mf = status.GetMakefile(); cmTest* test = mf.GetTest(testName); if (test) { - cmProp prop; + cmValue prop; if (!args[1].empty()) { prop = test->GetProperty(args[1]); } diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 12fd9c4526b..47cefaeaa4f 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -19,7 +19,6 @@ #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmSourceGroup.h" @@ -29,6 +28,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) : GeneratorTarget(target) @@ -43,7 +43,7 @@ cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) #endif { // Store the configuration name that is being used - if (cmProp config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { + if (cmValue config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { // Use the build type given by the user. this->ConfigName = *config; } else { @@ -453,7 +453,7 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty( std::ostream& fout, const cmSourceFile* sf, std::string const& propName, std::string const& propFlag) { - cmProp prop = sf->GetProperty(propName); + cmValue prop = sf->GetProperty(propName); if (prop) { std::vector<std::string> list = cmExpandedList(*prop); for (const std::string& p : list) { @@ -705,7 +705,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandLine( void cmGhsMultiTargetGenerator::WriteObjectLangOverride( std::ostream& fout, const cmSourceFile* sourceFile) { - cmProp rawLangProp = sourceFile->GetProperty("LANGUAGE"); + cmValue rawLangProp = sourceFile->GetProperty("LANGUAGE"); if (rawLangProp) { std::string sourceLangProp(*rawLangProp); std::string const& extension = sourceFile->GetExtension(); @@ -717,7 +717,7 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride( bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp() { - if (cmProp p = this->GeneratorTarget->GetProperty("ghs_integrity_app")) { + if (cmValue p = this->GeneratorTarget->GetProperty("ghs_integrity_app")) { return cmIsOn(*p); } std::vector<cmSourceFile*> sources; diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 24c8944fe9e..31ff52f09c2 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -11,12 +11,12 @@ #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm) @@ -48,7 +48,7 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const DirectoryTarget::Target t; t.GT = gt.get(); const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL"); - if (cmProp exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) { + if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) { for (const std::string& config : configs) { cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config, gt.get()); @@ -122,6 +122,6 @@ std::string cmGlobalCommonGenerator::GetEditCacheCommand() const cmStateEnums::INTERNAL); } } - cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); + cmValue edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); return edit_cmd ? *edit_cmd : std::string(); } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 1c3d2c2e528..981308eb64d 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -44,12 +44,12 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmWorkingDirectory.h" #include "cmake.h" @@ -199,7 +199,7 @@ std::string cmGlobalGenerator::SelectMakeProgram( { std::string makeProgram = inMakeProgram; if (cmIsOff(makeProgram)) { - cmProp makeProgramCSTR = + cmValue makeProgramCSTR = this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); if (cmIsOff(makeProgramCSTR)) { makeProgram = makeDefault; @@ -235,14 +235,14 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) { return; } - cmProp cname = + cmValue cname = this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp); // Split compiler from arguments std::vector<std::string> cnameArgVec; if (cname && !cname->empty()) { cmExpandList(*cname, cnameArgVec); - cname = cmProp(cnameArgVec.front()); + cname = cmValue(cnameArgVec.front()); } std::string changeVars; @@ -258,7 +258,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, cmSystemTools::ConvertToUnixSlashes(cnameString); cmSystemTools::ConvertToUnixSlashes(pathString); if (cnameString != pathString) { - cmProp cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty( + cmValue cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "__CMAKE_DELETE_CACHE_CHANGE_VARS_"); if (cvars) { changeVars += *cvars; @@ -801,7 +801,7 @@ void cmGlobalGenerator::EnableLanguage( std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER"); std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR"); std::ostringstream noCompiler; - cmProp compilerFile = mf->GetDefinition(compilerName); + cmValue compilerFile = mf->GetDefinition(compilerName); if (!cmNonempty(compilerFile) || cmIsNOTFOUND(*compilerFile)) { /* clang-format off */ noCompiler << @@ -922,7 +922,7 @@ void cmGlobalGenerator::EnableLanguage( void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os, std::string const& lang, - cmProp envVar) const + cmValue envVar) const { // Subclasses override this method if they do not support this advice. os << "Tell CMake where to find the compiler by setting "; @@ -1117,7 +1117,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, } std::string linkerPrefVar = "CMAKE_" + l + "_LINKER_PREFERENCE"; - cmProp linkerPref = mf->GetDefinition(linkerPrefVar); + cmValue linkerPref = mf->GetDefinition(linkerPrefVar); int preference = 0; if (cmNonempty(linkerPref)) { if (sscanf(linkerPref->c_str(), "%d", &preference) != 1) { @@ -1143,7 +1143,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, this->LanguageToLinkerPreference[l] = preference; std::string outputExtensionVar = "CMAKE_" + l + "_OUTPUT_EXTENSION"; - if (cmProp p = mf->GetDefinition(outputExtensionVar)) { + if (cmValue p = mf->GetDefinition(outputExtensionVar)) { std::string outputExtension = *p; this->LanguageToOutputExtension[l] = outputExtension; this->OutputExtensions[outputExtension] = outputExtension; @@ -1179,7 +1179,7 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, } } -cmProp cmGlobalGenerator::GetGlobalSetting(std::string const& name) const +cmValue cmGlobalGenerator::GetGlobalSetting(std::string const& name) const { assert(!this->Makefiles.empty()); return this->Makefiles[0]->GetDefinition(name); @@ -1746,7 +1746,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() for (std::string const& c : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c)); - if (cmProp val = mf->GetProperty(defPropName)) { + if (cmValue val = mf->GetProperty(defPropName)) { t->AppendProperty(defPropName, *val); } } @@ -1860,7 +1860,7 @@ void cmGlobalGenerator::CheckTargetProperties() } } std::vector<std::string> incs; - cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); + cmValue incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); if (!incDirProp) { continue; } @@ -2124,7 +2124,7 @@ void cmGlobalGenerator::AddMakefile(std::unique_ptr<cmMakefile> mf) // update progress // estimate how many lg there will be - cmProp numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue( + cmValue numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue( "CMAKE_NUMBER_OF_MAKEFILES"); if (!numGenC) { @@ -2183,7 +2183,7 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen, { this->SetConfiguredFilesPath(gen); this->TryCompileOuterMakefile = mf; - cmProp make = + cmValue make = gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); this->GetCMakeInstance()->AddCacheEntry( "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH); @@ -2246,7 +2246,7 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root, } cmMakefile* mf = root->GetMakefile(); const std::string EXCLUDE_FROM_ALL = "EXCLUDE_FROM_ALL"; - if (cmProp exclude = target->GetProperty(EXCLUDE_FROM_ALL)) { + if (cmValue exclude = target->GetProperty(EXCLUDE_FROM_ALL)) { // Expand the property value per configuration. unsigned int trueCount = 0; unsigned int falseCount = 0; @@ -2540,7 +2540,7 @@ void cmGlobalGenerator::AddGlobalTarget_Package( if (this->GetPreinstallTargetName()) { gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { - cmProp noPackageAll = + cmValue noPackageAll = mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY"); if (cmIsOff(noPackageAll)) { gti.Depends.emplace_back(this->GetAllTargetName()); @@ -2721,7 +2721,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( if (this->GetPreinstallTargetName()) { gti.Depends.emplace_back(this->GetPreinstallTargetName()); } else { - cmProp noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); + cmValue noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); if (cmIsOff(noall)) { gti.Depends.emplace_back(this->GetAllTargetName()); } @@ -2787,7 +2787,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const { - cmProp prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty( + cmValue prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "PREDEFINED_TARGETS_FOLDER"); if (prop) { @@ -2799,7 +2799,7 @@ std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const bool cmGlobalGenerator::UseFolderProperty() const { - cmProp prop = + cmValue prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS"); // If this property is defined, let the setter turn this on or off... @@ -3150,10 +3150,10 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) #ifndef CMAKE_BOOTSTRAP // Check whether labels are enabled for this target. - cmProp targetLabels = target->GetProperty("LABELS"); - cmProp directoryLabels = + cmValue targetLabels = target->GetProperty("LABELS"); + cmValue directoryLabels = target->Target->GetMakefile()->GetProperty("LABELS"); - cmProp cmakeDirectoryLabels = + cmValue cmakeDirectoryLabels = target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS"); if (targetLabels || directoryLabels || cmakeDirectoryLabels) { Json::Value lj_root(Json::objectValue); @@ -3221,7 +3221,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) std::string const& sfp = sf->ResolveFullPath(); fout << sfp << "\n"; lj_source["file"] = sfp; - if (cmProp svalue = sf->GetProperty("LABELS")) { + if (cmValue svalue = sf->GetProperty("LABELS")) { labels.clear(); Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue; cmExpandList(*svalue, labels); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 49a1a26cf08..23c5700de31 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -23,13 +23,13 @@ #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmExportSet.h" -#include "cmProperty.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" #include "cmTransformDepfile.h" +#include "cmValue.h" #if !defined(CMAKE_BOOTSTRAP) # include <cm3p/json/value.h> @@ -309,7 +309,7 @@ class cmGlobalGenerator cmExportSetMap& GetExportSets() { return this->ExportSets; } - cmProp GetGlobalSetting(std::string const& name) const; + cmValue GetGlobalSetting(std::string const& name) const; bool GlobalSettingIsOn(std::string const& name) const; std::string GetSafeGlobalSetting(std::string const& name) const; @@ -550,7 +550,7 @@ class cmGlobalGenerator virtual bool CheckLanguages(std::vector<std::string> const& languages, cmMakefile* mf) const; virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - cmProp envVar) const; + cmValue envVar) const; virtual bool ComputeTargetDepends(); diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index b81f82ec086..b1c0488d43b 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -18,11 +18,11 @@ #include "cmLocalGenerator.h" #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -99,7 +99,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, /* set the build tool to use */ std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") + DEFAULT_BUILD_PROGRAM); - cmProp prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); + cmValue prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM"); /* check if the toolset changed from last generate */ if (prevTool && (gbuild != *prevTool)) { @@ -215,7 +215,7 @@ bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/) void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts) { - cmProp ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); + cmValue ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT"); if (cmNonempty(ghsRoot)) { tsd = *ghsRoot; @@ -333,7 +333,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, fout << "# Top Level Project File\n"; // Specify BSP option if supplied by user - cmProp bspName = + cmValue bspName = this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); if (!cmIsOff(bspName)) { fout << " -bsp " << *bspName << '\n'; @@ -342,7 +342,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, // Specify OS DIR if supplied by user // -- not all platforms require this entry in the project file if (!cmIsOff(this->OsDir)) { - cmProp osDirOption = + cmValue osDirOption = this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION"); std::replace(this->OsDir.begin(), this->OsDir.end(), '\\', '/'); fout << " "; @@ -377,8 +377,8 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine( std::ostream& fout, cmGeneratorTarget const* target, std::string& rootBinaryDir) { - cmProp projName = target->GetProperty("GENERATOR_FILE_NAME"); - cmProp projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); + cmValue projName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); if (projName && projType) { cmLocalGenerator* lg = target->GetLocalGenerator(); std::string dir = lg->GetCurrentBinaryDirectory(); @@ -563,7 +563,7 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand( { GeneratedMakeCommand makeCommand = {}; std::string gbuild; - if (cmProp gbuildCached = + if (cmValue gbuildCached = this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM")) { gbuild = *gbuildCached; } @@ -616,7 +616,7 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, cmLocalGenerator* root) { fout << "macro PROJ_NAME=" << root->GetProjectName() << '\n'; - cmProp ghsGpjMacros = + cmValue ghsGpjMacros = this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS"); if (ghsGpjMacros) { std::vector<std::string> expandedList = cmExpandedList(*ghsGpjMacros); @@ -631,15 +631,15 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( { /* set primary target */ std::string tgt; - cmProp t = + cmValue t = this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET"); if (cmNonempty(t)) { tgt = *t; this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET"); } else { - cmProp a = + cmValue a = this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM"); - cmProp p = + cmValue p = this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM"); tgt = cmStrCat((a ? *a : ""), '_', (p ? *p : ""), ".tgt"); } @@ -652,7 +652,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( << "/CMakeFiles/custom_target.bod" << '\n'; /* clang-format on */ - cmProp const customization = + cmValue const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); if (cmNonempty(customization)) { fout << "customization=" diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index 0d474e50d1e..40deebb049d 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -41,7 +41,7 @@ void cmGlobalJOMMakefileGenerator::GetDocumentation( void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os, std::string const& lang, - cmProp envVar) const + cmValue envVar) const { if (lang == "CXX" || lang == "C") { /* clang-format off */ diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index cc581df166a..58860dd6421 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -50,5 +50,5 @@ class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3 private: void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - cmProp envVar) const override; + cmValue envVar) const override; }; diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 2bc668c3c8c..a038f871e73 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -42,7 +42,7 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf) if (!this->cmGlobalGenerator::FindMakeProgram(mf)) { return false; } - if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { + if (cmValue nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { std::vector<std::string> command{ *nmakeCommand, "-?" }; std::string out; std::string err; @@ -81,7 +81,7 @@ void cmGlobalNMakeMakefileGenerator::GetDocumentation( } void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice( - std::ostream& os, std::string const& lang, cmProp envVar) const + std::ostream& os, std::string const& lang, cmValue envVar) const { if (lang == "CXX" || lang == "C") { /* clang-format off */ diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index a48a55e95e7..4f202b5a470 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -61,5 +61,5 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 void CheckNMakeFeatures(); void PrintCompilerAdvice(std::ostream& os, std::string const& lang, - cmProp envVar) const override; + cmValue envVar) const override; }; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 768c0457835..5c3198e7302 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -35,7 +35,6 @@ #include "cmMessageType.h" #include "cmNinjaLinkLineComputer.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmScanDepFormat.h" #include "cmState.h" @@ -46,6 +45,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -694,7 +694,7 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) if (!this->cmGlobalGenerator::FindMakeProgram(mf)) { return false; } - if (cmProp ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { + if (cmValue ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) { this->NinjaCommand = *ninjaCommand; std::vector<std::string> command; command.push_back(this->NinjaCommand); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index d9f94a12ce8..0556540913d 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -20,12 +20,12 @@ #include "cmMakefile.h" #include "cmMakefileTargetGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTargetDepend.h" +#include "cmValue.h" #include "cmake.h" cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm) @@ -684,7 +684,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } bool targetMessages = true; - if (cmProp tgtMsg = + if (cmValue tgtMsg = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "TARGET_MESSAGES")) { targetMessages = cmIsOn(*tgtMsg); diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index b46f1b9b0fa..ff1642f8b63 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -239,7 +239,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion( { // if the given value is set, it can either be OFF/FALSE or a valid SDK // string - if (cmProp value = mf->GetDefinition( + if (cmValue value = mf->GetDefinition( "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM")) { // If the value is some off/false value, then there is NO maximum set. diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 21ea7e6c2b2..50975ffdf42 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -102,7 +102,7 @@ void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout, ext = ".csproj"; project = "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \""; } - cmProp targetExt = t->GetProperty("GENERATOR_FILE_NAME_EXT"); + cmValue targetExt = t->GetProperty("GENERATOR_FILE_NAME_EXT"); if (targetExt) { ext = *targetExt; } @@ -157,7 +157,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteExternalProject( std::ostream& fout, const std::string& name, const std::string& location, - cmProp typeGuid, const std::set<BT<std::pair<std::string, bool>>>& depends) + cmValue typeGuid, const std::set<BT<std::pair<std::string, bool>>>& depends) { fout << "Project(\"{" << (typeGuid ? typeGuid @@ -198,8 +198,8 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations( std::vector<std::string> mapConfig; const char* dstConfig = i.c_str(); if (target.GetProperty("EXTERNAL_MSPROJECT")) { - if (cmProp m = target.GetProperty("MAP_IMPORTED_CONFIG_" + - cmSystemTools::UpperCase(i))) { + if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" + + cmSystemTools::UpperCase(i))) { cmExpandList(*m, mapConfig); if (!mapConfig.empty()) { dstConfig = mapConfig[0].c_str(); diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 30ebf08e01f..cb3b8c13b56 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -33,7 +33,7 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator const std::string& platformMapping = "") override; void WriteExternalProject( std::ostream& fout, const std::string& name, const std::string& path, - cmProp typeGuid, + cmValue typeGuid, const std::set<BT<std::pair<std::string, bool>>>& depends) override; // Folders are not supported by VS 7.1. diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 2a142aef238..9db654f7b13 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -299,7 +299,7 @@ void cmGlobalVisualStudio7Generator::Generate() if (this->Version == VS10 && !this->CMakeInstance->GetIsInTryCompile()) { std::string cmakeWarnVS10; - if (cmProp cached = this->CMakeInstance->GetState()->GetCacheEntryValue( + if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue( "CMAKE_WARN_VS10")) { this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS10"); cmakeWarnVS10 = *cached; @@ -354,17 +354,17 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( if (!target->IsInBuildSystem()) { continue; } - cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT"); + cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT"); if (expath) { std::set<std::string> allConfigurations(configs.begin(), configs.end()); - cmProp mapping = target->GetProperty("VS_PLATFORM_MAPPING"); + cmValue mapping = target->GetProperty("VS_PLATFORM_MAPPING"); this->WriteProjectConfigurations(fout, target->GetName(), *target, configs, allConfigurations, mapping ? *mapping : ""); } else { const std::set<std::string>& configsPartOfDefaultBuild = this->IsPartOfDefaultBuild(configs, projectTargets, target); - cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { this->WriteProjectConfigurations(fout, *vcprojName, *target, configs, configsPartOfDefaultBuild); @@ -386,7 +386,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( bool written = false; // handle external vc project files - cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT"); + cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT"); if (expath) { std::string project = target->GetName(); std::string location = *expath; @@ -396,7 +396,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( target->GetUtilities()); written = true; } else { - cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { cmLocalGenerator* lg = target->GetLocalGenerator(); std::string dir = lg->GetCurrentBinaryDirectory(); @@ -449,7 +449,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends( if (!target->IsInBuildSystem()) { continue; } - cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { std::string dir = target->GetLocalGenerator()->GetCurrentSourceDirectory(); @@ -537,7 +537,7 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( extensibilityAddInsOverridden = true; } fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; - cmProp p = root->GetMakefile()->GetProperty(it); + cmValue p = root->GetMakefile()->GetProperty(it); std::vector<std::string> keyValuePairs = cmExpandedList(p ? *p : ""); for (std::string const& itPair : keyValuePairs) { const std::string::size_type posEqual = itPair.find('='); @@ -636,7 +636,7 @@ std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend( std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name) { std::string const& guidStoreName = name + "_GUID_CMAKE"; - if (cmProp storedGUID = + if (cmValue storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName)) { return *storedGUID; } @@ -686,7 +686,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( "CMAKE_VS_INCLUDE_" + t + "_TO_DEFAULT_BUILD"; // inspect CMAKE_VS_INCLUDE_<t>_TO_DEFAULT_BUILD properties for (std::string const& i : configs) { - cmProp propertyValue = + cmValue propertyValue = target->Target->GetMakefile()->GetDefinition(propertyName); if (propertyValue && cmIsOn(cmGeneratorExpression::Evaluate( diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 1e34792ed3a..8e762cf90f1 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -6,7 +6,7 @@ #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" -#include "cmProperty.h" +#include "cmValue.h" class cmTarget; struct cmIDEFlagTable; @@ -143,7 +143,7 @@ class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator virtual void WriteExternalProject( std::ostream& fout, const std::string& name, const std::string& path, - cmProp typeGuid, + cmValue typeGuid, const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0; std::string ConvertToSolutionPath(const std::string& path); diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index b19212e471f..34bdc1c6378 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -245,8 +245,8 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( std::vector<std::string> mapConfig; const char* dstConfig = i.c_str(); if (target.GetProperty("EXTERNAL_MSPROJECT")) { - if (cmProp m = target.GetProperty("MAP_IMPORTED_CONFIG_" + - cmSystemTools::UpperCase(i))) { + if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" + + cmSystemTools::UpperCase(i))) { cmExpandList(*m, mapConfig); if (!mapConfig.empty()) { dstConfig = mapConfig[0].c_str(); @@ -287,14 +287,14 @@ bool cmGlobalVisualStudio8Generator::NeedsDeploy( return false; } - if (cmProp prop = target.GetProperty("VS_SOLUTION_DEPLOY")) { + if (cmValue prop = target.GetProperty("VS_SOLUTION_DEPLOY")) { // If set, it dictates behavior return cmIsOn( cmGeneratorExpression::Evaluate(*prop, target.LocalGenerator, config)); } // To be deprecated, disable deployment even if target supports it. - if (cmProp prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) { + if (cmValue prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) { if (cmIsOn(cmGeneratorExpression::Evaluate(*prop, target.LocalGenerator, config))) { // If true, always disable deployment diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index cdecea03a49..f9bd67e083c 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -519,7 +519,7 @@ std::string cmGlobalVisualStudioGenerator::GetUtilityDepend( std::string cmGlobalVisualStudioGenerator::GetStartupProjectName( cmLocalGenerator const* root) const { - cmProp n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); + cmValue n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); if (cmNonempty(n)) { std::string startup = *n; if (this->FindTarget(startup)) { @@ -820,7 +820,7 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( // This allows the project to control the language choice in // a target with none of its own sources, e.g. when also using // object libraries. - cmProp linkLang = gt->GetProperty("LINKER_LANGUAGE"); + cmValue linkLang = gt->GetProperty("LINKER_LANGUAGE"); if (cmNonempty(linkLang)) { languages.insert(*linkLang); } diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 57ada62dde6..d1bd6b118d5 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -201,7 +201,7 @@ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator private: virtual std::string GetVSMakeProgram() = 0; void PrintCompilerAdvice(std::ostream&, std::string const&, - cmProp) const override + cmValue) const override { } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 4ccc955d2d5..c3d60b01a22 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -941,11 +941,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( gtgt->AddExplicitLanguageFlags(flags, *sf); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) { + if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) { lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS)); } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (cmProp coptions = sf->GetProperty(COMPILE_OPTIONS)) { + if (cmValue coptions = sf->GetProperty(COMPILE_OPTIONS)) { lg->AppendCompileOptions( flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS)); } @@ -953,7 +953,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( // Add per-source definitions. BuildObjectListOrString flagsBuild(this, false); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - if (cmProp compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) { + if (cmValue compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) { this->AppendDefines( flagsBuild, genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS).c_str(), @@ -974,7 +974,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( // Add per-source include directories. std::vector<std::string> includes; const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (cmProp cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) { + if (cmValue cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) { lg->AppendIncludeDirectories( includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), *sf); @@ -1006,7 +1006,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( } // Add user-specified file attributes. - cmProp extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES"); + cmValue extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES"); if (extraFileAttributes) { // Expand the list of attributes. std::vector<std::string> attributes = cmExpandedList(*extraFileAttributes); @@ -1194,9 +1194,9 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( bool useLastKnownFileType = false; std::string fileType; if (sf) { - if (cmProp e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) { + if (cmValue e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) { fileType = *e; - } else if (cmProp l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) { + } else if (cmValue l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) { useLastKnownFileType = true; fileType = *l; } @@ -2413,7 +2413,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CurrentLocalGenerator->GetStaticLibraryFlags( extraLinkOptions, configName, llang, gtgt); } else { - cmProp targetLinkFlags = gtgt->GetProperty("LINK_FLAGS"); + cmValue targetLinkFlags = gtgt->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, *targetLinkFlags); @@ -2421,7 +2421,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (!configName.empty()) { std::string linkFlagsVar = cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName)); - if (cmProp linkFlags = gtgt->GetProperty(linkFlagsVar)) { + if (cmValue linkFlags = gtgt->GetProperty(linkFlagsVar)) { this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, *linkFlags); } } @@ -2458,8 +2458,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string pnsuffix; gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); - cmProp version = gtgt->GetProperty("VERSION"); - cmProp soversion = gtgt->GetProperty("SOVERSION"); + cmValue version = gtgt->GetProperty("VERSION"); + cmValue soversion = gtgt->GetProperty("SOVERSION"); if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) { version = nullptr; soversion = nullptr; @@ -2523,7 +2523,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string fw_version = gtgt->GetFrameworkVersion(); buildSettings->AddAttribute("FRAMEWORK_VERSION", this->CreateString(fw_version)); - cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION"); + cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION"); if (ext) { buildSettings->AddAttribute("WRAPPER_EXTENSION", this->CreateString(*ext)); @@ -2564,7 +2564,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, extraLinkOptions += " "; extraLinkOptions += createFlags; } - cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION"); + cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION"); if (ext) { buildSettings->AddAttribute("WRAPPER_EXTENSION", this->CreateString(*ext)); @@ -2598,7 +2598,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string fw_version = gtgt->GetFrameworkVersion(); buildSettings->AddAttribute("FRAMEWORK_VERSION", this->CreateString(fw_version)); - cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION"); + cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION"); if (ext) { buildSettings->AddAttribute("WRAPPER_EXTENSION", this->CreateString(*ext)); @@ -2637,7 +2637,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // Handle bundles and normal executables separately. if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { - cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION"); + cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION"); if (ext) { buildSettings->AddAttribute("WRAPPER_EXTENSION", this->CreateString(*ext)); @@ -3083,7 +3083,7 @@ const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar( const char* cmGlobalXCodeGenerator::GetTargetFileType( cmGeneratorTarget* target) { - if (cmProp e = target->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) { + if (cmValue e = target->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) { return e->c_str(); } @@ -3116,7 +3116,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType( const char* cmGlobalXCodeGenerator::GetTargetProductType( cmGeneratorTarget* target) { - if (cmProp e = target->GetProperty("XCODE_PRODUCT_TYPE")) { + if (cmValue e = target->GetProperty("XCODE_PRODUCT_TYPE")) { return e->c_str(); } @@ -3235,7 +3235,7 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name, const std::string& id) { std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); - cmProp storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName); + cmValue storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName); if (storedGUID) { return *storedGUID; @@ -3411,7 +3411,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) std::map<std::string, std::vector<std::string>> targetProductNameMap; bool useLinkPhase = false; bool forceLinkPhase = false; - cmProp prop = + cmValue prop = target->GetTarget()->GetProperty("XCODE_LINK_BUILD_PHASE_MODE"); if (prop) { if (*prop == "BUILT_ONLY") { @@ -3784,7 +3784,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects( if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { return; } - cmProp files = gt->GetProperty(embedPropertyName); + cmValue files = gt->GetProperty(embedPropertyName); if (!files) { return; } @@ -3799,7 +3799,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects( this->CreateString(dstSubfolderSpec)); copyFilesBuildPhase->AddAttribute( "name", this->CreateString(copyFilesBuildPhaseName)); - if (cmProp fwEmbedPath = + if (cmValue fwEmbedPath = gt->GetProperty(cmStrCat(embedPropertyName, "_PATH"))) { copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(*fwEmbedPath)); @@ -4186,8 +4186,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateString(defaultConfigName)); cmXCodeObject* buildSettings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - cmProp sysroot = this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT"); - cmProp deploymentTarget = + cmValue sysroot = this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT"); + cmValue deploymentTarget = this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); if (sysroot) { buildSettings->AddAttribute("SDKROOT", this->CreateString(*sysroot)); @@ -4220,7 +4220,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( } if (this->GetLanguageEnabled("Swift")) { std::string swiftVersion; - if (cmProp vers = this->CurrentMakefile->GetDefinition( + if (cmValue vers = this->CurrentMakefile->GetDefinition( "CMAKE_Swift_LANGUAGE_VERSION")) { swiftVersion = *vers; } else if (this->XcodeVersion >= 102) { @@ -4343,7 +4343,7 @@ std::string cmGlobalXCodeGenerator::GetObjectsDirectory( void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) { this->Architectures.clear(); - cmProp sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); + cmValue sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); if (sysroot) { mf->GetDefExpandList("CMAKE_OSX_ARCHITECTURES", this->Architectures); } @@ -4356,7 +4356,7 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) // With no ARCHS we use ONLY_ACTIVE_ARCH and possibly a // platform-specific default ARCHS placeholder value. // Look up the arch that Xcode chooses in this case. - if (cmProp arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) { + if (cmValue arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) { this->ObjectDirArchDefault = *arch; // We expect only one arch but choose the first just in case. std::string::size_type pos = this->ObjectDirArchDefault.find(';'); @@ -4550,7 +4550,7 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( continue; } - cmProp testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE"); + cmValue testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE"); if (!testee) { continue; } @@ -4733,7 +4733,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags( { if (!varNameLang.empty()) { std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix); - if (cmProp varValue = this->CurrentMakefile->GetDefinition(varName)) { + if (cmValue varValue = this->CurrentMakefile->GetDefinition(varName)) { if (!varValue->empty()) { return *varValue; } @@ -4855,7 +4855,7 @@ bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation( bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const { - cmProp epnValue = this->GetCMakeInstance()->GetState()->GetGlobalProperty( + cmValue epnValue = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "XCODE_EMIT_EFFECTIVE_PLATFORM_NAME"); if (!epnValue) { diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index e54818eae11..72af4a40adc 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -327,7 +327,7 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator bool XcodeBuildCommandInitialized; void PrintCompilerAdvice(std::ostream&, std::string const&, - cmProp) const override + cmValue) const override { } diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 122bda52dcc..ab18e2a6613 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -17,11 +17,11 @@ #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -232,7 +232,7 @@ void cmGraphVizWriter::ReadSettings( #define set_if_set(var, cmakeDefinition) \ do { \ - cmProp value = mf.GetDefinition(cmakeDefinition); \ + cmValue value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ (var) = *value; \ } \ @@ -244,7 +244,7 @@ void cmGraphVizWriter::ReadSettings( #define set_bool_if_set(var, cmakeDefinition) \ do { \ - cmProp value = mf.GetDefinition(cmakeDefinition); \ + cmValue value = mf.GetDefinition(cmakeDefinition); \ if (value) { \ (var) = cmIsOn(*value); \ } \ diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx index d48c823973b..e0a6958ddb3 100644 --- a/Source/cmIncludeGuardCommand.cxx +++ b/Source/cmIncludeGuardCommand.cxx @@ -4,10 +4,10 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" namespace { diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 687741b3dae..ee77b2c2d3a 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -35,7 +35,6 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmRuntimeDependencyArchive.h" #include "cmStateTypes.h" @@ -44,6 +43,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" +#include "cmValue.h" namespace { @@ -926,7 +926,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) { - cmProp files = target.GetProperty("PRIVATE_HEADER"); + cmValue files = target.GetProperty("PRIVATE_HEADER"); if (cmNonempty(files)) { std::vector<std::string> relFiles = cmExpandedList(*files); std::vector<std::string> absFiles; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 35165cf7210..2f974c46e0a 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -18,11 +18,11 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -208,7 +208,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles( // Get App Bundle Extension std::string ext; - if (cmProp p = this->Target->GetProperty("BUNDLE_EXTENSION")) { + if (cmValue p = this->Target->GetProperty("BUNDLE_EXTENSION")) { ext = *p; } else { ext = "app"; @@ -825,7 +825,7 @@ void cmInstallTargetGenerator::AddUniversalInstallRule( return; } - cmProp xcodeVersion = mf->GetDefinition("XCODE_VERSION"); + cmValue xcodeVersion = mf->GetDefinition("XCODE_VERSION"); if (!xcodeVersion || cmSystemTools::VersionCompareGreater("6", *xcodeVersion)) { return; diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 2ffff96b9dc..43f161be473 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -16,11 +16,11 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" class cmOutputConverter; @@ -177,7 +177,7 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, return false; } - if (cmProp resolveDeviceSymbols = + if (cmValue resolveDeviceSymbols = target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { // If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need // to honor the value no matter what it is. diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 09cd88e08f5..a1aaee34406 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -25,12 +25,12 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" #include "cmSubcommandTable.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { @@ -79,7 +79,7 @@ bool GetListString(std::string& listString, const std::string& var, const cmMakefile& makefile) { // get the old value - cmProp cacheValue = makefile.GetDefinition(var); + cmValue cacheValue = makefile.GetDefinition(var); if (!cacheValue) { return false; } diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 211525a2659..eca7a9eb6ef 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -8,11 +8,11 @@ #include "cmGeneratorTarget.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" class cmGlobalGenerator; @@ -82,7 +82,7 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( // If there is a separate module path flag then duplicate the // include path with it. This compiler does not search the include // path for modules. - if (cmProp modpath_flag = + if (cmValue modpath_flag = this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) { std::vector<std::string> includes; this->GetIncludeDirectories(includes, target, "C", config); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e2e0d8e67bd..966cf285d1e 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -37,7 +37,6 @@ #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" @@ -50,6 +49,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTestGenerator.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -117,21 +117,21 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) std::vector<std::string> enabledLanguages = this->GetState()->GetEnabledLanguages(); - if (cmProp sysrootCompile = + if (cmValue sysrootCompile = this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { this->CompilerSysroot = *sysrootCompile; } else { this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); } - if (cmProp sysrootLink = + if (cmValue sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { this->LinkerSysroot = *sysrootLink; } else { this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); } - if (cmProp appleArchSysroots = + if (cmValue appleArchSysroots = this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) { std::string const& appleArchs = this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES"); @@ -221,7 +221,7 @@ void cmLocalGenerator::ComputeObjectMaxPath() #else this->ObjectPathMax = 1000; #endif - cmProp plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX"); + cmValue plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX"); if (cmNonempty(plen)) { unsigned int pmax; if (sscanf(plen->c_str(), "%u", &pmax) == 1) { @@ -329,12 +329,12 @@ void cmLocalGenerator::GenerateTestFiles() fout << "set(CTEST_RESOURCE_SPEC_FILE \"" << resourceSpecFile << "\")\n"; } - cmProp testIncludeFile = this->Makefile->GetProperty("TEST_INCLUDE_FILE"); + cmValue testIncludeFile = this->Makefile->GetProperty("TEST_INCLUDE_FILE"); if (testIncludeFile) { fout << "include(\"" << *testIncludeFile << "\")\n"; } - cmProp testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES"); + cmValue testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES"); if (testIncludeFiles) { std::vector<std::string> includesList = cmExpandedList(*testIncludeFiles); for (std::string const& i : includesList) { @@ -358,9 +358,9 @@ void cmLocalGenerator::GenerateTestFiles() } // Add directory labels property - cmProp directoryLabels = + cmValue directoryLabels = this->Makefile->GetDefinition("CMAKE_DIRECTORY_LABELS"); - cmProp labels = this->Makefile->GetProperty("LABELS"); + cmValue labels = this->Makefile->GetProperty("LABELS"); if (labels || directoryLabels) { fout << "set_directory_properties(PROPERTIES LABELS "; @@ -425,7 +425,8 @@ void cmLocalGenerator::ProcessEvaluationFiles( void cmLocalGenerator::GenerateInstallRules() { // Compute the install prefix. - cmProp installPrefix = this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX"); + cmValue installPrefix = + this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX"); std::string prefix = installPrefix; #if defined(_WIN32) && !defined(__CYGWIN__) @@ -433,7 +434,7 @@ void cmLocalGenerator::GenerateInstallRules() if (!cmSystemTools::GetEnv("SystemDrive", prefix)) { prefix = "C:"; } - cmProp project_name = this->Makefile->GetDefinition("PROJECT_NAME"); + cmValue project_name = this->Makefile->GetDefinition("PROJECT_NAME"); if (cmNonempty(project_name)) { prefix += "/Program Files/"; prefix += *project_name; @@ -456,7 +457,7 @@ void cmLocalGenerator::GenerateInstallRules() prefix = "/usr/local"; } #endif - if (cmProp stagingPrefix = + if (cmValue stagingPrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) { prefix = *stagingPrefix; } @@ -538,7 +539,7 @@ void cmLocalGenerator::GenerateInstallRules() /* clang-format on */ // Copy user-specified install options to the install code. - if (cmProp so_no_exe = + if (cmValue so_no_exe = this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE")) { /* clang-format off */ fout << @@ -551,7 +552,7 @@ void cmLocalGenerator::GenerateInstallRules() } // Copy cmake cross compile state to install code. - if (cmProp crosscompiling = + if (cmValue crosscompiling = this->Makefile->GetDefinition("CMAKE_CROSSCOMPILING")) { /* clang-format off */ fout << @@ -564,7 +565,7 @@ void cmLocalGenerator::GenerateInstallRules() } // Write default directory permissions. - if (cmProp defaultDirPermissions = this->Makefile->GetDefinition( + if (cmValue defaultDirPermissions = this->Makefile->GetDefinition( "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) { /* clang-format off */ fout << @@ -580,7 +581,7 @@ void cmLocalGenerator::GenerateInstallRules() // Write out CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM so that // installed code that uses `file(GET_RUNTIME_DEPENDENCIES)` // has same platform variable as when running cmake - if (cmProp platform = this->Makefile->GetDefinition( + if (cmValue platform = this->Makefile->GetDefinition( "CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM")) { /* clang-format off */ fout << @@ -596,7 +597,7 @@ void cmLocalGenerator::GenerateInstallRules() // Write out CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL so that // installed code that uses `file(GET_RUNTIME_DEPENDENCIES)` // has same tool selected as when running cmake - if (cmProp command = + if (cmValue command = this->Makefile->GetDefinition("CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL")) { /* clang-format off */ fout << @@ -612,7 +613,7 @@ void cmLocalGenerator::GenerateInstallRules() // Write out CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND so that // installed code that uses `file(GET_RUNTIME_DEPENDENCIES)` // has same path to the tool as when running cmake - if (cmProp command = this->Makefile->GetDefinition( + if (cmValue command = this->Makefile->GetDefinition( "CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND")) { /* clang-format off */ fout << @@ -630,7 +631,7 @@ void cmLocalGenerator::GenerateInstallRules() // CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND has consistent // logic to fallback to CMAKE_OBJDUMP when `objdump` is // not on the path - if (cmProp command = this->Makefile->GetDefinition("CMAKE_OBJDUMP")) { + if (cmValue command = this->Makefile->GetDefinition("CMAKE_OBJDUMP")) { /* clang-format off */ fout << "# Set default install directory permissions.\n" @@ -823,8 +824,8 @@ cmStateSnapshot cmLocalGenerator::GetStateSnapshot() const return this->Makefile->GetStateSnapshot(); } -cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target, - const std::string& prop) +cmValue cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target, + const std::string& prop) { if (target) { return target->GetProperty(prop); @@ -863,7 +864,7 @@ std::string cmLocalGenerator::GetIncludeFlags( std::string sep = " "; bool repeatFlag = true; // should the include flag be repeated like ie. -IA -IB - if (cmProp incSep = this->Makefile->GetDefinition( + if (cmValue incSep = this->Makefile->GetDefinition( cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang))) { // if there is a separator then the flag is not repeated but is only // given once i.e. -classpath a:b:c @@ -873,8 +874,8 @@ std::string cmLocalGenerator::GetIncludeFlags( // Support special system include flag if it is available and the // normal flag is repeated for each directory. - cmProp sysIncludeFlag = nullptr; - cmProp sysIncludeFlagWarning = nullptr; + cmValue sysIncludeFlag = nullptr; + cmValue sysIncludeFlagWarning = nullptr; if (repeatFlag) { sysIncludeFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang)); @@ -882,9 +883,9 @@ std::string cmLocalGenerator::GetIncludeFlags( cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", lang, "_WARNING")); } - cmProp fwSearchFlag = this->Makefile->GetDefinition( + cmValue fwSearchFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_FRAMEWORK_SEARCH_FLAG")); - cmProp sysFwSearchFlag = this->Makefile->GetDefinition( + cmValue sysFwSearchFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG")); bool flagUsed = false; @@ -960,10 +961,10 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, { std::string langFlagRegexVar = cmStrCat("CMAKE_", lang, "_FLAG_REGEX"); - if (cmProp langFlagRegexStr = + if (cmValue langFlagRegexStr = this->Makefile->GetDefinition(langFlagRegexVar)) { // Filter flags acceptable to this language. - if (cmProp targetFlags = target->GetProperty("COMPILE_FLAGS")) { + if (cmValue targetFlags = target->GetProperty("COMPILE_FLAGS")) { std::vector<std::string> opts; cmSystemTools::ParseWindowsCommandLine(targetFlags->c_str(), opts); // Re-escape these flags since COMPILE_FLAGS were already parsed @@ -981,7 +982,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, langFlagRegexStr->c_str()); } else { // Use all flags. - if (cmProp targetFlags = target->GetProperty("COMPILE_FLAGS")) { + if (cmValue targetFlags = target->GetProperty("COMPILE_FLAGS")) { // COMPILE_FLAGS are not escaped for historical reasons. std::string compileFlags; this->AppendFlags(compileFlags, *targetFlags); @@ -997,7 +998,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, cmStandardLevelResolver standardResolver(this->Makefile); for (auto const& it : target->GetMaxLanguageStandards()) { - cmProp standard = target->GetLanguageStandard(it.first, config); + cmValue standard = target->GetLanguageStandard(it.first, config); if (!standard) { continue; } @@ -1028,7 +1029,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, // Add compile flag for the MSVC compiler only. cmMakefile* mf = this->GetMakefile(); - if (cmProp jmc = + if (cmValue jmc = mf->GetDefinition("CMAKE_" + lang + "_COMPILE_OPTIONS_JMC")) { // Handle Just My Code debugging flags, /JMC. @@ -1037,7 +1038,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, cmGeneratorTarget::ManagedType::Managed) { // add /JMC flags if target property VS_JUST_MY_CODE_DEBUGGING is set // to ON - if (cmProp jmcExprGen = + if (cmValue jmcExprGen = target->GetProperty("VS_JUST_MY_CODE_DEBUGGING")) { std::string isJMCEnabled = cmGeneratorExpression::Evaluate(*jmcExprGen, this, config); @@ -1496,7 +1497,7 @@ void cmLocalGenerator::GetTargetFlags( } } - cmProp targetLinkFlags = target->GetProperty("LINK_FLAGS"); + cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { sharedLibFlags += *targetLinkFlags; sharedLibFlags += " "; @@ -1576,7 +1577,7 @@ void cmLocalGenerator::GetTargetFlags( exeFlags += " "; } - cmProp targetLinkFlags = target->GetProperty("LINK_FLAGS"); + cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { exeFlags += *targetLinkFlags; exeFlags += " "; @@ -1672,7 +1673,7 @@ static std::string GetFrameworkFlags(const std::string& lang, } std::string fwSearchFlagVar = "CMAKE_" + lang + "_FRAMEWORK_SEARCH_FLAG"; - cmProp fwSearchFlag = mf->GetDefinition(fwSearchFlagVar); + cmValue fwSearchFlag = mf->GetDefinition(fwSearchFlagVar); if (!cmNonempty(fwSearchFlag)) { return std::string(); } @@ -1781,7 +1782,7 @@ void cmLocalGenerator::OutputLinkLibraries( std::string linkLanguage = cli.GetLinkLanguage(); std::string libPathFlag; - if (cmProp value = this->Makefile->GetDefinition( + if (cmValue value = this->Makefile->GetDefinition( "CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_FLAG")) { libPathFlag = *value; } else { @@ -1790,7 +1791,7 @@ void cmLocalGenerator::OutputLinkLibraries( } std::string libPathTerminator; - if (cmProp value = this->Makefile->GetDefinition( + if (cmValue value = this->Makefile->GetDefinition( "CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_TERMINATOR")) { libPathTerminator = *value; } else { @@ -1866,7 +1867,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( } bool cmLocalGenerator::AllAppleArchSysrootsAreTheSame( - const std::vector<std::string>& archs, cmProp sysroot) + const std::vector<std::string>& archs, cmValue sysroot) { if (!sysroot) { return false; @@ -1901,12 +1902,12 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, } } - cmProp sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT"); + cmValue sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT"); if (sysroot && *sysroot == "/") { sysroot = nullptr; } std::string sysrootFlagVar = "CMAKE_" + lang + "_SYSROOT_FLAG"; - cmProp sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); + cmValue sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); if (cmNonempty(sysrootFlag)) { if (!this->AppleArchSysroots.empty() && !this->AllAppleArchSysrootsAreTheSame(archs, sysroot)) { @@ -1930,11 +1931,11 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, } } - cmProp deploymentTarget = + cmValue deploymentTarget = this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); std::string deploymentTargetFlagVar = "CMAKE_" + lang + "_OSX_DEPLOYMENT_TARGET_FLAG"; - cmProp deploymentTargetFlag = + cmValue deploymentTargetFlag = this->Makefile->GetDefinition(deploymentTargetFlagVar); if (cmNonempty(deploymentTargetFlag) && cmNonempty(deploymentTarget)) { flags += " "; @@ -1959,7 +1960,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, std::string compilerSimulateId = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_SIMULATE_ID")); if (lang == "Swift") { - if (cmProp v = target->GetProperty("Swift_LANGUAGE_VERSION")) { + if (cmValue v = target->GetProperty("Swift_LANGUAGE_VERSION")) { if (cmSystemTools::VersionCompare( cmSystemTools::OP_GREATER_EQUAL, this->Makefile->GetDefinition("CMAKE_Swift_COMPILER_VERSION"), @@ -1990,7 +1991,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, // Add VFS Overlay for Clang compilers if (compiler == "Clang") { - if (cmProp vfsOverlay = + if (cmValue vfsOverlay = this->Makefile->GetDefinition("CMAKE_CLANG_VFS_OVERLAY")) { if (compilerSimulateId == "MSVC") { this->AppendCompileOptions( @@ -2005,10 +2006,10 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } // Add MSVC runtime library flags. This is activated by the presence // of a default selection whether or not it is overridden by a property. - cmProp msvcRuntimeLibraryDefault = + cmValue msvcRuntimeLibraryDefault = this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT"); if (cmNonempty(msvcRuntimeLibraryDefault)) { - cmProp msvcRuntimeLibraryValue = + cmValue msvcRuntimeLibraryValue = target->GetProperty("MSVC_RUNTIME_LIBRARY"); if (!msvcRuntimeLibraryValue) { msvcRuntimeLibraryValue = msvcRuntimeLibraryDefault; @@ -2016,7 +2017,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, std::string const msvcRuntimeLibrary = cmGeneratorExpression::Evaluate( *msvcRuntimeLibraryValue, this, config, target); if (!msvcRuntimeLibrary.empty()) { - if (cmProp msvcRuntimeLibraryOptions = this->Makefile->GetDefinition( + if (cmValue msvcRuntimeLibraryOptions = this->Makefile->GetDefinition( "CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" + msvcRuntimeLibrary)) { this->AppendCompileOptions(flags, *msvcRuntimeLibraryOptions); @@ -2196,7 +2197,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string const& optionFlagDef = standardResolver.GetCompileOptionDef(target, lang, config); if (!optionFlagDef.empty()) { - cmProp opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef); + cmValue opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef); if (opt) { std::vector<std::string> optVec = cmExpandedList(*opt); for (std::string const& i : optVec) { @@ -2213,13 +2214,13 @@ static void AddVisibilityCompileOption(std::string& flags, std::string* warnCMP0063) { std::string compileOption = "CMAKE_" + lang + "_COMPILE_OPTIONS_VISIBILITY"; - cmProp opt = lg->GetMakefile()->GetDefinition(compileOption); + cmValue opt = lg->GetMakefile()->GetDefinition(compileOption); if (!opt) { return; } std::string flagDefine = lang + "_VISIBILITY_PRESET"; - cmProp prop = target->GetProperty(flagDefine); + cmValue prop = target->GetProperty(flagDefine); if (!prop) { return; } @@ -2249,7 +2250,7 @@ static void AddInlineVisibilityCompileOption(std::string& flags, { std::string compileOption = cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"); - cmProp opt = lg->GetMakefile()->GetDefinition(compileOption); + cmValue opt = lg->GetMakefile()->GetDefinition(compileOption); if (!opt) { return; } @@ -2446,7 +2447,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target) return; } - cmProp ispcHeaderSuffixProp = target->GetProperty("ISPC_HEADER_SUFFIX"); + cmValue ispcHeaderSuffixProp = target->GetProperty("ISPC_HEADER_SUFFIX"); assert(ispcHeaderSuffixProp); std::vector<std::string> ispcArchSuffixes = @@ -2459,7 +2460,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target) std::string rootObjectDir = target->GetObjectDirectory(config); std::string headerDir = rootObjectDir; - if (cmProp prop = target->GetProperty("ISPC_HEADER_DIRECTORY")) { + if (cmValue prop = target->GetProperty("ISPC_HEADER_DIRECTORY")) { headerDir = cmSystemTools::CollapseFullPath( cmStrCat(this->GetBinaryDirectory(), '/', *prop)); } @@ -2567,14 +2568,14 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) continue; } - cmProp pchExtension = + cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); if (pchExtension.IsEmpty()) { continue; } - cmProp ReuseFrom = + cmValue ReuseFrom = target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); auto* pch_sf = this->Makefile->GetOrCreateSource( @@ -2809,7 +2810,7 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, void cmLocalGenerator::IncludeFileInUnitySources( cmGeneratedFileStream& unity_file, std::string const& sf_full_path, - cmProp beforeInclude, cmProp afterInclude, cmProp uniqueIdName) const + cmValue beforeInclude, cmValue afterInclude, cmValue uniqueIdName) const { if (cmNonempty(uniqueIdName)) { std::string pathToHash; @@ -2847,14 +2848,14 @@ void cmLocalGenerator::IncludeFileInUnitySources( std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude, - cmProp afterInclude, std::string const& filename_base, size_t batchSize) + std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, + cmValue afterInclude, std::string const& filename_base, size_t batchSize) { if (batchSize == 0) { batchSize = filtered_sources.size(); } - cmProp uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); + cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); std::vector<std::string> unity_files; for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0; @@ -2890,8 +2891,8 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto( std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude, - cmProp afterInclude, std::string const& filename_base) + std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, + cmValue afterInclude, std::string const& filename_base) { std::vector<std::string> unity_files; @@ -2899,7 +2900,7 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup( // without a group std::unordered_map<std::string, std::vector<cmSourceFile*>> explicit_mapping; for (cmSourceFile* sf : filtered_sources) { - if (cmProp value = sf->GetProperty("UNITY_GROUP")) { + if (cmValue value = sf->GetProperty("UNITY_GROUP")) { auto i = explicit_mapping.find(*value); if (i == explicit_mapping.end()) { std::vector<cmSourceFile*> sources{ sf }; @@ -2910,7 +2911,7 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup( } } - cmProp uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); + cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); for (auto const& item : explicit_mapping) { auto const& name = item.first; @@ -2957,15 +2958,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) std::vector<cmSourceFile*> sources; target->GetSourceFiles(sources, config); - cmProp batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE"); + cmValue batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE"); const size_t unityBatchSize = batchSizeString ? static_cast<size_t>(std::atoi(batchSizeString->c_str())) : 0; - cmProp beforeInclude = + cmValue beforeInclude = target->GetProperty("UNITY_BUILD_CODE_BEFORE_INCLUDE"); - cmProp afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE"); - cmProp unityMode = target->GetProperty("UNITY_BUILD_MODE"); + cmValue afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE"); + cmValue unityMode = target->GetProperty("UNITY_BUILD_MODE"); for (std::string lang : { "C", "CXX" }) { std::vector<cmSourceFile*> filtered_sources; @@ -3025,7 +3026,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, } const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO"; - cmProp rawFlagsList = this->Makefile->GetDefinition(name); + cmValue rawFlagsList = this->Makefile->GetDefinition(name); if (!rawFlagsList) { return; } @@ -3240,7 +3241,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines, // Lookup the define flag for the current language. std::string dflag = "-D"; if (!lang.empty()) { - cmProp df = + cmValue df = this->Makefile->GetDefinition(cmStrCat("CMAKE_", lang, "_DEFINE_FLAG")); if (cmNonempty(df)) { dflag = *df; @@ -3287,7 +3288,7 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature) { - cmProp optionList = this->Makefile->GetDefinition( + cmValue optionList = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature)); if (optionList) { std::vector<std::string> options = cmExpandedList(*optionList); @@ -3297,8 +3298,8 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags, } } -cmProp cmLocalGenerator::GetFeature(const std::string& feature, - const std::string& config) +cmValue cmLocalGenerator::GetFeature(const std::string& feature, + const std::string& config) { std::string featureName = feature; // TODO: Define accumulation policy for features (prepend, append, @@ -3309,7 +3310,7 @@ cmProp cmLocalGenerator::GetFeature(const std::string& feature, } cmStateSnapshot snp = this->StateSnapshot; while (snp.IsValid()) { - if (cmProp value = snp.GetDirectory().GetProperty(featureName)) { + if (cmValue value = snp.GetDirectory().GetProperty(featureName)) { return value; } snp = snp.GetBuildsystemDirectoryParent(); @@ -3374,7 +3375,7 @@ void cmLocalGenerator::GenerateTargetInstallRules( } // Include the user-specified pre-install script for this target. - if (cmProp preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) { + if (cmValue preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) { cmInstallScriptGenerator g(*preinstall, false, "", false, false); g.Generate(os, config, configurationTypes); } @@ -3427,7 +3428,7 @@ void cmLocalGenerator::GenerateTargetInstallRules( } // Include the user-specified post-install script for this target. - if (cmProp postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) { + if (cmValue postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) { cmInstallScriptGenerator g(*postinstall, false, "", false, false); g.Generate(os, config, configurationTypes); } @@ -3652,8 +3653,8 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( // Ensure that for the CMakeFiles/<target>.dir/generated_source_file // we don't end up having: // CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj - cmProp unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE"); - cmProp pchExtension = source.GetProperty("PCH_EXTENSION"); + cmValue unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE"); + cmValue pchExtension = source.GetProperty("PCH_EXTENSION"); const bool isPchObject = objectName.find("cmake_pch") != std::string::npos; if (unitySourceFile || pchExtension || isPchObject) { if (pchExtension) { @@ -3752,7 +3753,7 @@ KWIML_INT_uint64_t cmLocalGenerator::GetBackwardsCompatibility() unsigned int major = 0; unsigned int minor = 0; unsigned int patch = 0; - if (cmProp value = + if (cmValue value = this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY")) { switch (sscanf(value->c_str(), "%u.%u.%u", &major, &minor, &patch)) { case 2: @@ -3847,7 +3848,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const static void cmLGInfoProp(cmMakefile* mf, cmGeneratorTarget* target, const std::string& prop) { - if (cmProp val = target->GetProperty(prop)) { + if (cmValue val = target->GetProperty(prop)) { mf->AddDefinition(prop, *val); } } @@ -3857,7 +3858,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target, const std::string& fname) { // Find the Info.plist template. - cmProp in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST"); + cmValue in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST"); std::string inFile = cmNonempty(in) ? *in : "MacOSXBundleInfo.plist.in"; if (!cmSystemTools::FileIsFullPath(inFile)) { std::string inMod = this->Makefile->GetModulesFile(inFile); @@ -3896,7 +3897,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( const std::string& fname) { // Find the Info.plist template. - cmProp in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST"); + cmValue in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST"); std::string inFile = cmNonempty(in) ? *in : "MacOSXFrameworkInfo.plist.in"; if (!cmSystemTools::FileIsFullPath(inFile)) { std::string inMod = this->Makefile->GetModulesFile(inFile); diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 678ef8c9c0d..3614c8466e5 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -20,8 +20,8 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateSnapshot.h" +#include "cmValue.h" class cmCompiledGeneratorExpression; class cmComputeLinkInformation; @@ -247,7 +247,7 @@ class cmLocalGenerator : public cmOutputConverter void AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature); - cmProp GetFeature(const std::string& feature, const std::string& config); + cmValue GetFeature(const std::string& feature, const std::string& config); /** \brief Get absolute path to dependency \a name * @@ -547,7 +547,7 @@ class cmLocalGenerator : public cmOutputConverter void CreateEvaluationFileOutputs(const std::string& config); void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles); - cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop); + cmValue GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop); protected: // The default implementation ignores the IncludePathStyle and always @@ -651,7 +651,7 @@ class cmLocalGenerator : public cmOutputConverter void ComputeObjectMaxPath(); bool AllAppleArchSysrootsAreTheSame(const std::vector<std::string>& archs, - cmProp sysroot); + cmValue sysroot); void CopyPchCompilePdb(const std::string& config, cmGeneratorTarget* target, const std::string& ReuseFrom, @@ -659,16 +659,16 @@ class cmLocalGenerator : public cmOutputConverter std::vector<std::string> const& extensions); void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file, std::string const& sf_full_path, - cmProp beforeInclude, cmProp afterInclude, - cmProp uniqueIdName) const; + cmValue beforeInclude, cmValue afterInclude, + cmValue uniqueIdName) const; std::vector<std::string> AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude, - cmProp afterInclude, std::string const& filename_base, size_t batchSize); + std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, + cmValue afterInclude, std::string const& filename_base, size_t batchSize); std::vector<std::string> AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude, - cmProp afterInclude, std::string const& filename_base); + std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, + cmValue afterInclude, std::string const& filename_base); }; #if !defined(CMAKE_BOOTSTRAP) diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 9f8e7ed4cbe..a43faa711b8 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -27,7 +27,6 @@ #include "cmMessageType.h" #include "cmNinjaTargetGenerator.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmState.h" @@ -35,6 +34,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, @@ -311,7 +311,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); - cmProp jobpools = + cmValue jobpools = this->GetCMakeInstance()->GetState()->GetGlobalProperty("JOB_POOLS"); if (!jobpools) { jobpools = this->GetMakefile()->GetDefinition("CMAKE_JOB_POOLS"); @@ -869,7 +869,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements( std::string cmLocalNinjaGenerator::MakeCustomLauncher( cmCustomCommandGenerator const& ccg) { - cmProp property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM"); + cmValue property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM"); if (!cmNonempty(property_value)) { return std::string(); @@ -903,7 +903,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) { - if (cmProp prop_value = + if (cmValue prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector<std::string> cleanFiles; { diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 0667c55a395..7e39b91f104 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -33,7 +33,6 @@ #include "cmMakefile.h" #include "cmMakefileTargetGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -43,6 +42,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTargetDepend.h" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -570,7 +570,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule( // Mark the rule as symbolic if requested. if (symbolic) { - if (cmProp sym = + if (cmValue sym = this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE")) { os << tgt << space << ": " << *sym << "\n"; } @@ -884,7 +884,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend( { // Add a dependency on the rule file itself unless an option to skip // it is specifically enabled by the user or project. - cmProp nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); + cmValue nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); if (cmIsOff(nodep)) { depends.emplace_back(ruleFileName); } @@ -999,7 +999,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( std::string launcher; // Short-circuit if there is no launcher. - cmProp val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM"); + cmValue val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM"); if (cmNonempty(val)) { // Expand rule variables referenced in the given launcher command. cmRulePlaceholderExpander::RuleVariables vars; @@ -1125,7 +1125,7 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( { std::vector<std::string> cleanFiles; // Look for additional files registered for cleaning in this directory. - if (cmProp prop_value = + if (cmValue prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmExpandList(cmGeneratorExpression::Evaluate( *prop_value, this, @@ -1501,18 +1501,18 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // Lookup useful directory information. if (haveDirectoryInfo) { // Test whether we need to force Unix paths. - if (cmProp force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) { + if (cmValue force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) { if (!cmIsOff(force)) { cmSystemTools::SetForceUnixPaths(true); } } // Setup relative path top directories. - if (cmProp relativePathTopSource = + if (cmValue relativePathTopSource = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) { this->SetRelativePathTopSource(*relativePathTopSource); } - if (cmProp relativePathTopBinary = + if (cmValue relativePathTopBinary = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) { this->SetRelativePathTopBinary(*relativePathTopBinary); } @@ -1582,7 +1582,7 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) cmMakefile* mf = this->Makefile; // Get the string listing the multiple output pairs. - cmProp pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS"); + cmValue pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS"); if (!pairs_string) { return; } @@ -1654,7 +1654,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( std::vector<std::string> commands; std::vector<std::string> depends; - cmProp p = gt->GetProperty("EchoString"); + cmValue p = gt->GetProperty("EchoString"); const char* text = p ? p->c_str() : "Running external command ..."; depends.reserve(gt->GetUtilities().size()); for (BT<std::pair<std::string, bool>> const& u : gt->GetUtilities()) { @@ -1754,7 +1754,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall"); commands.clear(); depends.clear(); - cmProp noall = + cmValue noall = this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); if (cmIsOff(noall)) { // Drive the build before installing. @@ -1804,7 +1804,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, bool verbose) { // Get the list of target files to check - cmProp infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES"); + cmValue infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES"); if (!infoDef) { return; } @@ -1903,7 +1903,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Tell the dependency scanner what compiler is used. std::string cidVar = cmStrCat("CMAKE_", lang, "_COMPILER_ID"); - cmProp cid = this->Makefile->GetDefinition(cidVar); + cmValue cid = this->Makefile->GetDefinition(cidVar); if (cmNonempty(cid)) { cmakefileStream << "set(CMAKE_" << lang << "_COMPILER_ID \"" << *cid << "\")\n"; @@ -1960,11 +1960,11 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Store include transform rule properties. Write the directory // rules first because they may be overridden by later target rules. std::vector<std::string> transformRules; - if (cmProp xform = + if (cmValue xform = this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { cmExpandList(*xform, transformRules); } - if (cmProp xform = + if (cmValue xform = target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { cmExpandList(*xform, transformRules); } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 7b5fed61f42..9ad5f5661ec 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -69,7 +69,7 @@ void cmLocalVisualStudio7Generator::AddHelperCommands() if (!l->IsInBuildSystem()) { continue; } - cmProp path = l->GetProperty("EXTERNAL_MSPROJECT"); + cmValue path = l->GetProperty("EXTERNAL_MSPROJECT"); if (path) { this->ReadAndStoreExternalGUID(l->GetName(), path->c_str()); } @@ -582,7 +582,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( const std::string& libName, cmGeneratorTarget* target) { std::string mfcFlag; - if (cmProp p = this->Makefile->GetDefinition("CMAKE_MFC_FLAG")) { + if (cmValue p = this->Makefile->GetDefinition("CMAKE_MFC_FLAG")) { mfcFlag = cmGeneratorExpression::Evaluate(*p, this, configName); } else { mfcFlag = "0"; @@ -781,7 +781,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( fout << "\t\t\t<Tool\n" << "\t\t\t\tName=\"" << tool << "\"\n"; if (this->FortranProject) { - cmProp target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY"); + cmValue target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY"); std::string modDir; if (target_mod_dir) { modDir = this->MaybeRelativeToCurBinDir(*target_mod_dir); @@ -938,7 +938,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( " " + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName); } - cmProp targetLinkFlags = target->GetProperty("LINK_FLAGS"); + cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { extraLinkOptions += " "; extraLinkOptions += *targetLinkFlags; @@ -1077,7 +1077,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } } std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); - cmProp stackVal = this->Makefile->GetDefinition(stackVar); + cmValue stackVal = this->Makefile->GetDefinition(stackVar); if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << *stackVal << "\"\n"; } @@ -1168,7 +1168,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( << "\"\n"; } std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); - cmProp stackVal = this->Makefile->GetDefinition(stackVar); + cmValue stackVal = this->Makefile->GetDefinition(stackVar); if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << *stackVal << "\""; } @@ -1209,8 +1209,8 @@ void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool( std::ostream& fout, std::string const& config, cmGeneratorTarget* target) { if (this->WindowsCEProject) { - cmProp dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY"); - cmProp additionalFiles = + cmValue dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY"); + cmValue additionalFiles = target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES"); if (!dir && !additionalFiles) { @@ -1447,12 +1447,12 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( needfc = true; } const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (cmProp cflags = sf.GetProperty(COMPILE_FLAGS)) { + if (cmValue cflags = sf.GetProperty(COMPILE_FLAGS)) { fc.CompileFlags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS); needfc = true; } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (cmProp coptions = sf.GetProperty(COMPILE_OPTIONS)) { + if (cmValue coptions = sf.GetProperty(COMPILE_OPTIONS)) { lg->AppendCompileOptions( fc.CompileFlags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS)); @@ -1504,25 +1504,25 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( } } const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - if (cmProp cdefs = sf.GetProperty(COMPILE_DEFINITIONS)) { + if (cmValue cdefs = sf.GetProperty(COMPILE_DEFINITIONS)) { fc.CompileDefs = genexInterpreter.Evaluate(*cdefs, COMPILE_DEFINITIONS); needfc = true; } std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); - if (cmProp ccdefs = sf.GetProperty(defPropName)) { + if (cmValue ccdefs = sf.GetProperty(defPropName)) { fc.CompileDefsConfig = genexInterpreter.Evaluate(*ccdefs, COMPILE_DEFINITIONS); needfc = true; } const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (cmProp cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) { + if (cmValue cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) { fc.IncludeDirs = genexInterpreter.Evaluate(*cincs, INCLUDE_DIRECTORIES); needfc = true; } // Check for extra object-file dependencies. - if (cmProp deps = sf.GetProperty("OBJECT_DEPENDS")) { + if (cmValue deps = sf.GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(*deps); const char* sep = ""; for (const std::string& d : depends) { @@ -1897,9 +1897,9 @@ void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout, { // if we have all the required Source code control tags // then add that to the project - cmProp vsProjectname = target->GetProperty("VS_SCC_PROJECTNAME"); - cmProp vsLocalpath = target->GetProperty("VS_SCC_LOCALPATH"); - cmProp vsProvider = target->GetProperty("VS_SCC_PROVIDER"); + cmValue vsProjectname = target->GetProperty("VS_SCC_PROJECTNAME"); + cmValue vsLocalpath = target->GetProperty("VS_SCC_LOCALPATH"); + cmValue vsProvider = target->GetProperty("VS_SCC_PROVIDER"); if (vsProvider && vsLocalpath && vsProjectname) { /* clang-format off */ @@ -1908,7 +1908,7 @@ void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout, << "\tSccProvider=\"" << *vsProvider << "\"\n"; /* clang-format on */ - cmProp vsAuxPath = target->GetProperty("VS_SCC_AUXPATH"); + cmValue vsAuxPath = target->GetProperty("VS_SCC_AUXPATH"); if (vsAuxPath) { fout << "\tSccAuxPath=\"" << *vsAuxPath << "\"\n"; } @@ -1928,7 +1928,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran( << "\tProjectCreator=\"Intel Fortran\"\n" << "\tVersion=\"" << gg->GetIntelProjectVersion() << "\"\n"; /* clang-format on */ - cmProp p = target->GetProperty("VS_KEYWORD"); + cmValue p = target->GetProperty("VS_KEYWORD"); const char* keyword = p ? p->c_str() : "Console Application"; const char* projectType = 0; switch (target->GetType()) { @@ -1990,14 +1990,14 @@ void cmLocalVisualStudio7Generator::WriteProjectStart( << "\tProjectType=\"Visual C++\"\n"; /* clang-format on */ fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n"; - cmProp p = target->GetProperty("PROJECT_LABEL"); + cmValue p = target->GetProperty("PROJECT_LABEL"); const std::string projLabel = p ? *p : libName; p = target->GetProperty("VS_KEYWORD"); const std::string keyword = p ? *p : "Win32Proj"; fout << "\tName=\"" << projLabel << "\"\n"; fout << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\"\n"; this->WriteProjectSCC(fout, target); - if (cmProp targetFrameworkVersion = + if (cmValue targetFrameworkVersion = target->GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { fout << "\tTargetFrameworkVersion=\"" << *targetFrameworkVersion << "\"\n"; } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index acddfe16730..4ed1dd92bac 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -173,7 +173,8 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( // for visual studio IDE add extra stuff to the PATH // if CMAKE_MSVCIDE_RUN_PATH is set. if (this->GetGlobalGenerator()->IsVisualStudio()) { - cmProp extraPath = this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH"); + cmValue extraPath = + this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH"); if (extraPath) { script += newline; newline = newline_text; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 78c7246f496..17445340af7 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -190,7 +190,7 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) { // Warn if a <pkg>_ROOT variable we may use is set. std::string const varName = pkg + "_ROOT"; - cmProp var = this->GetDefinition(varName); + cmValue var = this->GetDefinition(varName); std::string env; cmSystemTools::GetEnv(varName, env); @@ -400,7 +400,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, // Check for maximum recursion depth. int depth = CMake_DEFAULT_RECURSION_LIMIT; - cmProp depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); + cmValue depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); if (depthStr) { std::istringstream s(*depthStr); int d; @@ -586,7 +586,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011() bool cmMakefile::ReadDependentFile(const std::string& filename, bool noPolicyScope) { - if (cmProp def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) { + if (cmValue def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) { this->AddDefinition("CMAKE_PARENT_LIST_FILE", *def); } std::string filenametoread = cmSystemTools::CollapseFullPath( @@ -924,7 +924,7 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg) void cmMakefile::Generate(cmLocalGenerator& lg) { this->DoGenerate(lg); - cmProp oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); + cmValue oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); if (oldValue && cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { this->GetCMakeInstance()->IssueMessage( @@ -1405,7 +1405,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) const char* define = def.c_str() + 2; if (remove) { - if (cmProp cdefs = this->GetProperty("COMPILE_DEFINITIONS")) { + if (cmValue cdefs = this->GetProperty("COMPILE_DEFINITIONS")) { // Expand the list. std::vector<std::string> defs = cmExpandedList(*cdefs); @@ -1449,7 +1449,7 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) for (std::string const& config : configs) { std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); - cmProp prop = parent->GetProperty(defPropName); + cmValue prop = parent->GetProperty(defPropName); this->SetProperty(defPropName, prop); } } @@ -1897,7 +1897,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, cmStateEnums::CacheEntryType type, bool force) { - cmProp existingValue = this->GetState()->GetInitializedCacheValue(name); + cmValue existingValue = this->GetState()->GetInitializedCacheValue(name); // must be outside the following if() to keep it alive long enough std::string nvalue; @@ -2015,7 +2015,7 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) default:; } - if (cmProp linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { + if (cmValue linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp); for (auto j = linkLibs.begin(); j != linkLibs.end(); ++j) { @@ -2213,7 +2213,7 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup( cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name) { std::string delimiters; - if (cmProp p = this->GetDefinition("SOURCE_GROUP_DELIMITER")) { + if (cmValue p = this->GetDefinition("SOURCE_GROUP_DELIMITER")) { delimiters = *p; } else { delimiters = "/\\"; @@ -2266,7 +2266,7 @@ void cmMakefile::ExpandVariablesCMP0019() } std::ostringstream w; - cmProp includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); + cmValue includeDirs = this->GetProperty("INCLUDE_DIRECTORIES"); if (includeDirs && mightExpandVariablesCMP0019(includeDirs->c_str())) { std::string dirs = *includeDirs; this->ExpandVariablesInString(dirs, true, true); @@ -2304,7 +2304,7 @@ void cmMakefile::ExpandVariablesCMP0019() } } - if (cmProp linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { + if (cmValue linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) { if (mightExpandVariablesCMP0019(linkDirsProp->c_str())) { std::string d = *linkDirsProp; const std::string orig = d; @@ -2320,7 +2320,7 @@ void cmMakefile::ExpandVariablesCMP0019() } } - if (cmProp linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { + if (cmValue linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp); for (auto l = linkLibs.begin(); l != linkLibs.end(); ++l) { @@ -2364,7 +2364,7 @@ bool cmMakefile::IsOn(const std::string& name) const bool cmMakefile::IsSet(const std::string& name) const { - cmProp value = this->GetDefinition(name); + cmValue value = this->GetDefinition(name); if (!value) { return false; } @@ -2382,12 +2382,12 @@ bool cmMakefile::IsSet(const std::string& name) const bool cmMakefile::PlatformIs32Bit() const { - if (cmProp plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { + if (cmValue plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { if (*plat_abi == "ELF X32") { return false; } } - if (cmProp sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { + if (cmValue sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { return atoi(sizeof_dptr->c_str()) == 4; } return false; @@ -2395,7 +2395,7 @@ bool cmMakefile::PlatformIs32Bit() const bool cmMakefile::PlatformIs64Bit() const { - if (cmProp sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { + if (cmValue sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { return atoi(sizeof_dptr->c_str()) == 8; } return false; @@ -2403,7 +2403,7 @@ bool cmMakefile::PlatformIs64Bit() const bool cmMakefile::PlatformIsx32() const { - if (cmProp plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { + if (cmValue plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { if (*plat_abi == "ELF X32") { return true; } @@ -2476,7 +2476,7 @@ const std::string& cmMakefile::GetRequiredDefinition( const std::string& name) const { static std::string const empty; - cmProp def = this->GetDefinition(name); + cmValue def = this->GetDefinition(name); if (!def) { cmSystemTools::Error("Error required internal CMake variable not " "set, cmake may not be built correctly.\n" @@ -2489,7 +2489,7 @@ const std::string& cmMakefile::GetRequiredDefinition( bool cmMakefile::IsDefinitionSet(const std::string& name) const { - cmProp def = this->StateSnapshot.GetDefinition(name); + cmValue def = this->StateSnapshot.GetDefinition(name); if (!def) { def = this->GetState()->GetInitializedCacheValue(name); } @@ -2506,7 +2506,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const { - cmProp def = this->StateSnapshot.GetDefinition(name); + cmValue def = this->StateSnapshot.GetDefinition(name); #ifndef CMAKE_BOOTSTRAP if (cmVariableWatch* vv = this->GetVariableWatch()) { if (!def) { @@ -2518,9 +2518,9 @@ bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const return def != nullptr; } -cmProp cmMakefile::GetDefinition(const std::string& name) const +cmValue cmMakefile::GetDefinition(const std::string& name) const { - cmProp def = this->StateSnapshot.GetDefinition(name); + cmValue def = this->StateSnapshot.GetDefinition(name); if (!def) { def = this->GetState()->GetInitializedCacheValue(name); } @@ -2556,7 +2556,7 @@ bool cmMakefile::GetDefExpandList(const std::string& name, std::vector<std::string>& out, bool emptyArgs) const { - cmProp def = this->GetDefinition(name); + cmValue def = this->GetDefinition(name); if (!def) { return false; } @@ -2709,7 +2709,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld( // Lookup the definition of VAR. std::string var(first + 1, last - first - 2); - if (cmProp val = this->GetDefinition(var)) { + if (cmValue val = this->GetDefinition(var)) { // Store the value in the output escaping as requested. if (escapeQuotes) { source.append(cmEscapeQuotes(*val)); @@ -2914,7 +2914,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( openstack.pop_back(); result.append(last, in - last); std::string const& lookup = result.substr(var.loc); - cmProp value = nullptr; + cmValue value = nullptr; std::string varresult; std::string svalue; switch (var.domain) { @@ -2932,7 +2932,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( break; case ENVIRONMENT: if (cmSystemTools::GetEnv(lookup, svalue)) { - value = cmProp(svalue); + value = cmValue(svalue); } break; case CACHE: @@ -3059,7 +3059,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( if (filename && variable == lineVar) { varresult = std::to_string(line); } else { - cmProp def = this->GetDefinition(variable); + cmValue def = this->GetDefinition(variable); if (def) { varresult = *def; } else if (!this->SuppressSideEffects) { @@ -3555,7 +3555,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET")); cm.LoadCache(); if (!cm.GetGlobalGenerator()->IsMultiConfig()) { - if (cmProp config = + if (cmValue config = this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION")) { // Tell the single-configuration generator which one to use. // Add this before the user-provided CMake arguments in case @@ -3564,7 +3564,8 @@ int cmMakefile::TryCompile(const std::string& srcdir, cmStateEnums::STRING); } } - cmProp recursionDepth = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); + cmValue recursionDepth = + this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); if (recursionDepth) { cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth, "Maximum recursion depth", cmStateEnums::STRING); @@ -3699,7 +3700,7 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, std::string moduleInCMakeModulePath; // Always search in CMAKE_MODULE_PATH: - cmProp cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH"); + cmValue cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH"); if (cmakeModulePath) { std::vector<std::string> modulePath = cmExpandedList(*cmakeModulePath); @@ -3740,7 +3741,7 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, } if (!moduleInCMakeModulePath.empty() && !moduleInCMakeRoot.empty()) { - cmProp currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE"); + cmValue currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE"); std::string mods = cmSystemTools::GetCMakeRoot() + "/Modules/"; if (currentFile && cmSystemTools::IsSubDirectory(*currentFile, mods)) { switch (this->GetPolicyStatus(cmPolicies::CMP0017)) { @@ -3797,7 +3798,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, // Replace #cmakedefine instances. if (this->cmDefineRegex.find(line)) { - cmProp def = this->GetDefinition(this->cmDefineRegex.match(2)); + cmValue def = this->GetDefinition(this->cmDefineRegex.match(2)); if (!cmIsOff(def)) { const std::string indentation = this->cmDefineRegex.match(1); cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine", @@ -3810,7 +3811,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, } } else if (this->cmDefine01Regex.find(line)) { const std::string indentation = this->cmDefine01Regex.match(1); - cmProp def = this->GetDefinition(this->cmDefine01Regex.match(2)); + cmValue def = this->GetDefinition(this->cmDefine01Regex.match(2)); cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine01", "#" + indentation + "define"); output += line; @@ -3956,7 +3957,7 @@ void cmMakefile::SetProperty(const std::string& prop, const char* value) { this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace); } -void cmMakefile::SetProperty(const std::string& prop, cmProp value) +void cmMakefile::SetProperty(const std::string& prop, cmValue value) { this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace); } @@ -3968,7 +3969,7 @@ void cmMakefile::AppendProperty(const std::string& prop, this->Backtrace); } -cmProp cmMakefile::GetProperty(const std::string& prop) const +cmValue cmMakefile::GetProperty(const std::string& prop) const { // Check for computed properties. static std::string output; @@ -3981,13 +3982,13 @@ cmProp cmMakefile::GetProperty(const std::string& prop) const return pair.first; }); output = cmJoin(keys, ";"); - return cmProp(output); + return cmValue(output); } return this->StateSnapshot.GetDirectory().GetProperty(prop); } -cmProp cmMakefile::GetProperty(const std::string& prop, bool chain) const +cmValue cmMakefile::GetProperty(const std::string& prop, bool chain) const { return this->StateSnapshot.GetDirectory().GetProperty(prop, chain); } @@ -4046,7 +4047,7 @@ void cmMakefile::GetTests(const std::string& config, void cmMakefile::AddCMakeDependFilesFromUser() { std::vector<std::string> deps; - if (cmProp deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) { + if (cmValue deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) { cmExpandList(*deps_str, deps); } for (std::string const& dep : deps) { @@ -4335,7 +4336,7 @@ static std::string const nMatchesVariable = "CMAKE_MATCH_COUNT"; void cmMakefile::ClearMatches() { - cmProp nMatchesStr = this->GetDefinition(nMatchesVariable); + cmValue nMatchesStr = this->GetDefinition(nMatchesVariable); if (!nMatchesStr) { return; } @@ -4388,7 +4389,7 @@ cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id, bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) const { // Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting. - if (cmProp val = this->GetDefinition(var)) { + if (cmValue val = this->GetDefinition(var)) { return cmIsOn(val); } // Enable optional policy warnings with --debug-output, --trace, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index bad9d914998..671cdab4690 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -29,10 +29,10 @@ #include "cmMessageType.h" #include "cmNewLineStyle.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmSourceFileLocationKind.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmValue.h" // IWYU does not see that 'std::unordered_map<std::string, cmTarget>' // will not compile without the complete type. @@ -286,7 +286,7 @@ class cmMakefile * can be used in CMake to refer to lists, directories, etc. */ void AddDefinition(const std::string& name, cm::string_view value); - void AddDefinition(const std::string& name, cmProp value) + void AddDefinition(const std::string& name, cmValue value) { this->AddDefinition(name, *value); } @@ -492,7 +492,7 @@ class cmMakefile * If the variable is not found in this makefile instance, the * cache is then queried. */ - cmProp GetDefinition(const std::string&) const; + cmValue GetDefinition(const std::string&) const; const std::string& GetSafeDefinition(const std::string&) const; const std::string& GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; @@ -772,15 +772,15 @@ class cmMakefile //! Set/Get a property of this directory void SetProperty(const std::string& prop, const char* value); - void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, cmValue value); void SetProperty(const std::string& prop, const std::string& value) { - this->SetProperty(prop, cmProp(value)); + this->SetProperty(prop, cmValue(value)); } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); - cmProp GetProperty(const std::string& prop) const; - cmProp GetProperty(const std::string& prop, bool chain) const; + cmValue GetProperty(const std::string& prop) const; + cmValue GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; std::vector<std::string> GetPropertyKeys() const; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 306b38f6c1e..575fb05693a 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -21,7 +21,6 @@ #include "cmMakefile.h" #include "cmOSXBundleGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRulePlaceholderExpander.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -29,6 +28,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( cmGeneratorTarget* target) @@ -228,8 +228,8 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( std::string launcher; - cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, - "RULE_LAUNCH_LINK"); + cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, + "RULE_LAUNCH_LINK"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); } @@ -577,7 +577,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } if (this->UseLWYU) { - cmProp lwyuCheck = + cmValue lwyuCheck = this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); if (lwyuCheck) { std::string cmakeCommand = cmStrCat( @@ -592,8 +592,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string launcher; - cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, - "RULE_LAUNCH_LINK"); + cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, + "RULE_LAUNCH_LINK"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); } diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 64992f2d4e5..ace73a77ed1 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -21,7 +21,6 @@ #include "cmMakefile.h" #include "cmOSXBundleGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRulePlaceholderExpander.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -29,6 +28,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( cmGeneratorTarget* target) @@ -362,8 +362,8 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); std::string launcher; - cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, - "RULE_LAUNCH_LINK"); + cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, + "RULE_LAUNCH_LINK"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); } @@ -811,8 +811,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } std::string launcher; - cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, - "RULE_LAUNCH_LINK"); + cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget, + "RULE_LAUNCH_LINK"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); } @@ -872,7 +872,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string linkRule = this->GetLinkRule(linkRuleVar); cmExpandList(linkRule, real_link_commands); if (this->UseLWYU) { - cmProp lwyuCheck = + cmValue lwyuCheck = this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); if (lwyuCheck) { std::string cmakeCommand = cmStrCat( diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 70b6d27352f..0cbc741b58d 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -34,7 +34,6 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -45,6 +44,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) @@ -57,7 +57,8 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) this->LocalGenerator->GetGlobalGenerator()); cmake* cm = this->GlobalGenerator->GetCMakeInstance(); this->NoRuleMessages = false; - if (cmProp ruleStatus = cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { + if (cmValue ruleStatus = + cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { this->NoRuleMessages = cmIsOff(*ruleStatus); } switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) { @@ -200,14 +201,14 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() }; // Look for additional files registered for cleaning in this directory. - if (cmProp prop_value = + if (cmValue prop_value = this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) { std::vector<std::string> const files = evaluatedFiles(*prop_value); this->CleanFiles.insert(files.begin(), files.end()); } // Look for additional files registered for cleaning in this target. - if (cmProp prop_value = + if (cmValue prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector<std::string> const files = evaluatedFiles(*prop_value); // For relative path support @@ -287,7 +288,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator.get(), this->GetConfigName()); - cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, this->GetConfigName()); @@ -668,12 +669,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmSystemTools::GetFilenameWithoutLastExtension(objectName); ispcSource = cmSystemTools::GetFilenameWithoutLastExtension(ispcSource); - cmProp ispcSuffixProp = + cmValue ispcSuffixProp = this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX"); assert(ispcSuffixProp); std::string directory = this->GeneratorTarget->GetObjectDirectory(config); - if (cmProp prop = + if (cmValue prop = this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) { directory = cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop); @@ -685,7 +686,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Add flags from source file properties. const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (cmProp cflags = source.GetProperty(COMPILE_FLAGS)) { + if (cmValue cflags = source.GetProperty(COMPILE_FLAGS)) { const std::string& evaluatedFlags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS); this->LocalGenerator->AppendFlags(flags, evaluatedFlags); @@ -695,7 +696,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (cmProp coptions = source.GetProperty(COMPILE_OPTIONS)) { + if (cmValue coptions = source.GetProperty(COMPILE_OPTIONS)) { const std::string& evaluatedOptions = genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS); this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions); @@ -729,7 +730,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::vector<std::string> includes; const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (cmProp cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) { + if (cmValue cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) { const std::string& evaluatedIncludes = genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES); this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes, @@ -745,7 +746,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Add source-specific preprocessor definitions. const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - if (cmProp compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) { + if (cmValue compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) { const std::string& evaluatedDefs = genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS); this->LocalGenerator->AppendDefines(defines, evaluatedDefs); @@ -754,7 +755,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( << "\n"; } std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); - if (cmProp config_compile_defs = source.GetProperty(defPropName)) { + if (cmValue config_compile_defs = source.GetProperty(defPropName)) { const std::string& evaluatedDefs = genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS); this->LocalGenerator->AppendDefines(defines, evaluatedDefs); @@ -944,11 +945,11 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->GetIncludes(lang, this->GetConfigName())); } - cmProp eliminate[] = { + cmValue eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE") }; - for (cmProp el : eliminate) { + for (cmValue el : eliminate) { if (el) { cmSystemTools::ReplaceString(compileCommand, *el, ""); } @@ -965,7 +966,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( lang == "HIP" || lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; - cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); + cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (cmNonempty(clauncher)) { compilerLauncher = *clauncher; } @@ -975,10 +976,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( if (!compileCommands.empty() && (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) { std::string const tidy_prop = lang + "_CLANG_TIDY"; - cmProp tidy = this->GeneratorTarget->GetProperty(tidy_prop); - cmProp iwyu = nullptr; - cmProp cpplint = nullptr; - cmProp cppcheck = nullptr; + cmValue tidy = this->GeneratorTarget->GetProperty(tidy_prop); + cmValue iwyu = nullptr; + cmValue cpplint = nullptr; + cmValue cppcheck = nullptr; if (lang == "C" || lang == "CXX") { std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE"; iwyu = this->GeneratorTarget->GetProperty(iwyu_prop); @@ -1003,7 +1004,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Only add --driver-mode if it is not already specified, as adding // it unconditionally might override a user-specified driver-mode if (iwyu.Get()->find("--driver-mode=") == std::string::npos) { - cmProp p = this->Makefile->GetDefinition( + cmValue p = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE")); std::string driverMode; @@ -1021,8 +1022,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } if (cmNonempty(tidy)) { run_iwyu += " --tidy="; - cmProp p = this->Makefile->GetDefinition("CMAKE_" + lang + - "_CLANG_TIDY_DRIVER_MODE"); + cmValue p = this->Makefile->GetDefinition("CMAKE_" + lang + + "_CLANG_TIDY_DRIVER_MODE"); std::string driverMode; if (cmNonempty(p)) { driverMode = *p; @@ -1066,7 +1067,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string launcher; { - cmProp val = this->LocalGenerator->GetRuleLauncher( + cmValue val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_COMPILE"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); @@ -1136,7 +1137,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Check for extra outputs created by the compilation. std::vector<std::string> outputs(1, relativeObj); - if (cmProp extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) { + if (cmValue extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) { std::string evaluated_outputs = cmGeneratorExpression::Evaluate( *extra_outputs_str, this->LocalGenerator, config); @@ -1191,7 +1192,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string preprocessRuleVar = cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE"); - if (cmProp preprocessRule = + if (cmValue preprocessRule = this->Makefile->GetDefinition(preprocessRuleVar)) { std::vector<std::string> preprocessCommands = cmExpandedList(*preprocessRule); @@ -1236,7 +1237,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string assemblyRuleVar = cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE"); - if (cmProp assemblyRule = + if (cmValue assemblyRule = this->Makefile->GetDefinition(assemblyRuleVar)) { std::vector<std::string> assemblyCommands = cmExpandedList(*assemblyRule); @@ -1507,7 +1508,7 @@ void cmMakefileTargetGenerator::WriteObjectDependRules( // Create the list of dependencies known at cmake time. These are // shared between the object file and dependency scanning rule. depends.push_back(source.GetFullPath()); - if (cmProp objectDeps = source.GetProperty("OBJECT_DEPENDS")) { + if (cmValue objectDeps = source.GetProperty("OBJECT_DEPENDS")) { cmExpandList(*objectDeps, depends); } } @@ -1746,7 +1747,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( std::string object; const auto& lineContinue = this->GlobalGenerator->LineContinueDirective; - cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); for (std::string const& obj : this->Objects) { if (cmHasSuffix(obj, pchExtension)) { @@ -1833,7 +1834,7 @@ class cmMakefileTargetGeneratorObjectStrings void cmMakefileTargetGenerator::WriteObjectsStrings( std::vector<std::string>& objStrings, std::string::size_type limit) { - cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); cmMakefileTargetGeneratorObjectStrings helper( objStrings, this->LocalGenerator, @@ -1968,7 +1969,7 @@ std::string cmMakefileTargetGenerator::GetLinkRule( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_GNUtoMS_RULE"); - if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) { + if (cmValue rule = this->Makefile->GetDefinition(ruleVar)) { linkRule += *rule; } } @@ -2017,7 +2018,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects( // Check for an explicit setting one way or the other. std::string const responseVar = "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS"; - if (cmProp val = this->Makefile->GetDefinition(responseVar)) { + if (cmValue val = this->Makefile->GetDefinition(responseVar)) { if (!val->empty()) { return cmIsOn(val); } @@ -2056,7 +2057,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries( // Check for an explicit setting one way or the other. std::string const responseVar = "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES"; - if (cmProp val = this->Makefile->GetDefinition(responseVar)) { + if (cmValue val = this->Makefile->GetDefinition(responseVar)) { if (!val->empty()) { return cmIsOn(val); } @@ -2120,7 +2121,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs( this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_RESPONSE_FILE_LINK_FLAG"); std::string responseFlag; - if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) { + if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) { responseFlag = *p; } else { responseFlag = "@"; @@ -2160,7 +2161,7 @@ void cmMakefileTargetGenerator::CreateObjectLists( this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_RESPONSE_FILE_LINK_FLAG"); std::string responseFlag; - if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) { + if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) { responseFlag = *p; } else { responseFlag = "@"; @@ -2255,7 +2256,7 @@ void cmMakefileTargetGenerator::GenDefFile( cmd += this->LocalGenerator->ConvertToOutputFormat( this->LocalGenerator->MaybeRelativeToCurBinDir(objlist_file), cmOutputConverter::SHELL); - cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); + cmValue nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); if (cmNonempty(nm_executable)) { cmd += " --nm="; cmd += this->LocalCommonGenerator->ConvertToOutputFormat( diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx index 5908f7472d6..73e5f33b5d4 100644 --- a/Source/cmMarkAsAdvancedCommand.cxx +++ b/Source/cmMarkAsAdvancedCommand.cxx @@ -6,11 +6,11 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" // cmMarkAsAdvancedCommand diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 96e914279f3..596084b7636 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -32,7 +32,6 @@ #include "cmNinjaTypes.h" #include "cmOSXBundleGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmState.h" @@ -41,6 +40,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( cmGeneratorTarget* target) @@ -267,7 +267,7 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule( vars.LanguageCompileFlags = "$LANGUAGE_COMPILE_FLAGS"; std::string launcher; - cmProp val = this->GetLocalGenerator()->GetRuleLauncher( + cmValue val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); @@ -390,7 +390,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; - cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); + cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); if (flag) { responseFlag = *flag; @@ -462,7 +462,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, } std::string launcher; - cmProp val = this->GetLocalGenerator()->GetRuleLauncher( + cmValue val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); @@ -569,20 +569,20 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( // CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead. std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable( this->TargetLinkLanguage(config), config); - cmProp linkCmd = mf->GetDefinition(linkCmdVar); + cmValue linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { std::string linkCmdStr = *linkCmd; if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) { std::string ruleVar = cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config), "_GNUtoMS_RULE"); - if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) { + if (cmValue rule = this->Makefile->GetDefinition(ruleVar)) { linkCmdStr += *rule; } } cmExpandList(linkCmdStr, linkCmds); if (this->UseLWYU) { - cmProp lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + cmValue lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); if (lwyuCheck) { std::string cmakeCommand = cmStrCat( this->GetLocalGenerator()->ConvertToOutputFormat( @@ -1044,7 +1044,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( }(); vars["SWIFT_MODULE_NAME"] = [gt]() -> std::string { - if (cmProp name = gt->GetProperty("Swift_MODULE_NAME")) { + if (cmValue name = gt->GetProperty("Swift_MODULE_NAME")) { return *name; } return gt->GetName(); @@ -1053,13 +1053,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( vars["SWIFT_MODULE"] = [this](const std::string& module) -> std::string { std::string directory = this->GetLocalGenerator()->GetCurrentBinaryDirectory(); - if (cmProp prop = this->GetGeneratorTarget()->GetProperty( + if (cmValue prop = this->GetGeneratorTarget()->GetProperty( "Swift_MODULE_DIRECTORY")) { directory = *prop; } std::string name = module + ".swiftmodule"; - if (cmProp prop = + if (cmValue prop = this->GetGeneratorTarget()->GetProperty("Swift_MODULE")) { name = *prop; } @@ -1231,7 +1231,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( gt->GetFullNameComponents(prefix, base, suffix, config); std::string dbg_suffix = ".dbg"; // TODO: Where to document? - if (cmProp d = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) { + if (cmValue d = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) { dbg_suffix = *d; } vars["TARGET_PDB"] = base + suffix + dbg_suffix; @@ -1297,7 +1297,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( cmd += this->GetLocalGenerator()->ConvertToOutputFormat( obj_list_file, cmOutputConverter::SHELL); - cmProp nm_executable = this->GetMakefile()->GetDefinition("CMAKE_NM"); + cmValue nm_executable = this->GetMakefile()->GetDefinition("CMAKE_NM"); if (cmNonempty(nm_executable)) { cmd += " --nm="; cmd += this->LocalCommonGenerator->ConvertToOutputFormat( @@ -1351,7 +1351,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; - cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); + cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = !(this->TargetLinkLanguage(config) == "RC" || diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 7cc158108a9..57fc020abb5 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -31,7 +31,6 @@ #include "cmNinjaNormalTargetGenerator.h" #include "cmNinjaUtilityTargetGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -40,6 +39,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New( @@ -224,13 +224,13 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( this->LocalGenerator, config, this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); - if (cmProp cflags = source->GetProperty(COMPILE_FLAGS)) { + if (cmValue cflags = source->GetProperty(COMPILE_FLAGS)) { this->LocalGenerator->AppendFlags( flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS)); } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (cmProp coptions = source->GetProperty(COMPILE_OPTIONS)) { + if (cmValue coptions = source->GetProperty(COMPILE_OPTIONS)) { this->LocalGenerator->AppendCompileOptions( flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS)); } @@ -290,14 +290,14 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, } const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - if (cmProp compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { + if (cmValue compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { this->LocalGenerator->AppendDefines( defines, genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS)); } std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); - if (cmProp config_compile_defs = source->GetProperty(defPropName)) { + if (cmValue config_compile_defs = source->GetProperty(defPropName)) { this->LocalGenerator->AppendDefines( defines, genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS)); @@ -318,7 +318,7 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( this->LocalGenerator, config, this->GeneratorTarget, language); const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (cmProp cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { + if (cmValue cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) { this->LocalGenerator->AppendIncludeDirectories( includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES), *source); @@ -638,7 +638,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmLocalGenerator::SHELL); std::string launcher; - cmProp val = this->GetLocalGenerator()->GetRuleLauncher( + cmValue val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE"); if (cmNonempty(val)) { launcher = cmStrCat(*val, ' '); @@ -771,7 +771,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, if (!mf->GetIsSourceFileTryCompile()) { rule.DepType = "gcc"; rule.DepFile = "$DEP_FILE"; - cmProp d = mf->GetDefinition("CMAKE_C_COMPILER"); + cmValue d = mf->GetDefinition("CMAKE_C_COMPILER"); const std::string cl = d ? *d : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); std::string cmcldepsPath; @@ -843,7 +843,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, lang == "HIP" || lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER"); - cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); + cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (cmNonempty(clauncher)) { compilerLauncher = *clauncher; } @@ -853,10 +853,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, if (!compileCmds.empty() && (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) { std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY"); - cmProp tidy = this->GeneratorTarget->GetProperty(tidy_prop); - cmProp iwyu = nullptr; - cmProp cpplint = nullptr; - cmProp cppcheck = nullptr; + cmValue tidy = this->GeneratorTarget->GetProperty(tidy_prop); + cmValue iwyu = nullptr; + cmValue cpplint = nullptr; + cmValue cppcheck = nullptr; if (lang == "C" || lang == "CXX") { std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE"); iwyu = this->GeneratorTarget->GetProperty(iwyu_prop); @@ -882,7 +882,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, // Only add --driver-mode if it is not already specified, as adding // it unconditionally might override a user-specified driver-mode if (iwyu.Get()->find("--driver-mode=") == std::string::npos) { - cmProp p = this->Makefile->GetDefinition( + cmValue p = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE")); std::string driverMode; @@ -900,7 +900,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, } if (cmNonempty(tidy)) { run_iwyu += " --tidy="; - cmProp p = this->Makefile->GetDefinition( + cmValue p = this->Makefile->GetDefinition( cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE")); std::string driverMode; if (cmNonempty(p)) { @@ -1007,7 +1007,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( config); } if (firstForConfig) { - cmProp pchExtension = + cmValue pchExtension = this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; @@ -1112,7 +1112,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( "output-file-map.json"); std::string const targetSwiftDepsPath = [this, config]() -> std::string { cmGeneratorTarget const* target = this->GeneratorTarget; - if (cmProp name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { + if (cmValue name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { return *name; } return this->ConvertToNinjaPath( @@ -1236,7 +1236,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // build response file name std::string cmakeLinkVar = cmStrCat(cmakeVarLang, "_RESPONSE_FILE_FLAG"); - cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); + cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = !(language == "RC" || (language == "CUDA" && !flag)); @@ -1278,7 +1278,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild.Outputs.push_back(objectFileName); if (firstForConfig) { - cmProp pchExtension = + cmValue pchExtension = this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); if (!cmHasSuffix(objectFileName, pchExtension)) { // Add this object to the list of object files. @@ -1318,7 +1318,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } } - if (cmProp objectDeps = source->GetProperty("OBJECT_DEPENDS")) { + if (cmValue objectDeps = source->GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> objDepList = cmExpandedList(*objectDeps); std::copy(objDepList.begin(), objDepList.end(), std::back_inserter(depList)); @@ -1464,13 +1464,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmSystemTools::GetFilenameWithoutLastExtension(objectName); ispcSource = cmSystemTools::GetFilenameWithoutLastExtension(ispcSource); - cmProp ispcSuffixProp = + cmValue ispcSuffixProp = this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX"); assert(ispcSuffixProp); std::string ispcHeaderDirectory = this->GeneratorTarget->GetObjectDirectory(config); - if (cmProp prop = + if (cmValue prop = this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) { ispcHeaderDirectory = cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop); @@ -1521,7 +1521,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild, commandLineLengthLimit); } - if (cmProp objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { + if (cmValue objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { std::string evaluatedObjectOutputs = cmGeneratorExpression::Evaluate( *objectOutputs, this->LocalGenerator, config); @@ -1601,13 +1601,13 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( std::string const objectFilePath = this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const swiftDepsPath = [source, objectFilePath]() -> std::string { - if (cmProp name = source->GetProperty("Swift_DEPENDENCIES_FILE")) { + if (cmValue name = source->GetProperty("Swift_DEPENDENCIES_FILE")) { return *name; } return cmStrCat(objectFilePath, ".swiftdeps"); }(); std::string const swiftDiaPath = [source, objectFilePath]() -> std::string { - if (cmProp name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) { + if (cmValue name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) { return *name; } return cmStrCat(objectFilePath, ".dia"); @@ -1715,7 +1715,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) { - if (cmProp prop_value = + if (cmValue prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmLocalNinjaGenerator* lg = this->LocalGenerator; std::vector<std::string> cleanFiles; @@ -1805,7 +1805,7 @@ void cmNinjaTargetGenerator::addPoolNinjaVariable( const std::string& pool_property, cmGeneratorTarget* target, cmNinjaVars& vars) { - cmProp pool = target->GetProperty(pool_property); + cmValue pool = target->GetProperty(pool_property); if (pool) { vars["pool"] = *pool; } diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 1f5a7ff4c5b..15197ba27c9 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -18,12 +18,12 @@ #include "cmLocalNinjaGenerator.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmGeneratorTarget* target) @@ -141,7 +141,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements( std::string command = lg->BuildCommandLine( commands, config, fileConfig, "utility", this->GeneratorTarget); std::string desc; - cmProp echoStr = genTarget->GetProperty("EchoString"); + cmValue echoStr = genTarget->GetProperty("EchoString"); if (echoStr) { desc = *echoStr; } else { diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 014da4d2f24..2c4a77475c8 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -6,11 +6,11 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" // cmOptionCommand bool cmOptionCommand(std::vector<std::string> const& args, @@ -53,7 +53,7 @@ bool cmOptionCommand(std::vector<std::string> const& args, // See if a cache variable with this name already exists // If so just make sure the doc state is correct cmState* state = status.GetMakefile().GetState(); - cmProp existingValue = state->GetCacheEntryValue(args[0]); + cmValue existingValue = state->GetCacheEntryValue(args[0]); if (existingValue && (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) { state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]); diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index d589614d7e3..ad276d2f703 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -15,11 +15,11 @@ #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" namespace { /** \class cmDependInformation @@ -118,7 +118,7 @@ class cmLBDepend std::set<std::string> uniqueIncludes; std::vector<std::string> orderedAndUniqueIncludes; for (auto const& target : this->Makefile->GetTargets()) { - cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); + cmValue incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES"); if (!incDirProp) { continue; } diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 246506978f4..9f3fd00d3aa 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -13,10 +13,10 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" static std::string EscapeArg(const std::string& arg) { @@ -196,7 +196,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args, for (unsigned long i = argvStart; i < count; ++i) { std::ostringstream argName; argName << "ARGV" << i; - cmProp arg = status.GetMakefile().GetDefinition(argName.str()); + cmValue arg = status.GetMakefile().GetDefinition(argName.str()); if (!arg) { status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, "PARSE_ARGV called with " + diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index fc839c537ec..23000fae681 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -10,12 +10,12 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" static bool stringToId(const char* input, cmPolicies::PolicyID& pid) diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 6950c19efa7..20fcdbed9f3 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -15,10 +15,10 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" static bool IncludeByVariable(cmExecutionStatus& status, const std::string& variable); @@ -308,7 +308,7 @@ bool cmProjectCommand(std::vector<std::string> const& args, } std::string vw; for (std::string const& i : vv) { - cmProp v = mf.GetDefinition(i); + cmValue v = mf.GetDefinition(i); if (cmNonempty(v)) { if (cmp0048 == cmPolicies::WARN) { if (!injectedProjectCommand) { @@ -358,7 +358,7 @@ static bool IncludeByVariable(cmExecutionStatus& status, const std::string& variable) { cmMakefile& mf = status.GetMakefile(); - cmProp include = mf.GetDefinition(variable); + cmValue include = mf.GetDefinition(variable); if (!include) { return true; } diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 9d83df4ee27..07811092e17 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -4,12 +4,6 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <cstddef> -#include <iosfwd> -#include <string> - -#include <cm/string_view> - class cmProperty { public: @@ -26,206 +20,3 @@ class cmProperty INSTALL }; }; - -class cmProp -{ -public: - cmProp() noexcept = default; - cmProp(std::nullptr_t) noexcept {} - explicit cmProp(const std::string* value) noexcept - : Value(value) - { - } - explicit cmProp(const std::string& value) noexcept - : Value(&value) - { - } - cmProp(const cmProp& other) noexcept = default; - - cmProp& operator=(const cmProp& other) noexcept = default; - cmProp& operator=(std::nullptr_t) noexcept - { - this->Value = nullptr; - return *this; - } - - const std::string* Get() const noexcept { return this->Value; } - const char* GetCStr() const noexcept - { - return this->Value == nullptr ? nullptr : this->Value->c_str(); - } - - const std::string* operator->() const noexcept - { - return this->Value == nullptr ? &cmProp::Empty : this->Value; - } - const std::string& operator*() const noexcept - { - return this->Value == nullptr ? cmProp::Empty : *this->Value; - } - - explicit operator bool() const noexcept { return this->Value != nullptr; } - operator const std::string&() const noexcept { return this->operator*(); } - explicit operator cm::string_view() const noexcept - { - return this->operator*(); - } - - /** - * Does the value indicate a true or ON value? - */ - bool IsOn() const noexcept - { - return this->Value != nullptr && - cmProp::IsOn(cm::string_view(*this->Value)); - } - /** - * Does the value indicate a false or off value ? Note that this is - * not the same as !IsOn(...) because there are a number of - * ambiguous values such as "/usr/local/bin" a path will result in - * IsOn and IsOff both returning false. Note that the special path - * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. - */ - bool IsOff() const noexcept - { - return this->Value == nullptr || - cmProp::IsOff(cm::string_view(*this->Value)); - } - /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ - bool IsNOTFOUND() const noexcept - { - return this->Value != nullptr && - cmProp::IsNOTFOUND(cm::string_view(*this->Value)); - } - bool IsEmpty() const noexcept - { - return this->Value == nullptr || this->Value->empty(); - } - - bool IsSet() const noexcept - { - return !this->IsEmpty() && !this->IsNOTFOUND(); - } - - /** - * Does a string indicate a true or ON value? - */ - static bool IsOn(const char* value) noexcept - { - return value != nullptr && IsOn(cm::string_view(value)); - } - static bool IsOn(cm::string_view) noexcept; - - /** - * Compare method has same semantic as std::optional::compare - */ - int Compare(cmProp value) const noexcept; - int Compare(cm::string_view value) const noexcept; - - /** - * Does a string indicate a false or off value ? Note that this is - * not the same as !IsOn(...) because there are a number of - * ambiguous values such as "/usr/local/bin" a path will result in - * IsOn and IsOff both returning false. Note that the special path - * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. - */ - static bool IsOff(const char* value) noexcept - { - return value == nullptr || IsOff(cm::string_view(value)); - } - static bool IsOff(cm::string_view) noexcept; - - /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ - static bool IsNOTFOUND(const char* value) noexcept - { - return value == nullptr || IsNOTFOUND(cm::string_view(value)); - } - static bool IsNOTFOUND(cm::string_view) noexcept; - - static bool IsEmpty(const char* value) noexcept - { - return value == nullptr || *value == '\0'; - } - static bool IsEmpty(cm::string_view value) noexcept { return value.empty(); } - -private: - static std::string Empty; - const std::string* Value = nullptr; -}; - -std::ostream& operator<<(std::ostream& o, cmProp v); - -inline bool operator==(cmProp l, cmProp r) noexcept -{ - return l.Compare(r) == 0; -} -inline bool operator!=(cmProp l, cmProp r) noexcept -{ - return l.Compare(r) != 0; -} -inline bool operator<(cmProp l, cmProp r) noexcept -{ - return l.Compare(r) < 0; -} -inline bool operator<=(cmProp l, cmProp r) noexcept -{ - return l.Compare(r) <= 0; -} -inline bool operator>(cmProp l, cmProp r) noexcept -{ - return l.Compare(r) > 0; -} -inline bool operator>=(cmProp l, cmProp r) noexcept -{ - return l.Compare(r) >= 0; -} - -inline bool operator==(cmProp l, cm::string_view r) noexcept -{ - return l.Compare(r) == 0; -} -inline bool operator!=(cmProp l, cm::string_view r) noexcept -{ - return l.Compare(r) != 0; -} -inline bool operator<(cmProp l, cm::string_view r) noexcept -{ - return l.Compare(r) < 0; -} -inline bool operator<=(cmProp l, cm::string_view r) noexcept -{ - return l.Compare(r) <= 0; -} -inline bool operator>(cmProp l, cm::string_view r) noexcept -{ - return l.Compare(r) > 0; -} -inline bool operator>=(cmProp l, cm::string_view r) noexcept -{ - return l.Compare(r) >= 0; -} - -inline bool operator==(cmProp l, std::nullptr_t) noexcept -{ - return l.Compare(cmProp{}) == 0; -} -inline bool operator!=(cmProp l, std::nullptr_t) noexcept -{ - return l.Compare(cmProp{}) != 0; -} -inline bool operator<(cmProp l, std::nullptr_t) noexcept -{ - return l.Compare(cmProp{}) < 0; -} -inline bool operator<=(cmProp l, std::nullptr_t) noexcept -{ - return l.Compare(cmProp{}) <= 0; -} -inline bool operator>(cmProp l, std::nullptr_t) noexcept -{ - return l.Compare(cmProp{}) > 0; -} -inline bool operator>=(cmProp l, std::nullptr_t) noexcept -{ - return l.Compare(cmProp{}) >= 0; -} diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index 8ad3c6f1503..b15000f496e 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -19,7 +19,7 @@ void cmPropertyMap::SetProperty(const std::string& name, const char* value) this->Map_[name] = value; } -void cmPropertyMap::SetProperty(const std::string& name, cmProp value) +void cmPropertyMap::SetProperty(const std::string& name, cmValue value) { if (!value) { this->Map_.erase(name); @@ -51,11 +51,11 @@ void cmPropertyMap::RemoveProperty(const std::string& name) this->Map_.erase(name); } -cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const +cmValue cmPropertyMap::GetPropertyValue(const std::string& name) const { auto it = this->Map_.find(name); if (it != this->Map_.end()) { - return cmProp(it->second); + return cmValue(it->second); } return nullptr; } diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index b28d3c9046a..f50b65e2166 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -9,7 +9,7 @@ #include <utility> #include <vector> -#include "cmProperty.h" +#include "cmValue.h" /** \class cmPropertyMap * \brief String property map. @@ -26,10 +26,10 @@ class cmPropertyMap //! Set the property value void SetProperty(const std::string& name, const char* value); - void SetProperty(const std::string& name, cmProp value); + void SetProperty(const std::string& name, cmValue value); void SetProperty(const std::string& name, const std::string& value) { - this->SetProperty(name, cmProp(value)); + this->SetProperty(name, cmValue(value)); } //! Append to the property value @@ -37,7 +37,7 @@ class cmPropertyMap bool asString = false); //! Get the property value - cmProp GetPropertyValue(const std::string& name) const; + cmValue GetPropertyValue(const std::string& name) const; //! Remove the property @a name from the map void RemoveProperty(const std::string& name); diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index f3ad5657d24..f9e889a6661 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -15,7 +15,6 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmProcessOutput.h" -#include "cmProperty.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenInitializer.h" #include "cmState.h" @@ -23,6 +22,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" cmQtAutoGenGlobalInitializer::Keywords::Keywords() : AUTOMOC("AUTOMOC") @@ -183,7 +183,7 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( // Set FOLDER property in the target { - cmProp folder = + cmValue folder = makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); if (folder) { target->SetProperty("FOLDER", folder); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index fe038c70a3b..33ce3144633 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -37,7 +37,6 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenGlobalInitializer.h" #include "cmSourceFile.h" @@ -48,6 +47,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -356,7 +356,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Targets FOLDER { - cmProp folder = + cmValue folder = this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); if (!folder) { folder = this->Makefile->GetState()->GetGlobalProperty( @@ -1790,7 +1790,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP" }; for (std::string const& prop : props) { - cmProp propName = this->Makefile->GetState()->GetGlobalProperty(prop); + cmValue propName = this->Makefile->GetState()->GetGlobalProperty(prop); if (cmNonempty(propName)) { groupName = *propName; property = prop; @@ -1920,7 +1920,7 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target, } return 0u; }; - auto toUInt2 = [](cmProp input) -> unsigned int { + auto toUInt2 = [](cmValue input) -> unsigned int { unsigned long tmp = 0; if (input && cmStrToULong(*input, &tmp)) { return static_cast<unsigned int>(tmp); @@ -1948,8 +1948,8 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target, knownQtVersions.reserve(keys.size() * 2); // Adds a version to the result (nullptr safe) - auto addVersion = [&knownQtVersions, &toUInt2](cmProp major, - cmProp minor) { + auto addVersion = [&knownQtVersions, &toUInt2](cmValue major, + cmValue minor) { cmQtAutoGen::IntegerVersion ver(toUInt2(major), toUInt2(minor)); if (ver.Major != 0) { knownQtVersions.emplace_back(ver); diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx index 13455886b29..8af13ae2b4d 100644 --- a/Source/cmRemoveCommand.cxx +++ b/Source/cmRemoveCommand.cxx @@ -4,8 +4,8 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" // cmRemoveCommand bool cmRemoveCommand(std::vector<std::string> const& args, @@ -17,7 +17,7 @@ bool cmRemoveCommand(std::vector<std::string> const& args, std::string const& variable = args[0]; // VAR is always first // get the old value - cmProp cacheValue = status.GetMakefile().GetDefinition(variable); + cmValue cacheValue = status.GetMakefile().GetDefinition(variable); // if there is no old value then return if (!cacheValue) { diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index a58be621c54..1bb459c4ba4 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -8,9 +8,9 @@ #include "cmFindCommon.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmSearchPath::cmSearchPath(cmFindCommon* findCmd) : FC(findCmd) @@ -78,7 +78,7 @@ void cmSearchPath::AddCMakePath(const std::string& variable) assert(this->FC != nullptr); // Get a path from a CMake variable. - if (cmProp value = this->FC->Makefile->GetDefinition(variable)) { + if (cmValue value = this->FC->Makefile->GetDefinition(variable)) { std::vector<std::string> expanded = cmExpandedList(*value); for (std::string const& p : expanded) { @@ -102,7 +102,7 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable) assert(this->FC != nullptr); // Get a path from a CMake variable. - if (cmProp value = this->FC->Makefile->GetDefinition(variable)) { + if (cmValue value = this->FC->Makefile->GetDefinition(variable)) { std::vector<std::string> expanded = cmExpandedList(*value); this->AddPrefixPaths( @@ -179,7 +179,7 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths, dir += "/"; } if (subdir == "include" || subdir == "lib") { - cmProp arch = + cmValue arch = this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); if (cmNonempty(arch)) { if (this->FC->Makefile->IsDefinitionSet("CMAKE_SYSROOT") && diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx index c2fc45cf3ae..17285e723ad 100644 --- a/Source/cmSeparateArgumentsCommand.cxx +++ b/Source/cmSeparateArgumentsCommand.cxx @@ -10,10 +10,10 @@ #include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // cmSeparateArgumentsCommand bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, @@ -28,7 +28,7 @@ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, if (args.size() == 1) { // Original space-replacement version of command. - if (cmProp def = status.GetMakefile().GetDefinition(var)) { + if (cmValue def = status.GetMakefile().GetDefinition(var)) { std::string value = *def; std::replace(value.begin(), value.end(), ' ', ';'); status.GetMakefile().AddDefinition(var, value); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 354b4c327d0..ce0cb258ca3 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -5,12 +5,12 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // cmSetCommand bool cmSetCommand(std::vector<std::string> const& args, @@ -136,7 +136,7 @@ bool cmSetCommand(std::vector<std::string> const& args, // see if this is already in the cache cmState* state = status.GetMakefile().GetState(); - cmProp existingValue = state->GetCacheEntryValue(variable); + cmValue existingValue = state->GetCacheEntryValue(variable); if (existingValue && (state->GetCacheEntryType(variable) != cmStateEnums::UNINITIALIZED)) { // if the set is trying to CACHE the value but the value diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 59b44028db2..db10cd47aa1 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -21,6 +21,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTest.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -116,7 +117,7 @@ bool HandleSourceFileDirectoryScopes( "given non-existent target for TARGET_DIRECTORY ", target_name)); return false; } - cmProp target_source_dir = target->GetProperty("BINARY_DIR"); + cmValue target_source_dir = target->GetProperty("BINARY_DIR"); cmMakefile* target_dir_mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile( *target_source_dir); @@ -719,7 +720,7 @@ bool HandleCacheMode(cmExecutionStatus& status, for (std::string const& name : names) { // Get the source file. cmake* cm = status.GetMakefile().GetCMakeInstance(); - cmProp existingValue = cm->GetState()->GetCacheEntryValue(name); + cmValue existingValue = cm->GetState()->GetCacheEntryValue(name); if (existingValue) { if (!HandleCacheEntry(name, status.GetMakefile(), propertyName, propertyValue, appendAsString, appendMode, diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 58af8f0b0f1..34fdefe350f 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -6,10 +6,10 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // cmSiteNameCommand bool cmSiteNameCommand(std::vector<std::string> const& args, @@ -27,12 +27,12 @@ bool cmSiteNameCommand(std::vector<std::string> const& args, paths.emplace_back("/sbin"); paths.emplace_back("/usr/local/bin"); - cmProp cacheValue = status.GetMakefile().GetDefinition(args[0]); + cmValue cacheValue = status.GetMakefile().GetDefinition(args[0]); if (cacheValue) { return true; } - cmProp temp = status.GetMakefile().GetDefinition("HOSTNAME"); + cmValue temp = status.GetMakefile().GetDefinition("HOSTNAME"); std::string hostname_cmd; if (temp) { hostname_cmd = *temp; diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 6caae3abca0..3fa0051e245 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -13,6 +13,7 @@ #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name, @@ -53,7 +54,7 @@ std::string cmSourceFile::GetObjectLibrary() const std::string const& cmSourceFile::GetOrDetermineLanguage() { // If the language was set explicitly by the user then use it. - if (cmProp lang = this->GetProperty(propLANGUAGE)) { + if (cmValue lang = this->GetProperty(propLANGUAGE)) { // Assign to member in order to return a reference. this->Language = *lang; return this->Language; @@ -84,7 +85,7 @@ std::string const& cmSourceFile::GetOrDetermineLanguage() std::string cmSourceFile::GetLanguage() const { // If the language was set explicitly by the user then use it. - if (cmProp lang = this->GetProperty(propLANGUAGE)) { + if (cmValue lang = this->GetProperty(propLANGUAGE)) { return *lang; } @@ -299,7 +300,7 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value) { this->StoreProperty(prop, value); } -void cmSourceFile::SetProperty(const std::string& prop, cmProp value) +void cmSourceFile::SetProperty(const std::string& prop, cmValue value) { this->StoreProperty(prop, value); } @@ -327,7 +328,7 @@ void cmSourceFile::AppendProperty(const std::string& prop, } } -cmProp cmSourceFile::GetPropertyForUser(const std::string& prop) +cmValue cmSourceFile::GetPropertyForUser(const std::string& prop) { // This method is a consequence of design history and backwards // compatibility. GetProperty is (and should be) a const method. @@ -352,7 +353,7 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop) // if it is requested by the user. if (prop == propLANGUAGE) { // The pointer is valid until `this->Language` is modified. - return cmProp(this->GetOrDetermineLanguage()); + return cmValue(this->GetOrDetermineLanguage()); } // Special handling for GENERATED property. @@ -365,23 +366,23 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop) (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD) ? CheckScope::GlobalAndLocal : CheckScope::Global)) { - return cmProp(propTRUE); + return cmValue(propTRUE); } - return cmProp(propFALSE); + return cmValue(propFALSE); } // Perform the normal property lookup. return this->GetProperty(prop); } -cmProp cmSourceFile::GetProperty(const std::string& prop) const +cmValue cmSourceFile::GetProperty(const std::string& prop) const { // Check for computed properties. if (prop == propLOCATION) { if (this->FullPath.empty()) { return nullptr; } - return cmProp(this->FullPath); + return cmValue(this->FullPath); } // Check for the properties with backtraces. @@ -392,7 +393,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->IncludeDirectories, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propCOMPILE_OPTIONS) { @@ -402,7 +403,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->CompileOptions, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propCOMPILE_DEFINITIONS) { @@ -412,10 +413,10 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->CompileDefinitions, ";"); - return cmProp(output); + return cmValue(output); } - cmProp retVal = this->Properties.GetPropertyValue(prop); + cmValue retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { cmMakefile const* mf = this->Location.GetMakefile(); const bool chain = @@ -431,7 +432,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const const std::string& cmSourceFile::GetSafeProperty(const std::string& prop) const { - cmProp ret = this->GetProperty(prop); + cmValue ret = this->GetProperty(prop); if (ret) { return *ret; } diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 78e0d271257..c1c52010c8b 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -10,10 +10,10 @@ #include "cmCustomCommand.h" #include "cmListFileCache.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" +#include "cmValue.h" class cmMakefile; @@ -42,22 +42,22 @@ class cmSourceFile //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); - void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, cmValue value); void SetProperty(const std::string& prop, const std::string& value) { - this->SetProperty(prop, cmProp(value)); + this->SetProperty(prop, cmValue(value)); } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); //! Might return a nullptr if the property is not set or invalid - cmProp GetProperty(const std::string& prop) const; + cmValue GetProperty(const std::string& prop) const; //! Always returns a valid pointer const std::string& GetSafeProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; /** Implement getting a property when called from a CMake language command like get_property or get_source_file_property. */ - cmProp GetPropertyForUser(const std::string& prop); + cmValue GetPropertyForUser(const std::string& prop); /// Marks this file as generated /** diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 499317d2d60..c73f53a2ee1 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -20,9 +20,9 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -76,7 +76,7 @@ struct StandardLevelComputer const auto& stds = this->Levels; const auto& stdsStrings = this->LevelsAsStrings; - cmProp defaultStd = makefile->GetDefinition( + cmValue defaultStd = makefile->GetDefinition( cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); if (!cmNonempty(defaultStd)) { // this compiler has no notion of language standard levels @@ -84,13 +84,13 @@ struct StandardLevelComputer } bool ext = true; - if (cmProp extPropValue = target->GetLanguageExtensions(this->Language)) { + if (cmValue extPropValue = target->GetLanguageExtensions(this->Language)) { if (cmIsOff(*extPropValue)) { ext = false; } } - cmProp standardProp = target->GetLanguageStandard(this->Language, config); + cmValue standardProp = target->GetLanguageStandard(this->Language, config); if (!standardProp) { if (ext) { // No language standard is specified and extensions are not disabled. @@ -106,7 +106,7 @@ struct StandardLevelComputer std::string option_flag = cmStrCat( "CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION"); - cmProp opt = target->Target->GetMakefile()->GetDefinition(option_flag); + cmValue opt = target->Target->GetMakefile()->GetDefinition(option_flag); if (!opt) { std::ostringstream e; e << "Target \"" << target->GetName() @@ -174,7 +174,7 @@ struct StandardLevelComputer bool GetNewRequiredStandard(cmMakefile* makefile, std::string const& targetName, const std::string& feature, - cmProp currentLangStandardValue, + cmValue currentLangStandardValue, std::string& newRequiredStandard, std::string* error) const { @@ -186,9 +186,9 @@ struct StandardLevelComputer auto needed = this->HighestStandardNeeded(makefile, feature); - cmProp existingStandard = currentLangStandardValue; + cmValue existingStandard = currentLangStandardValue; if (!existingStandard) { - cmProp defaultStandard = makefile->GetDefinition( + cmValue defaultStandard = makefile->GetDefinition( cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); if (cmNonempty(defaultStandard)) { existingStandard = defaultStandard; @@ -231,7 +231,7 @@ struct StandardLevelComputer std::string const& config, std::string const& feature) const { - cmProp defaultStandard = makefile->GetDefinition( + cmValue defaultStandard = makefile->GetDefinition( cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT")); if (!defaultStandard) { makefile->IssueMessage( @@ -253,7 +253,7 @@ struct StandardLevelComputer return false; } - cmProp existingStandard = + cmValue existingStandard = target->GetLanguageStandard(this->Language, config); if (!existingStandard) { existingStandard = defaultStandard; @@ -283,7 +283,7 @@ struct StandardLevelComputer std::string prefix = cmStrCat("CMAKE_", this->Language); StandardNeeded maxLevel = { -1, -1 }; for (size_t i = 0; i < this->Levels.size(); ++i) { - if (cmProp prop = makefile->GetDefinition( + if (cmValue prop = makefile->GetDefinition( cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) { std::vector<std::string> props = cmExpandedList(*prop); if (cm::contains(props, feature)) { @@ -393,7 +393,7 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( return true; } - cmProp features = this->CompileFeaturesAvailable(lang, error); + cmValue features = this->CompileFeaturesAvailable(lang, error); if (!features) { return false; } @@ -471,7 +471,7 @@ bool cmStandardLevelResolver::CompileFeatureKnown( return false; } -cmProp cmStandardLevelResolver::CompileFeaturesAvailable( +cmValue cmStandardLevelResolver::CompileFeaturesAvailable( const std::string& lang, std::string* error) const { if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) { @@ -490,7 +490,7 @@ cmProp cmStandardLevelResolver::CompileFeaturesAvailable( return nullptr; } - cmProp featuresKnown = + cmValue featuresKnown = this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); if (!cmNonempty(featuresKnown)) { @@ -518,7 +518,7 @@ cmProp cmStandardLevelResolver::CompileFeaturesAvailable( bool cmStandardLevelResolver::GetNewRequiredStandard( const std::string& targetName, const std::string& feature, - cmProp currentLangStandardValue, std::string& newRequiredStandard, + cmValue currentLangStandardValue, std::string& newRequiredStandard, std::string* error) const { std::string lang; diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index c01a3b13279..422645604cd 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -4,7 +4,7 @@ #include <string> -#include "cmProperty.h" +#include "cmValue.h" class cmMakefile; class cmGeneratorTarget; @@ -30,12 +30,12 @@ class cmStandardLevelResolver const std::string& feature, std::string& lang, std::string* error) const; - cmProp CompileFeaturesAvailable(const std::string& lang, - std::string* error) const; + cmValue CompileFeaturesAvailable(const std::string& lang, + std::string* error) const; bool GetNewRequiredStandard(const std::string& targetName, const std::string& feature, - cmProp currentLangStandardValue, + cmValue currentLangStandardValue, std::string& newRequiredStandard, std::string* error = nullptr) const; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 16718e836ca..7fbc8f879b9 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -144,20 +144,20 @@ std::vector<std::string> cmState::GetCacheEntryKeys() const return this->CacheManager->GetCacheEntryKeys(); } -cmProp cmState::GetCacheEntryValue(std::string const& key) const +cmValue cmState::GetCacheEntryValue(std::string const& key) const { return this->CacheManager->GetCacheEntryValue(key); } std::string cmState::GetSafeCacheEntryValue(std::string const& key) const { - if (cmProp val = this->GetCacheEntryValue(key)) { + if (cmValue val = this->GetCacheEntryValue(key)) { return *val; } return std::string(); } -cmProp cmState::GetInitializedCacheValue(std::string const& key) const +cmValue cmState::GetInitializedCacheValue(std::string const& key) const { return this->CacheManager->GetInitializedCacheValue(key); } @@ -194,8 +194,8 @@ std::vector<std::string> cmState::GetCacheEntryPropertyList( return this->CacheManager->GetCacheEntryPropertyList(key); } -cmProp cmState::GetCacheEntryProperty(std::string const& key, - std::string const& propertyName) +cmValue cmState::GetCacheEntryProperty(std::string const& key, + std::string const& propertyName) { return this->CacheManager->GetCacheEntryProperty(key, propertyName); } @@ -206,7 +206,7 @@ bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, return this->CacheManager->GetCacheEntryPropertyAsBool(key, propertyName); } -void cmState::AddCacheEntry(const std::string& key, cmProp value, +void cmState::AddCacheEntry(const std::string& key, cmValue value, const char* helpString, cmStateEnums::CacheEntryType type) { @@ -472,7 +472,7 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error) name, [name, error](std::vector<cmListFileArgument> const&, cmExecutionStatus& status) -> bool { - cmProp versionValue = + cmValue versionValue = status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); if (name == "endif" && (!versionValue || atof(versionValue->c_str()) <= 1.4)) { @@ -564,7 +564,7 @@ void cmState::SetGlobalProperty(const std::string& prop, const char* value) { this->GlobalProperties.SetProperty(prop, value); } -void cmState::SetGlobalProperty(const std::string& prop, cmProp value) +void cmState::SetGlobalProperty(const std::string& prop, cmValue value) { this->GlobalProperties.SetProperty(prop, value); } @@ -575,7 +575,7 @@ void cmState::AppendGlobalProperty(const std::string& prop, this->GlobalProperties.AppendProperty(prop, value, asString); } -cmProp cmState::GetGlobalProperty(const std::string& prop) +cmValue cmState::GetGlobalProperty(const std::string& prop) { if (prop == "CACHE_VARIABLES") { std::vector<std::string> cacheKeys = this->GetCacheEntryKeys(); @@ -602,47 +602,47 @@ cmProp cmState::GetGlobalProperty(const std::string& prop) if (prop == "CMAKE_C_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_C90_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_C99_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_C11_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_CXX_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_CXX98_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_CXX11_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_CXX14_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } if (prop == "CMAKE_CUDA_KNOWN_FEATURES") { static const std::string s_out( &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]); - return cmProp(s_out); + return cmValue(s_out); } #undef STRING_LIST_ELEMENT diff --git a/Source/cmState.h b/Source/cmState.h index 390f6d6f23f..a1666ca1fc6 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -21,6 +21,7 @@ #include "cmPropertyMap.h" #include "cmStatePrivate.h" #include "cmStateTypes.h" +#include "cmValue.h" class cmCacheManager; class cmCommand; @@ -98,9 +99,9 @@ class cmState bool IsCacheLoaded() const; std::vector<std::string> GetCacheEntryKeys() const; - cmProp GetCacheEntryValue(std::string const& key) const; + cmValue GetCacheEntryValue(std::string const& key) const; std::string GetSafeCacheEntryValue(std::string const& key) const; - cmProp GetInitializedCacheValue(std::string const& key) const; + cmValue GetInitializedCacheValue(std::string const& key) const; cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const; void SetCacheEntryValue(std::string const& key, std::string const& value); @@ -112,8 +113,8 @@ class cmState void SetCacheEntryBoolProperty(std::string const& key, std::string const& propertyName, bool value); std::vector<std::string> GetCacheEntryPropertyList(std::string const& key); - cmProp GetCacheEntryProperty(std::string const& key, - std::string const& propertyName); + cmValue GetCacheEntryProperty(std::string const& key, + std::string const& propertyName); bool GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propertyName); void AppendCacheEntryProperty(std::string const& key, @@ -178,10 +179,10 @@ class cmState std::vector<std::string> GetCommandNames() const; void SetGlobalProperty(const std::string& prop, const char* value); - void SetGlobalProperty(const std::string& prop, cmProp value); + void SetGlobalProperty(const std::string& prop, cmValue value); void AppendGlobalProperty(const std::string& prop, const std::string& value, bool asString = false); - cmProp GetGlobalProperty(const std::string& prop); + cmValue GetGlobalProperty(const std::string& prop); bool GetGlobalPropertyAsBool(const std::string& prop); std::string const& GetSourceDirectory() const; @@ -222,15 +223,15 @@ class cmState const char* helpString, cmStateEnums::CacheEntryType type) { this->AddCacheEntry(key, - value ? cmProp(std::string(value)) : cmProp(nullptr), + value ? cmValue(std::string(value)) : cmValue(nullptr), helpString, type); } void AddCacheEntry(const std::string& key, const std::string& value, const char* helpString, cmStateEnums::CacheEntryType type) { - this->AddCacheEntry(key, cmProp(value), helpString, type); + this->AddCacheEntry(key, cmValue(value), helpString, type); } - void AddCacheEntry(const std::string& key, cmProp value, + void AddCacheEntry(const std::string& key, cmValue value, const char* helpString, cmStateEnums::CacheEntryType type); diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 8f83b02fa9a..b42e5c338e3 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -21,6 +21,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" static std::string const kBINARY_DIR = "BINARY_DIR"; static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS"; @@ -322,7 +323,7 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value, { this->StoreProperty(prop, value, lfbt); } -void cmStateDirectory::SetProperty(const std::string& prop, cmProp value, +void cmStateDirectory::SetProperty(const std::string& prop, cmValue value, cmListFileBacktrace const& lfbt) { this->StoreProperty(prop, value, lfbt); @@ -356,31 +357,32 @@ void cmStateDirectory::AppendProperty(const std::string& prop, this->DirectoryState->Properties.AppendProperty(prop, value, asString); } -cmProp cmStateDirectory::GetProperty(const std::string& prop) const +cmValue cmStateDirectory::GetProperty(const std::string& prop) const { const bool chain = this->Snapshot_.State->IsPropertyChained(prop, cmProperty::DIRECTORY); return this->GetProperty(prop, chain); } -cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const +cmValue cmStateDirectory::GetProperty(const std::string& prop, + bool chain) const { static std::string output; output.clear(); if (prop == "PARENT_DIRECTORY") { cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent(); if (parent.IsValid()) { - return cmProp(parent.GetDirectory().GetCurrentSource()); + return cmValue(parent.GetDirectory().GetCurrentSource()); } - return cmProp(output); + return cmValue(output); } if (prop == kBINARY_DIR) { output = this->GetCurrentBinary(); - return cmProp(output); + return cmValue(output); } if (prop == kSOURCE_DIR) { output = this->GetCurrentSource(); - return cmProp(output); + return cmValue(output); } if (prop == kSUBDIRECTORIES) { std::vector<std::string> child_dirs; @@ -391,15 +393,15 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const child_dirs.push_back(ci.GetDirectory().GetCurrentSource()); } output = cmJoin(child_dirs, ";"); - return cmProp(output); + return cmValue(output); } if (prop == kBUILDSYSTEM_TARGETS) { output = cmJoin(this->DirectoryState->NormalTargetNames, ";"); - return cmProp(output); + return cmValue(output); } if (prop == "IMPORTED_TARGETS"_s) { output = cmJoin(this->DirectoryState->ImportedTargetNames, ";"); - return cmProp(output); + return cmValue(output); } if (prop == "LISTFILE_STACK") { @@ -411,41 +413,41 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const } std::reverse(listFiles.begin(), listFiles.end()); output = cmJoin(listFiles, ";"); - return cmProp(output); + return cmValue(output); } if (prop == "CACHE_VARIABLES") { output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";"); - return cmProp(output); + return cmValue(output); } if (prop == "VARIABLES") { std::vector<std::string> res = this->Snapshot_.ClosureKeys(); cm::append(res, this->Snapshot_.State->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); output = cmJoin(res, ";"); - return cmProp(output); + return cmValue(output); } if (prop == "INCLUDE_DIRECTORIES") { output = cmJoin(this->GetIncludeDirectoriesEntries(), ";"); - return cmProp(output); + return cmValue(output); } if (prop == "COMPILE_OPTIONS") { output = cmJoin(this->GetCompileOptionsEntries(), ";"); - return cmProp(output); + return cmValue(output); } if (prop == "COMPILE_DEFINITIONS") { output = cmJoin(this->GetCompileDefinitionsEntries(), ";"); - return cmProp(output); + return cmValue(output); } if (prop == "LINK_OPTIONS") { output = cmJoin(this->GetLinkOptionsEntries(), ";"); - return cmProp(output); + return cmValue(output); } if (prop == "LINK_DIRECTORIES") { output = cmJoin(this->GetLinkDirectoriesEntries(), ";"); - return cmProp(output); + return cmValue(output); } - cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop); + cmValue retVal = this->DirectoryState->Properties.GetPropertyValue(prop); if (!retVal && chain) { cmStateSnapshot parentSnapshot = this->Snapshot_.GetBuildsystemDirectoryParent(); diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index fac5d58c6be..6429f329379 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -11,9 +11,9 @@ #include "cmAlgorithms.h" #include "cmLinkedTree.h" #include "cmListFileCache.h" -#include "cmProperty.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" +#include "cmValue.h" class cmStateDirectory { @@ -56,12 +56,12 @@ class cmStateDirectory void SetProperty(const std::string& prop, const char* value, cmListFileBacktrace const& lfbt); - void SetProperty(const std::string& prop, cmProp value, + void SetProperty(const std::string& prop, cmValue value, cmListFileBacktrace const& lfbt); void AppendProperty(const std::string& prop, const std::string& value, bool asString, cmListFileBacktrace const& lfbt); - cmProp GetProperty(const std::string& prop) const; - cmProp GetProperty(const std::string& prop, bool chain) const; + cmValue GetProperty(const std::string& prop) const; + cmValue GetProperty(const std::string& prop, bool chain) const; bool GetPropertyAsBool(const std::string& prop) const; std::vector<std::string> GetPropertyKeys() const; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index bd7db85b0b5..f73df8f08ac 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -11,12 +11,12 @@ #include "cmDefinitions.h" #include "cmListFileCache.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStatePrivate.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVersion.h" #if defined(__CYGWIN__) @@ -205,7 +205,7 @@ bool cmStateSnapshot::HasDefinedPolicyCMP0011() return !this->Position->Policies->IsEmpty(); } -cmProp cmStateSnapshot::GetDefinition(std::string const& name) const +cmValue cmStateSnapshot::GetDefinition(std::string const& name) const { assert(this->Position->Vars.IsValid()); return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root); @@ -378,7 +378,7 @@ void cmStateSnapshot::InitializeFromParent() this->Position->BuildSystemDirectory->LinkDirectories, this->Position->LinkDirectoriesPosition); - cmProp include_regex = + cmValue include_regex = parent->BuildSystemDirectory->Properties.GetPropertyValue( "INCLUDE_REGULAR_EXPRESSION"); this->Position->BuildSystemDirectory->Properties.SetProperty( diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index a5fe7e20cc6..a61ec833741 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -12,8 +12,8 @@ #include "cmLinkedTree.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" +#include "cmValue.h" class cmState; class cmStateDirectory; @@ -24,7 +24,7 @@ class cmStateSnapshot cmStateSnapshot(cmState* state = nullptr); cmStateSnapshot(cmState* state, cmStateDetail::PositionType position); - cmProp GetDefinition(std::string const& name) const; + cmValue GetDefinition(std::string const& name) const; bool IsInitialized(std::string const& name) const; void SetDefinition(std::string const& name, cm::string_view value); void RemoveDefinition(std::string const& name); diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 33ab403b7df..a9edcdf436d 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -14,8 +14,8 @@ #include <cm/string_view> -#include "cmProperty.h" #include "cmRange.h" +#include "cmValue.h" /** String range type. */ using cmStringRange = cmRange<std::vector<std::string>::const_iterator>; @@ -94,7 +94,7 @@ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep); */ void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut, bool emptyArgs = false); -inline void cmExpandList(cmProp arg, std::vector<std::string>& argsOut, +inline void cmExpandList(cmValue arg, std::vector<std::string>& argsOut, bool emptyArgs = false) { if (arg) { @@ -122,7 +122,7 @@ void cmExpandLists(InputIt first, InputIt last, */ std::vector<std::string> cmExpandedList(cm::string_view arg, bool emptyArgs = false); -inline std::vector<std::string> cmExpandedList(cmProp arg, +inline std::vector<std::string> cmExpandedList(cmValue arg, bool emptyArgs = false) { if (!arg) { @@ -177,7 +177,7 @@ class cmAlphaNum cmAlphaNum(unsigned long long int val); cmAlphaNum(float val); cmAlphaNum(double val); - cmAlphaNum(cmProp value) + cmAlphaNum(cmValue value) : View_(*value) { } @@ -232,7 +232,7 @@ inline bool cmIsInternallyOn(const char* val) } return cmIsInternallyOn(cm::string_view(val)); } -inline bool cmIsInternallyOn(cmProp val) +inline bool cmIsInternallyOn(cmValue val) { if (!val) { return false; @@ -243,13 +243,13 @@ inline bool cmIsInternallyOn(cmProp val) /** Check for non-empty Property/Variable value. */ inline bool cmNonempty(cm::string_view val) { - return !cmProp::IsEmpty(val); + return !cmValue::IsEmpty(val); } inline bool cmNonempty(const char* val) { - return !cmProp::IsEmpty(val); + return !cmValue::IsEmpty(val); } -inline bool cmNonempty(cmProp val) +inline bool cmNonempty(cmValue val) { return !val.IsEmpty(); } @@ -257,9 +257,9 @@ inline bool cmNonempty(cmProp val) /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ inline bool cmIsNOTFOUND(cm::string_view val) { - return cmProp::IsNOTFOUND(val); + return cmValue::IsNOTFOUND(val); } -inline bool cmIsNOTFOUND(cmProp val) +inline bool cmIsNOTFOUND(cmValue val) { return val.IsNOTFOUND(); } @@ -269,13 +269,13 @@ inline bool cmIsNOTFOUND(cmProp val) */ inline bool cmIsOn(cm::string_view val) { - return cmProp::IsOn(val); + return cmValue::IsOn(val); } inline bool cmIsOn(const char* val) { - return cmProp::IsOn(val); + return cmValue::IsOn(val); } -inline bool cmIsOn(cmProp val) +inline bool cmIsOn(cmValue val) { return val.IsOn(); } @@ -289,13 +289,13 @@ inline bool cmIsOn(cmProp val) */ inline bool cmIsOff(cm::string_view val) { - return cmProp::IsOff(val); + return cmValue::IsOff(val); } inline bool cmIsOff(const char* val) { - return cmProp::IsOff(val); + return cmValue::IsOff(val); } -inline bool cmIsOff(cmProp val) +inline bool cmIsOff(cmValue val) { return val.IsOff(); } @@ -313,7 +313,7 @@ inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix) } /** Returns true if string @a str starts with string @a prefix. */ -inline bool cmHasPrefix(cm::string_view str, cmProp prefix) +inline bool cmHasPrefix(cm::string_view str, cmValue prefix) { if (!prefix) { return false; @@ -343,7 +343,7 @@ inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix) } /** Returns true if string @a str ends with string @a suffix. */ -inline bool cmHasSuffix(cm::string_view str, cmProp suffix) +inline bool cmHasSuffix(cm::string_view str, cmValue suffix) { if (!suffix) { return false; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 5fa309df379..1cb6193daa5 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -31,7 +31,6 @@ #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" @@ -39,6 +38,7 @@ #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmUuid.h" +#include "cmValue.h" namespace { @@ -572,7 +572,7 @@ bool HandlePrependCommand(std::vector<std::string> const& args, const std::string& variable = args[1]; std::string value = cmJoin(cmMakeRange(args).advance(2), std::string()); - cmProp oldValue = status.GetMakefile().GetDefinition(variable); + cmValue oldValue = status.GetMakefile().GetDefinition(variable); if (oldValue) { value += *oldValue; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index af64dcea979..08734b417f6 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -37,6 +37,7 @@ #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmTargetPropertyComputer.h" +#include "cmValue.h" #include "cmake.h" template <> @@ -79,7 +80,7 @@ const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>( } template <> -cmProp cmTargetPropertyComputer::GetSources<cmTarget>( +cmValue cmTargetPropertyComputer::GetSources<cmTarget>( cmTarget const* tgt, cmMessenger* messenger, cmListFileBacktrace const& context) { @@ -157,7 +158,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>( } static std::string srcs; srcs = ss.str(); - return cmProp(srcs); + return cmValue(srcs); } class cmTargetInternals @@ -257,7 +258,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, auto initProp = [this, mf, &defKey](const std::string& property) { // Replace everything after "CMAKE_" defKey.replace(defKey.begin() + 6, defKey.end(), property); - if (cmProp value = mf->GetDefinition(defKey)) { + if (cmValue value = mf->GetDefinition(defKey)) { this->SetProperty(property, value); } }; @@ -265,7 +266,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, const char* default_value) { // Replace everything after "CMAKE_" defKey.replace(defKey.begin() + 6, defKey.end(), property); - if (cmProp value = mf->GetDefinition(defKey)) { + if (cmValue value = mf->GetDefinition(defKey)) { this->SetProperty(property, value); } else if (default_value) { this->SetProperty(property, default_value); @@ -525,7 +526,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // check for "CMAKE_VS_GLOBALS" variable and set up target properties // if any - cmProp globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); + cmValue globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); if (globals) { const std::string genName = mf->GetGlobalGenerator()->GetName(); if (cmHasLiteralPrefix(genName, "Visual Studio")) { @@ -1018,7 +1019,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) { std::string targetEntry = cmStrCat(this->impl->Name, "_LIB_DEPENDS"); std::string dependencies; - cmProp old_val = mf.GetDefinition(targetEntry); + cmValue old_val = mf.GetDefinition(targetEntry); if (old_val) { dependencies += *old_val; } @@ -1151,7 +1152,7 @@ std::string ConvertToString<const char*>(const char* value) return std::string(value); } template <> -std::string ConvertToString<cmProp>(cmProp value) +std::string ConvertToString<cmValue>(cmValue value) { return std::string(*value); } @@ -1306,7 +1307,7 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", cmStrCat(reusedFrom, ".dir/")); - cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); + cmValue tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); this->SetProperty("COMPILE_PDB_NAME", tmp); this->AddUtility(reusedFrom, false, this->impl->Makefile); } else if (prop == propC_STANDARD || prop == propCXX_STANDARD || @@ -1421,7 +1422,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) { this->StoreProperty(prop, value); } -void cmTarget::SetProperty(const std::string& prop, cmProp value) +void cmTarget::SetProperty(const std::string& prop, cmValue value) { this->StoreProperty(prop, value); } @@ -1579,17 +1580,17 @@ void cmTarget::CheckProperty(const std::string& prop, { // Certain properties need checking. if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) { - if (cmProp value = this->GetProperty(prop)) { + if (cmValue value = this->GetProperty(prop)) { cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false); } } if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) { - if (cmProp value = this->GetProperty(prop)) { + if (cmValue value = this->GetProperty(prop)) { cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true); } } if (prop == "INTERFACE_LINK_LIBRARIES") { - if (cmProp value = this->GetProperty(prop)) { + if (cmValue value = this->GetProperty(prop)) { cmTargetCheckINTERFACE_LINK_LIBRARIES(*value, context); } } @@ -1600,14 +1601,14 @@ void cmTarget::CheckProperty(const std::string& prop, } } -cmProp cmTarget::GetComputedProperty(const std::string& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) const +cmValue cmTarget::GetComputedProperty(const std::string& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) const { return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context); } -cmProp cmTarget::GetProperty(const std::string& prop) const +cmValue cmTarget::GetProperty(const std::string& prop) const { static std::unordered_set<std::string> const specialProps{ propC_STANDARD, @@ -1640,7 +1641,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const if (propertyIter == this->impl->LanguageStandardProperties.end()) { return nullptr; } - return cmProp(propertyIter->second.Value); + return cmValue(propertyIter->second.Value); } if (prop == propLINK_LIBRARIES) { if (this->impl->LinkImplementationPropertyEntries.empty()) { @@ -1649,11 +1650,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";"); - return cmProp(output); + return cmValue(output); } // the type property returns what type the target is if (prop == propTYPE) { - return cmProp(cmState::GetTargetTypeName(this->GetType())); + return cmValue(cmState::GetTargetTypeName(this->GetType())); } if (prop == propINCLUDE_DIRECTORIES) { if (this->impl->IncludeDirectoriesEntries.empty()) { @@ -1662,7 +1663,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->IncludeDirectoriesEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propCOMPILE_FEATURES) { if (this->impl->CompileFeaturesEntries.empty()) { @@ -1671,7 +1672,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->CompileFeaturesEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propCOMPILE_OPTIONS) { if (this->impl->CompileOptionsEntries.empty()) { @@ -1680,7 +1681,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->CompileOptionsEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propCOMPILE_DEFINITIONS) { if (this->impl->CompileDefinitionsEntries.empty()) { @@ -1689,7 +1690,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->CompileDefinitionsEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propLINK_OPTIONS) { if (this->impl->LinkOptionsEntries.empty()) { @@ -1698,7 +1699,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->LinkOptionsEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propLINK_DIRECTORIES) { if (this->impl->LinkDirectoriesEntries.empty()) { @@ -1708,7 +1709,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->LinkDirectoriesEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propMANUALLY_ADDED_DEPENDENCIES) { if (this->impl->Utilities.empty()) { @@ -1725,7 +1726,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const return item.Value.first; }); output = cmJoin(utilities, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propPRECOMPILE_HEADERS) { if (this->impl->PrecompileHeadersEntries.empty()) { @@ -1734,31 +1735,31 @@ cmProp cmTarget::GetProperty(const std::string& prop) const static std::string output; output = cmJoin(this->impl->PrecompileHeadersEntries, ";"); - return cmProp(output); + return cmValue(output); } if (prop == propIMPORTED) { - return this->IsImported() ? cmProp(propTRUE) : cmProp(propFALSE); + return this->IsImported() ? cmValue(propTRUE) : cmValue(propFALSE); } if (prop == propIMPORTED_GLOBAL) { - return this->IsImportedGloballyVisible() ? cmProp(propTRUE) - : cmProp(propFALSE); + return this->IsImportedGloballyVisible() ? cmValue(propTRUE) + : cmValue(propFALSE); } if (prop == propNAME) { - return cmProp(this->GetName()); + return cmValue(this->GetName()); } if (prop == propBINARY_DIR) { - return cmProp(this->impl->Makefile->GetStateSnapshot() - .GetDirectory() - .GetCurrentBinary()); + return cmValue(this->impl->Makefile->GetStateSnapshot() + .GetDirectory() + .GetCurrentBinary()); } if (prop == propSOURCE_DIR) { - return cmProp(this->impl->Makefile->GetStateSnapshot() - .GetDirectory() - .GetCurrentSource()); + return cmValue(this->impl->Makefile->GetStateSnapshot() + .GetDirectory() + .GetCurrentSource()); } } - cmProp retVal = this->impl->Properties.GetPropertyValue(prop); + cmValue retVal = this->impl->Properties.GetPropertyValue(prop); if (!retVal) { const bool chain = this->impl->Makefile->GetState()->IsPropertyChained( prop, cmProperty::TARGET); @@ -1774,7 +1775,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const std::string const& cmTarget::GetSafeProperty(std::string const& prop) const { - cmProp ret = this->GetProperty(prop); + cmValue ret = this->GetProperty(prop); if (ret) { return *ret; } @@ -1935,8 +1936,8 @@ std::string cmTarget::ImportedGetFullPath( std::string result; - cmProp loc = nullptr; - cmProp imp = nullptr; + cmValue loc = nullptr; + cmValue imp = nullptr; std::string suffix; if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -1947,9 +1948,9 @@ std::string cmTarget::ImportedGetFullPath( result = *loc; } else { std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); - if (cmProp config_location = this->GetProperty(impProp)) { + if (cmValue config_location = this->GetProperty(impProp)) { result = *config_location; - } else if (cmProp location = + } else if (cmValue location = this->GetProperty("IMPORTED_LOCATION")) { result = *location; } @@ -1962,9 +1963,9 @@ std::string cmTarget::ImportedGetFullPath( } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); - if (cmProp config_implib = this->GetProperty(impProp)) { + if (cmValue config_implib = this->GetProperty(impProp)) { result = *config_implib; - } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) { + } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) { result = *implib; } } @@ -2042,8 +2043,8 @@ bool cmTargetInternals::CheckImportedLibName(std::string const& prop, return true; } -bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc, - cmProp& imp, std::string& suffix) const +bool cmTarget::GetMappedConfig(std::string const& desired_config, cmValue& loc, + cmValue& imp, std::string& suffix) const { std::string config_upper; if (!desired_config.empty()) { @@ -2065,7 +2066,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc, std::vector<std::string> mappedConfigs; { std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper); - if (cmProp mapValue = this->GetProperty(mapProp)) { + if (cmValue mapValue = this->GetProperty(mapProp)) { cmExpandList(*mapValue, mappedConfigs, true); } } @@ -2147,7 +2148,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc, // any available configuration. if (!loc && !imp) { std::vector<std::string> availableConfigs; - if (cmProp iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) { + if (cmValue iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) { cmExpandList(*iconfigs, availableConfigs); } for (auto aci = availableConfigs.begin(); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index eced1ae4a93..3cf69429cfe 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -14,10 +14,10 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTargetLinkLibraryType.h" +#include "cmValue.h" class cmCustomCommand; class cmGlobalGenerator; @@ -170,21 +170,21 @@ class cmTarget //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); - void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, cmValue value); void SetProperty(const std::string& prop, const std::string& value) { - this->SetProperty(prop, cmProp(value)); + this->SetProperty(prop, cmValue(value)); } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); //! Might return a nullptr if the property is not set or invalid - cmProp GetProperty(const std::string& prop) const; + cmValue GetProperty(const std::string& prop) const; //! Always returns a valid pointer std::string const& GetSafeProperty(std::string const& prop) const; bool GetPropertyAsBool(const std::string& prop) const; void CheckProperty(const std::string& prop, cmMakefile* context) const; - cmProp GetComputedProperty(const std::string& prop, cmMessenger* messenger, - cmListFileBacktrace const& context) const; + cmValue GetComputedProperty(const std::string& prop, cmMessenger* messenger, + cmListFileBacktrace const& context) const; //! Get all properties cmPropertyMap const& GetProperties() const; @@ -199,8 +199,8 @@ class cmTarget bool IsPerConfig() const; bool CanCompileSources() const; - bool GetMappedConfig(std::string const& desired_config, cmProp& loc, - cmProp& imp, std::string& suffix) const; + bool GetMappedConfig(std::string const& desired_config, cmValue& loc, + cmValue& imp, std::string& suffix) const; //! Return whether this target is an executable with symbol exports enabled. bool IsExecutableWithExports() const; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 3423b30dcd4..d39824b9bef 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -14,13 +14,13 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" +#include "cmValue.h" #include "cmake.h" namespace { @@ -278,7 +278,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, // with old versions of CMake and new) llt = GENERAL_LibraryType; std::string linkType = cmStrCat(args[0], "_LINK_TYPE"); - cmProp linkTypeString = mf.GetDefinition(linkType); + cmValue linkTypeString = mf.GetDefinition(linkType); if (linkTypeString) { if (*linkTypeString == "debug") { llt = DEBUG_LibraryType; diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index e41714abacc..3bd1ea3c6b1 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -5,9 +5,9 @@ #include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmTarget.h" +#include "cmValue.h" #include "cmake.h" cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status) @@ -181,7 +181,7 @@ void cmTargetPropCommandBase::HandleInterfaceContent( { if (prepend) { const std::string propName = std::string("INTERFACE_") + this->Property; - cmProp propValue = tgt->GetProperty(propName); + cmValue propValue = tgt->GetProperty(propName); const std::string totalContent = this->Join(content) + (propValue ? (";" + *propValue) : std::string()); tgt->SetProperty(propName, totalContent); diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index a749b537e8b..e61a1fcda06 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -7,10 +7,10 @@ #include <string> #include "cmListFileCache.h" -#include "cmProperty.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" class cmMessenger; @@ -18,11 +18,11 @@ class cmTargetPropertyComputer { public: template <typename Target> - static cmProp GetProperty(Target const* tgt, const std::string& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) + static cmValue GetProperty(Target const* tgt, const std::string& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) { - if (cmProp loc = GetLocation(tgt, prop, messenger, context)) { + if (cmValue loc = GetLocation(tgt, prop, messenger, context)) { return loc; } if (cmSystemTools::GetFatalErrorOccured()) { @@ -46,9 +46,9 @@ class cmTargetPropertyComputer std::string const& config); template <typename Target> - static cmProp GetLocation(Target const* tgt, std::string const& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) + static cmValue GetLocation(Target const* tgt, std::string const& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) { // Watch for special "computed" properties that are dependent on @@ -65,7 +65,7 @@ class cmTargetPropertyComputer context)) { return nullptr; } - return cmProp(ComputeLocationForBuild(tgt)); + return cmValue(ComputeLocationForBuild(tgt)); } // Support "LOCATION_<CONFIG>". @@ -76,7 +76,7 @@ class cmTargetPropertyComputer return nullptr; } std::string configName = prop.substr(9); - return cmProp(ComputeLocation(tgt, configName)); + return cmValue(ComputeLocation(tgt, configName)); } // Support "<CONFIG>_LOCATION". @@ -89,7 +89,7 @@ class cmTargetPropertyComputer context)) { return nullptr; } - return cmProp(ComputeLocation(tgt, configName)); + return cmValue(ComputeLocation(tgt, configName)); } } } @@ -97,6 +97,6 @@ class cmTargetPropertyComputer } template <typename Target> - static cmProp GetSources(Target const* tgt, cmMessenger* messenger, - cmListFileBacktrace const& context); + static cmValue GetSources(Target const* tgt, cmMessenger* messenger, + cmListFileBacktrace const& context); }; diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 9d25ce9d971..56184871d71 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -6,6 +6,7 @@ #include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" cmTest::cmTest(cmMakefile* mf) : CommandExpandLists(false) @@ -32,14 +33,14 @@ void cmTest::SetCommand(std::vector<std::string> const& command) this->Command = command; } -cmProp cmTest::GetProperty(const std::string& prop) const +cmValue cmTest::GetProperty(const std::string& prop) const { - cmProp retVal = this->Properties.GetPropertyValue(prop); + cmValue retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { const bool chain = this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST); if (chain) { - if (cmProp p = this->Makefile->GetProperty(prop, chain)) { + if (cmValue p = this->Makefile->GetProperty(prop, chain)) { return p; } } @@ -57,7 +58,7 @@ void cmTest::SetProperty(const std::string& prop, const char* value) { this->Properties.SetProperty(prop, value); } -void cmTest::SetProperty(const std::string& prop, cmProp value) +void cmTest::SetProperty(const std::string& prop, cmValue value) { this->Properties.SetProperty(prop, value); } diff --git a/Source/cmTest.h b/Source/cmTest.h index a7905011ffb..85978dac281 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -8,8 +8,8 @@ #include <vector> #include "cmListFileCache.h" -#include "cmProperty.h" #include "cmPropertyMap.h" +#include "cmValue.h" class cmMakefile; @@ -35,14 +35,14 @@ class cmTest //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); - void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, cmValue value); void SetProperty(const std::string& prop, const std::string& value) { - this->SetProperty(prop, cmProp(value)); + this->SetProperty(prop, cmValue(value)); } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); - cmProp GetProperty(const std::string& prop) const; + cmValue GetProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; cmPropertyMap& GetProperties() { return this->Properties; } diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 7022c4eb1e1..dbb08760854 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -19,13 +19,13 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmRange.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTest.h" +#include "cmValue.h" namespace /* anonymous */ { @@ -167,7 +167,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, exe = target->GetFullPath(config); // Prepend with the emulator when cross compiling if required. - cmProp emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); + cmValue emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); if (cmNonempty(emulator)) { std::vector<std::string> emulatorWithArgs = cmExpandedList(*emulator); std::string emulatorExe(emulatorWithArgs[0]); diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 8cac74d3404..cc9e15864c8 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -9,12 +9,12 @@ #include "cmDuration.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmRange.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" class cmExecutionStatus; @@ -162,7 +162,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, if (!this->OutputVariable.empty()) { // if the TryCompileCore saved output in this outputVariable then // prepend that output to this output - cmProp compileOutput = + cmValue compileOutput = this->Makefile->GetDefinition(this->OutputVariable); if (compileOutput) { runOutputContents = *compileOutput + runOutputContents; @@ -260,7 +260,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, comment.c_str(), cmStateEnums::STRING); cmState* state = this->Makefile->GetState(); - cmProp existingValue = state->GetCacheEntryValue(this->RunResultVariable); + cmValue existingValue = state->GetCacheEntryValue(this->RunResultVariable); if (existingValue) { state->SetCacheEntryProperty(this->RunResultVariable, "ADVANCED", "1"); } @@ -282,7 +282,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(), cmStateEnums::STRING); cmState* state = this->Makefile->GetState(); - cmProp existing = state->GetCacheEntryValue(internalRunOutputName); + cmValue existing = state->GetCacheEntryValue(internalRunOutputName); if (existing) { state->SetCacheEntryProperty(internalRunOutputName, "ADVANCED", "1"); } diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index d276c8a6030..2805a33bbde 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -6,11 +6,11 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // cmUtilitySourceCommand bool cmUtilitySourceCommand(std::vector<std::string> const& args, @@ -25,7 +25,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, // The first argument is the cache entry name. std::string const& cacheEntry = *arg++; - cmProp cacheValue = status.GetMakefile().GetDefinition(cacheEntry); + cmValue cacheValue = status.GetMakefile().GetDefinition(cacheEntry); // If it exists already and appears up to date then we are done. If // the string contains "(IntDir)" but that is not the // CMAKE_CFG_INTDIR setting then the value is out of date. @@ -85,7 +85,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, std::string utilityDirectory = status.GetMakefile().GetCurrentBinaryDirectory(); std::string exePath; - if (cmProp d = + if (cmValue d = status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH")) { exePath = *d; } diff --git a/Source/cmProperty.cxx b/Source/cmValue.cxx similarity index 87% rename from Source/cmProperty.cxx rename to Source/cmValue.cxx index d012630de31..59bf201b702 100644 --- a/Source/cmProperty.cxx +++ b/Source/cmValue.cxx @@ -1,5 +1,5 @@ -#include "cmProperty.h" +#include "cmValue.h" #include <string> @@ -7,9 +7,9 @@ #include "cmStringAlgorithms.h" -std::string cmProp::Empty; +std::string cmValue::Empty; -bool cmProp::IsOn(cm::string_view value) noexcept +bool cmValue::IsOn(cm::string_view value) noexcept { switch (value.size()) { case 1: @@ -36,7 +36,7 @@ bool cmProp::IsOn(cm::string_view value) noexcept return false; } -bool cmProp::IsOff(cm::string_view value) noexcept +bool cmValue::IsOff(cm::string_view value) noexcept { switch (value.size()) { case 0: @@ -73,12 +73,12 @@ bool cmProp::IsOff(cm::string_view value) noexcept return IsNOTFOUND(value); } -bool cmProp::IsNOTFOUND(cm::string_view value) noexcept +bool cmValue::IsNOTFOUND(cm::string_view value) noexcept { return (value == "NOTFOUND"_s) || cmHasSuffix(value, "-NOTFOUND"_s); } -int cmProp::Compare(cmProp value) const noexcept +int cmValue::Compare(cmValue value) const noexcept { if (this->Value == nullptr && !value) { return 0; @@ -92,7 +92,7 @@ int cmProp::Compare(cmProp value) const noexcept return this->Value->compare(*value); } -int cmProp::Compare(cm::string_view value) const noexcept +int cmValue::Compare(cm::string_view value) const noexcept { if (this->Value == nullptr && value.data() == nullptr) { return 0; @@ -106,7 +106,7 @@ int cmProp::Compare(cm::string_view value) const noexcept return cm::string_view(*this->Value).compare(value); } -std::ostream& operator<<(std::ostream& o, cmProp v) +std::ostream& operator<<(std::ostream& o, cmValue v) { o << *v; return o; diff --git a/Source/cmValue.h b/Source/cmValue.h new file mode 100644 index 00000000000..43a5e0d3045 --- /dev/null +++ b/Source/cmValue.h @@ -0,0 +1,214 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <cstddef> +#include <iosfwd> +#include <string> + +#include <cm/string_view> + +class cmValue +{ +public: + cmValue() noexcept = default; + cmValue(std::nullptr_t) noexcept {} + explicit cmValue(const std::string* value) noexcept + : Value(value) + { + } + explicit cmValue(const std::string& value) noexcept + : Value(&value) + { + } + cmValue(const cmValue& other) noexcept = default; + + cmValue& operator=(const cmValue& other) noexcept = default; + cmValue& operator=(std::nullptr_t) noexcept + { + this->Value = nullptr; + return *this; + } + + const std::string* Get() const noexcept { return this->Value; } + const char* GetCStr() const noexcept + { + return this->Value == nullptr ? nullptr : this->Value->c_str(); + } + + const std::string* operator->() const noexcept + { + return this->Value == nullptr ? &cmValue::Empty : this->Value; + } + const std::string& operator*() const noexcept + { + return this->Value == nullptr ? cmValue::Empty : *this->Value; + } + + explicit operator bool() const noexcept { return this->Value != nullptr; } + operator const std::string&() const noexcept { return this->operator*(); } + explicit operator cm::string_view() const noexcept + { + return this->operator*(); + } + + /** + * Does the value indicate a true or ON value? + */ + bool IsOn() const noexcept + { + return this->Value != nullptr && + cmValue::IsOn(cm::string_view(*this->Value)); + } + /** + * Does the value indicate a false or off value ? Note that this is + * not the same as !IsOn(...) because there are a number of + * ambiguous values such as "/usr/local/bin" a path will result in + * IsOn and IsOff both returning false. Note that the special path + * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. + */ + bool IsOff() const noexcept + { + return this->Value == nullptr || + cmValue::IsOff(cm::string_view(*this->Value)); + } + /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ + bool IsNOTFOUND() const noexcept + { + return this->Value != nullptr && + cmValue::IsNOTFOUND(cm::string_view(*this->Value)); + } + bool IsEmpty() const noexcept + { + return this->Value == nullptr || this->Value->empty(); + } + + bool IsSet() const noexcept + { + return !this->IsEmpty() && !this->IsNOTFOUND(); + } + + /** + * Does a string indicate a true or ON value? + */ + static bool IsOn(const char* value) noexcept + { + return value != nullptr && IsOn(cm::string_view(value)); + } + static bool IsOn(cm::string_view) noexcept; + + /** + * Compare method has same semantic as std::optional::compare + */ + int Compare(cmValue value) const noexcept; + int Compare(cm::string_view value) const noexcept; + + /** + * Does a string indicate a false or off value ? Note that this is + * not the same as !IsOn(...) because there are a number of + * ambiguous values such as "/usr/local/bin" a path will result in + * IsOn and IsOff both returning false. Note that the special path + * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. + */ + static bool IsOff(const char* value) noexcept + { + return value == nullptr || IsOff(cm::string_view(value)); + } + static bool IsOff(cm::string_view) noexcept; + + /** Return true if value is NOTFOUND or ends in -NOTFOUND. */ + static bool IsNOTFOUND(const char* value) noexcept + { + return value == nullptr || IsNOTFOUND(cm::string_view(value)); + } + static bool IsNOTFOUND(cm::string_view) noexcept; + + static bool IsEmpty(const char* value) noexcept + { + return value == nullptr || *value == '\0'; + } + static bool IsEmpty(cm::string_view value) noexcept { return value.empty(); } + +private: + static std::string Empty; + const std::string* Value = nullptr; +}; + +std::ostream& operator<<(std::ostream& o, cmValue v); + +inline bool operator==(cmValue l, cmValue r) noexcept +{ + return l.Compare(r) == 0; +} +inline bool operator!=(cmValue l, cmValue r) noexcept +{ + return l.Compare(r) != 0; +} +inline bool operator<(cmValue l, cmValue r) noexcept +{ + return l.Compare(r) < 0; +} +inline bool operator<=(cmValue l, cmValue r) noexcept +{ + return l.Compare(r) <= 0; +} +inline bool operator>(cmValue l, cmValue r) noexcept +{ + return l.Compare(r) > 0; +} +inline bool operator>=(cmValue l, cmValue r) noexcept +{ + return l.Compare(r) >= 0; +} + +inline bool operator==(cmValue l, cm::string_view r) noexcept +{ + return l.Compare(r) == 0; +} +inline bool operator!=(cmValue l, cm::string_view r) noexcept +{ + return l.Compare(r) != 0; +} +inline bool operator<(cmValue l, cm::string_view r) noexcept +{ + return l.Compare(r) < 0; +} +inline bool operator<=(cmValue l, cm::string_view r) noexcept +{ + return l.Compare(r) <= 0; +} +inline bool operator>(cmValue l, cm::string_view r) noexcept +{ + return l.Compare(r) > 0; +} +inline bool operator>=(cmValue l, cm::string_view r) noexcept +{ + return l.Compare(r) >= 0; +} + +inline bool operator==(cmValue l, std::nullptr_t) noexcept +{ + return l.Compare(cmValue{}) == 0; +} +inline bool operator!=(cmValue l, std::nullptr_t) noexcept +{ + return l.Compare(cmValue{}) != 0; +} +inline bool operator<(cmValue l, std::nullptr_t) noexcept +{ + return l.Compare(cmValue{}) < 0; +} +inline bool operator<=(cmValue l, std::nullptr_t) noexcept +{ + return l.Compare(cmValue{}) <= 0; +} +inline bool operator>(cmValue l, std::nullptr_t) noexcept +{ + return l.Compare(cmValue{}) > 0; +} +inline bool operator>=(cmValue l, std::nullptr_t) noexcept +{ + return l.Compare(cmValue{}) >= 0; +} diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 1fe03ab26de..2b1efbac25e 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -4,10 +4,10 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" // cmLibraryCommand bool cmVariableRequiresCommand(std::vector<std::string> const& args, @@ -38,7 +38,7 @@ bool cmVariableRequiresCommand(std::vector<std::string> const& args, } } } - cmProp reqVar = status.GetMakefile().GetDefinition(resultVariable); + cmValue reqVar = status.GetMakefile().GetDefinition(resultVariable); // if reqVar is unset, then set it to requirementsMet // if reqVar is set to true, but requirementsMet is false , then // set reqVar to false. diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 7c7fbca5b98..fd5402cf682 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -10,9 +10,9 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmVariableWatch.h" #include "cmake.h" @@ -45,7 +45,7 @@ void cmVariableWatchCommandVariableAccessed(const std::string& variable, std::string stack = *mf->GetProperty("LISTFILE_STACK"); if (!data->Command.empty()) { - cmProp const currentListFile = + cmValue const currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE"); const auto fakeLineNo = std::numeric_limits<decltype(cmListFileArgument::Line)>::max(); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index e7ef7eace41..1ea0461f5cf 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -437,7 +437,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->VerifyNecessaryFiles(); } - cmProp vsProjectTypes = + cmValue vsProjectTypes = this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES"); if (vsProjectTypes) { const char* tagName = "ProjectTypes"; @@ -447,11 +447,11 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element(tagName, *vsProjectTypes); } - cmProp vsProjectName = + cmValue vsProjectName = this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME"); - cmProp vsLocalPath = + cmValue vsLocalPath = this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH"); - cmProp vsProvider = + cmValue vsProvider = this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER"); if (vsProjectName && vsLocalPath && vsProvider) { @@ -459,7 +459,7 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("SccLocalPath", *vsLocalPath); e1.Element("SccProvider", *vsProvider); - cmProp vsAuxPath = + cmValue vsAuxPath = this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH"); if (vsAuxPath) { e1.Element("SccAuxPath", *vsAuxPath); @@ -470,7 +470,7 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("WinMDAssembly", "true"); } - cmProp vsGlobalKeyword = + cmValue vsGlobalKeyword = this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD"); if (!vsGlobalKeyword) { if (this->GlobalGenerator->TargetsAndroid()) { @@ -482,17 +482,17 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("Keyword", *vsGlobalKeyword); } - cmProp vsGlobalRootNamespace = + cmValue vsGlobalRootNamespace = this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE"); if (vsGlobalRootNamespace) { e1.Element("RootNamespace", *vsGlobalRootNamespace); } e1.Element("Platform", this->Platform); - cmProp projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL"); + cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL"); e1.Element("ProjectName", projLabel ? projLabel : this->Name); { - cmProp targetFramework = + cmValue targetFramework = this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK"); if (targetFramework) { if (targetFramework->find(';') != std::string::npos) { @@ -502,7 +502,7 @@ void cmVisualStudio10TargetGenerator::Generate() } } else { // TODO: add deprecation warning for VS_* property? - cmProp p = this->GeneratorTarget->GetProperty( + cmValue p = this->GeneratorTarget->GetProperty( "VS_DOTNET_TARGET_FRAMEWORK_VERSION"); if (!p) { p = this->GeneratorTarget->GetProperty( @@ -527,12 +527,12 @@ void cmVisualStudio10TargetGenerator::Generate() } if (this->ProjectType == csproj && this->GlobalGenerator->TargetsWindowsCE()) { - cmProp targetFrameworkId = this->GeneratorTarget->GetProperty( + cmValue targetFrameworkId = this->GeneratorTarget->GetProperty( "VS_TARGET_FRAMEWORK_IDENTIFIER"); e1.Element("TargetFrameworkIdentifier", targetFrameworkId ? *targetFrameworkId : "WindowsEmbeddedCompact"); - cmProp targetFrameworkVer = this->GeneratorTarget->GetProperty( + cmValue targetFrameworkVer = this->GeneratorTarget->GetProperty( "VS_TARGET_FRAMEWORKS_TARGET_VERSION"); e1.Element("TargetFrameworkTargetsVersion", targetFrameworkVer ? *targetFrameworkVer : "v8.0"); @@ -571,7 +571,7 @@ void cmVisualStudio10TargetGenerator::Generate() globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") { continue; } - cmProp value = this->GeneratorTarget->GetProperty(keyIt); + cmValue value = this->GeneratorTarget->GetProperty(keyIt); if (!value) continue; e1.Element(globalKey, *value); @@ -694,7 +694,7 @@ void cmVisualStudio10TargetGenerator::Generate() props = VS10_CSharp_USER_PROPS; break; } - if (cmProp p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) { + if (cmValue p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) { props = *p; } if (!props.empty()) { @@ -807,7 +807,7 @@ void cmVisualStudio10TargetGenerator::Generate() void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) { std::vector<std::string> packageReferences; - if (cmProp vsPackageReferences = + if (cmValue vsPackageReferences = this->GeneratorTarget->GetProperty("VS_PACKAGE_REFERENCES")) { cmExpandList(*vsPackageReferences, packageReferences); } @@ -827,7 +827,7 @@ void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) { std::vector<std::string> references; - if (cmProp vsDotNetReferences = + if (cmValue vsDotNetReferences = this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) { cmExpandList(*vsDotNetReferences, references); } @@ -886,7 +886,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference( e2.Element("ReferenceOutputAssembly", "true"); if (!hint.empty()) { const char* privateReference = "True"; - if (cmProp value = this->GeneratorTarget->GetProperty( + if (cmValue value = this->GeneratorTarget->GetProperty( "VS_DOTNET_REFERENCES_COPY_LOCAL")) { if (cmIsOff(*value)) { privateReference = "False"; @@ -900,7 +900,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference( void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0) { - cmProp imports = + cmValue imports = this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT"); if (imports) { std::vector<std::string> argsSplit = cmExpandedList(*imports, false); @@ -1004,7 +1004,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) ".Designer.cs"; if (cmsys::SystemTools::FileExists(designerResource)) { std::string generator = "PublicResXFileCodeGenerator"; - if (cmProp g = oi->GetProperty("VS_RESOURCE_GENERATOR")) { + if (cmValue g = oi->GetProperty("VS_RESOURCE_GENERATOR")) { generator = *g; } if (!generator.empty()) { @@ -1028,7 +1028,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) cm::string_view tagName = cm::string_view(p).substr(propNamePrefix.length()); if (!tagName.empty()) { - cmProp value = props.GetPropertyValue(p); + cmValue value = props.GetPropertyValue(p); if (cmNonempty(value)) { e2.Element(tagName, *value); } @@ -1047,7 +1047,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) for (cmSourceFile const* oi : this->XamlObjs) { std::string obj = oi->GetFullPath(); std::string xamlType; - cmProp xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE"); + cmValue xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE"); if (xamlTypeProperty) { xamlType = *xamlTypeProperty; } else { @@ -1101,7 +1101,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1) void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0) { std::vector<std::string> references; - if (cmProp vsWinRTReferences = + if (cmValue vsWinRTReferences = this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) { cmExpandList(*vsWinRTReferences, references); } @@ -1144,7 +1144,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) if (this->ProjectType != csproj) { std::string configType; - if (cmProp vsConfigurationType = + if (cmValue vsConfigurationType = this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) { configType = cmGeneratorExpression::Evaluate(*vsConfigurationType, this->LocalGenerator, c); @@ -1206,9 +1206,9 @@ void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues( if (!this->GlobalGenerator->TargetsWindowsCE()) { return; } - cmProp additionalFiles = + cmValue additionalFiles = this->GeneratorTarget->GetProperty("DEPLOYMENT_ADDITIONAL_FILES"); - cmProp remoteDirectory = + cmValue remoteDirectory = this->GeneratorTarget->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY"); if (!(additionalFiles || remoteDirectory)) { return; @@ -1230,7 +1230,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( Elem& e1, std::string const& config) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; - cmProp mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); + cmValue mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); if (mfcFlag) { std::string const mfcFlagValue = cmGeneratorExpression::Evaluate(*mfcFlag, this->LocalGenerator, config); @@ -1260,7 +1260,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( } else { e1.Element("CharacterSet", "MultiByte"); } - if (cmProp projectToolsetOverride = + if (cmValue projectToolsetOverride = this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) { e1.Element("PlatformToolset", *projectToolsetOverride); } else if (const char* toolset = gg->GetPlatformToolset()) { @@ -1306,7 +1306,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( o.RemoveFlag("Platform"); } - if (cmProp projectToolsetOverride = + if (cmValue projectToolsetOverride = this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) { e1.Element("PlatformToolset", *projectToolsetOverride); } else if (const char* toolset = gg->GetPlatformToolset()) { @@ -1317,7 +1317,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX"); std::string assemblyName = this->GeneratorTarget->GetOutputName( config, cmStateEnums::RuntimeBinaryArtifact); - if (cmProp postfix = this->GeneratorTarget->GetProperty(postfixName)) { + if (cmValue postfix = this->GeneratorTarget->GetProperty(postfixName)) { assemblyName += *postfix; } e1.Element("AssemblyName", assemblyName); @@ -1338,18 +1338,18 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues( cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; const char* toolset = gg->GetPlatformToolset(); e1.Element("NdkToolchainVersion", toolset ? toolset : "Default"); - if (cmProp minApi = this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) { + if (cmValue minApi = this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) { e1.Element("AndroidMinAPI", "android-" + *minApi); } - if (cmProp api = this->GeneratorTarget->GetProperty("ANDROID_API")) { + if (cmValue api = this->GeneratorTarget->GetProperty("ANDROID_API")) { e1.Element("AndroidTargetAPI", "android-" + *api); } - if (cmProp cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) { + if (cmValue cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) { e1.Element("AndroidArch", *cpuArch); } - if (cmProp stlType = + if (cmValue stlType = this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) { e1.Element("AndroidStlType", *stlType); } @@ -1359,13 +1359,13 @@ void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues( Elem& e1, std::string const&) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; - if (cmProp projectToolsetOverride = + if (cmValue projectToolsetOverride = this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) { e1.Element("PlatformToolset", *projectToolsetOverride); } else if (const char* toolset = gg->GetPlatformToolset()) { e1.Element("PlatformToolset", toolset); } - if (cmProp stlType = + if (cmValue stlType = this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) { if (*stlType != "none") { e1.Element("UseOfStl", *stlType); @@ -1891,37 +1891,37 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( if (ext == "hlsl") { tool = "FXCompile"; // Figure out the type of shader compiler to use. - if (cmProp st = sf->GetProperty("VS_SHADER_TYPE")) { + if (cmValue st = sf->GetProperty("VS_SHADER_TYPE")) { for (const std::string& config : this->Configurations) { toolSettings[config]["ShaderType"] = *st; } } // Figure out which entry point to use if any - if (cmProp se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) { + if (cmValue se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) { for (const std::string& config : this->Configurations) { toolSettings[config]["EntryPointName"] = *se; } } // Figure out which shader model to use if any - if (cmProp sm = sf->GetProperty("VS_SHADER_MODEL")) { + if (cmValue sm = sf->GetProperty("VS_SHADER_MODEL")) { for (const std::string& config : this->Configurations) { toolSettings[config]["ShaderModel"] = *sm; } } // Figure out which output header file to use if any - if (cmProp ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) { + if (cmValue ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) { for (const std::string& config : this->Configurations) { toolSettings[config]["HeaderFileOutput"] = *ohf; } } // Figure out which variable name to use if any - if (cmProp vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) { + if (cmValue vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) { for (const std::string& config : this->Configurations) { toolSettings[config]["VariableName"] = *vn; } } // Figure out if there's any additional flags to use - if (cmProp saf = sf->GetProperty("VS_SHADER_FLAGS")) { + if (cmValue saf = sf->GetProperty("VS_SHADER_FLAGS")) { cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*saf); @@ -1934,7 +1934,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( } } // Figure out if debug information should be generated - if (cmProp sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) { + if (cmValue sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) { cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sed); @@ -1948,7 +1948,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( } } // Figure out if optimizations should be disabled - if (cmProp sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) { + if (cmValue sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) { cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sdo); @@ -1961,7 +1961,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( } } } - if (cmProp sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) { + if (cmValue sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) { for (const std::string& config : this->Configurations) { toolSettings[config]["ObjectFileOutput"] = *sofn; } @@ -1984,7 +1984,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( } else if (ext == "vsixmanifest") { subType = "Designer"; } - if (cmProp c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) { + if (cmValue c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) { tool = "Content"; copyToOutDir = *c; toolHasSettings = true; @@ -2013,7 +2013,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( } } - cmProp toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE"); + cmValue toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE"); if (cmNonempty(toolOverride)) { tool = toolOverride->c_str(); } @@ -2022,12 +2022,12 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( std::string deployLocation; if (this->GlobalGenerator->TargetsWindowsPhone() || this->GlobalGenerator->TargetsWindowsStore()) { - cmProp content = sf->GetProperty("VS_DEPLOYMENT_CONTENT"); + cmValue content = sf->GetProperty("VS_DEPLOYMENT_CONTENT"); if (cmNonempty(content)) { toolHasSettings = true; deployContent = *content; - cmProp location = sf->GetProperty("VS_DEPLOYMENT_LOCATION"); + cmValue location = sf->GetProperty("VS_DEPLOYMENT_LOCATION"); if (cmNonempty(location)) { deployLocation = *location; } @@ -2035,7 +2035,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource( } if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) { - cmProp toolTargetProperty = this->GeneratorTarget->Target->GetProperty( + cmValue toolTargetProperty = this->GeneratorTarget->Target->GetProperty( "VS_SOURCE_SETTINGS_" + std::string(tool)); ConfigToSettings toolTargetSettings; if (toolTargetProperty) { @@ -2202,7 +2202,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) for (const auto& config : this->Configurations) { toolSettings[config]; } - if (cmProp p = si.Source->GetProperty("VS_SETTINGS")) { + if (cmValue p = si.Source->GetProperty("VS_SETTINGS")) { ParseSettingsProperty(*p, toolSettings); } @@ -2399,22 +2399,22 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( bool configDependentDefines = false; std::string includes; bool configDependentIncludes = false; - if (cmProp cflags = sf.GetProperty("COMPILE_FLAGS")) { + if (cmValue cflags = sf.GetProperty("COMPILE_FLAGS")) { configDependentFlags = cmGeneratorExpression::Find(*cflags) != std::string::npos; flags += *cflags; } - if (cmProp coptions = sf.GetProperty("COMPILE_OPTIONS")) { + if (cmValue coptions = sf.GetProperty("COMPILE_OPTIONS")) { configDependentOptions = cmGeneratorExpression::Find(*coptions) != std::string::npos; options += *coptions; } - if (cmProp cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) { + if (cmValue cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) { configDependentDefines = cmGeneratorExpression::Find(*cdefs) != std::string::npos; defines += *cdefs; } - if (cmProp cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) { + if (cmValue cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) { configDependentIncludes = cmGeneratorExpression::Find(*cincludes) != std::string::npos; includes += *cincludes; @@ -2452,7 +2452,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( std::string configUpper = cmSystemTools::UpperCase(config); std::string configDefines = defines; std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); - if (cmProp ccdefs = sf.GetProperty(defPropName)) { + if (cmValue ccdefs = sf.GetProperty(defPropName)) { if (!configDefines.empty()) { configDefines += ";"; } @@ -2628,7 +2628,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( const std::string cond = this->CalcCondition(config); if (ttype <= cmStateEnums::UTILITY) { - if (cmProp workingDir = this->GeneratorTarget->GetProperty( + if (cmValue workingDir = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_WORKING_DIRECTORY")) { std::string genWorkingDir = cmGeneratorExpression::Evaluate( *workingDir, this->LocalGenerator, config); @@ -2636,7 +2636,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( genWorkingDir); } - if (cmProp environment = + if (cmValue environment = this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) { std::string genEnvironment = cmGeneratorExpression::Evaluate( *environment, this->LocalGenerator, config); @@ -2644,7 +2644,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( genEnvironment); } - if (cmProp debuggerCommand = + if (cmValue debuggerCommand = this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) { std::string genDebuggerCommand = cmGeneratorExpression::Evaluate( *debuggerCommand, this->LocalGenerator, config); @@ -2652,7 +2652,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( genDebuggerCommand); } - if (cmProp commandArguments = this->GeneratorTarget->GetProperty( + if (cmValue commandArguments = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_COMMAND_ARGUMENTS")) { std::string genCommandArguments = cmGeneratorExpression::Evaluate( *commandArguments, this->LocalGenerator, config); @@ -2684,40 +2684,40 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.WritePlatformConfigTag("IntDir", cond, intermediateDir); - if (cmProp sdkExecutableDirectories = this->Makefile->GetDefinition( + if (cmValue sdkExecutableDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) { e1.WritePlatformConfigTag("ExecutablePath", cond, *sdkExecutableDirectories); } - if (cmProp sdkIncludeDirectories = this->Makefile->GetDefinition( + if (cmValue sdkIncludeDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) { e1.WritePlatformConfigTag("IncludePath", cond, *sdkIncludeDirectories); } - if (cmProp sdkReferenceDirectories = this->Makefile->GetDefinition( + if (cmValue sdkReferenceDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) { e1.WritePlatformConfigTag("ReferencePath", cond, *sdkReferenceDirectories); } - if (cmProp sdkLibraryDirectories = this->Makefile->GetDefinition( + if (cmValue sdkLibraryDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) { e1.WritePlatformConfigTag("LibraryPath", cond, *sdkLibraryDirectories); } - if (cmProp sdkLibraryWDirectories = this->Makefile->GetDefinition( + if (cmValue sdkLibraryWDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) { e1.WritePlatformConfigTag("LibraryWPath", cond, *sdkLibraryWDirectories); } - if (cmProp sdkSourceDirectories = + if (cmValue sdkSourceDirectories = this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) { e1.WritePlatformConfigTag("SourcePath", cond, *sdkSourceDirectories); } - if (cmProp sdkExcludeDirectories = this->Makefile->GetDefinition( + if (cmValue sdkExcludeDirectories = this->Makefile->GetDefinition( "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) { e1.WritePlatformConfigTag("ExcludePath", cond, *sdkExcludeDirectories); } @@ -2915,7 +2915,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->Makefile->IssueMessage(MessageType::WARNING, message); } } - if (cmProp clr = + if (cmValue clr = this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) { std::string clrString = *clr; if (!clrString.empty()) { @@ -3058,7 +3058,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( oh.OutputPreprocessorDefinitions(this->LangForClCompile); if (this->NsightTegra) { - if (cmProp processMax = + if (cmValue processMax = this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) { e2.Element("ProcessMax", *processMax); } @@ -3616,7 +3616,7 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions( std::vector<cmSourceFile const*> manifest_srcs; this->GeneratorTarget->GetManifests(manifest_srcs, config); - cmProp dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE"); + cmValue dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE"); if (!manifest_srcs.empty() || dpiAware) { Elem e2(e1, "Manifest"); @@ -3677,24 +3677,24 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( e2.Element("EnableProGuard", "true"); } - if (cmProp proGuardConfigLocation = + if (cmValue proGuardConfigLocation = this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) { e2.Element("ProGuardConfigLocation", *proGuardConfigLocation); } - if (cmProp securePropertiesLocation = + if (cmValue securePropertiesLocation = this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) { e2.Element("SecurePropertiesLocation", *securePropertiesLocation); } - if (cmProp nativeLibDirectoriesExpression = + if (cmValue nativeLibDirectoriesExpression = this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) { std::string nativeLibDirs = cmGeneratorExpression::Evaluate( *nativeLibDirectoriesExpression, this->LocalGenerator, configName); e2.Element("NativeLibDirectories", nativeLibDirs); } - if (cmProp nativeLibDependenciesExpression = + if (cmValue nativeLibDependenciesExpression = this->GeneratorTarget->GetProperty( "ANDROID_NATIVE_LIB_DEPENDENCIES")) { std::string nativeLibDeps = cmGeneratorExpression::Evaluate( @@ -3702,24 +3702,24 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( e2.Element("NativeLibDependencies", nativeLibDeps); } - if (cmProp javaSourceDir = + if (cmValue javaSourceDir = this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) { e2.Element("JavaSourceDir", *javaSourceDir); } - if (cmProp jarDirectoriesExpression = + if (cmValue jarDirectoriesExpression = this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) { std::string jarDirectories = cmGeneratorExpression::Evaluate( *jarDirectoriesExpression, this->LocalGenerator, configName); e2.Element("JarDirectories", jarDirectories); } - if (cmProp jarDeps = + if (cmValue jarDeps = this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) { e2.Element("JarDependencies", *jarDeps); } - if (cmProp assetsDirectories = + if (cmValue assetsDirectories = this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) { e2.Element("AssetsDirectories", *assetsDirectories); } @@ -3730,7 +3730,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( e2.Element("AndroidManifestLocation", manifest_xml); } - if (cmProp antAdditionalOptions = + if (cmValue antAdditionalOptions = this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) { e2.Element("AdditionalOptions", *antAdditionalOptions + " %(AdditionalOptions)"); @@ -3785,13 +3785,13 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG; flags += " "; flags += this->Makefile->GetRequiredDefinition(linkFlagVar); - cmProp targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS"); + cmValue targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { flags += " "; flags += *targetLinkFlags; } std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG); - if (cmProp flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) { + if (cmValue flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) { flags += " "; flags += *flagsConfig; } @@ -3872,7 +3872,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( }; } - if (cmProp stackVal = this->Makefile->GetDefinition( + if (cmValue stackVal = this->Makefile->GetDefinition( "CMAKE_" + linkLanguage + "_STACK_SIZE")) { linkOptions.AddFlag("StackReserveSize", *stackVal); } @@ -4273,7 +4273,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) cmLocalGenerator* lg = dt->GetLocalGenerator(); std::string name = dt->GetName(); std::string path; - if (cmProp p = dt->GetProperty("EXTERNAL_MSPROJECT")) { + if (cmValue p = dt->GetProperty("EXTERNAL_MSPROJECT")) { path = *p; } else { path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(), @@ -4303,13 +4303,13 @@ void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1) // This only applies to Windows 10 apps if (this->GlobalGenerator->TargetsWindowsStore() && cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) { - cmProp desktopExtensionsVersion = + cmValue desktopExtensionsVersion = this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION"); if (desktopExtensionsVersion) { this->WriteSinglePlatformExtension(e1, "WindowsDesktop", *desktopExtensionsVersion); } - cmProp mobileExtensionsVersion = + cmValue mobileExtensionsVersion = this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION"); if (mobileExtensionsVersion) { this->WriteSinglePlatformExtension(e1, "WindowsMobile", @@ -4338,7 +4338,7 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) { std::vector<std::string> sdkReferences; std::unique_ptr<Elem> spe1; - if (cmProp vsSDKReferences = + if (cmValue vsSDKReferences = this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) { cmExpandList(*vsSDKReferences, sdkReferences); spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); @@ -4350,11 +4350,11 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) // This only applies to Windows 10 apps if (this->GlobalGenerator->TargetsWindowsStore() && cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) { - cmProp desktopExtensionsVersion = + cmValue desktopExtensionsVersion = this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION"); - cmProp mobileExtensionsVersion = + cmValue mobileExtensionsVersion = this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION"); - cmProp iotExtensionsVersion = + cmValue iotExtensionsVersion = this->GeneratorTarget->GetProperty("VS_IOT_EXTENSIONS_VERSION"); if (desktopExtensionsVersion || mobileExtensionsVersion || @@ -4564,7 +4564,7 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) if (!targetPlatformVersion.empty()) { e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion); } - cmProp targetPlatformMinVersion = this->GeneratorTarget->GetProperty( + cmValue targetPlatformMinVersion = this->GeneratorTarget->GetProperty( "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION"); if (targetPlatformMinVersion) { e1.Element("WindowsTargetPlatformMinVersion", *targetPlatformMinVersion); @@ -5060,7 +5060,7 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties( if (cmHasPrefix(p, propNamePrefix)) { std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - cmProp val = props.GetPropertyValue(p); + cmValue val = props.GetPropertyValue(p); if (cmNonempty(val)) { tags[tagName] = *val; } else { @@ -5112,7 +5112,7 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( } else if (!cmHasSuffix(fullFileName, ".cs") && cmHasPrefix(fullFileName, binDir)) { link = fullFileName.substr(binDir.length() + 1); - } else if (cmProp l = source->GetProperty("VS_CSHARP_Link")) { + } else if (cmValue l = source->GetProperty("VS_CSHARP_Link")) { link = *l; } diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index e4329afc6cb..e2c0f2daf68 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -204,7 +204,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, // Info tab begin - if (cmProp exe = + if (cmValue exe = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_EXECUTABLE")) { xout.StartElement("PathRunnable"); @@ -220,7 +220,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, // Arguments tab begin - if (cmProp argList = + if (cmValue argList = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) { std::vector<std::string> arguments = cmExpandedList(*argList); if (!arguments.empty()) { @@ -240,7 +240,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, } } - if (cmProp envList = + if (cmValue envList = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) { std::vector<std::string> envs = cmExpandedList(*envList); if (!envs.empty()) { @@ -323,7 +323,7 @@ bool cmXCodeScheme::WriteLaunchActionBooleanAttribute( cmXMLWriter& xout, const std::string& attrName, const std::string& varName, bool defaultValue) { - cmProp property = Target->GetTarget()->GetProperty(varName); + cmValue property = Target->GetTarget()->GetProperty(varName); bool isOn = (!property && defaultValue) || cmIsOn(property); if (isOn) { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 7cafaee92d7..fda79009175 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -599,7 +599,7 @@ void cmake::ProcessCacheArg(const std::string& var, const std::string& value, bool haveValue = false; std::string cachedValue; if (this->WarnUnusedCli) { - if (cmProp v = this->State->GetInitializedCacheValue(var)) { + if (cmValue v = this->State->GetInitializedCacheValue(var)) { haveValue = true; cachedValue = *v; } @@ -1468,7 +1468,7 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) // If there is a CMakeCache.txt file, use its settings. if (!cachePath.empty()) { if (this->LoadCache(cachePath)) { - cmProp existingValue = + cmValue existingValue = this->State->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"); if (existingValue) { this->SetHomeOutputDirectory(cachePath); @@ -1865,10 +1865,10 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) warning << "\n"; i -= 1; } - cmProp existingValue = this->State->GetCacheEntryValue(save.key); + cmValue existingValue = this->State->GetCacheEntryValue(save.key); if (existingValue) { save.type = this->State->GetCacheEntryType(save.key); - if (cmProp help = + if (cmValue help = this->State->GetCacheEntryProperty(save.key, "HELPSTRING")) { save.help = *help; } @@ -1917,9 +1917,9 @@ int cmake::Configure() if (this->DiagLevels.count("dev") == 1) { bool setDeprecatedVariables = false; - cmProp cachedWarnDeprecated = + cmValue cachedWarnDeprecated = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); - cmProp cachedErrorDeprecated = + cmValue cachedErrorDeprecated = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); // don't overwrite deprecated warning setting from a previous invocation @@ -1958,7 +1958,7 @@ int cmake::Configure() // 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. - cmProp value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); + cmValue value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(*value)); value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); @@ -1971,7 +1971,7 @@ int cmake::Configure() this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(*value)); int ret = this->ActualConfigure(); - cmProp delCacheVars = + cmValue delCacheVars = this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_"); if (delCacheVars && !delCacheVars->empty()) { return this->HandleDeleteCacheVariables(*delCacheVars); @@ -1999,8 +1999,8 @@ int cmake::ActualConfigure() // no generator specified on the command line if (!this->GlobalGenerator) { - cmProp genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); - cmProp extraGenName = + cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); + cmValue extraGenName = this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); if (genName) { std::string fullName = @@ -2023,7 +2023,7 @@ int cmake::ActualConfigure() } } - cmProp genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); + cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); if (genName) { if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) { std::string message = @@ -2053,7 +2053,7 @@ int cmake::ActualConfigure() } } - if (cmProp instance = + if (cmValue instance = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) { if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) { std::string message = @@ -2070,7 +2070,7 @@ int cmake::ActualConfigure() cmStateEnums::INTERNAL); } - if (cmProp platformName = + if (cmValue platformName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) { if (this->GeneratorPlatformSet && this->GeneratorPlatform != *platformName) { @@ -2087,7 +2087,7 @@ int cmake::ActualConfigure() "Name of generator platform.", cmStateEnums::INTERNAL); } - if (cmProp tsName = + if (cmValue tsName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) { if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) { std::string message = @@ -2410,7 +2410,7 @@ int cmake::Generate() return 0; } -void cmake::AddCacheEntry(const std::string& key, cmProp value, +void cmake::AddCacheEntry(const std::string& key, cmValue value, const char* helpString, int type) { this->State->AddCacheEntry(key, value, helpString, @@ -2486,7 +2486,7 @@ std::string cmake::StripExtension(const std::string& file) const return file; } -cmProp cmake::GetCacheDefinition(const std::string& name) const +cmValue cmake::GetCacheDefinition(const std::string& name) const { return this->State->GetInitializedCacheValue(name); } @@ -2695,7 +2695,7 @@ void cmake::PrintGeneratorList() void cmake::UpdateConversionPathTable() { // Update the path conversion table with any specified file: - cmProp tablepath = + cmValue tablepath = this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE"); if (tablepath) { @@ -2913,7 +2913,7 @@ void cmake::SetProperty(const std::string& prop, const char* value) { this->State->SetGlobalProperty(prop, value); } -void cmake::SetProperty(const std::string& prop, cmProp value) +void cmake::SetProperty(const std::string& prop, cmValue value) { this->State->SetGlobalProperty(prop, value); } @@ -2924,7 +2924,7 @@ void cmake::AppendProperty(const std::string& prop, const std::string& value, this->State->AppendGlobalProperty(prop, value, asString); } -cmProp cmake::GetProperty(const std::string& prop) +cmValue cmake::GetProperty(const std::string& prop) { return this->State->GetGlobalProperty(prop); } @@ -3169,7 +3169,7 @@ void cmake::IssueMessage(MessageType t, std::string const& text, std::vector<std::string> cmake::GetDebugConfigs() { std::vector<std::string> configs; - if (cmProp config_list = + if (cmValue config_list = this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) { // Expand the specified list and convert to upper-case. cmExpandList(*config_list, configs); @@ -3318,7 +3318,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, std::cerr << "Error: could not load cache\n"; return 1; } - cmProp cachedGenerator = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); + cmValue cachedGenerator = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); if (!cachedGenerator) { std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return 1; @@ -3330,7 +3330,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, return 1; } this->SetGlobalGenerator(std::move(gen)); - cmProp cachedGeneratorInstance = + cmValue cachedGeneratorInstance = this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE"); if (cachedGeneratorInstance) { cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); @@ -3339,7 +3339,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, return 1; } } - cmProp cachedGeneratorPlatform = + cmValue cachedGeneratorPlatform = this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM"); if (cachedGeneratorPlatform) { cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); @@ -3348,7 +3348,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, return 1; } } - cmProp cachedGeneratorToolset = + cmValue cachedGeneratorToolset = this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); if (cachedGeneratorToolset) { cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot()); @@ -3359,7 +3359,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, } std::string output; std::string projName; - cmProp cachedProjectName = + cmValue cachedProjectName = this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME"); if (!cachedProjectName) { std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n"; @@ -3451,12 +3451,12 @@ bool cmake::Open(const std::string& dir, bool dryRun) std::cerr << "Error: could not load cache\n"; return false; } - cmProp genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); + cmValue genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); if (!genName) { std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; return false; } - cmProp extraGenName = + cmValue extraGenName = this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); std::string fullName = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( @@ -3470,7 +3470,7 @@ bool cmake::Open(const std::string& dir, bool dryRun) return false; } - cmProp cachedProjectName = + cmValue cachedProjectName = this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME"); if (!cachedProjectName) { std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n"; diff --git a/Source/cmake.h b/Source/cmake.h index 74080440c5f..3f2b2eda414 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -21,10 +21,10 @@ #include "cmInstalledFile.h" #include "cmListFileCache.h" #include "cmMessageType.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmValue.h" #if !defined(CMAKE_BOOTSTRAP) # include <cm/optional> @@ -329,21 +329,21 @@ class cmake /** * Given a variable name, return its value (as a string). */ - cmProp GetCacheDefinition(const std::string&) const; + cmValue GetCacheDefinition(const std::string&) const; //! Add an entry into the cache void AddCacheEntry(const std::string& key, const char* value, const char* helpString, int type) { this->AddCacheEntry(key, - value ? cmProp(std::string(value)) : cmProp(nullptr), + value ? cmValue(std::string(value)) : cmValue(nullptr), helpString, type); } void AddCacheEntry(const std::string& key, const std::string& value, const char* helpString, int type) { - this->AddCacheEntry(key, cmProp(value), helpString, type); + this->AddCacheEntry(key, cmValue(value), helpString, type); } - void AddCacheEntry(const std::string& key, cmProp value, + void AddCacheEntry(const std::string& key, cmValue value, const char* helpString, int type); bool DoWriteGlobVerifyTarget() const; @@ -408,14 +408,14 @@ class cmake //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); - void SetProperty(const std::string& prop, cmProp value); + void SetProperty(const std::string& prop, cmValue value); void SetProperty(const std::string& prop, const std::string& value) { - this->SetProperty(prop, cmProp(value)); + this->SetProperty(prop, cmValue(value)); } void AppendProperty(const std::string& prop, const std::string& value, bool asString = false); - cmProp GetProperty(const std::string& prop); + cmValue GetProperty(const std::string& prop); bool GetPropertyAsBool(const std::string& prop); //! Get or create an cmInstalledFile instance and return a pointer to it diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 64d93df7fc7..61d4ae486b2 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -25,11 +25,11 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageMetadata.h" -#include "cmProperty.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmake.h" #include "cmcmd.h" @@ -375,11 +375,11 @@ int do_cmake(int ac, char const* const* av) cmStateEnums::CacheEntryType t = cm.GetState()->GetCacheEntryType(k); if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC && t != cmStateEnums::UNINITIALIZED) { - cmProp advancedProp = + cmValue advancedProp = cm.GetState()->GetCacheEntryProperty(k, "ADVANCED"); if (list_all_cached || !advancedProp) { if (list_help) { - cmProp help = + cmValue help = cm.GetState()->GetCacheEntryProperty(k, "HELPSTRING"); std::cout << "// " << (help ? *help : "") << std::endl; } diff --git a/bootstrap b/bootstrap index d0329fbf706..d48a8672343 100755 --- a/bootstrap +++ b/bootstrap @@ -426,7 +426,7 @@ CMAKE_CXX_SOURCES="\ cmPolicies \ cmProcessOutput \ cmProjectCommand \ - cmProperty \ + cmValue \ cmPropertyDefinition \ cmPropertyMap \ cmGccDepfileLexerHelper \ From edf67dd039f40a4222e41cc15a197cb6395bf885 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 21 Sep 2021 17:13:14 +0200 Subject: [PATCH 1268/1519] cmValue: add IsInternallyOn methods --- Source/cmStringAlgorithms.cxx | 9 --------- Source/cmStringAlgorithms.h | 15 ++++++--------- Source/cmValue.cxx | 10 ++++++++++ Source/cmValue.h | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx index acb5e5be5bf..1bb68081999 100644 --- a/Source/cmStringAlgorithms.cxx +++ b/Source/cmStringAlgorithms.cxx @@ -218,15 +218,6 @@ std::string cmCatViews(std::initializer_list<cm::string_view> views) return result; } -bool cmIsInternallyOn(cm::string_view val) -{ - return (val.size() == 4) && // - (val[0] == 'I' || val[0] == 'i') && // - (val[1] == '_') && // - (val[2] == 'O' || val[2] == 'o') && // - (val[3] == 'N' || val[3] == 'n'); -} - bool cmStrToLong(const char* str, long* value) { errno = 0; diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index a9edcdf436d..fd5febff72e 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -224,20 +224,17 @@ std::string cmWrap(char prefix, Range const& rng, char suffix, * forced this value. This is not the same as On, but this * may be considered as "internally switched on". */ -bool cmIsInternallyOn(cm::string_view val); +inline bool cmIsInternallyOn(cm::string_view val) +{ + return cmValue::IsInternallyOn(val); +} inline bool cmIsInternallyOn(const char* val) { - if (!val) { - return false; - } - return cmIsInternallyOn(cm::string_view(val)); + return cmValue::IsInternallyOn(val); } inline bool cmIsInternallyOn(cmValue val) { - if (!val) { - return false; - } - return cmIsInternallyOn(*val); + return val.IsInternallyOn(); } /** Check for non-empty Property/Variable value. */ diff --git a/Source/cmValue.cxx b/Source/cmValue.cxx index 59bf201b702..044db2909d0 100644 --- a/Source/cmValue.cxx +++ b/Source/cmValue.cxx @@ -73,11 +73,21 @@ bool cmValue::IsOff(cm::string_view value) noexcept return IsNOTFOUND(value); } + bool cmValue::IsNOTFOUND(cm::string_view value) noexcept { return (value == "NOTFOUND"_s) || cmHasSuffix(value, "-NOTFOUND"_s); } +bool cmValue::IsInternallyOn(cm::string_view value) noexcept +{ + return (value.size() == 4) && // + (value[0] == 'I' || value[0] == 'i') && // + (value[1] == '_') && // + (value[2] == 'O' || value[2] == 'o') && // + (value[3] == 'N' || value[3] == 'n'); +} + int cmValue::Compare(cmValue value) const noexcept { if (this->Value == nullptr && !value) { diff --git a/Source/cmValue.h b/Source/cmValue.h index 43a5e0d3045..c79b9971c48 100644 --- a/Source/cmValue.h +++ b/Source/cmValue.h @@ -85,6 +85,17 @@ class cmValue return this->Value == nullptr || this->Value->empty(); } + /** + * Does a string indicates that CMake/CPack/CTest internally + * forced this value. This is not the same as On, but this + * may be considered as "internally switched on". + */ + bool IsInternallyOn() const noexcept + { + return this->Value != nullptr && + cmValue::IsInternallyOn(cm::string_view(*this->Value)); + } + bool IsSet() const noexcept { return !this->IsEmpty() && !this->IsNOTFOUND(); @@ -131,6 +142,17 @@ class cmValue } static bool IsEmpty(cm::string_view value) noexcept { return value.empty(); } + /** + * Does a string indicates that CMake/CPack/CTest internally + * forced this value. This is not the same as On, but this + * may be considered as "internally switched on". + */ + static bool IsInternallyOn(const char* value) noexcept + { + return value != nullptr && IsInternallyOn(cm::string_view(value)); + } + static bool IsInternallyOn(cm::string_view) noexcept; + private: static std::string Empty; const std::string* Value = nullptr; From 59ad7a1c243022284f8475e0bebbe1864ee23928 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Tue, 21 Sep 2021 17:38:59 +0200 Subject: [PATCH 1269/1519] Move helpers functions from cmStringAlgorithms.h to cmValue.h Helpers functions related to cmValue semantic are now part of cmValue.h header. --- Source/CTest/cmCTestGIT.cxx | 1 + Source/CTest/cmCTestVC.cxx | 2 +- Source/cmAddLibraryCommand.cxx | 1 + Source/cmComputeTargetDepends.cxx | 1 - Source/cmFileInstaller.cxx | 1 + Source/cmGlobalCommonGenerator.cxx | 1 - Source/cmIncludeDirectoryCommand.cxx | 1 + Source/cmInstalledFile.cxx | 1 + Source/cmOutputConverter.cxx | 1 + Source/cmQtAutoGenerator.cxx | 1 + Source/cmSiteNameCommand.cxx | 1 - Source/cmStringAlgorithms.h | 78 ---------------------------- Source/cmSystemTools.cxx | 1 + Source/cmTest.cxx | 1 - Source/cmValue.h | 78 ++++++++++++++++++++++++++++ Source/cmcmd.cxx | 1 + 16 files changed, 88 insertions(+), 83 deletions(-) diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 568b0917c6c..d85edcc5ff0 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -18,6 +18,7 @@ #include "cmProcessTools.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major, unsigned int minor, unsigned int fix) diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 452d7143bc2..423b5064c9e 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -10,8 +10,8 @@ #include "cmsys/Process.h" #include "cmCTest.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" #include "cmXMLWriter.h" cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log) diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 92e04e43c46..a5d1f6a07fc 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -12,6 +12,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" +#include "cmValue.h" bool cmAddLibraryCommand(std::vector<std::string> const& args, cmExecutionStatus& status) diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index d85dea33f6d..2f296108391 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -22,7 +22,6 @@ #include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx index 0d8ba2d2662..9bfbd135c92 100644 --- a/Source/cmFileInstaller.cxx +++ b/Source/cmFileInstaller.cxx @@ -17,6 +17,7 @@ #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" using namespace cmFSPermissions; diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 31ff52f09c2..3ae66f0abe8 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -14,7 +14,6 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" #include "cmake.h" diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index b408f7210fa..23427a1a50c 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -13,6 +13,7 @@ #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" static void GetIncludes(cmMakefile& mf, const std::string& arg, std::vector<std::string>& incs); diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 32395d10e20..0974eea5638 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -8,6 +8,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" cmInstalledFile::cmInstalledFile() = default; diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 840fdb9ecfc..bda2fe5c2a3 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -12,6 +12,7 @@ #include "cmStateDirectory.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" namespace { bool PathEqOrSubDir(std::string const& a, std::string const& b) diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 568926e3c5d..e5c7bda669b 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -9,6 +9,7 @@ #include "cmQtAutoGen.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmValue.h" cmQtAutoGenerator::Logger::Logger() { diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 34fdefe350f..61d1c30027b 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -7,7 +7,6 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmValue.h" diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index fd5febff72e..492e588bbd3 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -219,84 +219,6 @@ std::string cmWrap(char prefix, Range const& rng, char suffix, sep); } -/** - * Does a string indicates that CMake/CPack/CTest internally - * forced this value. This is not the same as On, but this - * may be considered as "internally switched on". - */ -inline bool cmIsInternallyOn(cm::string_view val) -{ - return cmValue::IsInternallyOn(val); -} -inline bool cmIsInternallyOn(const char* val) -{ - return cmValue::IsInternallyOn(val); -} -inline bool cmIsInternallyOn(cmValue val) -{ - return val.IsInternallyOn(); -} - -/** Check for non-empty Property/Variable value. */ -inline bool cmNonempty(cm::string_view val) -{ - return !cmValue::IsEmpty(val); -} -inline bool cmNonempty(const char* val) -{ - return !cmValue::IsEmpty(val); -} -inline bool cmNonempty(cmValue val) -{ - return !val.IsEmpty(); -} - -/** Return true if value is NOTFOUND or ends in -NOTFOUND. */ -inline bool cmIsNOTFOUND(cm::string_view val) -{ - return cmValue::IsNOTFOUND(val); -} -inline bool cmIsNOTFOUND(cmValue val) -{ - return val.IsNOTFOUND(); -} - -/** - * Does a string indicate a true or ON value? This is not the same as ifdef. - */ -inline bool cmIsOn(cm::string_view val) -{ - return cmValue::IsOn(val); -} -inline bool cmIsOn(const char* val) -{ - return cmValue::IsOn(val); -} -inline bool cmIsOn(cmValue val) -{ - return val.IsOn(); -} - -/** - * Does a string indicate a false or off value ? Note that this is - * not the same as !IsOn(...) because there are a number of - * ambiguous values such as "/usr/local/bin" a path will result in - * IsON and IsOff both returning false. Note that the special path - * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. - */ -inline bool cmIsOff(cm::string_view val) -{ - return cmValue::IsOff(val); -} -inline bool cmIsOff(const char* val) -{ - return cmValue::IsOff(val); -} -inline bool cmIsOff(cmValue val) -{ - return val.IsOff(); -} - /** Returns true if string @a str starts with the character @a prefix. */ inline bool cmHasPrefix(cm::string_view str, char prefix) { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 27cb90fa581..75a5a8d8789 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -25,6 +25,7 @@ #include "cmProcessOutput.h" #include "cmRange.h" #include "cmStringAlgorithms.h" +#include "cmValue.h" #if !defined(CMAKE_BOOTSTRAP) # include <cm3p/archive.h> diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 56184871d71..7c0f9e72226 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -5,7 +5,6 @@ #include "cmMakefile.h" #include "cmProperty.h" #include "cmState.h" -#include "cmStringAlgorithms.h" #include "cmValue.h" cmTest::cmTest(cmMakefile* mf) diff --git a/Source/cmValue.h b/Source/cmValue.h index c79b9971c48..f96d2f5de23 100644 --- a/Source/cmValue.h +++ b/Source/cmValue.h @@ -234,3 +234,81 @@ inline bool operator>=(cmValue l, std::nullptr_t) noexcept { return l.Compare(cmValue{}) >= 0; } + +/** + * Does a string indicate a true or ON value? This is not the same as ifdef. + */ +inline bool cmIsOn(cm::string_view val) +{ + return cmValue::IsOn(val); +} +inline bool cmIsOn(const char* val) +{ + return cmValue::IsOn(val); +} +inline bool cmIsOn(cmValue val) +{ + return val.IsOn(); +} + +/** + * Does a string indicate a false or off value ? Note that this is + * not the same as !IsOn(...) because there are a number of + * ambiguous values such as "/usr/local/bin" a path will result in + * IsON and IsOff both returning false. Note that the special path + * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. + */ +inline bool cmIsOff(cm::string_view val) +{ + return cmValue::IsOff(val); +} +inline bool cmIsOff(const char* val) +{ + return cmValue::IsOff(val); +} +inline bool cmIsOff(cmValue val) +{ + return val.IsOff(); +} + +/** Return true if value is NOTFOUND or ends in -NOTFOUND. */ +inline bool cmIsNOTFOUND(cm::string_view val) +{ + return cmValue::IsNOTFOUND(val); +} +inline bool cmIsNOTFOUND(cmValue val) +{ + return val.IsNOTFOUND(); +} + +/** Check for non-empty Property/Variable value. */ +inline bool cmNonempty(cm::string_view val) +{ + return !cmValue::IsEmpty(val); +} +inline bool cmNonempty(const char* val) +{ + return !cmValue::IsEmpty(val); +} +inline bool cmNonempty(cmValue val) +{ + return !val.IsEmpty(); +} + +/** + * Does a string indicates that CMake/CPack/CTest internally + * forced this value. This is not the same as On, but this + * may be considered as "internally switched on". + */ +inline bool cmIsInternallyOn(cm::string_view val) +{ + return cmValue::IsInternallyOn(val); +} +inline bool cmIsInternallyOn(const char* val) +{ + return cmValue::IsInternallyOn(val); +} +inline bool cmIsInternallyOn(cmValue val) +{ + return val.IsInternallyOn(); +} diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 3e36f978594..4eb98b98074 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -23,6 +23,7 @@ #include "cmTransformDepfile.h" #include "cmUVProcessChain.h" #include "cmUtils.hxx" +#include "cmValue.h" #include "cmVersion.h" #include "cmake.h" From 60caed1bd646a7efbf045d55e80286c0cf28c685 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 22 Sep 2021 00:02:18 -0400 Subject: [PATCH 1270/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index caa48066ce0..ab48c04caf5 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210921) +set(CMake_VERSION_PATCH 20210922) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2f43ba507397a6d13924a592d4ebd86d7df8a2ef Mon Sep 17 00:00:00 2001 From: Vincent Newsum <vynewsum@gmail.com> Date: Wed, 22 Sep 2021 09:43:56 +0200 Subject: [PATCH 1271/1519] FindMatlab: Sort available Matlab versions using natural comparison. On Windows, when FindMatlab.cmake searches the registry for installed Matlab versions, it sorts these versions alphabetically. Since Matlab 2021a (version 9.10) came out this became a problem as now version 9.10 is placed after 9.1 instead of after a higher version less than 9.10. The result is that FindMatlab doesn't return the highest version by default. This fix uses the natural sort comparison which was introduced in CMake 3.18. --- Modules/FindMatlab.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 12a5fde7e6d..e4fcd839a11 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -477,7 +477,7 @@ function(matlab_extract_all_installed_versions_from_registry win64 matlab_versio if(matlabs_from_registry) list(REMOVE_DUPLICATES matlabs_from_registry) - list(SORT matlabs_from_registry) + list(SORT matlabs_from_registry COMPARE NATURAL) list(REVERSE matlabs_from_registry) endif() @@ -521,7 +521,7 @@ macro(extract_matlab_versions_from_registry_brute_force matlab_versions) # we order from more recent to older if(matlab_supported_versions) list(REMOVE_DUPLICATES matlab_supported_versions) - list(SORT matlab_supported_versions) + list(SORT matlab_supported_versions COMPARE NATURAL) list(REVERSE matlab_supported_versions) endif() From a2b782bbc113eab4c2d64d7f40fa6e829f6937b2 Mon Sep 17 00:00:00 2001 From: Luigi Fiorentini <lfiorentini@topcon.com> Date: Tue, 14 Sep 2021 20:44:44 +0200 Subject: [PATCH 1272/1519] VS: Map /Y- flag to not use precompiled headers with VS 2008 --- Source/cmGlobalVisualStudio7Generator.cxx | 1 + Source/cmGlobalVisualStudio8Generator.cxx | 1 + Source/cmLocalVisualStudio7Generator.cxx | 1 + 3 files changed, 3 insertions(+) diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 9db654f7b13..6876e6179a2 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -37,6 +37,7 @@ static cmVS7FlagTable cmVS7ExtraFlagTable[] = { cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", cmVS7FlagTable::UserValueRequired }, + { "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 }, { "WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true", 0 }, diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 34bdc1c6378..092e5b92d9e 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -370,6 +370,7 @@ static cmVS7FlagTable cmVS8ExtraFlagTable[] = { cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", cmVS7FlagTable::UserValueRequired }, + { "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 }, // There is no YX option in the VS8 IDE. // Exception handling mode. If no entries match, it will be FALSE. diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 9ad5f5661ec..5d3e11a64f1 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -402,6 +402,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = { cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "", cmVS7FlagTable::UserValueRequired }, + { "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 }, { "PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "", cmVS7FlagTable::UserValue }, // The YX and Yu options are in a per-global-generator table because From 8a859fd6aef8f6c829eaf2a9b0628f1e049951c0 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 10:59:29 +0300 Subject: [PATCH 1273/1519] FindLAPACK: Fujitsu_SSL2: LAPACK is in BLAS --- Modules/FindLAPACK.cmake | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index f36acfdb564..7b5e01d8d23 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -581,33 +581,10 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # Fujitsu SSL2 Library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All")) - if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP") - set(_ssl2_suffix BLAMP) - else() - set(_ssl2_suffix) - endif() - set(_ssl2_blas) - if(BLAS_LIBRARIES STREQUAL "") - set(_ssl2_blas "${BLAS_LINKER_FLAGS}") - else() - set(_ssl2_blas "${BLAS_LIBRARIES} ${BLAS_LINKER_FLAGS}") - endif() - check_lapack_libraries( - LAPACK_LIBRARIES - LAPACK - cheev - "-SSL2${_ssl2_suffix}" - "" - "" - "" - "" - "${_ssl2_blas}" - ) - if(LAPACK_LIBRARIES) - set(LAPACK_LINKER_FLAGS "-SSL2${_ssl2_suffix}") - set(_lapack_fphsa_req_var LAPACK_LINKER_FLAGS) + if(BLAS_LIBRARIES MATCHES "fjlapack.+") + set(LAPACK_LIBRARIES ${BLAS_LIBRARIES}) + set(LAPACK_LINKER_FLAGS ${BLAS_LINKER_FLAGS}) endif() - unset(_ssl2_suffix) endif() # LAPACK in IBM ESSL library? From f17f20f6cd8a96a57965f08f8f8fecaedeb277af Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:00:27 +0300 Subject: [PATCH 1274/1519] FindLAPACK: IBMESSL: LAPACK is in BLAS --- Modules/FindLAPACK.cmake | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 7b5e01d8d23..aee0dc28433 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -590,25 +590,9 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # LAPACK in IBM ESSL library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All")) - set(_lapack_essl_lib "essl") - - # Check for OpenMP support, VIA BLA_VENDOR of esslsmp - if(BLA_VENDOR MATCHES "_SMP") - set(_lapack_essl_lib "${_lapack_essl_lib}smp") + if(BLAS_LIBRARIES MATCHES "essl.+") + set(LAPACK_LIBRARIES ${BLAS_LIBRARIES}) endif() - - check_lapack_libraries( - LAPACK_LIBRARIES - LAPACK - cheev - "" - "${_lapack_essl_lib}" - "" - "" - "" - "${BLAS_LIBRARIES}" - ) - unset(_lapack_essl_lib) endif() # NVHPC Library? From 7cb89314dd6f2b7d919133b83c1114a55ac7a209 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:00:57 +0300 Subject: [PATCH 1275/1519] FindLAPACK: EML: LAPACK is in BLAS --- Modules/FindLAPACK.cmake | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index aee0dc28433..3f9635e6721 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -557,25 +557,9 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # Elbrus Math Library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")) - - set(LAPACK_EML_LIB "eml") - - # Check for OpenMP support, VIA BLA_VENDOR of eml_mt - if(BLA_VENDOR MATCHES "_mt") - set(LAPACK_EML_LIB "${LAPACK_EML_LIB}_mt") + if(BLAS_LIBRARIES MATCHES "eml.+") + set(LAPACK_LIBRARIES ${BLAS_LIBRARIES}) endif() - - check_lapack_libraries( - LAPACK_LIBRARIES - LAPACK - cheev - "" - "${LAPACK_EML_LIB}" - "" - "" - "" - "${BLAS_LIBRARIES}" - ) endif() # Fujitsu SSL2 Library? From 9f525327574e3381d425bee02173ff03aeb1351c Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:02:47 +0300 Subject: [PATCH 1276/1519] FindLAPACK: Update NVHPC --- Modules/FindLAPACK.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 3f9635e6721..ca62b847e2a 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -580,19 +580,24 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) endif() # NVHPC Library? + if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All")) + set(_lapack_nvhpc_lib "lapack") + check_lapack_libraries( LAPACK_LIBRARIES LAPACK cheev "" - "lapack" + "${_lapack_nvhpc_lib}" "-fortranlibs" "" "" "${BLAS_LIBRARIES}" ) + + unset(_lapack_nvhpc_lib) endif() # Generic LAPACK library? From 285c518937b6a3d7cfd9866d5e91910a587523d5 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:04:22 +0300 Subject: [PATCH 1277/1519] FindLAPACK: Update OpenBLAS --- Modules/FindLAPACK.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index ca62b847e2a..7bef443e8c6 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -434,17 +434,21 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # OpenBLAS? (http://www.openblas.net) if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")) + set(_lapack_openblas_lib "openblas") + check_lapack_libraries( LAPACK_LIBRARIES LAPACK cheev "" - "openblas" + "${_lapack_openblas_lib}" "" "" "" "${BLAS_LIBRARIES}" ) + + unset(_lapack_openblas_lib) endif() # ArmPL? (https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux/arm-performance-libraries) From 8fdbd272b580344da2fbca33dd960dc2b29a43d1 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:05:12 +0300 Subject: [PATCH 1278/1519] FindLAPACK: Update FlexiBLAS --- Modules/FindLAPACK.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 7bef443e8c6..b82a464fab2 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -418,17 +418,21 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # FlexiBLAS? (http://www.mpi-magdeburg.mpg.de/mpcsc/software/FlexiBLAS/) if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All")) + set(_lapack_flexiblas_lib "flexiblas") + check_lapack_libraries( LAPACK_LIBRARIES LAPACK cheev "" - "flexiblas" + "${_lapack_flexiblas_lib}" "" "" "" "${BLAS_LIBRARIES}" ) + + unset(_lapack_flexiblas_lib) endif() # OpenBLAS? (http://www.openblas.net) From 2531e464dfefaacdd06c6b28e7f59897510a52c1 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:30:46 +0300 Subject: [PATCH 1279/1519] FindLAPACK: Update Generic LAPACK --- Modules/FindLAPACK.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index b82a464fab2..824cfd24a11 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -613,6 +613,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) AND (BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All")) + set(_lapack_generic_lib "lapack") if(BLA_STATIC) # We do not know for sure how the LAPACK reference implementation # is built on this host. Guess typical dependencies. @@ -625,13 +626,15 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) LAPACK cheev "" - "lapack" + "${_lapack_generic_lib}" "${_lapack_generic_deps}" "" "" "${BLAS_LIBRARIES}" ) + unset(_lapack_generic_deps) + unset(_lapack_generic_lib) endif() endif() From c4d4f0708b9c8aa0cba6d8d031aee7d30798dba6 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:13:33 +0300 Subject: [PATCH 1280/1519] FindBLAS: Move NVHPC from Generic BLAS --- Modules/FindBLAS.cmake | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index a44af4d2a42..5743f9d63d3 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -1153,9 +1153,28 @@ if(NOT BLAS_LIBRARIES unset(_ssl2_suffix) endif() +# BLAS in nVidia HPC SDK? (https://developer.nvidia.com/hpc-sdk) +if(BLA_VENDOR STREQUAL "NVHPC" OR BLA_VENDOR STREQUAL "All") + set(_blas_nvhpc_lib "blas") + + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "${_blas_nvhpc_lib}" + "" + "" + "" + ) + endif() + + unset(_blas_nvhpc_lib) +endif() + # Generic BLAS library? if(BLA_VENDOR STREQUAL "Generic" OR - BLA_VENDOR STREQUAL "NVHPC" OR BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) check_blas_libraries( From bf048d2ddd3472c52cadd9c1562717ef29d6323a Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:29:18 +0300 Subject: [PATCH 1281/1519] FindBLAS: Update Generic BLAS --- Modules/FindBLAS.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 5743f9d63d3..575d223bc10 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -1176,18 +1176,22 @@ endif() # Generic BLAS library? if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All") + set(_blas_generic_lib "blas") + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS sgemm "" - "blas" + "${_blas_generic_lib}" "" "" "" ) endif() + + unset(_blas_generic_lib) endif() # On compilers that implicitly link BLAS (i.e. CrayPrgEnv) we used a From 84b7e2e15d6ed70474c345484c2961725f066142 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:19:54 +0300 Subject: [PATCH 1282/1519] FindBLAS: Update FLAME --- Modules/FindBLAS.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 575d223bc10..ca3afc4215d 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -765,18 +765,22 @@ endif() # FLAME's blis library? (https://github.com/flame/blis) if(BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All") + set(_blas_flame_lib "blis") + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS sgemm "" - "blis" + "${_blas_flame_lib}" "" "" "" ) endif() + + unset(_blas_flame_lib) endif() # BLAS in the ATLAS library? (http://math-atlas.sourceforge.net/) From 21250d4dd2e0e6cdb3da089b6f9e0d8e30614f40 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:20:15 +0300 Subject: [PATCH 1283/1519] FindBLAS: Update OpenBLAS --- Modules/FindBLAS.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index ca3afc4215d..5ce726c401f 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -691,13 +691,15 @@ endif() # OpenBLAS? (http://www.openblas.net) if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All") + set(_blas_openblas_lib "openblas") + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS sgemm "" - "openblas" + "${_blas_openblas_lib}" "" "" "" @@ -724,13 +726,15 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All") BLAS sgemm "" - "openblas" + "${_blas_openblas_lib}" "${_threadlibs}" "" "" ) unset(_threadlibs) endif() + + unset(_blas_openblas_lib) endif() # ArmPL blas library? (https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux/arm-performance-libraries) From 88969b51679784ce2f64da4d8ceefbf802cfcdff Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:21:16 +0300 Subject: [PATCH 1284/1519] FindBLAS: Update FlexiBLAS --- Modules/FindBLAS.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 5ce726c401f..e22fae318e1 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -675,18 +675,22 @@ endif() # FlexiBLAS? (http://www.mpi-magdeburg.mpg.de/mpcsc/software/FlexiBLAS/) if(BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All") + set(_blas_flexiblas_lib "flexiblas") + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS sgemm "" - "flexiblas" + "${_blas_flexiblas_lib}" "" "" "" ) endif() + + unset(_blas_flexiblas_lib) endif() # OpenBLAS? (http://www.openblas.net) From efed2f8706b46d2f5c7711a9426b7e23a08b9709 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 23 Sep 2021 00:01:16 -0400 Subject: [PATCH 1285/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ab48c04caf5..e8a633edfa6 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210922) +set(CMake_VERSION_PATCH 20210923) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 84e02be51c5c725c033e54276e6e41be8bd1b96d Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 5 Sep 2021 18:12:14 +1000 Subject: [PATCH 1286/1519] Help: Restructure the find_package() docs The explanation of the basic and full signatures was interwoven tightly with that of the Module and Config search modes. Config mode is supported by both signatures, which made the structure of the command documentation a bit confusing. Add a section at the start which unambiguously describes the two modes, including the fallback functionality between them. Move the text about this out of the basic signature section, leaving just a description of the basic syntax with a note that it is supported by both search modes. This makes the basic signature section more focused. Drop the Module and Config mode parts of the titles for the basic and full signature sections. Those are now more precisely covered by the new opening section, so the Basic Signature and Full Signature sections are now clearer in what they cover. Swap the order of the Search Procedure and Version Selection sections to improve the logical flow. Also add "Config Mode" to their titles to make it clearer what they apply to. Add a note at the start of both sections to highlight their relationship to the basic and full signatures. --- Help/command/find_package.rst | 407 +++++++++++++++++++--------------- 1 file changed, 231 insertions(+), 176 deletions(-) diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 83887096baa..1a79a8af370 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -5,12 +5,74 @@ find_package .. contents:: -Find an external project, and load its settings. +Find a package (usually provided by something external to the project), +and load its package-specific details. + +Search Modes +^^^^^^^^^^^^ + +The command has two very distinct ways of conducting the search: + +**Module mode** + In this mode, CMake searches for a file called ``Find<PackageName>.cmake``, + looking first in the locations listed in the :variable:`CMAKE_MODULE_PATH`, + then among the :ref:`Find Modules` provided by the CMake installation. + If the file is found, it is read and processed by CMake. It is responsible + for finding the package, checking the version, and producing any needed + messages. Some Find modules provide limited or no support for versioning; + check the Find module's documentation. + + The ``Find<PackageName>.cmake`` file is not typically provided by the + package itself. Rather, it is normally provided by something external to + the package, such as the operating system, CMake itself, or even the project + from which the ``find_package()`` command was called. Being externally + provided, :ref:`Find Modules` tend to be heuristic in nature and are + susceptible to becoming out-of-date. They typically search for certain + libraries, files and other package artifacts. + + Module mode is only supported by the + :ref:`basic command signature <Basic Signature>`. + +**Config mode** + In this mode, CMake searches for a file called + ``<lowercasePackageName>-config.cmake`` or ``<PackageName>Config.cmake``. + It will also look for ``<lowercasePackageName>-config-version.cmake`` or + ``<PackageName>ConfigVersion.cmake`` if version details were specified + (see :ref:`version selection` for an explanation of how these separate + version files are used). + + In config mode, the command can be given a list of names to search for + as package names. The locations where CMake searches for the config and + version files is considerably more complicated than for Module mode + (see :ref:`search procedure`). + + The config and version files are typically installed as part of the + package, so they tend to be more reliable than Find modules. They usually + contain direct knowledge of the package contents, so no searching or + heuristics are needed within the config or version files themselves. + + Config mode is supported by both the :ref:`basic <Basic Signature>` and + :ref:`full <Full Signature>` command signatures. + +The command arguments determine which of the above modes is used. When the +`basic signature`_ is used, the command searches in Module mode first. +If the package is not found, the search falls back to Config mode. +A user may set the :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` variable +to true to reverse the priority and direct CMake to search using Config mode +first before falling back to Module mode. The basic signature can also be +forced to use only Module mode with a ``MODULE`` keyword. If the +`full signature`_ is used, the command only searches in Config mode. + +Where possible, user code should generally look for packages using the +`basic signature`_, since that allows the package to be found with either mode. +Project maintainers wishing to provide a config package should understand +the bigger picture, as explained in :ref:`Full Signature` and all subsequent +sections on this page. .. _`basic signature`: -Basic Signature and Module Mode -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Basic Signature +^^^^^^^^^^^^^^^ .. code-block:: cmake @@ -19,10 +81,14 @@ Basic Signature and Module Mode [OPTIONAL_COMPONENTS components...] [NO_POLICY_SCOPE]) -Finds and loads settings from an external project. ``<PackageName>_FOUND`` -will be set to indicate whether the package was found. When the -package is found package-specific information is provided through -variables and :ref:`Imported Targets` documented by the package itself. The +The basic signature is supported by both Module and Config modes. +The ``MODULE`` keyword implies that only Module mode can be used to find +the package, with no fallback to Config mode. + +Regardless of the mode used, a ``<PackageName>_FOUND`` variable will be +set to indicate whether the package was found. When the package is found, +package-specific information may be provided through other variables and +:ref:`Imported Targets` documented by the package itself. The ``QUIET`` option disables informational messages, including those indicating that the package cannot be found if it is not ``REQUIRED``. The ``REQUIRED`` option stops processing with an error message if the package cannot be found. @@ -78,36 +144,10 @@ only take the single version at the lower end of the range into account. See the :command:`cmake_policy` command documentation for discussion of the ``NO_POLICY_SCOPE`` option. -The command has two modes by which it searches for packages: "Module" -mode and "Config" mode. The above signature selects Module mode. -If no module is found the command falls back to Config mode, described -below. This fall back is disabled if the ``MODULE`` option is given. - -In Module mode, CMake searches for a file called ``Find<PackageName>.cmake``. -The file is first searched in the :variable:`CMAKE_MODULE_PATH`, -then among the :ref:`Find Modules` provided by the CMake installation. -If the file is found, it is read and processed by CMake. It is responsible -for finding the package, checking the version, and producing any needed -messages. Some find-modules provide limited or no support for versioning; -check the module documentation. - -If the ``MODULE`` option is not specified in the above signature, -CMake first searches for the package using Module mode. Then, if the -package is not found, it searches again using Config mode. A user -may set the variable :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` to -``TRUE`` to direct CMake first search using Config mode before falling -back to Module mode. - -Full Signature and Config Mode -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -User code should generally look for packages using the above `basic -signature`_. The remainder of this command documentation specifies the -full command signature and details of the search process. Project -maintainers wishing to provide a package to be found by this command -are encouraged to read on. - -The complete Config mode command signature is +.. _`full signature`: + +Full Signature +^^^^^^^^^^^^^^ .. code-block:: cmake @@ -145,18 +185,19 @@ hold the directory containing the file. By default the command searches for a package with the name ``<PackageName>``. If the ``NAMES`` option is given the names following it are used instead of ``<PackageName>``. The command searches for a file called ``<PackageName>Config.cmake`` or -``<lower-case-package-name>-config.cmake`` for each name specified. +``<lowercasePackageName>-config.cmake`` for each name specified. A replacement set of possible configuration file names may be given -using the ``CONFIGS`` option. The search procedure is specified below. -Once found, the configuration file is read and processed by CMake. +using the ``CONFIGS`` option. The :ref:`search procedure` is specified below. +Once found, any :ref:`version constraint <version selection>` is checked, +and if satisfied, the configuration file is read and processed by CMake. Since the file is provided by the package it already knows the location of package contents. The full path to the configuration file is stored in the cmake variable ``<PackageName>_CONFIG``. All configuration files which have been considered by CMake while -searching for an installation of the package with an appropriate -version are stored in the cmake variable ``<PackageName>_CONSIDERED_CONFIGS``, -the associated versions in ``<PackageName>_CONSIDERED_VERSIONS``. +searching for the package with an appropriate version are stored in the +``<PackageName>_CONSIDERED_CONFIGS`` variable, and the associated versions +in the ``<PackageName>_CONSIDERED_VERSIONS`` variable. If the package configuration file cannot be found CMake will generate an error describing the problem unless the ``QUIET`` argument is @@ -166,143 +207,18 @@ fatal error is generated and the configure step stops executing. If configuration file CMake will ignore it and search from scratch. Package maintainers providing CMake package configuration files are -encouraged to name and install them such that the `Search Procedure`_ +encouraged to name and install them such that the :ref:`search procedure` outlined below will find them without requiring use of additional options. -Version Selection -^^^^^^^^^^^^^^^^^ - -When the ``[version]`` argument is given, Config mode will only find a -version of the package that claims compatibility with the requested -version (see :ref:`format specification <FIND_PACKAGE_VERSION_FORMAT>`). If the -``EXACT`` option is given, only a version of the package claiming an exact match -of the requested version may be found. CMake does not establish any -convention for the meaning of version numbers. Package version -numbers are checked by "version" files provided by the packages -themselves. For a candidate package configuration file -``<config-file>.cmake`` the corresponding version file is located next -to it and named either ``<config-file>-version.cmake`` or -``<config-file>Version.cmake``. If no such version file is available -then the configuration file is assumed to not be compatible with any -requested version. A basic version file containing generic version -matching code can be created using the -:module:`CMakePackageConfigHelpers` module. When a version file -is found it is loaded to check the requested version number. The -version file is loaded in a nested scope in which the following -variables have been defined: - -``PACKAGE_FIND_NAME`` - The ``<PackageName>`` -``PACKAGE_FIND_VERSION`` - Full requested version string -``PACKAGE_FIND_VERSION_MAJOR`` - Major version if requested, else 0 -``PACKAGE_FIND_VERSION_MINOR`` - Minor version if requested, else 0 -``PACKAGE_FIND_VERSION_PATCH`` - Patch version if requested, else 0 -``PACKAGE_FIND_VERSION_TWEAK`` - Tweak version if requested, else 0 -``PACKAGE_FIND_VERSION_COUNT`` - Number of version components, 0 to 4 - -When a version range is specified, the above version variables will hold -values based on the lower end of the version range. This is to preserve -compatibility with packages that have not been implemented to expect version -ranges. In addition, the version range will be described by the following -variables: +.. _`search procedure`: -``PACKAGE_FIND_VERSION_RANGE`` - Full requested version range string -``PACKAGE_FIND_VERSION_RANGE_MIN`` - This specifies whether the lower end point of the version range should be - included or excluded. Currently, the only supported value for this variable - is ``INCLUDE``. -``PACKAGE_FIND_VERSION_RANGE_MAX`` - This specifies whether the upper end point of the version range should be - included or excluded. The supported values for this variable are - ``INCLUDE`` and ``EXCLUDE``. +Config Mode Search Procedure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``PACKAGE_FIND_VERSION_MIN`` - Full requested version string of the lower end point of the range -``PACKAGE_FIND_VERSION_MIN_MAJOR`` - Major version of the lower end point if requested, else 0 -``PACKAGE_FIND_VERSION_MIN_MINOR`` - Minor version of the lower end point if requested, else 0 -``PACKAGE_FIND_VERSION_MIN_PATCH`` - Patch version of the lower end point if requested, else 0 -``PACKAGE_FIND_VERSION_MIN_TWEAK`` - Tweak version of the lower end point if requested, else 0 -``PACKAGE_FIND_VERSION_MIN_COUNT`` - Number of version components of the lower end point, 0 to 4 - -``PACKAGE_FIND_VERSION_MAX`` - Full requested version string of the upper end point of the range -``PACKAGE_FIND_VERSION_MAX_MAJOR`` - Major version of the upper end point if requested, else 0 -``PACKAGE_FIND_VERSION_MAX_MINOR`` - Minor version of the upper end point if requested, else 0 -``PACKAGE_FIND_VERSION_MAX_PATCH`` - Patch version of the upper end point if requested, else 0 -``PACKAGE_FIND_VERSION_MAX_TWEAK`` - Tweak version of the upper end point if requested, else 0 -``PACKAGE_FIND_VERSION_MAX_COUNT`` - Number of version components of the upper end point, 0 to 4 - -Regardless of whether a single version or a version range is specified, the -variable ``PACKAGE_FIND_VERSION_COMPLETE`` will be defined and will hold -the full requested version string as specified. - -The version file checks whether it satisfies the requested version and -sets these variables: - -``PACKAGE_VERSION`` - Full provided version string -``PACKAGE_VERSION_EXACT`` - True if version is exact match -``PACKAGE_VERSION_COMPATIBLE`` - True if version is compatible -``PACKAGE_VERSION_UNSUITABLE`` - True if unsuitable as any version - -These variables are checked by the ``find_package`` command to determine -whether the configuration file provides an acceptable version. They -are not available after the ``find_package`` call returns. If the version -is acceptable the following variables are set: - -``<PackageName>_VERSION`` - Full provided version string -``<PackageName>_VERSION_MAJOR`` - Major version if provided, else 0 -``<PackageName>_VERSION_MINOR`` - Minor version if provided, else 0 -``<PackageName>_VERSION_PATCH`` - Patch version if provided, else 0 -``<PackageName>_VERSION_TWEAK`` - Tweak version if provided, else 0 -``<PackageName>_VERSION_COUNT`` - Number of version components, 0 to 4 - -and the corresponding package configuration file is loaded. -When multiple package configuration files are available whose version files -claim compatibility with the version requested it is unspecified which -one is chosen: unless the variable :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` -is set no attempt is made to choose a highest or closest version number. - -To control the order in which ``find_package`` checks for compatibility use -the two variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` and -:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`. -For instance in order to select the highest version one can set - -.. code-block:: cmake - - SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL) - SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) - -before calling ``find_package``. - -Search Procedure -^^^^^^^^^^^^^^^^ +.. note:: + When Config mode is used, this search procedure is applied regardless of + whether the :ref:`full <full signature>` or :ref:`basic <basic signature>` + signature was given. CMake constructs a set of possible installation prefixes for the package. Under each prefix several directories are searched for a @@ -474,6 +390,145 @@ Every non-REQUIRED ``find_package`` call can be disabled or made REQUIRED: Setting both variables to ``TRUE`` simultaneously is an error. +.. _`version selection`: + +Config Mode Version Selection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + When Config mode is used, this version selection process is applied + regardless of whether the :ref:`full <full signature>` or + :ref:`basic <basic signature>` signature was given. + +When the ``[version]`` argument is given, Config mode will only find a +version of the package that claims compatibility with the requested +version (see :ref:`format specification <FIND_PACKAGE_VERSION_FORMAT>`). If the +``EXACT`` option is given, only a version of the package claiming an exact match +of the requested version may be found. CMake does not establish any +convention for the meaning of version numbers. Package version +numbers are checked by "version" files provided by the packages +themselves. For a candidate package configuration file +``<config-file>.cmake`` the corresponding version file is located next +to it and named either ``<config-file>-version.cmake`` or +``<config-file>Version.cmake``. If no such version file is available +then the configuration file is assumed to not be compatible with any +requested version. A basic version file containing generic version +matching code can be created using the +:module:`CMakePackageConfigHelpers` module. When a version file +is found it is loaded to check the requested version number. The +version file is loaded in a nested scope in which the following +variables have been defined: + +``PACKAGE_FIND_NAME`` + The ``<PackageName>`` +``PACKAGE_FIND_VERSION`` + Full requested version string +``PACKAGE_FIND_VERSION_MAJOR`` + Major version if requested, else 0 +``PACKAGE_FIND_VERSION_MINOR`` + Minor version if requested, else 0 +``PACKAGE_FIND_VERSION_PATCH`` + Patch version if requested, else 0 +``PACKAGE_FIND_VERSION_TWEAK`` + Tweak version if requested, else 0 +``PACKAGE_FIND_VERSION_COUNT`` + Number of version components, 0 to 4 + +When a version range is specified, the above version variables will hold +values based on the lower end of the version range. This is to preserve +compatibility with packages that have not been implemented to expect version +ranges. In addition, the version range will be described by the following +variables: + +``PACKAGE_FIND_VERSION_RANGE`` + Full requested version range string +``PACKAGE_FIND_VERSION_RANGE_MIN`` + This specifies whether the lower end point of the version range should be + included or excluded. Currently, the only supported value for this variable + is ``INCLUDE``. +``PACKAGE_FIND_VERSION_RANGE_MAX`` + This specifies whether the upper end point of the version range should be + included or excluded. The supported values for this variable are + ``INCLUDE`` and ``EXCLUDE``. + +``PACKAGE_FIND_VERSION_MIN`` + Full requested version string of the lower end point of the range +``PACKAGE_FIND_VERSION_MIN_MAJOR`` + Major version of the lower end point if requested, else 0 +``PACKAGE_FIND_VERSION_MIN_MINOR`` + Minor version of the lower end point if requested, else 0 +``PACKAGE_FIND_VERSION_MIN_PATCH`` + Patch version of the lower end point if requested, else 0 +``PACKAGE_FIND_VERSION_MIN_TWEAK`` + Tweak version of the lower end point if requested, else 0 +``PACKAGE_FIND_VERSION_MIN_COUNT`` + Number of version components of the lower end point, 0 to 4 + +``PACKAGE_FIND_VERSION_MAX`` + Full requested version string of the upper end point of the range +``PACKAGE_FIND_VERSION_MAX_MAJOR`` + Major version of the upper end point if requested, else 0 +``PACKAGE_FIND_VERSION_MAX_MINOR`` + Minor version of the upper end point if requested, else 0 +``PACKAGE_FIND_VERSION_MAX_PATCH`` + Patch version of the upper end point if requested, else 0 +``PACKAGE_FIND_VERSION_MAX_TWEAK`` + Tweak version of the upper end point if requested, else 0 +``PACKAGE_FIND_VERSION_MAX_COUNT`` + Number of version components of the upper end point, 0 to 4 + +Regardless of whether a single version or a version range is specified, the +variable ``PACKAGE_FIND_VERSION_COMPLETE`` will be defined and will hold +the full requested version string as specified. + +The version file checks whether it satisfies the requested version and +sets these variables: + +``PACKAGE_VERSION`` + Full provided version string +``PACKAGE_VERSION_EXACT`` + True if version is exact match +``PACKAGE_VERSION_COMPATIBLE`` + True if version is compatible +``PACKAGE_VERSION_UNSUITABLE`` + True if unsuitable as any version + +These variables are checked by the ``find_package`` command to determine +whether the configuration file provides an acceptable version. They +are not available after the ``find_package`` call returns. If the version +is acceptable the following variables are set: + +``<PackageName>_VERSION`` + Full provided version string +``<PackageName>_VERSION_MAJOR`` + Major version if provided, else 0 +``<PackageName>_VERSION_MINOR`` + Minor version if provided, else 0 +``<PackageName>_VERSION_PATCH`` + Patch version if provided, else 0 +``<PackageName>_VERSION_TWEAK`` + Tweak version if provided, else 0 +``<PackageName>_VERSION_COUNT`` + Number of version components, 0 to 4 + +and the corresponding package configuration file is loaded. +When multiple package configuration files are available whose version files +claim compatibility with the version requested it is unspecified which +one is chosen: unless the variable :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` +is set no attempt is made to choose a highest or closest version number. + +To control the order in which ``find_package`` checks for compatibility use +the two variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` and +:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`. +For instance in order to select the highest version one can set + +.. code-block:: cmake + + SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL) + SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) + +before calling ``find_package``. + Package File Interface Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b1727b8a7e7e9237bfa1363b088ac17020d629ef Mon Sep 17 00:00:00 2001 From: Felipe Torrezan <felipe.torrezan@iar.com> Date: Tue, 21 Sep 2021 15:21:49 +0200 Subject: [PATCH 1287/1519] IAR: ASM module code deduplication --- Modules/Compiler/IAR-ASM.cmake | 72 ++++++++++++++-------------------- Modules/Compiler/IAR.cmake | 16 -------- 2 files changed, 30 insertions(+), 58 deletions(-) diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake index e3ca16edca9..750ac2f6323 100644 --- a/Modules/Compiler/IAR-ASM.cmake +++ b/Modules/Compiler/IAR-ASM.cmake @@ -1,57 +1,45 @@ -# This file is processed when the IAR compiler is used for an assembler file +# This file is processed when the IAR Assembler is used include(Compiler/IAR) -if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_ilink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_ilink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) +set(_CMAKE_IAR_ITOOLS "ARM" "RH850" "RL78" "RX" "RISC-V" "STM8") +set(_CMAKE_IAR_XTOOLS "AVR" "MSP430" "V850" "8051") -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_ilink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) +set(_CMAKE_IAR_ASM_SILENT "RH850" "RL78" "RX" "RISC-V" "STM8") +if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ASM_SILENT) + set(_CMAKE_IAR_SILENCER_FLAG " --silent") +else() + set(_CMAKE_IAR_SILENCER_FLAG " -S") +endif() -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_ilink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) +string(APPEND CMAKE_ASM_FLAGS_INIT " ") +string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r") +string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG") +string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG") +string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG") + +set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> ${_CMAKE_IAR_SILENCER_FLAG} <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISC-V") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") +if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS) __compiler_iar_ilink(ASM) set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") +elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_XTOOLS) __compiler_iar_xlink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;asm;msa) - -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_xlink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s43;asm;msa) - -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_xlink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s85;asm;msa) - -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_xlink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s51;asm;msa) - -elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8") - set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") - __compiler_iar_ilink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) + # AVR=s90, MSP430=s43, V850=s85, 8051=s51 + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;s43;s85;s51;asm;msa) else() message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.") + endif() + +unset(_CMAKE_IAR_ITOOLS) +unset(_CMAKE_IAR_XTOOLS) +unset(_CMAKE_IAR_ASM_SILENT) +unset(_CMAKE_IAR_SILENCER_FLAG) + +cmake_policy(POP) diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index 2200a21a760..ed03ef73f6f 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -58,14 +58,6 @@ macro(__compiler_iar_ilink lang) string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG") endif() - if (${lang} STREQUAL "ASM") - string(APPEND CMAKE_ASM_FLAGS_INIT " ") - string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r") - string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG") - string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG") - string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG") - endif() - set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>") @@ -91,14 +83,6 @@ macro(__compiler_iar_xlink lang) string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG") endif() - if (${lang} STREQUAL "ASM") - string(APPEND CMAKE_ASM_FLAGS_INIT " ") - string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r") - string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG") - string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG") - string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG") - endif() - set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>") set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>") From a013404f4340358475b8546077fc4195135755e0 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Wed, 22 Sep 2021 22:56:09 -0400 Subject: [PATCH 1288/1519] FindMatlab: Add R2021b => 9.11 version R2021b released 09/22/2021. --- Modules/FindMatlab.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index c8df670b1b6..e7cd834d946 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -261,6 +261,7 @@ if(NOT MATLAB_ADDITIONAL_VERSIONS) endif() set(MATLAB_VERSIONS_MAPPING + "R2021b=9.11" "R2021a=9.10" "R2020b=9.9" "R2020a=9.8" From 956160bb9a50cae8efc0bc256cc4ad3a9330792d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 23 Sep 2021 11:45:35 -0400 Subject: [PATCH 1289/1519] IRSL: Fix search for Windows redist files with Intel Classic compiler The oneAPI icx/ifx compilers are under `.../windows/bin`. The classic icl/ifort compilers are under `.../windows/bin/intel64`. Add paths to the redist directory relative to both locations. Fixes: #22673 --- Modules/InstallRequiredSystemLibraries.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index 4d3bfe2df74..4399a7126d9 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -73,6 +73,8 @@ set(_IRSL_HAVE_MSVC FALSE) foreach(LANG IN ITEMS C CXX Fortran) if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "Intel") if(NOT _IRSL_HAVE_Intel) + # The oneAPI icx/ifx compilers are under ${os}/bin. + # The classic icc/icpc/icl/ifort compilers may be under ${os}/bin/intel64. get_filename_component(_Intel_basedir "${CMAKE_${LANG}_COMPILER}" PATH) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_Intel_archdir intel64) @@ -83,6 +85,8 @@ foreach(LANG IN ITEMS C CXX Fortran) if(WIN32) set(_Intel_possible_redistdirs "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler" + "${_Intel_basedir}/../redist/${_Intel_archdir}/compiler" + "${_Intel_basedir}/../../redist/${_Intel_archdir}_win/compiler" "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" ) elseif(APPLE) From a9073db736f6388f10f914c7361cc374f7522073 Mon Sep 17 00:00:00 2001 From: Felipe Torrezan <felipe.torrezan@iar.com> Date: Thu, 23 Sep 2021 20:11:16 +0200 Subject: [PATCH 1290/1519] IAR: update language specification detection --- Modules/Compiler/IAR-C.cmake | 42 ++++++------- Modules/Compiler/IAR-CXX.cmake | 62 ++++++++++---------- Modules/Compiler/IAR-DetermineCompiler.cmake | 42 +++++++------ Modules/Compiler/IAR.cmake | 40 ++----------- 4 files changed, 76 insertions(+), 110 deletions(-) diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index 7b2e5569512..9629279c431 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -1,10 +1,16 @@ -# This file is processed when the IAR compiler is used for a C file - +# This file is processed when the IAR C Compiler is used +# +# C Language Specification support +# - Newer versions of the IAR C Compiler require the --c89 flag to build a file under the C90 standard. +# - Earlier versions of the compiler had C90 by default, not requiring the backward-compatibility flag. +# +# The IAR Language Extensions +# - The IAR Language Extensions can be enabled by -e flag +# include(Compiler/IAR) include(Compiler/CMakeCommonCompilerMacros) -# Common -if(NOT CMAKE_C_COMPILER_VERSION) +if(NOT DEFINED CMAKE_C_COMPILER_VERSION) message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION not detected. This should be automatic.") endif() @@ -13,46 +19,42 @@ set(CMAKE_C_EXTENSION_COMPILE_OPTION -e) if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_GREATER 7) set(CMAKE_C90_STANDARD_COMPILE_OPTION --c89) set(CMAKE_C90_EXTENSION_COMPILE_OPTION --c89 -e) - set(CMAKE_C99_STANDARD_COMPILE_OPTION "") - set(CMAKE_C99_EXTENSION_COMPILE_OPTION -e) else() set(CMAKE_C90_STANDARD_COMPILE_OPTION "") set(CMAKE_C90_EXTENSION_COMPILE_OPTION -e) endif() -if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_GREATER 8) - set(CMAKE_C11_STANDARD_COMPILE_OPTION "") - set(CMAKE_C11_EXTENSION_COMPILE_OPTION -e) -endif() +set(CMAKE_C${CMAKE_C_STANDARD_COMPUTED_DEFAULT}_STANDARD_COMPILE_OPTION "") +set(CMAKE_C${CMAKE_C_STANDARD_COMPUTED_DEFAULT}_EXTENSION_COMPILE_OPTION -e) # Architecture specific if("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") - if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_LESS 7) - # IAR ARM 4.X uses xlink.exe, detection is not implemented - message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") + if (CMAKE_C_COMPILER_VERSION VERSION_LESS 5) + # IAR C Compiler for Arm prior version 5.xx uses XLINK. Support in CMake is not implemented. + message(FATAL_ERROR "IAR C Compiler for Arm version ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") endif() __compiler_iar_ilink(C) - __compiler_check_default_language_standard(C 1.10 90 6.10 99 8.10 11) + __compiler_check_default_language_standard(C 5.10 90 6.10 99 8.10 11 8.40 17) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX") __compiler_iar_ilink(C) - __compiler_check_default_language_standard(C 1.10 90 2.10 99 4.10 11) + __compiler_check_default_language_standard(C 1.10 90 2.10 99 4.10 11 4.20 17) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850") __compiler_iar_ilink(C) - __compiler_check_default_language_standard(C 1.10 90 1.10 99 2.10 11) + __compiler_check_default_language_standard(C 1.10 90 1.10 99 2.10 11 2.21 17) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78") if(CMAKE_C_COMPILER_VERSION VERSION_LESS 2) - # IAR RL78 1.X uses xlink.exe, detection is not implemented - message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") + # IAR C Compiler for RL78 prior version 2.xx uses XLINK. Support in CMake is not implemented. + message(FATAL_ERROR "IAR C Compiler for RL78 version ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") endif() __compiler_iar_ilink(C) - __compiler_check_default_language_standard(C 2.10 90 1.10 99 4.10 11) + __compiler_check_default_language_standard(C 2.10 90 2.10 99 4.10 11 4.20 17) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV") __compiler_iar_ilink(C) - __compiler_check_default_language_standard(C 1.10 90 1.10 99 1.10 11) + __compiler_check_default_language_standard(C 1.10 90 1.10 99 1.10 11 1.21 17) elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") __compiler_iar_xlink(C) diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index 4909cc51540..b102aa6dfd9 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -1,67 +1,65 @@ -# This file is processed when the IAR compiler is used for a C++ file - +# This file is processed when the IAR C++ Compiler is used +# +# C++ Language Specification support +# - Newer versions of the IAR C++ Compiler require the --c++ flag to build a C++ file. +# Earlier versions for non-ARM architectures provided Embedded C++, enabled with the --eec++ flag. +# +# The IAR Language Extensions +# - The IAR Language Extensions can be enabled by -e flag +# include(Compiler/IAR) include(Compiler/CMakeCommonCompilerMacros) -# Common -if(NOT CMAKE_CXX_COMPILER_VERSION) +if(NOT DEFINED CMAKE_CXX_COMPILER_VERSION) message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION not detected. This should be automatic.") endif() +# Whenever needed, override this default behavior using CMAKE_IAR_CXX_FLAG in your toolchain file. if(NOT CMAKE_IAR_CXX_FLAG) - # The --c++ flag was introduced in platform version 9 for all architectures except ARM where it was introduced already in version 7 - if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 8 OR - (CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 6 AND "${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") ) - set(CMAKE_IAR_CXX_FLAG --c++) + set(_CMAKE_IAR_MODERNCXX_LIST 14 17) + if(${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} IN_LIST _CMAKE_IAR_MODERNCXX_LIST OR + ("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM" AND ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} EQUAL 98)) + string(PREPEND CMAKE_CXX_FLAGS "--c++ ") else() - set(CMAKE_IAR_CXX_FLAG --eec++) + string(PREPEND CMAKE_CXX_FLAGS "--eec++ ") endif() + unset(_CMAKE_IAR_MODERNCXX_LIST) endif() +set(CMAKE_CXX_STANDARD_COMPILE_OPTION "") set(CMAKE_CXX_EXTENSION_COMPILE_OPTION -e) -if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 7) - set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -e) - set(CMAKE_CXX03_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX03_EXTENSION_COMPILE_OPTION -e) -endif() - -if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 8) - set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -e) - set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION -e) -endif() +set(CMAKE_CXX${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}_STANDARD_COMPILE_OPTION "") +set(CMAKE_CXX${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}_EXTENSION_COMPILE_OPTION -e) # Architecture specific if("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") - if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_LESS 7) - # IAR ARM 4.X uses xlink.exe, detection is not implemented - message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5) + # IAR C++ Compiler for Arm prior version 5.xx uses XLINK. Support in CMake is not implemented. + message(FATAL_ERROR "IAR C++ Compiler for Arm version ${CMAKE_CXX_COMPILER_VERSION} not supported by CMake.") endif() __compiler_iar_ilink(CXX) - __compiler_check_default_language_standard(CXX 6.10 98 8.10 14) + __compiler_check_default_language_standard(CXX 5.10 98 8.10 14 8.40 17) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX") __compiler_iar_ilink(CXX) - __compiler_check_default_language_standard(CXX 2.10 98 4.10 14) + __compiler_check_default_language_standard(CXX 2.10 98 4.10 14 4.20 17) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850") __compiler_iar_ilink(CXX) - __compiler_check_default_language_standard(CXX 1.10 98 2.10 14) + __compiler_check_default_language_standard(CXX 1.10 98 2.10 14 2.21 17) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2) - # IAR RL78 1.X uses xlink.exe, detection is not implemented - message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.") + # # IAR C++ Compiler for RL78 prior version 2.xx uses XLINK. Support in CMake is not implemented. + message(FATAL_ERROR "IAR C++ Compiler for RL78 version ${CMAKE_CXX_COMPILER_VERSION} not supported by CMake.") endif() __compiler_iar_ilink(CXX) - __compiler_check_default_language_standard(CXX 2.10 98 4.10 14) + __compiler_check_default_language_standard(CXX 2.10 98 4.10 14 4.20 17) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV") __compiler_iar_ilink(CXX) - __compiler_check_default_language_standard(CXX 1.10 98 1.10 14) + __compiler_check_default_language_standard(CXX 1.10 98 1.10 14 1.21 17) elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR") __compiler_iar_xlink(CXX) diff --git a/Modules/Compiler/IAR-DetermineCompiler.cmake b/Modules/Compiler/IAR-DetermineCompiler.cmake index 443b09c3229..b03fd1faae8 100644 --- a/Modules/Compiler/IAR-DetermineCompiler.cmake +++ b/Modules/Compiler/IAR-DetermineCompiler.cmake @@ -1,28 +1,26 @@ -# IAR Systems compiler for ARM embedded systems. -# http://www.iar.com -# http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf +# IAR C/C++ Compiler (https://www.iar.com) +# CPU <arch> supported in CMake: 8051, Arm, AVR, MSP430, RH850, RISC-V, RL78, RX and V850 # -# __IAR_SYSTEMS_ICC__ An integer that identifies the IAR compiler platform: -# 9 and higher means C11 and C++14 as language default -# 8 means C99 and C++03 as language default -# 7 and lower means C89 and EC++ as language default. -# __ICCARM__ An integer that is set to 1 when the code is compiled with the IAR C/C++ Compiler for ARM -# __VER__ An integer that identifies the version number of the IAR compiler in use. For example, -# version 5.11.3 is returned as 5011003. +# IAR C/C++ Compiler for <arch> internal integer symbols used in CMake: # -# IAR Systems Compiler for AVR embedded systems -# http://supp.iar.com/FilesPublic/UPDINFO/007051/ew/doc/EWAVR_CompilerReference.pdf +# __IAR_SYSTEMS_ICC__ +# Provides the compiler internal platform version +# __ICC<arch>__ +# Provides 1 for the current <arch> in use +# __VER__ +# Provides the current version in use +# The semantic version of the compiler is architecture-dependent +# When <arch> is ARM: +# CMAKE_<LANG>_COMPILER_VERSION_MAJOR = (__VER__ / 1E6) +# CMAKE_<LANG>_COMPILER_VERSION_MINOR = (__VER__ / 1E3) % 1E3 +# CMAKE_<LANG>_COMPILER_VERSION_PATCH = (__VER__ % 1E3) +# When <arch> is non-ARM: +# CMAKE_<LANG>_COMPILER_VERSION_MAJOR = (__VER__ / 1E2) +# CMAKE_<LANG>_COMPILER_VERSION_MINOR = (__VER__ - ((__VER__/ 1E2) * 1E2)) +# CMAKE_<LANG>_COMPILER_VERSION_PATCH = (__SUBVERSION__) +# __SUBVERSION__ +# Provides the version's patch level for non-ARM <arch> # -# __IAR_SYSTEMS_ICC__ An integer that identifies the IAR compiler platform. -# __ICCAVR__ An integer that is set to 1 when the code is compiled with the IAR C/C++ Compiler for AVR -# __VER__ An integer that identifies the version number of the IAR compiler in use. -# The value is calculated by (100 * VERSION_MAJOR + VERSION_MINOR). For example the version -# 3.34 is given as 334 -# __SUBVERSION__ An integer that identifies the subversion number of the compiler version number -# for example 3 in 1.2.3.4. THis is used as the patch version, as seen when running iccavr -# from the command line -# - set(_compiler_id_pp_test "defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)") set(_compiler_id_version_compute " diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake index 9382c3fc678..53456f5c37b 100644 --- a/Modules/Compiler/IAR.cmake +++ b/Modules/Compiler/IAR.cmake @@ -1,43 +1,11 @@ -# This file is processed when the IAR compiler is used for a C or C++ file -# Documentation can be downloaded here: http://www.iar.com/website1/1.0.1.0/675/1/ -# The initial feature request is here: https://gitlab.kitware.com/cmake/cmake/-/issues/10176 -# It also contains additional links and information. -# See USER GUIDES -> C/C++ Development Guide and ReleaseNotes for EWARM: -# version 6.30.8: http://supp.iar.com/FilesPublic/UPDINFO/006607/arm/doc/infocenter/index.ENU.html -# version 7.60.1: http://supp.iar.com/FilesPublic/UPDINFO/011006/arm/doc/infocenter/index.ENU.html -# version 8.10.1: http://netstorage.iar.com/SuppDB/Public/UPDINFO/011854/arm/doc/infocenter/index.ENU.html - -# The IAR internal compiler platform generations (Predefined symbol __IAR_SYSTEMS_ICC__): -# 9 and higher means C11 and C++14 as language default (EWARM v8.x, EWRX v4.x and higher) -# 8 means C99 and C++03 as language default (EWARM v6.x, v7.x. EWRX v2.x, 3.x) -# 7 and lower means C89 and EC++ as language default. (EWARM v5.x and lower) - -# C/C++ Standard versions -# -# IAR typically only supports one C and C++ Standard version, -# the exception is C89 which is always supported and can be selected -# if its not the default +# This file is processed when the IAR C/C++ Compiler is used # -# C++ is trickier, there were historically 3 switches, -# and some IAR versions support multiple of those. -# they are --eec++, --ec++ and --c++ and where used to -# enable various language features like exceptions +# CPU <arch> supported in CMake: 8051, Arm, AVR, MSP430, RH850, RISC-V, RL78, RX and V850 # -# recent versions only have --c++ for full support -# but can choose to disable features with further arguments +# The compiler user documentation is architecture-dependent +# and it can found with the product installation under <arch>/doc/{EW,BX}<arch>_DevelopmentGuide.ENU.pdf # -# C/C++ Standard compliance # -# IAR has 3 modes: default, strict and extended -# the extended mode is needed for popular libraries like CMSIS -# -# "Silent" Operation -# -# this really is different to most programs I know. -# nothing meaningful from the operation is lost, just some redundant -# code and data size printouts (that can be inspected with common tools). - -# This module is shared by multiple languages; use include blocker. include_guard() macro(__compiler_iar_ilink lang) From d2541062bd8708e88e99db57b00ab80193374193 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 24 Sep 2021 00:01:17 -0400 Subject: [PATCH 1291/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e8a633edfa6..4d845d14074 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210923) +set(CMake_VERSION_PATCH 20210924) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 68e0f72744320e9ffb3ae3c39b648386dc0296ad Mon Sep 17 00:00:00 2001 From: Joseph Snyder <joe.snyder@kitware.com> Date: Fri, 24 Sep 2021 08:59:23 -0400 Subject: [PATCH 1292/1519] Tutorial: Describe placement of add_subdirectory Clarify that the process of making a target optional in the second step of the tutorial is further steps to the work done before, not a separate addition to the file. Do this by ensuring that the paragraph which describes the work done mentions the placement and use of the previous command. This is done to avoid duplication of the add_subdirectory call. CMake Issue: #22663 --- Help/guide/tutorial/Adding a Library.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index 180636141f6..ed034489c54 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -64,8 +64,13 @@ will be stored in the cache so that the user does not need to set the value each time they run CMake on a build directory. The next change is to make building and linking the ``MathFunctions`` library -conditional. To do this we change the end of the top-level ``CMakeLists.txt`` -file to look like the following: +conditional. To do this, we will create an ``if`` statement which checks the +value of the option. Inside the ``if`` block, put the +:command:`add_subdirectory` command from above with some additional list +commands to store information needed to link to the library and add the +subdirectory as an include directory in the ``Tutorial`` target. +The end of the top-level ``CMakeLists.txt`` file will now look like the +following: .. literalinclude:: Step3/CMakeLists.txt :caption: CMakeLists.txt From 71ea2d607d0294f44f03e2a8e34cbb6222edc3a4 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 24 Sep 2021 10:03:35 -0400 Subject: [PATCH 1293/1519] curl: Update script to get curl 7.79.1 --- Utilities/Scripts/update-curl.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash index abd54f6f72d..dd8e7a8e098 100755 --- a/Utilities/Scripts/update-curl.bash +++ b/Utilities/Scripts/update-curl.bash @@ -8,7 +8,7 @@ readonly name="curl" readonly ownership="Curl Upstream <curl-library@cool.haxx.se>" readonly subtree="Utilities/cmcurl" readonly repo="https://github.com/curl/curl.git" -readonly tag="curl-7_79_0" +readonly tag="curl-7_79_1" readonly shortlog=false readonly paths=" CMake/* From c4f76b28dcabdf9513a244eb1ce7d1431ae4d84d Mon Sep 17 00:00:00 2001 From: Curl Upstream <curl-library@cool.haxx.se> Date: Wed, 22 Sep 2021 08:10:23 +0200 Subject: [PATCH 1294/1519] curl 2021-09-22 (c7aef0a9) Code extracted from: https://github.com/curl/curl.git at commit c7aef0a945f9b6fb6d3f91716a21dfe2f4ea635f (curl-7_79_1). --- include/curl/curlver.h | 6 +++--- lib/hsts.c | 42 ++++++++++++++++++++++++++---------------- lib/hsts.h | 2 +- lib/http.c | 10 +++++----- lib/http2.c | 12 ++++++------ lib/multi.c | 10 ++++++++-- lib/select.h | 24 +++++++++++++----------- lib/strerror.c | 4 ++-- lib/transfer.c | 2 +- 9 files changed, 65 insertions(+), 47 deletions(-) diff --git a/include/curl/curlver.h b/include/curl/curlver.h index 3e2de3e925d..393ba122162 100644 --- a/include/curl/curlver.h +++ b/include/curl/curlver.h @@ -30,13 +30,13 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.79.0-DEV" +#define LIBCURL_VERSION "7.79.1-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 #define LIBCURL_VERSION_MINOR 79 -#define LIBCURL_VERSION_PATCH 0 +#define LIBCURL_VERSION_PATCH 1 /* This is the numeric version of the libcurl version number, meant for easier parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will @@ -57,7 +57,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 0x074f00 +#define LIBCURL_VERSION_NUM 0x074f01 /* * This is the date and time when the full source package was created. The diff --git a/lib/hsts.c b/lib/hsts.c index 853c7dfea5a..052dc115718 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -49,6 +49,7 @@ #define MAX_HSTS_HOSTLENSTR "256" #define MAX_HSTS_DATELEN 64 #define MAX_HSTS_DATELENSTR "64" +#define UNLIMITED "unlimited" #ifdef DEBUGBUILD /* to play well with debug builds, we can *set* a fixed time this will @@ -283,13 +284,17 @@ static CURLcode hsts_push(struct Curl_easy *data, e.namelen = strlen(sts->host); e.includeSubDomains = sts->includeSubDomains; - result = Curl_gmtime((time_t)sts->expires, &stamp); - if(result) - return result; + if(sts->expires != TIME_T_MAX) { + result = Curl_gmtime((time_t)sts->expires, &stamp); + if(result) + return result; - msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d", - stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, - stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d", + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + } + else + strcpy(e.expire, UNLIMITED); sc = data->set.hsts_write(data, &e, i, data->set.hsts_write_userp); @@ -303,14 +308,18 @@ static CURLcode hsts_push(struct Curl_easy *data, static CURLcode hsts_out(struct stsentry *sts, FILE *fp) { struct tm stamp; - CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); - if(result) - return result; - - fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n", - sts->includeSubDomains ? ".": "", sts->host, - stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, - stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + if(sts->expires != TIME_T_MAX) { + CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); + if(result) + return result; + fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n", + sts->includeSubDomains ? ".": "", sts->host, + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec); + } + else + fprintf(fp, "%s%s \"%s\"\n", + sts->includeSubDomains ? ".": "", sts->host, UNLIMITED); return CURLE_OK; } @@ -403,7 +412,8 @@ static CURLcode hsts_add(struct hsts *h, char *line) "%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"", host, date); if(2 == rc) { - time_t expires = Curl_getdate_capped(date); + time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) : + TIME_T_MAX; CURLcode result; char *p = host; bool subdomain = FALSE; @@ -456,7 +466,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) return result; } else if(sc == CURLSTS_FAIL) - return CURLE_BAD_FUNCTION_ARGUMENT; + return CURLE_ABORTED_BY_CALLBACK; } while(sc == CURLSTS_OK); } return CURLE_OK; diff --git a/lib/hsts.h b/lib/hsts.h index baa582864a2..653c05348d8 100644 --- a/lib/hsts.h +++ b/lib/hsts.h @@ -59,7 +59,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h); #else #define Curl_hsts_cleanup(x) -#define Curl_hsts_loadcb(x,y) +#define Curl_hsts_loadcb(x,y) CURLE_OK #define Curl_hsts_save(x,y,z) #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ #endif /* HEADER_CURL_HSTS_H */ diff --git a/lib/http.c b/lib/http.c index d5c36dd54a0..648583c56ab 100644 --- a/lib/http.c +++ b/lib/http.c @@ -4232,9 +4232,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, char separator; char twoorthree[2]; int httpversion = 0; - int digit4 = -1; /* should remain untouched to be good */ + char digit4 = 0; nc = sscanf(HEADER1, - " HTTP/%1d.%1d%c%3d%1d", + " HTTP/%1d.%1d%c%3d%c", &httpversion_major, &httpversion, &separator, @@ -4250,13 +4250,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* There can only be a 4th response code digit stored in 'digit4' if all the other fields were parsed and stored first, so nc is 5 when - digit4 is not -1 */ - else if(digit4 != -1) { + digit4 a digit */ + else if(ISDIGIT(digit4)) { failf(data, "Unsupported response code in HTTP response"); return CURLE_UNSUPPORTED_PROTOCOL; } - if((nc == 4) && (' ' == separator)) { + if((nc >= 4) && (' ' == separator)) { httpversion += 10 * httpversion_major; switch(httpversion) { case 10: diff --git a/lib/http2.c b/lib/http2.c index a3de607c7d2..6d63f43636a 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -2221,12 +2221,6 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, stream->mem = data->state.buffer; stream->len = data->set.buffer_size; - httpc->inbuflen = 0; - httpc->nread_inbuf = 0; - - httpc->pause_stream_id = 0; - httpc->drain_total = 0; - multi_connchanged(data->multi); /* below this point only connection related inits are done, which only needs to be done once per connection */ @@ -2252,6 +2246,12 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, conn->httpversion = 20; conn->bundle->multiuse = BUNDLE_MULTIPLEX; + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + + httpc->pause_stream_id = 0; + httpc->drain_total = 0; + infof(data, "Connection state changed (HTTP/2 confirmed)"); return CURLE_OK; diff --git a/lib/multi.c b/lib/multi.c index 85097816db5..518ceb51f57 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1052,11 +1052,17 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) { curl_socket_t s = CURL_SOCKET_BAD; - if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) { + if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) { + if(!FDSET_SOCK(sockbunch[i])) + /* pretend it doesn't exist */ + continue; FD_SET(sockbunch[i], read_fd_set); s = sockbunch[i]; } - if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) { + if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) { + if(!FDSET_SOCK(sockbunch[i])) + /* pretend it doesn't exist */ + continue; FD_SET(sockbunch[i], write_fd_set); s = sockbunch[i]; } diff --git a/lib/select.h b/lib/select.h index 19da1e774be..59a571dbbd9 100644 --- a/lib/select.h +++ b/lib/select.h @@ -97,8 +97,10 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, #if defined(TPF) #define VALID_SOCK(x) 1 #define VERIFY_SOCK(x) Curl_nop_stmt +#define FDSET_SOCK(x) 1 #elif defined(USE_WINSOCK) #define VALID_SOCK(s) ((s) < INVALID_SOCKET) +#define FDSET_SOCK(x) 1 #define VERIFY_SOCK(x) do { \ if(!VALID_SOCK(x)) { \ SET_SOCKERRNO(WSAEINVAL); \ @@ -106,17 +108,17 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, } \ } while(0) #else -#ifdef HAVE_POLL_FINE -#define VALID_SOCK(s) ((s) >= 0) /* FD_SETSIZE is irrelevant for poll */ -#else -#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) -#endif -#define VERIFY_SOCK(x) do { \ - if(!VALID_SOCK(x)) { \ - SET_SOCKERRNO(EINVAL); \ - return -1; \ - } \ -} while(0) +#define VALID_SOCK(s) ((s) >= 0) + +/* If the socket is small enough to get set or read from an fdset */ +#define FDSET_SOCK(s) ((s) < FD_SETSIZE) + +#define VERIFY_SOCK(x) do { \ + if(!VALID_SOCK(x) || !FDSET_SOCK(x)) { \ + SET_SOCKERRNO(EINVAL); \ + return -1; \ + } \ + } while(0) #endif #endif /* HEADER_CURL_SELECT_H */ diff --git a/lib/strerror.c b/lib/strerror.c index 431ff1c2fb0..8a271976512 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -731,12 +731,11 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) max = buflen - 1; *buf = '\0'; - /* !checksrc! disable STRERROR 2 */ #if defined(WIN32) || defined(_WIN32_WCE) #if defined(WIN32) /* 'sys_nerr' is the maximum errno number, it is not widely portable */ if(err >= 0 && err < sys_nerr) - strncpy(buf, strerror(err), max); + strncpy(buf, sys_errlist[err], max); else #endif { @@ -787,6 +786,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) } #else { + /* !checksrc! disable STRERROR 1 */ const char *msg = strerror(err); if(msg) strncpy(buf, msg, max); diff --git a/lib/transfer.c b/lib/transfer.c index 3e650b5b9e5..05fec7998ce 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -1503,7 +1503,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) } #endif Curl_http2_init_state(&data->state); - Curl_hsts_loadcb(data, data->hsts); + result = Curl_hsts_loadcb(data, data->hsts); } /* From 354c1f5628bdc104c9b9cd0436dd4cfa585124ec Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Thu, 23 Sep 2021 17:05:03 -0400 Subject: [PATCH 1295/1519] Tests/RunCMake/Autogen: test CMP0111 behavior On Windows, imported shared libraries which only have an `IMPORTED_IMPLIB` set fail if they are depended upon by a target using automoc. Add a test for the behavior of depending upon all imported target types from an automoc-using target. --- .../CMP0111-imported-target-full.cmake | 12 +++++++ .../CMP0111-imported-target-implib-only.cmake | 13 ++++++++ .../CMP0111-imported-target-libname.cmake | 14 ++++++++ .../CMP0111-imported-target-prelude.cmake | 32 +++++++++++++++++++ Tests/RunCMake/Autogen/RunCMakeTest.cmake | 4 +++ 5 files changed, 75 insertions(+) create mode 100644 Tests/RunCMake/Autogen/CMP0111-imported-target-full.cmake create mode 100644 Tests/RunCMake/Autogen/CMP0111-imported-target-implib-only.cmake create mode 100644 Tests/RunCMake/Autogen/CMP0111-imported-target-libname.cmake create mode 100644 Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake diff --git a/Tests/RunCMake/Autogen/CMP0111-imported-target-full.cmake b/Tests/RunCMake/Autogen/CMP0111-imported-target-full.cmake new file mode 100644 index 00000000000..331da64537f --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0111-imported-target-full.cmake @@ -0,0 +1,12 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0111-imported-target-prelude.cmake") + +set_location(executable LOCATION "${CMAKE_CURRENT_BINARY_DIR}/executable${CMAKE_EXECUTABLE_SUFFIX}") + +set_location(shared LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}shared${CMAKE_SHARED_LIBRARY_SUFFIX}") +if (CMAKE_IMPORT_LIBRARY_SUFFIX) + set_location(shared IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}shared${CMAKE_IMPORT_LIBRARY_SUFFIX}") +endif () + +set_location(static LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}static${CMAKE_STATIC_LIBRARY_SUFFIX}") +set_location(unknown LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}unknown${CMAKE_IMPORT_LIBRARY_SUFFIX}") +set_location(module LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_MODULE_PREFIX}module${CMAKE_SHARED_MODULE_SUFFIX}") diff --git a/Tests/RunCMake/Autogen/CMP0111-imported-target-implib-only.cmake b/Tests/RunCMake/Autogen/CMP0111-imported-target-implib-only.cmake new file mode 100644 index 00000000000..8640fdc5322 --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0111-imported-target-implib-only.cmake @@ -0,0 +1,13 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0111-imported-target-prelude.cmake") + +set_location(executable LOCATION "${CMAKE_CURRENT_BINARY_DIR}/executable${CMAKE_EXECUTABLE_SUFFIX}") + +if (CMAKE_IMPORT_LIBRARY_SUFFIX) + set_location(shared IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}shared${CMAKE_IMPORT_LIBRARY_SUFFIX}") +else () + set_location(shared LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}shared${CMAKE_SHARED_LIBRARY_SUFFIX}") +endif () + +set_location(static LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}static${CMAKE_STATIC_LIBRARY_SUFFIX}") +set_location(unknown LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unknown${CMAKE_STATIC_LIBRARY_SUFFIX}") +set_location(module LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_MODULE_PREFIX}module${CMAKE_SHARED_MODULE_SUFFIX}") diff --git a/Tests/RunCMake/Autogen/CMP0111-imported-target-libname.cmake b/Tests/RunCMake/Autogen/CMP0111-imported-target-libname.cmake new file mode 100644 index 00000000000..e1318c27e88 --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0111-imported-target-libname.cmake @@ -0,0 +1,14 @@ +include("${CMAKE_CURRENT_LIST_DIR}/CMP0111-imported-target-prelude.cmake") + +set_location(executable LOCATION "${CMAKE_CURRENT_BINARY_DIR}/executable${CMAKE_EXECUTABLE_SUFFIX}") + +set_location(shared LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}shared${CMAKE_SHARED_LIBRARY_SUFFIX}") +if (CMAKE_IMPORT_LIBRARY_SUFFIX) + set_location(shared IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}shared${CMAKE_IMPORT_LIBRARY_SUFFIX}") +endif () + +set_location(static LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}static${CMAKE_IMPORT_LIBRARY_SUFFIX}") +set_location(unknown LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}unknown${CMAKE_IMPORT_LIBRARY_SUFFIX}") +set_location(module LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_MODULE_PREFIX}module${CMAKE_SHARED_MODULE_SUFFIX}") + +set_location(interface LIBNAME "interface") diff --git a/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake b/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake new file mode 100644 index 00000000000..8fa6041b969 --- /dev/null +++ b/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake @@ -0,0 +1,32 @@ +enable_language(CXX) + +find_package(Qt5 REQUIRED COMPONENTS Core) + +# Detect `-NOTFOUND` libraries at generate time. +cmake_policy(SET CMP0111 NEW) + +add_executable(imported::executable IMPORTED) +add_library(imported::shared SHARED IMPORTED) +add_library(imported::static STATIC IMPORTED) +add_library(imported::unknown UNKNOWN IMPORTED) +add_library(imported::interface INTERFACE IMPORTED) +add_library(imported::module MODULE IMPORTED) + +function (set_location target name loc) + set_property(TARGET "imported::${target}" PROPERTY + "IMPORTED_${name}" "${loc}") +endfunction () + +set(CMAKE_AUTOMOC 1) + +add_library(automoc + empty.cpp) +target_link_libraries(automoc + PRIVATE + imported::shared + imported::static + imported::unknown + imported::interface) +add_dependencies(automoc + imported::executable + imported::module) diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake index a31b67cd7d4..bbcbd5ed8f9 100644 --- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake +++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake @@ -5,4 +5,8 @@ if (with_qt5) run_cmake(QtInFunction) run_cmake(QtInFunctionNested) run_cmake(QtInFunctionProperty) + + run_cmake(CMP0111-imported-target-full) + run_cmake(CMP0111-imported-target-libname) + run_cmake(CMP0111-imported-target-implib-only) endif () From 895fa3433f50b7011fa475a4696dc06fe072aa25 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Thu, 23 Sep 2021 17:05:22 -0400 Subject: [PATCH 1296/1519] cmQtAutoGenInitializer: support IMPLIB-only imported targets Instead of using the target name directly (which ends up in the `Ninja` generators querying for the `LOCATION` parameter), wrap up the target name in a `$<TARGET_LINKER_FILE:>` to avoid the query for the unset property. --- Source/cmQtAutoGenInitializer.cxx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 4dd78e514f5..4e3c5842173 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1306,7 +1306,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Add additional autogen target dependencies to // '_autogen_timestamp_deps'. for (const cmTarget* t : this->AutogenTarget.DependTargets) { - dependencies.push_back(t->GetName()); + std::string depname = t->GetName(); + if (t->IsImported()) { + auto ttype = t->GetType(); + if (ttype == cmStateEnums::TargetType::STATIC_LIBRARY || + ttype == cmStateEnums::TargetType::SHARED_LIBRARY || + ttype == cmStateEnums::TargetType::UNKNOWN_LIBRARY) { + depname = cmStrCat("$<TARGET_LINKER_FILE:", t->GetName(), ">"); + } + } + dependencies.push_back(depname); } cmTarget* timestampTarget = this->LocalGen->AddUtilityCommand( From c42a5a6d931a1f5e6e3924b889fae8798941c84e Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 25 Sep 2021 00:01:17 -0400 Subject: [PATCH 1297/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4d845d14074..2ad27f63a41 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210924) +set(CMake_VERSION_PATCH 20210925) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 1edc9e88879d00e7015ce2ab2c6e663ae59a37fe Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 26 Sep 2021 00:01:28 -0400 Subject: [PATCH 1298/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2ad27f63a41..2eb2b122196 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210925) +set(CMake_VERSION_PATCH 20210926) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From b0c2aeaab457a43f8dc4cc89ec9c80f2c49a3929 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 27 Sep 2021 00:01:25 -0400 Subject: [PATCH 1299/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2eb2b122196..89de6918d98 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210926) +set(CMake_VERSION_PATCH 20210927) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From f55a02a26e203f09282e1e7e693b6b5afeca966c Mon Sep 17 00:00:00 2001 From: Joseph Snyder <joe.snyder@kitware.com> Date: Mon, 27 Sep 2021 10:11:17 -0400 Subject: [PATCH 1300/1519] Tutorial: Enhance CTestConfig info in Step 8 Add a copy of the CTestConfig.cmake from Step 9 into the directory for Step 8. Expand the information about the contents of the CTestConfig file and write a brief explanation of where on CDash to acquire the CTestConfig file for a specific project. CMake Issue: #22663 --- ...Adding Support for a Testing Dashboard.rst | 20 ++++++++++++++++--- Help/guide/tutorial/Step8/CTestConfig.cmake | 7 +++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 Help/guide/tutorial/Step8/CTestConfig.cmake diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index 26aae4f8111..c6e0fd0b3b4 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -28,9 +28,23 @@ With: The :module:`CTest` module will automatically call ``enable_testing()``, so we can remove it from our CMake files. -We will also need to create a ``CTestConfig.cmake`` file in the top-level -directory where we can specify the name of the project and where to submit the -dashboard. +We will also need to acquire a ``CTestConfig.cmake`` file to be placed in the +top-level directory where we can specify information to CTest about the +project. It contains: + +* The project name + +* The project "Nightly" start time + + * The time when a 24 hour "day" starts for this project. + +* The URL of the CDash instance where the submission's generated documents + will be sent + +One has been provided for you in this directory. It would normally be +downloaded from the ``Settings`` page of the project on the CDash +instance that will host and display the test results. Once downloaded from +CDash, the file should not be modified locally. .. literalinclude:: Step9/CTestConfig.cmake :caption: CTestConfig.cmake diff --git a/Help/guide/tutorial/Step8/CTestConfig.cmake b/Help/guide/tutorial/Step8/CTestConfig.cmake new file mode 100644 index 00000000000..73efdb1f6e0 --- /dev/null +++ b/Help/guide/tutorial/Step8/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) From 966d9b3967fcb054012f4b97373fa1433837d2d9 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 28 Sep 2021 00:01:17 -0400 Subject: [PATCH 1301/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 89de6918d98..0359ca6a437 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210927) +set(CMake_VERSION_PATCH 20210928) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 907d098838c99ee6c0c72ae0cdf1cc53dbf51ba2 Mon Sep 17 00:00:00 2001 From: Sean McBride <sean@rogue-research.com> Date: Fri, 24 Sep 2021 11:52:11 -0400 Subject: [PATCH 1302/1519] Source: Fix clang -Wextra-semi warnings --- Source/cmCommand.h | 2 +- Source/cmConditionEvaluator.cxx | 2 +- Source/cmFindLibraryCommand.cxx | 4 ++-- Source/cmGeneratorTarget.h | 2 +- Source/cmLocalUnixMakefileGenerator3.h | 2 +- Source/cmMakefileProfilingData.cxx | 2 +- Source/cmOutputConverter.cxx | 2 +- Source/cmQtAutoGenGlobalInitializer.h | 2 +- Source/cmQtAutoGenInitializer.h | 16 ++++++++++++---- Source/cmQtAutoMocUic.cxx | 4 ++-- Source/cmStringCommand.cxx | 2 +- Source/cmUVHandlePtr.h | 2 +- Source/cmWorkerPool.h | 4 ++-- Tests/CMakeLib/testUVRAII.cxx | 6 +++--- 14 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 68c56d90c2f..f5a5190229a 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -44,7 +44,7 @@ class cmCommand cmMakefile* GetMakefile() { return this->Makefile; } void SetExecutionStatus(cmExecutionStatus* s); - cmExecutionStatus* GetExecutionStatus() { return this->Status; }; + cmExecutionStatus* GetExecutionStatus() { return this->Status; } /** * This is called by the cmMakefile when the command is first diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 913b532e8fa..cbe2a264bad 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -117,7 +117,7 @@ bool looksLikeSpecialVariable(const std::string& var, { \ } #else -# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base; +# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base #endif // BEGIN cmConditionEvaluator::cmArgumentList diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index bfa007cc741..ff04bab061e 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -247,7 +247,7 @@ struct cmFindLibraryHelper cmStrCat(this->PrefixRegexStr, name, this->SuffixRegexStr); this->DebugSearches.FailedAt(path, regexName); } - }; + } void DebugLibraryFound(std::string const& name, std::string const& path) { @@ -256,7 +256,7 @@ struct cmFindLibraryHelper cmStrCat(this->PrefixRegexStr, name, this->SuffixRegexStr); this->DebugSearches.FoundAt(path, regexName); } - }; + } }; namespace { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index e9ce9623de6..9906963073a 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -221,7 +221,7 @@ class cmGeneratorTarget { this->PreviousState = target.SetDeviceLink(true); } - ~DeviceLinkSetter() { this->Target.SetDeviceLink(this->PreviousState); }; + ~DeviceLinkSetter() { this->Target.SetDeviceLink(this->PreviousState); } private: cmGeneratorTarget& Target; diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 14dd0baf454..78aa7f9c2f4 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -299,7 +299,7 @@ class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator cmGeneratorTarget const* target) { return this->CommandsVisited[target]; - }; + } std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>> CommandsVisited; diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx index 86188db4cd5..337f78bf718 100644 --- a/Source/cmMakefileProfilingData.cxx +++ b/Source/cmMakefileProfilingData.cxx @@ -29,7 +29,7 @@ cmMakefileProfilingData::cmMakefileProfilingData( } this->ProfileStream << "["; -}; +} cmMakefileProfilingData::~cmMakefileProfilingData() noexcept { diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index bda2fe5c2a3..2b785e1d3b8 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -19,7 +19,7 @@ bool PathEqOrSubDir(std::string const& a, std::string const& b) { return (cmSystemTools::ComparePath(a, b) || cmSystemTools::IsSubDirectory(a, b)); -}; +} } cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot) diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index afcb4a2a966..3de5c1a850d 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -49,7 +49,7 @@ class cmQtAutoGenGlobalInitializer std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators); ~cmQtAutoGenGlobalInitializer(); - Keywords const& kw() const { return this->Keywords_; }; + Keywords const& kw() const { return this->Keywords_; } bool generate(); diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index e76817b9c43..603c5377739 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -95,7 +95,9 @@ class cmQtAutoGenInitializer : public cmQtAutoGen GenVarsT(GenT gen) : Gen(gen) - , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){}; + , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)) + { + } }; /** @param mocExecutable The file path to the moc executable. Will be used as @@ -209,7 +211,9 @@ class cmQtAutoGenInitializer : public cmQtAutoGen struct MocT : public GenVarsT { MocT() - : GenVarsT(GenT::MOC){}; + : GenVarsT(GenT::MOC) + { + } bool RelaxedMode = false; bool PathPrefix = false; @@ -237,7 +241,9 @@ class cmQtAutoGenInitializer : public cmQtAutoGen using UiFileT = std::pair<std::string, std::vector<std::string>>; UicT() - : GenVarsT(GenT::UIC){}; + : GenVarsT(GenT::UIC) + { + } std::set<std::string> SkipUi; std::vector<std::string> UiFilesNoOptions; @@ -252,7 +258,9 @@ class cmQtAutoGenInitializer : public cmQtAutoGen struct RccT : public GenVarsT { RccT() - : GenVarsT(GenT::RCC){}; + : GenVarsT(GenT::RCC) + { + } bool GlobalTarget = false; std::vector<Qrc> Qrcs; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 2753fd57c02..056056c702a 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -310,7 +310,7 @@ class cmQtAutoMocUicT : public cmQtAutoGenerator cmQtAutoMocUicT* Gen() const { return static_cast<cmQtAutoMocUicT*>(this->UserData()); - }; + } // -- Accessors. Only valid during Process() call! Logger const& Log() const { return this->Gen()->Log(); } @@ -346,7 +346,7 @@ class cmQtAutoMocUicT : public cmQtAutoGenerator : JobT(true) { } - void Process() override{}; + void Process() override {} }; /** Generate moc_predefs.h. */ diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 1cb6193daa5..f44fcf7c680 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -1054,7 +1054,7 @@ Json::Value& ResolvePath(Json::Value& json, Args path) } } return *search; -}; +} Json::Value ReadJson(const std::string& jsonstr) { diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h index 8c5ad598327..027d6905f12 100644 --- a/Source/cmUVHandlePtr.h +++ b/Source/cmUVHandlePtr.h @@ -23,7 +23,7 @@ #else -# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base; +# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base #endif diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h index ff255261d81..40356501632 100644 --- a/Source/cmWorkerPool.h +++ b/Source/cmWorkerPool.h @@ -87,7 +87,7 @@ class cmWorkerPool * Get the user data. * Only valid during the JobT::Process() call! */ - void* UserData() const { return this->Pool_->UserData(); }; + void* UserData() const { return this->Pool_->UserData(); } /** * Get the worker index. @@ -138,7 +138,7 @@ class cmWorkerPool { } //! Does nothing - void Process() override{}; + void Process() override {} }; /** diff --git a/Tests/CMakeLib/testUVRAII.cxx b/Tests/CMakeLib/testUVRAII.cxx index 0607f449fae..7d21959bff5 100644 --- a/Tests/CMakeLib/testUVRAII.cxx +++ b/Tests/CMakeLib/testUVRAII.cxx @@ -169,7 +169,7 @@ static bool testAllMoves() allTypes b(std::move(a)); allTypes c = std::move(b); return true; -}; +} static bool testLoopReset() { @@ -192,7 +192,7 @@ static bool testLoopReset() } return true; -}; +} static bool testLoopDestructor() { @@ -217,7 +217,7 @@ static bool testLoopDestructor() } return true; -}; +} int testUVRAII(int, char** const) { From 403f3430820b2777c137093ce631233e2b554134 Mon Sep 17 00:00:00 2001 From: Daniel Schlegel <ds.work@posteo.me> Date: Tue, 28 Sep 2021 05:00:06 -0400 Subject: [PATCH 1303/1519] GetPrerequisites: Support CMAKE_OBJDUMP with .exe extension When running `fixup_bundle` in a MSYS environment it fails because `gp_tool` resolves to `objdump.exe` and not just `objdump`. Fixes: #22381 --- Modules/GetPrerequisites.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index e90a9b5b7bc..53584c639a3 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -746,7 +746,7 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa set(gp_regex_error "") set(gp_regex_fallback "") set(gp_regex_cmp_count 1) - elseif(gp_tool MATCHES "objdump$") + elseif(gp_tool MATCHES "objdump(\\.exe)?$") set(gp_cmd_args "-p") set(gp_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$") set(gp_regex_error "") From 9b94f95bed62cfcef7061ce94052ff246a673a95 Mon Sep 17 00:00:00 2001 From: Wirtos_new <Wirtos.new@gmail.com> Date: Tue, 28 Sep 2021 15:34:29 +0300 Subject: [PATCH 1304/1519] ASM_NASM: Pass preprocessor definitions to assembler Add the `<DEFINES>` placeholder to `CMAKE_ASM_NASM_COMPILE_OBJECT`. Fixes: #22694 --- Modules/CMakeASM_NASMInformation.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeASM_NASMInformation.cmake b/Modules/CMakeASM_NASMInformation.cmake index dad2750e800..a72575b4aaf 100644 --- a/Modules/CMakeASM_NASMInformation.cmake +++ b/Modules/CMakeASM_NASMInformation.cmake @@ -35,7 +35,7 @@ if(NOT CMAKE_ASM_NASM_OBJECT_FORMAT) endif() if(NOT CMAKE_ASM_NASM_COMPILE_OBJECT) - set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>") + set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>") endif() if(CMAKE_ASM_NASM_COMPILER_ID STREQUAL "NASM") From b8a2ce048416c5a4582a4956a7f9039423d72c44 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 28 Sep 2021 10:42:48 -0400 Subject: [PATCH 1305/1519] cmGlobalXCodeGenerator: Remove dead buildsystem version check In commit 8d5f4c4db9 (Xcode: Switch to the "new build system" for Xcode 12 and above, 2020-09-14, v3.19.0-rc1~143^2~7) we accidentally added code in an `else` block that under the opposite condition by which the block can be entered. Remove it. Fixes: #22681 --- Source/cmGlobalXCodeGenerator.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index c3d60b01a22..1aaeabb3b90 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1756,9 +1756,6 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( if (sourceFile->GetCustomCommand() && visited.insert(sourceFile).second) { commands.push_back(*sourceFile->GetCustomCommand()); - if (this->XcodeBuildSystem >= BuildSystem::Twelve) { - this->CustomCommandRoots[sourceFile].insert(gtgt); - } } } // create custom commands phase From 16ea0e57f7ff51ef1d1b64eb270a7762e0c67726 Mon Sep 17 00:00:00 2001 From: Jake Turner <jake@evansturner.co.uk> Date: Sun, 26 Sep 2021 11:38:02 +0100 Subject: [PATCH 1306/1519] Xcode: Treat .inl files as C++ header files Generate the `explicitFileType` as `sourcecode.cpp.h` instead of just `sourcecode`. This enables syntax highlighting in Xcode. --- Source/cmGlobalXCodeGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index c3d60b01a22..d61d373fb62 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1097,7 +1097,7 @@ std::string GetSourcecodeValueFromFileExtension( } else if (ext == "h") { sourcecode += ".c.h"; } else if (ext == "hxx" || ext == "hpp" || ext == "txx" || ext == "pch" || - ext == "hh") { + ext == "hh" || ext == "inl") { sourcecode += ".cpp.h"; } else if (ext == "png" || ext == "gif" || ext == "jpg") { keepLastKnownFileType = true; From 37859e32442bb433af9876963c92594d05fb64b3 Mon Sep 17 00:00:00 2001 From: Sean McBride <sean@rogue-research.com> Date: Fri, 24 Sep 2021 11:56:57 -0400 Subject: [PATCH 1307/1519] Source: Fix clang -Wimplicit-fallthrough warnings --- Source/cmCTest.cxx | 2 +- Source/cmComputeLinkInformation.cxx | 6 +++++- Source/cmComputeTargetDepends.cxx | 2 ++ Source/cmConditionEvaluator.cxx | 1 + Source/cmCoreTryCompile.cxx | 3 +++ Source/cmExportCommand.cxx | 1 + Source/cmExtraCodeBlocksGenerator.cxx | 4 ++-- Source/cmExtraCodeLiteGenerator.cxx | 9 +++++---- Source/cmFileCommand.cxx | 3 ++- Source/cmGeneratorTarget.cxx | 6 ++++++ Source/cmGetTargetPropertyCommand.cxx | 2 ++ Source/cmGlobalGenerator.cxx | 2 ++ Source/cmGlobalNinjaGenerator.cxx | 4 ++-- Source/cmIncludeCommand.cxx | 1 + Source/cmInstallCommand.cxx | 2 ++ Source/cmInstallSubdirectoryGenerator.cxx | 1 + Source/cmLinkDirectoriesCommand.cxx | 2 +- Source/cmListCommand.cxx | 2 +- Source/cmLocalGenerator.cxx | 5 +++-- Source/cmLocalNinjaGenerator.cxx | 3 ++- Source/cmMakefile.cxx | 15 +++++++++++---- Source/cmMakefileTargetGenerator.cxx | 1 + Source/cmOptionCommand.cxx | 2 +- Source/cmState.cxx | 2 +- Source/cmTarget.cxx | 2 ++ Source/cmTargetLinkLibrariesCommand.cxx | 4 ++++ Source/cmTargetPropertyComputer.cxx | 2 ++ 27 files changed, 67 insertions(+), 22 deletions(-) diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index bc6abb5f7f2..dfd2b6c345d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2425,7 +2425,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum:: Extra: this->Impl->ExtraVerbose = true; - // intentional fallthrough + CM_FALLTHROUGH; case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum:: Verbose: this->Impl->Verbose = true; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index a3e346c00e8..831a81fd2bc 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1185,6 +1185,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) this->CMP0060WarnItems.insert(item); } } + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_ALWAYS: @@ -1454,8 +1455,10 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, this->Target->GetBacktrace()); } } - case cmPolicies::OLD: + CM_FALLTHROUGH; + case cmPolicies::OLD: // NOLINT(bugprone-branch-clone) // OLD behavior does not warn. + break; case cmPolicies::NEW: // NEW behavior will not get here. break; @@ -1494,6 +1497,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->Target->GetBacktrace()); } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to add the paths containing libraries with // known full paths as link directories. diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 2f296108391..ef89c8b5c67 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -359,6 +359,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n"; issueMessage = true; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::NEW: @@ -366,6 +367,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; messageType = MessageType::FATAL_ERROR; + break; } if (issueMessage) { cmake* cm = this->GlobalGenerator->GetCMakeInstance(); diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index cbe2a264bad..8e479c5451d 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -447,6 +447,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( "\" appears in a conditional statement. " + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012); status = MessageType::FATAL_ERROR; + break; } case cmPolicies::NEW: break; diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 02d559be509..971c86e5988 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -626,6 +626,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, /* clang-format on */ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to do nothing. break; @@ -663,6 +664,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, /* clang-format on */ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to do nothing. break; @@ -878,6 +880,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->Makefile->IssueMessage( MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067)); + break; case cmPolicies::NEW: // NEW behavior is to honor the language standard variables. // We already initialized honorStandard to true. diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 352eaf2911d..63440a317f0 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -282,6 +282,7 @@ static bool HandlePackage(std::vector<std::string> const& args, // CMP0090 decides both the default and what variable changes it. switch (mf.GetPolicyStatus(cmPolicies::CMP0090)) { case cmPolicies::WARN: + CM_FALLTHROUGH; case cmPolicies::OLD: // Default is to export, but can be disabled. if (mf.IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) { diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 9ad8876fc87..e2c54d77e94 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -396,8 +396,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( CbpUnit& cbpUnit = allFiles[fullPath]; cbpUnit.Targets.push_back(target.get()); } - } - default: // intended fallthrough + } break; + default: break; } } diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 549b08b4efc..9e8ac5cf0ef 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -208,7 +208,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( case cmStateEnums::MODULE_LIBRARY: { projectType = "Dynamic Library"; } break; - default: // intended fallthrough + default: break; } @@ -233,8 +233,8 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( otherFiles.insert(fullPath); } } - } - default: // intended fallthrough + } break; + default: break; } return projectType; @@ -556,7 +556,8 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile( case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: visualname = "lib" + targetName; - default: // intended fallthrough + break; + default: break; } xml.Attribute("Name", visualname); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 4eb632d0419..d2341c5bcdc 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -640,8 +640,9 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, case cmPolicies::NEW: g.RecurseThroughSymlinksOff(); break; - case cmPolicies::OLD: case cmPolicies::WARN: + CM_FALLTHROUGH; + case cmPolicies::OLD: g.RecurseThroughSymlinksOn(); break; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ef1f8716fcc..8033ef54432 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1137,6 +1137,7 @@ bool cmGeneratorTarget::IsInBuildSystem() const if (!this->SourceEntries.empty()) { return true; } + break; case cmStateEnums::UNKNOWN_LIBRARY: break; } @@ -2558,6 +2559,7 @@ class cmTargetCollectLinkLanguages } break; case cmPolicies::OLD: noMessage = true; + break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: @@ -3267,6 +3269,7 @@ void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags, switch (this->GetPolicyStatusCMP0119()) { case cmPolicies::WARN: + CM_FALLTHROUGH; case cmPolicies::OLD: // The OLD behavior is to not add explicit language flags. return; @@ -3565,6 +3568,7 @@ void processIncludeDirectories(cmGeneratorTarget const* tgt, } break; case cmPolicies::OLD: noMessage = true; + break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: @@ -7433,6 +7437,7 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const cm->IssueMessage(MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace()); } + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::NEW: { @@ -7670,6 +7675,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } break; case cmPolicies::OLD: noMessage = true; + break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 9c5a2fc36ad..12c82216b88 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -62,6 +62,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, case cmPolicies::WARN: issueMessage = true; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0045) << "\n"; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: @@ -69,6 +70,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args, case cmPolicies::NEW: issueMessage = true; messageType = MessageType::FATAL_ERROR; + break; } if (issueMessage) { e << "get_target_property() called with non-existent target \"" diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 981308eb64d..6dabf63744f 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -965,6 +965,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( mf->IssueMessage( MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025)); + break; case cmPolicies::NEW: // NEW behavior is to keep AppleClang. break; @@ -1031,6 +1032,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( mf->IssueMessage( MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0089)); + break; case cmPolicies::NEW: // NEW behavior is to keep AppleClang. break; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 5c3198e7302..3f6f55ee9c6 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1263,7 +1263,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( break; } } - // FALLTHROUGH + CM_FALLTHROUGH; case cmStateEnums::EXECUTABLE: { outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath( config, cmStateEnums::RuntimeBinaryArtifact, realname))); @@ -1275,7 +1275,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( break; } } - // FALLTHROUGH + CM_FALLTHROUGH; case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: { diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index ce1f030be32..7b0320c1f13 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -120,6 +120,7 @@ bool cmIncludeCommand(std::vector<std::string> const& args, case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n"; modal = "should"; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index ee77b2c2d3a..eaf88f64a0a 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1391,6 +1391,7 @@ bool HandleFilesMode(std::vector<std::string> const& args, case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n"; modal = "should"; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: @@ -1398,6 +1399,7 @@ bool HandleFilesMode(std::vector<std::string> const& args, case cmPolicies::NEW: modal = "may"; messageType = MessageType::FATAL_ERROR; + break; } if (modal) { e << "The file\n " << file diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx index 794694ea31a..0a8e065b505 100644 --- a/Source/cmInstallSubdirectoryGenerator.cxx +++ b/Source/cmInstallSubdirectoryGenerator.cxx @@ -57,6 +57,7 @@ void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os) this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082); switch (status) { case cmPolicies::WARN: + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is handled in cmLocalGenerator::GenerateInstallRules() break; diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 29140462a9c..1ec071b7579 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -62,7 +62,7 @@ static void AddLinkDir(cmMakefile& mf, std::string const& dir, case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015); mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); - break; + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior does not convert break; diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index a1aaee34406..7d42fc8276f 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -46,7 +46,7 @@ bool GetIndexArg(const std::string& arg, int* idx, cmMakefile& mf) cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121), " Invalid list index \"", arg, "\"."); mf.IssueMessage(MessageType::AUTHOR_WARNING, warn); - break; + CM_FALLTHROUGH; } case cmPolicies::OLD: // OLD behavior is to allow compatibility, so just ignore the diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 966cf285d1e..9b6b9abe1da 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3780,8 +3780,9 @@ bool cmLocalGenerator::NeedBackwardsCompatibility_2_4() // variable. switch (this->GetPolicyStatus(cmPolicies::CMP0001)) { case cmPolicies::WARN: - // WARN is just OLD without warning because user code does not - // always affect whether this check is done. + // WARN is just OLD without warning because user code does not + // always affect whether this check is done. + CM_FALLTHROUGH; case cmPolicies::OLD: // Old behavior is to check the variable. break; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index a43faa711b8..d337d3ead15 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -796,8 +796,9 @@ cmLocalNinjaGenerator::MakeCustomCommandGenerators( bool transformDepfile = false; switch (cc.GetCMP0116Status()) { - case cmPolicies::OLD: case cmPolicies::WARN: + CM_FALLTHROUGH; + case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 17445340af7..a490dacc6c0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -818,6 +818,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const // version. this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, msg.str(), this->Backtrace); + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to use policy version 2.4 set in // cmListFileCache. @@ -829,7 +830,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, msg.str(), this->Backtrace); cmSystemTools::SetFatalErrorOccured(); - return; + break; } } } @@ -1001,6 +1002,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget( case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0040) << "\n"; issueMessage = true; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::NEW: @@ -1008,6 +1010,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget( case cmPolicies::REQUIRED_ALWAYS: issueMessage = true; messageType = MessageType::FATAL_ERROR; + break; } if (issueMessage) { @@ -1751,6 +1754,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014); /* clang-format on */ this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior does not warn. break; @@ -1761,6 +1765,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) case cmPolicies::NEW: // NEW behavior prints the error. this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + break; } return; } @@ -2781,6 +2786,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld( case cmPolicies::REQUIRED_ALWAYS: error << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0010); + break; case cmPolicies::NEW: // NEW behavior is to report the error. break; @@ -3078,8 +3084,8 @@ MessageType cmMakefile::ExpandVariablesInStringNew( break; } } - // Failed to find a valid @ expansion; treat it as literal. - /* FALLTHROUGH */ + // Failed to find a valid @ expansion; treat it as literal. + CM_FALLTHROUGH; default: { if (!openstack.empty() && !(isalnum(inc) || inc == '_' || inc == '/' || inc == '.' || @@ -4505,7 +4511,8 @@ bool cmMakefile::IgnoreErrorsCMP0061() const bool ignoreErrors = true; switch (this->GetPolicyStatus(cmPolicies::CMP0061)) { case cmPolicies::WARN: - // No warning for this policy! + // No warning for this policy! + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 0cbc741b58d..8edadd31e7c 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -63,6 +63,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) } switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) { case cmPolicies::WARN: + CM_FALLTHROUGH; case cmPolicies::OLD: this->CMP0113New = false; break; diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 2c4a77475c8..ec54fc59028 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -34,7 +34,7 @@ bool cmOptionCommand(std::vector<std::string> const& args, switch (policyStatus) { case cmPolicies::WARN: checkAndWarn = (existsBeforeSet != nullptr); - break; + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior does not warn. break; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 7fbc8f879b9..e79949d97c8 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -453,7 +453,7 @@ void cmState::AddDisallowedCommand(std::string const& name, case cmPolicies::WARN: mf.IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(policy)); - break; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 08734b417f6..97d60cf0305 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -113,12 +113,14 @@ cmValue cmTargetPropertyComputer::GetSources<cmTarget>( case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n"; noMessage = false; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: addContent = true; + break; } if (!noMessage) { e << "Target \"" << tgt->GetName() diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index d39824b9bef..e15c9418ac1 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -143,6 +143,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n"; modal = "should"; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_ALWAYS: @@ -150,6 +151,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, case cmPolicies::NEW: modal = "must"; messageType = MessageType::FATAL_ERROR; + break; } if (modal) { e << "Utility target \"" << target->GetName() << "\" " << modal @@ -395,6 +397,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState, case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; modal = "should"; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_ALWAYS: @@ -402,6 +405,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState, case cmPolicies::NEW: modal = "must"; messageType = MessageType::FATAL_ERROR; + break; } if (modal) { diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index b9c93659fba..9b941427734 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -21,6 +21,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n"; modal = "should"; + CM_FALLTHROUGH; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_ALWAYS: @@ -28,6 +29,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( case cmPolicies::NEW: modal = "may"; messageType = MessageType::FATAL_ERROR; + break; } if (modal) { From 3feff8379b05332035319de4f733549695fcc6de Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sat, 28 Aug 2021 18:00:28 +0300 Subject: [PATCH 1308/1519] Help: Generic language standard and extension variables documentation Add generic documentation to improve the discoverability of language-specific ones and to make it possible to refer to them generically from other language generic documentation. --- Help/manual/cmake-properties.7.rst | 3 +++ Help/manual/cmake-variables.7.rst | 3 +++ Help/prop_tgt/LANG_EXTENSIONS.rst | 23 ++++++++++++++++ Help/prop_tgt/LANG_STANDARD.rst | 26 +++++++++++++++++++ Help/prop_tgt/LANG_STANDARD_REQUIRED.rst | 26 +++++++++++++++++++ Help/variable/CMAKE_LANG_EXTENSIONS.rst | 19 ++++++++++++++ Help/variable/CMAKE_LANG_STANDARD.rst | 19 ++++++++++++++ .../variable/CMAKE_LANG_STANDARD_REQUIRED.rst | 19 ++++++++++++++ 8 files changed, 138 insertions(+) create mode 100644 Help/prop_tgt/LANG_EXTENSIONS.rst create mode 100644 Help/prop_tgt/LANG_STANDARD.rst create mode 100644 Help/prop_tgt/LANG_STANDARD_REQUIRED.rst create mode 100644 Help/variable/CMAKE_LANG_EXTENSIONS.rst create mode 100644 Help/variable/CMAKE_LANG_STANDARD.rst create mode 100644 Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index c71e8ffdfbe..d04a8647f00 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -274,8 +274,11 @@ Properties on Targets /prop_tgt/LANG_COMPILER_LAUNCHER /prop_tgt/LANG_CPPCHECK /prop_tgt/LANG_CPPLINT + /prop_tgt/LANG_EXTENSIONS /prop_tgt/LANG_INCLUDE_WHAT_YOU_USE /prop_tgt/LANG_LINKER_LAUNCHER + /prop_tgt/LANG_STANDARD + /prop_tgt/LANG_STANDARD_REQUIRED /prop_tgt/LANG_VISIBILITY_PRESET /prop_tgt/LIBRARY_OUTPUT_DIRECTORY /prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 7cfa0c8f083..bab53f0bb62 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -549,6 +549,7 @@ Variables for Languages /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY /variable/CMAKE_LANG_CREATE_SHARED_MODULE /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY + /variable/CMAKE_LANG_EXTENSIONS /variable/CMAKE_LANG_FLAGS /variable/CMAKE_LANG_FLAGS_CONFIG /variable/CMAKE_LANG_FLAGS_CONFIG_INIT @@ -577,8 +578,10 @@ Variables for Languages /variable/CMAKE_LANG_SIMULATE_VERSION /variable/CMAKE_LANG_SIZEOF_DATA_PTR /variable/CMAKE_LANG_SOURCE_FILE_EXTENSIONS + /variable/CMAKE_LANG_STANDARD /variable/CMAKE_LANG_STANDARD_INCLUDE_DIRECTORIES /variable/CMAKE_LANG_STANDARD_LIBRARIES + /variable/CMAKE_LANG_STANDARD_REQUIRED /variable/CMAKE_OBJC_EXTENSIONS /variable/CMAKE_OBJC_STANDARD /variable/CMAKE_OBJC_STANDARD_REQUIRED diff --git a/Help/prop_tgt/LANG_EXTENSIONS.rst b/Help/prop_tgt/LANG_EXTENSIONS.rst new file mode 100644 index 00000000000..2add21db58b --- /dev/null +++ b/Help/prop_tgt/LANG_EXTENSIONS.rst @@ -0,0 +1,23 @@ +<LANG>_EXTENSIONS +----------------- + +The variations are: + +* :prop_tgt:`C_EXTENSIONS` +* :prop_tgt:`CXX_EXTENSIONS` +* :prop_tgt:`CUDA_EXTENSIONS` +* :prop_tgt:`HIP_EXTENSIONS` +* :prop_tgt:`OBJC_EXTENSIONS` +* :prop_tgt:`OBJCXX_EXTENSIONS` + +These properties specify whether compiler-specific extensions are requested. + +These properties are initialized by the value of the +:variable:`CMAKE_<LANG>_EXTENSIONS` variable if it is set when a target is +created. + +For supported CMake versions see the respective pages. +To control language standard versions see :prop_tgt:`<LANG>_STANDARD`. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/prop_tgt/LANG_STANDARD.rst b/Help/prop_tgt/LANG_STANDARD.rst new file mode 100644 index 00000000000..bd377eccd64 --- /dev/null +++ b/Help/prop_tgt/LANG_STANDARD.rst @@ -0,0 +1,26 @@ +<LANG>_STANDARD +--------------- + +The variations are: + +* :prop_tgt:`C_STANDARD` +* :prop_tgt:`CXX_STANDARD` +* :prop_tgt:`CUDA_STANDARD` +* :prop_tgt:`HIP_STANDARD` +* :prop_tgt:`OBJC_STANDARD` +* :prop_tgt:`OBJCXX_STANDARD` + +These properties specify language standard versions which are requested. When a +newer standard is specified than is supported by the compiler, then it will +fallback to the latest supported standard. This "decay" behavior may be +controlled with the :prop_tgt:`<LANG>_STANDARD_REQUIRED` target property. + +These properties are initialized by the value of the +:variable:`CMAKE_<LANG>_STANDARD` variable if it is set when a target is +created. + +For supported values and CMake versions see the respective pages. +To control compiler-specific extensions see :prop_tgt:`<LANG>_EXTENSIONS`. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/prop_tgt/LANG_STANDARD_REQUIRED.rst b/Help/prop_tgt/LANG_STANDARD_REQUIRED.rst new file mode 100644 index 00000000000..56ecef85f52 --- /dev/null +++ b/Help/prop_tgt/LANG_STANDARD_REQUIRED.rst @@ -0,0 +1,26 @@ +<LANG>_STANDARD_REQUIRED +------------------------ + +The variations are: + +* :prop_tgt:`C_STANDARD_REQUIRED` +* :prop_tgt:`CXX_STANDARD_REQUIRED` +* :prop_tgt:`CUDA_STANDARD_REQUIRED` +* :prop_tgt:`HIP_STANDARD_REQUIRED` +* :prop_tgt:`OBJC_STANDARD_REQUIRED` +* :prop_tgt:`OBJCXX_STANDARD_REQUIRED` + +These properties specify whether the value of :prop_tgt:`<LANG>_STANDARD` is a +requirement. When ``OFF`` or unset, the :prop_tgt:`<LANG>_STANDARD` target +property is treated as optional and may "decay" to a previous standard if the +requested is not available. + +These properties are initialized by the value of the +:variable:`CMAKE_<LANG>_STANDARD_REQUIRED` variable if it is set when a target +is created. + +For supported CMake versions see the respective pages. +To control language standard versions see :prop_tgt:`<LANG>_STANDARD`. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_LANG_EXTENSIONS.rst b/Help/variable/CMAKE_LANG_EXTENSIONS.rst new file mode 100644 index 00000000000..84e5e3ad1b8 --- /dev/null +++ b/Help/variable/CMAKE_LANG_EXTENSIONS.rst @@ -0,0 +1,19 @@ +CMAKE_<LANG>_EXTENSIONS +----------------------- + +The variations are: + +* :variable:`CMAKE_C_EXTENSIONS` +* :variable:`CMAKE_CXX_EXTENSIONS` +* :variable:`CMAKE_CUDA_EXTENSIONS` +* :variable:`CMAKE_HIP_EXTENSIONS` +* :variable:`CMAKE_OBJC_EXTENSIONS` +* :variable:`CMAKE_OBJCXX_EXTENSIONS` + +Default values for :prop_tgt:`<LANG>_EXTENSIONS` target properties if set when +a target is created. + +For supported CMake versions see the respective pages. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_LANG_STANDARD.rst b/Help/variable/CMAKE_LANG_STANDARD.rst new file mode 100644 index 00000000000..0c41e196817 --- /dev/null +++ b/Help/variable/CMAKE_LANG_STANDARD.rst @@ -0,0 +1,19 @@ +CMAKE_<LANG>_STANDARD +--------------------- + +The variations are: + +* :variable:`CMAKE_C_STANDARD` +* :variable:`CMAKE_CXX_STANDARD` +* :variable:`CMAKE_CUDA_STANDARD` +* :variable:`CMAKE_HIP_STANDARD` +* :variable:`CMAKE_OBJC_STANDARD` +* :variable:`CMAKE_OBJCXX_STANDARD` + +Default values for :prop_tgt:`<LANG>_STANDARD` target properties if set when a +target is created. + +For supported CMake versions see the respective pages. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst new file mode 100644 index 00000000000..d7fa9b69b5d --- /dev/null +++ b/Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst @@ -0,0 +1,19 @@ +CMAKE_<LANG>_STANDARD_REQUIRED +------------------------------ + +The variations are: + +* :variable:`CMAKE_C_STANDARD_REQUIRED` +* :variable:`CMAKE_CXX_STANDARD_REQUIRED` +* :variable:`CMAKE_CUDA_STANDARD_REQUIRED` +* :variable:`CMAKE_HIP_STANDARD_REQUIRED` +* :variable:`CMAKE_OBJC_STANDARD_REQUIRED` +* :variable:`CMAKE_OBJCXX_STANDARD_REQUIRED` + +Default values for :prop_tgt:`<LANG>_STANDARD_REQUIRED` target properties if +set when a target is created. + +For supported CMake versions see the respective pages. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. From a40ff1bb5a8243b8ad749c3010d90e934c3a700f Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sat, 28 Aug 2021 18:27:37 +0300 Subject: [PATCH 1309/1519] Help: Make language standard/extensions variable pages less wordy They all had two sentences describing the same thing. Furthermore, with the shorter wording the explicit advice to see the property being initialized for further information seems unnecessary. --- Help/variable/CMAKE_CUDA_EXTENSIONS.rst | 7 ++----- Help/variable/CMAKE_CUDA_STANDARD.rst | 7 ++----- Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst | 7 ++----- Help/variable/CMAKE_CXX_EXTENSIONS.rst | 7 ++----- Help/variable/CMAKE_CXX_STANDARD.rst | 7 ++----- Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst | 7 ++----- Help/variable/CMAKE_C_EXTENSIONS.rst | 7 ++----- Help/variable/CMAKE_C_STANDARD.rst | 7 ++----- Help/variable/CMAKE_C_STANDARD_REQUIRED.rst | 7 ++----- Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst | 7 ++----- Help/variable/CMAKE_OBJCXX_STANDARD.rst | 7 ++----- Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst | 7 ++----- Help/variable/CMAKE_OBJC_EXTENSIONS.rst | 7 ++----- Help/variable/CMAKE_OBJC_STANDARD.rst | 7 ++----- Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst | 7 ++----- 15 files changed, 30 insertions(+), 75 deletions(-) diff --git a/Help/variable/CMAKE_CUDA_EXTENSIONS.rst b/Help/variable/CMAKE_CUDA_EXTENSIONS.rst index b86c0ea39cd..12749ce5975 100644 --- a/Help/variable/CMAKE_CUDA_EXTENSIONS.rst +++ b/Help/variable/CMAKE_CUDA_EXTENSIONS.rst @@ -3,11 +3,8 @@ CMAKE_CUDA_EXTENSIONS .. versionadded:: 3.8 -Default value for :prop_tgt:`CUDA_EXTENSIONS` property of targets. - -This variable is used to initialize the :prop_tgt:`CUDA_EXTENSIONS` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`CUDA_EXTENSIONS` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_CUDA_STANDARD.rst b/Help/variable/CMAKE_CUDA_STANDARD.rst index 798ab1e7442..ee9395aef4e 100644 --- a/Help/variable/CMAKE_CUDA_STANDARD.rst +++ b/Help/variable/CMAKE_CUDA_STANDARD.rst @@ -3,11 +3,8 @@ CMAKE_CUDA_STANDARD .. versionadded:: 3.8 -Default value for :prop_tgt:`CUDA_STANDARD` property of targets. - -This variable is used to initialize the :prop_tgt:`CUDA_STANDARD` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`CUDA_STANDARD` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst index ae2f52f8bcf..0c85a04d7cc 100644 --- a/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst +++ b/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst @@ -3,11 +3,8 @@ CMAKE_CUDA_STANDARD_REQUIRED .. versionadded:: 3.8 -Default value for :prop_tgt:`CUDA_STANDARD_REQUIRED` property of targets. - -This variable is used to initialize the :prop_tgt:`CUDA_STANDARD_REQUIRED` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`CUDA_STANDARD_REQUIRED` target property if set +when a target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_CXX_EXTENSIONS.rst b/Help/variable/CMAKE_CXX_EXTENSIONS.rst index ea8c4be7051..017f503aec2 100644 --- a/Help/variable/CMAKE_CXX_EXTENSIONS.rst +++ b/Help/variable/CMAKE_CXX_EXTENSIONS.rst @@ -3,11 +3,8 @@ CMAKE_CXX_EXTENSIONS .. versionadded:: 3.1 -Default value for :prop_tgt:`CXX_EXTENSIONS` property of targets. - -This variable is used to initialize the :prop_tgt:`CXX_EXTENSIONS` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`CXX_EXTENSIONS` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_CXX_STANDARD.rst b/Help/variable/CMAKE_CXX_STANDARD.rst index 8ef8c80e31e..33eb89e035e 100644 --- a/Help/variable/CMAKE_CXX_STANDARD.rst +++ b/Help/variable/CMAKE_CXX_STANDARD.rst @@ -3,11 +3,8 @@ CMAKE_CXX_STANDARD .. versionadded:: 3.1 -Default value for :prop_tgt:`CXX_STANDARD` property of targets. - -This variable is used to initialize the :prop_tgt:`CXX_STANDARD` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`CXX_STANDARD` target property if set when a target +is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst index f7b2ae92ea2..1c6c0cc9684 100644 --- a/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst +++ b/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst @@ -3,11 +3,8 @@ CMAKE_CXX_STANDARD_REQUIRED .. versionadded:: 3.1 -Default value for :prop_tgt:`CXX_STANDARD_REQUIRED` property of targets. - -This variable is used to initialize the :prop_tgt:`CXX_STANDARD_REQUIRED` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`CXX_STANDARD_REQUIRED` target property if set when +a target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_C_EXTENSIONS.rst b/Help/variable/CMAKE_C_EXTENSIONS.rst index fce8fc72204..66805211194 100644 --- a/Help/variable/CMAKE_C_EXTENSIONS.rst +++ b/Help/variable/CMAKE_C_EXTENSIONS.rst @@ -3,11 +3,8 @@ CMAKE_C_EXTENSIONS .. versionadded:: 3.1 -Default value for :prop_tgt:`C_EXTENSIONS` property of targets. - -This variable is used to initialize the :prop_tgt:`C_EXTENSIONS` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`C_EXTENSIONS` target property if set when a target +is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_C_STANDARD.rst b/Help/variable/CMAKE_C_STANDARD.rst index 64ef8ce2966..ec1e5131e79 100644 --- a/Help/variable/CMAKE_C_STANDARD.rst +++ b/Help/variable/CMAKE_C_STANDARD.rst @@ -3,11 +3,8 @@ CMAKE_C_STANDARD .. versionadded:: 3.1 -Default value for :prop_tgt:`C_STANDARD` property of targets. - -This variable is used to initialize the :prop_tgt:`C_STANDARD` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`C_STANDARD` target property if set when a target +is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst index e70b6bd26a8..2bd9d51b5bb 100644 --- a/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst +++ b/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst @@ -3,11 +3,8 @@ CMAKE_C_STANDARD_REQUIRED .. versionadded:: 3.1 -Default value for :prop_tgt:`C_STANDARD_REQUIRED` property of targets. - -This variable is used to initialize the :prop_tgt:`C_STANDARD_REQUIRED` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`C_STANDARD_REQUIRED` target property if set when +a target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst b/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst index b5225ea68fb..46736aa7d4f 100644 --- a/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst +++ b/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst @@ -3,11 +3,8 @@ CMAKE_OBJCXX_EXTENSIONS .. versionadded:: 3.16 -Default value for :prop_tgt:`OBJCXX_EXTENSIONS` property of targets. - -This variable is used to initialize the :prop_tgt:`OBJCXX_EXTENSIONS` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`OBJCXX_EXTENSIONS` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_OBJCXX_STANDARD.rst b/Help/variable/CMAKE_OBJCXX_STANDARD.rst index 98e462414fa..0913382a4b9 100644 --- a/Help/variable/CMAKE_OBJCXX_STANDARD.rst +++ b/Help/variable/CMAKE_OBJCXX_STANDARD.rst @@ -3,11 +3,8 @@ CMAKE_OBJCXX_STANDARD .. versionadded:: 3.16 -Default value for :prop_tgt:`OBJCXX_STANDARD` property of targets. - -This variable is used to initialize the :prop_tgt:`OBJCXX_STANDARD` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`OBJCXX_STANDARD` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst index 4b5e77cf052..9afc4eab486 100644 --- a/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst +++ b/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst @@ -3,11 +3,8 @@ CMAKE_OBJCXX_STANDARD_REQUIRED .. versionadded:: 3.16 -Default value for :prop_tgt:`OBJCXX_STANDARD_REQUIRED` property of targets. - -This variable is used to initialize the :prop_tgt:`OBJCXX_STANDARD_REQUIRED` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`OBJCXX_STANDARD_REQUIRED` target property if set +when a target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_OBJC_EXTENSIONS.rst b/Help/variable/CMAKE_OBJC_EXTENSIONS.rst index d6e3c7dc0dc..9df11f1c8d0 100644 --- a/Help/variable/CMAKE_OBJC_EXTENSIONS.rst +++ b/Help/variable/CMAKE_OBJC_EXTENSIONS.rst @@ -3,11 +3,8 @@ CMAKE_OBJC_EXTENSIONS .. versionadded:: 3.16 -Default value for :prop_tgt:`OBJC_EXTENSIONS` property of targets. - -This variable is used to initialize the :prop_tgt:`OBJC_EXTENSIONS` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`OBJC_EXTENSIONS` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_OBJC_STANDARD.rst b/Help/variable/CMAKE_OBJC_STANDARD.rst index fde367dfd26..0b9b63ff260 100644 --- a/Help/variable/CMAKE_OBJC_STANDARD.rst +++ b/Help/variable/CMAKE_OBJC_STANDARD.rst @@ -3,11 +3,8 @@ CMAKE_OBJC_STANDARD .. versionadded:: 3.16 -Default value for :prop_tgt:`OBJC_STANDARD` property of targets. - -This variable is used to initialize the :prop_tgt:`OBJC_STANDARD` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`OBJC_STANDARD` target property if set when a +target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst index 8d26d952a3f..c74db55c154 100644 --- a/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst +++ b/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst @@ -3,11 +3,8 @@ CMAKE_OBJC_STANDARD_REQUIRED .. versionadded:: 3.16 -Default value for :prop_tgt:`OBJC_STANDARD_REQUIRED` property of targets. - -This variable is used to initialize the :prop_tgt:`OBJC_STANDARD_REQUIRED` -property on all targets. See that target property for additional -information. +Default value for :prop_tgt:`OBJC_STANDARD_REQUIRED` target property if set +when a target is created. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. From a65bee4cfc80972d58510c4a71d753d4f085c584 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sat, 28 Aug 2021 18:12:18 +0300 Subject: [PATCH 1310/1519] Help: Document HIP standard/extensions properties and variables --- Help/manual/cmake-properties.7.rst | 3 ++ Help/manual/cmake-variables.7.rst | 3 ++ Help/prop_tgt/HIP_EXTENSIONS.rst | 19 ++++++++ Help/prop_tgt/HIP_STANDARD.rst | 48 +++++++++++++++++++ Help/prop_tgt/HIP_STANDARD_REQUIRED.rst | 19 ++++++++ Help/variable/CMAKE_HIP_EXTENSIONS.rst | 10 ++++ Help/variable/CMAKE_HIP_STANDARD.rst | 10 ++++ Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst | 10 ++++ 8 files changed, 122 insertions(+) create mode 100644 Help/prop_tgt/HIP_EXTENSIONS.rst create mode 100644 Help/prop_tgt/HIP_STANDARD.rst create mode 100644 Help/prop_tgt/HIP_STANDARD_REQUIRED.rst create mode 100644 Help/variable/CMAKE_HIP_EXTENSIONS.rst create mode 100644 Help/variable/CMAKE_HIP_STANDARD.rst create mode 100644 Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index d04a8647f00..bb5dba3f01b 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -215,6 +215,9 @@ Properties on Targets /prop_tgt/GNUtoMS /prop_tgt/HAS_CXX /prop_tgt/HIP_ARCHITECTURES + /prop_tgt/HIP_EXTENSIONS + /prop_tgt/HIP_STANDARD + /prop_tgt/HIP_STANDARD_REQUIRED /prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM /prop_tgt/IMPORTED /prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index bab53f0bb62..4882003f637 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -528,6 +528,9 @@ Variables for Languages /variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG /variable/CMAKE_HIP_ARCHITECTURES + /variable/CMAKE_HIP_EXTENSIONS + /variable/CMAKE_HIP_STANDARD + /variable/CMAKE_HIP_STANDARD_REQUIRED /variable/CMAKE_ISPC_HEADER_DIRECTORY /variable/CMAKE_ISPC_HEADER_SUFFIX /variable/CMAKE_ISPC_INSTRUCTION_SETS diff --git a/Help/prop_tgt/HIP_EXTENSIONS.rst b/Help/prop_tgt/HIP_EXTENSIONS.rst new file mode 100644 index 00000000000..b731753bd03 --- /dev/null +++ b/Help/prop_tgt/HIP_EXTENSIONS.rst @@ -0,0 +1,19 @@ +HIP_EXTENSIONS +-------------- + +.. versionadded:: 3.21 + +Boolean specifying whether compiler specific extensions are requested. + +This property specifies whether compiler specific extensions should be +used. For some compilers, this results in adding a flag such +as ``-std=gnu++11`` instead of ``-std=c++11`` to the compile line. This +property is ``ON`` by default. The basic HIP/C++ standard level is +controlled by the :prop_tgt:`HIP_STANDARD` target property. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. + +This property is initialized by the value of +the :variable:`CMAKE_HIP_EXTENSIONS` variable if it is set when a target +is created. diff --git a/Help/prop_tgt/HIP_STANDARD.rst b/Help/prop_tgt/HIP_STANDARD.rst new file mode 100644 index 00000000000..0c767c629d6 --- /dev/null +++ b/Help/prop_tgt/HIP_STANDARD.rst @@ -0,0 +1,48 @@ +HIP_STANDARD +------------ + +.. versionadded:: 3.21 + +The HIP/C++ standard requested to build this target. + +Supported values are: + +``98`` + HIP C++98 + +``11`` + HIP C++11 + +``14`` + HIP C++14 + +``17`` + HIP C++17 + +``20`` + HIP C++20 + +``23`` + HIP C++23 + +If the value requested does not result in a compile flag being added for +the compiler in use, a previous standard flag will be added instead. This +means that using: + +.. code-block:: cmake + + set_property(TARGET tgt PROPERTY HIP_STANDARD 11) + +with a compiler which does not support ``-std=gnu++11`` or an equivalent +flag will not result in an error or warning, but will instead add the +``-std=gnu++98`` flag if supported. This "decay" behavior may be controlled +with the :prop_tgt:`HIP_STANDARD_REQUIRED` target property. +Additionally, the :prop_tgt:`HIP_EXTENSIONS` target property may be used to +control whether compiler-specific extensions are enabled on a per-target basis. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. + +This property is initialized by the value of +the :variable:`CMAKE_HIP_STANDARD` variable if it is set when a target +is created. diff --git a/Help/prop_tgt/HIP_STANDARD_REQUIRED.rst b/Help/prop_tgt/HIP_STANDARD_REQUIRED.rst new file mode 100644 index 00000000000..e56209a3cbc --- /dev/null +++ b/Help/prop_tgt/HIP_STANDARD_REQUIRED.rst @@ -0,0 +1,19 @@ +HIP_STANDARD_REQUIRED +--------------------- + +.. versionadded:: 3.21 + +Boolean describing whether the value of :prop_tgt:`HIP_STANDARD` is a requirement. + +If this property is set to ``ON``, then the value of the +:prop_tgt:`HIP_STANDARD` target property is treated as a requirement. If this +property is ``OFF`` or unset, the :prop_tgt:`HIP_STANDARD` target property is +treated as optional and may "decay" to a previous standard if the requested is +not available. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. + +This property is initialized by the value of +the :variable:`CMAKE_HIP_STANDARD_REQUIRED` variable if it is set when a +target is created. diff --git a/Help/variable/CMAKE_HIP_EXTENSIONS.rst b/Help/variable/CMAKE_HIP_EXTENSIONS.rst new file mode 100644 index 00000000000..13987dcdab4 --- /dev/null +++ b/Help/variable/CMAKE_HIP_EXTENSIONS.rst @@ -0,0 +1,10 @@ +CMAKE_HIP_EXTENSIONS +-------------------- + +.. versionadded:: 3.21 + +Default value for :prop_tgt:`HIP_EXTENSIONS` target property if set when a +target is created. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_HIP_STANDARD.rst b/Help/variable/CMAKE_HIP_STANDARD.rst new file mode 100644 index 00000000000..5f151458617 --- /dev/null +++ b/Help/variable/CMAKE_HIP_STANDARD.rst @@ -0,0 +1,10 @@ +CMAKE_HIP_STANDARD +------------------ + +.. versionadded:: 3.21 + +Default value for :prop_tgt:`HIP_STANDARD` target property if set when a target +is created. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst new file mode 100644 index 00000000000..5d35e4e2892 --- /dev/null +++ b/Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst @@ -0,0 +1,10 @@ +CMAKE_HIP_STANDARD_REQUIRED +--------------------------- + +.. versionadded:: 3.21 + +Default value for :prop_tgt:`HIP_STANDARD_REQUIRED` target property if set when +a target is created. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. From 00055d7779b04d27c98bcad1f6da7ffc5d7a09c0 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sun, 15 Aug 2021 13:52:42 +0300 Subject: [PATCH 1311/1519] Help: Document CMAKE_<LANG>_STANDARD_DEFAULT Seems to be stable and will referred to by policy for standards flags rework. --- Help/manual/cmake-variables.7.rst | 1 + Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 4882003f637..543528ce3fa 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -582,6 +582,7 @@ Variables for Languages /variable/CMAKE_LANG_SIZEOF_DATA_PTR /variable/CMAKE_LANG_SOURCE_FILE_EXTENSIONS /variable/CMAKE_LANG_STANDARD + /variable/CMAKE_LANG_STANDARD_DEFAULT /variable/CMAKE_LANG_STANDARD_INCLUDE_DIRECTORIES /variable/CMAKE_LANG_STANDARD_LIBRARIES /variable/CMAKE_LANG_STANDARD_REQUIRED diff --git a/Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst b/Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst new file mode 100644 index 00000000000..eb63d208a3c --- /dev/null +++ b/Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst @@ -0,0 +1,7 @@ +CMAKE_<LANG>_STANDARD_DEFAULT +----------------------------- + +.. versionadded:: 3.9 + +The compiler's default standard for the language ``<LANG>``. Empty if the +compiler has no conception of standard levels. From 2adfd95d793b516fdef2d02a60b9529f525f6374 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sat, 29 May 2021 16:10:36 +0300 Subject: [PATCH 1312/1519] CompilerID: Rename language_dialect to language_standard In Linux C++ terms dialect usually refers to having GNU extensions or not. Change the name to better reflect that this is about the standard version. --- Modules/CMakeCCompilerId.c.in | 20 ++++++++++---------- Modules/CMakeCUDACompilerId.cu.in | 4 ++-- Modules/CMakeCXXCompilerId.cpp.in | 4 ++-- Modules/CMakeDetermineCompilerId.cmake | 2 +- Modules/CMakeHIPCompilerId.hip.in | 4 ++-- Modules/CMakeOBJCCompilerId.m.in | 20 ++++++++++---------- Modules/CMakeOBJCXXCompilerId.mm.in | 4 ++-- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index 1f19c00e2ef..911619088bf 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -41,23 +41,23 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; #if !defined(__STDC__) && !defined(__clang__) # if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) -# define C_DIALECT "90" +# define C_VERSION "90" # else -# define C_DIALECT +# define C_VERSION # endif #elif __STDC_VERSION__ > 201710L -# define C_DIALECT "23" +# define C_VERSION "23" #elif __STDC_VERSION__ >= 201710L -# define C_DIALECT "17" +# define C_VERSION "17" #elif __STDC_VERSION__ >= 201000L -# define C_DIALECT "11" +# define C_VERSION "11" #elif __STDC_VERSION__ >= 199901L -# define C_DIALECT "99" +# define C_VERSION "99" #else -# define C_DIALECT "90" +# define C_VERSION "90" #endif -const char* info_language_dialect_default = - "INFO" ":" "dialect_default[" C_DIALECT "]"; +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; /*--------------------------------------------------------------------------*/ @@ -89,7 +89,7 @@ int main(int argc, char* argv[]) #if defined(__CRAYXT_COMPUTE_LINUX_TARGET) require += info_cray[argc]; #endif - require += info_language_dialect_default[argc]; + require += info_language_standard_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in index 91039e5ae97..96cc8e63a84 100644 --- a/Modules/CMakeCUDACompilerId.cu.in +++ b/Modules/CMakeCUDACompilerId.cu.in @@ -16,7 +16,7 @@ char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; @CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_CUDA_COMPILER_ID_ERROR_FOR_TEST@ -const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +const char* info_language_standard_default = "INFO" ":" "standard_default[" #if __cplusplus > 202002L "23" #elif __cplusplus > 201703L @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) #ifdef SIMULATE_VERSION_MAJOR require += info_simulate_version[argc]; #endif - require += info_language_dialect_default[argc]; + require += info_language_standard_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index 7362a083740..51c901eb095 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -49,7 +49,7 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; # define CXX_STD __cplusplus #endif -const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +const char* info_language_standard_default = "INFO" ":" "standard_default[" #if CXX_STD > 202002L "23" #elif CXX_STD > 201703L @@ -87,7 +87,7 @@ int main(int argc, char* argv[]) #if defined(__CRAYXT_COMPUTE_LINUX_TARGET) require += info_cray[argc]; #endif - require += info_language_dialect_default[argc]; + require += info_language_standard_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index d54e2b057f4..904416f5032 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -881,7 +881,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) if("${info}" MATCHES "INFO:qnxnto\\[\\]") set(COMPILER_QNXNTO 1) endif() - if("${info}" MATCHES "INFO:dialect_default\\[([^]\"]*)\\]") + if("${info}" MATCHES "INFO:standard_default\\[([^]\"]*)\\]") set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_MATCH_1}") endif() endforeach() diff --git a/Modules/CMakeHIPCompilerId.hip.in b/Modules/CMakeHIPCompilerId.hip.in index 5258efba042..72574d42e31 100644 --- a/Modules/CMakeHIPCompilerId.hip.in +++ b/Modules/CMakeHIPCompilerId.hip.in @@ -16,7 +16,7 @@ char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; @CMAKE_HIP_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_HIP_COMPILER_ID_ERROR_FOR_TEST@ -const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +const char* info_language_standard_default = "INFO" ":" "standard_default[" #if __cplusplus > 202002L "23" #elif __cplusplus > 201703L @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) #ifdef SIMULATE_VERSION_MAJOR require += info_simulate_version[argc]; #endif - require += info_language_dialect_default[argc]; + require += info_language_standard_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in index 418fd4852ff..91ae0646f8f 100644 --- a/Modules/CMakeOBJCCompilerId.m.in +++ b/Modules/CMakeOBJCCompilerId.m.in @@ -23,23 +23,23 @@ char const* qnxnto = "INFO" ":" "qnxnto[]"; #if !defined(__STDC__) # if (defined(_MSC_VER) && !defined(__clang__)) \ || (defined(__ibmxl__) || defined(__IBMC__)) -# define C_DIALECT "90" +# define C_VERSION "90" # else -# define C_DIALECT +# define C_VERSION # endif #elif __STDC_VERSION__ > 201710L -# define C_DIALECT "23" +# define C_VERSION "23" #elif __STDC_VERSION__ >= 201710L -# define C_DIALECT "17" +# define C_VERSION "17" #elif __STDC_VERSION__ >= 201000L -# define C_DIALECT "11" +# define C_VERSION "11" #elif __STDC_VERSION__ >= 199901L -# define C_DIALECT "99" +# define C_VERSION "99" #else -# define C_DIALECT "90" +# define C_VERSION "90" #endif -const char* info_language_dialect_default = - "INFO" ":" "dialect_default[" C_DIALECT "]"; +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; /*--------------------------------------------------------------------------*/ @@ -61,7 +61,7 @@ int main(int argc, char* argv[]) #ifdef SIMULATE_VERSION_MAJOR require += info_simulate_version[argc]; #endif - require += info_language_dialect_default[argc]; + require += info_language_standard_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in index e2ac35d05b6..375e05b3770 100644 --- a/Modules/CMakeOBJCXXCompilerId.mm.in +++ b/Modules/CMakeOBJCXXCompilerId.mm.in @@ -29,7 +29,7 @@ char const* qnxnto = "INFO" ":" "qnxnto[]"; #define CXX_STD __cplusplus #endif -const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +const char* info_language_standard_default = "INFO" ":" "standard_default[" #if CXX_STD > 202002L "23" #elfif CXX_STD > 201703L @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) #ifdef SIMULATE_VERSION_MAJOR require += info_simulate_version[argc]; #endif - require += info_language_dialect_default[argc]; + require += info_language_standard_default[argc]; (void)argv; return require; } From fc3a1cbdd81f350b897c6cd06d75e8e228514773 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sat, 29 May 2021 16:54:41 +0300 Subject: [PATCH 1313/1519] CompilerID: Compiler extensions default detection --- Help/manual/cmake-variables.7.rst | 1 + .../variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst | 7 +++++++ Modules/CMakeCCompiler.cmake.in | 1 + Modules/CMakeCCompilerId.c.in | 12 ++++++++++++ Modules/CMakeCUDACompiler.cmake.in | 1 + Modules/CMakeCUDACompilerId.cu.in | 11 +++++++++++ Modules/CMakeCXXCompiler.cmake.in | 1 + Modules/CMakeCXXCompilerId.cpp.in | 12 ++++++++++++ Modules/CMakeDetermineCompilerId.cmake | 5 +++++ Modules/CMakeHIPCompiler.cmake.in | 1 + Modules/CMakeHIPCompilerId.hip.in | 9 +++++++++ Modules/CMakeOBJCCompiler.cmake.in | 1 + Modules/CMakeOBJCCompilerId.m.in | 9 +++++++++ Modules/CMakeOBJCXXCompiler.cmake.in | 1 + Modules/CMakeOBJCXXCompilerId.mm.in | 9 +++++++++ .../Compiler/CMakeCommonCompilerMacros.cmake | 18 ++++++++++++------ 16 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 543528ce3fa..d78ae37df37 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -553,6 +553,7 @@ Variables for Languages /variable/CMAKE_LANG_CREATE_SHARED_MODULE /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY /variable/CMAKE_LANG_EXTENSIONS + /variable/CMAKE_LANG_EXTENSIONS_DEFAULT /variable/CMAKE_LANG_FLAGS /variable/CMAKE_LANG_FLAGS_CONFIG /variable/CMAKE_LANG_FLAGS_CONFIG_INIT diff --git a/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst b/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst new file mode 100644 index 00000000000..6783eb5b599 --- /dev/null +++ b/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst @@ -0,0 +1,7 @@ +CMAKE_<LANG>_EXTENSIONS_DEFAULT +------------------------------- + +.. versionadded:: 3.22 + +Default value used when the :prop_tgt:`<LANG>_EXTENSIONS` target property is +not set. Initialized during compiler detection to the compiler's default. diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 68183815033..2b24ff2aadf 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -5,6 +5,7 @@ set(CMAKE_C_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@") set(CMAKE_C_COMPILER_VERSION_INTERNAL "@CMAKE_C_COMPILER_VERSION_INTERNAL@") set(CMAKE_C_COMPILER_WRAPPER "@CMAKE_C_COMPILER_WRAPPER@") set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "@CMAKE_C_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT@") set(CMAKE_C_COMPILE_FEATURES "@CMAKE_C_COMPILE_FEATURES@") set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@") set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@") diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index 911619088bf..43ede3e8a8d 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -59,6 +59,17 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; const char* info_language_standard_default = "INFO" ":" "standard_default[" C_VERSION "]"; +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + /*--------------------------------------------------------------------------*/ #ifdef ID_VOID_MAIN @@ -90,6 +101,7 @@ int main(int argc, char* argv[]) require += info_cray[argc]; #endif require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 56ae7324b2d..2f3e9a8ce87 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -6,6 +6,7 @@ set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@") set(CMAKE_CUDA_DEVICE_LINKER "@CMAKE_CUDA_DEVICE_LINKER@") set(CMAKE_CUDA_FATBINARY "@CMAKE_CUDA_FATBINARY@") set(CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT "@CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_CUDA_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_CUDA_EXTENSIONS_COMPUTED_DEFAULT@") set(CMAKE_CUDA_COMPILE_FEATURES "@CMAKE_CUDA_COMPILE_FEATURES@") set(CMAKE_CUDA03_COMPILE_FEATURES "@CMAKE_CUDA03_COMPILE_FEATURES@") set(CMAKE_CUDA11_COMPILE_FEATURES "@CMAKE_CUDA11_COMPILE_FEATURES@") diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in index 96cc8e63a84..bc685a7eb80 100644 --- a/Modules/CMakeCUDACompilerId.cu.in +++ b/Modules/CMakeCUDACompilerId.cu.in @@ -32,6 +32,16 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" #endif "]"; +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. +#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__) && \ + !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + /*--------------------------------------------------------------------------*/ int main(int argc, char* argv[]) @@ -49,6 +59,7 @@ int main(int argc, char* argv[]) require += info_simulate_version[argc]; #endif require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 7aad9e2a3e0..534e96055f9 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -5,6 +5,7 @@ set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@") set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "@CMAKE_CXX_COMPILER_VERSION_INTERNAL@") set(CMAKE_CXX_COMPILER_WRAPPER "@CMAKE_CXX_COMPILER_WRAPPER@") set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_CXX_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT@") set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@") set(CMAKE_CXX98_COMPILE_FEATURES "@CMAKE_CXX98_COMPILE_FEATURES@") set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@") diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index 51c901eb095..cdf9c1828aa 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -65,6 +65,17 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" #endif "]"; +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + /*--------------------------------------------------------------------------*/ int main(int argc, char* argv[]) @@ -88,6 +99,7 @@ int main(int argc, char* argv[]) require += info_cray[argc]; #endif require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 904416f5032..b38de8a1e7b 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -267,6 +267,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE) set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE) set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE) + set(CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT "${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_PRODUCED_OUTPUT "${COMPILER_${lang}_PRODUCED_OUTPUT}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE) endfunction() @@ -884,6 +885,9 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) if("${info}" MATCHES "INFO:standard_default\\[([^]\"]*)\\]") set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_MATCH_1}") endif() + if("${info}" MATCHES "INFO:extensions_default\\[([^]\"]*)\\]") + set(CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT "${CMAKE_MATCH_1}") + endif() endforeach() # Construct compiler version from components if needed. @@ -993,6 +997,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE) set(COMPILER_QNXNTO "${COMPILER_QNXNTO}" PARENT_SCOPE) set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE) + set(CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT "${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT}" PARENT_SCOPE) endfunction() #----------------------------------------------------------------------------- diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in index 17633a86c41..ce4e2cf6565 100644 --- a/Modules/CMakeHIPCompiler.cmake.in +++ b/Modules/CMakeHIPCompiler.cmake.in @@ -2,6 +2,7 @@ set(CMAKE_HIP_COMPILER "@CMAKE_HIP_COMPILER@") set(CMAKE_HIP_COMPILER_ID "@CMAKE_HIP_COMPILER_ID@") set(CMAKE_HIP_COMPILER_VERSION "@CMAKE_HIP_COMPILER_VERSION@") set(CMAKE_HIP_STANDARD_COMPUTED_DEFAULT "@CMAKE_HIP_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_HIP_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_HIP_EXTENSIONS_COMPUTED_DEFAULT@") set(CMAKE_HIP_COMPILE_FEATURES "@CMAKE_HIP_COMPILE_FEATURES@") set(CMAKE_HIP98_COMPILE_FEATURES "@CMAKE_HIP03_COMPILE_FEATURES@") set(CMAKE_HIP11_COMPILE_FEATURES "@CMAKE_HIP11_COMPILE_FEATURES@") diff --git a/Modules/CMakeHIPCompilerId.hip.in b/Modules/CMakeHIPCompilerId.hip.in index 72574d42e31..3c4a1d4be0e 100644 --- a/Modules/CMakeHIPCompilerId.hip.in +++ b/Modules/CMakeHIPCompilerId.hip.in @@ -32,6 +32,14 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" #endif "]"; +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + /*--------------------------------------------------------------------------*/ int main(int argc, char* argv[]) @@ -49,6 +57,7 @@ int main(int argc, char* argv[]) require += info_simulate_version[argc]; #endif require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in index ab67bf3961c..36f6ec15051 100644 --- a/Modules/CMakeOBJCCompiler.cmake.in +++ b/Modules/CMakeOBJCCompiler.cmake.in @@ -5,6 +5,7 @@ set(CMAKE_OBJC_COMPILER_VERSION "@CMAKE_OBJC_COMPILER_VERSION@") set(CMAKE_OBJC_COMPILER_VERSION_INTERNAL "@CMAKE_OBJC_COMPILER_VERSION_INTERNAL@") set(CMAKE_OBJC_COMPILER_WRAPPER "@CMAKE_OBJC_COMPILER_WRAPPER@") set(CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_OBJC_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_OBJC_EXTENSIONS_COMPUTED_DEFAULT@") set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@") set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@") set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@") diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in index 91ae0646f8f..89bfe02e690 100644 --- a/Modules/CMakeOBJCCompilerId.m.in +++ b/Modules/CMakeOBJCCompilerId.m.in @@ -41,6 +41,14 @@ char const* qnxnto = "INFO" ":" "qnxnto[]"; const char* info_language_standard_default = "INFO" ":" "standard_default[" C_VERSION "]"; +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + /*--------------------------------------------------------------------------*/ int main(int argc, char* argv[]) @@ -62,6 +70,7 @@ int main(int argc, char* argv[]) require += info_simulate_version[argc]; #endif require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; (void)argv; return require; } diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in index a24582b8b54..4f271003a57 100644 --- a/Modules/CMakeOBJCXXCompiler.cmake.in +++ b/Modules/CMakeOBJCXXCompiler.cmake.in @@ -5,6 +5,7 @@ set(CMAKE_OBJCXX_COMPILER_VERSION "@CMAKE_OBJCXX_COMPILER_VERSION@") set(CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL "@CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL@") set(CMAKE_OBJCXX_COMPILER_WRAPPER "@CMAKE_OBJCXX_COMPILER_WRAPPER@") set(CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_OBJCXX_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_OBJCXX_EXTENSIONS_COMPUTED_DEFAULT@") set(CMAKE_OBJCXX_COMPILE_FEATURES "@CMAKE_OBJCXX_COMPILE_FEATURES@") set(CMAKE_OBJCXX98_COMPILE_FEATURES "@CMAKE_OBJCXX98_COMPILE_FEATURES@") set(CMAKE_OBJCXX11_COMPILE_FEATURES "@CMAKE_OBJCXX11_COMPILE_FEATURES@") diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in index 375e05b3770..2145b4046e0 100644 --- a/Modules/CMakeOBJCXXCompilerId.mm.in +++ b/Modules/CMakeOBJCXXCompilerId.mm.in @@ -45,6 +45,14 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" #endif "]"; +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + /*--------------------------------------------------------------------------*/ int main(int argc, char* argv[]) @@ -65,6 +73,7 @@ int main(int argc, char* argv[]) require += info_simulate_version[argc]; #endif require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; (void)argv; return require; } diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index c86af98f8db..2f220d466ca 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -38,20 +38,26 @@ macro(__compiler_check_default_language_standard lang stdver1 std1) # support for language standards, then don't bother. if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "${stdver1}") if (NOT CMAKE_${lang}_COMPILER_FORCED) - if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}") + if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT OR NOT DEFINED CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT) + message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT and CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}") endif () set(CMAKE_${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}) + set(CMAKE_${lang}_EXTENSIONS_DEFAULT ${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT}) else () list(REVERSE __std_ver_pairs) foreach (__std_ver_pair IN LISTS __std_ver_pairs) string(REGEX MATCH "([^ ]+) (.+)" __std_ver_pair "${__std_ver_pair}") set(__stdver ${CMAKE_MATCH_1}) set(__std ${CMAKE_MATCH_2}) - if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver AND - NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_${lang}_STANDARD_DEFAULT ${__std}) + # Compiler id was forced so just guess the defaults. + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver) + if(NOT DEFINED CMAKE_${lang}_EXTENSIONS_DEFAULT) + # Currently known compilers default to enabling extensions. + set(CMAKE_${lang}_EXTENSIONS_DEFAULT ON) + endif() + if(NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT) + set(CMAKE_${lang}_STANDARD_DEFAULT ${__std}) + endif() endif () unset(__std) unset(__stdver) From 29e2b8517126389b2c4b2f3479c4634a8260bea3 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Thu, 12 Aug 2021 17:53:29 +0300 Subject: [PATCH 1314/1519] Tests: Simplify RunCMake.CompileFeatures introspection --- Tests/RunCMake/CMakeLists.txt | 2 +- .../CompileFeatures/RunCMakeTest.cmake | 19 ++------ .../compiler_introspection.cmake | 20 +++++++++ .../generate_feature_list.cmake | 43 ------------------- 4 files changed, 24 insertions(+), 60 deletions(-) create mode 100644 Tests/RunCMake/CompileFeatures/compiler_introspection.cmake delete mode 100644 Tests/RunCMake/CompileFeatures/generate_feature_list.cmake diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index eb2c2d94ae1..af6cbb5642b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -310,7 +310,7 @@ add_RunCMake_test(TargetProperties) add_RunCMake_test(ToolchainFile) add_RunCMake_test(find_dependency) add_RunCMake_test(CompileDefinitions) -add_RunCMake_test(CompileFeatures) +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(WriteBasicConfigVersionFile) diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake index 5a70da2fa3f..934d8ca878d 100644 --- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake @@ -9,17 +9,8 @@ run_cmake(NotAFeature_OriginDebugGenex) run_cmake(NotAFeature_OriginDebugTransitive) run_cmake(NotAFeature_OriginDebugCommand) -run_cmake(generate_feature_list) -file(READ - "${RunCMake_BINARY_DIR}/generate_feature_list-build/c_features.txt" - C_FEATURES -) -file(READ - "${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx_features.txt" - CXX_FEATURES -) -include("${RunCMake_BINARY_DIR}/generate_feature_list-build/c_standard_default.cmake") -include("${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx_standard_default.cmake") +run_cmake(compiler_introspection) +include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake") if (NOT C_FEATURES) run_cmake(NoSupportedCFeatures) @@ -47,15 +38,11 @@ if(CXX_STANDARD_DEFAULT) run_cmake(NotAStandard) foreach(standard 98 11) - file(READ - "${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx${standard}_flag.txt" - CXX${standard}_FLAG - ) if (CXX${standard}_FLAG STREQUAL NOTFOUND) run_cmake(RequireCXX${standard}) run_cmake(RequireCXX${standard}Variable) endif() - if (CXX${standard}EXT_FLAG STREQUAL NOTFOUND) + if (CXX${standard}_EXT_FLAG STREQUAL NOTFOUND) run_cmake(RequireCXX${standard}Ext) run_cmake(RequireCXX${standard}ExtVariable) endif() diff --git a/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake b/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake new file mode 100644 index 00000000000..c42324b9dd3 --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake @@ -0,0 +1,20 @@ +enable_language(C CXX) + +macro(info lang) + string(APPEND info "\ +set(${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_DEFAULT}) +set(${lang}_EXTENSIONS_DEFAULT ${CMAKE_${lang}_EXTENSIONS_DEFAULT}) +set(${lang}_FEATURES ${CMAKE_${lang}_COMPILE_FEATURES}) +") + + foreach(standard ${ARGN}) + string(APPEND info "\ +set(${lang}${standard}_FLAG ${CMAKE_${lang}${standard}_STANDARD_COMPILE_OPTION}) +set(${lang}${standard}_EXT_FLAG ${CMAKE_${lang}${standard}_EXTENSION_COMPILE_OPTION}) +") + endforeach() +endmacro() + +info(C 90 99 11 17 23) +info(CXX 98 11 14 17 20 23) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}") diff --git a/Tests/RunCMake/CompileFeatures/generate_feature_list.cmake b/Tests/RunCMake/CompileFeatures/generate_feature_list.cmake deleted file mode 100644 index 5c58052b810..00000000000 --- a/Tests/RunCMake/CompileFeatures/generate_feature_list.cmake +++ /dev/null @@ -1,43 +0,0 @@ - -enable_language(C) - -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/c_features.txt" - "${CMAKE_C_COMPILE_FEATURES}" -) - -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_features.txt" - "${CMAKE_CXX_COMPILE_FEATURES}" -) - -if(DEFINED CMAKE_C_STANDARD_DEFAULT) - set(c_standard_default_code "set(C_STANDARD_DEFAULT \"${CMAKE_C_STANDARD_DEFAULT}\")\n") -else() - set(c_standard_default_code "unset(C_STANDARD_DEFAULT)\n") -endif() -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/c_standard_default.cmake" "${c_standard_default_code}") - -if(DEFINED CMAKE_CXX_STANDARD_DEFAULT) - set(cxx_standard_default_code "set(CXX_STANDARD_DEFAULT \"${CMAKE_CXX_STANDARD_DEFAULT}\")\n") -else() - set(cxx_standard_default_code "unset(CXX_STANDARD_DEFAULT)\n") -endif() -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_standard_default.cmake" "${cxx_standard_default_code}") - -foreach(standard 98 11) - set(CXX${standard}_FLAG NOTFOUND) - if (DEFINED CMAKE_CXX${standard}_STANDARD_COMPILE_OPTION) - set(CXX${standard}_FLAG ${CMAKE_CXX${standard}_STANDARD_COMPILE_OPTION}) - endif() - - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx${standard}_flag.txt" - "${CXX${standard}_FLAG}" - ) - set(CXX${standard}EXT_FLAG NOTFOUND) - if (DEFINED CMAKE_CXX${standard}_EXTENSION_COMPILE_OPTION) - set(CXX${standard}EXT_FLAG ${CMAKE_CXX${standard}_EXTENSION_COMPILE_OPTION}) - endif() - - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx${standard}ext_flag.txt" - "${CXX${standard}EXT_FLAG}" - ) -endforeach() From 700f76299c40ba2c17841b69e480d13055743a0c Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 29 Sep 2021 00:01:13 -0400 Subject: [PATCH 1315/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0359ca6a437..9fe9c752131 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210928) +set(CMake_VERSION_PATCH 20210929) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 096450f8080f3bec2498a44e47604e37d4aa4eb2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 29 Sep 2021 11:25:01 -0400 Subject: [PATCH 1316/1519] libuv: Include BSD sys/cpuset.h only on platforms where we use it Since commit 43d6e5a71f (libuv: misc: add function to get CPU affinity mask size, 2017-09-06, v3.12.0-rc1~412^2~3) we include `<sys/cpuset.h>` on several BSD platforms but only use it on FreeBSD. --- Utilities/cmlibuv/src/unix/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index e6d61ee2dfc..4245e027a65 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -72,8 +72,6 @@ extern char** environ; # include <sys/sysctl.h> # include <sys/filio.h> # include <sys/wait.h> -# include <sys/param.h> -# include <sys/cpuset.h> # if defined(__FreeBSD__) # define uv__accept4 accept4 # endif @@ -82,6 +80,11 @@ extern char** environ; # endif #endif +#if defined(__FreeBSD__) +# include <sys/param.h> +# include <sys/cpuset.h> +#endif + #if defined(__MVS__) #include <sys/ioctl.h> #endif From 9aba0ce29d9e6f1dfc3c17020fac45424d393329 Mon Sep 17 00:00:00 2001 From: Ralf Habacker <ralf.habacker@freenet.de> Date: Wed, 29 Sep 2021 14:17:41 +0200 Subject: [PATCH 1317/1519] Help: Fix CMAKE_FIND_LIBRARY_SUFFIXES examples for Windows Fixes: #22697 --- Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst b/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst index 4a64e33e9b6..c2c2609dfc6 100644 --- a/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst +++ b/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst @@ -5,5 +5,8 @@ Suffixes to append when looking for libraries. This specifies what suffixes to add to library names when the :command:`find_library` command looks for libraries. On Windows systems this -is typically ``.lib`` and ``.dll``, meaning that when trying to find the -``foo`` library it will look for ``foo.dll`` etc. +is typically ``.lib`` and, depending on the compiler, ``.dll.a``, ``.a`` +(e.g. GCC and Clang), so when it tries to find the ``foo`` library, it will +look for ``[<prefix>]foo.lib`` and/or ``[<prefix>]foo[.dll].a``, depending on +the compiler used and the ``<prefix>`` specified in the +:variable:`CMAKE_FIND_LIBRARY_PREFIXES`. From 7fdd5128b17d0edc97ec555c0afa54c0608804d2 Mon Sep 17 00:00:00 2001 From: Alexander Neumann <neumann@imt.uni-luebeck.de> Date: Fri, 2 Jul 2021 16:24:20 +0200 Subject: [PATCH 1318/1519] FindMatlab: Fix version selection if a version is given Fixes: #22377 --- Modules/FindMatlab.cmake | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index fdab9e93622..0ca593e98f8 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -1572,6 +1572,29 @@ if(_numbers_of_matlab_roots GREATER 0) list(GET _matlab_possible_roots ${_matlab_or_mcr_index} Matlab_Or_MCR) list(GET _matlab_possible_roots ${_list_index} Matlab_VERSION_STRING) list(GET _matlab_possible_roots ${_matlab_root_dir_index} Matlab_ROOT_DIR) + elseif(DEFINED Matlab_FIND_VERSION) + foreach(_matlab_root_index RANGE 1 ${_numbers_of_matlab_roots} 3) + list(GET _matlab_possible_roots ${_matlab_root_index} _matlab_root_version) + if(_matlab_root_version VERSION_GREATER_EQUAL Matlab_FIND_VERSION) + set(_list_index ${_matlab_root_index}) + break() + endif() + endforeach() + + if(_list_index LESS 0) + set(_list_index 1) + endif() + + math(EXPR _matlab_or_mcr_index "${_list_index} - 1") + math(EXPR _matlab_root_dir_index "${_list_index} + 1") + list(GET _matlab_possible_roots ${_matlab_or_mcr_index} Matlab_Or_MCR) + list(GET _matlab_possible_roots ${_list_index} Matlab_VERSION_STRING) + list(GET _matlab_possible_roots ${_matlab_root_dir_index} Matlab_ROOT_DIR) + # adding a warning in case of ambiguity + if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})." + " If this is not the desired behavior, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line") + endif() else() list(GET _matlab_possible_roots 0 Matlab_Or_MCR) list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING) From ae53a3071bfa9919b54a7a4e41a4b26f0b3c9d9f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 29 Sep 2021 15:08:24 -0400 Subject: [PATCH 1319/1519] update-third-party: update from upstream Update to `update-common.sh` from commit `7134d5ebef` in https://gitlab.kitware.com/utils/git-import-third-party --- Utilities/Scripts/update-third-party.bash | 42 ++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash index 0d0a667c126..bfe6828de98 100644 --- a/Utilities/Scripts/update-third-party.bash +++ b/Utilities/Scripts/update-third-party.bash @@ -42,6 +42,22 @@ # For convenience, the function may use the "git_archive" function which # does a standard "git archive" extraction using the (optional) "paths" # variable to only extract a subset of the source tree. +# +# Dependencies +# +# To update third party packages from git repositories with submodule, +# you will need to install the "git-archive-all" Python package with +# +# pip install git-archive-all +# +# or install it from https://github.com/Kentzo/git-archive-all. +# +# This package installs a script named "git-archive-all" where pip +# installs executables. If you run pip under your user privileges (i.e., +# not using "sudo"), this location may be $HOME/.local/bin. Make sure +# that directory is in your path so that git can find the +# "git-archive-all" script. +# ######################################################################## ######################################################################## @@ -52,11 +68,24 @@ git_archive () { tar -C "$extractdir" -x } +confirm_archive_all_exists () { + which git-archive-all || die "git requires an archive-all command. Please run 'pip install git-archive-all'" +} + +git_archive_all () { + confirm_archive_all_exists + local tmptarball="temp.tar" + git archive-all --prefix="" "$tmptarball" + mkdir -p "$extractdir/$name-reduced" + tar -C "$extractdir/$name-reduced" -xf "$tmptarball" $paths + rm -f "$tmptarball" +} + disable_custom_gitattributes() { pushd "${extractdir}/${name}-reduced" # Git does not allow custom attributes in a subdirectory where we # are about to merge the `.gitattributes` file, so disable them. - sed -i '/^\[attr\]/ {s/^/#/}' .gitattributes + sed -i '/^\[attr\]/ {s/^/#/;}' .gitattributes popd } @@ -71,6 +100,9 @@ warn () { readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]' readonly basehash_regex="$name $regex_date ([0-9a-f]*)" +readonly toplevel_dir="$( git rev-parse --show-toplevel )" + +cd "$toplevel_dir" ######################################################################## # Sanity checking @@ -95,7 +127,7 @@ if [ ! -d "$(git rev-parse --show-toplevel)/$subtree" ]; then else readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )" fi -readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )" +readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p;}' | egrep '^[0-9a-f]+$' )" [ -n "$basehash" ] || \ warn "'basehash' is empty; performing initial import" @@ -111,7 +143,7 @@ readonly extractdir="$workdir/extract" trap "rm -rf '$workdir'" EXIT # Get upstream -git clone "$repo" "$upstreamdir" +git clone --recursive "$repo" "$upstreamdir" if [ -n "$basehash" ]; then # Remove old worktrees @@ -120,7 +152,7 @@ if [ -n "$basehash" ]; then git worktree add "$extractdir" "$basehash" # Clear out the working tree pushd "$extractdir" - git ls-files | xargs rm -v + git ls-files -z --recurse-submodules | xargs -0 rm -v find . -type d -empty -delete popd else @@ -132,6 +164,8 @@ fi # Extract the subset of upstream we care about pushd "$upstreamdir" git checkout "$tag" +git submodule sync --recursive +git submodule update --recursive --init readonly upstream_hash="$( git rev-parse HEAD )" readonly upstream_hash_short="$( git rev-parse --short=8 "$upstream_hash" )" readonly upstream_datetime="$( git rev-list "$upstream_hash" --format='%ci' -n 1 | grep -e "^$regex_date" )" From 4a0485be7f4ab06201c478f5a46111ab1e8e773e Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sat, 29 May 2021 18:34:18 +0300 Subject: [PATCH 1320/1519] cmStandardLevelResolver: Avoid unnecessary flags, fix unset level logic The changes are part of CMP0128. When the standard level is unset: * Flags are added if extension mode doesn't match the compiler's default. Previously logic only worked if LANG_EXTENSIONS was ON. Fixes #22224. * The full flag is used. Previously CMAKE_LANG_EXTENSION_COMPILE_OPTION was used. This was only supported for IAR. Otherwise: * Avoid adding flags if not necessary per the detected compiler defaults. * Fixed check for when the requested standard is older. It now matches the nearby comments. I reworded the fallback comment as its logic was a bit difficult to wrap my head around. --- Help/manual/cmake-compile-features.7.rst | 11 +- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0128.rst | 78 ++++++++++++ ...compile-features-standard-logic-rework.rst | 10 ++ .../variable/CMAKE_POLICY_WARNING_CMPNNNN.rst | 2 + Modules/Compiler/IAR-C.cmake | 1 + Modules/Compiler/IAR-CXX.cmake | 2 +- Source/cmPolicies.h | 5 +- Source/cmStandardLevelResolver.cxx | 87 ++++++++++--- .../CMP0128WarnMatch-stderr.txt | 8 ++ .../CompileFeatures/CMP0128WarnMatch.cmake | 7 ++ .../CMP0128WarnUnset-stderr.txt | 8 ++ .../CompileFeatures/CMP0128WarnUnset.cmake | 6 + .../NoUnnecessaryFlag-build-check.cmake | 8 ++ .../CompileFeatures/NoUnnecessaryFlag.cmake | 9 ++ .../CompileFeatures/RunCMakeTest.cmake | 116 ++++++++++++++++++ .../UnsetStandard-build-check.cmake | 12 ++ .../CompileFeatures/UnsetStandard.cmake | 8 ++ .../compiler_introspection.cmake | 18 +++ Tests/RunCMake/CompileFeatures/empty.c | 2 +- 20 files changed, 375 insertions(+), 24 deletions(-) create mode 100644 Help/policy/CMP0128.rst create mode 100644 Help/release/dev/compile-features-standard-logic-rework.rst create mode 100644 Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake create mode 100644 Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt create mode 100644 Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake create mode 100644 Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake create mode 100644 Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake create mode 100644 Tests/RunCMake/CompileFeatures/UnsetStandard-build-check.cmake create mode 100644 Tests/RunCMake/CompileFeatures/UnsetStandard.cmake diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 2b0de110189..a0459fac46f 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -118,14 +118,13 @@ as well as any dependents (that may include headers from ``mylib``). Availability of Compiler Extensions ----------------------------------- -Because the :prop_tgt:`CXX_EXTENSIONS` target property is ``ON`` by default, -CMake uses extended variants of language dialects by default, such as -``-std=gnu++11`` instead of ``-std=c++11``. That target property may be -set to ``OFF`` to use the non-extended variant of the dialect flag. Note -that because most compilers enable extensions by default, this could -expose cross-platform bugs in user code or in the headers of third-party +The :prop_tgt:`<LANG>_EXTENSIONS` target property defaults to the compiler's +efault. Note that because most compilers enable extensions by default, this +may expose cross-platform bugs in user code or in the headers of third-party dependencies. +:prop_tgt:`<LANG>_EXTENSIONS` used to default to ``ON``. See :policy:`CMP0128`. + Optional Compile Features ========================= diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 0f0c0abbecd..3df4f9fa79e 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.22 .. toctree:: :maxdepth: 1 + CMP0128: Selection of language standard and extension flags improved. </policy/CMP0128> CMP0127: cmake_dependent_option() supports full Condition Syntax. </policy/CMP0127> Policies Introduced by CMake 3.21 diff --git a/Help/policy/CMP0128.rst b/Help/policy/CMP0128.rst new file mode 100644 index 00000000000..f341f24abf7 --- /dev/null +++ b/Help/policy/CMP0128.rst @@ -0,0 +1,78 @@ +CMP0128 +------- + +.. versionadded:: 3.22 + +When this policy is set to ``NEW``: + +* :prop_tgt:`<LANG>_EXTENSIONS` is initialized to + :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. + +* Extensions are correctly disabled/enabled if :prop_tgt:`<LANG>_STANDARD` is + unset. + +* Standard mode-affecting flags aren't added unless necessary to achieve the + specified mode. + +The ``OLD`` behavior: + +* Initializes :prop_tgt:`<LANG>_EXTENSIONS` to ``ON``. + +* Always adds a flag if :prop_tgt:`<LANG>_STANDARD` is set and + :prop_tgt:`<LANG>_STANDARD_REQUIRED` is ``OFF``. + +* If :prop_tgt:`<LANG>_STANDARD` is unset: + + * Doesn't disable extensions even if :prop_tgt:`<LANG>_EXTENSIONS` is + ``OFF``. + + * Fails to enable extensions if :prop_tgt:`<LANG>_EXTENSIONS` is ``ON`` + except for the ``IAR`` compiler. + +Code may need to be updated for the ``NEW`` behavior in the following cases: + +* If :prop_tgt:`<LANG>_EXTENSIONS` matches + :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT` or is unset and the compiler's + default satisfies :prop_tgt:`<LANG>_STANDARD` but the compiled code requires + the exact standard specified. + Such code should set :prop_tgt:`<LANG>_STANDARD_REQUIRED` to ``ON``. + + For example: + + .. code-block:: cmake + + cmake_minimum_required(VERSION |release|) + project(example C) + + add_executable(exe main.c) + set_property(TARGET exe PROPERTY C_STANDARD 99) + + If the compiler defaults to C11 then the standard specification for C99 is + satisfied and CMake will pass no flags. ``main.c`` will no longer compile if + it is incompatible with C11. + +* If a standard mode flag previously overridden by CMake's and not used during + compiler detection now takes effect due to CMake no longer adding one as the + default detected is appropriate. + + Such code should be converted to either: + + * Use :prop_tgt:`<LANG>_STANDARD` and :prop_tgt:`<LANG>_EXTENSIONS` instead + of manually adding flags. + + * Or ensure the manually-specified flags are used during compiler detection. + +If compiler flags affecting the standard mode are used during compiler +detection (for example in :manual:`a toolchain file <cmake-toolchains(7)>` +using :variable:`CMAKE_<LANG>_FLAGS_INIT`) then they will affect the detected +default :variable:`standard <CMAKE_<LANG>_STANDARD_DEFAULT>` and +:variable:`extensions <CMAKE_<LANG>_EXTENSIONS_DEFAULT>`. + +Unlike many policies, CMake version |release| does *not* warn when the policy +is not set and simply uses the ``OLD`` behavior. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +See documentation of the +:variable:`CMAKE_POLICY_WARNING_CMP0128 <CMAKE_POLICY_WARNING_CMP<NNNN>>` +variable to control the warning. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/compile-features-standard-logic-rework.rst b/Help/release/dev/compile-features-standard-logic-rework.rst new file mode 100644 index 00000000000..432a7568744 --- /dev/null +++ b/Help/release/dev/compile-features-standard-logic-rework.rst @@ -0,0 +1,10 @@ +compile-features-standard-logic-rework +-------------------------------------- + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality now + correctly disables or enables compiler extensions when no standard level is + specified and avoids unnecessarily adding language standard flags if the + requested settings match the compiler's defaults. See :policy:`CMP0128`. + +* :prop_tgt:`<LANG>_EXTENSIONS` is initialized to + :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. See :policy:`CMP0128`. diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst index 11dd194c2c2..02316682ed2 100644 --- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst +++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst @@ -32,6 +32,8 @@ only for the policies that do not warn by default: policy :policy:`CMP0116`. * ``CMAKE_POLICY_WARNING_CMP0126`` controls the warning for policy :policy:`CMP0126`. +* ``CMAKE_POLICY_WARNING_CMP0128`` controls the warning for + policy :policy:`CMP0128`. This variable should not be set by a project in CMake code. Project developers running CMake may set this variable in their cache to diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index 9629279c431..0ef1a2a8534 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -14,6 +14,7 @@ if(NOT DEFINED CMAKE_C_COMPILER_VERSION) message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION not detected. This should be automatic.") endif() +# Unused after CMP0128 set(CMAKE_C_EXTENSION_COMPILE_OPTION -e) if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_GREATER 7) diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index b102aa6dfd9..a3f1dbc29e6 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -27,7 +27,7 @@ if(NOT CMAKE_IAR_CXX_FLAG) endif() set(CMAKE_CXX_STANDARD_COMPILE_OPTION "") -set(CMAKE_CXX_EXTENSION_COMPILE_OPTION -e) +set(CMAKE_CXX_EXTENSION_COMPILE_OPTION -e) # Unused after CMP0128 set(CMAKE_CXX${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}_STANDARD_COMPILE_OPTION "") set(CMAKE_CXX${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}_EXTENSION_COMPILE_OPTION -e) diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index a98e6c6df9c..ce0411761c0 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -382,7 +382,10 @@ class cmMakefile; 21, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0127, \ "cmake_dependent_option() supports full Condition Syntax.", 3, 22, \ - 0, cmPolicies::WARN) + 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0128, \ + "Selection of language standard and extension flags improved.", 3, \ + 22, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index c73f53a2ee1..957f4ca2df0 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -20,6 +20,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmValue.h" @@ -83,25 +84,62 @@ struct StandardLevelComputer return std::string{}; } + cmPolicies::PolicyStatus const cmp0128{ makefile->GetPolicyStatus( + cmPolicies::CMP0128) }; + bool const defaultExt{ cmIsOn(*makefile->GetDefinition( + cmStrCat("CMAKE_", this->Language, "_EXTENSIONS_DEFAULT"))) }; bool ext = true; + + if (cmp0128 == cmPolicies::NEW) { + ext = defaultExt; + } + if (cmValue extPropValue = target->GetLanguageExtensions(this->Language)) { - if (cmIsOff(*extPropValue)) { - ext = false; - } + ext = cmIsOn(*extPropValue); } + std::string const type{ ext ? "EXTENSION" : "STANDARD" }; + cmValue standardProp = target->GetLanguageStandard(this->Language, config); if (!standardProp) { - if (ext) { - // No language standard is specified and extensions are not disabled. - // Check if this compiler needs a flag to enable extensions. - return cmStrCat("CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION"); + if (cmp0128 == cmPolicies::NEW) { + // Add extension flag if compiler's default doesn't match. + if (ext != defaultExt) { + return cmStrCat("CMAKE_", this->Language, *defaultStd, "_", type, + "_COMPILE_OPTION"); + } + } else { + if (cmp0128 == cmPolicies::WARN && + makefile->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0128") && + ext != defaultExt) { + const char* state{}; + if (ext) { + if (!makefile->GetDefinition(cmStrCat( + "CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION"))) { + state = "enabled"; + } + } else { + state = "disabled"; + } + if (state) { + makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0128), + "\nFor compatibility with older versions of CMake, " + "compiler extensions won't be ", + state, ".")); + } + } + + if (ext) { + return cmStrCat("CMAKE_", this->Language, + "_EXTENSION_COMPILE_OPTION"); + } } return std::string{}; } - std::string const type = ext ? "EXTENSION" : "STANDARD"; - if (target->GetLanguageStandardRequired(this->Language)) { std::string option_flag = cmStrCat( "CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION"); @@ -121,6 +159,25 @@ struct StandardLevelComputer return option_flag; } + // If the request matches the compiler's defaults we don't need to add + // anything. + if (*standardProp == *defaultStd && ext == defaultExt) { + if (cmp0128 == cmPolicies::NEW) { + return std::string{}; + } + + if (cmp0128 == cmPolicies::WARN && + makefile->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0128")) { + makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0128), + "\nFor compatibility with older versions of CMake, " + "unnecessary flags for language standard or compiler " + "extensions may be added.")); + } + } + std::string standardStr(*standardProp); if (this->Language == "CUDA" && standardStr == "98") { standardStr = "03"; @@ -147,17 +204,17 @@ struct StandardLevelComputer return std::string{}; } - // If the standard requested is older than the compiler's default - // then we need to use a flag to change it. - if (stdIt <= defaultStdIt) { + // If the standard requested is older than the compiler's default or the + // extension mode doesn't match then we need to use a flag. + if (stdIt < defaultStdIt) { auto offset = std::distance(cm::cbegin(stds), stdIt); return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type, "_COMPILE_OPTION"); } - // The standard requested is at least as new as the compiler's default, - // and the standard request is not required. Decay to the newest standard - // for which a flag is defined. + // The compiler's default is at least as new as the requested standard, + // and the requested standard is not required. Decay to the newest + // standard for which a flag is defined. for (; defaultStdIt < stdIt; --stdIt) { auto offset = std::distance(cm::cbegin(stds), stdIt); std::string option_flag = diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt new file mode 100644 index 00000000000..320c2bafe5a --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) in CMakeLists\.txt: + Policy CMP0128 is not set: Selection of language standard and extension + flags improved\. Run "cmake --help-policy CMP0128" for policy details\. Use + the cmake_policy command to set the policy and suppress this warning\. + + For compatibility with older versions of CMake, unnecessary flags for + language standard or compiler extensions may be added. +This warning is for project developers\. Use -Wno-dev to suppress it\. diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake new file mode 100644 index 00000000000..0a5606ac7b2 --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake @@ -0,0 +1,7 @@ +enable_language(@lang@) +cmake_policy(SET CMP0128 OLD) +set(CMAKE_POLICY_WARNING_CMP0128 ON) + +set(CMAKE_@lang@_EXTENSIONS @extensions_default@) +set(CMAKE_@lang@_STANDARD @standard_default@) +add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@") diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt new file mode 100644 index 00000000000..068cba9c23c --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) in CMakeLists\.txt: + Policy CMP0128 is not set: Selection of language standard and extension + flags improved\. Run "cmake --help-policy CMP0128" for policy details\. Use + the cmake_policy command to set the policy and suppress this warning\. + + For compatibility with older versions of CMake, compiler extensions won't + be @opposite@\. +This warning is for project developers\. Use -Wno-dev to suppress it\. diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake new file mode 100644 index 00000000000..cd7af2c00e4 --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake @@ -0,0 +1,6 @@ +enable_language(@lang@) +cmake_policy(SET CMP0128 OLD) +set(CMAKE_POLICY_WARNING_CMP0128 ON) + +set(CMAKE_@lang@_EXTENSIONS @extensions_opposite@) +add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@") diff --git a/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake new file mode 100644 index 00000000000..4f767fabd2d --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake @@ -0,0 +1,8 @@ +foreach(flag @flags@) + string(FIND "${actual_stdout}" "${flag}" position) + + if(NOT position EQUAL -1) + set(RunCMake_TEST_FAILED "\"${flag}\" compile flag found.") + break() + endif() +endforeach() diff --git a/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake new file mode 100644 index 00000000000..8ef3a7206d2 --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake @@ -0,0 +1,9 @@ +enable_language(@lang@) + +# Make sure the compile command is not hidden. +string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}") +string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}") + +set(CMAKE_@lang@_EXTENSIONS @extensions_default@) +set(CMAKE_@lang@_STANDARD @standard_default@) +add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@") diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake index 934d8ca878d..3bfd2112a1a 100644 --- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake @@ -34,6 +34,120 @@ elseif (cxx_std_98 IN_LIST CXX_FEATURES AND cxx_std_11 IN_LIST CXX_FEATURES) unset(RunCMake_TEST_OPTIONS) endif() +configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt" "${RunCMake_BINARY_DIR}/CMakeLists.txt" COPYONLY) + +macro(test_build) + set(test ${name}-${lang}) + + configure_file("${RunCMake_SOURCE_DIR}/${name}.cmake" "${RunCMake_BINARY_DIR}/${test}.cmake" @ONLY) + if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-build-check.cmake") + configure_file("${RunCMake_SOURCE_DIR}/${name}-build-check.cmake" "${RunCMake_BINARY_DIR}/${test}-build-check.cmake" @ONLY) + endif() + if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-stderr.txt") + configure_file("${RunCMake_SOURCE_DIR}/${name}-stderr.txt" "${RunCMake_BINARY_DIR}/${test}-stderr.txt" @ONLY) + endif() + + set(RunCMake_SOURCE_DIR "${RunCMake_BINARY_DIR}") + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${test}-build") + run_cmake(${test}) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . ${ARGN}) +endmacro() + +# Mangle flags such as they're in verbose build output. +macro(mangle_flags variable) + set(result "${${variable}}") + + if(RunCMake_GENERATOR MATCHES "Visual Studio" AND MSVC_TOOLSET_VERSION GREATER_EQUAL 141) + string(REPLACE "-" "/" result "${result}") + elseif(RunCMake_GENERATOR STREQUAL "Xcode" AND CMAKE_XCODE_BUILD_SYSTEM GREATER_EQUAL 12) + string(REPLACE "=" [[\\=]] result "${result}") + endif() + + string(REPLACE ";" " " result "${result}") + list(APPEND flags "${result}") +endmacro() + +function(test_unset_standard) + if(extensions_opposite) + set(flag_ext "_EXT") + endif() + + set(flag "${${lang}${${lang}_STANDARD_DEFAULT}${flag_ext}_FLAG}") + + if(NOT flag) + return() + endif() + + mangle_flags(flag) + + set(name UnsetStandard) + set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0128=NEW) + test_build(--verbose) +endfunction() + +function(test_no_unnecessary_flag) + set(standard_flag "${${lang}${${lang}_STANDARD_DEFAULT}_FLAG}") + set(extension_flag "${${lang}${${lang}_STANDARD_DEFAULT}_EXT_FLAG}") + + if(NOT standard_flag AND NOT extension_flag) + return() + endif() + + mangle_flags(standard_flag) + mangle_flags(extension_flag) + + set(name NoUnnecessaryFlag) + set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0128=NEW) + test_build(--verbose) +endfunction() + +function(test_cmp0128_warn_match) + set(name CMP0128WarnMatch) + test_build() +endfunction() + +function(test_cmp0128_warn_unset) + # For compilers that had CMAKE_<LANG>_EXTENSION_COMPILE_OPTION (only IAR) + # there is no behavioural change and thus no warning. + if(NOT "${${lang}_EXT_FLAG}" STREQUAL "") + return() + endif() + + if(extensions_opposite) + set(opposite "enabled") + else() + set(opposite "disabled") + endif() + + set(name CMP0128WarnUnset) + test_build() +endfunction() + +function(test_lang lang ext) + if(CMake_NO_${lang}_STANDARD) + return() + endif() + + set(extensions_default "${${lang}_EXTENSIONS_DEFAULT}") + set(standard_default "${${lang}_STANDARD_DEFAULT}") + + if(extensions_default) + set(extensions_opposite OFF) + else() + set(extensions_opposite ON) + endif() + + test_unset_standard() + test_no_unnecessary_flag() + test_cmp0128_warn_match() + test_cmp0128_warn_unset() +endfunction() + +if(C_STANDARD_DEFAULT) + test_lang(C c) +endif() + if(CXX_STANDARD_DEFAULT) run_cmake(NotAStandard) @@ -47,4 +161,6 @@ if(CXX_STANDARD_DEFAULT) run_cmake(RequireCXX${standard}ExtVariable) endif() endforeach() + + test_lang(CXX cpp) endif() diff --git a/Tests/RunCMake/CompileFeatures/UnsetStandard-build-check.cmake b/Tests/RunCMake/CompileFeatures/UnsetStandard-build-check.cmake new file mode 100644 index 00000000000..abe293c34ae --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/UnsetStandard-build-check.cmake @@ -0,0 +1,12 @@ +foreach(flag @flags@) + string(FIND "${actual_stdout}" "${flag}" position) + + if(NOT position EQUAL -1) + set(found TRUE) + break() + endif() +endforeach() + +if(NOT found) + set(RunCMake_TEST_FAILED "No compile flags from \"@flags@\" found for CMAKE_@lang@_EXTENSIONS=@extensions_opposite@.") +endif() diff --git a/Tests/RunCMake/CompileFeatures/UnsetStandard.cmake b/Tests/RunCMake/CompileFeatures/UnsetStandard.cmake new file mode 100644 index 00000000000..99bb3f069aa --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/UnsetStandard.cmake @@ -0,0 +1,8 @@ +enable_language(@lang@) + +# Make sure the compile command is not hidden. +string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}") +string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}") + +set(CMAKE_@lang@_EXTENSIONS @extensions_opposite@) +add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@") diff --git a/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake b/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake index c42324b9dd3..56913448a12 100644 --- a/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake +++ b/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake @@ -1,10 +1,28 @@ enable_language(C CXX) +set(info "") + +if(MSVC_TOOLSET_VERSION) + string(APPEND info " +set(MSVC_TOOLSET_VERSION ${MSVC_TOOLSET_VERSION}) + +") +endif() + +if(CMAKE_XCODE_BUILD_SYSTEM) + string(APPEND info " +set(CMAKE_XCODE_BUILD_SYSTEM ${CMAKE_XCODE_BUILD_SYSTEM}) + +") +endif() + macro(info lang) string(APPEND info "\ set(${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_DEFAULT}) set(${lang}_EXTENSIONS_DEFAULT ${CMAKE_${lang}_EXTENSIONS_DEFAULT}) set(${lang}_FEATURES ${CMAKE_${lang}_COMPILE_FEATURES}) + +set(${lang}_EXT_FLAG ${CMAKE_${lang}_EXTENSION_COMPILE_OPTION}) ") foreach(standard ${ARGN}) diff --git a/Tests/RunCMake/CompileFeatures/empty.c b/Tests/RunCMake/CompileFeatures/empty.c index 11ec041d1ee..8d91e77d31a 100644 --- a/Tests/RunCMake/CompileFeatures/empty.c +++ b/Tests/RunCMake/CompileFeatures/empty.c @@ -1,7 +1,7 @@ #ifdef _WIN32 __declspec(dllexport) #endif - int empty() + int empty(void) { return 0; } From 32818510c885a50ec611333b657f58d3be28c5bc Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 30 Sep 2021 00:01:14 -0400 Subject: [PATCH 1321/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9fe9c752131..beb0e972a4a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210929) +set(CMake_VERSION_PATCH 20210930) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0f17b37b9612267b10ff92746578df72ccf20b76 Mon Sep 17 00:00:00 2001 From: Christophe Bernard <christophe.p.bernard@gmail.com> Date: Wed, 29 Sep 2021 21:21:56 +0200 Subject: [PATCH 1322/1519] Tutorial: Fix regexps in sample CMakeLists.txt files Replace original regexp `[-nan|nan|0]` with `(-nan|nan|0)` which is what the author most likely intended to write in the first place. --- Help/guide/tutorial/Complete/CMakeLists.txt | 2 +- Help/guide/tutorial/Step10/CMakeLists.txt | 2 +- Help/guide/tutorial/Step11/CMakeLists.txt | 2 +- Help/guide/tutorial/Step12/CMakeLists.txt | 2 +- Help/guide/tutorial/Step5/CMakeLists.txt | 2 +- Help/guide/tutorial/Step6/CMakeLists.txt | 2 +- Help/guide/tutorial/Step7/CMakeLists.txt | 2 +- Help/guide/tutorial/Step8/CMakeLists.txt | 2 +- Help/guide/tutorial/Step9/CMakeLists.txt | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt index 4d8a3ada877..ec6ff16a005 100644 --- a/Help/guide/tutorial/Complete/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/CMakeLists.txt @@ -81,7 +81,7 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") include(InstallRequiredSystemLibraries) diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt index 34ae70c2741..f4f9e050731 100644 --- a/Help/guide/tutorial/Step10/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/CMakeLists.txt @@ -63,7 +63,7 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") include(InstallRequiredSystemLibraries) diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt index 4763951c747..30580e62efe 100644 --- a/Help/guide/tutorial/Step11/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/CMakeLists.txt @@ -71,7 +71,7 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") include(InstallRequiredSystemLibraries) diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index 1b0c82667ff..64ea788569f 100644 --- a/Help/guide/tutorial/Step12/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -77,7 +77,7 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") include(InstallRequiredSystemLibraries) diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt index c3b375a3da9..fb10f575486 100644 --- a/Help/guide/tutorial/Step5/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/CMakeLists.txt @@ -62,5 +62,5 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt index c3b375a3da9..fb10f575486 100644 --- a/Help/guide/tutorial/Step6/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/CMakeLists.txt @@ -62,5 +62,5 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt index c3b375a3da9..fb10f575486 100644 --- a/Help/guide/tutorial/Step7/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/CMakeLists.txt @@ -62,5 +62,5 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt index 19b9913e95c..89972fb47c6 100644 --- a/Help/guide/tutorial/Step8/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/CMakeLists.txt @@ -62,7 +62,7 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") # setup installer diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt index d5f1cc89745..d67209acef4 100644 --- a/Help/guide/tutorial/Step9/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/CMakeLists.txt @@ -62,7 +62,7 @@ do_test(Tutorial 9 "9 is 3") do_test(Tutorial 5 "5 is 2.236") do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is [-nan|nan|0]") +do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") include(InstallRequiredSystemLibraries) From a1f0ddcbb724914005b74ca181bfd1da391df7c7 Mon Sep 17 00:00:00 2001 From: samuel100u <hsm100u@cs.ccu.edu.tw> Date: Thu, 30 Sep 2021 17:54:02 +0800 Subject: [PATCH 1323/1519] CUDA: Fix detection of implicit link information with CUDA 6.5 Fixes: #22701 --- Modules/CMakeDetermineCUDACompiler.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 342425c50e1..d06315e479c 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -441,9 +441,10 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") if("${_nvcc_output_line}" MATCHES "^ *nvlink") string(APPEND _nvcc_log " ignoring nvlink line\n") elseif(_nvcc_libraries) - if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)") + if("${_nvcc_output_line}" MATCHES "(@\"?((tmp/)?a\\.exe\\.res)\"?)") set(_nvcc_link_res_arg "${CMAKE_MATCH_1}") - set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res") + set(_nvcc_link_res_file "${CMAKE_MATCH_2}") + set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/${_nvcc_link_res_file}") if(EXISTS "${_nvcc_link_res}") file(READ "${_nvcc_link_res}" _nvcc_link_res_content) string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}") From 14600a42c8ec9af38d5b5e8a9b7d377a57cfc157 Mon Sep 17 00:00:00 2001 From: Betsy McPhail <betsy.mcphail@kitware.com> Date: Thu, 30 Sep 2021 12:04:52 -0400 Subject: [PATCH 1324/1519] Tutorial: Update Step 1 instructions To demonstrate how simple a CMake project can be, move the `Build and Run` section earlier in the step. --- .../guide/tutorial/A Basic Starting Point.rst | 70 +++++++++++++------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index 41e8479b223..cf1ec018603 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -24,6 +24,45 @@ Upper, lower, and mixed case commands are supported by CMake. The source code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be used to compute the square root of a number. +Build and Run +------------- + +That's all that is needed - we can build and run our project now! First, run +the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it +with your chosen build tool. + +For example, from the command line we could navigate to the +``Help/guide/tutorial`` directory of the CMake source code tree and create a +build directory: + +.. code-block:: console + + mkdir Step1_build + +Next, navigate to the build directory and run CMake to configure the project +and generate a native build system: + +.. code-block:: console + + cd Step1_build + cmake ../Step1 + +Then call that build system to actually compile/link the project: + +.. code-block:: console + + cmake --build . + +Finally, try to use the newly built ``Tutorial`` with these commands: + +.. code-block:: console + + Tutorial 4294967296 + Tutorial 10 + Tutorial + + Adding a Version Number and Configured Header File -------------------------------------------------- @@ -113,39 +152,24 @@ call to ``add_executable``. :language: cmake :end-before: # configure a header file to pass some of the CMake settings -Build and Test --------------- - -Run the :manual:`cmake <cmake(1)>` executable or the -:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it -with your chosen build tool. - -For example, from the command line we could navigate to the -``Help/guide/tutorial`` directory of the CMake source code tree and create a -build directory: - -.. code-block:: console +Rebuild +------- - mkdir Step1_build - -Next, navigate to the build directory and run CMake to configure the project -and generate a native build system: +Let's build our project again. We already created a build directory and ran +CMake, so we can skip to the build step: .. code-block:: console cd Step1_build - cmake ../Step1 - -Then call that build system to actually compile/link the project: - -.. code-block:: console - cmake --build . -Finally, try to use the newly built ``Tutorial`` with these commands: +Now we can try to use the newly built ``Tutorial`` with same commands as before: .. code-block:: console Tutorial 4294967296 Tutorial 10 Tutorial + +Check that the version number is now reported when running the executable without +any arguments. From 01c332c9c728cb79b8fc2d2438e798396c2e3f35 Mon Sep 17 00:00:00 2001 From: Betsy McPhail <betsy.mcphail@kitware.com> Date: Thu, 30 Sep 2021 12:18:41 -0400 Subject: [PATCH 1325/1519] Tutorial: Clarify instructions in Step 5 --- Help/guide/tutorial/Adding System Introspection.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index 7210a8dbcd7..e149110084b 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -14,11 +14,14 @@ these functions using the :module:`CheckSymbolExists` module in the ``m`` library. If ``log`` and ``exp`` are not initially found, require the ``m`` library and try again. +Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``, +after the call to :command:`target_include_directories`: + .. literalinclude:: Step6/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-check_symbol_exists :language: cmake - :start-after: # does this system provide the log and exp functions? + :start-after: # to find MathFunctions.h, while we don't. :end-before: # add compile definitions If available, use :command:`target_compile_definitions` to specify From 1bf25b5b5fe2b1c9c9667984c3cd0408244942a9 Mon Sep 17 00:00:00 2001 From: Joseph Snyder <joe.snyder@kitware.com> Date: Thu, 30 Sep 2021 13:06:20 -0400 Subject: [PATCH 1326/1519] Tutorial: Remove information about EXPORT keyword Remove the text that implies that the EXPORT keyword will also install the generated CMake file. --- Help/guide/tutorial/Adding Export Configuration.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index e5ab6a2266d..b54c154ca30 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -12,10 +12,10 @@ packaged. The first step is to update our :command:`install(TARGETS)` commands to not only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword -generates and installs a CMake file containing code to import all targets -listed in the install command from the installation tree. So let's go ahead and -explicitly ``EXPORT`` the ``MathFunctions`` library by updating the ``install`` -command in ``MathFunctions/CMakeLists.txt`` to look like: +generates a CMake file containing code to import all targets listed in the +install command from the installation tree. So let's go ahead and explicitly +``EXPORT`` the ``MathFunctions`` library by updating the ``install`` command +in ``MathFunctions/CMakeLists.txt`` to look like: .. literalinclude:: Complete/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt From 6dade88d1ccafc08539ec11b02770764b917f004 Mon Sep 17 00:00:00 2001 From: Joseph Snyder <joe.snyder@kitware.com> Date: Thu, 30 Sep 2021 14:43:28 -0400 Subject: [PATCH 1327/1519] Tutorial: Add documentation on Package helper functions Add documentation for the configure_package_config_file() and write_basic_package_version_file() commands. Update the comment for the installation of those files to allow a stopping point for the code display. Issue: #22663 --- .../tutorial/Adding Export Configuration.rst | 40 +++++++++++++++++++ Help/guide/tutorial/Step12/CMakeLists.txt | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index b54c154ca30..3bd6d64642b 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -82,6 +82,46 @@ bottom of the top-level ``CMakeLists.txt``: :name: CMakeLists.txt-install-Config.cmake :language: cmake :start-after: # install the configuration targets + :end-before: # generate the config file + + +Next, we execute the :command:`configure_package_config_file`. This command +will configure a provided file but with a few specific differences from the +standard :command:`configure_file` way. +To properly utilize this function, the input file should have a single line +with the text ``@PACKAGE_INIT@`` in addition to the content that is desired. +That variable will be replaced with a block of code which turns set values into +relative paths. These values which are new can be referenced by the same name +but prepended with a ``PACKAGE_`` prefix. + +.. literalinclude:: Step12/CMakeLists.txt + :caption: CMakeLists.txt + :name: CMakeLists.txt-configure-package-config.cmake + :language: cmake + :start-after: # install the configuration targets + :end-before: # generate the version file + +The :command:`write_basic_package_version_file` is next. This command writes +a file which is used by the "find_package" document the version and +compatibility of the desired package. Here, we use the ``Tutorial_VERSION_*`` +variables and say that it is compatible with ``AnyNewerVersion``, which +denotes that this version or any higher one are compatible with the requested +version. + +.. literalinclude:: Step12/CMakeLists.txt + :caption: CMakeLists.txt + :name: CMakeLists.txt-basic-version-file.cmake + :language: cmake + :start-after: # generate the version file + :end-before: # install the generated configuration files + +Finally, set both generated files to be installed: + +.. literalinclude:: Step12/CMakeLists.txt + :caption: CMakeLists.txt + :name: CMakeLists.txt-install-configured-files.cmake + :language: cmake + :start-after: # install the generated configuration files :end-before: # generate the export At this point, we have generated a relocatable CMake Configuration for our diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index 1b0c82667ff..6c51b29be28 100644 --- a/Help/guide/tutorial/Step12/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -107,7 +107,7 @@ write_basic_package_version_file( COMPATIBILITY AnyNewerVersion ) -# install the configuration file +# install the generated configuration files install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake From 8f7e98ef09085011e92b3dfeb8aaf60f31bc9270 Mon Sep 17 00:00:00 2001 From: Seth R Johnson <johnsonsr@ornl.gov> Date: Thu, 30 Sep 2021 15:36:18 -0400 Subject: [PATCH 1328/1519] cmInstallTargetGenerator: optimize rpath adjustments With builds that have many internal library directories or many external libraries, rpaths can be quite large. The cost of calling install_name_tool thousands of times can add up to minutes on a build, especially if virus scanning software is there to help you out. With this change, instead of deleting and then re-adding an rpath, we ignore it. Likewise we batch all the rpath adjustment calls into a single command. Before, installing SCALE (some libraries have 70+ build-time RPATHs that get deleted, plus up to a dozen external RPATHs from upstream dependencies that should remain in the binary) would take almost 9 minutes on my laptop, and after this change the installation takes only 30 second. --- Source/cmInstallTargetGenerator.cxx | 65 +++++++++++++++++++---------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 2f974c46e0a..ae11afca9a6 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -2,11 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallTargetGenerator.h" +#include <algorithm> #include <cassert> #include <map> #include <set> #include <sstream> #include <utility> +#include <vector> #include "cmComputeLinkInformation.h" #include "cmGeneratorExpression.h" @@ -680,33 +682,52 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( " this limitation."; mf->IssueMessage(MessageType::WARNING, msg.str()); } else { - // Note: These paths are kept unique to avoid - // install_name_tool corruption. - std::set<std::string> runpaths; - for (std::string const& i : oldRuntimeDirs) { - std::string runpath = - mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config); - - if (runpaths.find(runpath) == runpaths.end()) { - runpaths.insert(runpath); - os << indent << "execute_process(COMMAND " << installNameTool - << "\n"; - os << indent << " -delete_rpath \"" << runpath << "\"\n"; - os << indent << " \"" << toDestDirPath << "\")\n"; + // To be consistent with older versions, runpath changes must be ordered, + // deleted first, then added, *and* the same path must only appear once. + std::map<std::string, std::string> runpath_change; + std::vector<std::string> ordered; + for (std::string const& dir : oldRuntimeDirs) { + // Normalize path and add to map of changes to make + auto iter_inserted = runpath_change.insert( + { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config), + "delete" }); + if (iter_inserted.second) { + // Add path to ordered list of changes + ordered.push_back(iter_inserted.first->first); } } - runpaths.clear(); - for (std::string const& i : newRuntimeDirs) { - std::string runpath = - mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config); + for (std::string const& dir : newRuntimeDirs) { + // Normalize path and add to map of changes to make + auto iter_inserted = runpath_change.insert( + { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config), "add" }); + if (iter_inserted.second) { + // Add path to ordered list of changes + ordered.push_back(iter_inserted.first->first); + } else if (iter_inserted.first->second != "add") { + // Rpath was requested to be deleted and then later re-added. Drop it + // from the list by marking as an empty value. + iter_inserted.first->second.clear(); + } + } - if (runpaths.find(runpath) == runpaths.end()) { - os << indent << "execute_process(COMMAND " << installNameTool - << "\n"; - os << indent << " -add_rpath \"" << runpath << "\"\n"; - os << indent << " \"" << toDestDirPath << "\")\n"; + // Remove rpaths that are unchanged (value was set to empty) + ordered.erase( + std::remove_if(ordered.begin(), ordered.end(), + [&runpath_change](const std::string& runpath) { + return runpath_change.find(runpath)->second.empty(); + }), + ordered.end()); + + if (!ordered.empty()) { + os << indent << "execute_process(COMMAND " << installNameTool << "\n"; + for (std::string const& runpath : ordered) { + // Either 'add_rpath' or 'delete_rpath' since we've removed empty + // entries + os << indent << " -" << runpath_change.find(runpath)->second + << "_rpath \"" << runpath << "\"\n"; } + os << indent << " \"" << toDestDirPath << "\")\n"; } } } else { From 77c237d21943363ebe17b9fefe5ef1e62fa374a1 Mon Sep 17 00:00:00 2001 From: makise-homura <akemi_homura@kurisa.ch> Date: Thu, 30 Sep 2021 21:34:57 +0300 Subject: [PATCH 1329/1519] zstd: Fix incorrect pragma error on LCC compiler LCC (Elbrus C Compiler) doesn't understand some of GCC pragmas, despite of declaring itself GCC-aware. The pragma of subject is the one that forbids vectorizing. Actually, LCC don't vectorize anything unless explicitly said to, so this pragma may be safely omitted and thus not cause an error. This patch does this. --- Utilities/cmzstd/lib/common/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/cmzstd/lib/common/compiler.h b/Utilities/cmzstd/lib/common/compiler.h index 95e9483521d..1b864eaeebd 100644 --- a/Utilities/cmzstd/lib/common/compiler.h +++ b/Utilities/cmzstd/lib/common/compiler.h @@ -139,7 +139,7 @@ /* vectorization * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ -#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) +#if !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__LCC__) && defined(__GNUC__) # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) # else From b3a0bddc4e1c8f1f86078cdffaebbc4c493e4409 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 1 Oct 2021 00:01:25 -0400 Subject: [PATCH 1330/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index beb0e972a4a..cf85089e125 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210930) +set(CMake_VERSION_PATCH 20211001) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 5329366527f5e03cdafe4f7ad55482d513bf2fd7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 1 Oct 2021 10:21:39 -0400 Subject: [PATCH 1331/1519] ci: update cuda9.2 base image after DST Root CA X3 expiry --- .gitlab/ci/docker/cuda9.2/install_deps.sh | 6 ++++++ .gitlab/os-linux.yml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitlab/ci/docker/cuda9.2/install_deps.sh b/.gitlab/ci/docker/cuda9.2/install_deps.sh index 146f98255c1..0dcb507e66b 100755 --- a/.gitlab/ci/docker/cuda9.2/install_deps.sh +++ b/.gitlab/ci/docker/cuda9.2/install_deps.sh @@ -4,6 +4,12 @@ set -e apt-get update +# Update base packages. +apt-get install -y \ + libgnutls30 \ + libssl1.0.0 \ + openssl + # Install development tools. apt-get install -y \ g++ \ diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 1513c904dc1..948775ca7a7 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -209,7 +209,7 @@ ### CUDA builds .cuda9.2: - image: "kitware/cmake:ci-cuda9.2-x86_64-2021-07-01" + image: "kitware/cmake:ci-cuda9.2-x86_64-2021-10-01" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" From 2a00e5072d0639a4b88bee811df2c5acce37ea62 Mon Sep 17 00:00:00 2001 From: Seth R Johnson <johnsonsr@ornl.gov> Date: Thu, 30 Sep 2021 21:48:26 -0400 Subject: [PATCH 1332/1519] FortranCInterface: Fix regression in timestamp check Since commit d7c8030541 (FortranCInterface: Fix misuse of IS_NEWER_THAN in timestamp check, 2021-02-21, v3.21.0-rc1~631^2~3), FortranCInterface checks for `Output.cmake.in` in the build tree instead of the source tree as before. This caused it to always re-run the detection. Fixes: #22709 --- Modules/FortranCInterface/Detect.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 9e5726b03a0..4d3cb005a7c 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -8,11 +8,10 @@ configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in # configuration changes. if(NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Input.cmake - OR NOT EXISTS ${FortranCInterface_BINARY_DIR}/Output.cmake.in OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Input.cmake OR NOT ${FortranCInterface_SOURCE_DIR}/Output.cmake - IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake.in + IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/Output.cmake.in OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake IS_NEWER_THAN ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt OR NOT ${FortranCInterface_BINARY_DIR}/Output.cmake From d6746fd05c92a8edb94de746846227e6101fc05e Mon Sep 17 00:00:00 2001 From: makise-homura <akemi_homura@kurisa.ch> Date: Thu, 30 Sep 2021 21:30:06 +0300 Subject: [PATCH 1333/1519] cmMakefile: Fix compilation on EDG-based compilers such as LCC Compilers based on EDG frontend sometimes throw an internal error while using `this->` at some circumstances. While it is up to be fixed in future versions of front end, this bug still occurs in some modern compilers, such as LCC for Elbrus CPUs, and probably others (maybe ICC). It caused CMake to be unbuildable by these compilers. This patch fixes it. --- Source/cmMakefile.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index a490dacc6c0..83984f7a300 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3982,11 +3982,10 @@ cmValue cmMakefile::GetProperty(const std::string& prop) const if (prop == "TESTS") { std::vector<std::string> keys; // get list of keys - std::transform(this->Tests.begin(), this->Tests.end(), - std::back_inserter(keys), - [](decltype(this->Tests)::value_type const& pair) { - return pair.first; - }); + const auto* t = this; + std::transform( + t->Tests.begin(), t->Tests.end(), std::back_inserter(keys), + [](decltype(t->Tests)::value_type const& pair) { return pair.first; }); output = cmJoin(keys, ";"); return cmValue(output); } From b75f77853149760e48e4f6e765f5b31de1c9600d Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" <ferdnyc@gmail.com> Date: Sat, 25 Sep 2021 02:23:51 -0400 Subject: [PATCH 1334/1519] Help: Detailed version tags for compiler known features --- Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst | 2 ++ Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst | 6 ++++++ Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst | 14 +++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst index 6bbb870f151..3a1797356b0 100644 --- a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst @@ -32,4 +32,6 @@ The features known to this version of CMake are: Compiler mode is at least CUDA/C++ 20. ``cuda_std_23`` + .. versionadded:: 3.20 + Compiler mode is at least CUDA/C++ 23. diff --git a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst index 73c0b34eef6..1a913fb65dd 100644 --- a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst @@ -18,6 +18,8 @@ The features known to this version of CMake are listed below. High level meta features indicating C++ standard support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. versionadded:: 3.8 + The following meta features indicate general support for the associated language standard. It reflects the language support claimed by the compiler, but it does not necessarily imply complete conformance to that standard. @@ -35,9 +37,13 @@ but it does not necessarily imply complete conformance to that standard. Compiler mode is at least C++ 17. ``cxx_std_20`` + .. versionadded:: 3.12 + Compiler mode is at least C++ 20. ``cxx_std_23`` + .. versionadded:: 3.20 + Compiler mode is at least C++ 23. Low level individual compile features diff --git a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst index 2bd0febeaa0..97da697e052 100644 --- a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst @@ -13,7 +13,12 @@ The features listed here may be used with the :command:`target_compile_features` command. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. -The features known to this version of CMake are: +The features known to this version of CMake are listed below. + +High level meta features indicating C standard support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.8 ``c_std_90`` Compiler mode is at least C 90. @@ -25,11 +30,18 @@ The features known to this version of CMake are: Compiler mode is at least C 11. ``c_std_17`` + .. versionadded:: 3.21 + Compiler mode is at least C 17. ``c_std_23`` + .. versionadded:: 3.21 + Compiler mode is at least C 23. +Low level individual compile features +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ``c_function_prototypes`` Function prototypes, as defined in ``ISO/IEC 9899:1990``. From be604bec8dfffb2f68e898b4d68b2fcf03e54cea Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sat, 2 Oct 2021 00:01:09 -0400 Subject: [PATCH 1335/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index cf85089e125..67d5a26e2b9 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211001) +set(CMake_VERSION_PATCH 20211002) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 589c6c8e3f440336e4acc73357a941a054dac082 Mon Sep 17 00:00:00 2001 From: Felipe Torrezan <felipe.torrezan@iar.com> Date: Sat, 2 Oct 2021 21:35:18 +0200 Subject: [PATCH 1336/1519] IAR: added .S extension for IAR-ASM.cmake --- Modules/Compiler/IAR-ASM.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake index 750ac2f6323..bae0fbd8ca5 100644 --- a/Modules/Compiler/IAR-ASM.cmake +++ b/Modules/Compiler/IAR-ASM.cmake @@ -25,7 +25,7 @@ set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> ${_CMAKE_IAR_SILENCER_FLAG} < if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS) __compiler_iar_ilink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S) elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_XTOOLS) __compiler_iar_xlink(ASM) From fae0b9fb710712c1f07940658daa40e099115499 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Sun, 3 Oct 2021 00:01:10 -0400 Subject: [PATCH 1337/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 67d5a26e2b9..a26f8b28444 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211002) +set(CMake_VERSION_PATCH 20211003) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 8dee2c3aee3495fcb4df3f41e4a31aa7ffc38567 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Mon, 4 Oct 2021 00:01:32 -0400 Subject: [PATCH 1338/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a26f8b28444..7a69f8d8c60 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211003) +set(CMake_VERSION_PATCH 20211004) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 2a82bd85b66f5de2acaac60159c9b624da37ce37 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 4 Oct 2021 21:46:46 +1100 Subject: [PATCH 1339/1519] Help: Add documentation for CMAKE_TLS_CAINFO --- Help/command/file.rst | 5 +++-- Help/manual/cmake-variables.7.rst | 1 + Help/variable/CMAKE_TLS_CAINFO.rst | 9 +++++++++ Modules/ExternalProject.cmake | 8 ++++---- 4 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 Help/variable/CMAKE_TLS_CAINFO.rst diff --git a/Help/command/file.rst b/Help/command/file.rst index 96a55ee8018..798f50753ee 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -1113,8 +1113,9 @@ If neither ``NETRC`` option is given CMake will check variables For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL`` certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to -check certificates. If neither ``TLS`` option is given CMake will check -variables :variable:`CMAKE_TLS_VERIFY` and ``CMAKE_TLS_CAINFO``, respectively. +check certificates. If neither ``TLS`` option is given, CMake will use the +settings from the :variable:`CMAKE_TLS_VERIFY` and :variable:`CMAKE_TLS_CAINFO` +variables instead. Additional options to ``DOWNLOAD`` are: diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 7cfa0c8f083..63ea5ac3405 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -247,6 +247,7 @@ Variables that Change Behavior /variable/CMAKE_SYSTEM_LIBRARY_PATH /variable/CMAKE_SYSTEM_PREFIX_PATH /variable/CMAKE_SYSTEM_PROGRAM_PATH + /variable/CMAKE_TLS_CAINFO /variable/CMAKE_TLS_VERIFY /variable/CMAKE_USER_MAKE_RULES_OVERRIDE /variable/CMAKE_WARN_DEPRECATED diff --git a/Help/variable/CMAKE_TLS_CAINFO.rst b/Help/variable/CMAKE_TLS_CAINFO.rst new file mode 100644 index 00000000000..fe3433527b1 --- /dev/null +++ b/Help/variable/CMAKE_TLS_CAINFO.rst @@ -0,0 +1,9 @@ +CMAKE_TLS_CAINFO +---------------- + +Specify the default value for the :command:`file(DOWNLOAD)` and +:command:`file(UPLOAD)` commands' ``TLS_CAINFO`` options. +It is unset by default. + +This variable is also used by the :module:`ExternalProject` module +for internal calls to :command:`file(DOWNLOAD)`. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 9e25beecace..e49faae183e 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -224,14 +224,14 @@ External Project Definition ``TLS_CAINFO <file>`` Specify a custom certificate authority file to use if ``TLS_VERIFY`` is enabled. If this option is not specified, the value of the - ``CMAKE_TLS_CAINFO`` variable will be used instead (see + :variable:`CMAKE_TLS_CAINFO` variable will be used instead (see :command:`file(DOWNLOAD)`) ``NETRC <level>`` .. versionadded:: 3.11 Specify whether the ``.netrc`` file is to be used for operation. - If this option is not specified, the value of the ``CMAKE_NETRC`` + If this option is not specified, the value of the :variable:`CMAKE_NETRC` variable will be used instead (see :command:`file(DOWNLOAD)`) Valid levels are: @@ -251,8 +251,8 @@ External Project Definition Specify an alternative ``.netrc`` file to the one in your home directory if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option - is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will - be used instead (see :command:`file(DOWNLOAD)`) + is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable + will be used instead (see :command:`file(DOWNLOAD)`) .. versionadded:: 3.1 Added support for `tbz2`, `.tar.xz`, `.txz`, and `.7z` extensions. From 96937438b74469eea5b0ae46b4e13489ac3faec7 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 4 Oct 2021 22:01:48 +1100 Subject: [PATCH 1340/1519] Help: Clean up how TLS and NETRC variables are discussed Mention of the fallback of the command options to the CMAKE_... variables was repeated in places. The wording was also a bit unclear about whether the fallback only occurred when neither TLS or neither NETRC option was given to the command. Move the fallback details directly to each relevant option instead. Also use cross-referencing to the variables where it was not linked previously. --- Help/command/file.rst | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Help/command/file.rst b/Help/command/file.rst index 798f50753ee..5a3fd883bc1 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -1073,7 +1073,7 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are: .. versionadded:: 3.11 Specify whether the .netrc file is to be used for operation. If this - option is not specified, the value of the ``CMAKE_NETRC`` variable + option is not specified, the value of the :variable:`CMAKE_NETRC` variable will be used instead. Valid levels are: @@ -1092,30 +1092,28 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are: Specify an alternative .netrc file to the one in your home directory, if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option - is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will + is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable will be used instead. -If neither ``NETRC`` option is given CMake will check variables -``CMAKE_NETRC`` and ``CMAKE_NETRC_FILE``, respectively. - ``TLS_VERIFY <ON|OFF>`` Specify whether to verify the server certificate for ``https://`` URLs. - The default is to *not* verify. + The default is to *not* verify. If this option is not specified, the value + of the :variable:`CMAKE_TLS_VERIFY` variable will be used instead. .. versionadded:: 3.18 Added support to ``file(UPLOAD)``. ``TLS_CAINFO <file>`` - Specify a custom Certificate Authority file for ``https://`` URLs. + Specify a custom Certificate Authority file for ``https://`` URLs. If this + option is not specified, the value of the :variable:`CMAKE_TLS_CAINFO` + variable will be used instead. .. versionadded:: 3.18 Added support to ``file(UPLOAD)``. For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL`` certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to -check certificates. If neither ``TLS`` option is given, CMake will use the -settings from the :variable:`CMAKE_TLS_VERIFY` and :variable:`CMAKE_TLS_CAINFO` -variables instead. +check certificates. Additional options to ``DOWNLOAD`` are: From a7420884723c4fb09e6370fb25710a2172c10a0c Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 4 Oct 2021 22:10:56 +1100 Subject: [PATCH 1341/1519] Tests: Add support for testing Qt6 The minimum CMake version for Qt6 is 3.16, so all the calls to cmake_minimum_required() are updated here to enforce that minimum. This will avoid any CMake version-related warnings from Qt. Avoid hard-coding Qt5 where the tests could now be using Qt5 or Qt6. Fixes: #22188 --- .gitlab/artifacts.yml | 2 +- Tests/CMakeLists.txt | 10 +++ Tests/Qt6Autogen/CMakeLists.txt | 8 +++ Tests/QtAutogen/AutogenCoreTest.cmake | 16 ++--- Tests/QtAutogen/AutogenGuiTest.cmake | 16 ++--- .../AutogenOriginDependsOff/CMakeLists.txt | 2 +- .../AutogenOriginDependsOn/CMakeLists.txt | 2 +- .../AutogenTargetDepends/CMakeLists.txt | 2 +- Tests/QtAutogen/Complex/CMakeLists.txt | 4 +- Tests/QtAutogen/Complex/codeeditor.cpp | 4 ++ .../GlobalAutogenTarget/CMakeLists.txt | 3 +- .../GlobalAutogenTarget/GAT/CMakeLists.txt | 4 +- Tests/QtAutogen/MacOsFW/CMakeLists.txt | 22 ++++--- Tests/QtAutogen/MacOsFW/src/CMakeLists.txt | 6 +- Tests/QtAutogen/MacOsFW/test/CMakeLists.txt | 12 ++-- Tests/QtAutogen/ManySources/CMakeLists.txt | 2 +- Tests/QtAutogen/MocCMP0071/CMakeLists.txt | 2 +- Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt | 1 - Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt | 1 - Tests/QtAutogen/MocCMP0100/CMakeLists.txt | 2 +- Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt | 1 - Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt | 1 - Tests/QtAutogen/MocInclude/CMakeLists.txt | 2 +- .../MocIncludeSymlink/CMakeLists.txt | 3 +- Tests/QtAutogen/MocMacroName/CMakeLists.txt | 2 +- Tests/QtAutogen/MocOnly/CMakeLists.txt | 2 +- Tests/QtAutogen/MocOptions/CMakeLists.txt | 2 +- Tests/QtAutogen/MocOsMacros/CMakeLists.txt | 6 +- Tests/QtAutogen/MocSkipSource/CMakeLists.txt | 2 +- Tests/QtAutogen/ObjectLibrary/CMakeLists.txt | 4 +- .../QtAutogen/ObjectLibrary/a/CMakeLists.txt | 2 +- Tests/QtAutogen/Parallel/CMakeLists.txt | 2 +- Tests/QtAutogen/Parallel1/CMakeLists.txt | 2 +- Tests/QtAutogen/Parallel2/CMakeLists.txt | 2 +- Tests/QtAutogen/Parallel3/CMakeLists.txt | 2 +- Tests/QtAutogen/Parallel4/CMakeLists.txt | 2 +- Tests/QtAutogen/ParallelAUTO/CMakeLists.txt | 2 +- Tests/QtAutogen/RccEmpty/CMakeLists.txt | 2 +- .../QtAutogen/RccOffMocLibrary/CMakeLists.txt | 8 +-- Tests/QtAutogen/RccOnly/CMakeLists.txt | 2 +- Tests/QtAutogen/RccSkipSource/CMakeLists.txt | 2 +- Tests/QtAutogen/RerunMocBasic/CMakeLists.txt | 3 +- .../RerunMocBasic/MocBasic/CMakeLists.txt | 2 +- .../RerunMocOnAddFile/CMakeLists.txt | 3 +- .../MocOnAddFile/CMakeLists.txt.in | 2 +- .../CMakeLists.txt | 9 +-- Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt | 3 +- .../RerunMocPlugin/MocPlugin/CMakeLists.txt | 4 +- .../RerunRccConfigChange/CMakeLists.txt | 3 +- .../RccConfigChange/CMakeLists.txt | 2 +- .../QtAutogen/RerunRccDepends/CMakeLists.txt | 3 +- .../RerunRccDepends/RccDepends/CMakeLists.txt | 2 +- .../RerunUicOnFileChange/CMakeLists.txt | 1 + .../UicOnFileChange/CMakeLists.txt.in | 2 +- .../StaticLibraryCycle/CMakeLists.txt | 2 +- Tests/QtAutogen/TestMacros.cmake | 11 +++- Tests/QtAutogen/UicInclude/CMakeLists.txt | 2 +- Tests/QtAutogen/UicInterface/CMakeLists.txt | 6 +- Tests/QtAutogen/UicNoGui/CMakeLists.txt | 2 +- Tests/QtAutogen/UicOnly/CMakeLists.txt | 2 +- Tests/QtAutogen/UicSkipSource/CMakeLists.txt | 2 +- .../CMP0111-imported-target-prelude.cmake | 2 +- Tests/RunCMake/Autogen/CMakeLists.txt | 2 +- Tests/RunCMake/Autogen/QtInFunction.cmake | 6 +- .../RunCMake/Autogen/QtInFunctionNested.cmake | 6 +- .../Autogen/QtInFunctionProperty.cmake | 6 +- Tests/RunCMake/Autogen/RunCMakeTest.cmake | 8 ++- Tests/RunCMake/CMakeLists.txt | 64 +++++++++++++++---- Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake | 21 ------ Tests/RunCMake/Ninja/QtAutoMocDeps.cmake | 27 ++++++++ Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt | 2 +- Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt | 2 +- Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt | 2 +- Tests/RunCMake/Ninja/RunCMakeTest.cmake | 21 ++++-- ...txt => QtX-automoc-check-ninja-stdout.txt} | 0 ...-debug-in-release-graph-build-check.cmake} | 0 .../NinjaMultiConfig/{Qt5.cmake => QtX.cmake} | 9 ++- .../NinjaMultiConfig/RunCMakeTest.cmake | 20 ++++-- 78 files changed, 272 insertions(+), 166 deletions(-) create mode 100644 Tests/Qt6Autogen/CMakeLists.txt delete mode 100644 Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake create mode 100644 Tests/RunCMake/Ninja/QtAutoMocDeps.cmake rename Tests/RunCMake/NinjaMultiConfig/{Qt5-automoc-check-ninja-stdout.txt => QtX-automoc-check-ninja-stdout.txt} (100%) rename Tests/RunCMake/NinjaMultiConfig/{Qt5-debug-in-release-graph-build-check.cmake => QtX-debug-in-release-graph-build-check.cmake} (100%) rename Tests/RunCMake/NinjaMultiConfig/{Qt5.cmake => QtX.cmake} (77%) diff --git a/.gitlab/artifacts.yml b/.gitlab/artifacts.yml index 45e4c5b526d..982f50b3bdb 100644 --- a/.gitlab/artifacts.yml +++ b/.gitlab/artifacts.yml @@ -56,7 +56,7 @@ # Test directories. - build/Tests/CTest* - build/Tests/Find* - - build/Tests/Qt5* + - build/Tests/Qt* - build/Tests/RunCMake/ - build/Tests/CMakeOnly/ - build/Tests/CMakeTests/ diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index da6b6704bcc..20b6e251e7d 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -257,6 +257,13 @@ if(BUILD_TESTING) #--------------------------------------------------------------------------- # Add tests below here. + if(NOT DEFINED CMake_TEST_Qt6) + set(CMake_TEST_Qt6 1) + endif() + if(CMake_TEST_Qt6) + find_package(Qt6 COMPONENTS Core Widgets QUIET NO_MODULE) + endif() + if(NOT DEFINED CMake_TEST_Qt5) set(CMake_TEST_Qt5 1) endif() @@ -1384,6 +1391,9 @@ if(BUILD_TESTING) ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt") + if(CMake_TEST_Qt6 AND Qt6Widgets_FOUND) + add_subdirectory(Qt6Autogen) + endif() if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND) add_subdirectory(Qt5Autogen) endif() diff --git a/Tests/Qt6Autogen/CMakeLists.txt b/Tests/Qt6Autogen/CMakeLists.txt new file mode 100644 index 00000000000..a603b50818c --- /dev/null +++ b/Tests/Qt6Autogen/CMakeLists.txt @@ -0,0 +1,8 @@ +# Set Qt test version and include the Autogen test macros +set(QT_TEST_VERSION 6) +include("../QtAutogen/TestMacros.cmake") + +# Common tests +include("../QtAutogen/Tests.cmake") + +set(TEST_BUILD_DIRS "${TEST_BUILD_DIRS}" PARENT_SCOPE) diff --git a/Tests/QtAutogen/AutogenCoreTest.cmake b/Tests/QtAutogen/AutogenCoreTest.cmake index 58038592851..e62a6aac4c6 100644 --- a/Tests/QtAutogen/AutogenCoreTest.cmake +++ b/Tests/QtAutogen/AutogenCoreTest.cmake @@ -21,27 +21,27 @@ if (QT_TEST_VERSION EQUAL 4) qt4_generate_moc(${ARGN}) endmacro() -elseif(QT_TEST_VERSION EQUAL 5) +elseif(QT_TEST_VERSION GREATER_EQUAL 5) - find_package(Qt5Core REQUIRED) + find_package(Qt${QT_TEST_VERSION}Core REQUIRED) - set(QT_QTCORE_TARGET Qt5::Core) - set(QT_LIBRARIES Qt5::Core) + set(QT_QTCORE_TARGET Qt${QT_TEST_VERSION}::Core) + set(QT_LIBRARIES Qt${QT_TEST_VERSION}::Core) # Include directories - include_directories(${Qt5Core_INCLUDE_DIRS}) + include_directories(${Qt${QT_TEST_VERSION}Core_INCLUDE_DIRS}) # Definitions - if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + if(Qt${QT_TEST_VERSION}_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) endif() # Qt macros macro(qtx_wrap_cpp) - qt5_wrap_cpp(${ARGN}) + cmake_language(CALL qt${QT_TEST_VERSION}_wrap_cpp ${ARGN}) endmacro() macro(qtx_generate_moc) - qt5_generate_moc(${ARGN}) + cmake_language(CALL qt${QT_TEST_VERSION}_generate_moc ${ARGN}) endmacro() else() diff --git a/Tests/QtAutogen/AutogenGuiTest.cmake b/Tests/QtAutogen/AutogenGuiTest.cmake index b76d341a458..e5eb7510c0d 100644 --- a/Tests/QtAutogen/AutogenGuiTest.cmake +++ b/Tests/QtAutogen/AutogenGuiTest.cmake @@ -21,27 +21,27 @@ if (QT_TEST_VERSION EQUAL 4) qt4_generate_moc(${ARGN}) endmacro() -elseif(QT_TEST_VERSION EQUAL 5) +elseif(QT_TEST_VERSION GREATER_EQUAL 5) - find_package(Qt5Widgets REQUIRED) + find_package(Qt${QT_TEST_VERSION}Widgets REQUIRED) - set(QT_QTCORE_TARGET Qt5::Core) - set(QT_LIBRARIES Qt5::Widgets) + set(QT_QTCORE_TARGET Qt${QT_TEST_VERSION}::Core) + set(QT_LIBRARIES Qt${QT_TEST_VERSION}::Widgets) # Include directories - include_directories(${Qt5Widgets_INCLUDE_DIRS}) + include_directories(${Qt${QT_TEST_VERSION}Widgets_INCLUDE_DIRS}) # Definitions - if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + if(Qt${QT_TEST_VERSION}_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) endif() # Qt macros macro(qtx_wrap_cpp) - qt5_wrap_cpp(${ARGN}) + cmake_language(CALL qt${QT_TEST_VERSION}_wrap_cpp ${ARGN}) endmacro() macro(qtx_generate_moc) - qt5_generate_moc(${ARGN}) + cmake_language(CALL qt${QT_TEST_VERSION}_generate_moc ${ARGN}) endmacro() else() diff --git a/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt b/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt index 17855ffd88e..cac680f87e1 100644 --- a/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt +++ b/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.16) project(AutogenOriginDependsOff) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt b/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt index 5aabe0e682f..37ce90b93ca 100644 --- a/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt +++ b/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(AutogenOriginDependsOn) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt b/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt index 492b5dbd3fd..cf3f155679e 100644 --- a/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt +++ b/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(AutogenTargetDepends) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/Complex/CMakeLists.txt b/Tests/QtAutogen/Complex/CMakeLists.txt index d9fdf5cf4d6..8a9a5d29a96 100644 --- a/Tests/QtAutogen/Complex/CMakeLists.txt +++ b/Tests/QtAutogen/Complex/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(Complex) include("../AutogenGuiTest.cmake") @@ -16,6 +16,8 @@ add_library(privateSlot OBJECT private_slot.cpp) # Pass Qt compiler features to targets that don't link against Qt target_compile_features(codeeditorLib PRIVATE ${QT_COMPILE_FEATURES}) target_compile_features(privateSlot PRIVATE ${QT_COMPILE_FEATURES}) +target_link_libraries(codeeditorLib PRIVATE ${QT_LIBRARIES}) +target_link_libraries(privateSlot PRIVATE ${QT_LIBRARIES}) configure_file(generated_resource.qrc.in generated_resource.qrc @ONLY) add_custom_command( diff --git a/Tests/QtAutogen/Complex/codeeditor.cpp b/Tests/QtAutogen/Complex/codeeditor.cpp index 80d6a550956..9c9dbc3231a 100644 --- a/Tests/QtAutogen/Complex/codeeditor.cpp +++ b/Tests/QtAutogen/Complex/codeeditor.cpp @@ -70,7 +70,11 @@ int CodeEditor::lineNumberAreaWidth() ++digits; } +#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits; +#else int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; +#endif return space; } diff --git a/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt b/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt index e95c626e70b..5c70e4336b9 100644 --- a/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt +++ b/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.16) project(GlobalAutogenTarget) include("../AutogenCoreTest.cmake") @@ -74,6 +74,7 @@ execute_process( -T "${CMAKE_GENERATOR_TOOLSET}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" WORKING_DIRECTORY "${GAT_BDIR}" OUTPUT_VARIABLE output diff --git a/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt b/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt index 3925197fe9b..0e3df6f43b0 100644 --- a/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt +++ b/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.16) project(GAT) include("../../AutogenCoreTest.cmake") @@ -9,7 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -# Disable ORIGN_DEPENDS and enable AUTOGEN global targets +# Disable ORIGIN_DEPENDS and enable AUTOGEN global targets set(CMAKE_AUTOGEN_ORIGIN_DEPENDS OFF) set(CMAKE_GLOBAL_AUTOGEN_TARGET ON) set(CMAKE_GLOBAL_AUTORCC_TARGET ON) diff --git a/Tests/QtAutogen/MacOsFW/CMakeLists.txt b/Tests/QtAutogen/MacOsFW/CMakeLists.txt index c08efc47a20..27c5f433bf4 100644 --- a/Tests/QtAutogen/MacOsFW/CMakeLists.txt +++ b/Tests/QtAutogen/MacOsFW/CMakeLists.txt @@ -1,21 +1,23 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MacOsFW) include("../AutogenGuiTest.cmake") -find_package(Qt5Test REQUIRED) +find_package(Qt${QT_TEST_VERSION}Test REQUIRED) + +if(QT_TEST_VERSION EQUAL 5) + set(CMAKE_CXX_STANDARD 11) +elseif(QT_TEST_VERSION EQUAL 6) + set(CMAKE_CXX_STANDARD 17) +else() + message(FATAL_ERROR "Unsupported Qt version: ${QT_TEST_VERSION}") +endif() -set(CMAKE_CXX_STANDARD 11) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output/lib) set(CMAKE_INSTALL_NAME_DIR ${CMAKE_BINARY_DIR}/output/lib) -if(POLICY CMP0042) # in CMake 3.0.0+ - set (CMAKE_MACOSX_RPATH OFF) # otherwise ON by default -endif(POLICY CMP0042) - -if(POLICY CMP0068) # in CMake 3.9+ - cmake_policy(SET CMP0068 NEW) -endif(POLICY CMP0068) +set (CMAKE_MACOSX_RPATH OFF) # otherwise ON by default +cmake_policy(SET CMP0068 NEW) add_subdirectory(src) add_subdirectory(test) diff --git a/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt b/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt index a02be00c588..67e2c8a8a0b 100644 --- a/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt +++ b/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt @@ -9,7 +9,7 @@ set(MACOS_FW_LIB_HDRS include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} - ${Qt5Core_INCLUDE_DIRS} + ${Qt${QT_TEST_VERSION}Core_INCLUDE_DIRS} ) add_library(macos_fw_lib SHARED @@ -28,6 +28,4 @@ set_target_properties(macos_fw_lib PROPERTIES POSITION_INDEPENDENT_CODE ON PUBLIC_HEADER "${MACOS_FW_LIB_HDRS}" ) -target_link_libraries(macos_fw_lib - Qt5::Core -) +target_link_libraries(macos_fw_lib PRIVATE ${QT_QTCORE_TARGET}) diff --git a/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt b/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt index 521c18450b3..8cb1bc531fb 100644 --- a/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt +++ b/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt @@ -4,16 +4,16 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../src ) include_directories(SYSTEM - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Widgets_INCLUDE_DIRS} + ${Qt${QT_TEST_VERSION}Core_INCLUDE_DIRS} + ${Qt${QT_TEST_VERSION}Widgets_INCLUDE_DIRS} ) set(testname AutomocMacosFWLib) add_executable(${testname} testMacosFWLib.cpp) set_target_properties(${testname} PROPERTIES AUTOMOC TRUE) -target_link_libraries(${testname} - Qt5::Core - Qt5::Widgets - Qt5::Test +target_link_libraries(${testname} PRIVATE + Qt${QT_TEST_VERSION}::Core + Qt${QT_TEST_VERSION}::Widgets + Qt${QT_TEST_VERSION}::Test macos_fw_lib ) diff --git a/Tests/QtAutogen/ManySources/CMakeLists.txt b/Tests/QtAutogen/ManySources/CMakeLists.txt index df8a2a662ac..f9ac7db416e 100644 --- a/Tests/QtAutogen/ManySources/CMakeLists.txt +++ b/Tests/QtAutogen/ManySources/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(ManySources) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/MocCMP0071/CMakeLists.txt b/Tests/QtAutogen/MocCMP0071/CMakeLists.txt index 5c58a82785d..7ab3a8eeedf 100644 --- a/Tests/QtAutogen/MocCMP0071/CMakeLists.txt +++ b/Tests/QtAutogen/MocCMP0071/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocCMP0071) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt b/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt index 954fe3dc173..4375b1778f7 100644 --- a/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt +++ b/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.10) cmake_policy(SET CMP0071 NEW) # *Generate* files diff --git a/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt b/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt index 68fa0670808..3771487b85f 100644 --- a/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt +++ b/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.10) cmake_policy(SET CMP0071 OLD) # *Generate* files diff --git a/Tests/QtAutogen/MocCMP0100/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/CMakeLists.txt index 559cffe96d0..b19dc6aefab 100644 --- a/Tests/QtAutogen/MocCMP0100/CMakeLists.txt +++ b/Tests/QtAutogen/MocCMP0100/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocCMP0100) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt index 654b31e29eb..aaaf7fbb66e 100644 --- a/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt +++ b/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0100 NEW) add_executable(mocCMP0100New diff --git a/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt index 2be0535044b..006cda1b447 100644 --- a/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt +++ b/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt @@ -1,4 +1,3 @@ -cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0100 OLD) # Generate moc files externally. diff --git a/Tests/QtAutogen/MocInclude/CMakeLists.txt b/Tests/QtAutogen/MocInclude/CMakeLists.txt index 04c8bafb7f6..4224d2f9c71 100644 --- a/Tests/QtAutogen/MocInclude/CMakeLists.txt +++ b/Tests/QtAutogen/MocInclude/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.16) project(MocInclude) get_filename_component(CS_REAL ${CMAKE_CURRENT_SOURCE_DIR} REALPATH) include("${CS_REAL}/../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt b/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt index 8b11b465d22..c28616bfcec 100644 --- a/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt +++ b/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.16) project(MocIncludeSymlink) include("../AutogenCoreTest.cmake") @@ -63,6 +63,7 @@ macro(buildMocInclude sourceDir binaryDir) CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOMOC_PATH_PREFIX=ON" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" OUTPUT_VARIABLE output ) diff --git a/Tests/QtAutogen/MocMacroName/CMakeLists.txt b/Tests/QtAutogen/MocMacroName/CMakeLists.txt index bf13d187de9..d8dc4a33dfa 100644 --- a/Tests/QtAutogen/MocMacroName/CMakeLists.txt +++ b/Tests/QtAutogen/MocMacroName/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocMacroName) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/MocOnly/CMakeLists.txt b/Tests/QtAutogen/MocOnly/CMakeLists.txt index f4fde58e79f..b5d405a1e0e 100644 --- a/Tests/QtAutogen/MocOnly/CMakeLists.txt +++ b/Tests/QtAutogen/MocOnly/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocOnly) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/MocOptions/CMakeLists.txt b/Tests/QtAutogen/MocOptions/CMakeLists.txt index 19ee6587e73..169e6cbe831 100644 --- a/Tests/QtAutogen/MocOptions/CMakeLists.txt +++ b/Tests/QtAutogen/MocOptions/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocOptions) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/MocOsMacros/CMakeLists.txt b/Tests/QtAutogen/MocOsMacros/CMakeLists.txt index b0125f6c389..db44da318b5 100644 --- a/Tests/QtAutogen/MocOsMacros/CMakeLists.txt +++ b/Tests/QtAutogen/MocOsMacros/CMakeLists.txt @@ -1,10 +1,10 @@ -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.16) project(MocOsMacros) include("../AutogenCoreTest.cmake") # Tests if moc processes Q_OS_XXX macros -message( "Qt5Core_VERSION: ${Qt5Core_VERSION}" ) +message( "Qt${QT_TEST_VERSION}Core_VERSION: ${Qt${QT_TEST_VERSION}Core_VERSION}" ) message( "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND: " ${CMAKE_CXX_COMPILER_PREDEFINES_COMMAND} ) @@ -12,7 +12,7 @@ message( # On some platforms (e.g. MAC) Q_OS_XXX requires moc to include moc_predefs.h # which is supported since Qt 5.8 and requires # CMAKE_CXX_COMPILER_PREDEFINES_COMMAND to be defined. -if( ( ${Qt5Core_VERSION} VERSION_GREATER_EQUAL "5.8" ) AND +if( ( ${Qt${QT_TEST_VERSION}Core_VERSION} VERSION_GREATER_EQUAL "5.8" ) AND DEFINED CMAKE_CXX_COMPILER_PREDEFINES_COMMAND ) message( "Test enabled!" ) diff --git a/Tests/QtAutogen/MocSkipSource/CMakeLists.txt b/Tests/QtAutogen/MocSkipSource/CMakeLists.txt index c8867361832..b9e20c84c2f 100644 --- a/Tests/QtAutogen/MocSkipSource/CMakeLists.txt +++ b/Tests/QtAutogen/MocSkipSource/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocSkipSource) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt b/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt index e8af6c98380..88d0998974a 100644 --- a/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt +++ b/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(ObjectLibrary) include("../AutogenCoreTest.cmake") @@ -11,7 +11,7 @@ add_subdirectory(a) # Object library b defined locally include_directories(b) add_library(b OBJECT b/classb.cpp) -target_compile_features(b PRIVATE ${QT_COMPILE_FEATURES}) +target_link_libraries(b PRIVATE ${QT_LIBRARIES}) # Executable with OBJECT library generator expressions add_executable(someProgram main.cpp $<TARGET_OBJECTS:a> $<TARGET_OBJECTS:b>) diff --git a/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt b/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt index fe76ac32cfe..5ace3aeda79 100644 --- a/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt +++ b/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt @@ -1,2 +1,2 @@ add_library(a OBJECT classa.cpp) -target_compile_features(a PRIVATE ${QT_COMPILE_FEATURES}) +target_link_libraries(a PRIVATE ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/Parallel/CMakeLists.txt b/Tests/QtAutogen/Parallel/CMakeLists.txt index 299bcbfd70a..29628ebf85f 100644 --- a/Tests/QtAutogen/Parallel/CMakeLists.txt +++ b/Tests/QtAutogen/Parallel/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(Parallel) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/Parallel1/CMakeLists.txt b/Tests/QtAutogen/Parallel1/CMakeLists.txt index 5c7d547df5b..d94aba5477d 100644 --- a/Tests/QtAutogen/Parallel1/CMakeLists.txt +++ b/Tests/QtAutogen/Parallel1/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(Parallel1) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/Parallel2/CMakeLists.txt b/Tests/QtAutogen/Parallel2/CMakeLists.txt index 668aea4bdd0..58667a85bee 100644 --- a/Tests/QtAutogen/Parallel2/CMakeLists.txt +++ b/Tests/QtAutogen/Parallel2/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(Parallel2) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/Parallel3/CMakeLists.txt b/Tests/QtAutogen/Parallel3/CMakeLists.txt index 5c50f5ee58d..cc3aae006fb 100644 --- a/Tests/QtAutogen/Parallel3/CMakeLists.txt +++ b/Tests/QtAutogen/Parallel3/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(Parallel3) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/Parallel4/CMakeLists.txt b/Tests/QtAutogen/Parallel4/CMakeLists.txt index 2c40c6a676f..2b81e9853ec 100644 --- a/Tests/QtAutogen/Parallel4/CMakeLists.txt +++ b/Tests/QtAutogen/Parallel4/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(Parallel4) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt b/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt index cddece37a50..5543b9aaa40 100644 --- a/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt +++ b/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(ParallelAUTO) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/RccEmpty/CMakeLists.txt b/Tests/QtAutogen/RccEmpty/CMakeLists.txt index a8e2af1b631..c8f9d17cf1e 100644 --- a/Tests/QtAutogen/RccEmpty/CMakeLists.txt +++ b/Tests/QtAutogen/RccEmpty/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RccEmpty) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt b/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt index 61b9601a297..b44973d8de2 100644 --- a/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt +++ b/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RccOffMocLibrary) include("../AutogenCoreTest.cmake") @@ -9,9 +9,7 @@ include("../AutogenCoreTest.cmake") add_library(empty STATIC empty.cpp not_generated_file.qrc) set_target_properties(empty PROPERTIES AUTORCC OFF) set_target_properties(empty PROPERTIES AUTOMOC TRUE) -target_link_libraries(empty no_link_language) +target_link_libraries(empty PRIVATE no_link_language ${QT_LIBRARIES}) add_library(no_link_language STATIC empty.h) set_target_properties(no_link_language PROPERTIES AUTOMOC TRUE) -# Pass Qt compiler features to targets that don't link against Qt -target_compile_features(no_link_language PRIVATE ${QT_COMPILE_FEATURES}) -target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES}) +target_link_libraries(no_link_language PRIVATE ${QT_LIBRARIES}) diff --git a/Tests/QtAutogen/RccOnly/CMakeLists.txt b/Tests/QtAutogen/RccOnly/CMakeLists.txt index f3776f5750d..f3271e07c03 100644 --- a/Tests/QtAutogen/RccOnly/CMakeLists.txt +++ b/Tests/QtAutogen/RccOnly/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RccOnly) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RccSkipSource/CMakeLists.txt b/Tests/QtAutogen/RccSkipSource/CMakeLists.txt index 42232744fbc..a79177fe583 100644 --- a/Tests/QtAutogen/RccSkipSource/CMakeLists.txt +++ b/Tests/QtAutogen/RccSkipSource/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RccSkipSource) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt b/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt index c53e857e7cf..76dbdf50e64 100644 --- a/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt +++ b/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RerunMocBasic) include("../AutogenCoreTest.cmake") @@ -63,6 +63,7 @@ execute_process( ${_D_CMAKE_GENERATOR_INSTANCE} "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" RESULT_VARIABLE exit_code OUTPUT_VARIABLE output diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt b/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt index 42f2f57c551..e27a8242dd3 100644 --- a/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt +++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocBasic) include("../../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt b/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt index 26776595d96..3a9244d2f8b 100644 --- a/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt +++ b/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt @@ -1,6 +1,6 @@ # This test checks whether adding a source file to the project triggers an AUTOMOC re-run. -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RerunMocOnAddFile) include("../AutogenCoreTest.cmake") @@ -64,6 +64,7 @@ try_compile(MOC_RERUN MocOnAddFile CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" OUTPUT_VARIABLE output ) diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in index 9e5e21c30ac..e600137fb76 100644 --- a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in +++ b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocOnAddFile) include("@CMAKE_CURRENT_LIST_DIR@/../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt b/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt index c5811ebce16..b17e4c54efe 100644 --- a/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt +++ b/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt @@ -1,6 +1,6 @@ # This test checks whether a missing dependency of the moc output triggers an AUTOMOC re-run. -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RerunMocOnMissingDependency) include("../AutogenCoreTest.cmake") @@ -13,10 +13,10 @@ add_executable(exe "${main_source}") set(testProjectTemplateDir "${CMAKE_CURRENT_SOURCE_DIR}/MocOnMissingDependency") set(testProjectSrc "${CMAKE_CURRENT_BINARY_DIR}/MocOnMissingDependency") set(testProjectBinDir "${CMAKE_CURRENT_BINARY_DIR}/MocOnMissingDependency-build") -if(DEFINED Qt5Core_VERSION AND Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0") - set(moc_depfiles_supported TRUE) +if(DEFINED Qt${QT_TEST_VERSION}Core_VERSION AND Qt${QT_TEST_VERSION}Core_VERSION VERSION_GREATER_EQUAL "5.15.0") + set(moc_depfiles_supported TRUE) else() - set(moc_depfiles_supported FALSE) + set(moc_depfiles_supported FALSE) endif() # Utility macros @@ -48,6 +48,7 @@ try_compile(MOC_RERUN MocOnMissingDependency CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=ON" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" OUTPUT_VARIABLE output ) diff --git a/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt b/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt index a7fb2d7f750..2d2edb497ab 100644 --- a/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt +++ b/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RerunMocPlugin) include("../AutogenCoreTest.cmake") @@ -63,6 +63,7 @@ try_compile(MOC_PLUGIN MocPlugin CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" OUTPUT_VARIABLE output ) diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt index 50682897678..8097fd033f2 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(MocPlugin) include("../../AutogenGuiTest.cmake") @@ -22,7 +22,7 @@ configure_file(jsonIn/StyleE.json jsonFiles/StyleE_Custom.json) set(CMAKE_AUTOMOC TRUE) include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") -link_libraries(Qt5::Widgets) +link_libraries(Qt${QT_TEST_VERSION}::Widgets) add_library(PlugA STATIC StyleA.cpp) add_library(PlugB STATIC StyleB.cpp) diff --git a/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt b/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt index 33c01acbed0..1598bfd58e1 100644 --- a/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.11.2) +cmake_minimum_required(VERSION 3.16) project(RerunRccConfigChange) include("../AutogenCoreTest.cmake") @@ -33,6 +33,7 @@ try_compile(RCC_DEPENDS RccConfigChange CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" OUTPUT_VARIABLE output ) diff --git a/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt b/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt index e2dd0ac385d..83f3a45c04e 100644 --- a/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.11.2) +cmake_minimum_required(VERSION 3.16) project(RccConfigChange) include("../../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt index 1301550f236..15e38db721c 100644 --- a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt +++ b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RerunRccDepends) include("../AutogenCoreTest.cmake") @@ -66,6 +66,7 @@ try_compile(RCC_DEPENDS RccDepends CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" OUTPUT_VARIABLE output ) diff --git a/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt b/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt index 150f849b3bb..6bba16396ac 100644 --- a/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt +++ b/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(RccDepends) include("../../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt index 9b114e9be20..979e8785799 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt @@ -66,6 +66,7 @@ execute_process( "${build_type_extra}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" RESULT_VARIABLE exit_code OUTPUT_VARIABLE output diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in index c787db1d561..1775725992a 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(UicOnFileChange) include("@CMAKE_CURRENT_LIST_DIR@/../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt b/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt index f3536ba2c55..25ea8220463 100644 --- a/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt +++ b/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(StaticLibraryCycle) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/TestMacros.cmake b/Tests/QtAutogen/TestMacros.cmake index 9dcf31fbdcb..529592e85ee 100644 --- a/Tests/QtAutogen/TestMacros.cmake +++ b/Tests/QtAutogen/TestMacros.cmake @@ -7,8 +7,17 @@ else() endif() list(APPEND Autogen_BUILD_OPTIONS "-DCMAKE_AUTOGEN_VERBOSE=1" - "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" ) +if(Qt${QT_TEST_VERSION}Core_DIR) + get_filename_component(prefix "${Qt${QT_TEST_VERSION}Core_DIR}" DIRECTORY) + get_filename_component(prefix "${prefix}" DIRECTORY) + get_filename_component(prefix "${prefix}" DIRECTORY) + list(APPEND Autogen_BUILD_OPTIONS "-DCMAKE_PREFIX_PATH:STRING=${prefix}") +else() + list(APPEND Autogen_BUILD_OPTIONS + "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + ) +endif() # XXX(xcode-per-cfg-src): Drop the NO_PER_CONFIG_SOURCES exclusion # when the Xcode generator supports per-config sources. if(CMAKE_GENERATOR STREQUAL "Xcode") diff --git a/Tests/QtAutogen/UicInclude/CMakeLists.txt b/Tests/QtAutogen/UicInclude/CMakeLists.txt index 929868b5257..042d18f5ed0 100644 --- a/Tests/QtAutogen/UicInclude/CMakeLists.txt +++ b/Tests/QtAutogen/UicInclude/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(UicInclude) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/UicInterface/CMakeLists.txt b/Tests/QtAutogen/UicInterface/CMakeLists.txt index e0227645b98..167ae49c231 100644 --- a/Tests/QtAutogen/UicInterface/CMakeLists.txt +++ b/Tests/QtAutogen/UicInterface/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(UicInterface) include("../AutogenGuiTest.cmake") @@ -11,12 +11,12 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_VERBOSE_MAKEFILE ON) add_library(KI18n klocalizedstring.cpp) -target_link_libraries(KI18n ${QT_QTCORE_TARGET}) +target_link_libraries(KI18n PRIVATE ${QT_QTCORE_TARGET}) set(autouic_options -tr tr2$<$<NOT:$<BOOL:$<TARGET_PROPERTY:NO_KUIT_SEMANTIC>>>:x>i18n ) -if (NOT Qt5Widgets_VERSION VERSION_LESS 5.3.0) +if (NOT Qt${QT_TEST_VERSION}Widgets_VERSION VERSION_LESS 5.3.0) list(APPEND autouic_options -include klocalizedstring.h) endif() diff --git a/Tests/QtAutogen/UicNoGui/CMakeLists.txt b/Tests/QtAutogen/UicNoGui/CMakeLists.txt index 076299db1f1..b938a17c64c 100644 --- a/Tests/QtAutogen/UicNoGui/CMakeLists.txt +++ b/Tests/QtAutogen/UicNoGui/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.16) project(UicNoGui) include("../AutogenCoreTest.cmake") diff --git a/Tests/QtAutogen/UicOnly/CMakeLists.txt b/Tests/QtAutogen/UicOnly/CMakeLists.txt index b163254389e..e25b44d278a 100644 --- a/Tests/QtAutogen/UicOnly/CMakeLists.txt +++ b/Tests/QtAutogen/UicOnly/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(UicOnly) include("../AutogenGuiTest.cmake") diff --git a/Tests/QtAutogen/UicSkipSource/CMakeLists.txt b/Tests/QtAutogen/UicSkipSource/CMakeLists.txt index dc3b7d4eb5f..15dfe6563bf 100644 --- a/Tests/QtAutogen/UicSkipSource/CMakeLists.txt +++ b/Tests/QtAutogen/UicSkipSource/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(UicSkipSource) include("../AutogenGuiTest.cmake") diff --git a/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake b/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake index 8fa6041b969..6d26f99c7c9 100644 --- a/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake +++ b/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake @@ -1,6 +1,6 @@ enable_language(CXX) -find_package(Qt5 REQUIRED COMPONENTS Core) +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core) # Detect `-NOTFOUND` libraries at generate time. cmake_policy(SET CMP0111 NEW) diff --git a/Tests/RunCMake/Autogen/CMakeLists.txt b/Tests/RunCMake/Autogen/CMakeLists.txt index 9a66cde9b7e..2632ffa91f1 100644 --- a/Tests/RunCMake/Autogen/CMakeLists.txt +++ b/Tests/RunCMake/Autogen/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.16) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Autogen/QtInFunction.cmake b/Tests/RunCMake/Autogen/QtInFunction.cmake index a44bc5ab488..6c42cc2324e 100644 --- a/Tests/RunCMake/Autogen/QtInFunction.cmake +++ b/Tests/RunCMake/Autogen/QtInFunction.cmake @@ -1,9 +1,9 @@ enable_language(CXX) function (use_autogen target) - find_package(Qt5 REQUIRED COMPONENTS Core Widgets) - set(Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}" PARENT_SCOPE) - set(Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}" PARENT_SCOPE) + find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets) + set(Qt${with_qt_version}Core_VERSION_MAJOR "${Qt${with_qt_version}Core_VERSION_MAJOR}" PARENT_SCOPE) + set(Qt${with_qt_version}Core_VERSION_MINOR "${Qt${with_qt_version}Core_VERSION_MINOR}" PARENT_SCOPE) set_property(TARGET "${target}" PROPERTY AUTOMOC 1) set_property(TARGET "${target}" PROPERTY AUTORCC 1) set_property(TARGET "${target}" PROPERTY AUTOUIC 1) diff --git a/Tests/RunCMake/Autogen/QtInFunctionNested.cmake b/Tests/RunCMake/Autogen/QtInFunctionNested.cmake index 5421ba00df4..2e7b8add312 100644 --- a/Tests/RunCMake/Autogen/QtInFunctionNested.cmake +++ b/Tests/RunCMake/Autogen/QtInFunctionNested.cmake @@ -1,9 +1,9 @@ enable_language(CXX) function (use_autogen target) - find_package(Qt5 REQUIRED COMPONENTS Core Widgets) - set(Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}" PARENT_SCOPE) - set(Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}" PARENT_SCOPE) + find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets) + set(Qt${with_qt_version}Core_VERSION_MAJOR "${Qt${with_qt_version}Core_VERSION_MAJOR}" PARENT_SCOPE) + set(Qt${with_qt_version}Core_VERSION_MINOR "${Qt${with_qt_version}Core_VERSION_MINOR}" PARENT_SCOPE) set_property(TARGET "${target}" PROPERTY AUTOMOC 1) set_property(TARGET "${target}" PROPERTY AUTORCC 1) set_property(TARGET "${target}" PROPERTY AUTOUIC 1) diff --git a/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake b/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake index 35f1cd16cae..d9296c44cbd 100644 --- a/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake +++ b/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake @@ -1,13 +1,13 @@ enable_language(CXX) function (use_autogen target) - find_package(Qt5 REQUIRED COMPONENTS Core Widgets) + find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets) set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" PROPERTY - Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}") + Qt${with_qt_version}Core_VERSION_MAJOR "${Qt${with_qt_version}Core_VERSION_MAJOR}") set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" PROPERTY - Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}") + Qt${with_qt_version}Core_VERSION_MINOR "${Qt${with_qt_version}Core_VERSION_MINOR}") set_property(TARGET "${target}" PROPERTY AUTOMOC 1) set_property(TARGET "${target}" PROPERTY AUTORCC 1) set_property(TARGET "${target}" PROPERTY AUTOUIC 1) diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake index bbcbd5ed8f9..e4c5811466a 100644 --- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake +++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake @@ -1,7 +1,13 @@ include(RunCMake) run_cmake(NoQt) -if (with_qt5) +if (DEFINED with_qt_version) + set(RunCMake_TEST_OPTIONS + -Dwith_qt_version=${with_qt_version} + "-DQt${with_qt_version}_DIR:PATH=${Qt${with_qt_version}_DIR}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" + ) + run_cmake(QtInFunction) run_cmake(QtInFunctionNested) run_cmake(QtInFunctionProperty) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index eb2c2d94ae1..3baa645e56f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -151,8 +151,23 @@ endif() if(CMAKE_GENERATOR MATCHES "Make") add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU}) endif() -if(CMake_TEST_Qt5) +unset(ninja_test_with_qt_version) +unset(ninja_qt_args) +if(CMake_TEST_Qt6) + find_package(Qt6Widgets QUIET NO_MODULE) + if(Qt6Widgets_FOUND) + set(ninja_test_with_qt_version 6) + # Work around Qt6 not finding sibling dependencies without CMAKE_PREFIX_PATH + cmake_path(GET Qt6_DIR PARENT_PATH base_dir) # <base>/lib/cmake + cmake_path(GET base_dir PARENT_PATH base_dir) # <base>/lib + cmake_path(GET base_dir PARENT_PATH base_dir) # <base> + set(ninja_qt_args -DCMAKE_PREFIX_PATH=${base_dir}) + endif() +elseif(CMake_TEST_Qt5) find_package(Qt5Widgets QUIET NO_MODULE) + if(Qt5Widgets_FOUND) + set(ninja_test_with_qt_version 5) + endif() endif() if(CMAKE_GENERATOR MATCHES "Ninja") set(Ninja_ARGS @@ -162,18 +177,27 @@ if(CMAKE_GENERATOR MATCHES "Ninja") if(CMAKE_Fortran_COMPILER) list(APPEND Ninja_ARGS -DTEST_Fortran=1) endif() - if(CMake_TEST_Qt5 AND Qt5Core_FOUND) - list(APPEND Ninja_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION}) - if(Qt5Widgets_FOUND) - list(APPEND Ninja_ARGS -DQt5Widgets_DIR=${Qt5Widgets_DIR}) - endif() + if(ninja_test_with_qt_version) + list(APPEND Ninja_ARGS + -DCMake_TEST_Qt_version=${ninja_test_with_qt_version} + -DQt${ninja_test_with_qt_version}_DIR=${Qt${ninja_test_with_qt_version}_DIR} + -DQt${ninja_test_with_qt_version}Core_DIR=${Qt${ninja_test_with_qt_version}Core_DIR} + -DCMake_TEST_Qt${ninja_test_with_qt_version}Core_Version=${Qt${ninja_test_with_qt_version}Core_VERSION} + -DQt${ninja_test_with_qt_version}Widgets_DIR=${Qt${ninja_test_with_qt_version}Widgets_DIR} + ${ninja_qt_args} + ) endif() add_RunCMake_test(Ninja) set(NinjaMultiConfig_ARGS -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} ) - if(CMake_TEST_Qt5 AND Qt5Core_FOUND) - list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION}) + if(ninja_test_with_qt_version) + list(APPEND NinjaMultiConfig_ARGS + -DCMake_TEST_Qt_version=${ninja_test_with_qt_version} + -DQt${ninja_test_with_qt_version}Core_DIR=${Qt${ninja_test_with_qt_version}Core_DIR} + -DCMake_TEST_Qt${ninja_test_with_qt_version}Core_Version=${Qt${ninja_test_with_qt_version}Core_VERSION} + ${ninja_qt_args} + ) endif() if(DEFINED CMake_TEST_CUDA) list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) @@ -205,11 +229,29 @@ add_RunCMake_test(AndroidTestUtilities) if(CMake_TEST_APPLE_SILICON) add_RunCMake_test(AppleSilicon) endif() -set(autogen_with_qt5 FALSE) +set(want_NoQt_test TRUE) +if(CMake_TEST_Qt6 AND Qt6Widgets_FOUND) + # Work around Qt6 not finding sibling dependencies without CMAKE_PREFIX_PATH + cmake_path(GET Qt6_DIR PARENT_PATH base_dir) # <base>/lib/cmake + cmake_path(GET base_dir PARENT_PATH base_dir) # <base>/lib + cmake_path(GET base_dir PARENT_PATH base_dir) # <base> + add_RunCMake_test(AutogenQt6 TEST_DIR Autogen + -Dwith_qt_version=6 + "-DQt6_DIR:PATH=${Qt6_DIR}" + "-DCMAKE_PREFIX_PATH:STRING=${base_dir}" + ) + set(want_NoQt_test FALSE) +endif () if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND) - set(autogen_with_qt5 TRUE) + add_RunCMake_test(AutogenQt5 TEST_DIR Autogen + -Dwith_qt_version=5 + "-DQt5_DIR:PATH=${Qt5_DIR}" + ) + set(want_NoQt_test FALSE) endif () -add_RunCMake_test(Autogen -Dwith_qt5=${autogen_with_qt5}) +if(want_NoQt_test) + add_RunCMake_test(AutogenNoQt TEST_DIR Autogen) +endif() add_RunCMake_test(ArtifactOutputDirs) diff --git a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake deleted file mode 100644 index 46b840f4c32..00000000000 --- a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake +++ /dev/null @@ -1,21 +0,0 @@ -enable_language(CXX) - -find_package(Qt5Core REQUIRED) - -set(CMAKE_AUTOMOC ON) - -add_library(simple_lib SHARED simple_lib.cpp) -add_executable(app_with_qt app.cpp app_qt.cpp) -target_link_libraries(app_with_qt PRIVATE simple_lib Qt5::Core) - -if(Qt5Widgets_DIR) - find_package(Qt5Widgets REQUIRED) - qt5_wrap_ui(_headers MyWindow.ui) - add_executable(app_with_widget app.cpp MyWindow.cpp ${_headers}) - target_link_libraries(app_with_widget PRIVATE Qt5::Widgets) - target_include_directories(app_with_widget PRIVATE "${CMAKE_BINARY_DIR}") -endif() - -add_subdirectory(QtSubDir1) -add_subdirectory(QtSubDir2) -add_subdirectory(QtSubDir3) diff --git a/Tests/RunCMake/Ninja/QtAutoMocDeps.cmake b/Tests/RunCMake/Ninja/QtAutoMocDeps.cmake new file mode 100644 index 00000000000..c4411696901 --- /dev/null +++ b/Tests/RunCMake/Ninja/QtAutoMocDeps.cmake @@ -0,0 +1,27 @@ +enable_language(CXX) + +set(QtX Qt${with_qt_version}) + +find_package(${QtX} REQUIRED COMPONENTS Core) + +set(CMAKE_AUTOMOC ON) + +add_library(simple_lib SHARED simple_lib.cpp) +add_executable(app_with_qt app.cpp app_qt.cpp) +target_link_libraries(app_with_qt PRIVATE simple_lib ${QtX}::Core) + +if(${QtX}Widgets_DIR) + find_package(${QtX} REQUIRED COMPONENTS Widgets) + if(with_qt_version STREQUAL 5) + qt5_wrap_ui(_headers MyWindow.ui) + else() + qt_wrap_ui(_headers MyWindow.ui) + endif() + add_executable(app_with_widget app.cpp MyWindow.cpp ${_headers}) + target_link_libraries(app_with_widget PRIVATE ${QtX}::Widgets) + target_include_directories(app_with_widget PRIVATE "${CMAKE_BINARY_DIR}") +endif() + +add_subdirectory(QtSubDir1) +add_subdirectory(QtSubDir2) +add_subdirectory(QtSubDir3) diff --git a/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt index 64016b683ba..3a12dcd6cd4 100644 --- a/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt +++ b/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt @@ -1,4 +1,4 @@ cmake_policy(SET CMP0116 OLD) add_executable(sub_exe_1 ../app.cpp) -target_link_libraries(sub_exe_1 PRIVATE Qt5::Core) +target_link_libraries(sub_exe_1 PRIVATE ${QtX}::Core) diff --git a/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt index 3176426f406..a2f77e4d01a 100644 --- a/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt +++ b/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt @@ -1,4 +1,4 @@ cmake_policy(SET CMP0116 NEW) add_executable(sub_exe_2 ../app.cpp) -target_link_libraries(sub_exe_2 PRIVATE Qt5::Core) +target_link_libraries(sub_exe_2 PRIVATE ${QtX}::Core) diff --git a/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt index d38cfe0763e..70644fa7a02 100644 --- a/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt +++ b/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt @@ -1,2 +1,2 @@ add_executable(sub_exe_3 ../app.cpp) -target_link_libraries(sub_exe_3 PRIVATE Qt5::Core) +target_link_libraries(sub_exe_3 PRIVATE ${QtX}::Core) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 3f239b974d7..2a5b5562016 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -319,12 +319,17 @@ function (run_ChangeBuildType) endfunction() run_ChangeBuildType() -function(run_Qt5AutoMocDeps) - if(CMake_TEST_Qt5 AND CMAKE_TEST_Qt5Core_Version VERSION_GREATER_EQUAL 5.15.0) - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5AutoMocDeps-build) - set(RunCMake_TEST_OPTIONS "-DQt5Core_DIR=${Qt5Core_DIR}" "-DQt5Widgets_DIR=${Qt5Widgets_DIR}") - run_cmake(Qt5AutoMocDeps) - unset(RunCMake_TEST_OPTIONS) +function(run_QtAutoMocDeps) + set(QtX Qt${CMake_TEST_Qt_version}) + if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtAutoMocDeps-build) + run_cmake_with_options(QtAutoMocDeps + "-Dwith_qt_version=${CMake_TEST_Qt_version}" + "-D${QtX}_DIR=${${QtX}_DIR}" + "-D${QtX}Core_DIR=${${QtX}Core_DIR}" + "-D${QtX}Widgets_DIR=${${QtX}Widgets_DIR}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" + ) # Build the project. run_ninja("${RunCMake_TEST_BINARY_DIR}") # Touch just the library source file, which shouldn't cause a rerun of AUTOMOC @@ -352,4 +357,6 @@ function(run_Qt5AutoMocDeps) run_ninja("${RunCMake_TEST_BINARY_DIR}") endif() endfunction() -run_Qt5AutoMocDeps() +if(CMake_TEST_Qt_version) + run_QtAutoMocDeps() +endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5-automoc-check-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/QtX-automoc-check-ninja-stdout.txt similarity index 100% rename from Tests/RunCMake/NinjaMultiConfig/Qt5-automoc-check-ninja-stdout.txt rename to Tests/RunCMake/NinjaMultiConfig/QtX-automoc-check-ninja-stdout.txt diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake similarity index 100% rename from Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake rename to Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake b/Tests/RunCMake/NinjaMultiConfig/QtX.cmake similarity index 77% rename from Tests/RunCMake/NinjaMultiConfig/Qt5.cmake rename to Tests/RunCMake/NinjaMultiConfig/QtX.cmake index 578256a73b2..130f883901d 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/QtX.cmake @@ -1,18 +1,21 @@ enable_language(CXX) -find_package(Qt5Core REQUIRED) +set(QtX Qt${with_qt_version}) + +find_package(${QtX} REQUIRED COMPONENTS Core) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC_COMPILER_PREDEFINES OFF) +# Source files are always named qt5.* for simplicity but apply to Qt5 and later add_executable(exe qt5.cxx) -target_link_libraries(exe PRIVATE Qt5::Core) +target_link_libraries(exe PRIVATE ${QtX}::Core) include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) generate_output_files(exe) set(moc_writes_depfiles 0) -if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0") +if(${QtX}Core_VERSION VERSION_GREATER_EQUAL "5.15.0") set(moc_writes_depfiles 1) endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 7c100eb1eab..c7b876c4b4e 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -446,14 +446,20 @@ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang") run_ninja(CudaSimple all-clean build-Debug.ninja clean:Debug) endif() -if(CMake_TEST_Qt5) - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build) - set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all" "-DQt5Core_DIR=${Qt5Core_DIR}") - run_cmake_configure(Qt5) +if(CMake_TEST_Qt_version) + set(QtX Qt${CMake_TEST_Qt_version}) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtX-build) + set(RunCMake_TEST_OPTIONS + "-DCMAKE_CROSS_CONFIGS=all" + "-Dwith_qt_version:STRING=${CMake_TEST_Qt_version}" + "-D${QtX}Core_DIR=${${QtX}Core_DIR}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" + ) + run_cmake_configure(QtX) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) - run_cmake_build(Qt5 debug-in-release-graph Release exe:Debug) - if(CMAKE_TEST_Qt5Core_Version VERSION_GREATER_EQUAL 5.15.0) - run_ninja(Qt5 automoc-check build-Debug.ninja -t query exe_autogen/timestamp) + run_cmake_build(QtX debug-in-release-graph Release exe:Debug) + if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0) + run_ninja(QtX automoc-check build-Debug.ninja -t query exe_autogen/timestamp) endif() endif() From ba54092842f8eb712f57448c33763cb56d8931da Mon Sep 17 00:00:00 2001 From: Sylvain Joubert <joubert.sy@gmail.com> Date: Mon, 4 Oct 2021 15:28:18 +0200 Subject: [PATCH 1342/1519] TestDriver: Fix old-style-cast warning in C++ mode A C-style cast was added by commit 3f6ff4b5db (create_test_sourcelist: add test driver option to run all tests, 2021-04-27, v3.21.0-rc1~257^2). Use our `CM_CAST` macro to adapt based on the language. --- Templates/TestDriver.cxx.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index 6ced8001ca2..632bb8065cb 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -138,7 +138,7 @@ int main(int ac, char* av[]) t = clock() - t; status_message = (status == -1) ? "not ok" : "ok"; { - double time_taken = ((double)t) / CLOCKS_PER_SEC; + double time_taken = CM_CAST(double, t) / CLOCKS_PER_SEC; printf("%s %d %s # %f\n", status_message, i + 1, name, time_taken); } } From 1d03aa841c38ea19ffdab08f762fa39d4134874c Mon Sep 17 00:00:00 2001 From: Arcturus Arcturus <arcturus98@outlook.com> Date: Thu, 16 Sep 2021 12:55:12 +0100 Subject: [PATCH 1343/1519] Utilities/Sphinx: Print path to index.html in build output Print the url to index.html in the build output, just so one can "open in browser" from the context menu in some terminals. --- Utilities/Sphinx/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index a71dfcdfaab..c8a970dcafc 100644 --- a/Utilities/Sphinx/CMakeLists.txt +++ b/Utilities/Sphinx/CMakeLists.txt @@ -58,6 +58,13 @@ configure_file(conf.py.in conf.py @ONLY) set(doc_formats "") if(SPHINX_HTML) list(APPEND doc_formats html) + + # we provide the path to the produced html output in the console + # for tools that support URI protocol schemes + set(html_extra_commands + COMMAND ${CMAKE_COMMAND} -E echo "sphinx-build html: HTML documentation generated in file://${CMAKE_CURRENT_BINARY_DIR}/html/index.html" + ) + endif() if(SPHINX_MAN) list(APPEND doc_formats man) From 1b21eb82126bb350a4cbe8b2f7969913407b81a8 Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Tue, 5 Oct 2021 00:01:15 -0400 Subject: [PATCH 1344/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7a69f8d8c60..db86b722485 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211004) +set(CMake_VERSION_PATCH 20211005) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 0e86fea0bee63592e024c330b22939ec7846712e Mon Sep 17 00:00:00 2001 From: Gregor Jasny <gregor.jasny@logmein.com> Date: Fri, 1 Oct 2021 10:04:48 +0200 Subject: [PATCH 1345/1519] Tests: Specify destination for Xcode scheme The `Using the first of multiple matching destinations` warning vanishes if we explicitly specify a destination. Fixes: #22704 --- Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index ed8e7258f86..fa26c3d325e 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -91,7 +91,12 @@ function(XcodeSchemaGeneration) file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") run_cmake(XcodeSchemaGeneration) - run_cmake_command(XcodeSchemaGeneration-build xcodebuild -scheme foo build) + if (XCODE_VERSION VERSION_GREATER_EQUAL 13) + set(maybe_destination -destination platform=macOS) + else() + set(maybe_destination "") + endif() + run_cmake_command(XcodeSchemaGeneration-build xcodebuild -scheme foo ${maybe_destination} build) endfunction() if(NOT XCODE_VERSION VERSION_LESS 7) From 2a3116795528354b9e93238d057efa16b3635da8 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 4 Oct 2021 14:04:51 +1100 Subject: [PATCH 1346/1519] AUTOUIC: Fix merging of --blah options not being detected for Qt6 When merging a new set of uic options with a base set of options, such as when a source file has a non-empty AUTOUIC_OPTIONS property, the test for whether to support options starting with two hyphens was only testing if the Qt major version was exactly 5 rather than at least 5. That had the effect of preventing such options from being merged correctly when using Qt6, so new and base options would both be present instead of the single merged option from the source file properties. Update the version check and rename function arguments to avoid misrepresenting what they mean. Note that uic accepts long option names with a single hyphen too. See Qt docs for QCommandLineParser::ParseAsLongOptions for confirmation. --- Source/cmQtAutoGen.cxx | 13 +++++++------ Source/cmQtAutoGen.h | 4 ++-- Source/cmQtAutoMocUic.cxx | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 57fcd2da768..9584e5c41a2 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -24,7 +24,8 @@ /// @arg valueOpts list of options that accept a value void MergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, - std::initializer_list<cm::string_view> valueOpts, bool isQt5) + std::initializer_list<cm::string_view> valueOpts, + bool isQt5OrLater) { if (newOpts.empty()) { return; @@ -47,7 +48,7 @@ void MergeOptions(std::vector<std::string>& baseOpts, auto oit = newOpt.begin(); if (*oit == '-') { ++oit; - if (isQt5 && (*oit == '-')) { + if (isQt5OrLater && (*oit == '-')) { ++oit; } optName.assign(oit, newOpt.end()); @@ -204,24 +205,24 @@ std::string cmQtAutoGen::AppendFilenameSuffix(cm::string_view filename, void cmQtAutoGen::UicMergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, - bool isQt5) + bool isQt5OrLater) { static std::initializer_list<cm::string_view> const valueOpts = { "tr", "translate", "postfix", "generator", "include", // Since Qt 5.3 "g" }; - MergeOptions(baseOpts, newOpts, valueOpts, isQt5); + MergeOptions(baseOpts, newOpts, valueOpts, isQt5OrLater); } void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, - bool isQt5) + bool isQt5OrLater) { static std::initializer_list<cm::string_view> const valueOpts = { "name", "root", "compress", "threshold" }; - MergeOptions(baseOpts, newOpts, valueOpts, isQt5); + MergeOptions(baseOpts, newOpts, valueOpts, isQt5OrLater); } static void RccListParseContent(std::string const& content, diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 466a954a981..5a23ae92497 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -93,12 +93,12 @@ class cmQtAutoGen /// @brief Merges newOpts into baseOpts static void UicMergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, - bool isQt5); + bool isQt5OrLater); /// @brief Merges newOpts into baseOpts static void RccMergeOptions(std::vector<std::string>& baseOpts, std::vector<std::string> const& newOpts, - bool isQt5); + bool isQt5OrLater); /** @class RccLister * @brief Lists files in qrc resource files diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 056056c702a..4ed728ea948 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -2083,7 +2083,7 @@ void cmQtAutoMocUicT::JobCompileUicT::Process() auto optionIt = this->UicConst().UiFiles.find(sourceFile); if (optionIt != this->UicConst().UiFiles.end()) { UicMergeOptions(allOpts, optionIt->second.Options, - (this->BaseConst().QtVersion.Major == 5)); + (this->BaseConst().QtVersion.Major >= 5)); } cm::append(cmd, allOpts); } From 1851aa49be01076e0869ce14b22b9a860454bba4 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 4 Oct 2021 21:47:12 +1100 Subject: [PATCH 1347/1519] FetchContent: Pass through networking-related CMAKE_... variables CMAKE_TLS_VERIFY, CMAKE_TLS_CAINFO, CMAKE_NETRC and CMAKE_NETRC_FILE are now passed through to the underlying ExternalProject sub-build. Previously, they were silently ignored. Fixes: #22144 --- .../fetchcontent-CMAKE-vars-passthrough.rst | 8 ++++ Help/variable/CMAKE_NETRC.rst | 10 +++-- Help/variable/CMAKE_NETRC_FILE.rst | 10 +++-- Help/variable/CMAKE_TLS_CAINFO.rst | 4 +- Help/variable/CMAKE_TLS_VERIFY.rst | 4 +- Modules/FetchContent.cmake | 32 ++++++++++++---- .../RunCMake/FetchContent/RunCMakeTest.cmake | 1 + .../FetchContent/VarPassthroughs.cmake | 38 +++++++++++++++++++ 8 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst create mode 100644 Tests/RunCMake/FetchContent/VarPassthroughs.cmake diff --git a/Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst b/Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst new file mode 100644 index 00000000000..842c016a0be --- /dev/null +++ b/Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst @@ -0,0 +1,8 @@ +fetchcontent-CMAKE-vars-passthrough.rst +--------------------------------------- + +* The :module:`FetchContent` module now passes through the + :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`, + :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables (when + defined) to the underlying :module:`ExternalProject` sub-build. + Previously, those variables were silently ignored by :module:`FetchContent`. diff --git a/Help/variable/CMAKE_NETRC.rst b/Help/variable/CMAKE_NETRC.rst index 2c64a814957..bddfca555d8 100644 --- a/Help/variable/CMAKE_NETRC.rst +++ b/Help/variable/CMAKE_NETRC.rst @@ -3,9 +3,11 @@ CMAKE_NETRC .. versionadded:: 3.11 -This variable is used to initialize the ``NETRC`` option for -:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and the -module :module:`ExternalProject`. See those commands for additional -information. +This variable is used to initialize the ``NETRC`` option for the +:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands. +See those commands for additional information. + +This variable is also used by the :module:`ExternalProject` and +:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`. The local option takes precedence over this variable. diff --git a/Help/variable/CMAKE_NETRC_FILE.rst b/Help/variable/CMAKE_NETRC_FILE.rst index 97a645efea3..af98170b965 100644 --- a/Help/variable/CMAKE_NETRC_FILE.rst +++ b/Help/variable/CMAKE_NETRC_FILE.rst @@ -3,9 +3,11 @@ CMAKE_NETRC_FILE .. versionadded:: 3.11 -This variable is used to initialize the ``NETRC_FILE`` option for -:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and the -module :module:`ExternalProject`. See those commands for additional -information. +This variable is used to initialize the ``NETRC_FILE`` option for the +:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands. +See those commands for additional information. + +This variable is also used by the :module:`ExternalProject` and +:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`. The local option takes precedence over this variable. diff --git a/Help/variable/CMAKE_TLS_CAINFO.rst b/Help/variable/CMAKE_TLS_CAINFO.rst index fe3433527b1..07f63660db4 100644 --- a/Help/variable/CMAKE_TLS_CAINFO.rst +++ b/Help/variable/CMAKE_TLS_CAINFO.rst @@ -5,5 +5,5 @@ Specify the default value for the :command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands' ``TLS_CAINFO`` options. It is unset by default. -This variable is also used by the :module:`ExternalProject` module -for internal calls to :command:`file(DOWNLOAD)`. +This variable is also used by the :module:`ExternalProject` and +:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`. diff --git a/Help/variable/CMAKE_TLS_VERIFY.rst b/Help/variable/CMAKE_TLS_VERIFY.rst index 24f8a256a01..b22f1cefc68 100644 --- a/Help/variable/CMAKE_TLS_VERIFY.rst +++ b/Help/variable/CMAKE_TLS_VERIFY.rst @@ -5,8 +5,8 @@ Specify the default value for the :command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands' ``TLS_VERIFY`` options. If not set, the default is *off*. -This setting is also used by the :module:`ExternalProject` module -for internal calls to :command:`file(DOWNLOAD)`. +This variable is also used by the :module:`ExternalProject` and +:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`. TLS verification can help provide confidence that one is connecting to the desired server. When downloading known content, one should diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 5ea8b2a92cc..be75689b0ad 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -162,6 +162,13 @@ Commands This may be needed for things like password prompts or real-time display of command progress. + .. versionadded:: 3.22 + The :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`, + :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables now + provide the defaults for their corresponding content options, just like + they do for :command:`ExternalProject_Add`. Previously, these variables + were ignored by the ``FetchContent`` module. + .. command:: FetchContent_MakeAvailable .. versionadded:: 3.14 @@ -1016,18 +1023,29 @@ ExternalProject_Add_Step(${contentName}-populate copyfile unset(subCMakeOpts) endif() - if(DEFINED CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY) - list(APPEND subCMakeOpts - "-DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY=${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}") - endif() + set(__FETCHCONTENT_CACHED_INFO "") + set(__passthrough_vars + CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY + CMAKE_TLS_VERIFY + CMAKE_TLS_CAINFO + CMAKE_NETRC + CMAKE_NETRC_FILE + ) + foreach(var IN LISTS __passthrough_vars) + if(DEFINED ${var}) + # Embed directly in the generated CMakeLists.txt file to avoid making + # the cmake command line excessively long. It also makes debugging and + # testing easier. + string(APPEND __FETCHCONTENT_CACHED_INFO "set(${var} [==[${${var}}]==])\n") + endif() + endforeach() # Avoid using if(... IN_LIST ...) so we don't have to alter policy settings - set(__FETCHCONTENT_CACHED_INFO "") list(FIND ARG_UNPARSED_ARGUMENTS GIT_REPOSITORY indexResult) if(indexResult GREATER_EQUAL 0) find_package(Git QUIET) - set(__FETCHCONTENT_CACHED_INFO -"# Pass through things we've already detected in the main project to avoid + string(APPEND __FETCHCONTENT_CACHED_INFO " +# Pass through things we've already detected in the main project to avoid # paying the cost of redetecting them again in ExternalProject_Add() set(GIT_EXECUTABLE [==[${GIT_EXECUTABLE}]==]) set(GIT_VERSION_STRING [==[${GIT_VERSION_STRING}]==]) diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index 9baeab75e2d..e83c45e7038 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -9,6 +9,7 @@ run_cmake(DownloadTwice) run_cmake(DownloadFile) run_cmake(SameGenerator) run_cmake(VarDefinitions) +run_cmake(VarPassthroughs) run_cmake(GetProperties) run_cmake(UsesTerminalOverride) run_cmake(MakeAvailable) diff --git a/Tests/RunCMake/FetchContent/VarPassthroughs.cmake b/Tests/RunCMake/FetchContent/VarPassthroughs.cmake new file mode 100644 index 00000000000..ad743d890c0 --- /dev/null +++ b/Tests/RunCMake/FetchContent/VarPassthroughs.cmake @@ -0,0 +1,38 @@ +include(FetchContent) + +set(CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY AAAA) +set(CMAKE_TLS_VERIFY BBBB) +set(CMAKE_TLS_CAINFO CCCC) +set(CMAKE_NETRC DDDD) +set(CMAKE_NETRC_FILE EEEE) + +FetchContent_Declare(PassThrough + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed" +) +FetchContent_Populate(PassThrough) + +set(gen_file ${FETCHCONTENT_BASE_DIR}/passthrough-subbuild/CMakeLists.txt) +if(NOT EXISTS ${gen_file}) + message(FATAL_ERROR "File does not exist: ${gen_file}") +endif() +file(READ ${gen_file} contents) + +if(NOT contents MATCHES "CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY \\[==\\[AAAA\\]==\\]") + message(FATAL_ERROR "Missing CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY") +endif() + +if(NOT contents MATCHES "CMAKE_TLS_VERIFY \\[==\\[BBBB\\]==\\]") + message(FATAL_ERROR "Missing CMAKE_TLS_VERIFY") +endif() + +if(NOT contents MATCHES "CMAKE_TLS_CAINFO \\[==\\[CCCC\\]==\\]") + message(FATAL_ERROR "Missing CMAKE_TLS_CAINFO") +endif() + +if(NOT contents MATCHES "CMAKE_NETRC \\[==\\[DDDD\\]==\\]") + message(FATAL_ERROR "Missing CMAKE_NETRC") +endif() + +if(NOT contents MATCHES "CMAKE_NETRC_FILE \\[==\\[EEEE\\]==\\]") + message(FATAL_ERROR "Missing CMAKE_NETRC_FILE") +endif() From 75901f0472016adfe89e246f3f0cb32d57513f8a Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 30 Sep 2021 11:46:56 -0400 Subject: [PATCH 1348/1519] Tests: Fix RunCMake.XcodeProject XcodeIOSInstallCombined cases for Xcode 13.0 The output of `otool -vf` now contains additional content that happens to be matched by our architectures regex. Make the regex more strict. --- .../XcodeProject/XcodeIOSInstallCombined-install-check.cmake | 4 ++-- .../XcodeIOSInstallCombinedPrune-install-check.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined-install-check.cmake b/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined-install-check.cmake index a1c06718f28..53b885d29b0 100644 --- a/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined-install-check.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined-install-check.cmake @@ -9,8 +9,8 @@ function(verify_architectures file) return() endif() - string(REGEX MATCHALL "architecture [^ \n\t]+" architectures ${otool_out}) - string(REPLACE "architecture " "" actual "${architectures}") + string(REGEX MATCHALL "\narchitecture [^ \n\t()]+" architectures ${otool_out}) + string(REPLACE "\narchitecture " "" actual "${architectures}") list(SORT actual) set(expected arm64 armv7 i386 x86_64) diff --git a/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombinedPrune-install-check.cmake b/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombinedPrune-install-check.cmake index 83da17da7ed..37bb4d59463 100644 --- a/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombinedPrune-install-check.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombinedPrune-install-check.cmake @@ -9,8 +9,8 @@ function(verify_architectures file) return() endif() - string(REGEX MATCHALL "architecture [^ \n\t]+" architectures ${otool_out}) - string(REPLACE "architecture " "" actual "${architectures}") + string(REGEX MATCHALL "\narchitecture [^ \n\t()]+" architectures ${otool_out}) + string(REPLACE "\narchitecture " "" actual "${architectures}") list(SORT actual) set(expected armv7 x86_64) From 429522e89c5322d19d6215cfb7e6a76a74d84874 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 30 Sep 2021 10:37:05 -0400 Subject: [PATCH 1349/1519] gitlab-ci: update macOS jobs to use Xcode 13.0 --- .gitlab/os-macos.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab/os-macos.yml b/.gitlab/os-macos.yml index 9c4a920797a..b79d46d7766 100644 --- a/.gitlab/os-macos.yml +++ b/.gitlab/os-macos.yml @@ -7,7 +7,7 @@ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci ext/$CI_CONCURRENT_ID" # TODO: Factor this out so that each job selects the Xcode version to # use so that different versions can be tested in a single pipeline. - DEVELOPER_DIR: "/Applications/Xcode-12.5.app/Contents/Developer" + DEVELOPER_DIR: "/Applications/Xcode-13.0.app/Contents/Developer" # Avoid conflicting with other projects running on the same machine. SCCACHE_SERVER_PORT: 4227 @@ -87,7 +87,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-12.5 + - xcode-13.0 - nonconcurrent .macos_x86_64_builder_tags_package: @@ -95,7 +95,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-12.5 + - xcode-13.0 - nonconcurrent - finder @@ -104,7 +104,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-12.5 + - xcode-13.0 - concurrent .macos_arm64_builder_tags: @@ -112,7 +112,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos-arm64 - shell - - xcode-12.5 + - xcode-13.0 - nonconcurrent .macos_arm64_builder_ext_tags: @@ -120,7 +120,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos-arm64 - shell - - xcode-12.5 + - xcode-13.0 - concurrent ## macOS-specific scripts From 5895f236ae724418db2a2b3e98163947b55cdb69 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" <erlend.aasland@innova.no> Date: Tue, 5 Oct 2021 09:12:15 +0200 Subject: [PATCH 1350/1519] CPack/IFW: Add support for QtIFW 4.1 Fixes: #22722 --- Modules/CPackIFW.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index 2087a518bca..2e68770a54d 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -439,6 +439,7 @@ set(_CPACK_IFW_PREFIXES "QtIFW-") set(_CPACK_IFW_VERSIONS + "4.1" "4.0" "3.2" "3.2.0" From 5632933304a236f8c7aa227cb69601c82683d0d5 Mon Sep 17 00:00:00 2001 From: Joseph Snyder <joe.snyder@kitware.com> Date: Thu, 30 Sep 2021 12:06:15 -0400 Subject: [PATCH 1351/1519] Tutorial: Add version update instructions to Step 10 Add instructions to update the cmake_minimum_required version to 3.15 just before the usage of COMPILE_LANG_AND_ID Issue: #22663 --- Help/guide/tutorial/Adding Generator Expressions.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index 55acb346fcd..7fcc97fcc25 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -53,6 +53,16 @@ Would be replaced with: :start-after: project(Tutorial VERSION 1.0) :end-before: # add compiler warning flags just when building this project via +**Note**: This upcoming section will require a change to the +:command:`cmake_minimum_required` usage in the code. The Generator Expression +that is about to be used was introduced in `3.15`. Update the call to require +that more recent version: + +.. code-block:: cmake + :caption: CMakeLists.txt + :name: CMakeLists.txt-version-update + + cmake_minimum_required(VERSION 3.15) Next we add the desired compiler warning flags that we want for our project. As warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID`` From 6458a322421dcf097c319321736fb7fd72549078 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 5 Oct 2021 09:47:19 -0400 Subject: [PATCH 1352/1519] bootstrap: Enable cmake_language command to support cmake-gui with Qt 6.2 Fixes: #22721 --- Source/cmCommands.cxx | 4 ++-- bootstrap | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index a241a3a6430..c6296f9f424 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -16,6 +16,7 @@ #include "cmAddTestCommand.h" #include "cmBreakCommand.h" #include "cmBuildCommand.h" +#include "cmCMakeLanguageCommand.h" #include "cmCMakeMinimumRequired.h" #include "cmCMakePathCommand.h" #include "cmCMakePolicyCommand.h" @@ -93,7 +94,6 @@ # include "cmAuxSourceDirectoryCommand.h" # include "cmBuildNameCommand.h" # include "cmCMakeHostSystemInformationCommand.h" -# include "cmCMakeLanguageCommand.h" # include "cmExportCommand.h" # include "cmExportLibraryDependenciesCommand.h" # include "cmFLTKWrapUICommand.h" @@ -128,6 +128,7 @@ void GetScriptingCommands(cmState* state) state->AddFlowControlCommand("return", cmReturnCommand); state->AddFlowControlCommand("while", cmWhileCommand); + state->AddBuiltinCommand("cmake_language", cmCMakeLanguageCommand); state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired); state->AddBuiltinCommand("cmake_path", cmCMakePathCommand); state->AddBuiltinCommand("cmake_policy", cmCMakePolicyCommand); @@ -202,7 +203,6 @@ void GetScriptingCommands(cmState* state) #if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("cmake_host_system_information", cmCMakeHostSystemInformationCommand); - state->AddBuiltinCommand("cmake_language", cmCMakeLanguageCommand); state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("remove", cmRemoveCommand); state->AddBuiltinCommand("variable_watch", cmVariableWatchCommand); diff --git a/bootstrap b/bootstrap index dc5ed0b4776..c7fbed11c9f 100755 --- a/bootstrap +++ b/bootstrap @@ -297,6 +297,7 @@ CMAKE_CXX_SOURCES="\ cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool \ cmBreakCommand \ cmBuildCommand \ + cmCMakeLanguageCommand \ cmCMakeMinimumRequired \ cmCMakePath \ cmCMakePathCommand \ From f8079ec8d0c82d1010bbc889e3faaef50898060b Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:25:54 +0300 Subject: [PATCH 1353/1519] FindBLAS: Update Fujitsu_SSL2 --- Modules/FindBLAS.cmake | 50 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index e22fae318e1..6d6e84d70f8 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -101,10 +101,10 @@ BLAS/LAPACK Vendors ``FlexiBLAS`` .. versionadded:: 3.19 -``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP`` +``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``, ``Fujitsu_SSL2SVE``, ``Fujitsu_SSL2BLAMPSVE`` .. versionadded:: 3.20 - Fujitsu SSL2 serial and parallel blas/lapack + Fujitsu SSL2 serial and parallel blas/lapack with SVE instructions ``Goto`` GotoBLAS @@ -1142,27 +1142,35 @@ endif() # Fujitsu SSL2 Library? if(NOT BLAS_LIBRARIES - AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All")) - if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP") - set(_ssl2_suffix BLAMP) - else() - set(_ssl2_suffix) + AND (BLA_VENDOR MATCHES "^Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All")) + set(_blas_fjlapack_lib "fjlapack") + set(_blas_fjlapack_flags "-Kopenmp") + + if(BLA_VENDOR MATCHES "BLAMP") + string(APPEND _blas_fjlapack_lib "ex") endif() - check_blas_libraries( - BLAS_LIBRARIES - BLAS - sgemm - "-SSL2${_ssl2_suffix}" - "" - "" - "" - "" - ) - if(BLAS_LIBRARIES) - set(BLAS_LINKER_FLAGS "-SSL2${_ssl2_suffix}") - set(_blas_fphsa_req_var BLAS_LINKER_FLAGS) + if(BLA_VENDOR MATCHES "SVE") + string(APPEND _blas_fjlapack_lib "sve") endif() - unset(_ssl2_suffix) + + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "${_blas_fjlapack_flags}" + "${_blas_fjlapack_lib}" + "" + "" + "" + ) + if(BLAS_LIBRARIES) + set(BLAS_LINKER_FLAGS ${_blas_fjlapack_flags}) + endif() + endif() + + unset(_blas_fjlapack_flags) + unset(_blas_fjlapack_lib) endif() # BLAS in nVidia HPC SDK? (https://developer.nvidia.com/hpc-sdk) From 50696efc64b3f992df96a260886fe7c6befa9013 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:47:15 +0300 Subject: [PATCH 1354/1519] FindBLAS: Search 32/64-bit integer API via BLA_SIZEOF_INTEGER if possible --- Modules/FindBLAS.cmake | 106 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 6d6e84d70f8..043d9c17cbb 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -35,6 +35,19 @@ The following variables may be set to influence this module's behavior: if set ``pkg-config`` will be used to search for a BLAS library first and if one is found that is preferred +``BLA_SIZEOF_INTEGER`` + .. versionadded:: 3.22 + + Specify the BLAS/LAPACK library integer size: + + ``4`` + Search for a BLAS/LAPACK with 32-bit integer interfaces. + ``8`` + Search for a BLAS/LAPACK with 64-bit integer interfaces. + ``ANY`` + Search for any BLAS/LAPACK. + Most likely, a BLAS/LAPACK with 32-bit integer interfaces will be found. + Imported targets ^^^^^^^^^^^^^^^^ @@ -372,6 +385,17 @@ else() endif() endif() +if(NOT BLA_SIZEOF_INTEGER) + # in the reality we do not know which API of BLAS/LAPACK is masked in library + set(_blas_sizeof_integer "ANY") +elseif((BLA_SIZEOF_INTEGER STREQUAL "ANY") OR + (BLA_SIZEOF_INTEGER STREQUAL "4") OR + (BLA_SIZEOF_INTEGER STREQUAL "8")) + set(_blas_sizeof_integer ${BLA_SIZEOF_INTEGER}) +else() + message(FATAL_ERROR "BLA_SIZEOF_INTEGER can have only <no value>, ANY, 4, or 8 values") +endif() + # Implicitly linked BLAS libraries? if(BLA_VENDOR STREQUAL "All") if(NOT BLAS_LIBRARIES) @@ -432,10 +456,16 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") find_package(Threads REQUIRED) endif() - if(BLA_VENDOR MATCHES "_64ilp") + if(_blas_sizeof_integer EQUAL 8) set(BLAS_mkl_ILP_MODE "ilp64") - else() + elseif(_blas_sizeof_integer EQUAL 4) set(BLAS_mkl_ILP_MODE "lp64") + else() + if(BLA_VENDOR MATCHES "_64ilp") + set(BLAS_mkl_ILP_MODE "ilp64") + else() + set(BLAS_mkl_ILP_MODE "lp64") + endif() endif() set(BLAS_SEARCH_LIBS "") @@ -677,6 +707,10 @@ endif() if(BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All") set(_blas_flexiblas_lib "flexiblas") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_flexiblas_lib "64") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES @@ -697,6 +731,10 @@ endif() if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All") set(_blas_openblas_lib "openblas") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_openblas_lib "64") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES @@ -745,11 +783,17 @@ endif() if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All") # Check for 64bit Integer support - if(BLA_VENDOR MATCHES "_ilp64") - set(_blas_armpl_lib "armpl_ilp64") - else() - set(_blas_armpl_lib "armpl_lp64") - endif() + if(_blas_sizeof_integer EQUAL 8) + set(_blas_armpl_lib "armpl_ilp64") + elseif(_blas_sizeof_integer EQUAL 4) + set(_blas_armpl_lib "armpl_lp64") + else() + if(BLA_VENDOR MATCHES "_ilp64") + set(_blas_armpl_lib "armpl_ilp64") + else() + set(_blas_armpl_lib "armpl_lp64") + endif() + endif() # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp if(BLA_VENDOR MATCHES "_mp") @@ -775,6 +819,10 @@ endif() if(BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All") set(_blas_flame_lib "blis") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_flame_lib "64") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES @@ -878,6 +926,9 @@ endif() if(BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All") set(_blas_scsl_lib "scs") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_scsl_lib "_i8") + endif() if(BLA_VENDOR MATCHES "_mp") set(_blas_scsl_lib "${_blas_scsl_lib}_mp") endif() @@ -921,6 +972,10 @@ if(BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All") if(BLA_VENDOR MATCHES "_SMP") set(_blas_essl_lib "${_blas_essl_lib}smp") endif() + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_essl_lib "6464") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES @@ -958,7 +1013,7 @@ if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All") list(GET _ACML_GPU_ROOT 0 _ACML_GPU_ROOT) if(_ACML_ROOT) get_filename_component(_ACML_ROOT ${_ACML_ROOT} PATH) - if(SIZEOF_INTEGER EQUAL 8) + if(_blas_sizeof_integer EQUAL 8) set(_ACML_PATH_SUFFIX "_int64") else() set(_ACML_PATH_SUFFIX "") @@ -1120,6 +1175,9 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") set(_blas_eml_lib "eml") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_eml_lib "_ilp64") + endif() # Check for OpenMP support, VIA BLA_VENDOR of eml_mt if(BLA_VENDOR MATCHES "_mt") set(_blas_eml_lib "${_blas_eml_lib}_mt") @@ -1152,6 +1210,9 @@ if(NOT BLAS_LIBRARIES if(BLA_VENDOR MATCHES "SVE") string(APPEND _blas_fjlapack_lib "sve") endif() + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_fjlapack_lib "_ilp64") + endif() if(NOT BLAS_LIBRARIES) check_blas_libraries( @@ -1177,6 +1238,12 @@ endif() if(BLA_VENDOR STREQUAL "NVHPC" OR BLA_VENDOR STREQUAL "All") set(_blas_nvhpc_lib "blas") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_nvhpc_lib "_ilp64") + elseif(_blas_sizeof_integer EQUAL 4) + string(APPEND _blas_nvhpc_lib "_lp64") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES @@ -1190,6 +1257,24 @@ if(BLA_VENDOR STREQUAL "NVHPC" OR BLA_VENDOR STREQUAL "All") ) endif() + # an additional check for NVHPC 2020 + # which does not have differentiation + # between lp64 and ilp64 modes + if(NOT BLAS_LIBRARIES AND NOT _blas_sizeof_integer EQUAL 8) + set(_blas_nvhpc_lib "blas") + + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "${_blas_nvhpc_lib}" + "" + "" + "" + ) + endif() + unset(_blas_nvhpc_lib) endif() @@ -1198,6 +1283,10 @@ if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All") set(_blas_generic_lib "blas") + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_generic_lib "64") + endif() + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES @@ -1226,4 +1315,5 @@ endif() _add_blas_target() unset(_blas_fphsa_req_var) +unset(_blas_sizeof_integer) unset(_BLAS_LIBRARIES) From d2f5c7856f60c3487581ba3b279a4e252d855fa6 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 11:58:01 +0300 Subject: [PATCH 1355/1519] FindLAPACK: Search 32/64-bit integer API via BLA_SIZEOF_INTEGER if possible --- Modules/FindLAPACK.cmake | 86 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 824cfd24a11..dd452737283 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -35,6 +35,19 @@ The following variables may be set to influence this module's behavior: if set ``pkg-config`` will be used to search for a LAPACK library first and if one is found that is preferred +``BLA_SIZEOF_INTEGER`` + .. versionadded:: 3.22 + + Specify the BLAS/LAPACK library integer size: + + ``4`` + Search for a BLAS/LAPACK with 32-bit integer interfaces. + ``8`` + Search for a BLAS/LAPACK with 64-bit integer interfaces. + ``ANY`` + Search for any BLAS/LAPACK. + Most likely, a BLAS/LAPACK with 32-bit integer interfaces will be found. + Imported targets ^^^^^^^^^^^^^^^^ @@ -247,6 +260,17 @@ if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_CO "FindLAPACK requires Fortran, C, or C++ to be enabled.") endif() +if(NOT BLA_SIZEOF_INTEGER) + # in the reality we do not know which API of BLAS/LAPACK is masked in library + set(_lapack_sizeof_integer "ANY") +elseif((BLA_SIZEOF_INTEGER STREQUAL "ANY") OR + (BLA_SIZEOF_INTEGER STREQUAL "4") OR + (BLA_SIZEOF_INTEGER STREQUAL "8")) + set(_lapack_sizeof_integer ${BLA_SIZEOF_INTEGER}) +else() + message(FATAL_ERROR "BLA_SIZEOF_INTEGER can have only <no value>, ANY, 4, or 8 values") +endif() + # Load BLAS if(NOT LAPACK_NOT_FOUND_MESSAGE) _lapack_find_dependency(BLAS) @@ -288,10 +312,16 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) _lapack_find_dependency(Threads) - if(BLA_VENDOR MATCHES "_64ilp") + if(_lapack_sizeof_integer EQUAL 8) set(LAPACK_mkl_ILP_MODE "ilp64") - else() + elseif(_lapack_sizeof_integer EQUAL 4) set(LAPACK_mkl_ILP_MODE "lp64") + else() + if(BLA_VENDOR MATCHES "_64ilp") + set(LAPACK_mkl_ILP_MODE "ilp64") + else() + set(LAPACK_mkl_ILP_MODE "lp64") + endif() endif() set(LAPACK_SEARCH_LIBS "") @@ -420,6 +450,10 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) AND (BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All")) set(_lapack_flexiblas_lib "flexiblas") + if(_lapack_sizeof_integer EQUAL 8) + string(APPEND _lapack_flexiblas_lib "64") + endif() + check_lapack_libraries( LAPACK_LIBRARIES LAPACK @@ -440,6 +474,10 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) AND (BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")) set(_lapack_openblas_lib "openblas") + if(_lapack_sizeof_integer EQUAL 8) + string(APPEND _lapack_openblas_lib "64") + endif() + check_lapack_libraries( LAPACK_LIBRARIES LAPACK @@ -459,10 +497,16 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All")) # Check for 64bit Integer support - if(BLA_VENDOR MATCHES "_ilp64") + if(_lapack_sizeof_integer EQUAL 8) set(LAPACK_armpl_LIB "armpl_ilp64") - else() + elseif(_lapack_sizeof_integer EQUAL 4) set(LAPACK_armpl_LIB "armpl_lp64") + else() + if(BLA_VENDOR MATCHES "_ilp64") + set(LAPACK_armpl_LIB "armpl_ilp64") + else() + set(LAPACK_armpl_LIB "armpl_lp64") + endif() endif() # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp @@ -504,6 +548,9 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) AND (BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All")) set(_lapack_scsl_lib "scs") + if(_lapack_sizeof_integer EQUAL 8) + string(APPEND _lapack_scsl_lib "_i8") + endif() # Check for OpenMP support, VIA BLA_VENDOR of scs_mp if(BLA_VENDOR MATCHES "_mp") set(_lapack_scsl_lib "${_lapack_scsl_lib}_mp") @@ -593,6 +640,12 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All")) set(_lapack_nvhpc_lib "lapack") + if(_lapack_sizeof_integer EQUAL 8) + string(APPEND _lapack_nvhpc_lib "_ilp64") + elseif(_lapack_sizeof_integer EQUAL 4) + string(APPEND _lapack_nvhpc_lib "_lp64") + endif() + check_lapack_libraries( LAPACK_LIBRARIES LAPACK @@ -605,6 +658,25 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) "${BLAS_LIBRARIES}" ) + # an additional check for NVHPC 2020 + # which does not have differentiation + # between lp64 and ilp64 modes + if(NOT LAPACK_LIBRARIES AND NOT _lapack_sizeof_integer EQUAL 8) + set(_lapack_nvhpc_lib "lapack") + + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "${_lapack_nvhpc_lib}" + "-fortranlibs" + "" + "" + "${BLAS_LIBRARIES}" + ) + endif() + unset(_lapack_nvhpc_lib) endif() @@ -621,6 +693,11 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) else() set(_lapack_generic_deps "") endif() + + if(_lapack_sizeof_integer EQUAL 8) + string(APPEND _lapack_generic_lib "64") + endif() + check_lapack_libraries( LAPACK_LIBRARIES LAPACK @@ -662,4 +739,5 @@ endif() _add_lapack_target() unset(_lapack_fphsa_req_var) +unset(_lapack_sizeof_integer) unset(_LAPACK_LIBRARIES) From b8a3cea51fc2853200801d599d873472b80b6619 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 12:01:21 +0300 Subject: [PATCH 1356/1519] FindBLAS: Stop processing if BLAS library does not have 64-bit integer API --- Modules/FindBLAS.cmake | 112 +++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 44 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 043d9c17cbb..f16d176ce2e 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -873,33 +873,45 @@ endif() # BLAS in Alpha CXML library? if(BLA_VENDOR STREQUAL "CXML" OR BLA_VENDOR STREQUAL "All") - if(NOT BLAS_LIBRARIES) - check_blas_libraries( - BLAS_LIBRARIES - BLAS - sgemm - "" - "cxml" - "" - "" - "" - ) + if(_blas_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "CXML") + message(FATAL_ERROR "CXML does not support Int64 type") + endif() + else() + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "cxml" + "" + "" + "" + ) + endif() endif() endif() # BLAS in Alpha DXML library? (now called CXML, see above) if(BLA_VENDOR STREQUAL "DXML" OR BLA_VENDOR STREQUAL "All") - if(NOT BLAS_LIBRARIES) - check_blas_libraries( - BLAS_LIBRARIES - BLAS - sgemm - "" - "dxml" - "" - "" - "" - ) + if(_blas_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "DXML") + message(FATAL_ERROR "DXML does not support Int64 type") + endif() + else() + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "dxml" + "" + "" + "" + ) + endif() endif() endif() @@ -1140,33 +1152,45 @@ endif() # ACML # Apple BLAS library? if(BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All") - if(NOT BLAS_LIBRARIES) - check_blas_libraries( - BLAS_LIBRARIES - BLAS - dgemm - "" - "Accelerate" - "" - "" - "" - ) + if(_blas_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "Apple") + message(FATAL_ERROR "Accelerate Framework does not support Int64 type") + endif() + else() + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + dgemm + "" + "Accelerate" + "" + "" + "" + ) + endif() endif() endif() # Apple NAS (vecLib) library? if(BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All") - if(NOT BLAS_LIBRARIES) - check_blas_libraries( - BLAS_LIBRARIES - BLAS - dgemm - "" - "vecLib" - "" - "" - "" - ) + if(_blas_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "NAS") + message(FATAL_ERROR "Accelerate Framework does not support Int64 type") + endif() + else() + if(NOT BLAS_LIBRARIES) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + dgemm + "" + "vecLib" + "" + "" + "" + ) + endif() endif() endif() From 91fd645d46adeaa22221b0c08307d2dc35b81ade Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 7 Aug 2021 12:02:42 +0300 Subject: [PATCH 1357/1519] FindLAPACK: Stop processing if LAPACK library does not have 64-bit integer API --- Modules/FindLAPACK.cmake | 84 ++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index dd452737283..32d15db2a7f 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -530,17 +530,23 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # FLAME's blis library? (https://github.com/flame/blis) if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")) - check_lapack_libraries( - LAPACK_LIBRARIES - LAPACK - cheev - "" - "flame" - "" - "" - "" - "${BLAS_LIBRARIES}" - ) + if(_lapack_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "FLAME") + message(FATAL_ERROR "libFLAME does not support Int64 type") + endif() + else() + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "flame" + "" + "" + "" + "${BLAS_LIBRARIES}" + ) + endif() endif() # LAPACK in SCSL library? (SGI/Cray Scientific Library) @@ -580,33 +586,45 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # Apple LAPACK library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All")) - check_lapack_libraries( - LAPACK_LIBRARIES - LAPACK - cheev - "" - "Accelerate" - "" - "" - "" - "${BLAS_LIBRARIES}" - ) + if(_lapack_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "Apple") + message(FATAL_ERROR "Accelerate Framework does not support Int64 type") + endif() + else() + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "Accelerate" + "" + "" + "" + "${BLAS_LIBRARIES}" + ) + endif() endif() # Apple NAS (vecLib) library? if(NOT LAPACK_LIBRARIES AND (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All")) - check_lapack_libraries( - LAPACK_LIBRARIES - LAPACK - cheev - "" - "vecLib" - "" - "" - "" - "${BLAS_LIBRARIES}" - ) + if(_lapack_sizeof_integer EQUAL 8) + if(BLA_VENDOR STREQUAL "NAS") + message(FATAL_ERROR "Accelerate Framework does not support Int64 type") + endif() + else() + check_lapack_libraries( + LAPACK_LIBRARIES + LAPACK + cheev + "" + "vecLib" + "" + "" + "" + "${BLAS_LIBRARIES}" + ) + endif() endif() # Elbrus Math Library? From 9b69307b56376e2bd0a82539562f9e59a808194b Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 22 Sep 2021 14:55:42 -0400 Subject: [PATCH 1358/1519] Find{BLAS,LAPACK}: De-duplicate and generalize test creation logic Interpret `CMake_TEST_FindBLAS` and `CMake_TEST_FindLAPACK` as a sequence of option assignments intermixed with vendor names. --- .../ci/configure_debian10_aarch64_ninja.cmake | 6 +-- .gitlab/ci/configure_debian10_ninja.cmake | 6 +-- .gitlab/ci/configure_fedora34_makefiles.cmake | 6 +-- .../ci/configure_intelcompiler_common.cmake | 15 +++--- Tests/FindBLAS/CMakeLists.txt | 51 +------------------ Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake | 43 ++++++++++++++++ Tests/FindLAPACK/CMakeLists.txt | 51 +------------------ 7 files changed, 60 insertions(+), 118 deletions(-) create mode 100644 Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index a6b7cb50a3e..8e03eef59d8 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -1,6 +1,5 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") -set(CMake_TEST_FindBLAS "All" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC "Generic" CACHE STRING "") +set(CMake_TEST_FindBLAS "All;static=1;Generic" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -25,8 +24,7 @@ set(CMake_TEST_FindIconv "ON" CACHE BOOL "") set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") -set(CMake_TEST_FindLAPACK "All" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC "Generic" CACHE STRING "") +set(CMake_TEST_FindLAPACK "All;static=1;Generic" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index 10d0997baff..d50ab1f05a4 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -1,6 +1,5 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") -set(CMake_TEST_FindBLAS "All" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC "Generic" CACHE STRING "") +set(CMake_TEST_FindBLAS "All;static=1;Generic" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -25,8 +24,7 @@ set(CMake_TEST_FindIconv "ON" CACHE BOOL "") set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") -set(CMake_TEST_FindLAPACK "All" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC "Generic" CACHE STRING "") +set(CMake_TEST_FindLAPACK "All;static=1;Generic" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_fedora34_makefiles.cmake b/.gitlab/ci/configure_fedora34_makefiles.cmake index d4bdb6a11e9..a482378a4d3 100644 --- a/.gitlab/ci/configure_fedora34_makefiles.cmake +++ b/.gitlab/ci/configure_fedora34_makefiles.cmake @@ -1,6 +1,5 @@ set(CMake_TEST_FindALSA "ON" CACHE BOOL "") -set(CMake_TEST_FindBLAS "All" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC "Generic" CACHE STRING "") +set(CMake_TEST_FindBLAS "All;static=1;Generic" CACHE STRING "") set(CMake_TEST_FindBoost "ON" CACHE BOOL "") set(CMake_TEST_FindBoost_Python "ON" CACHE BOOL "") set(CMake_TEST_FindBZip2 "ON" CACHE BOOL "") @@ -25,8 +24,7 @@ set(CMake_TEST_FindIconv "ON" CACHE BOOL "") set(CMake_TEST_FindIntl "ON" CACHE BOOL "") set(CMake_TEST_FindJPEG "ON" CACHE BOOL "") set(CMake_TEST_FindJsonCpp "ON" CACHE BOOL "") -set(CMake_TEST_FindLAPACK "All" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC "Generic" CACHE STRING "") +set(CMake_TEST_FindLAPACK "All;static=1;Generic" CACHE STRING "") set(CMake_TEST_FindLibArchive "ON" CACHE BOOL "") set(CMake_TEST_FindLibinput "ON" CACHE BOOL "") set(CMake_TEST_FindLibLZMA "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake index be175e42d5d..2698f887ca6 100644 --- a/.gitlab/ci/configure_intelcompiler_common.cmake +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -1,10 +1,9 @@ -set(CMake_TEST_FindBLAS "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindBLAS_All "Intel10_64lp" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindBLAS_STATIC_All "Intel10_64lp" CACHE STRING "") -set(CMake_TEST_FindLAPACK "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindLAPACK_All "Intel10_64lp" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC "All;Intel10_64lp;Intel10_64lp.gcc" CACHE STRING "") -set(CMake_TEST_FindLAPACK_STATIC_All "Intel10_64lp" CACHE STRING "") +set(blas_lapack_cases + all=Intel10_64lp + static=0 All Intel10_64lp compiler=gcc Intel10_64lp compiler= + static=1 All Intel10_64lp compiler=gcc Intel10_64lp compiler= + ) +set(CMake_TEST_FindBLAS "${blas_lapack_cases}" CACHE STRING "") +set(CMake_TEST_FindLAPACK "${blas_lapack_cases}" CACHE STRING "") include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt index 482cee876e3..00b254dfa40 100644 --- a/Tests/FindBLAS/CMakeLists.txt +++ b/Tests/FindBLAS/CMakeLists.txt @@ -1,49 +1,2 @@ -foreach(variant IN LISTS CMake_TEST_FindBLAS) - if(variant MATCHES "^([^.]+)\\.(.*)$") - set(vendor "${CMAKE_MATCH_1}") - set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") - else() - set(vendor "${variant}") - set(alt_compiler "") - endif() - if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_All) - set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_All}") - else() - set(EXPECT_All "") - endif() - add_test(NAME FindBLAS.Test_${variant} COMMAND - ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> - --build-and-test - "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" - "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}" - ${build_generator_args} - --build-project TestFindBLAS - --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> - ) -endforeach() - -foreach(variant IN LISTS CMake_TEST_FindBLAS_STATIC) - if(variant MATCHES "^([^.]+)\\.(.*)$") - set(vendor "${CMAKE_MATCH_1}") - set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") - else() - set(vendor "${variant}") - set(alt_compiler "") - endif() - if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_STATIC_All) - set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_STATIC_All}") - else() - set(EXPECT_All "") - endif() - add_test(NAME FindBLAS.Test_${variant}_Static COMMAND - ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> - --build-and-test - "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test" - "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}_Static" - ${build_generator_args} - --build-project TestFindBLAS - --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> - ) -endforeach() +include("${CMake_SOURCE_DIR}/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake") +add_BLAS_LAPACK_tests(CMake_TEST_FindBLAS) diff --git a/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake b/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake new file mode 100644 index 00000000000..db334043652 --- /dev/null +++ b/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake @@ -0,0 +1,43 @@ +function(add_BLAS_LAPACK_tests var) + if(var MATCHES "^CMake_TEST_Find(BLAS|LAPACK)$") + set(package "${CMAKE_MATCH_1}") + else() + message(FATAL_ERROR "Test list variable '${var}' not supported.") + endif() + + set(all "") + set(compiler "") + set(static "") + + foreach(variant IN LISTS ${var}) + if(variant MATCHES "^(all|compiler|static)=(.*)$") + set("${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}") + continue() + elseif(variant MATCHES "^([^=]+)=(.*)$") + message(FATAL_ERROR "Unknown variable '${variant}'") + endif() + set(variant_name "${variant}") + set(variant_options "-DBLA_VENDOR=${variant}") + if(variant STREQUAL "All" AND all) + list(APPEND variant_options "-DEXPECT_All=${all}") + endif() + if(compiler) + string(APPEND variant_name "_${compiler}") + list(APPEND variant_options "-DCMAKE_C_COMPILER=${compiler}") + endif() + if(static) + string(APPEND variant_name "_Static") + list(APPEND variant_options "-DBLA_STATIC=ON") + endif() + add_test(NAME Find${package}.Test_${variant_name} COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Find${package}/Test" + "${CMake_BINARY_DIR}/Tests/Find${package}/Test_${variant_name}" + ${build_generator_args} + --build-project TestFind${package} + --build-options ${build_options} ${variant_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + endforeach() +endfunction() diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt index 535c7b60e2a..a2470ef148f 100644 --- a/Tests/FindLAPACK/CMakeLists.txt +++ b/Tests/FindLAPACK/CMakeLists.txt @@ -1,49 +1,2 @@ -foreach(variant IN LISTS CMake_TEST_FindLAPACK) - if(variant MATCHES "^([^.]+)\\.(.*)$") - set(vendor "${CMAKE_MATCH_1}") - set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") - else() - set(vendor "${variant}") - set(alt_compiler "") - endif() - if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_All) - set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_All}") - else() - set(EXPECT_All "") - endif() - add_test(NAME FindLAPACK.Test_${variant} COMMAND - ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> - --build-and-test - "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" - "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}" - ${build_generator_args} - --build-project TestFindLAPACK - --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> - ) -endforeach() - -foreach(variant IN LISTS CMake_TEST_FindLAPACK_STATIC) - if(variant MATCHES "^([^.]+)\\.(.*)$") - set(vendor "${CMAKE_MATCH_1}") - set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}") - else() - set(vendor "${variant}") - set(alt_compiler "") - endif() - if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_STATIC_All) - set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_STATIC_All}") - else() - set(EXPECT_All "") - endif() - add_test(NAME FindLAPACK.Test_${variant}_Static COMMAND - ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> - --build-and-test - "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test" - "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}_Static" - ${build_generator_args} - --build-project TestFindLAPACK - --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> - ) -endforeach() +include("${CMake_SOURCE_DIR}/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake") +add_BLAS_LAPACK_tests(CMake_TEST_FindLAPACK) From 2cd94f3e57e843fa392f3c50d2c141c938b48112 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 4 Sep 2021 11:43:08 +0900 Subject: [PATCH 1359/1519] Find{BLAS,LAPACK}: Specify integer type in tests --- Tests/FindBLAS/Test/main.c | 10 ++++++---- Tests/FindLAPACK/Test/main.c | 13 ++++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Tests/FindBLAS/Test/main.c b/Tests/FindBLAS/Test/main.c index e61b02cbe8c..8e585594b67 100644 --- a/Tests/FindBLAS/Test/main.c +++ b/Tests/FindBLAS/Test/main.c @@ -1,16 +1,18 @@ #include <assert.h> #include <string.h> +typedef int blas_int; + // declare what parts of the blas C-API we need -void dswap_(int* N, double* X, int* incX, double* Y, int* incY); +void dswap_(blas_int* N, double* X, blas_int* incX, double* Y, blas_int* incY); int main() { double x[4] = { 1, 2, 3, 4 }; double y[4] = { 8, 7, 7, 6 }; - int N = 4; - int incX = 1; - int incY = 1; + blas_int N = 4; + blas_int incX = 1; + blas_int incY = 1; dswap_(&N, x, &incX, y, &incY); return 0; } diff --git a/Tests/FindLAPACK/Test/main.c b/Tests/FindLAPACK/Test/main.c index 5873e7b471c..04eedeae16b 100644 --- a/Tests/FindLAPACK/Test/main.c +++ b/Tests/FindLAPACK/Test/main.c @@ -1,8 +1,11 @@ #include <assert.h> #include <string.h> +typedef int blas_int; + // declare what parts of the lapack C-API we need -void dgesv_(int*, int*, double*, int*, int*, double*, int*, int*); +void dgesv_(blas_int*, blas_int*, double*, blas_int*, blas_int*, double*, + blas_int*, blas_int*); int main() { @@ -10,11 +13,11 @@ int main() 0, 1, 2, 3, 4, 5, 6, 7, }; double B[2] = { 0, 5 }; - int ipiv[2] = { 0, 0 }; - int info = 0; + blas_int ipiv[2] = { 0, 0 }; + blas_int info = 0; - int dim = 2; - int numCols = 1; + blas_int dim = 2; + blas_int numCols = 1; dgesv_(&dim, &numCols, A, &dim, ipiv, B, &dim, &info); return 0; } From 95219365ff76d9f28eb0c09cf2ad73312a2da11f Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 4 Sep 2021 11:35:22 +0900 Subject: [PATCH 1360/1519] Find{BLAS,LAPACK}: Make possible testing of ILP64 model --- Tests/FindBLAS/Test/CMakeLists.txt | 5 +++++ Tests/FindLAPACK/Test/CMakeLists.txt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt index 73797496a80..bbe2ddcd500 100644 --- a/Tests/FindBLAS/Test/CMakeLists.txt +++ b/Tests/FindBLAS/Test/CMakeLists.txt @@ -17,4 +17,9 @@ if((BLA_VENDOR STREQUAL "Intel10_64lp") OR if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64") message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_lp64:\n ${BLAS_LIBRARIES}") endif() +elseif((BLA_VENDOR STREQUAL "Intel10_64ilp") OR + (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64ilp")) + if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_ilp64") + message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_ilp64:\n ${BLAS_LIBRARIES}") + endif() endif() diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt index 23a43acec49..21b1303001f 100644 --- a/Tests/FindLAPACK/Test/CMakeLists.txt +++ b/Tests/FindLAPACK/Test/CMakeLists.txt @@ -17,4 +17,9 @@ if((BLA_VENDOR STREQUAL "Intel10_64lp") OR if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64") message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_lp64:\n ${LAPACK_LIBRARIES}") endif() +elseif((BLA_VENDOR STREQUAL "Intel10_64ilp") OR + (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64ilp")) + if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_ilp64") + message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_ilp64:\n ${LAPACK_LIBRARIES}") + endif() endif() From 972489ae4e22179028b5e3ed8f908100665a368d Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Sat, 4 Sep 2021 11:35:22 +0900 Subject: [PATCH 1361/1519] Find{BLAS,LAPACK}: Provide testing of BLA_SIZEOF_INTEGER --- .gitlab/ci/configure_intelcompiler_common.cmake | 6 +++++- Tests/FindBLAS/Test/CMakeLists.txt | 6 ++++++ Tests/FindBLAS/Test/main.c | 9 ++++++++- Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake | 12 +++++++++++- Tests/FindLAPACK/Test/CMakeLists.txt | 6 ++++++ Tests/FindLAPACK/Test/main.c | 9 ++++++++- 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/.gitlab/ci/configure_intelcompiler_common.cmake b/.gitlab/ci/configure_intelcompiler_common.cmake index 2698f887ca6..bd34740f0cf 100644 --- a/.gitlab/ci/configure_intelcompiler_common.cmake +++ b/.gitlab/ci/configure_intelcompiler_common.cmake @@ -1,7 +1,11 @@ set(blas_lapack_cases - all=Intel10_64lp + model=lp64 all=Intel10_64lp static=0 All Intel10_64lp compiler=gcc Intel10_64lp compiler= static=1 All Intel10_64lp compiler=gcc Intel10_64lp compiler= + + model=ilp64 all=Intel10_64ilp + static=0 All Intel10_64ilp compiler=gcc Intel10_64ilp compiler= + static=1 All Intel10_64ilp compiler=gcc Intel10_64ilp compiler= ) set(CMake_TEST_FindBLAS "${blas_lapack_cases}" CACHE STRING "") set(CMake_TEST_FindLAPACK "${blas_lapack_cases}" CACHE STRING "") diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt index bbe2ddcd500..14bf19f391c 100644 --- a/Tests/FindBLAS/Test/CMakeLists.txt +++ b/Tests/FindBLAS/Test/CMakeLists.txt @@ -4,12 +4,18 @@ include(CTest) find_package(BLAS REQUIRED) +if(NOT BLA_SIZEOF_INTEGER) + set(BLA_SIZEOF_INTEGER 4) +endif() + add_executable(test_tgt main.c) target_link_libraries(test_tgt BLAS::BLAS) +target_compile_definitions(test_tgt PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER}) add_test(NAME test_tgt COMMAND test_tgt) add_executable(test_var main.c) target_link_libraries(test_var PRIVATE ${BLAS_LIBRARIES}) +target_compile_definitions(test_var PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER}) add_test(NAME test_var COMMAND test_var) if((BLA_VENDOR STREQUAL "Intel10_64lp") OR diff --git a/Tests/FindBLAS/Test/main.c b/Tests/FindBLAS/Test/main.c index 8e585594b67..4fc9fe4495a 100644 --- a/Tests/FindBLAS/Test/main.c +++ b/Tests/FindBLAS/Test/main.c @@ -1,7 +1,14 @@ #include <assert.h> +#include <stdint.h> #include <string.h> -typedef int blas_int; +#if BLA_SIZEOF_INTEGER == 4 +typedef int32_t blas_int; +#elif BLA_SIZEOF_INTEGER == 8 +typedef int64_t blas_int; +#else +# error BLA_SIZEOF_INTEGER is not declared! +#endif // declare what parts of the blas C-API we need void dswap_(blas_int* N, double* X, blas_int* incX, double* Y, blas_int* incY); diff --git a/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake b/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake index db334043652..42fe386f9ec 100644 --- a/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake +++ b/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake @@ -7,10 +7,14 @@ function(add_BLAS_LAPACK_tests var) set(all "") set(compiler "") + set(model "") set(static "") + set(sizeof_int_lp64 4) + set(sizeof_int_ilp64 8) + foreach(variant IN LISTS ${var}) - if(variant MATCHES "^(all|compiler|static)=(.*)$") + if(variant MATCHES "^(all|compiler|model|static)=(.*)$") set("${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}") continue() elseif(variant MATCHES "^([^=]+)=(.*)$") @@ -21,6 +25,12 @@ function(add_BLAS_LAPACK_tests var) if(variant STREQUAL "All" AND all) list(APPEND variant_options "-DEXPECT_All=${all}") endif() + if(model) + if(NOT variant_name MATCHES "Intel10_64") + string(APPEND variant_name "_${model}") + endif() + list(APPEND variant_options "-DBLA_SIZEOF_INTEGER=${sizeof_int_${model}}") + endif() if(compiler) string(APPEND variant_name "_${compiler}") list(APPEND variant_options "-DCMAKE_C_COMPILER=${compiler}") diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt index 21b1303001f..f5d5a7391dd 100644 --- a/Tests/FindLAPACK/Test/CMakeLists.txt +++ b/Tests/FindLAPACK/Test/CMakeLists.txt @@ -4,12 +4,18 @@ include(CTest) find_package(LAPACK REQUIRED) +if(NOT BLA_SIZEOF_INTEGER) + set(BLA_SIZEOF_INTEGER 4) +endif() + add_executable(test_tgt main.c) target_link_libraries(test_tgt LAPACK::LAPACK) +target_compile_definitions(test_tgt PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER}) add_test(NAME test_tgt COMMAND test_tgt) add_executable(test_var main.c) target_link_libraries(test_var PRIVATE ${LAPACK_LIBRARIES}) +target_compile_definitions(test_var PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER}) add_test(NAME test_var COMMAND test_var) if((BLA_VENDOR STREQUAL "Intel10_64lp") OR diff --git a/Tests/FindLAPACK/Test/main.c b/Tests/FindLAPACK/Test/main.c index 04eedeae16b..dd33fb39a86 100644 --- a/Tests/FindLAPACK/Test/main.c +++ b/Tests/FindLAPACK/Test/main.c @@ -1,7 +1,14 @@ #include <assert.h> +#include <stdint.h> #include <string.h> -typedef int blas_int; +#if BLA_SIZEOF_INTEGER == 4 +typedef int32_t blas_int; +#elif BLA_SIZEOF_INTEGER == 8 +typedef int64_t blas_int; +#else +# error BLA_SIZEOF_INTEGER is not declared! +#endif // declare what parts of the lapack C-API we need void dgesv_(blas_int*, blas_int*, double*, blas_int*, blas_int*, double*, From 64038fd5bc901f90cf0ab5a76b562db455d66c22 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 14 Sep 2021 10:32:27 -0400 Subject: [PATCH 1362/1519] Help: Add release notes for Find{BLAS,LAPACK} BLA_SIZEOF_INTEGER option --- Help/release/dev/find-blas-lapack-sizeof-integer.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Help/release/dev/find-blas-lapack-sizeof-integer.rst diff --git a/Help/release/dev/find-blas-lapack-sizeof-integer.rst b/Help/release/dev/find-blas-lapack-sizeof-integer.rst new file mode 100644 index 00000000000..bb206548516 --- /dev/null +++ b/Help/release/dev/find-blas-lapack-sizeof-integer.rst @@ -0,0 +1,6 @@ +find-blas-lapack-sizeof-integer +------------------------------- + +* The :module:`FindBLAS` and :module:`FindLAPACK` modules gained + a ``BLA_SIZEOF_INTEGER`` option to find a BLAS/LAPACK whose ABI + uses a specific integer size. From 3b581ab3aafe76e420db2e397b24d86f4064d2b2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 5 Oct 2021 10:21:57 -0400 Subject: [PATCH 1363/1519] ci: Enable CTest.Update{CVS,SVN,HG} tests Enable all three in Debian builds. Leave out CVS in Fedora builds because the cvs package was not built with `--enable-rootcommit`. --- .gitlab/ci/docker/debian10-aarch64/install_deps.sh | 6 ++++++ .gitlab/ci/docker/debian10/install_deps.sh | 6 ++++++ .gitlab/ci/docker/fedora34/install_deps.sh | 5 +++++ .gitlab/os-linux.yml | 6 +++--- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh index f2ffcd6204f..d7f4f9c8f85 100755 --- a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh +++ b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh @@ -23,6 +23,12 @@ apt-get install -y \ apt-get install -y \ jq +# Packages needed to test CTest. +apt-get install -y \ + cvs \ + subversion \ + mercurial + # Packages needed to test find modules. apt-get install -y \ alsa-utils \ diff --git a/.gitlab/ci/docker/debian10/install_deps.sh b/.gitlab/ci/docker/debian10/install_deps.sh index 14dc67dcc28..b4d0f8676b5 100755 --- a/.gitlab/ci/docker/debian10/install_deps.sh +++ b/.gitlab/ci/docker/debian10/install_deps.sh @@ -23,6 +23,12 @@ apt-get install -y \ apt-get install -y \ jq +# Packages needed to test CTest. +apt-get install -y \ + cvs \ + subversion \ + mercurial + # Packages needed to test find modules. apt-get install -y \ alsa-utils \ diff --git a/.gitlab/ci/docker/fedora34/install_deps.sh b/.gitlab/ci/docker/fedora34/install_deps.sh index 878b5f868d6..bef3a97e708 100755 --- a/.gitlab/ci/docker/fedora34/install_deps.sh +++ b/.gitlab/ci/docker/fedora34/install_deps.sh @@ -36,6 +36,11 @@ dnf install --setopt=install_weak_deps=False -y \ jq \ which +# Packages needed to test CTest. +dnf install --setopt=install_weak_deps=False -y \ + subversion \ + mercurial + # Packages needed to test CPack. dnf install --setopt=install_weak_deps=False -y \ rpm-build diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 95cab05e59f..b814655146d 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -45,7 +45,7 @@ ### Debian .debian10: - image: "kitware/cmake:ci-debian10-x86_64-2021-06-28" + image: "kitware/cmake:ci-debian10-x86_64-2021-10-05" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -60,7 +60,7 @@ CMake_SKIP_INSTALL: 1 .debian10_aarch64: - image: "kitware/cmake:ci-debian10-aarch64-2021-06-28" + image: "kitware/cmake:ci-debian10-aarch64-2021-10-05" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -69,7 +69,7 @@ ### Fedora .fedora34: - image: "kitware/cmake:ci-fedora34-x86_64-2021-06-28" + image: "kitware/cmake:ci-fedora34-x86_64-2021-10-05" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" From f4387c197d39fe0b96a7e2aeda769792c8680e44 Mon Sep 17 00:00:00 2001 From: Sean McBride <sean@rogue-research.com> Date: Tue, 5 Oct 2021 11:34:18 -0400 Subject: [PATCH 1364/1519] CPack/OSXX11: Fix Clang 13 Wunused-but-set-variable Use the success/fail flag for the function return value. --- Source/CPack/OSXScriptLauncher.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index bdaf779af15..b7140abd7e9 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -118,5 +118,5 @@ int main(int argc, char* argv[]) cmsysProcess_Delete(cp); - return 0; + return !result; } From 32574814c78fb67cbe23dd1352ca304ec804d4e2 Mon Sep 17 00:00:00 2001 From: Steven Hahn <hahnse@ornl.gov> Date: Mon, 4 Oct 2021 14:20:24 -0400 Subject: [PATCH 1365/1519] FindCUDAToolkit: Fix missing sibling include directory for math libraries Fixes: #22706 --- Modules/FindCUDAToolkit.cmake | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 92042d23c42..d22a6765ea6 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -742,6 +742,19 @@ elseif(NOT CUDAToolkit_FIND_QUIETLY) message(STATUS "Unable to find cuda_runtime.h in \"${CUDAToolkit_TARGET_DIR}/include\" for CUDAToolkit_INCLUDE_DIR.") endif() +# The NVHPC layout moves math library headers and libraries to a sibling directory. +# Create a separate variable so this directory can be selectively added to math targets. +if(NOT EXISTS "${CUDAToolkit_INCLUDE_DIR}/cublas_v2.h") + set(CUDAToolkit_MATH_INCLUDE_DIR "${CUDAToolkit_TARGET_DIR}/../../math_libs/include") + cmake_path(NORMAL_PATH CUDAToolkit_MATH_INCLUDE_DIR) + if(NOT EXISTS "${CUDAToolkit_MATH_INCLUDE_DIR}/cublas_v2.h") + if(NOT CUDAToolkit_FIND_QUIETLY) + message(STATUS "Unable to find cublas_v2.h in either \"${CUDAToolkit_INCLUDE_DIR}\" or \"${CUDAToolkit_MATH_INCLUDE_DIR}\"") + endif() + unset(CUDAToolkit_MATH_INCLUDE_DIR) + endif() +endif() + if(CUDAToolkit_NVCC_EXECUTABLE AND CMAKE_CUDA_COMPILER_VERSION AND CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER) @@ -854,6 +867,12 @@ if(CUDAToolkit_FOUND) if (NOT TARGET CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY) add_library(CUDA::${lib_name} UNKNOWN IMPORTED) target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}") + if(DEFINED CUDAToolkit_MATH_INCLUDE_DIR) + string(FIND ${CUDA_${lib_name}_LIBRARY} "math_libs" math_libs) + if(NOT ${math_libs} EQUAL -1) + target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_MATH_INCLUDE_DIR}") + endif() + endif() set_property(TARGET CUDA::${lib_name} PROPERTY IMPORTED_LOCATION "${CUDA_${lib_name}_LIBRARY}") foreach(dep ${arg_DEPS}) if(TARGET CUDA::${dep}) From 380f9020eb2935861dbfd3a5549c7289eadfb33b Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Wed, 6 Oct 2021 00:01:13 -0400 Subject: [PATCH 1366/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index db86b722485..cff48061adc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211005) +set(CMake_VERSION_PATCH 20211006) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 5c4424e5b7d014eae7fc6951d4af32102f198306 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 6 Oct 2021 09:56:08 -0400 Subject: [PATCH 1367/1519] CMakeDetermineCompilerId: Tolerate variables named for languages --- Modules/CMakeDetermineCompilerId.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index b38de8a1e7b..258249753c7 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -539,7 +539,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} else() set(id_toolset "") endif() - if("${lang}" STREQUAL "Swift") + if("x${lang}" STREQUAL "xSwift") if(CMAKE_Swift_LANGUAGE_VERSION) set(id_lang_version "SWIFT_VERSION = ${CMAKE_Swift_LANGUAGE_VERSION};") elseif(XCODE_VERSION VERSION_GREATER_EQUAL 10.2) From 3add62462cfd91ad8f73bbbdab3f5e4e72c50a98 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 6 Oct 2021 09:36:56 -0400 Subject: [PATCH 1368/1519] Xcode: Fix detection of default language standard when given -std= flags If one uses `CFLAGS='-std=...'` or `CXXFLAGS='-std=...'` then the given `-std=` flag(s) will always be used. That effectively changes the compiler default standard level and extension settings. Fix the Xcode generator's compiler id logic to preserve any `-std=` flag so that the proper defaults are detected. This problem was exposed by commit 4a0485be7f (cmStandardLevelResolver: Avoid unnecessary flags, fix unset level logic, 2021-05-29), which changed the logic to not pass any `-std=` flag if the standard level and extension settings requested by the project match the default (`stdIt <= defaultStdIt` became `stdIt < defaultStdIt`). The new logic assumes the detected default standard matches what will actually happen when the project is generated. --- Modules/CMakeDetermineCompilerId.cmake | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 258249753c7..fa283fec14c 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -539,6 +539,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} else() set(id_toolset "") endif() + set(id_lang_version "") if("x${lang}" STREQUAL "xSwift") if(CMAKE_Swift_LANGUAGE_VERSION) set(id_lang_version "SWIFT_VERSION = ${CMAKE_Swift_LANGUAGE_VERSION};") @@ -549,8 +550,14 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} else() set(id_lang_version "SWIFT_VERSION = 2.3;") endif() - else() - set(id_lang_version "") + elseif("x${lang}" STREQUAL "xC" OR "x${lang}" STREQUAL "xOBJC") + if(CMAKE_${lang}_COMPILER_ID_FLAGS MATCHES "(^| )(-std=[^ ]+)( |$)") + set(id_lang_version "OTHER_CFLAGS = \"${CMAKE_MATCH_2}\";") + endif() + elseif("x${lang}" STREQUAL "xCXX" OR "x${lang}" STREQUAL "xOBJCXX") + if(CMAKE_${lang}_COMPILER_ID_FLAGS MATCHES "(^| )(-std=[^ ]+)( |$)") + set(id_lang_version "OTHER_CPLUSPLUSFLAGS = \"${CMAKE_MATCH_2}\";") + endif() endif() if(CMAKE_OSX_DEPLOYMENT_TARGET) set(id_deployment_target From 524205a7a520abc77283103c01e0098d2d008a8f Mon Sep 17 00:00:00 2001 From: Hiroshi Miura <miurahr@linux.com> Date: Wed, 6 Oct 2021 09:39:02 +0900 Subject: [PATCH 1369/1519] FindJasper: Modernize code layout --- Modules/FindJasper.cmake | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/Modules/FindJasper.cmake b/Modules/FindJasper.cmake index 729a50350d3..9bb4dd825a1 100644 --- a/Modules/FindJasper.cmake +++ b/Modules/FindJasper.cmake @@ -18,30 +18,26 @@ Once done this will define #]=======================================================================] find_path(JASPER_INCLUDE_DIR jasper/jasper.h) +mark_as_advanced(JASPER_INCLUDE_DIR) -if (NOT JASPER_LIBRARIES) - find_package(JPEG) - - find_library(JASPER_LIBRARY_RELEASE NAMES jasper libjasper) - find_library(JASPER_LIBRARY_DEBUG NAMES jasperd) - - include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) - SELECT_LIBRARY_CONFIGURATIONS(JASPER) -endif () - -if (JASPER_INCLUDE_DIR AND EXISTS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h") - file(STRINGS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h" jasper_version_str REGEX "^#define[\t ]+JAS_VERSION[\t ]+\".*\".*") +if(NOT JASPER_LIBRARIES) + find_package(JPEG) + find_library(JASPER_LIBRARY_RELEASE NAMES jasper libjasper) + find_library(JASPER_LIBRARY_DEBUG NAMES jasperd) + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) + select_library_configurations(JASPER) +endif() - string(REGEX REPLACE "^#define[\t ]+JAS_VERSION[\t ]+\"([^\"]+)\".*" "\\1" JASPER_VERSION_STRING "${jasper_version_str}") -endif () +if(JASPER_INCLUDE_DIR AND EXISTS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h") + file(STRINGS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h" jasper_version_str REGEX "^#define[\t ]+JAS_VERSION[\t ]+\".*\".*") + string(REGEX REPLACE "^#define[\t ]+JAS_VERSION[\t ]+\"([^\"]+)\".*" "\\1" JASPER_VERSION_STRING "${jasper_version_str}") +endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Jasper +find_package_handle_standard_args(Jasper REQUIRED_VARS JASPER_LIBRARIES JASPER_INCLUDE_DIR JPEG_LIBRARIES VERSION_VAR JASPER_VERSION_STRING) -if (JASPER_FOUND) - set(JASPER_LIBRARIES ${JASPER_LIBRARIES} ${JPEG_LIBRARIES} ) -endif () - -mark_as_advanced(JASPER_INCLUDE_DIR) +if(JASPER_FOUND) + set(JASPER_LIBRARIES ${JASPER_LIBRARIES} ${JPEG_LIBRARIES}) +endif() From 7f8413c3093220cd26e6196e473cdff00754f7e8 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura <miurahr@linux.com> Date: Wed, 6 Oct 2021 09:39:02 +0900 Subject: [PATCH 1370/1519] FindJasper: Modernize documentation layout --- Modules/FindJasper.cmake | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/Modules/FindJasper.cmake b/Modules/FindJasper.cmake index 9bb4dd825a1..5eb96e4c0c7 100644 --- a/Modules/FindJasper.cmake +++ b/Modules/FindJasper.cmake @@ -5,16 +5,33 @@ FindJasper ---------- -Try to find the Jasper JPEG2000 library +Find the Jasper JPEG2000 library. -Once done this will define +Result Variables +^^^^^^^^^^^^^^^^ -:: +This module defines the following variables: - JASPER_FOUND - system has Jasper - JASPER_INCLUDE_DIR - the Jasper include directory - JASPER_LIBRARIES - the libraries needed to use Jasper - JASPER_VERSION_STRING - the version of Jasper found (since CMake 2.8.8) +``JASPER_FOUND`` + system has Jasper +``JASPER_INCLUDE_DIR`` + the Jasper include directory +``JASPER_LIBRARIES`` + the libraries needed to use Jasper +``JASPER_VERSION_STRING`` + the version of Jasper found + +Cache variables +^^^^^^^^^^^^^^^ + +The following cache variables may also be set: + +``JASPER_INCLUDE_DIR`` + where to find jasper/jasper.h, etc. +``JASPER_LIBRARY_RELEASE`` + where to find the Jasper library (optimized). +``JASPER_LIBARRY_DEBUG`` + where to find the Jasper library (debug). #]=======================================================================] find_path(JASPER_INCLUDE_DIR jasper/jasper.h) From bdbce845cd714a1e844976e4cba4734932e89dd5 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura <miurahr@linux.com> Date: Wed, 6 Oct 2021 09:39:02 +0900 Subject: [PATCH 1371/1519] FindJasper: Add JASPER_INCLUDE_DIRS result variable The `JASPER_INCLUDE_DIR` cache entry is not supposed to be the public result variable. --- Modules/FindJasper.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/FindJasper.cmake b/Modules/FindJasper.cmake index 5eb96e4c0c7..0ca0f3197c6 100644 --- a/Modules/FindJasper.cmake +++ b/Modules/FindJasper.cmake @@ -14,7 +14,9 @@ This module defines the following variables: ``JASPER_FOUND`` system has Jasper -``JASPER_INCLUDE_DIR`` +``JASPER_INCLUDE_DIRS`` + .. versionadded:: 3.22 + the Jasper include directory ``JASPER_LIBRARIES`` the libraries needed to use Jasper @@ -57,4 +59,5 @@ find_package_handle_standard_args(Jasper if(JASPER_FOUND) set(JASPER_LIBRARIES ${JASPER_LIBRARIES} ${JPEG_LIBRARIES}) + set(JASPER_INCLUDE_DIRS ${JASPER_INCLUDE_DIR}) endif() From 6e8754c6251bc2f7edfb0d71303e1b85fce93f5e Mon Sep 17 00:00:00 2001 From: Hiroshi Miura <miurahr@linux.com> Date: Wed, 6 Oct 2021 09:39:02 +0900 Subject: [PATCH 1372/1519] FindJasper: Add IMPORTED target Fixes: #20601 Signed-off-by: Hiroshi Miura <miurahr@linux.com> --- .../dev/FindJasper-imported-target.rst | 4 +++ Modules/FindJasper.cmake | 27 +++++++++++++++++++ Tests/CMakeLists.txt | 1 + Tests/FindJasper/CMakeLists.txt | 10 +++++++ Tests/FindJasper/Test/CMakeLists.txt | 16 +++++++++++ Tests/FindJasper/Test/main.c | 17 ++++++++++++ 6 files changed, 75 insertions(+) create mode 100644 Help/release/dev/FindJasper-imported-target.rst create mode 100644 Tests/FindJasper/CMakeLists.txt create mode 100644 Tests/FindJasper/Test/CMakeLists.txt create mode 100644 Tests/FindJasper/Test/main.c diff --git a/Help/release/dev/FindJasper-imported-target.rst b/Help/release/dev/FindJasper-imported-target.rst new file mode 100644 index 00000000000..33ee88526bc --- /dev/null +++ b/Help/release/dev/FindJasper-imported-target.rst @@ -0,0 +1,4 @@ +FindJasper-imported-target +-------------------------- + +* The :module:`FindJasper` module now provides an imported target. diff --git a/Modules/FindJasper.cmake b/Modules/FindJasper.cmake index 0ca0f3197c6..9a62669f2df 100644 --- a/Modules/FindJasper.cmake +++ b/Modules/FindJasper.cmake @@ -7,6 +7,12 @@ FindJasper Find the Jasper JPEG2000 library. +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +``Jasper::Jasper`` + The jasper library, if found. + Result Variables ^^^^^^^^^^^^^^^^ @@ -60,4 +66,25 @@ find_package_handle_standard_args(Jasper if(JASPER_FOUND) set(JASPER_LIBRARIES ${JASPER_LIBRARIES} ${JPEG_LIBRARIES}) set(JASPER_INCLUDE_DIRS ${JASPER_INCLUDE_DIR}) + if(NOT TARGET Jasper::Jasper) + add_library(Jasper::Jasper UNKNOWN IMPORTED) + if(JASPER_INCLUDE_DIRS) + set_target_properties(Jasper::Jasper PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${JASPER_INCLUDE_DIRS}") + endif() + if(EXISTS "${JASPER_LIBRARY_RELEASE}") + set_property(TARGET Jasper::Jasper APPEND PROPERTY + IMPORTED CONFIGURATION RELEASE) + set_target_properties(Jasper::Jasper PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION "${JASPER_LIBRARY_RELEASE}") + endif() + if(EXISTS "${JASPER_LIBRARY_DEBUG}") + set_property(TARGET Jasper::Jasper APPEND PROPERTY + IMPORTED CONFIGURATION DEBUG) + set_target_properties(Jasper::Jasper PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" + IMPORTED_LOCATION "${JASPER_LIBRARY_DEBUG}") + endif() + endif() endif() diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 20b6e251e7d..d1f7b6979b8 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1466,6 +1466,7 @@ if(BUILD_TESTING) Iconv ICU Intl + Jasper JPEG JsonCpp LAPACK diff --git a/Tests/FindJasper/CMakeLists.txt b/Tests/FindJasper/CMakeLists.txt new file mode 100644 index 00000000000..1bfae78d22a --- /dev/null +++ b/Tests/FindJasper/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindJasper.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindJasper/Test" + "${CMake_BINARY_DIR}/Tests/FindJasper/Test" + ${build_generator_args} + --build-project TestFindJasper + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindJasper/Test/CMakeLists.txt b/Tests/FindJasper/Test/CMakeLists.txt new file mode 100644 index 00000000000..1e9467d49ff --- /dev/null +++ b/Tests/FindJasper/Test/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.21) +project(TestFindJasper C) +include(CTest) + +find_package(Jasper) + +add_definitions(-DCMAKE_EXPECTED_JASPER_VERSION=${JASPER_VERSION_STRING}) + +add_executable(test_jasper_tgt main.c) +target_link_libraries(test_jasper_tgt Jasper::Jasper) +add_test(NAME test_jasper_tgt COMMAND test_jasper_tgt) + +add_executable(test_jasper_var main.c) +target_include_directories(test_jasper_var PRIVATE ${JASPER_INCLUDE_DIRS}) +target_link_libraries(test_jasper_var PRIVATE ${JASPER_LIBRARIES}) +add_test(NAME test_jasper_var COMMAND test_jasper_var) diff --git a/Tests/FindJasper/Test/main.c b/Tests/FindJasper/Test/main.c new file mode 100644 index 00000000000..771344deab3 --- /dev/null +++ b/Tests/FindJasper/Test/main.c @@ -0,0 +1,17 @@ +#include <assert.h> +// clang-format off +#include <stdio.h> +#include <jasper/jasper.h> +// clang-format on + +int main() +{ + /* Without any JPEG file to open, test that the call fails as + expected. This tests that linking worked. */ + jas_init(); + jas_image_t* img = jas_image_create0(); + jas_image_destroy(img); + jas_cleanup(); + + return (JAS_VERSION != CMAKE_EXPECTED_JASPER_VERSION); +} From 6dd924563500c76b63fdb59d5b0ff3a65f45aaf2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 6 Oct 2021 13:22:32 -0400 Subject: [PATCH 1373/1519] gitlab-ci: Add cmake and ninja to PATH incrementally --- .gitlab/os-linux.yml | 3 ++- .gitlab/os-macos.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index de370db9d95..7fce1770daa 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -321,8 +321,9 @@ .before_script_linux: &before_script_linux - source .gitlab/ci/env.sh - .gitlab/ci/cmake.sh + - export PATH=$PWD/.gitlab/cmake/bin:$PATH - .gitlab/ci/ninja.sh - - export PATH=$PWD/.gitlab:$PWD/.gitlab/cmake/bin:$PATH + - export PATH=$PWD/.gitlab:$PATH - cmake --version - ninja --version diff --git a/.gitlab/os-macos.yml b/.gitlab/os-macos.yml index b79d46d7766..3ffd9d78947 100644 --- a/.gitlab/os-macos.yml +++ b/.gitlab/os-macos.yml @@ -127,8 +127,9 @@ .before_script_macos: &before_script_macos - .gitlab/ci/cmake.sh + - export PATH=$PWD/.gitlab/cmake/bin:$PATH - .gitlab/ci/ninja.sh - - export PATH=$PWD/.gitlab:$PWD/.gitlab/cmake/bin:$PATH + - export PATH=$PWD/.gitlab:$PATH - cmake --version - ninja --version # Download Qt From b5a59251cbd3cfdc00ffeb6d6d64af12a540c702 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 6 Oct 2021 13:23:18 -0400 Subject: [PATCH 1374/1519] gitlab-ci: Try upstream ninja development branch in some nightly jobs --- .gitlab-ci.yml | 4 ++++ .gitlab/ci/ninja-nightly.sh | 11 +++++++++++ .gitlab/ci/ninja.sh | 4 ++++ 3 files changed, 19 insertions(+) create mode 100755 .gitlab/ci/ninja-nightly.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a964b46da36..68f690d7f0a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -166,6 +166,8 @@ test:debian10-ninja: - .cmake_junit_artifacts - .run_dependent - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY_NINJA: "true" test:debian10-aarch64-ninja: extends: @@ -611,6 +613,8 @@ test:macos-x86_64-ninja: - build:macos-x86_64-ninja needs: - build:macos-x86_64-ninja + variables: + CMAKE_CI_JOB_NIGHTLY_NINJA: "true" test:macos-arm64-ninja: extends: diff --git a/.gitlab/ci/ninja-nightly.sh b/.gitlab/ci/ninja-nightly.sh new file mode 100755 index 00000000000..b78b64e2404 --- /dev/null +++ b/.gitlab/ci/ninja-nightly.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +cd .gitlab + +git clone https://github.com/ninja-build/ninja.git ninja-src +cmake -S ninja-src -B ninja-src/build -DCMAKE_BUILD_TYPE=Release +cmake --build ninja-src/build --parallel --target ninja +mv ninja-src/build/ninja . +rm -rf ninja-src diff --git a/.gitlab/ci/ninja.sh b/.gitlab/ci/ninja.sh index 8ead67085e3..866d1d5edc7 100755 --- a/.gitlab/ci/ninja.sh +++ b/.gitlab/ci/ninja.sh @@ -2,6 +2,10 @@ set -e +if test "$CMAKE_CI_JOB_NIGHTLY_NINJA" = "true" -a "$CMAKE_CI_NIGHTLY" = "true"; then + exec .gitlab/ci/ninja-nightly.sh +fi + readonly version="1.10.2" baseurl="https://github.com/ninja-build/ninja/releases/download/v$version" From 915ef42cabaa12a9ee2802e30e2261bc949430c7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 6 Oct 2021 15:40:59 -0400 Subject: [PATCH 1375/1519] gitlab-ci: Fix asan test job rules The job runs dependently after the asan build job. Fix the rules for the job added by commit 20bc209a0c (gitlab-ci: add clang asan job, 2021-06-07, v3.21.0-rc1~61^2). --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a964b46da36..f67e1916af7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -572,7 +572,7 @@ test:fedora34-asan: - .fedora34_asan - .cmake_memcheck_linux - .linux_builder_tags_qt - - .run_automatically + - .run_dependent dependencies: - build:fedora34-asan needs: From 1a828043b76d12882bea266148af0e73bb1de9d7 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Wed, 6 Oct 2021 16:21:29 -0400 Subject: [PATCH 1376/1519] NVHPC: only use '-MD' for the C and CXX languages CMake shouldn't use '-MD' for nvfortran to generate dependency information. Fixes #22723 --- Modules/Compiler/NVHPC-C.cmake | 11 +++++++++++ Modules/Compiler/NVHPC-CXX.cmake | 10 ++++++++++ Modules/Compiler/NVHPC.cmake | 12 ------------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake index e37aad562c4..9295abda8c1 100644 --- a/Modules/Compiler/NVHPC-C.cmake +++ b/Modules/Compiler/NVHPC-C.cmake @@ -9,4 +9,15 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 20.11) set(CMAKE_C17_EXTENSION_COMPILE_OPTION -std=gnu17) endif() +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 21.07) + set(CMAKE_DEPFILE_FLAGS_C "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") + set(CMAKE_C_DEPFILE_FORMAT gcc) + set(CMAKE_C_DEPENDS_USE_COMPILER TRUE) +else() + # Before NVHPC 21.07 the `-MD` flag implicitly + # implies `-E` and therefore compilation and dependency generation + # can't occur in the same invocation + set(CMAKE_C_DEPENDS_EXTRA_COMMANDS "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>") +endif() + __compiler_nvhpc(C) diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake index 534e822325f..59ba7bfab4e 100644 --- a/Modules/Compiler/NVHPC-CXX.cmake +++ b/Modules/Compiler/NVHPC-CXX.cmake @@ -9,4 +9,14 @@ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20.11) set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION -std=gnu++20) endif() +if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 21.07) + set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") + set(CMAKE_CXX_DEPFILE_FORMAT gcc) + set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE) +else() + # Before NVHPC 21.07 the `-MD` flag implicitly + # implies `-E` and therefore compilation and dependency generation + # can't occur in the same invocation + set(CMAKE_CXX_DEPENDS_EXTRA_COMMANDS "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c++ -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>") +endif() __compiler_nvhpc(CXX) diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake index a85df711e6d..70486705c1c 100644 --- a/Modules/Compiler/NVHPC.cmake +++ b/Modules/Compiler/NVHPC.cmake @@ -12,16 +12,4 @@ include(Compiler/PGI) macro(__compiler_nvhpc lang) # Logic specific to NVHPC. - - if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 21.07) - set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") - set(CMAKE_${lang}_DEPFILE_FORMAT gcc) - set(CMAKE_${lang}_DEPENDS_USE_COMPILER TRUE) - else() - # Before NVHPC 21.07 the `-MD` flag implicitly - # implies `-E` and therefore compilation and dependency generation - # can't occur in the same invocation - set(CMAKE_${lang}_DEPENDS_EXTRA_COMMANDS "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${CMAKE_${lang}_COMPILE_OPTIONS_EXPLICIT_LANGUAGE} -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>") - endif() - endmacro() From 9dcf924093cab43190a0fb7e98bb804f4ce37c54 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 6 Oct 2021 16:35:51 -0400 Subject: [PATCH 1377/1519] Tests: Skip RunCMake.file INSTALL-FOLLOW_SYMLINK_CHAIN case on Cygwin This case was added by commit e3ff7ced63 (file(INSTALL): Add FOLLOW_SYMLINK_CHAIN argument, 2019-05-16, v3.15.0-rc1~103^2). Skip it on Cygwin because it fails due to `foo/../` pairs being flattened away in symlinks. --- Tests/RunCMake/CMakeLists.txt | 2 +- Tests/RunCMake/file/RunCMakeTest.cmake | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index b7d38fbd8ff..e24ef58501b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -419,7 +419,7 @@ add_RunCMake_test(ctest_update) add_RunCMake_test(ctest_upload) add_RunCMake_test(ctest_environment) add_RunCMake_test(ctest_fixtures) -add_RunCMake_test(file -DMSYS=${MSYS}) +add_RunCMake_test(file -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(find_file) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 9efd3f49337..aff4735f41e 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -97,7 +97,9 @@ if(NOT WIN32 run_cmake(READ_SYMLINK) run_cmake(READ_SYMLINK-noexist) run_cmake(READ_SYMLINK-notsymlink) - run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) + if(NOT CYGWIN) + run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) + endif() endif() run_cmake(REAL_PATH-unexpected-arg) From b00d14ac5efd782866c3190a55efb47e4d8a8deb Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Thu, 7 Oct 2021 00:01:12 -0400 Subject: [PATCH 1378/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index cff48061adc..998a351fe82 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211006) +set(CMake_VERSION_PATCH 20211007) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From a7843faa20d14a825e3c5d0ecba91112d697dbe6 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Thu, 7 Oct 2021 11:08:16 +0900 Subject: [PATCH 1379/1519] FindLAPACK: Replace set(A val) with string(APPEND) --- Modules/FindLAPACK.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 32d15db2a7f..6801083d324 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -181,9 +181,9 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl list(APPEND _libraries "${_library}") else() string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") - set(_combined_name ${_combined_name}_${_lib_var}) + string(APPEND _combined_name "_${_lib_var}") if(NOT "${_deps}" STREQUAL "") - set(_combined_name ${_combined_name}_deps) + string(APPEND _combined_name "_deps") endif() if(_libraries_work) find_library(${_prefix}_${_lib_var}_LIBRARY @@ -201,7 +201,7 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl foreach(_flag ${_flags}) string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}") - set(_combined_name ${_combined_name}_${_flag_var}) + string(APPEND _combined_name "_${_flag_var}") endforeach() if(_libraries_work) # Test this combination of libraries. @@ -511,7 +511,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp if(BLA_VENDOR MATCHES "_mp") - set(LAPACK_armpl_LIB "${LAPACK_armpl_LIB}_mp") + string(APPEND LAPACK_armpl_LIB "_mp") endif() check_lapack_libraries( @@ -559,7 +559,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) endif() # Check for OpenMP support, VIA BLA_VENDOR of scs_mp if(BLA_VENDOR MATCHES "_mp") - set(_lapack_scsl_lib "${_lapack_scsl_lib}_mp") + string(APPEND _lapack_scsl_lib "_mp") endif() check_lapack_libraries( From 816dc1cb19a1ed1cd4aef1f4b06e9d57cce0d4e6 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Thu, 7 Oct 2021 11:16:08 +0900 Subject: [PATCH 1380/1519] FindBLAS: Replace set(A val) with string(APPEND) --- Modules/FindBLAS.cmake | 14 +++++++------- Modules/FindLAPACK.cmake | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index f16d176ce2e..89b347ad5d3 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -326,9 +326,9 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib list(APPEND _libraries "${_library}") else() string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}") - set(_combined_name ${_combined_name}_${_lib_var}) + string(APPEND _combined_name "_${_lib_var}") if(NOT "${_deps}" STREQUAL "") - set(_combined_name ${_combined_name}_deps) + string(APPEND _combined_name "_deps") endif() if(_libraries_work) find_library(${_prefix}_${_lib_var}_LIBRARY @@ -346,7 +346,7 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib foreach(_flag ${_flags}) string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}") - set(_combined_name ${_combined_name}_${_flag_var}) + string(APPEND _combined_name "_${_flag_var}") endforeach() if(_libraries_work) # Test this combination of libraries. @@ -797,7 +797,7 @@ if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All") # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp if(BLA_VENDOR MATCHES "_mp") - set(_blas_armpl_lib "${_blas_armpl_lib}_mp") + string(APPEND _blas_armpl_lib "_mp") endif() if(NOT BLAS_LIBRARIES) @@ -942,7 +942,7 @@ if(BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All") string(APPEND _blas_scsl_lib "_i8") endif() if(BLA_VENDOR MATCHES "_mp") - set(_blas_scsl_lib "${_blas_scsl_lib}_mp") + string(APPEND _blas_scsl_lib "_mp") endif() if(NOT BLAS_LIBRARIES) @@ -982,7 +982,7 @@ if(BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All") set(_blas_essl_lib "essl") if(BLA_VENDOR MATCHES "_SMP") - set(_blas_essl_lib "${_blas_essl_lib}smp") + string(APPEND _blas_essl_lib "smp") endif() if(_blas_sizeof_integer EQUAL 8) string(APPEND _blas_essl_lib "6464") @@ -1204,7 +1204,7 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") endif() # Check for OpenMP support, VIA BLA_VENDOR of eml_mt if(BLA_VENDOR MATCHES "_mt") - set(_blas_eml_lib "${_blas_eml_lib}_mt") + string(APPEND _blas_eml_lib "_mt") endif() if(NOT BLAS_LIBRARIES) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 6801083d324..5540965e530 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -511,7 +511,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE) # Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp if(BLA_VENDOR MATCHES "_mp") - string(APPEND LAPACK_armpl_LIB "_mp") + string(APPEND LAPACK_armpl_LIB "_mp") endif() check_lapack_libraries( From 635f2c87f5cc9249b5626df1aec76c43709d8223 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" <i.s.ger@ya.ru> Date: Thu, 7 Oct 2021 12:15:44 +0900 Subject: [PATCH 1381/1519] FindBLAS: Fix EML and ArmPL indentations --- Modules/FindBLAS.cmake | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 89b347ad5d3..308138f4119 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -801,16 +801,16 @@ if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All") endif() if(NOT BLAS_LIBRARIES) - check_blas_libraries( - BLAS_LIBRARIES - BLAS - sgemm - "" - "${_blas_armpl_lib}" - "" - "" - "" - ) + check_blas_libraries( + BLAS_LIBRARIES + BLAS + sgemm + "" + "${_blas_armpl_lib}" + "" + "" + "" + ) endif() unset(_blas_armpl_lib) endif() @@ -1197,17 +1197,17 @@ endif() # Elbrus Math Library? if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All") - set(_blas_eml_lib "eml") + set(_blas_eml_lib "eml") - if(_blas_sizeof_integer EQUAL 8) - string(APPEND _blas_eml_lib "_ilp64") - endif() - # Check for OpenMP support, VIA BLA_VENDOR of eml_mt - if(BLA_VENDOR MATCHES "_mt") - string(APPEND _blas_eml_lib "_mt") - endif() + if(_blas_sizeof_integer EQUAL 8) + string(APPEND _blas_eml_lib "_ilp64") + endif() + # Check for OpenMP support, VIA BLA_VENDOR of eml_mt + if(BLA_VENDOR MATCHES "_mt") + string(APPEND _blas_eml_lib "_mt") + endif() - if(NOT BLAS_LIBRARIES) + if(NOT BLAS_LIBRARIES) check_blas_libraries( BLAS_LIBRARIES BLAS From 48e503ec78ced6da83f78a8d26d5867ee56873a3 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 7 Oct 2021 09:46:29 -0400 Subject: [PATCH 1382/1519] Help: Consolidate 3.22 release notes Run the `Utilities/Release/consolidate-relnotes.bash` script to move notes from `Help/release/dev/*` into `Help/release/3.22.rst`. --- Help/release/3.22.rst | 124 ++++++++++++++++++ .../dev/FindJasper-imported-target.rst | 4 - .../dev/FindPkgConfig-PKG_CONFIG-args.rst | 5 - Help/release/dev/GoogleTest-gtest-filter.rst | 6 - .../dev/LINK_WHAT_USE_USE-configuration.rst | 5 - Help/release/dev/UseSWIG-dependencies.rst | 6 - .../dev/cmake-install-mode-symlink.rst | 16 --- .../dev/cmake_dependent_option_policy.rst | 6 - ...compile-features-standard-logic-rework.rst | 10 -- .../dev/cpack-deb-add-zstd-compression.rst | 6 - .../dev/cpack-rpm-requires-exclude-from.rst | 6 - .../dev/ctest-environment-modifications.rst | 7 - Help/release/dev/ctest-runtime-labels.rst | 7 - .../dev/ctest_memcheck-generate-test.xml.rst | 6 - Help/release/dev/env-init-configs.rst | 9 -- .../fetchcontent-CMAKE-vars-passthrough.rst | 8 -- .../dev/find-blas-lapack-sizeof-integer.rst | 6 - .../dev/find-matlab-imported-targets.rst | 4 - .../release/dev/find_package-required-var.rst | 5 - Help/release/dev/msvc-isystem.rst | 7 - Help/release/dev/ninja-edit_cache.rst | 5 - Help/release/dev/nsis-minimal-version.rst | 4 - Help/release/dev/nsis_ignore_install_page.rst | 6 - Help/release/dev/os-release.rst | 6 - .../dev/string-TIMESTAMP-specifier-V.rst | 5 - ...compile_features-ignore-disabled-langs.rst | 5 - Help/release/dev/vs10-deprecate.rst | 5 - Help/release/dev/vs_settings.rst | 5 - Help/release/index.rst | 1 + 29 files changed, 125 insertions(+), 170 deletions(-) create mode 100644 Help/release/3.22.rst delete mode 100644 Help/release/dev/FindJasper-imported-target.rst delete mode 100644 Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst delete mode 100644 Help/release/dev/GoogleTest-gtest-filter.rst delete mode 100644 Help/release/dev/LINK_WHAT_USE_USE-configuration.rst delete mode 100644 Help/release/dev/UseSWIG-dependencies.rst delete mode 100644 Help/release/dev/cmake-install-mode-symlink.rst delete mode 100644 Help/release/dev/cmake_dependent_option_policy.rst delete mode 100644 Help/release/dev/compile-features-standard-logic-rework.rst delete mode 100644 Help/release/dev/cpack-deb-add-zstd-compression.rst delete mode 100644 Help/release/dev/cpack-rpm-requires-exclude-from.rst delete mode 100644 Help/release/dev/ctest-environment-modifications.rst delete mode 100644 Help/release/dev/ctest-runtime-labels.rst delete mode 100644 Help/release/dev/ctest_memcheck-generate-test.xml.rst delete mode 100644 Help/release/dev/env-init-configs.rst delete mode 100644 Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst delete mode 100644 Help/release/dev/find-blas-lapack-sizeof-integer.rst delete mode 100644 Help/release/dev/find-matlab-imported-targets.rst delete mode 100644 Help/release/dev/find_package-required-var.rst delete mode 100644 Help/release/dev/msvc-isystem.rst delete mode 100644 Help/release/dev/ninja-edit_cache.rst delete mode 100644 Help/release/dev/nsis-minimal-version.rst delete mode 100644 Help/release/dev/nsis_ignore_install_page.rst delete mode 100644 Help/release/dev/os-release.rst delete mode 100644 Help/release/dev/string-TIMESTAMP-specifier-V.rst delete mode 100644 Help/release/dev/target_compile_features-ignore-disabled-langs.rst delete mode 100644 Help/release/dev/vs10-deprecate.rst delete mode 100644 Help/release/dev/vs_settings.rst diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst new file mode 100644 index 00000000000..d8427a672da --- /dev/null +++ b/Help/release/3.22.rst @@ -0,0 +1,124 @@ +CMake 3.22 Release Notes +************************ + +.. only:: html + + .. contents:: + +Changes made since CMake 3.21 include the following. + +* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` + macro now supports full :ref:`Condition Syntax`. + See policy :policy:`CMP0127`. + +* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to + allow users to override the default file-copying behavior of + :command:`install` and :command:`file(INSTALL)` into creating + symbolic links. This can aid in lowering storage space requirements + and avoiding redundancy. + +* The :command:`file(INSTALL)` can now be affected / modified by the + :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation + of symbolic links instead of copying of files. + +* The :command:`install` can now be affected / modified by the + :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation + of symbolic links instead of copying of files. + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality now + correctly disables or enables compiler extensions when no standard level is + specified and avoids unnecessarily adding language standard flags if the + requested settings match the compiler's defaults. See :policy:`CMP0128`. + +* :prop_tgt:`<LANG>_EXTENSIONS` is initialized to + :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. See :policy:`CMP0128`. + +* The :cpack_gen:`CPack DEB Generator` gained the + option to set :variable:`CPACK_DEBIAN_COMPRESSION_TYPE` to zstd, + which enables Zstandard compression for deb packages. + +* The :cpack_gen:`CPack RPM Generator` gained the + :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option avoid scanning + specific paths for dependencies. + +* :manual:`ctest(1)` learned to be able to modify the environment for a test + through the :prop_test:`ENVIRONMENT_MODIFICATION` property. This is allows + for updates to environment variables based on the environment present at + test time. + +* The :command:`ctest_memcheck` command now also generates a + `DynamicAnalysis-Test.xml` file which may be used to submit test results to + CDash. + +* :manual:`ctest(1)` learned to recognize labels attached to a test at run time. + Previously it was only possible to attach labels to tests at configure time + by using the :prop_test:`LABELS` test property. + See :ref:`Additional Test Measurements` for more information. + +* The :envvar:`CMAKE_BUILD_TYPE` environment variable was added to + provide a default value for the :variable:`CMAKE_BUILD_TYPE` variable. + +* The :envvar:`CMAKE_CONFIGURATION_TYPES` environment variable was added to + provide a default value for the :variable:`CMAKE_CONFIGURATION_TYPES` + variable. + +* The :module:`FetchContent` module now passes through the + :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`, + :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables (when + defined) to the underlying :module:`ExternalProject` sub-build. + Previously, those variables were silently ignored by :module:`FetchContent`. + +* The :module:`FindBLAS` and :module:`FindLAPACK` modules gained + a ``BLA_SIZEOF_INTEGER`` option to find a BLAS/LAPACK whose ABI + uses a specific integer size. + +* The :module:`FindJasper` module now provides an imported target. + +* The :module:`FindMatlab` module now provides imported targets. + +* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable was added + to turn a non-REQUIRED :command:`find_package` call into a REQUIRED one. + +* The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN` + variable to specify arguments to ``pkg-config`` calls. + +* The :module:`GoogleTest` module :command:`gtest_discover_tests` + function gained a ``TEST_FILTER`` option to filter tests using + ``--gtest_filter`` during test discovery. + +* Configuration for :prop_tgt:`LINK_WHAT_YOU_USE` feature is now controlled by + ``CMake`` variables and only active for ``ELF`` platforms. + +* The MSVC compilers learned to pass the ``-external:I`` flag for system + includes when using the :generator:`Ninja` and :generator:`NMake Makefiles` + generators. This became available as of Visual Studio 16.10 (toolchain + version 14.29.30037). + +* The :ref:`Ninja Generators` now implement the ``edit_cache`` target + using :manual:`ccmake(1)` if available. + +* The :cpack_gen:`CPack NSIS Generator` gained a new variable + :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` to ignore the + license page in the installer. + +* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. + +* The :command:`cmake_host_system_information` command query operating system + identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ + from the :file:`/etc/os-release` file. + +* The :command:`string(TIMESTAMP)` command now supports the ``%V`` + specifier for ISO 8601 week numbers. + +* :command:`target_compile_features` learned to ignored features for languages that + aren't enabled. + +* :module:`UseSWIG` module gained the capability, for + :ref:`Visual Studio Generators` to use `swig` tool to generate implicit + dependencies. + +* The :generator:`Visual Studio 10 2010` generator is now deprecated + and will be removed in a future version of CMake. + +* The :prop_sf:`VS_SETTINGS` source file property is now supported for + all source file types. Previously it worked only for non-built sources. diff --git a/Help/release/dev/FindJasper-imported-target.rst b/Help/release/dev/FindJasper-imported-target.rst deleted file mode 100644 index 33ee88526bc..00000000000 --- a/Help/release/dev/FindJasper-imported-target.rst +++ /dev/null @@ -1,4 +0,0 @@ -FindJasper-imported-target --------------------------- - -* The :module:`FindJasper` module now provides an imported target. diff --git a/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst b/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst deleted file mode 100644 index 44c26b544fa..00000000000 --- a/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst +++ /dev/null @@ -1,5 +0,0 @@ -FindPkgConfig-PKG_CONFIG-args ------------------------------ - -* The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN` - variable to specify arguments to ``pkg-config`` calls. diff --git a/Help/release/dev/GoogleTest-gtest-filter.rst b/Help/release/dev/GoogleTest-gtest-filter.rst deleted file mode 100644 index 48b97a72500..00000000000 --- a/Help/release/dev/GoogleTest-gtest-filter.rst +++ /dev/null @@ -1,6 +0,0 @@ -GoogleTest-gtest-filter ------------------------ - -* The :module:`GoogleTest` module :command:`gtest_discover_tests` - function gained a ``TEST_FILTER`` option to filter tests using - ``--gtest_filter`` during test discovery. diff --git a/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst b/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst deleted file mode 100644 index 990ed36e012..00000000000 --- a/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst +++ /dev/null @@ -1,5 +0,0 @@ -LINK_WHAT_YOU_USE-configuration -------------------------------- - -* Configuration for :prop_tgt:`LINK_WHAT_YOU_USE` feature is now controlled by - ``CMake`` variables and only active for ``ELF`` platforms. diff --git a/Help/release/dev/UseSWIG-dependencies.rst b/Help/release/dev/UseSWIG-dependencies.rst deleted file mode 100644 index a3ec29e713f..00000000000 --- a/Help/release/dev/UseSWIG-dependencies.rst +++ /dev/null @@ -1,6 +0,0 @@ -UseSWIG-dependencies --------------------- - -* :module:`UseSWIG` module gained the capability, for - :ref:`Visual Studio Generators` to use `swig` tool to generate implicit - dependencies. diff --git a/Help/release/dev/cmake-install-mode-symlink.rst b/Help/release/dev/cmake-install-mode-symlink.rst deleted file mode 100644 index a5f75ca2b0f..00000000000 --- a/Help/release/dev/cmake-install-mode-symlink.rst +++ /dev/null @@ -1,16 +0,0 @@ -cmake-install-mode-symlink --------------------------- - -* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to - allow users to override the default file-copying behavior of - :command:`install` and :command:`file(INSTALL)` into creating - symbolic links. This can aid in lowering storage space requirements - and avoiding redundancy. - -* The :command:`file(INSTALL)` can now be affected / modified by the - :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation - of symbolic links instead of copying of files. - -* The :command:`install` can now be affected / modified by the - :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation - of symbolic links instead of copying of files. diff --git a/Help/release/dev/cmake_dependent_option_policy.rst b/Help/release/dev/cmake_dependent_option_policy.rst deleted file mode 100644 index c1311700ff9..00000000000 --- a/Help/release/dev/cmake_dependent_option_policy.rst +++ /dev/null @@ -1,6 +0,0 @@ -cmake_dependent_option_policy ------------------------------ - -* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` - macro now supports full :ref:`Condition Syntax`. - See policy :policy:`CMP0127`. diff --git a/Help/release/dev/compile-features-standard-logic-rework.rst b/Help/release/dev/compile-features-standard-logic-rework.rst deleted file mode 100644 index 432a7568744..00000000000 --- a/Help/release/dev/compile-features-standard-logic-rework.rst +++ /dev/null @@ -1,10 +0,0 @@ -compile-features-standard-logic-rework --------------------------------------- - -* The :manual:`Compile Features <cmake-compile-features(7)>` functionality now - correctly disables or enables compiler extensions when no standard level is - specified and avoids unnecessarily adding language standard flags if the - requested settings match the compiler's defaults. See :policy:`CMP0128`. - -* :prop_tgt:`<LANG>_EXTENSIONS` is initialized to - :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. See :policy:`CMP0128`. diff --git a/Help/release/dev/cpack-deb-add-zstd-compression.rst b/Help/release/dev/cpack-deb-add-zstd-compression.rst deleted file mode 100644 index a138455f0cb..00000000000 --- a/Help/release/dev/cpack-deb-add-zstd-compression.rst +++ /dev/null @@ -1,6 +0,0 @@ -cpack-deb-add-zstd-compression ------------------------------- - -* The :cpack_gen:`CPack DEB Generator` gained the - option to set :variable:`CPACK_DEBIAN_COMPRESSION_TYPE` to zstd, - which enables Zstandard compression for deb packages. diff --git a/Help/release/dev/cpack-rpm-requires-exclude-from.rst b/Help/release/dev/cpack-rpm-requires-exclude-from.rst deleted file mode 100644 index 71259015cde..00000000000 --- a/Help/release/dev/cpack-rpm-requires-exclude-from.rst +++ /dev/null @@ -1,6 +0,0 @@ -cpack-rpm-requires-exclude-from -------------------------------- - -* The :cpack_gen:`CPack RPM Generator` gained the - :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option avoid scanning - specific paths for dependencies. diff --git a/Help/release/dev/ctest-environment-modifications.rst b/Help/release/dev/ctest-environment-modifications.rst deleted file mode 100644 index 64265f00d2d..00000000000 --- a/Help/release/dev/ctest-environment-modifications.rst +++ /dev/null @@ -1,7 +0,0 @@ -ctest-environment-modifications -------------------------------- - -* :manual:`ctest(1)` learned to be able to modify the environment for a test - through the :prop_test:`ENVIRONMENT_MODIFICATION` property. This is allows - for updates to environment variables based on the environment present at - test time. diff --git a/Help/release/dev/ctest-runtime-labels.rst b/Help/release/dev/ctest-runtime-labels.rst deleted file mode 100644 index 7ce0b64113b..00000000000 --- a/Help/release/dev/ctest-runtime-labels.rst +++ /dev/null @@ -1,7 +0,0 @@ -ctest-runtime-labels --------------------- - -* :manual:`ctest(1)` learned to recognize labels attached to a test at run time. - Previously it was only possible to attach labels to tests at configure time - by using the :prop_test:`LABELS` test property. - See :ref:`Additional Test Measurements` for more information. diff --git a/Help/release/dev/ctest_memcheck-generate-test.xml.rst b/Help/release/dev/ctest_memcheck-generate-test.xml.rst deleted file mode 100644 index fac02d8b802..00000000000 --- a/Help/release/dev/ctest_memcheck-generate-test.xml.rst +++ /dev/null @@ -1,6 +0,0 @@ -ctest_memcheck-generate-test.xml --------------------------------- - -* The :command:`ctest_memcheck` command now also generates a - `DynamicAnalysis-Test.xml` file which may be used to submit test results to - CDash. diff --git a/Help/release/dev/env-init-configs.rst b/Help/release/dev/env-init-configs.rst deleted file mode 100644 index 5c9892d9f8f..00000000000 --- a/Help/release/dev/env-init-configs.rst +++ /dev/null @@ -1,9 +0,0 @@ -env-init-configs ----------------- - -* The :envvar:`CMAKE_BUILD_TYPE` environment variable was added to - provide a default value for the :variable:`CMAKE_BUILD_TYPE` variable. - -* The :envvar:`CMAKE_CONFIGURATION_TYPES` environment variable was added to - provide a default value for the :variable:`CMAKE_CONFIGURATION_TYPES` - variable. diff --git a/Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst b/Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst deleted file mode 100644 index 842c016a0be..00000000000 --- a/Help/release/dev/fetchcontent-CMAKE-vars-passthrough.rst +++ /dev/null @@ -1,8 +0,0 @@ -fetchcontent-CMAKE-vars-passthrough.rst ---------------------------------------- - -* The :module:`FetchContent` module now passes through the - :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`, - :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables (when - defined) to the underlying :module:`ExternalProject` sub-build. - Previously, those variables were silently ignored by :module:`FetchContent`. diff --git a/Help/release/dev/find-blas-lapack-sizeof-integer.rst b/Help/release/dev/find-blas-lapack-sizeof-integer.rst deleted file mode 100644 index bb206548516..00000000000 --- a/Help/release/dev/find-blas-lapack-sizeof-integer.rst +++ /dev/null @@ -1,6 +0,0 @@ -find-blas-lapack-sizeof-integer -------------------------------- - -* The :module:`FindBLAS` and :module:`FindLAPACK` modules gained - a ``BLA_SIZEOF_INTEGER`` option to find a BLAS/LAPACK whose ABI - uses a specific integer size. diff --git a/Help/release/dev/find-matlab-imported-targets.rst b/Help/release/dev/find-matlab-imported-targets.rst deleted file mode 100644 index 33a93ffc087..00000000000 --- a/Help/release/dev/find-matlab-imported-targets.rst +++ /dev/null @@ -1,4 +0,0 @@ -find-matlab-imported-targets ----------------------------- - -* The :module:`FindMatlab` module now provides imported targets. diff --git a/Help/release/dev/find_package-required-var.rst b/Help/release/dev/find_package-required-var.rst deleted file mode 100644 index 36935ef9e20..00000000000 --- a/Help/release/dev/find_package-required-var.rst +++ /dev/null @@ -1,5 +0,0 @@ -find_package-required-var -------------------------- - -* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable was added - to turn a non-REQUIRED :command:`find_package` call into a REQUIRED one. diff --git a/Help/release/dev/msvc-isystem.rst b/Help/release/dev/msvc-isystem.rst deleted file mode 100644 index 4a5d79f7dfc..00000000000 --- a/Help/release/dev/msvc-isystem.rst +++ /dev/null @@ -1,7 +0,0 @@ -msvc-isystem ------------- - -* The MSVC compilers learned to pass the ``-external:I`` flag for system - includes when using the :generator:`Ninja` and :generator:`NMake Makefiles` - generators. This became available as of Visual Studio 16.10 (toolchain - version 14.29.30037). diff --git a/Help/release/dev/ninja-edit_cache.rst b/Help/release/dev/ninja-edit_cache.rst deleted file mode 100644 index 9083f56c181..00000000000 --- a/Help/release/dev/ninja-edit_cache.rst +++ /dev/null @@ -1,5 +0,0 @@ -ninja-edit_cache ----------------- - -* The :ref:`Ninja Generators` now implement the ``edit_cache`` target - using :manual:`ccmake(1)` if available. diff --git a/Help/release/dev/nsis-minimal-version.rst b/Help/release/dev/nsis-minimal-version.rst deleted file mode 100644 index b19597a13f6..00000000000 --- a/Help/release/dev/nsis-minimal-version.rst +++ /dev/null @@ -1,4 +0,0 @@ -nsis-minimal-version.rst ------------------------- - -* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. diff --git a/Help/release/dev/nsis_ignore_install_page.rst b/Help/release/dev/nsis_ignore_install_page.rst deleted file mode 100644 index 2d8a8d05f9b..00000000000 --- a/Help/release/dev/nsis_ignore_install_page.rst +++ /dev/null @@ -1,6 +0,0 @@ -nsis_ignore_install_page ------------------------- - -* The :cpack_gen:`CPack NSIS Generator` gained a new variable - :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` to ignore the - license page in the installer. diff --git a/Help/release/dev/os-release.rst b/Help/release/dev/os-release.rst deleted file mode 100644 index cce6aee8239..00000000000 --- a/Help/release/dev/os-release.rst +++ /dev/null @@ -1,6 +0,0 @@ -os-release ----------- - -* The :command:`cmake_host_system_information` command query operating system - identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ - from the :file:`/etc/os-release` file. diff --git a/Help/release/dev/string-TIMESTAMP-specifier-V.rst b/Help/release/dev/string-TIMESTAMP-specifier-V.rst deleted file mode 100644 index afd3f036955..00000000000 --- a/Help/release/dev/string-TIMESTAMP-specifier-V.rst +++ /dev/null @@ -1,5 +0,0 @@ -string-TIMESTAMP-specifier-V ----------------------------- - -* The :command:`string(TIMESTAMP)` command now supports the ``%V`` - specifier for ISO 8601 week numbers. diff --git a/Help/release/dev/target_compile_features-ignore-disabled-langs.rst b/Help/release/dev/target_compile_features-ignore-disabled-langs.rst deleted file mode 100644 index 0eba1259ca2..00000000000 --- a/Help/release/dev/target_compile_features-ignore-disabled-langs.rst +++ /dev/null @@ -1,5 +0,0 @@ -target_compile_features-ignore-disabled-langs ---------------------------------------------- - -* :command:`target_compile_features` learned to ignored features for languages that - aren't enabled. diff --git a/Help/release/dev/vs10-deprecate.rst b/Help/release/dev/vs10-deprecate.rst deleted file mode 100644 index 7bec3911545..00000000000 --- a/Help/release/dev/vs10-deprecate.rst +++ /dev/null @@ -1,5 +0,0 @@ -vs10-deprecate --------------- - -* The :generator:`Visual Studio 10 2010` generator is now deprecated - and will be removed in a future version of CMake. diff --git a/Help/release/dev/vs_settings.rst b/Help/release/dev/vs_settings.rst deleted file mode 100644 index 64f3ced3ed7..00000000000 --- a/Help/release/dev/vs_settings.rst +++ /dev/null @@ -1,5 +0,0 @@ -vs_settings ------------ - -* The :prop_sf:`VS_SETTINGS` source file property is now supported for - all source file types. Previously it worked only for non-built sources. diff --git a/Help/release/index.rst b/Help/release/index.rst index 59388784510..131595a2625 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -15,6 +15,7 @@ Releases .. toctree:: :maxdepth: 1 + 3.22 <3.22> 3.21 <3.21> 3.20 <3.20> 3.19 <3.19> From c632a7105c1bd3cfaac82b6961efb8ac6c848b6e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 7 Oct 2021 09:48:56 -0400 Subject: [PATCH 1383/1519] Help: Organize and revise 3.22 release notes Add section headers similar to the 3.21 release notes and move each individual bullet into an appropriate section. Revise a few bullets. --- Help/release/3.22.rst | 158 ++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 69 deletions(-) diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst index d8427a672da..fcb655d196b 100644 --- a/Help/release/3.22.rst +++ b/Help/release/3.22.rst @@ -7,53 +7,22 @@ CMake 3.22 Release Notes Changes made since CMake 3.21 include the following. -* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` - macro now supports full :ref:`Condition Syntax`. - See policy :policy:`CMP0127`. - -* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to - allow users to override the default file-copying behavior of - :command:`install` and :command:`file(INSTALL)` into creating - symbolic links. This can aid in lowering storage space requirements - and avoiding redundancy. +New Features +============ -* The :command:`file(INSTALL)` can now be affected / modified by the - :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation - of symbolic links instead of copying of files. +Commands +-------- -* The :command:`install` can now be affected / modified by the - :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation - of symbolic links instead of copying of files. - -* The :manual:`Compile Features <cmake-compile-features(7)>` functionality now - correctly disables or enables compiler extensions when no standard level is - specified and avoids unnecessarily adding language standard flags if the - requested settings match the compiler's defaults. See :policy:`CMP0128`. +* The :command:`cmake_host_system_information` command can now query + `OS identification variables`_ from the :file:`/etc/os-release` file. -* :prop_tgt:`<LANG>_EXTENSIONS` is initialized to - :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. See :policy:`CMP0128`. - -* The :cpack_gen:`CPack DEB Generator` gained the - option to set :variable:`CPACK_DEBIAN_COMPRESSION_TYPE` to zstd, - which enables Zstandard compression for deb packages. - -* The :cpack_gen:`CPack RPM Generator` gained the - :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option avoid scanning - specific paths for dependencies. - -* :manual:`ctest(1)` learned to be able to modify the environment for a test - through the :prop_test:`ENVIRONMENT_MODIFICATION` property. This is allows - for updates to environment variables based on the environment present at - test time. +* The :command:`string(TIMESTAMP)` command now supports the ``%V`` + specifier for ISO 8601 week numbers. -* The :command:`ctest_memcheck` command now also generates a - `DynamicAnalysis-Test.xml` file which may be used to submit test results to - CDash. +.. _`OS identification variables`: https://www.freedesktop.org/software/systemd/man/os-release.html -* :manual:`ctest(1)` learned to recognize labels attached to a test at run time. - Previously it was only possible to attach labels to tests at configure time - by using the :prop_test:`LABELS` test property. - See :ref:`Additional Test Measurements` for more information. +Variables +--------- * The :envvar:`CMAKE_BUILD_TYPE` environment variable was added to provide a default value for the :variable:`CMAKE_BUILD_TYPE` variable. @@ -62,6 +31,36 @@ Changes made since CMake 3.21 include the following. provide a default value for the :variable:`CMAKE_CONFIGURATION_TYPES` variable. +* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to + tell :command:`install` rules (implemented by :command:`file(INSTALL)`) + to install symbolic links instead of copying of files. + +* The :variable:`CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG` and + :variable:`CMAKE_LINK_WHAT_YOU_USE_CHECK` variables were added to + control the linker flag and check used by the + :prop_tgt:`LINK_WHAT_YOU_USE` target property. + +* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable + was added to turn a non-REQUIRED :command:`find_package` call into + a REQUIRED one. + +Properties +---------- + +* The :prop_tgt:`<LANG>_EXTENSIONS` target property is now initialized to + :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`, detected from the compiler. + See :policy:`CMP0128`. + +* The :prop_sf:`VS_SETTINGS` source file property is now supported for + all source file types. Previously it worked only for non-built sources. + +Modules +------- + +* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` + macro now supports full :ref:`Condition Syntax`. + See policy :policy:`CMP0127`. + * The :module:`FetchContent` module now passes through the :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`, :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables (when @@ -76,9 +75,6 @@ Changes made since CMake 3.21 include the following. * The :module:`FindMatlab` module now provides imported targets. -* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable was added - to turn a non-REQUIRED :command:`find_package` call into a REQUIRED one. - * The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN` variable to specify arguments to ``pkg-config`` calls. @@ -86,39 +82,63 @@ Changes made since CMake 3.21 include the following. function gained a ``TEST_FILTER`` option to filter tests using ``--gtest_filter`` during test discovery. -* Configuration for :prop_tgt:`LINK_WHAT_YOU_USE` feature is now controlled by - ``CMake`` variables and only active for ``ELF`` platforms. +* The :module:`UseSWIG` module, for :ref:`Visual Studio Generators`, + can now use the ``swig`` tool to generate implicit dependencies. -* The MSVC compilers learned to pass the ``-external:I`` flag for system - includes when using the :generator:`Ninja` and :generator:`NMake Makefiles` - generators. This became available as of Visual Studio 16.10 (toolchain - version 14.29.30037). +CTest +----- -* The :ref:`Ninja Generators` now implement the ``edit_cache`` target - using :manual:`ccmake(1)` if available. +* :manual:`ctest(1)` learned to recognize labels attached to a test at run time. + Previously it was only possible to attach labels to tests at configure time + by using the :prop_test:`LABELS` test property. + See :ref:`Additional Test Measurements` for more information. -* The :cpack_gen:`CPack NSIS Generator` gained a new variable - :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` to ignore the - license page in the installer. +* :manual:`ctest(1)` learned to be able to modify the environment for a test + through the :prop_test:`ENVIRONMENT_MODIFICATION` property. This is allows + for updates to environment variables based on the environment present at + test time. -* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. +* The :command:`ctest_memcheck` command now also generates a + :file:`DynamicAnalysis-Test.xml` file which may be used to submit test + results to CDash. -* The :command:`cmake_host_system_information` command query operating system - identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ - from the :file:`/etc/os-release` file. +CPack +----- -* The :command:`string(TIMESTAMP)` command now supports the ``%V`` - specifier for ISO 8601 week numbers. +* The :cpack_gen:`CPack DEB Generator` gained the + option to set :variable:`CPACK_DEBIAN_COMPRESSION_TYPE` to ``zstd``, + which enables Zstandard compression for deb packages. + +* The :cpack_gen:`CPack NSIS Generator` gained a new + :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` variable to suppress + the license page in the installer. -* :command:`target_compile_features` learned to ignored features for languages that - aren't enabled. +* The :cpack_gen:`CPack RPM Generator` gained the + :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option to avoid scanning + specific paths for dependencies. -* :module:`UseSWIG` module gained the capability, for - :ref:`Visual Studio Generators` to use `swig` tool to generate implicit - dependencies. +Deprecated and Removed Features +=============================== * The :generator:`Visual Studio 10 2010` generator is now deprecated and will be removed in a future version of CMake. -* The :prop_sf:`VS_SETTINGS` source file property is now supported for - all source file types. Previously it worked only for non-built sources. +Other Changes +============= + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality now + correctly disables or enables compiler extensions when no standard level is + specified and avoids unnecessarily adding language standard flags if the + requested settings match the compiler's defaults. See :policy:`CMP0128`. + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality + now ignores features for languages that are not enabled. + +* The :ref:`Ninja Generators` now implement the ``edit_cache`` target + using :manual:`ccmake(1)` if available. + +* The :generator:`Ninja` and :generator:`NMake Makefiles` generators + now use the MSVC ``-external:I`` flag for system includes. + This became available as of VS 16.10 (toolchain version 14.29.30037). + +* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. From 9f0b52b8e649ddf629fa82eee63a46ea7bcf16c5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 7 Oct 2021 11:16:32 -0400 Subject: [PATCH 1384/1519] Help: Update Sphinx versionadded directives for 3.22 release Run the script: Utilities/Sphinx/update_versions.py --since v3.21.0 --overwrite Manually select updates that really belong to the 3.22 release, as against adding documentation for previously-existing entities. --- Help/policy/CMP0127.rst | 2 ++ Help/prop_test/ENVIRONMENT_MODIFICATION.rst | 2 ++ Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Help/policy/CMP0127.rst b/Help/policy/CMP0127.rst index 8560bbf615c..2106110d4c0 100644 --- a/Help/policy/CMP0127.rst +++ b/Help/policy/CMP0127.rst @@ -1,6 +1,8 @@ CMP0127 ------- +.. versionadded:: 3.22 + :command:`cmake_dependent_option` supports full :ref:`Condition Syntax`. The ``<depends>`` parameter accepts a :ref:`semicolon-separated list <CMake diff --git a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst index ffd5de4afdb..00312100cf2 100644 --- a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst +++ b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst @@ -1,6 +1,8 @@ ENVIRONMENT_MODIFICATION ------------------------ +.. versionadded:: 3.22 + Specify environment variables that should be modified for running a test. Note that the operations performed by this property are performed after the :prop_test:`ENVIRONMENT` property is already applied. diff --git a/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst index 518bca72689..3533ef9c8f1 100644 --- a/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst +++ b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst @@ -1,6 +1,8 @@ Fortran_BUILDING_INSTRINSIC_MODULES ----------------------------------- +.. versionadded:: 3.22 + Instructs the CMake Fortran preprocessor that the target is building Fortran intrinsics for building a Fortran compiler. From ef47e18ad0fab68f67b95c777c1bee96fe7a4785 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 7 Oct 2021 11:37:59 -0400 Subject: [PATCH 1385/1519] MSVC: Tolerate cxx_std_23 feature on older compiler versions In commit 3aaf1d91bf (MSVC: C++20 final flag, C++23 support, 2021-05-29, v3.20.4~7^2~1) we forgot to add `cxx_std_23` to the fallback table for MSVC versions from VS 2010 through VS 2015. This allows project to at least attempt compilation with these compilers since they do not have any modes. Issue: #22729 --- Modules/Compiler/MSVC-CXX.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index f1c7450fad9..5df5c1ebf0a 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -70,6 +70,7 @@ elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) cxx_std_14 cxx_std_17 cxx_std_20 + cxx_std_23 ) _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES) endmacro() From 5a86ce5428136b601e72b377e1447772e71a3812 Mon Sep 17 00:00:00 2001 From: Joseph Snyder <joe.snyder@kitware.com> Date: Mon, 27 Sep 2021 09:03:00 -0400 Subject: [PATCH 1386/1519] Tutorial: Step 4 improvements Small changes to the text and CMake code for the fourth step of the tutorial: * Remove parameter from endfunction call * Standardize on "binary directory" for test location * Add additional information about a Release build. Issue: #22663 --- Help/guide/tutorial/Complete/CMakeLists.txt | 2 +- Help/guide/tutorial/Installing and Testing.rst | 8 +++++--- Help/guide/tutorial/Step10/CMakeLists.txt | 2 +- Help/guide/tutorial/Step11/CMakeLists.txt | 2 +- Help/guide/tutorial/Step12/CMakeLists.txt | 2 +- Help/guide/tutorial/Step5/CMakeLists.txt | 2 +- Help/guide/tutorial/Step6/CMakeLists.txt | 2 +- Help/guide/tutorial/Step7/CMakeLists.txt | 2 +- Help/guide/tutorial/Step8/CMakeLists.txt | 2 +- Help/guide/tutorial/Step9/CMakeLists.txt | 2 +- 10 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt index ec6ff16a005..ac1d0839aa5 100644 --- a/Help/guide/tutorial/Complete/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/CMakeLists.txt @@ -73,7 +73,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 2fc3202e5f2..394c9865f19 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -88,6 +88,8 @@ input, and expected results based on the passed arguments. Rebuild the application and then cd to the binary directory and run the :manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For multi-config generators (e.g. Visual Studio), the configuration type must be -specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV`` -from the build directory (not the Debug subdirectory!). Alternatively, build -the ``RUN_TESTS`` target from the IDE. +specified with the ``-C <mode>`` flag. For example, to run tests in Debug +mode use ``ctest -C Debug -VV`` from the binary directory +(not the Debug subdirectory!). Release mode would be executed from the same +location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS`` +target from the IDE. diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt index f4f9e050731..dc9a0e8e62c 100644 --- a/Help/guide/tutorial/Step10/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/CMakeLists.txt @@ -55,7 +55,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt index 30580e62efe..10f35ce2dd0 100644 --- a/Help/guide/tutorial/Step11/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/CMakeLists.txt @@ -63,7 +63,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index 53dccd7dd29..634b84cdd4d 100644 --- a/Help/guide/tutorial/Step12/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -69,7 +69,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt index fb10f575486..82d00c8d47a 100644 --- a/Help/guide/tutorial/Step5/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/CMakeLists.txt @@ -54,7 +54,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt index fb10f575486..82d00c8d47a 100644 --- a/Help/guide/tutorial/Step6/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/CMakeLists.txt @@ -54,7 +54,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt index fb10f575486..82d00c8d47a 100644 --- a/Help/guide/tutorial/Step7/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/CMakeLists.txt @@ -54,7 +54,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt index 89972fb47c6..4ae898f9ba6 100644 --- a/Help/guide/tutorial/Step8/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/CMakeLists.txt @@ -54,7 +54,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt index d67209acef4..130bc9a2085 100644 --- a/Help/guide/tutorial/Step9/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/CMakeLists.txt @@ -54,7 +54,7 @@ function(do_test target arg result) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) -endfunction(do_test) +endfunction() # do a bunch of result based tests do_test(Tutorial 4 "4 is 2") From 6658e260d481f5e51537cffefcd3aac6844d529d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20R=C3=B6hling?= <roehling@debian.org> Date: Thu, 7 Oct 2021 19:45:39 +0200 Subject: [PATCH 1387/1519] GNUInstallDirs: Fix misinterpretation of Debian Policy on LIBEXECDIR Revert commit 798c1c3192 (GNUInstallDirs: Comply with Debian Policy on LIBEXECDIR, 2020-10-08, v3.19.0-rc1~11^2). The Debian Policy builds upon FHS 3.0 and permits installing to `/usr/libexec`. While Policy does grant an additional exception for applications to use a single subdirectory of `/usr/lib/<triplet>`, this is not meant to replace `/usr/libexec` as valid target. Fixes: #22731 --- Modules/GNUInstallDirs.cmake | 15 ++------------- .../RunCMake/GNUInstallDirs/Usr-Debian-stderr.txt | 4 ++-- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index 13d067a2db4..9ef22b93603 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -167,6 +167,8 @@ _GNUInstallDirs_cache_path(CMAKE_INSTALL_BINDIR "bin" "User executables (bin)") _GNUInstallDirs_cache_path(CMAKE_INSTALL_SBINDIR "sbin" "System admin executables (sbin)") +_GNUInstallDirs_cache_path(CMAKE_INSTALL_LIBEXECDIR "libexec" + "Program executables (libexec)") _GNUInstallDirs_cache_path(CMAKE_INSTALL_SYSCONFDIR "etc" "Read-only single-machine data (etc)") _GNUInstallDirs_cache_path(CMAKE_INSTALL_SHAREDSTATEDIR "com" @@ -260,19 +262,6 @@ set(_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE IN unset(_libdir_set) unset(__LAST_LIBDIR_DEFAULT) -if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" - AND NOT CMAKE_CROSSCOMPILING - AND NOT EXISTS "/etc/arch-release" - AND EXISTS "/etc/debian_version" # is this a debian system ? - AND "${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$") - # see https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.html#usrlibexec - # and https://www.debian.org/doc/debian-policy/ch-opersys#file-system-structure (section 9.1.1 bullet point 4) - _GNUInstallDirs_cache_path(CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBDIR}" - "Program executables (${CMAKE_INSTALL_LIBDIR})") -else() - _GNUInstallDirs_cache_path(CMAKE_INSTALL_LIBEXECDIR "libexec" - "Program executables (libexec)") -endif() _GNUInstallDirs_cache_path(CMAKE_INSTALL_INCLUDEDIR "include" "C header files (include)") _GNUInstallDirs_cache_path(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" diff --git a/Tests/RunCMake/GNUInstallDirs/Usr-Debian-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Usr-Debian-stderr.txt index 89578ee560f..c38006c3011 100644 --- a/Tests/RunCMake/GNUInstallDirs/Usr-Debian-stderr.txt +++ b/Tests/RunCMake/GNUInstallDirs/Usr-Debian-stderr.txt @@ -5,7 +5,7 @@ CMAKE_INSTALL_DOCDIR='share/doc/Usr' CMAKE_INSTALL_INCLUDEDIR='include' CMAKE_INSTALL_INFODIR='share/info' CMAKE_INSTALL_LIBDIR='lib/arch' -CMAKE_INSTALL_LIBEXECDIR='lib/arch' +CMAKE_INSTALL_LIBEXECDIR='libexec' CMAKE_INSTALL_LOCALEDIR='share/locale' CMAKE_INSTALL_LOCALSTATEDIR='var' CMAKE_INSTALL_RUNSTATEDIR='var/run' @@ -20,7 +20,7 @@ CMAKE_INSTALL_FULL_DOCDIR='/usr/share/doc/Usr' CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/include' CMAKE_INSTALL_FULL_INFODIR='/usr/share/info' CMAKE_INSTALL_FULL_LIBDIR='/usr/lib/arch' -CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/lib/arch' +CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec' CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale' CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var' CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run' From a8c72f6257678e376265bcf7ff72c1d0ec0c930e Mon Sep 17 00:00:00 2001 From: Kitware Robot <kwrobot@kitware.com> Date: Fri, 8 Oct 2021 00:01:10 -0400 Subject: [PATCH 1388/1519] CMake Nightly Date Stamp --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 998a351fe82..8d06bc74753 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211007) +set(CMake_VERSION_PATCH 20211008) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From e5a97f83b332d4bad7e74e645f29100f5c7b7710 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 8 Oct 2021 10:00:22 -0400 Subject: [PATCH 1389/1519] Help: Drop development topic notes to prepare release Release versions do not have the development topic section of the CMake Release Notes index page. --- Help/release/dev/0-sample-topic.rst | 7 ------- Help/release/index.rst | 2 -- 2 files changed, 9 deletions(-) delete mode 100644 Help/release/dev/0-sample-topic.rst diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst deleted file mode 100644 index e4cc01e23fe..00000000000 --- a/Help/release/dev/0-sample-topic.rst +++ /dev/null @@ -1,7 +0,0 @@ -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/index.rst b/Help/release/index.rst index 131595a2625..3d2ed43105c 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -7,8 +7,6 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. -.. include:: dev.txt - Releases ======== From e137ce0a5243b923ab5fb0be6f5f1bdc9ecf805d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 8 Oct 2021 10:01:41 -0400 Subject: [PATCH 1390/1519] gitlab-ci: Drop package pipeline upload jobs for release branch The package pipeline for release versions should not upload packages automatically to our archive of nightly development versions. --- .gitlab-ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 33439183717..708d80ae8ff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,7 @@ prep:doc-package: - .cmake_doc_artifacts - .run_only_for_package -upload:source-package: +.upload:source-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -70,7 +70,7 @@ build:help:master: - .cmake_org_help - .run_only_for_continuous_master -upload:help:master: +.upload:help:master: extends: - .rsync_upload_help - .run_only_for_continuous_master @@ -86,7 +86,7 @@ build:help:stage: - .cmake_org_help - .run_only_for_continuous_stage -upload:help:stage: +.upload:help:stage: extends: - .rsync_upload_help - .run_only_for_continuous_stage @@ -522,7 +522,7 @@ build:linux-x86_64-package: needs: - prep:doc-package -upload:linux-x86_64-package: +.upload:linux-x86_64-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -546,7 +546,7 @@ build:linux-aarch64-package: needs: - prep:doc-package -upload:linux-aarch64-package: +.upload:linux-aarch64-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -687,7 +687,7 @@ build:macos-package: needs: - prep:doc-package -upload:macos-package: +.upload:macos-package: extends: - .rsync_upload_binary - .run_only_for_package @@ -710,7 +710,7 @@ build:macos10.10-package: needs: - prep:doc-package -upload:macos10.10-package: +.upload:macos10.10-package: extends: - .rsync_upload_binary - .run_only_for_package From 975b93512944e04c3817cbfe91fee1327ddfb834 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 8 Oct 2021 10:02:29 -0400 Subject: [PATCH 1391/1519] Begin 3.22 release versioning --- Source/CMakeVersion.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8d06bc74753..beb43a83eec 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,8 +1,8 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20211008) -#set(CMake_VERSION_RC 0) +set(CMake_VERSION_MINOR 22) +set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From fc92d6640b09def31d129f3e347b98af1aa1e098 Mon Sep 17 00:00:00 2001 From: Seth R Johnson <johnsonsr@ornl.gov> Date: Sun, 10 Oct 2021 06:31:42 -0400 Subject: [PATCH 1392/1519] cmFileCommand: improve error message Print full list of unresolved dependencies and a phrase that indicates what about the file is unresolved. --- Source/cmFileCommand.cxx | 9 ++++++--- .../linux-notfile-all-stderr.txt | 4 +++- .../linux-unresolved-all-stderr.txt | 4 +++- .../macos-unresolved-all-stderr.txt | 4 +++- .../windows-unresolved-all-stderr.txt | 4 +++- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d2341c5bcdc..fd0595d88eb 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3170,9 +3170,12 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, archive.GetUnresolvedPaths().begin(), archive.GetUnresolvedPaths().end()); } else { - auto it = archive.GetUnresolvedPaths().begin(); - assert(it != archive.GetUnresolvedPaths().end()); - status.SetError(cmStrCat("Could not resolve file ", *it)); + std::ostringstream e; + e << "Could not resolve runtime dependencies:"; + for (auto const& path : archive.GetUnresolvedPaths()) { + e << "\n " << path; + } + status.SetError(e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt index 5b863220abc..9ed17286f6f 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt @@ -1,2 +1,4 @@ ^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): - file Could not resolve file libtest\.so$ + file Could not resolve runtime dependencies: + + libtest\.so$ diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt index eaca5121b8f..51010a19d1f 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt @@ -1,2 +1,4 @@ ^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): - file Could not resolve file libunresolved\.so$ + file Could not resolve runtime dependencies: + + libunresolved\.so$ diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt index 01762b45f51..5743d27f4d9 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt @@ -1,2 +1,4 @@ ^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): - file Could not resolve file @rpath/libunresolved\.dylib$ + file Could not resolve runtime dependencies: + + @rpath/libunresolved\.dylib$ diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt index a20654c5aa0..0efcb57d452 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt @@ -1,2 +1,4 @@ ^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): - file Could not resolve file (lib)?unresolved\.dll$ + file Could not resolve runtime dependencies: + + (lib)?unresolved\.dll$ From 93c5864aa19a9af058910172939db177bd5a3b9f Mon Sep 17 00:00:00 2001 From: Seth R Johnson <johnsonsr@ornl.gov> Date: Sun, 10 Oct 2021 06:33:33 -0400 Subject: [PATCH 1393/1519] cmBinUtilsMacOSMachOLinker: improve performance by memoizing otool calls Libraries with many repeated transitive dependencies (e.g. Trilinos) can result in very long runtime dependency call times, especially if system calls are made more expensive by antivirus software. This change caches the results of the calls to otool for efficiency. --- Source/cmBinUtilsMacOSMachOLinker.cxx | 42 +++++++++++++++++++++------ Source/cmBinUtilsMacOSMachOLinker.h | 10 +++++++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx index 47f77d8b996..c0643776cd1 100644 --- a/Source/cmBinUtilsMacOSMachOLinker.cxx +++ b/Source/cmBinUtilsMacOSMachOLinker.cxx @@ -5,6 +5,8 @@ #include <sstream> #include <string> +#include <type_traits> +#include <utility> #include <vector> #include <cm/memory> @@ -52,6 +54,26 @@ bool cmBinUtilsMacOSMachOLinker::Prepare() return true; } +auto cmBinUtilsMacOSMachOLinker::GetFileInfo(std::string const& file) + -> const FileInfo* +{ + // Memoize processed rpaths and library dependencies to reduce the number + // of calls to otool, especially in the case of heavily recursive libraries + auto iter = ScannedFileInfo.find(file); + if (iter != ScannedFileInfo.end()) { + return &iter->second; + } + + FileInfo file_info; + if (!this->Tool->GetFileInfo(file, file_info.libs, file_info.rpaths)) { + // Call to otool failed + return nullptr; + } + + auto iter_inserted = ScannedFileInfo.insert({ file, std::move(file_info) }); + return &iter_inserted.first->second; +} + bool cmBinUtilsMacOSMachOLinker::ScanDependencies( std::string const& file, cmStateEnums::TargetType type) { @@ -65,12 +87,12 @@ bool cmBinUtilsMacOSMachOLinker::ScanDependencies( if (!executableFile.empty()) { executablePath = cmSystemTools::GetFilenamePath(executableFile); } - std::vector<std::string> libs; - std::vector<std::string> rpaths; - if (!this->Tool->GetFileInfo(file, libs, rpaths)) { + const FileInfo* file_info = this->GetFileInfo(file); + if (file_info == nullptr) { return false; } - return this->ScanDependencies(file, libs, rpaths, executablePath); + return this->ScanDependencies(file, file_info->libs, file_info->rpaths, + executablePath); } bool cmBinUtilsMacOSMachOLinker::ScanDependencies( @@ -98,14 +120,16 @@ bool cmBinUtilsMacOSMachOLinker::GetFileDependencies( !IsMissingSystemDylib(path)) { auto filename = cmSystemTools::GetFilenameName(path); bool unique; - std::vector<std::string> libs; - std::vector<std::string> depRpaths; - if (!this->Tool->GetFileInfo(path, libs, depRpaths)) { + const FileInfo* dep_file_info = this->GetFileInfo(path); + if (dep_file_info == nullptr) { return false; } - this->Archive->AddResolvedPath(filename, path, unique, depRpaths); + + this->Archive->AddResolvedPath(filename, path, unique, + dep_file_info->rpaths); if (unique && - !this->ScanDependencies(path, libs, depRpaths, executablePath)) { + !this->ScanDependencies(path, dep_file_info->libs, + dep_file_info->rpaths, executablePath)) { return false; } } diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h index eae23cc88b9..ac1177bb579 100644 --- a/Source/cmBinUtilsMacOSMachOLinker.h +++ b/Source/cmBinUtilsMacOSMachOLinker.h @@ -5,6 +5,7 @@ #include <memory> #include <string> +#include <unordered_map> #include <vector> #include "cmBinUtilsLinker.h" @@ -24,7 +25,16 @@ class cmBinUtilsMacOSMachOLinker : public cmBinUtilsLinker cmStateEnums::TargetType type) override; private: + struct FileInfo + { + std::vector<std::string> libs; + std::vector<std::string> rpaths; + }; + std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool; + std::unordered_map<std::string, FileInfo> ScannedFileInfo; + + const FileInfo* GetFileInfo(std::string const& file); bool ScanDependencies(std::string const& file, std::vector<std::string> const& libs, From 8c65ea474437f20f787038e0c955dbb1582d7e5d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 13 Oct 2021 09:37:09 -0400 Subject: [PATCH 1394/1519] zstd: Update script to get zstd 1.5.0 --- Utilities/Scripts/update-zstd.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utilities/Scripts/update-zstd.bash b/Utilities/Scripts/update-zstd.bash index a9b62f9499b..48ca5a17d19 100755 --- a/Utilities/Scripts/update-zstd.bash +++ b/Utilities/Scripts/update-zstd.bash @@ -8,7 +8,7 @@ readonly name="zstd" readonly ownership="zstd upstream <kwrobot@kitware.com>" readonly subtree="Utilities/cmzstd" readonly repo="https://github.com/facebook/zstd.git" -readonly tag="v1.4.5" +readonly tag="v1.5.0" readonly shortlog=false readonly paths=" LICENSE @@ -23,7 +23,7 @@ readonly paths=" lib/deprecated/*.h lib/dictBuilder/*.c lib/dictBuilder/*.h - lib/zstd.h + lib/*.h " extract_source () { From da1e841ccf2fd4600b97abf1695b307592867352 Mon Sep 17 00:00:00 2001 From: zstd upstream <kwrobot@kitware.com> Date: Fri, 14 May 2021 10:59:34 -0400 Subject: [PATCH 1395/1519] zstd 2021-05-14 (a488ba11) Code extracted from: https://github.com/facebook/zstd.git at commit a488ba114ec17ea1054b9057c26a046fc122b3b6 (v1.5.0). --- README.md | 12 +- lib/common/bitstream.h | 41 +- lib/common/compiler.h | 122 +- lib/common/cpu.h | 4 +- lib/common/debug.c | 2 +- lib/common/debug.h | 31 +- lib/common/entropy_common.c | 232 +- lib/common/error_private.c | 3 +- lib/common/error_private.h | 6 +- lib/common/fse.h | 52 +- lib/common/fse_decompress.c | 161 +- lib/common/huf.h | 36 +- lib/common/mem.h | 167 +- lib/common/pool.c | 40 +- lib/common/pool.h | 4 +- lib/common/threading.c | 11 +- lib/common/xxhash.c | 80 +- lib/common/xxhash.h | 4 +- lib/common/zstd_common.c | 20 +- lib/common/zstd_deps.h | 111 + lib/common/zstd_internal.h | 167 +- lib/common/zstd_trace.h | 154 + lib/compress/fse_compress.c | 55 +- lib/compress/hist.c | 56 +- lib/compress/hist.h | 4 +- lib/compress/huf_compress.c | 391 ++- lib/compress/zstd_compress.c | 3571 ++++++++++++++++----- lib/compress/zstd_compress_internal.h | 368 ++- lib/compress/zstd_compress_literals.c | 16 +- lib/compress/zstd_compress_literals.h | 2 +- lib/compress/zstd_compress_sequences.c | 36 +- lib/compress/zstd_compress_sequences.h | 2 +- lib/compress/zstd_compress_superblock.c | 317 +- lib/compress/zstd_compress_superblock.h | 2 +- lib/compress/zstd_cwksp.h | 271 +- lib/compress/zstd_double_fast.c | 50 +- lib/compress/zstd_double_fast.h | 2 +- lib/compress/zstd_fast.c | 46 +- lib/compress/zstd_fast.h | 2 +- lib/compress/zstd_lazy.c | 1228 ++++++- lib/compress/zstd_lazy.h | 60 +- lib/compress/zstd_ldm.c | 525 +-- lib/compress/zstd_ldm.h | 11 +- lib/compress/zstd_ldm_geartab.h | 103 + lib/compress/zstd_opt.c | 237 +- lib/compress/zstd_opt.h | 2 +- lib/compress/zstdmt_compress.c | 508 +-- lib/compress/zstdmt_compress.h | 144 +- lib/decompress/huf_decompress.c | 581 ++-- lib/decompress/zstd_ddict.c | 18 +- lib/decompress/zstd_ddict.h | 4 +- lib/decompress/zstd_decompress.c | 456 ++- lib/decompress/zstd_decompress_block.c | 266 +- lib/decompress/zstd_decompress_block.h | 9 +- lib/decompress/zstd_decompress_internal.h | 38 +- lib/deprecated/zbuff.h | 2 +- lib/deprecated/zbuff_common.c | 2 +- lib/deprecated/zbuff_compress.c | 2 +- lib/deprecated/zbuff_decompress.c | 2 +- lib/dictBuilder/cover.c | 82 +- lib/dictBuilder/cover.h | 13 +- lib/dictBuilder/divsufsort.c | 2 +- lib/dictBuilder/fastcover.c | 62 +- lib/dictBuilder/zdict.c | 59 +- lib/{dictBuilder => }/zdict.h | 157 +- lib/zstd.h | 694 +++- lib/{common => }/zstd_errors.h | 3 +- 67 files changed, 8584 insertions(+), 3337 deletions(-) create mode 100644 lib/common/zstd_deps.h create mode 100644 lib/common/zstd_trace.h create mode 100644 lib/compress/zstd_ldm_geartab.h rename lib/{dictBuilder => }/zdict.h (70%) rename lib/{common => }/zstd_errors.h (97%) diff --git a/README.md b/README.md index 5c300fdc49a..dcca7662d2f 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,12 @@ Going into `build` directory, you will find additional possibilities: You can build the zstd binary via buck by executing: `buck build programs:zstd` from the root of the repo. The output binary will be in `buck-out/gen/programs/`. +## Testing + +You can run quick local smoke tests by executing the `playTest.sh` script from the `src/tests` directory. +Two env variables `$ZSTD_BIN` and `$DATAGEN_BIN` are needed for the test script to locate the zstd and datagen binary. +For information on CI testing, please refer to TESTING.md + ## Status Zstandard is currently deployed within Facebook. It is used continuously to compress large amounts of data in multiple formats and use cases. @@ -187,7 +193,7 @@ Zstandard is dual-licensed under [BSD](LICENSE) and [GPLv2](COPYING). ## Contributing -The "dev" branch is the one where all contributions are merged before reaching "master". -If you plan to propose a patch, please commit into the "dev" branch, or its own feature branch. -Direct commit to "master" are not permitted. +The `dev` branch is the one where all contributions are merged before reaching `release`. +If you plan to propose a patch, please commit into the `dev` branch, or its own feature branch. +Direct commit to `release` are not permitted. For more information, please read [CONTRIBUTING](CONTRIBUTING.md). diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index 37b99c01eed..2e5a933ad3d 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -1,7 +1,7 @@ /* ****************************************************************** * bitstream * Part of FSE library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -17,7 +17,6 @@ #if defined (__cplusplus) extern "C" { #endif - /* * This API consists of small unitary functions, which must be inlined for best performance. * Since link-time-optimization is not available for all compilers, @@ -36,10 +35,12 @@ extern "C" { /*========================================= * Target specific =========================================*/ -#if defined(__BMI__) && defined(__GNUC__) -# include <immintrin.h> /* support for bextr (experimental) */ -#elif defined(__ICCARM__) -# include <intrinsics.h> +#ifndef ZSTD_NO_INTRINSICS +# if defined(__BMI__) && defined(__GNUC__) +# include <immintrin.h> /* support for bextr (experimental) */ +# elif defined(__ICCARM__) +# include <intrinsics.h> +# endif #endif #define STREAM_ACCUMULATOR_MIN_32 25 @@ -141,8 +142,12 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val) assert(val != 0); { # if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - return _BitScanReverse ( &r, val ) ? (unsigned)r : 0; +# if STATIC_BMI2 == 1 + return _lzcnt_u32(val) ^ 31; +# else + unsigned long r = 0; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ @@ -198,7 +203,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits) { - MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32); + DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32); assert(nbBits < BIT_MASK_SIZE); assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos; @@ -271,7 +276,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) { - if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } + if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } bitD->start = (const char*)srcBuffer; bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer); @@ -317,12 +322,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si return srcSize; } -MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start) { return bitContainer >> start; } -MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) { U32 const regMask = sizeof(bitContainer)*8 - 1; /* if start > regMask, bitstream is corrupted, and result is undefined */ @@ -330,10 +335,14 @@ MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 co return (bitContainer >> (start & regMask)) & BIT_mask[nbBits]; } -MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { +#if defined(STATIC_BMI2) && STATIC_BMI2 == 1 + return _bzhi_u64(bitContainer, nbBits); +#else assert(nbBits < BIT_MASK_SIZE); return bitContainer & BIT_mask[nbBits]; +#endif } /*! BIT_lookBits() : @@ -342,7 +351,7 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) * On 32-bits, maxNbBits==24. * On 64-bits, maxNbBits==56. * @return : value extracted */ -MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) { /* arbitrate between double-shift and shift+mask */ #if 1 @@ -365,7 +374,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask); } -MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; } @@ -374,7 +383,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) * Read (consume) next n bits from local register and update. * Pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ -MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) { size_t const value = BIT_lookBits(bitD, nbBits); BIT_skipBits(bitD, nbBits); diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 95e9483521d..a951d0adea2 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -38,6 +38,17 @@ #endif +/** + On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC). + This explictly marks such functions as __cdecl so that the code will still compile + if a CC other than __cdecl has been made the default. +*/ +#if defined(_MSC_VER) +# define WIN_CDECL __cdecl +#else +# define WIN_CDECL +#endif + /** * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant * parameters. They must be inlined for the compiler to eliminate the constant @@ -79,6 +90,7 @@ # endif #endif + /* target attribute */ #ifndef __has_attribute #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ @@ -114,12 +126,12 @@ # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) -# elif defined(__aarch64__) -# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) -# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) +# elif defined(__aarch64__) +# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) +# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # else # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ @@ -172,4 +184,106 @@ # pragma warning(disable : 4324) /* disable: C4324: padded structure */ #endif +/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ +#ifndef STATIC_BMI2 +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) +# ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 +# define STATIC_BMI2 1 +# endif +# endif +#endif + +#ifndef STATIC_BMI2 + #define STATIC_BMI2 0 +#endif + +/* compat. with non-clang compilers */ +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/* compat. with non-clang compilers */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +/* detects whether we are being compiled under msan */ +#ifndef ZSTD_MEMORY_SANITIZER +# if __has_feature(memory_sanitizer) +# define ZSTD_MEMORY_SANITIZER 1 +# else +# define ZSTD_MEMORY_SANITIZER 0 +# endif +#endif + +#if ZSTD_MEMORY_SANITIZER +/* Not all platforms that support msan provide sanitizers/msan_interface.h. + * We therefore declare the functions we need ourselves, rather than trying to + * include the header file... */ +#include <stddef.h> /* size_t */ +#define ZSTD_DEPS_NEED_STDINT +#include "zstd_deps.h" /* intptr_t */ + +/* Make memory region fully initialized (without changing its contents). */ +void __msan_unpoison(const volatile void *a, size_t size); + +/* Make memory region fully uninitialized (without changing its contents). + This is a legacy interface that does not update origin information. Use + __msan_allocated_memory() instead. */ +void __msan_poison(const volatile void *a, size_t size); + +/* Returns the offset of the first (at least partially) poisoned byte in the + memory range, or -1 if the whole range is good. */ +intptr_t __msan_test_shadow(const volatile void *x, size_t size); +#endif + +/* detects whether we are being compiled under asan */ +#ifndef ZSTD_ADDRESS_SANITIZER +# if __has_feature(address_sanitizer) +# define ZSTD_ADDRESS_SANITIZER 1 +# elif defined(__SANITIZE_ADDRESS__) +# define ZSTD_ADDRESS_SANITIZER 1 +# else +# define ZSTD_ADDRESS_SANITIZER 0 +# endif +#endif + +#if ZSTD_ADDRESS_SANITIZER +/* Not all platforms that support asan provide sanitizers/asan_interface.h. + * We therefore declare the functions we need ourselves, rather than trying to + * include the header file... */ +#include <stddef.h> /* size_t */ + +/** + * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable. + * + * This memory must be previously allocated by your program. Instrumented + * code is forbidden from accessing addresses in this region until it is + * unpoisoned. This function is not guaranteed to poison the entire region - + * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan + * alignment restrictions. + * + * \note This function is not thread-safe because no two threads can poison or + * unpoison memory in the same memory region simultaneously. + * + * \param addr Start of memory region. + * \param size Size of memory region. */ +void __asan_poison_memory_region(void const volatile *addr, size_t size); + +/** + * Marks a memory region (<c>[addr, addr+size)</c>) as addressable. + * + * This memory must be previously allocated by your program. Accessing + * addresses in this region is allowed until this region is poisoned again. + * This function could unpoison a super-region of <c>[addr, addr+size)</c> due + * to ASan alignment restrictions. + * + * \note This function is not thread-safe because no two threads can + * poison or unpoison memory in the same memory region simultaneously. + * + * \param addr Start of memory region. + * \param size Size of memory region. */ +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#endif + #endif /* ZSTD_COMPILER_H */ diff --git a/lib/common/cpu.h b/lib/common/cpu.h index 6e8a974f62d..8acd33be3cd 100644 --- a/lib/common/cpu.h +++ b/lib/common/cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Facebook, Inc. + * Copyright (c) Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -16,8 +16,6 @@ * https://github.com/facebook/folly/blob/master/folly/CpuId.h */ -#include <string.h> - #include "mem.h" #ifdef _MSC_VER diff --git a/lib/common/debug.c b/lib/common/debug.c index f303f4a2e53..bb863c9ea61 100644 --- a/lib/common/debug.c +++ b/lib/common/debug.c @@ -1,7 +1,7 @@ /* ****************************************************************** * debug * Part of FSE library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy diff --git a/lib/common/debug.h b/lib/common/debug.h index ac6224888d8..3b2a320a188 100644 --- a/lib/common/debug.h +++ b/lib/common/debug.h @@ -1,7 +1,7 @@ /* ****************************************************************** * debug * Part of FSE library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -51,15 +51,6 @@ extern "C" { #endif -/* DEBUGFILE can be defined externally, - * typically through compiler command line. - * note : currently useless. - * Value must be stderr or stdout */ -#ifndef DEBUGFILE -# define DEBUGFILE stderr -#endif - - /* recommended values for DEBUGLEVEL : * 0 : release mode, no debug, all run-time checks disabled * 1 : enables assert() only, no display @@ -76,7 +67,8 @@ extern "C" { */ #if (DEBUGLEVEL>=1) -# include <assert.h> +# define ZSTD_DEPS_NEED_ASSERT +# include "zstd_deps.h" #else # ifndef assert /* assert may be already defined, due to prior #include <assert.h> */ # define assert(condition) ((void)0) /* disable assert (default) */ @@ -84,7 +76,8 @@ extern "C" { #endif #if (DEBUGLEVEL>=2) -# include <stdio.h> +# define ZSTD_DEPS_NEED_IO +# include "zstd_deps.h" extern int g_debuglevel; /* the variable is only declared, it actually lives in debug.c, and is shared by the whole process. @@ -92,14 +85,14 @@ extern int g_debuglevel; /* the variable is only declared, It's useful when enabling very verbose levels on selective conditions (such as position in src) */ -# define RAWLOG(l, ...) { \ - if (l<=g_debuglevel) { \ - fprintf(stderr, __VA_ARGS__); \ +# define RAWLOG(l, ...) { \ + if (l<=g_debuglevel) { \ + ZSTD_DEBUG_PRINT(__VA_ARGS__); \ } } -# define DEBUGLOG(l, ...) { \ - if (l<=g_debuglevel) { \ - fprintf(stderr, __FILE__ ": " __VA_ARGS__); \ - fprintf(stderr, " \n"); \ +# define DEBUGLOG(l, ...) { \ + if (l<=g_debuglevel) { \ + ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \ + ZSTD_DEBUG_PRINT(" \n"); \ } } #else # define RAWLOG(l, ...) {} /* disabled */ diff --git a/lib/common/entropy_common.c b/lib/common/entropy_common.c index 9d3e4e8e36a..41cd69566bc 100644 --- a/lib/common/entropy_common.c +++ b/lib/common/entropy_common.c @@ -1,6 +1,6 @@ /* ****************************************************************** * Common functions of New Generation Entropy library - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -38,8 +38,31 @@ const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } /*-************************************************************** * FSE NCount encoding-decoding ****************************************************************/ -size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, - const void* headerBuffer, size_t hbSize) +static U32 FSE_ctz(U32 val) +{ + assert(val != 0); + { +# if defined(_MSC_VER) /* Visual */ + unsigned long r=0; + return _BitScanForward(&r, val) ? (unsigned)r : 0; +# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ + return __builtin_ctz(val); +# elif defined(__ICCARM__) /* IAR Intrinsic */ + return __CTZ(val); +# else /* Software version */ + U32 count = 0; + while ((val & 1) == 0) { + val >>= 1; + ++count; + } + return count; +# endif + } +} + +FORCE_INLINE_TEMPLATE +size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) { const BYTE* const istart = (const BYTE*) headerBuffer; const BYTE* const iend = istart + hbSize; @@ -50,23 +73,23 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t U32 bitStream; int bitCount; unsigned charnum = 0; + unsigned const maxSV1 = *maxSVPtr + 1; int previous0 = 0; - if (hbSize < 4) { - /* This function only works when hbSize >= 4 */ - char buffer[4]; - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, headerBuffer, hbSize); + if (hbSize < 8) { + /* This function only works when hbSize >= 8 */ + char buffer[8] = {0}; + ZSTD_memcpy(buffer, headerBuffer, hbSize); { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, buffer, sizeof(buffer)); if (FSE_isError(countSize)) return countSize; if (countSize > hbSize) return ERROR(corruption_detected); return countSize; } } - assert(hbSize >= 4); + assert(hbSize >= 8); /* init */ - memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ + ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ bitStream = MEM_readLE32(ip); nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); @@ -77,36 +100,58 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t threshold = 1<<nbBits; nbBits++; - while ((remaining>1) & (charnum<=*maxSVPtr)) { + for (;;) { if (previous0) { - unsigned n0 = charnum; - while ((bitStream & 0xFFFF) == 0xFFFF) { - n0 += 24; - if (ip < iend-5) { - ip += 2; - bitStream = MEM_readLE32(ip) >> bitCount; + /* Count the number of repeats. Each time the + * 2-bit repeat code is 0b11 there is another + * repeat. + * Avoid UB by setting the high bit to 1. + */ + int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; + while (repeats >= 12) { + charnum += 3 * 12; + if (LIKELY(ip <= iend-7)) { + ip += 3; } else { - bitStream >>= 16; - bitCount += 16; - } } - while ((bitStream & 3) == 3) { - n0 += 3; - bitStream >>= 2; - bitCount += 2; + bitCount -= (int)(8 * (iend - 7 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; } - n0 += bitStream & 3; + charnum += 3 * repeats; + bitStream >>= 2 * repeats; + bitCount += 2 * repeats; + + /* Add the final repeat which isn't 0b11. */ + assert((bitStream & 3) < 3); + charnum += bitStream & 3; bitCount += 2; - if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); - while (charnum < n0) normalizedCounter[charnum++] = 0; - if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + + /* This is an error, but break and return an error + * at the end, because returning out of a loop makes + * it harder for the compiler to optimize. + */ + if (charnum >= maxSV1) break; + + /* We don't need to set the normalized count to 0 + * because we already memset the whole buffer to 0. + */ + + if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { assert((bitCount >> 3) <= 3); /* For first condition to work */ ip += bitCount>>3; bitCount &= 7; - bitStream = MEM_readLE32(ip) >> bitCount; } else { - bitStream >>= 2; - } } - { int const max = (2*threshold-1) - remaining; + bitCount -= (int)(8 * (iend - 4 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + } + { + int const max = (2*threshold-1) - remaining; int count; if ((bitStream & (threshold-1)) < (U32)max) { @@ -119,24 +164,43 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t } count--; /* extra accuracy */ - remaining -= count < 0 ? -count : count; /* -1 means +1 */ + /* When it matters (small blocks), this is a + * predictable branch, because we don't use -1. + */ + if (count >= 0) { + remaining -= count; + } else { + assert(count == -1); + remaining += count; + } normalizedCounter[charnum++] = (short)count; previous0 = !count; - while (remaining < threshold) { - nbBits--; - threshold >>= 1; + + assert(threshold > 1); + if (remaining < threshold) { + /* This branch can be folded into the + * threshold update condition because we + * know that threshold > 1. + */ + if (remaining <= 1) break; + nbBits = BIT_highbit32(remaining) + 1; + threshold = 1 << (nbBits - 1); } + if (charnum >= maxSV1) break; - if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { ip += bitCount>>3; bitCount &= 7; } else { bitCount -= (int)(8 * (iend - 4 - ip)); + bitCount &= 31; ip = iend - 4; } - bitStream = MEM_readLE32(ip) >> (bitCount & 31); - } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ + bitStream = MEM_readLE32(ip) >> bitCount; + } } if (remaining != 1) return ERROR(corruption_detected); + /* Only possible when there are too many zeros. */ + if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall); if (bitCount > 32) return ERROR(corruption_detected); *maxSVPtr = charnum-1; @@ -144,6 +208,43 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t return ip-istart; } +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t FSE_readNCount_body_default( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} + +#if DYNAMIC_BMI2 +TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} +#endif + +size_t FSE_readNCount_bmi2( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); + } +#endif + (void)bmi2; + return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} + +size_t FSE_readNCount( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0); +} + /*! HUF_readStats() : Read compact Huffman tree, saved by HUF_writeCTable(). @@ -155,6 +256,17 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, const void* src, size_t srcSize) +{ + U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; + return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0); +} + +FORCE_INLINE_TEMPLATE size_t +HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, + int bmi2) { U32 weightTotal; const BYTE* ip = (const BYTE*) src; @@ -163,7 +275,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, if (!srcSize) return ERROR(srcSize_wrong); iSize = ip[0]; - /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ + /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ if (iSize >= 128) { /* special header */ oSize = iSize - 127; @@ -177,14 +289,14 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, huffWeight[n+1] = ip[n/2] & 15; } } } else { /* header compressed with FSE (normal case) */ - FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */ if (iSize+1 > srcSize) return ERROR(srcSize_wrong); - oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */ + /* max (hwSize-1) values decoded, as last one is implied */ + oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2); if (FSE_isError(oSize)) return oSize; } /* collect weight stats */ - memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); + ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); weightTotal = 0; { U32 n; for (n=0; n<oSize; n++) { if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected); @@ -214,3 +326,37 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, *nbSymbolsPtr = (U32)(oSize+1); return iSize+1; } + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0); +} + +#if DYNAMIC_BMI2 +static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1); +} +#endif + +size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, + int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); + } +#endif + (void)bmi2; + return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); +} diff --git a/lib/common/error_private.c b/lib/common/error_private.c index cd437529c12..6d1135f8c37 100644 --- a/lib/common/error_private.c +++ b/lib/common/error_private.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -48,6 +48,7 @@ const char* ERR_getErrorString(ERR_enum code) case PREFIX(frameIndex_tooLarge): return "Frame index is too large"; case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking"; case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong"; + case PREFIX(srcBuffer_wrong): return "Source buffer is wrong"; case PREFIX(maxCode): default: return notErrorCode; } diff --git a/lib/common/error_private.h b/lib/common/error_private.h index 982cf8e9fe6..6d8b9f77633 100644 --- a/lib/common/error_private.h +++ b/lib/common/error_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -21,8 +21,8 @@ extern "C" { /* **************************************** * Dependencies ******************************************/ -#include <stddef.h> /* size_t */ -#include "zstd_errors.h" /* enum list */ +#include "../zstd_errors.h" /* enum list */ +#include "zstd_deps.h" /* size_t */ /* **************************************** diff --git a/lib/common/fse.h b/lib/common/fse.h index ff54e70ea75..19dd4febcd0 100644 --- a/lib/common/fse.h +++ b/lib/common/fse.h @@ -1,7 +1,7 @@ /* ****************************************************************** * FSE : Finite State Entropy codec * Public Prototypes declaration - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -23,7 +23,7 @@ extern "C" { /*-***************************************** * Dependencies ******************************************/ -#include <stddef.h> /* size_t, ptrdiff_t */ +#include "zstd_deps.h" /* size_t, ptrdiff_t */ /*-***************************************** @@ -137,10 +137,16 @@ FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize /*! FSE_normalizeCount(): normalize counts so that sum(count[]) == Power_of_2 (2^tableLog) 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). + useLowProbCount is a boolean parameter which trades off compressed size for + faster header decoding. When it is set to 1, the compressed data will be slightly + smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be + faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0 + is a good default, since header deserialization makes a big speed difference. + Otherwise, useLowProbCount=1 is a good default, since the speed difference is small. @return : tableLog, or an errorCode, which can be tested using FSE_isError() */ FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, - const unsigned* count, size_t srcSize, unsigned maxSymbolValue); + const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount); /*! FSE_NCountWriteBound(): Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. @@ -228,6 +234,13 @@ FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize); +/*! FSE_readNCount_bmi2(): + * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise. + */ +FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter, + unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, + const void* rBuffer, size_t rBuffSize, int bmi2); + /*! Constructor and Destructor of FSE_DTable. Note that its size depends on 'tableLog' */ typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ @@ -288,12 +301,12 @@ If there is an error, the function will return an error code, which can be teste *******************************************/ /* FSE buffer bounds */ #define FSE_NCOUNTBOUND 512 -#define FSE_BLOCKBOUND(size) (size + (size>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) +#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ /* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ -#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) -#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog)) +#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2)) +#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog))) /* or use the size to malloc() space directly. Pay attention to alignment restrictions though */ #define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable)) @@ -309,9 +322,9 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). - * FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. + * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. */ -#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) +#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); @@ -322,18 +335,30 @@ size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); /* FSE_buildCTable_wksp() : * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). - * `wkspSize` must be >= `(1<<tableLog)`. + * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`. */ +#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (maxSymbolValue + 2 + (1ull << (tableLog - 2))) +#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)) size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); +#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8) +#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned)) +FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); +/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */ + size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); /**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */ size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); /**< build a fake FSE_DTable, designed to always generate the same symbolValue */ -size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog); -/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */ +#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1) +#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned)) +size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize); +/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */ + +size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2); +/**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */ typedef enum { FSE_repeat_none, /**< Cannot use the previous table */ @@ -644,6 +669,9 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) #ifndef FSE_DEFAULT_MEMORY_USAGE # define FSE_DEFAULT_MEMORY_USAGE 13 #endif +#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE) +# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE" +#endif /*!FSE_MAX_SYMBOL_VALUE : * Maximum symbol value authorized. @@ -677,7 +705,7 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) # error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" #endif -#define FSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3) +#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3) #endif /* FSE_STATIC_LINKING_ONLY */ diff --git a/lib/common/fse_decompress.c b/lib/common/fse_decompress.c index bcc2223ccc6..f4ff58fa0ab 100644 --- a/lib/common/fse_decompress.c +++ b/lib/common/fse_decompress.c @@ -1,6 +1,6 @@ /* ****************************************************************** * FSE : Finite State Entropy decoder - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -16,13 +16,14 @@ /* ************************************************************** * Includes ****************************************************************/ -#include <stdlib.h> /* malloc, free, qsort */ -#include <string.h> /* memcpy, memset */ +#include "debug.h" /* assert */ #include "bitstream.h" #include "compiler.h" #define FSE_STATIC_LINKING_ONLY #include "fse.h" #include "error_private.h" +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* ************************************************************** @@ -59,25 +60,27 @@ FSE_DTable* FSE_createDTable (unsigned tableLog) { if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; - return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); + return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); } void FSE_freeDTable (FSE_DTable* dt) { - free(dt); + ZSTD_free(dt); } -size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) +static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize) { void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); - U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; + U16* symbolNext = (U16*)workSpace; + BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1); U32 const maxSV1 = maxSymbolValue + 1; U32 const tableSize = 1 << tableLog; U32 highThreshold = tableSize-1; /* Sanity Checks */ + if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge); if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); @@ -95,11 +98,57 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0; symbolNext[s] = normalizedCounter[s]; } } } - memcpy(dt, &DTableH, sizeof(DTableH)); + ZSTD_memcpy(dt, &DTableH, sizeof(DTableH)); } /* Spread symbols */ - { U32 const tableMask = tableSize-1; + if (highThreshold == tableSize - 1) { + size_t const tableMask = tableSize-1; + size_t const step = FSE_TABLESTEP(tableSize); + /* First lay down the symbols in order. + * We use a uint64_t to lay down 8 bytes at a time. This reduces branch + * misses since small blocks generally have small table logs, so nearly + * all symbols have counts <= 8. We ensure we have 8 bytes at the end of + * our buffer to handle the over-write. + */ + { + U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s<maxSV1; ++s, sv += add) { + int i; + int const n = normalizedCounter[s]; + MEM_write64(spread + pos, sv); + for (i = 8; i < n; i += 8) { + MEM_write64(spread + pos + i, sv); + } + pos += n; + } + } + /* Now we spread those positions across the table. + * The benefit of doing it in two stages is that we avoid the the + * variable size inner loop, which caused lots of branch misses. + * Now we can run through all the positions without any branch misses. + * We unroll the loop twice, since that is what emperically worked best. + */ + { + size_t position = 0; + size_t s; + size_t const unroll = 2; + assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */ + for (s = 0; s < (size_t)tableSize; s += unroll) { + size_t u; + for (u = 0; u < unroll; ++u) { + size_t const uPosition = (position + (u * step)) & tableMask; + tableDecode[uPosition].symbol = spread[s + u]; + } + position = (position + (unroll * step)) & tableMask; + } + assert(position == 0); + } + } else { + U32 const tableMask = tableSize-1; U32 const step = FSE_TABLESTEP(tableSize); U32 s, position = 0; for (s=0; s<maxSV1; s++) { @@ -124,6 +173,11 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned return 0; } +size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize) +{ + return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize); +} + #ifndef FSE_COMMONDEFS_ONLY @@ -251,36 +305,99 @@ size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, } -size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog) +size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0); +} + +typedef struct { + short ncount[FSE_MAX_SYMBOL_VALUE + 1]; + FSE_DTable dtable[1]; /* Dynamically sized */ +} FSE_DecompressWksp; + + +FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body( + void* dst, size_t dstCapacity, + const void* cSrc, size_t cSrcSize, + unsigned maxLog, void* workSpace, size_t wkspSize, + int bmi2) { const BYTE* const istart = (const BYTE*)cSrc; const BYTE* ip = istart; - short counting[FSE_MAX_SYMBOL_VALUE+1]; unsigned tableLog; unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; + FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace; + + DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0); + if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC); /* normal FSE decoding mode */ - size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); - if (FSE_isError(NCountLength)) return NCountLength; - /* if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); */ /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ - if (tableLog > maxLog) return ERROR(tableLog_tooLarge); - ip += NCountLength; - cSrcSize -= NCountLength; + { + size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2); + if (FSE_isError(NCountLength)) return NCountLength; + if (tableLog > maxLog) return ERROR(tableLog_tooLarge); + assert(NCountLength <= cSrcSize); + ip += NCountLength; + cSrcSize -= NCountLength; + } + + if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge); + workSpace = wksp->dtable + FSE_DTABLE_SIZE_U32(tableLog); + wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog); + + CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) ); + + { + const void* ptr = wksp->dtable; + const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; + const U32 fastMode = DTableH->fastMode; - CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); + /* select fast mode (static) */ + if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1); + return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0); + } +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0); +} + +#if DYNAMIC_BMI2 +TARGET_ATTRIBUTE("bmi2") static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1); +} +#endif - return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ +size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize); + } +#endif + (void)bmi2; + return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize); } typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { + U32 wksp[FSE_BUILD_DTABLE_WKSP_SIZE_U32(FSE_TABLELOG_ABSOLUTE_MAX, FSE_MAX_SYMBOL_VALUE)]; + return FSE_buildDTable_wksp(dt, normalizedCounter, maxSymbolValue, tableLog, wksp, sizeof(wksp)); +} + size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize) { - DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ - return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG); + /* Static analyzer seems unable to understand this table will be properly initialized later */ + U32 wksp[FSE_DECOMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; + return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, FSE_MAX_TABLELOG, wksp, sizeof(wksp)); } - +#endif #endif /* FSE_COMMONDEFS_ONLY */ diff --git a/lib/common/huf.h b/lib/common/huf.h index ef432685dac..3d47ced030c 100644 --- a/lib/common/huf.h +++ b/lib/common/huf.h @@ -1,7 +1,7 @@ /* ****************************************************************** * huff0 huffman codec, * part of Finite State Entropy library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -20,7 +20,7 @@ extern "C" { #define HUF_H_298734234 /* *** Dependencies *** */ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" /* size_t */ /* *** library symbols visibility *** */ @@ -111,6 +111,8 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, /* *** Dependencies *** */ #include "mem.h" /* U32 */ +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" /* *** Constants *** */ @@ -133,12 +135,16 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, #define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ /* static allocation of HUF's Compression Table */ +/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */ +struct HUF_CElt_s { + U16 val; + BYTE nbBits; +}; /* typedef'd to HUF_CElt */ +typedef struct HUF_CElt_s HUF_CElt; /* consider it an incomplete type */ #define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */ #define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32)) #define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ - U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \ - void* name##hv = &(name##hb); \ - HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */ + HUF_CElt name[HUF_CTABLE_SIZE_U32(maxSymbolValue)] /* no final ; */ /* static allocation of HUF's DTable */ typedef U32 HUF_DTable; @@ -184,9 +190,9 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, * or to save and regenerate 'CTable' using external methods. */ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); -typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */ size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); +size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize); size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); @@ -226,6 +232,19 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, const void* src, size_t srcSize); +/*! HUF_readStats_wksp() : + * Same as HUF_readStats() but takes an external workspace which must be + * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE. + * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. + */ +#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1) +#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned)) +size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, + U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workspace, size_t wkspSize, + int bmi2); + /** HUF_readCTable() : * Loading a CTable saved with HUF_writeCTable() */ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); @@ -260,7 +279,7 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); * a required workspace size greater than that specified in the following * macro. */ -#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10) +#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9)) #define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32)) #ifndef HUF_FORCE_DECOMPRESS_X2 @@ -332,6 +351,9 @@ size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstS #endif size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2); +#endif #endif /* HUF_STATIC_LINKING_ONLY */ diff --git a/lib/common/mem.h b/lib/common/mem.h index 89c8aea7d22..9f3b81ab9d3 100644 --- a/lib/common/mem.h +++ b/lib/common/mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -18,8 +18,10 @@ extern "C" { /*-**************************************** * Dependencies ******************************************/ -#include <stddef.h> /* size_t, ptrdiff_t */ -#include <string.h> /* memcpy */ +#include <stddef.h> /* size_t, ptrdiff_t */ +#include "compiler.h" /* __has_builtin */ +#include "debug.h" /* DEBUG_STATIC_ASSERT */ +#include "zstd_deps.h" /* ZSTD_memcpy */ /*-**************************************** @@ -39,93 +41,15 @@ extern "C" { # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ #endif -#ifndef __has_builtin -# define __has_builtin(x) 0 /* compat. with non-clang compilers */ -#endif - -/* code only tested on 32 and 64 bits systems */ -#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; } -MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } - -/* detects whether we are being compiled under msan */ -#if defined (__has_feature) -# if __has_feature(memory_sanitizer) -# define MEMORY_SANITIZER 1 -# endif -#endif - -#if defined (MEMORY_SANITIZER) -/* Not all platforms that support msan provide sanitizers/msan_interface.h. - * We therefore declare the functions we need ourselves, rather than trying to - * include the header file... */ - -#include <stdint.h> /* intptr_t */ - -/* Make memory region fully initialized (without changing its contents). */ -void __msan_unpoison(const volatile void *a, size_t size); - -/* Make memory region fully uninitialized (without changing its contents). - This is a legacy interface that does not update origin information. Use - __msan_allocated_memory() instead. */ -void __msan_poison(const volatile void *a, size_t size); - -/* Returns the offset of the first (at least partially) poisoned byte in the - memory range, or -1 if the whole range is good. */ -intptr_t __msan_test_shadow(const volatile void *x, size_t size); -#endif - -/* detects whether we are being compiled under asan */ -#if defined (__has_feature) -# if __has_feature(address_sanitizer) -# define ADDRESS_SANITIZER 1 -# endif -#elif defined(__SANITIZE_ADDRESS__) -# define ADDRESS_SANITIZER 1 -#endif - -#if defined (ADDRESS_SANITIZER) -/* Not all platforms that support asan provide sanitizers/asan_interface.h. - * We therefore declare the functions we need ourselves, rather than trying to - * include the header file... */ - -/** - * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable. - * - * This memory must be previously allocated by your program. Instrumented - * code is forbidden from accessing addresses in this region until it is - * unpoisoned. This function is not guaranteed to poison the entire region - - * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan - * alignment restrictions. - * - * \note This function is not thread-safe because no two threads can poison or - * unpoison memory in the same memory region simultaneously. - * - * \param addr Start of memory region. - * \param size Size of memory region. */ -void __asan_poison_memory_region(void const volatile *addr, size_t size); - -/** - * Marks a memory region (<c>[addr, addr+size)</c>) as addressable. - * - * This memory must be previously allocated by your program. Accessing - * addresses in this region is allowed until this region is poisoned again. - * This function could unpoison a super-region of <c>[addr, addr+size)</c> due - * to ASan alignment restrictions. - * - * \note This function is not thread-safe because no two threads can - * poison or unpoison memory in the same memory region simultaneously. - * - * \param addr Start of memory region. - * \param size Size of memory region. */ -void __asan_unpoison_memory_region(void const volatile *addr, size_t size); -#endif - - /*-************************************************************** * Basic Types *****************************************************************/ #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include <stdint.h> +# if defined(_AIX) +# include <inttypes.h> +# else +# include <stdint.h> /* intptr_t */ +# endif typedef uint8_t BYTE; typedef uint16_t U16; typedef int16_t S16; @@ -157,7 +81,53 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /*-************************************************************** -* Memory I/O +* Memory I/O API +*****************************************************************/ +/*=== Static platform detection ===*/ +MEM_STATIC unsigned MEM_32bits(void); +MEM_STATIC unsigned MEM_64bits(void); +MEM_STATIC unsigned MEM_isLittleEndian(void); + +/*=== Native unaligned read/write ===*/ +MEM_STATIC U16 MEM_read16(const void* memPtr); +MEM_STATIC U32 MEM_read32(const void* memPtr); +MEM_STATIC U64 MEM_read64(const void* memPtr); +MEM_STATIC size_t MEM_readST(const void* memPtr); + +MEM_STATIC void MEM_write16(void* memPtr, U16 value); +MEM_STATIC void MEM_write32(void* memPtr, U32 value); +MEM_STATIC void MEM_write64(void* memPtr, U64 value); + +/*=== Little endian unaligned read/write ===*/ +MEM_STATIC U16 MEM_readLE16(const void* memPtr); +MEM_STATIC U32 MEM_readLE24(const void* memPtr); +MEM_STATIC U32 MEM_readLE32(const void* memPtr); +MEM_STATIC U64 MEM_readLE64(const void* memPtr); +MEM_STATIC size_t MEM_readLEST(const void* memPtr); + +MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val); +MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val); +MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32); +MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64); +MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val); + +/*=== Big endian unaligned read/write ===*/ +MEM_STATIC U32 MEM_readBE32(const void* memPtr); +MEM_STATIC U64 MEM_readBE64(const void* memPtr); +MEM_STATIC size_t MEM_readBEST(const void* memPtr); + +MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32); +MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64); +MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val); + +/*=== Byteswap ===*/ +MEM_STATIC U32 MEM_swap32(U32 in); +MEM_STATIC U64 MEM_swap64(U64 in); +MEM_STATIC size_t MEM_swapST(size_t in); + + +/*-************************************************************** +* Memory I/O Implementation *****************************************************************/ /* MEM_FORCE_MEMORY_ACCESS : * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. @@ -173,9 +143,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); * Prefer these methods in priority order (0 > 1 > 2) */ #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define MEM_FORCE_MEMORY_ACCESS 2 -# elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__) +# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__) # define MEM_FORCE_MEMORY_ACCESS 1 # endif #endif @@ -236,37 +204,37 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = MEM_STATIC U16 MEM_read16(const void* memPtr) { - U16 val; memcpy(&val, memPtr, sizeof(val)); return val; + U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC U32 MEM_read32(const void* memPtr) { - U32 val; memcpy(&val, memPtr, sizeof(val)); return val; + U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC U64 MEM_read64(const void* memPtr) { - U64 val; memcpy(&val, memPtr, sizeof(val)); return val; + U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC size_t MEM_readST(const void* memPtr) { - size_t val; memcpy(&val, memPtr, sizeof(val)); return val; + size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC void MEM_write16(void* memPtr, U16 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } MEM_STATIC void MEM_write32(void* memPtr, U32 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } MEM_STATIC void MEM_write64(void* memPtr, U64 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } #endif /* MEM_FORCE_MEMORY_ACCESS */ @@ -338,7 +306,7 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) MEM_STATIC U32 MEM_readLE24(const void* memPtr) { - return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); + return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16); } MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val) @@ -445,6 +413,9 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val) MEM_writeBE64(memPtr, (U64)val); } +/* code only tested on 32 and 64 bits systems */ +MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } + #if defined (__cplusplus) } diff --git a/lib/common/pool.c b/lib/common/pool.c index aa4b4de0d3f..ea70b8b65ad 100644 --- a/lib/common/pool.c +++ b/lib/common/pool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -10,9 +10,9 @@ /* ====== Dependencies ======= */ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" /* size_t */ #include "debug.h" /* assert */ -#include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */ +#include "zstd_internal.h" /* ZSTD_customMalloc, ZSTD_customFree */ #include "pool.h" /* ====== Compiler specifics ====== */ @@ -105,6 +105,10 @@ static void* POOL_thread(void* opaque) { assert(0); /* Unreachable */ } +POOL_ctx* ZSTD_createThreadPool(size_t numThreads) { + return POOL_create (numThreads, 0); +} + POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem); } @@ -115,14 +119,14 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, /* Check parameters */ if (!numThreads) { return NULL; } /* Allocate the context and zero initialize */ - ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem); + ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem); if (!ctx) { return NULL; } /* Initialize the job queue. * It needs one extra space since one space is wasted to differentiate * empty and full queues. */ ctx->queueSize = queueSize + 1; - ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem); + ctx->queue = (POOL_job*)ZSTD_customMalloc(ctx->queueSize * sizeof(POOL_job), customMem); ctx->queueHead = 0; ctx->queueTail = 0; ctx->numThreadsBusy = 0; @@ -136,7 +140,7 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, } ctx->shutdown = 0; /* Allocate space for the thread handles */ - ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem); + ctx->threads = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), customMem); ctx->threadCapacity = 0; ctx->customMem = customMem; /* Check for errors */ @@ -179,12 +183,14 @@ void POOL_free(POOL_ctx *ctx) { ZSTD_pthread_mutex_destroy(&ctx->queueMutex); ZSTD_pthread_cond_destroy(&ctx->queuePushCond); ZSTD_pthread_cond_destroy(&ctx->queuePopCond); - ZSTD_free(ctx->queue, ctx->customMem); - ZSTD_free(ctx->threads, ctx->customMem); - ZSTD_free(ctx, ctx->customMem); + ZSTD_customFree(ctx->queue, ctx->customMem); + ZSTD_customFree(ctx->threads, ctx->customMem); + ZSTD_customFree(ctx, ctx->customMem); } - +void ZSTD_freeThreadPool (ZSTD_threadPool* pool) { + POOL_free (pool); +} size_t POOL_sizeof(POOL_ctx *ctx) { if (ctx==NULL) return 0; /* supports sizeof NULL */ @@ -203,11 +209,11 @@ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads) return 0; } /* numThreads > threadCapacity */ - { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem); + { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem); if (!threadPool) return 1; /* replace existing thread pool */ - memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool)); - ZSTD_free(ctx->threads, ctx->customMem); + ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool)); + ZSTD_customFree(ctx->threads, ctx->customMem); ctx->threads = threadPool; /* Initialize additional threads */ { size_t threadId; @@ -301,7 +307,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) struct POOL_ctx_s { int dummy; }; -static POOL_ctx g_ctx; +static POOL_ctx g_poolCtx; POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem); @@ -311,11 +317,11 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM (void)numThreads; (void)queueSize; (void)customMem; - return &g_ctx; + return &g_poolCtx; } void POOL_free(POOL_ctx* ctx) { - assert(!ctx || ctx == &g_ctx); + assert(!ctx || ctx == &g_poolCtx); (void)ctx; } @@ -337,7 +343,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) { size_t POOL_sizeof(POOL_ctx* ctx) { if (ctx==NULL) return 0; /* supports sizeof NULL */ - assert(ctx == &g_ctx); + assert(ctx == &g_poolCtx); return sizeof(*ctx); } diff --git a/lib/common/pool.h b/lib/common/pool.h index 259bafc9757..e18aa0708f7 100644 --- a/lib/common/pool.h +++ b/lib/common/pool.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -16,7 +16,7 @@ extern "C" { #endif -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */ #include "../zstd.h" diff --git a/lib/common/threading.c b/lib/common/threading.c index e2edb313ebf..92cf57c195a 100644 --- a/lib/common/threading.c +++ b/lib/common/threading.c @@ -78,11 +78,12 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr) #if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32) -#include <stdlib.h> +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr) { - *mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); + *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t)); if (!*mutex) return 1; return pthread_mutex_init(*mutex, attr); @@ -94,14 +95,14 @@ int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex) return 0; { int const ret = pthread_mutex_destroy(*mutex); - free(*mutex); + ZSTD_free(*mutex); return ret; } } int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr) { - *cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t)); + *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t)); if (!*cond) return 1; return pthread_cond_init(*cond, attr); @@ -113,7 +114,7 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond) return 0; { int const ret = pthread_cond_destroy(*cond); - free(*cond); + ZSTD_free(*cond); return ret; } } diff --git a/lib/common/xxhash.c b/lib/common/xxhash.c index 597de18fc89..926b33604ef 100644 --- a/lib/common/xxhash.c +++ b/lib/common/xxhash.c @@ -1,6 +1,6 @@ /* * xxHash - Fast Hash algorithm - * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - xxHash homepage: http://www.xxhash.com @@ -30,9 +30,7 @@ * Prefer these methods in priority order (0 > 1 > 2) */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define XXH_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ +# if (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \ defined(__ICCARM__) # define XXH_FORCE_MEMORY_ACCESS 1 @@ -77,14 +75,12 @@ * Includes & Memory related functions ***************************************/ /* Modify the local functions below should you wish to use some other memory routines */ -/* for malloc(), free() */ -#include <stdlib.h> -#include <stddef.h> /* size_t */ -static void* XXH_malloc(size_t s) { return malloc(s); } -static void XXH_free (void* p) { free(p); } -/* for memcpy() */ -#include <string.h> -static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } +/* for ZSTD_malloc(), ZSTD_free() */ +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* size_t, ZSTD_malloc, ZSTD_free, ZSTD_memcpy */ +static void* XXH_malloc(size_t s) { return ZSTD_malloc(s); } +static void XXH_free (void* p) { ZSTD_free(p); } +static void* XXH_memcpy(void* dest, const void* src, size_t size) { return ZSTD_memcpy(dest,src,size); } #ifndef XXH_STATIC_LINKING_ONLY # define XXH_STATIC_LINKING_ONLY @@ -95,49 +91,13 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp /* ************************************* * Compiler Specific Options ***************************************/ -#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# define INLINE_KEYWORD inline -#else -# define INLINE_KEYWORD -#endif - -#if defined(__GNUC__) || defined(__ICCARM__) -# define FORCE_INLINE_ATTR __attribute__((always_inline)) -#elif defined(_MSC_VER) -# define FORCE_INLINE_ATTR __forceinline -#else -# define FORCE_INLINE_ATTR -#endif - -#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR - - -#ifdef _MSC_VER -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif +#include "compiler.h" /* ************************************* * Basic Types ***************************************/ -#ifndef MEM_MODULE -# define MEM_MODULE -# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include <stdint.h> - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; -# else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */ -# endif -#endif - +#include "mem.h" /* BYTE, U32, U64, size_t */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) @@ -163,14 +123,14 @@ static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; } static U32 XXH_read32(const void* memPtr) { U32 val; - memcpy(&val, memPtr, sizeof(val)); + ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } static U64 XXH_read64(const void* memPtr) { U64 val; - memcpy(&val, memPtr, sizeof(val)); + ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } @@ -307,12 +267,12 @@ XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } ****************************/ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState) { - memcpy(dstState, srcState, sizeof(*dstState)); + ZSTD_memcpy(dstState, srcState, sizeof(*dstState)); } XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState) { - memcpy(dstState, srcState, sizeof(*dstState)); + ZSTD_memcpy(dstState, srcState, sizeof(*dstState)); } @@ -554,12 +514,12 @@ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) { XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ + ZSTD_memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ state.v1 = seed + PRIME32_1 + PRIME32_2; state.v2 = seed + PRIME32_2; state.v3 = seed + 0; state.v4 = seed - PRIME32_1; - memcpy(statePtr, &state, sizeof(state)); + ZSTD_memcpy(statePtr, &state, sizeof(state)); return XXH_OK; } @@ -567,12 +527,12 @@ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int s XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) { XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ + ZSTD_memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ state.v1 = seed + PRIME64_1 + PRIME64_2; state.v2 = seed + PRIME64_2; state.v3 = seed + 0; state.v4 = seed - PRIME64_1; - memcpy(statePtr, &state, sizeof(state)); + ZSTD_memcpy(statePtr, &state, sizeof(state)); return XXH_OK; } @@ -843,14 +803,14 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); + ZSTD_memcpy(dst, &hash, sizeof(*dst)); } XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); + ZSTD_memcpy(dst, &hash, sizeof(*dst)); } XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h index 4207eba8328..16c1f1617b9 100644 --- a/lib/common/xxhash.h +++ b/lib/common/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - xxHash source repository : https://github.com/Cyan4973/xxHash @@ -55,7 +55,7 @@ extern "C" { /* **************************** * Definitions ******************************/ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; diff --git a/lib/common/zstd_common.c b/lib/common/zstd_common.c index 91fe3323a5b..3d7e35b309b 100644 --- a/lib/common/zstd_common.c +++ b/lib/common/zstd_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -13,8 +13,8 @@ /*-************************************* * Dependencies ***************************************/ -#include <stdlib.h> /* malloc, calloc, free */ -#include <string.h> /* memset */ +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */ #include "error_private.h" #include "zstd_internal.h" @@ -53,31 +53,31 @@ const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString /*=************************************************************** * Custom allocator ****************************************************************/ -void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) +void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem) { if (customMem.customAlloc) return customMem.customAlloc(customMem.opaque, size); - return malloc(size); + return ZSTD_malloc(size); } -void* ZSTD_calloc(size_t size, ZSTD_customMem customMem) +void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem) { if (customMem.customAlloc) { /* calloc implemented as malloc+memset; * not as efficient as calloc, but next best guess for custom malloc */ void* const ptr = customMem.customAlloc(customMem.opaque, size); - memset(ptr, 0, size); + ZSTD_memset(ptr, 0, size); return ptr; } - return calloc(1, size); + return ZSTD_calloc(1, size); } -void ZSTD_free(void* ptr, ZSTD_customMem customMem) +void ZSTD_customFree(void* ptr, ZSTD_customMem customMem) { if (ptr!=NULL) { if (customMem.customFree) customMem.customFree(customMem.opaque, ptr); else - free(ptr); + ZSTD_free(ptr); } } diff --git a/lib/common/zstd_deps.h b/lib/common/zstd_deps.h new file mode 100644 index 00000000000..14211344a02 --- /dev/null +++ b/lib/common/zstd_deps.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* This file provides common libc dependencies that zstd requires. + * The purpose is to allow replacing this file with a custom implementation + * to compile zstd without libc support. + */ + +/* Need: + * NULL + * INT_MAX + * UINT_MAX + * ZSTD_memcpy() + * ZSTD_memset() + * ZSTD_memmove() + */ +#ifndef ZSTD_DEPS_COMMON +#define ZSTD_DEPS_COMMON + +#include <limits.h> +#include <stddef.h> +#include <string.h> + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l)) +# define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l)) +# define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l)) +#else +# define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l)) +# define ZSTD_memmove(d,s,l) memmove((d),(s),(l)) +# define ZSTD_memset(p,v,l) memset((p),(v),(l)) +#endif + +#endif /* ZSTD_DEPS_COMMON */ + +/* Need: + * ZSTD_malloc() + * ZSTD_free() + * ZSTD_calloc() + */ +#ifdef ZSTD_DEPS_NEED_MALLOC +#ifndef ZSTD_DEPS_MALLOC +#define ZSTD_DEPS_MALLOC + +#include <stdlib.h> + +#define ZSTD_malloc(s) malloc(s) +#define ZSTD_calloc(n,s) calloc((n), (s)) +#define ZSTD_free(p) free((p)) + +#endif /* ZSTD_DEPS_MALLOC */ +#endif /* ZSTD_DEPS_NEED_MALLOC */ + +/* + * Provides 64-bit math support. + * Need: + * U64 ZSTD_div64(U64 dividend, U32 divisor) + */ +#ifdef ZSTD_DEPS_NEED_MATH64 +#ifndef ZSTD_DEPS_MATH64 +#define ZSTD_DEPS_MATH64 + +#define ZSTD_div64(dividend, divisor) ((dividend) / (divisor)) + +#endif /* ZSTD_DEPS_MATH64 */ +#endif /* ZSTD_DEPS_NEED_MATH64 */ + +/* Need: + * assert() + */ +#ifdef ZSTD_DEPS_NEED_ASSERT +#ifndef ZSTD_DEPS_ASSERT +#define ZSTD_DEPS_ASSERT + +#include <assert.h> + +#endif /* ZSTD_DEPS_ASSERT */ +#endif /* ZSTD_DEPS_NEED_ASSERT */ + +/* Need: + * ZSTD_DEBUG_PRINT() + */ +#ifdef ZSTD_DEPS_NEED_IO +#ifndef ZSTD_DEPS_IO +#define ZSTD_DEPS_IO + +#include <stdio.h> +#define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) + +#endif /* ZSTD_DEPS_IO */ +#endif /* ZSTD_DEPS_NEED_IO */ + +/* Only requested when <stdint.h> is known to be present. + * Need: + * intptr_t + */ +#ifdef ZSTD_DEPS_NEED_STDINT +#ifndef ZSTD_DEPS_STDINT +#define ZSTD_DEPS_STDINT + +#include <stdint.h> + +#endif /* ZSTD_DEPS_STDINT */ +#endif /* ZSTD_DEPS_NEED_STDINT */ diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 3bc7e55a0a9..68252e987e7 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -19,7 +19,7 @@ /*-************************************* * Dependencies ***************************************/ -#ifdef __aarch64__ +#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) #include <arm_neon.h> #endif #include "compiler.h" @@ -36,6 +36,11 @@ # define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ #endif #include "xxhash.h" /* XXH_reset, update, digest */ +#ifndef ZSTD_NO_TRACE +# include "zstd_trace.h" +#else +# define ZSTD_TRACE 0 +#endif #if defined (__cplusplus) extern "C" { @@ -139,7 +144,7 @@ void _force_has_format_string(const char *format, ...) { #define ZSTD_REP_NUM 3 /* number of repcodes */ #define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) -static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; +static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; #define KB *(1 <<10) #define MB *(1 <<20) @@ -153,13 +158,13 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; #define BIT0 1 #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 -static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; -static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; +static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; +static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; #define ZSTD_FRAMEIDSIZE 4 /* magic number size */ #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ -static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; +static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; #define ZSTD_FRAMECHECKSUMSIZE 4 @@ -186,61 +191,75 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy #define OffFSELog 8 #define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog) -static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, - 4, 6, 7, 8, 9,10,11,12, - 13,14,15,16 }; -static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 2, 1, 1, 1, 1, 1, - -1,-1,-1,-1 }; +#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */ +/* Each table cannot take more than #symbols * FSELog bits */ +#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8) + +static UNUSED_ATTR const U32 LL_bits[MaxLL+1] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 6, 7, 8, 9,10,11,12, + 13,14,15,16 +}; +static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = { + 4, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 2, 1, 1, 1, 1, 1, + -1,-1,-1,-1 +}; #define LL_DEFAULTNORMLOG 6 /* for static allocation */ -static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; - -static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, - 4, 4, 5, 7, 8, 9,10,11, - 12,13,14,15,16 }; -static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1,-1,-1, - -1,-1,-1,-1,-1 }; +static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; + +static UNUSED_ATTR const U32 ML_bits[MaxML+1] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 7, 8, 9,10,11, + 12,13,14,15,16 +}; +static UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = { + 1, 4, 3, 2, 2, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1,-1,-1, + -1,-1,-1,-1,-1 +}; #define ML_DEFAULTNORMLOG 6 /* for static allocation */ -static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; - -static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - -1,-1,-1,-1,-1 }; +static UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; + +static UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = { + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + -1,-1,-1,-1,-1 +}; #define OF_DEFAULTNORMLOG 5 /* for static allocation */ -static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; +static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; /*-******************************************* * Shared functions to include for inlining *********************************************/ static void ZSTD_copy8(void* dst, const void* src) { -#ifdef __aarch64__ +#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src)); #else - memcpy(dst, src, 8); + ZSTD_memcpy(dst, src, 8); #endif } #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } static void ZSTD_copy16(void* dst, const void* src) { -#ifdef __aarch64__ +#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src)); #else - memcpy(dst, src, 16); + ZSTD_memcpy(dst, src, 16); #endif } #define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; } @@ -255,13 +274,13 @@ typedef enum { } ZSTD_overlap_e; /*! ZSTD_wildcopy() : - * Custom version of memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0) + * Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0) * @param ovtype controls the overlap detection * - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart. * - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart. * The src buffer must be before the dst buffer. */ -MEM_STATIC FORCE_INLINE_ATTR +MEM_STATIC FORCE_INLINE_ATTR void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype) { ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src; @@ -284,14 +303,16 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e * one COPY16() in the first call. Then, do two calls per loop since * at that point it is more likely to have a high trip count. */ -#ifndef __aarch64__ +#ifdef __aarch64__ do { COPY16(op, ip); } while (op < oend); #else - COPY16(op, ip); - if (op >= oend) return; + ZSTD_copy16(op, ip); + if (16 >= length) return; + op += 16; + ip += 16; do { COPY16(op, ip); COPY16(op, ip); @@ -305,7 +326,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, { size_t const length = MIN(dstCapacity, srcSize); if (length > 0) { - memcpy(dst, src, length); + ZSTD_memcpy(dst, src, length); } return length; } @@ -320,28 +341,46 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, * In which case, resize it down to free some memory */ #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 +/* Controls whether the input/output buffer is buffered or stable. */ +typedef enum { + ZSTD_bm_buffered = 0, /* Buffer the input/output */ + ZSTD_bm_stable = 1 /* ZSTD_inBuffer/ZSTD_outBuffer is stable */ +} ZSTD_bufferMode_e; + /*-******************************************* * Private declarations *********************************************/ typedef struct seqDef_s { - U32 offset; + U32 offset; /* offset == rawOffset + ZSTD_REP_NUM, or equivalently, offCode + 1 */ U16 litLength; U16 matchLength; } seqDef; +/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */ +typedef enum { + ZSTD_llt_none = 0, /* no longLengthType */ + ZSTD_llt_literalLength = 1, /* represents a long literal */ + ZSTD_llt_matchLength = 2 /* represents a long match */ +} ZSTD_longLengthType_e; + typedef struct { seqDef* sequencesStart; - seqDef* sequences; + seqDef* sequences; /* ptr to end of sequences */ BYTE* litStart; - BYTE* lit; + BYTE* lit; /* ptr to end of literals */ BYTE* llCode; BYTE* mlCode; BYTE* ofCode; size_t maxNbSeq; size_t maxNbLit; - U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ - U32 longLengthPos; + + /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength + * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment + * the existing value of the litLength or matchLength by 0x10000. + */ + ZSTD_longLengthType_e longLengthType; + U32 longLengthPos; /* Index of the sequence to apply long length modification to */ } seqStore_t; typedef struct { @@ -351,7 +390,7 @@ typedef struct { /** * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences - * indicated by longLengthPos and longLengthID, and adds MINMATCH back to matchLength. + * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. */ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq) { @@ -359,10 +398,10 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore seqLen.litLength = seq->litLength; seqLen.matchLength = seq->matchLength + MINMATCH; if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) { - if (seqStore->longLengthID == 1) { + if (seqStore->longLengthType == ZSTD_llt_literalLength) { seqLen.litLength += 0xFFFF; } - if (seqStore->longLengthID == 2) { + if (seqStore->longLengthType == ZSTD_llt_matchLength) { seqLen.matchLength += 0xFFFF; } } @@ -384,9 +423,9 @@ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBu void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ /* custom memory allocation functions */ -void* ZSTD_malloc(size_t size, ZSTD_customMem customMem); -void* ZSTD_calloc(size_t size, ZSTD_customMem customMem); -void ZSTD_free(void* ptr, ZSTD_customMem customMem); +void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem); +void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem); +void ZSTD_customFree(void* ptr, ZSTD_customMem customMem); MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */ @@ -394,8 +433,12 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus assert(val != 0); { # if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# if STATIC_BMI2 == 1 + return _lzcnt_u32(val)^31; +# else + unsigned long r=0; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h new file mode 100644 index 00000000000..2da5640771d --- /dev/null +++ b/lib/common/zstd_trace.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_TRACE_H +#define ZSTD_TRACE_H + +#if defined (__cplusplus) +extern "C" { +#endif + +#include <stddef.h> + +/* weak symbol support */ +#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && defined(__GNUC__) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \ + !defined(__CYGWIN__) +# define ZSTD_HAVE_WEAK_SYMBOLS 1 +#else +# define ZSTD_HAVE_WEAK_SYMBOLS 0 +#endif +#if ZSTD_HAVE_WEAK_SYMBOLS +# define ZSTD_WEAK_ATTR __attribute__((__weak__)) +#else +# define ZSTD_WEAK_ATTR +#endif + +/* Only enable tracing when weak symbols are available. */ +#ifndef ZSTD_TRACE +# define ZSTD_TRACE ZSTD_HAVE_WEAK_SYMBOLS +#endif + +#if ZSTD_TRACE + +struct ZSTD_CCtx_s; +struct ZSTD_DCtx_s; +struct ZSTD_CCtx_params_s; + +typedef struct { + /** + * ZSTD_VERSION_NUMBER + * + * This is guaranteed to be the first member of ZSTD_trace. + * Otherwise, this struct is not stable between versions. If + * the version number does not match your expectation, you + * should not interpret the rest of the struct. + */ + unsigned version; + /** + * Non-zero if streaming (de)compression is used. + */ + unsigned streaming; + /** + * The dictionary ID. + */ + unsigned dictionaryID; + /** + * Is the dictionary cold? + * Only set on decompression. + */ + unsigned dictionaryIsCold; + /** + * The dictionary size or zero if no dictionary. + */ + size_t dictionarySize; + /** + * The uncompressed size of the data. + */ + size_t uncompressedSize; + /** + * The compressed size of the data. + */ + size_t compressedSize; + /** + * The fully resolved CCtx parameters (NULL on decompression). + */ + struct ZSTD_CCtx_params_s const* params; + /** + * The ZSTD_CCtx pointer (NULL on decompression). + */ + struct ZSTD_CCtx_s const* cctx; + /** + * The ZSTD_DCtx pointer (NULL on compression). + */ + struct ZSTD_DCtx_s const* dctx; +} ZSTD_Trace; + +/** + * A tracing context. It must be 0 when tracing is disabled. + * Otherwise, any non-zero value returned by a tracing begin() + * function is presented to any subsequent calls to end(). + * + * Any non-zero value is treated as tracing is enabled and not + * interpreted by the library. + * + * Two possible uses are: + * * A timestamp for when the begin() function was called. + * * A unique key identifying the (de)compression, like the + * address of the [dc]ctx pointer if you need to track + * more information than just a timestamp. + */ +typedef unsigned long long ZSTD_TraceCtx; + +/** + * Trace the beginning of a compression call. + * @param cctx The dctx pointer for the compression. + * It can be used as a key to map begin() to end(). + * @returns Non-zero if tracing is enabled. The return value is + * passed to ZSTD_trace_compress_end(). + */ +ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_compress_begin( + struct ZSTD_CCtx_s const* cctx); + +/** + * Trace the end of a compression call. + * @param ctx The return value of ZSTD_trace_compress_begin(). + * @param trace The zstd tracing info. + */ +ZSTD_WEAK_ATTR void ZSTD_trace_compress_end( + ZSTD_TraceCtx ctx, + ZSTD_Trace const* trace); + +/** + * Trace the beginning of a decompression call. + * @param dctx The dctx pointer for the decompression. + * It can be used as a key to map begin() to end(). + * @returns Non-zero if tracing is enabled. The return value is + * passed to ZSTD_trace_compress_end(). + */ +ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_decompress_begin( + struct ZSTD_DCtx_s const* dctx); + +/** + * Trace the end of a decompression call. + * @param ctx The return value of ZSTD_trace_decompress_begin(). + * @param trace The zstd tracing info. + */ +ZSTD_WEAK_ATTR void ZSTD_trace_decompress_end( + ZSTD_TraceCtx ctx, + ZSTD_Trace const* trace); + +#endif /* ZSTD_TRACE */ + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_TRACE_H */ diff --git a/lib/compress/fse_compress.c b/lib/compress/fse_compress.c index a42759814fd..b4297ec88a4 100644 --- a/lib/compress/fse_compress.c +++ b/lib/compress/fse_compress.c @@ -1,6 +1,6 @@ /* ****************************************************************** * FSE : Finite State Entropy encoder - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -15,8 +15,6 @@ /* ************************************************************** * Includes ****************************************************************/ -#include <stdlib.h> /* malloc, free, qsort */ -#include <string.h> /* memcpy, memset */ #include "../common/compiler.h" #include "../common/mem.h" /* U32, U16, etc. */ #include "../common/debug.h" /* assert, DEBUGLOG */ @@ -25,6 +23,9 @@ #define FSE_STATIC_LINKING_ONLY #include "../common/fse.h" #include "../common/error_private.h" +#define ZSTD_DEPS_NEED_MALLOC +#define ZSTD_DEPS_NEED_MATH64 +#include "../common/zstd_deps.h" /* ZSTD_malloc, ZSTD_free, ZSTD_memcpy, ZSTD_memset */ /* ************************************************************** @@ -74,13 +75,15 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ; FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT); U32 const step = FSE_TABLESTEP(tableSize); - U32 cumul[FSE_MAX_SYMBOL_VALUE+2]; - FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)workSpace; + U32* cumul = (U32*)workSpace; + FSE_FUNCTION_TYPE* tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSymbolValue + 2)); + U32 highThreshold = tableSize-1; + if ((size_t)workSpace & 3) return ERROR(GENERIC); /* Must be 4 byte aligned */ + if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge); /* CTable header */ - if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge); tableU16[-2] = (U16) tableLog; tableU16[-1] = (U16) maxSymbolValue; assert(tableLog < 16); /* required for threshold strategy to work */ @@ -89,7 +92,7 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */ #ifdef __clang_analyzer__ - memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */ + ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */ #endif /* symbol start positions */ @@ -168,12 +171,13 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, return 0; } - +#ifndef ZSTD_NO_UNUSED_FUNCTIONS size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */ return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol)); } +#endif @@ -307,10 +311,10 @@ FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog) size_t size; if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32); - return (FSE_CTable*)malloc(size); + return (FSE_CTable*)ZSTD_malloc(size); } -void FSE_freeCTable (FSE_CTable* ct) { free(ct); } +void FSE_freeCTable (FSE_CTable* ct) { ZSTD_free(ct); } /* provides the minimum logSize to safely represent a distribution */ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) @@ -341,11 +345,10 @@ unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2); } - /* Secondary normalization method. To be used when primary method fails. */ -static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue) +static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue, short lowProbCount) { short const NOT_YET_ASSIGNED = -2; U32 s; @@ -362,7 +365,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, continue; } if (count[s] <= lowThreshold) { - norm[s] = -1; + norm[s] = lowProbCount; distributed++; total -= count[s]; continue; @@ -414,7 +417,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, { U64 const vStepLog = 62 - tableLog; U64 const mid = (1ULL << (vStepLog-1)) - 1; - U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */ + U64 const rStep = ZSTD_div64((((U64)1<<vStepLog) * ToDistribute) + mid, (U32)total); /* scale on remaining */ U64 tmpTotal = mid; for (s=0; s<=maxSymbolValue; s++) { if (norm[s]==NOT_YET_ASSIGNED) { @@ -431,10 +434,9 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, return 0; } - size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t total, - unsigned maxSymbolValue) + unsigned maxSymbolValue, unsigned useLowProbCount) { /* Sanity checks */ if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; @@ -443,8 +445,9 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ { static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 }; + short const lowProbCount = useLowProbCount ? -1 : 1; U64 const scale = 62 - tableLog; - U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */ + U64 const step = ZSTD_div64((U64)1<<62, (U32)total); /* <== here, one division ! */ U64 const vStep = 1ULL<<(scale-20); int stillToDistribute = 1<<tableLog; unsigned s; @@ -456,7 +459,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, if (count[s] == total) return 0; /* rle special case */ if (count[s] == 0) { normalizedCounter[s]=0; continue; } if (count[s] <= lowThreshold) { - normalizedCounter[s] = -1; + normalizedCounter[s] = lowProbCount; stillToDistribute--; } else { short proba = (short)((count[s]*step) >> scale); @@ -470,7 +473,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, } } if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) { /* corner case, need another normalization method */ - size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue); + size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue, lowProbCount); if (FSE_isError(errorCode)) return errorCode; } else normalizedCounter[largest] += (short)stillToDistribute; @@ -625,6 +628,7 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize, size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). * `wkspSize` size must be `(1<<tableLog)`. @@ -643,7 +647,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src size_t const scratchBufferSize = wkspSize - (CTableSize * sizeof(FSE_CTable)); /* init conditions */ - if (wkspSize < FSE_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge); + if (wkspSize < FSE_COMPRESS_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge); if (srcSize <= 1) return 0; /* Not compressible */ if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE; if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG; @@ -656,7 +660,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src } tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) ); + CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue, /* useLowProbCount */ srcSize >= 2048) ); /* Write table description header */ { CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); @@ -678,13 +682,16 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src typedef struct { FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; - BYTE scratchBuffer[1 << FSE_MAX_TABLELOG]; + union { + U32 hist_wksp[HIST_WKSP_SIZE_U32]; + BYTE scratchBuffer[1 << FSE_MAX_TABLELOG]; + } workspace; } fseWkspMax_t; size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog) { fseWkspMax_t scratchBuffer; - DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ + DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_COMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer)); } @@ -693,6 +700,6 @@ size_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcS { return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG); } - +#endif #endif /* FSE_COMMONDEFS_ONLY */ diff --git a/lib/compress/hist.c b/lib/compress/hist.c index 61e08c7968b..073c57e7527 100644 --- a/lib/compress/hist.c +++ b/lib/compress/hist.c @@ -1,7 +1,7 @@ /* ****************************************************************** * hist : Histogram functions * part of Finite State Entropy project - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -34,7 +34,7 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, unsigned maxSymbolValue = *maxSymbolValuePtr; unsigned largestCount=0; - memset(count, 0, (maxSymbolValue+1) * sizeof(*count)); + ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count)); if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; } while (ip<end) { @@ -60,9 +60,9 @@ typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e; * this design makes better use of OoO cpus, * and is noticeably faster when some values are heavily repeated. * But it needs some additional workspace for intermediate tables. - * `workSpace` size must be a table of size >= HIST_WKSP_SIZE_U32. + * `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32. * @return : largest histogram frequency, - * or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */ + * or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */ static size_t HIST_count_parallel_wksp( unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize, @@ -71,22 +71,21 @@ static size_t HIST_count_parallel_wksp( { const BYTE* ip = (const BYTE*)source; const BYTE* const iend = ip+sourceSize; - unsigned maxSymbolValue = *maxSymbolValuePtr; + size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count); unsigned max=0; U32* const Counting1 = workSpace; U32* const Counting2 = Counting1 + 256; U32* const Counting3 = Counting2 + 256; U32* const Counting4 = Counting3 + 256; - memset(workSpace, 0, 4*256*sizeof(unsigned)); - /* safety checks */ + assert(*maxSymbolValuePtr <= 255); if (!sourceSize) { - memset(count, 0, maxSymbolValue + 1); + ZSTD_memset(count, 0, countSize); *maxSymbolValuePtr = 0; return 0; } - if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */ + ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned)); /* by stripes of 16 bytes */ { U32 cached = MEM_read32(ip); ip += 4; @@ -118,21 +117,18 @@ static size_t HIST_count_parallel_wksp( /* finish last symbols */ while (ip<iend) Counting1[*ip++]++; - if (check) { /* verify stats will fit into destination table */ - U32 s; for (s=255; s>maxSymbolValue; s--) { - Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; - if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); - } } - { U32 s; - if (maxSymbolValue > 255) maxSymbolValue = 255; - for (s=0; s<=maxSymbolValue; s++) { - count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; - if (count[s] > max) max = count[s]; + for (s=0; s<256; s++) { + Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; + if (Counting1[s] > max) max = Counting1[s]; } } - while (!count[maxSymbolValue]) maxSymbolValue--; - *maxSymbolValuePtr = maxSymbolValue; + { unsigned maxSymbolValue = 255; + while (!Counting1[maxSymbolValue]) maxSymbolValue--; + if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall); + *maxSymbolValuePtr = maxSymbolValue; + ZSTD_memmove(count, Counting1, countSize); /* in case count & Counting1 are overlapping */ + } return (size_t)max; } @@ -152,14 +148,6 @@ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace); } -/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ -size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, - const void* source, size_t sourceSize) -{ - unsigned tmpCounters[HIST_WKSP_SIZE_U32]; - return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); -} - /* HIST_count_wksp() : * Same as HIST_count(), but using an externally provided scratch buffer. * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */ @@ -175,9 +163,19 @@ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr, return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ +size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, + const void* source, size_t sourceSize) +{ + unsigned tmpCounters[HIST_WKSP_SIZE_U32]; + return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); +} + size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize) { unsigned tmpCounters[HIST_WKSP_SIZE_U32]; return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters)); } +#endif diff --git a/lib/compress/hist.h b/lib/compress/hist.h index 77e3ec4fb19..228ed48a71d 100644 --- a/lib/compress/hist.h +++ b/lib/compress/hist.h @@ -1,7 +1,7 @@ /* ****************************************************************** * hist : Histogram functions * part of Finite State Entropy project - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -14,7 +14,7 @@ ****************************************************************** */ /* --- dependencies --- */ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ /* --- simple histogram functions --- */ diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 546879868a5..485906e678a 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -1,6 +1,6 @@ /* ****************************************************************** * Huffman encoder, part of New Generation Entropy library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -23,8 +23,7 @@ /* ************************************************************** * Includes ****************************************************************/ -#include <string.h> /* memcpy, memset */ -#include <stdio.h> /* printf (debug) */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */ #include "../common/compiler.h" #include "../common/bitstream.h" #include "hist.h" @@ -60,7 +59,15 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX. */ #define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6 -static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize) + +typedef struct { + FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; + U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)]; + unsigned count[HUF_TABLELOG_MAX+1]; + S16 norm[HUF_TABLELOG_MAX+1]; +} HUF_CompressWeightsWksp; + +static size_t HUF_compressWeights(void* dst, size_t dstSize, const void* weightTable, size_t wtSize, void* workspace, size_t workspaceSize) { BYTE* const ostart = (BYTE*) dst; BYTE* op = ostart; @@ -68,33 +75,30 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight unsigned maxSymbolValue = HUF_TABLELOG_MAX; U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; + HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)workspace; - FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; - BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER]; - - unsigned count[HUF_TABLELOG_MAX+1]; - S16 norm[HUF_TABLELOG_MAX+1]; + if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC); /* init conditions */ if (wtSize <= 1) return 0; /* Not compressible */ /* Scan input and build symbol stats */ - { unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize); /* never fails */ + { unsigned const maxCount = HIST_count_simple(wksp->count, &maxSymbolValue, weightTable, wtSize); /* never fails */ if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */ if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */ } tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); + CHECK_F( FSE_normalizeCount(wksp->norm, tableLog, wksp->count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) ); /* Write table description header */ - { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) ); + { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), wksp->norm, maxSymbolValue, tableLog) ); op += hSize; } /* Compress */ - CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); - { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) ); + CHECK_F( FSE_buildCTable_wksp(wksp->CTable, wksp->norm, maxSymbolValue, tableLog, wksp->scratchBuffer, sizeof(wksp->scratchBuffer)) ); + { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, wksp->CTable) ); if (cSize == 0) return 0; /* not enough space for compressed data */ op += cSize; } @@ -103,34 +107,33 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight } -struct HUF_CElt_s { - U16 val; - BYTE nbBits; -}; /* typedef'd to HUF_CElt within "huf.h" */ - -/*! HUF_writeCTable() : - `CTable` : Huffman tree to save, using huf representation. - @return : size of saved CTable */ -size_t HUF_writeCTable (void* dst, size_t maxDstSize, - const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog) -{ +typedef struct { + HUF_CompressWeightsWksp wksp; BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */ BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; +} HUF_WriteCTableWksp; + +size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, + const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, + void* workspace, size_t workspaceSize) +{ BYTE* op = (BYTE*)dst; U32 n; + HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)workspace; - /* check conditions */ + /* check conditions */ + if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC); if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); /* convert to weight */ - bitsToWeight[0] = 0; + wksp->bitsToWeight[0] = 0; for (n=1; n<huffLog+1; n++) - bitsToWeight[n] = (BYTE)(huffLog + 1 - n); + wksp->bitsToWeight[n] = (BYTE)(huffLog + 1 - n); for (n=0; n<maxSymbolValue; n++) - huffWeight[n] = bitsToWeight[CTable[n].nbBits]; + wksp->huffWeight[n] = wksp->bitsToWeight[CTable[n].nbBits]; /* attempt weights compression by FSE */ - { CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) ); + { CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) ); if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */ op[0] = (BYTE)hSize; return hSize+1; @@ -140,12 +143,22 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize, if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */ if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1)); - huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */ + wksp->huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */ for (n=0; n<maxSymbolValue; n+=2) - op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]); + op[(n/2)+1] = (BYTE)((wksp->huffWeight[n] << 4) + wksp->huffWeight[n+1]); return ((maxSymbolValue+1)/2) + 1; } +/*! HUF_writeCTable() : + `CTable` : Huffman tree to save, using huf representation. + @return : size of saved CTable */ +size_t HUF_writeCTable (void* dst, size_t maxDstSize, + const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog) +{ + HUF_WriteCTableWksp wksp; + return HUF_writeCTable_wksp(dst, maxDstSize, CTable, maxSymbolValue, huffLog, &wksp, sizeof(wksp)); +} + size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights) { @@ -156,6 +169,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void /* get symbol weights */ CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize)); + *hasZeroWeights = (rankVal[0] > 0); /* check result */ if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); @@ -164,16 +178,14 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void /* Prepare base value per rank */ { U32 n, nextRankStart = 0; for (n=1; n<=tableLog; n++) { - U32 current = nextRankStart; + U32 curr = nextRankStart; nextRankStart += (rankVal[n] << (n-1)); - rankVal[n] = current; + rankVal[n] = curr; } } /* fill nbBits */ - *hasZeroWeights = 0; { U32 n; for (n=0; n<nbSymbols; n++) { const U32 w = huffWeight[n]; - *hasZeroWeights |= (w == 0); CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0); } } @@ -212,32 +224,63 @@ typedef struct nodeElt_s { BYTE nbBits; } nodeElt; +/** + * HUF_setMaxHeight(): + * Enforces maxNbBits on the Huffman tree described in huffNode. + * + * It sets all nodes with nbBits > maxNbBits to be maxNbBits. Then it adjusts + * the tree to so that it is a valid canonical Huffman tree. + * + * @pre The sum of the ranks of each symbol == 2^largestBits, + * where largestBits == huffNode[lastNonNull].nbBits. + * @post The sum of the ranks of each symbol == 2^largestBits, + * where largestBits is the return value <= maxNbBits. + * + * @param huffNode The Huffman tree modified in place to enforce maxNbBits. + * @param lastNonNull The symbol with the lowest count in the Huffman tree. + * @param maxNbBits The maximum allowed number of bits, which the Huffman tree + * may not respect. After this function the Huffman tree will + * respect maxNbBits. + * @return The maximum number of bits of the Huffman tree after adjustment, + * necessarily no more than maxNbBits. + */ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) { const U32 largestBits = huffNode[lastNonNull].nbBits; - if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */ + /* early exit : no elt > maxNbBits, so the tree is already valid. */ + if (largestBits <= maxNbBits) return largestBits; /* there are several too large elements (at least >= 2) */ { int totalCost = 0; const U32 baseCost = 1 << (largestBits - maxNbBits); int n = (int)lastNonNull; + /* Adjust any ranks > maxNbBits to maxNbBits. + * Compute totalCost, which is how far the sum of the ranks is + * we are over 2^largestBits after adjust the offending ranks. + */ while (huffNode[n].nbBits > maxNbBits) { totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); huffNode[n].nbBits = (BYTE)maxNbBits; - n --; - } /* n stops at huffNode[n].nbBits <= maxNbBits */ - while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */ + n--; + } + /* n stops at huffNode[n].nbBits <= maxNbBits */ + assert(huffNode[n].nbBits <= maxNbBits); + /* n end at index of smallest symbol using < maxNbBits */ + while (huffNode[n].nbBits == maxNbBits) --n; - /* renorm totalCost */ - totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */ + /* renorm totalCost from 2^largestBits to 2^maxNbBits + * note : totalCost is necessarily a multiple of baseCost */ + assert((totalCost & (baseCost - 1)) == 0); + totalCost >>= (largestBits - maxNbBits); + assert(totalCost > 0); /* repay normalized cost */ { U32 const noSymbol = 0xF0F0F0F0; U32 rankLast[HUF_TABLELOG_MAX+2]; - /* Get pos of last (smallest) symbol per rank */ - memset(rankLast, 0xF0, sizeof(rankLast)); + /* Get pos of last (smallest = lowest cum. count) symbol per rank */ + ZSTD_memset(rankLast, 0xF0, sizeof(rankLast)); { U32 currentNbBits = maxNbBits; int pos; for (pos=n ; pos >= 0; pos--) { @@ -247,34 +290,65 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) } } while (totalCost > 0) { + /* Try to reduce the next power of 2 above totalCost because we + * gain back half the rank. + */ U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1; for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { U32 const highPos = rankLast[nBitsToDecrease]; U32 const lowPos = rankLast[nBitsToDecrease-1]; if (highPos == noSymbol) continue; + /* Decrease highPos if no symbols of lowPos or if it is + * not cheaper to remove 2 lowPos than highPos. + */ if (lowPos == noSymbol) break; { U32 const highTotal = huffNode[highPos].count; U32 const lowTotal = 2 * huffNode[lowPos].count; if (highTotal <= lowTotal) break; } } /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ + assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1); /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) - nBitsToDecrease ++; + nBitsToDecrease++; + assert(rankLast[nBitsToDecrease] != noSymbol); + /* Increase the number of bits to gain back half the rank cost. */ totalCost -= 1 << (nBitsToDecrease-1); + huffNode[rankLast[nBitsToDecrease]].nbBits++; + + /* Fix up the new rank. + * If the new rank was empty, this symbol is now its smallest. + * Otherwise, this symbol will be the largest in the new rank so no adjustment. + */ if (rankLast[nBitsToDecrease-1] == noSymbol) - rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */ - huffNode[rankLast[nBitsToDecrease]].nbBits ++; + rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; + /* Fix up the old rank. + * If the symbol was at position 0, meaning it was the highest weight symbol in the tree, + * it must be the only symbol in its rank, so the old rank now has no symbols. + * Otherwise, since the Huffman nodes are sorted by count, the previous position is now + * the smallest node in the rank. If the previous position belongs to a different rank, + * then the rank is now empty. + */ if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ rankLast[nBitsToDecrease] = noSymbol; else { rankLast[nBitsToDecrease]--; if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease) rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ - } } /* while (totalCost > 0) */ - + } + } /* while (totalCost > 0) */ + + /* If we've removed too much weight, then we have to add it back. + * To avoid overshooting again, we only adjust the smallest rank. + * We take the largest nodes from the lowest rank 0 and move them + * to rank 1. There's guaranteed to be enough rank 0 symbols because + * TODO. + */ while (totalCost < 0) { /* Sometimes, cost correction overshoot */ - if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ + /* special case : no rank 1 symbol (using maxNbBits-1); + * let's create one from largest rank 0 (using maxNbBits). + */ + if (rankLast[1] == noSymbol) { while (huffNode[n].nbBits == maxNbBits) n--; huffNode[n+1].nbBits--; assert(n >= 0); @@ -285,14 +359,16 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) huffNode[ rankLast[1] + 1 ].nbBits--; rankLast[1]++; totalCost ++; - } } } /* there are several too large elements (at least >= 2) */ + } + } /* repay normalized cost */ + } /* there are several too large elements (at least >= 2) */ return maxNbBits; } typedef struct { U32 base; - U32 current; + U32 curr; } rankPos; typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; @@ -304,21 +380,45 @@ typedef struct { rankPos rankPosition[RANK_POSITION_TABLE_SIZE]; } HUF_buildCTable_wksp_tables; +/** + * HUF_sort(): + * Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order. + * + * @param[out] huffNode Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled. + * Must have (maxSymbolValue + 1) entries. + * @param[in] count Histogram of the symbols. + * @param[in] maxSymbolValue Maximum symbol value. + * @param rankPosition This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries. + */ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition) { - U32 n; - - memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); - for (n=0; n<=maxSymbolValue; n++) { - U32 r = BIT_highbit32(count[n] + 1); - rankPosition[r].base ++; + int n; + int const maxSymbolValue1 = (int)maxSymbolValue + 1; + + /* Compute base and set curr to base. + * For symbol s let lowerRank = BIT_highbit32(count[n]+1) and rank = lowerRank + 1. + * Then 2^lowerRank <= count[n]+1 <= 2^rank. + * We attribute each symbol to lowerRank's base value, because we want to know where + * each rank begins in the output, so for rank R we want to count ranks R+1 and above. + */ + ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); + for (n = 0; n < maxSymbolValue1; ++n) { + U32 lowerRank = BIT_highbit32(count[n] + 1); + rankPosition[lowerRank].base++; } - for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base; - for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base; - for (n=0; n<=maxSymbolValue; n++) { + assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0); + for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) { + rankPosition[n-1].base += rankPosition[n].base; + rankPosition[n-1].curr = rankPosition[n-1].base; + } + /* Sort */ + for (n = 0; n < maxSymbolValue1; ++n) { U32 const c = count[n]; U32 const r = BIT_highbit32(c+1) + 1; - U32 pos = rankPosition[r].current++; + U32 pos = rankPosition[r].curr++; + /* Insert into the correct position in the rank. + * We have at most 256 symbols, so this insertion should be fine. + */ while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) { huffNode[pos] = huffNode[pos-1]; pos--; @@ -335,28 +435,20 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu */ #define STARTNODE (HUF_SYMBOLVALUE_MAX+1) -size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) +/* HUF_buildTree(): + * Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree. + * + * @param huffNode The array sorted by HUF_sort(). Builds the Huffman tree in this array. + * @param maxSymbolValue The maximum symbol value. + * @return The smallest node in the Huffman tree (by count). + */ +static int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue) { - HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; - nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; - nodeElt* const huffNode = huffNode0+1; + nodeElt* const huffNode0 = huffNode - 1; int nonNullRank; int lowS, lowN; int nodeNb = STARTNODE; int n, nodeRoot; - - /* safety checks */ - if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) - return ERROR(workSpace_tooSmall); - if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) - return ERROR(maxSymbolValue_tooLarge); - memset(huffNode0, 0, sizeof(huffNodeTable)); - - /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); - /* init for parents */ nonNullRank = (int)maxSymbolValue; while(huffNode[nonNullRank].count == 0) nonNullRank--; @@ -383,42 +475,72 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo for (n=0; n<=nonNullRank; n++) huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; + return nonNullRank; +} + +/** + * HUF_buildCTableFromTree(): + * Build the CTable given the Huffman tree in huffNode. + * + * @param[out] CTable The output Huffman CTable. + * @param huffNode The Huffman tree. + * @param nonNullRank The last and smallest node in the Huffman tree. + * @param maxSymbolValue The maximum symbol value. + * @param maxNbBits The exact maximum number of bits used in the Huffman tree. + */ +static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits) +{ + /* fill result into ctable (val, nbBits) */ + int n; + U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; + U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; + int const alphabetSize = (int)(maxSymbolValue + 1); + for (n=0; n<=nonNullRank; n++) + nbPerRank[huffNode[n].nbBits]++; + /* determine starting value per rank */ + { U16 min = 0; + for (n=(int)maxNbBits; n>0; n--) { + valPerRank[n] = min; /* get starting value within each rank */ + min += nbPerRank[n]; + min >>= 1; + } } + for (n=0; n<alphabetSize; n++) + CTable[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ + for (n=0; n<alphabetSize; n++) + CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */ +} + +size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) +{ + HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; + nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; + nodeElt* const huffNode = huffNode0+1; + int nonNullRank; + + /* safety checks */ + if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ + if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) + return ERROR(workSpace_tooSmall); + if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) + return ERROR(maxSymbolValue_tooLarge); + ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable)); + + /* sort, decreasing order */ + HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); + + /* build tree */ + nonNullRank = HUF_buildTree(huffNode, maxSymbolValue); + /* enforce maxTableLog */ maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); + if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ - /* fill result into tree (val, nbBits) */ - { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; - U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; - int const alphabetSize = (int)(maxSymbolValue + 1); - if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ - for (n=0; n<=nonNullRank; n++) - nbPerRank[huffNode[n].nbBits]++; - /* determine stating value per rank */ - { U16 min = 0; - for (n=(int)maxNbBits; n>0; n--) { - valPerRank[n] = min; /* get starting value within each rank */ - min += nbPerRank[n]; - min >>= 1; - } } - for (n=0; n<alphabetSize; n++) - tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ - for (n=0; n<alphabetSize; n++) - tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */ - } + HUF_buildCTableFromTree(tree, huffNode, nonNullRank, maxSymbolValue, maxNbBits); return maxNbBits; } -/** HUF_buildCTable() : - * @return : maxNbBits - * Note : count is used before tree is written, so they can safely overlap - */ -size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) -{ - HUF_buildCTable_wksp_tables workspace; - return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace)); -} - size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { size_t nbBits = 0; @@ -629,29 +751,33 @@ static size_t HUF_compressCTable_internal( typedef struct { unsigned count[HUF_SYMBOLVALUE_MAX + 1]; HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1]; - HUF_buildCTable_wksp_tables buildCTable_wksp; + union { + HUF_buildCTable_wksp_tables buildCTable_wksp; + HUF_WriteCTableWksp writeCTable_wksp; + } wksps; } HUF_compress_tables_t; /* HUF_compress_internal() : - * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ + * `workSpace_align4` must be aligned on 4-bytes boundaries, + * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U32 unsigned */ static size_t HUF_compress_internal (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, HUF_nbStreams_e nbStreams, - void* workSpace, size_t wkspSize, + void* workSpace_align4, size_t wkspSize, HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat, const int bmi2) { - HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace; + HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace_align4; BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstSize; BYTE* op = ostart; HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE); + assert(((size_t)workSpace_align4 & 3) == 0); /* must be aligned on 4-bytes boundaries */ /* checks & inits */ - if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall); if (!srcSize) return 0; /* Uncompressed */ if (!dstSize) return 0; /* cannot fit anything within dst budget */ @@ -669,7 +795,7 @@ HUF_compress_internal (void* dst, size_t dstSize, } /* Scan input and build symbol stats */ - { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) ); + { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace_align4, wkspSize) ); if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */ } @@ -691,16 +817,17 @@ HUF_compress_internal (void* dst, size_t dstSize, huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count, maxSymbolValue, huffLog, - &table->buildCTable_wksp, sizeof(table->buildCTable_wksp)); + &table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp)); CHECK_F(maxBits); huffLog = (U32)maxBits; /* Zero unused symbols in CTable, so we can check it for validity */ - memset(table->CTable + (maxSymbolValue + 1), 0, + ZSTD_memset(table->CTable + (maxSymbolValue + 1), 0, sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt))); } /* Write table description header */ - { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) ); + { CHECK_V_F(hSize, HUF_writeCTable_wksp(op, dstSize, table->CTable, maxSymbolValue, huffLog, + &table->wksps.writeCTable_wksp, sizeof(table->wksps.writeCTable_wksp)) ); /* Check if using previous huffman table is beneficial */ if (repeat && *repeat != HUF_repeat_none) { size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue); @@ -716,7 +843,7 @@ HUF_compress_internal (void* dst, size_t dstSize, op += hSize; if (repeat) { *repeat = HUF_repeat_none; } if (oldHufTable) - memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */ + ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */ } return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, @@ -747,14 +874,6 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize, repeat, preferRepeat, bmi2); } -size_t HUF_compress1X (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog) -{ - unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; - return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); -} - /* HUF_compress4X_repeat(): * compress input using 4 streams. * provide workspace to generate compression tables */ @@ -784,6 +903,25 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize, hufTable, repeat, preferRepeat, bmi2); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +/** HUF_buildCTable() : + * @return : maxNbBits + * Note : count is used before tree is written, so they can safely overlap + */ +size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) +{ + HUF_buildCTable_wksp_tables workspace; + return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace)); +} + +size_t HUF_compress1X (void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned huffLog) +{ + unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; + return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); +} + size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog) @@ -796,3 +934,4 @@ size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSi { return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT); } +#endif diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3f963b1cfff..b7ee2980a77 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,8 +11,7 @@ /*-************************************* * Dependencies ***************************************/ -#include <limits.h> /* INT_MAX */ -#include <string.h> /* memset */ +#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */ #include "../common/cpu.h" #include "../common/mem.h" #include "hist.h" /* HIST_countFast_wksp */ @@ -30,6 +29,19 @@ #include "zstd_ldm.h" #include "zstd_compress_superblock.h" +/* *************************************************************** +* Tuning parameters +*****************************************************************/ +/*! + * COMPRESS_HEAPMODE : + * Select how default decompression function ZSTD_compress() allocates its context, + * on stack (0, default), or into heap (1). + * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected. + */ +#ifndef ZSTD_COMPRESS_HEAPMODE +# define ZSTD_COMPRESS_HEAPMODE 0 +#endif + /*-************************************* * Helper functions @@ -52,6 +64,7 @@ size_t ZSTD_compressBound(size_t srcSize) { struct ZSTD_CDict_s { const void* dictContent; size_t dictContentSize; + ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */ U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ ZSTD_cwksp workspace; ZSTD_matchState_t matchState; @@ -59,6 +72,10 @@ struct ZSTD_CDict_s { ZSTD_customMem customMem; U32 dictID; int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */ + ZSTD_useRowMatchFinderMode_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use + * row-based matchfinder. Unless the cdict is reloaded, we will use + * the same greedy/lazy matchfinder at compression time. + */ }; /* typedef'd to ZSTD_CDict within "zstd.h" */ ZSTD_CCtx* ZSTD_createCCtx(void) @@ -69,7 +86,7 @@ ZSTD_CCtx* ZSTD_createCCtx(void) static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager) { assert(cctx != NULL); - memset(cctx, 0, sizeof(*cctx)); + ZSTD_memset(cctx, 0, sizeof(*cctx)); cctx->customMem = memManager; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); { size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters); @@ -82,8 +99,8 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) { ZSTD_STATIC_ASSERT(zcss_init==0); ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1)); - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem); + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem); if (!cctx) return NULL; ZSTD_initCCtx(cctx, customMem); return cctx; @@ -96,20 +113,20 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) ZSTD_CCtx* cctx; if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */ if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */ - ZSTD_cwksp_init(&ws, workspace, workspaceSize); + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc); cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx)); if (cctx == NULL) return NULL; - memset(cctx, 0, sizeof(ZSTD_CCtx)); + ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx)); ZSTD_cwksp_move(&cctx->workspace, &ws); cctx->staticSize = workspaceSize; /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ - if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; + if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, HUF_WORKSPACE_SIZE); + cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE); cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; } @@ -119,10 +136,10 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) */ static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx) { - ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem); + ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem); ZSTD_freeCDict(cctx->localDict.cdict); - memset(&cctx->localDict, 0, sizeof(cctx->localDict)); - memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); + ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict)); + ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); cctx->cdict = NULL; } @@ -153,7 +170,7 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx); ZSTD_freeCCtxContent(cctx); if (!cctxInWorkspace) { - ZSTD_free(cctx, cctx->customMem); + ZSTD_customFree(cctx, cctx->customMem); } } return 0; @@ -189,15 +206,90 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) /* private API call, for dictBuilder only */ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } +/* Returns true if the strategy supports using a row based matchfinder */ +static int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) { + return (strategy >= ZSTD_greedy && strategy <= ZSTD_lazy2); +} + +/* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder + * for this compression. + */ +static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_useRowMatchFinderMode_e mode) { + assert(mode != ZSTD_urm_auto); + return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_urm_enableRowMatchFinder); +} + +/* Returns row matchfinder usage enum given an initial mode and cParams */ +static ZSTD_useRowMatchFinderMode_e ZSTD_resolveRowMatchFinderMode(ZSTD_useRowMatchFinderMode_e mode, + const ZSTD_compressionParameters* const cParams) { +#if !defined(ZSTD_NO_INTRINSICS) && (defined(__SSE2__) || defined(__ARM_NEON)) + int const kHasSIMD128 = 1; +#else + int const kHasSIMD128 = 0; +#endif + if (mode != ZSTD_urm_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */ + mode = ZSTD_urm_disableRowMatchFinder; + if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode; + if (kHasSIMD128) { + if (cParams->windowLog > 14) mode = ZSTD_urm_enableRowMatchFinder; + } else { + if (cParams->windowLog > 17) mode = ZSTD_urm_enableRowMatchFinder; + } + return mode; +} + +/* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */ +static int ZSTD_allocateChainTable(const ZSTD_strategy strategy, + const ZSTD_useRowMatchFinderMode_e useRowMatchFinder, + const U32 forDDSDict) { + assert(useRowMatchFinder != ZSTD_urm_auto); + /* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate. + * We do not allocate a chaintable if we are using ZSTD_fast, or are using the row-based matchfinder. + */ + return forDDSDict || ((strategy != ZSTD_fast) && !ZSTD_rowMatchFinderUsed(strategy, useRowMatchFinder)); +} + +/* Returns 1 if compression parameters are such that we should + * enable long distance matching (wlog >= 27, strategy >= btopt). + * Returns 0 otherwise. + */ +static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) { + return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27; +} + +/* Returns 1 if compression parameters are such that we should + * enable blockSplitter (wlog >= 17, strategy >= btopt). + * Returns 0 otherwise. + */ +static U32 ZSTD_CParams_useBlockSplitter(const ZSTD_compressionParameters* const cParams) { + return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17; +} + static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( ZSTD_compressionParameters cParams) { ZSTD_CCtx_params cctxParams; - memset(&cctxParams, 0, sizeof(cctxParams)); + /* should not matter, as all cParams are presumed properly defined */ + ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT); cctxParams.cParams = cParams; - cctxParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ + + /* Adjust advanced params according to cParams */ + if (ZSTD_CParams_shouldEnableLdm(&cParams)) { + DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params"); + cctxParams.ldmParams.enableLdm = 1; + /* LDM is enabled by default for optimal parser and window size >= 128MB */ + ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams); + assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog); + assert(cctxParams.ldmParams.hashRateLog < 32); + } + + if (ZSTD_CParams_useBlockSplitter(&cParams)) { + DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including block splitting into cctx params"); + cctxParams.splitBlocks = 1; + } + + cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); assert(!ZSTD_checkCParams(cParams)); - cctxParams.fParams.contentSizeFlag = 1; return cctxParams; } @@ -205,13 +297,12 @@ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced( ZSTD_customMem customMem) { ZSTD_CCtx_params* params; - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - params = (ZSTD_CCtx_params*)ZSTD_calloc( + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + params = (ZSTD_CCtx_params*)ZSTD_customCalloc( sizeof(ZSTD_CCtx_params), customMem); if (!params) { return NULL; } + ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT); params->customMem = customMem; - params->compressionLevel = ZSTD_CLEVEL_DEFAULT; - params->fParams.contentSizeFlag = 1; return params; } @@ -223,7 +314,7 @@ ZSTD_CCtx_params* ZSTD_createCCtxParams(void) size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params) { if (params == NULL) { return 0; } - ZSTD_free(params, params->customMem); + ZSTD_customFree(params, params->customMem); return 0; } @@ -234,35 +325,54 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params) size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - memset(cctxParams, 0, sizeof(*cctxParams)); + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); cctxParams->compressionLevel = compressionLevel; cctxParams->fParams.contentSizeFlag = 1; return 0; } +#define ZSTD_NO_CLEVEL 0 + +/** + * Initializes the cctxParams from params and compressionLevel. + * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL. + */ +static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_parameters const* params, int compressionLevel) +{ + assert(!ZSTD_checkCParams(params->cParams)); + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); + cctxParams->cParams = params->cParams; + cctxParams->fParams = params->fParams; + /* Should not matter, as all cParams are presumed properly defined. + * But, set it for tracing anyway. + */ + cctxParams->compressionLevel = compressionLevel; + cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, ¶ms->cParams); + DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d", cctxParams->useRowMatchFinder); +} + size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) { RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); - memset(cctxParams, 0, sizeof(*cctxParams)); - assert(!ZSTD_checkCParams(params.cParams)); - cctxParams->cParams = params.cParams; - cctxParams->fParams = params.fParams; - cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ + ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL); return 0; } -/* ZSTD_assignParamsToCCtxParams() : - * params is presumed valid at this stage */ -static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams( - const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) +/** + * Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone. + * @param param Validated zstd parameters. + */ +static void ZSTD_CCtxParams_setZstdParams( + ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) { - ZSTD_CCtx_params ret = *cctxParams; assert(!ZSTD_checkCParams(params->cParams)); - ret.cParams = params->cParams; - ret.fParams = params->fParams; - ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ - return ret; + cctxParams->cParams = params->cParams; + cctxParams->fParams = params->fParams; + /* Should not matter, as all cParams are presumed properly defined. + * But, set it for tracing anyway. + */ + cctxParams->compressionLevel = ZSTD_NO_CLEVEL; } ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) @@ -354,6 +464,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) #endif return bounds; + case ZSTD_c_enableDedicatedDictSearch: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + case ZSTD_c_enableLongDistanceMatching: bounds.lowerBound = 0; bounds.upperBound = 1; @@ -397,7 +512,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) return bounds; case ZSTD_c_forceAttachDict: - ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy); + ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad); bounds.lowerBound = ZSTD_dictDefaultAttach; bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */ return bounds; @@ -418,6 +533,37 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = ZSTD_SRCSIZEHINT_MAX; return bounds; + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + bounds.lowerBound = (int)ZSTD_bm_buffered; + bounds.upperBound = (int)ZSTD_bm_stable; + return bounds; + + case ZSTD_c_blockDelimiters: + bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters; + bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters; + return bounds; + + case ZSTD_c_validateSequences: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_splitBlocks: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_useRowMatchFinder: + bounds.lowerBound = (int)ZSTD_urm_auto; + bounds.upperBound = (int)ZSTD_urm_enableRowMatchFinder; + return bounds; + + case ZSTD_c_deterministicRefPrefix: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + default: bounds.error = ERROR(parameter_unsupported); return bounds; @@ -465,6 +611,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_jobSize: case ZSTD_c_overlapLog: case ZSTD_c_rsyncable: + case ZSTD_c_enableDedicatedDictSearch: case ZSTD_c_enableLongDistanceMatching: case ZSTD_c_ldmHashLog: case ZSTD_c_ldmMinMatch: @@ -474,6 +621,13 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_literalCompressionMode: case ZSTD_c_targetCBlockSize: case ZSTD_c_srcSizeHint: + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + case ZSTD_c_blockDelimiters: + case ZSTD_c_validateSequences: + case ZSTD_c_splitBlocks: + case ZSTD_c_useRowMatchFinder: + case ZSTD_c_deterministicRefPrefix: default: return 0; } @@ -515,12 +669,20 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_jobSize: case ZSTD_c_overlapLog: case ZSTD_c_rsyncable: + case ZSTD_c_enableDedicatedDictSearch: case ZSTD_c_enableLongDistanceMatching: case ZSTD_c_ldmHashLog: case ZSTD_c_ldmMinMatch: case ZSTD_c_ldmBucketSizeLog: case ZSTD_c_targetCBlockSize: case ZSTD_c_srcSizeHint: + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + case ZSTD_c_blockDelimiters: + case ZSTD_c_validateSequences: + case ZSTD_c_splitBlocks: + case ZSTD_c_useRowMatchFinder: + case ZSTD_c_deterministicRefPrefix: break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); @@ -541,9 +703,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_compressionLevel : { FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); - if (value) { /* 0 : does not change current level */ + if (value == 0) + CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ + else CCtxParams->compressionLevel = value; - } if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel; return 0; /* return type (size_t) cannot represent negative values */ } @@ -667,6 +830,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, return CCtxParams->rsyncable; #endif + case ZSTD_c_enableDedicatedDictSearch : + CCtxParams->enableDedicatedDictSearch = (value!=0); + return CCtxParams->enableDedicatedDictSearch; + case ZSTD_c_enableLongDistanceMatching : CCtxParams->ldmParams.enableLdm = (value!=0); return CCtxParams->ldmParams.enableLdm; @@ -707,17 +874,52 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->srcSizeHint = value; return CCtxParams->srcSizeHint; + case ZSTD_c_stableInBuffer: + BOUNDCHECK(ZSTD_c_stableInBuffer, value); + CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value; + return CCtxParams->inBufferMode; + + case ZSTD_c_stableOutBuffer: + BOUNDCHECK(ZSTD_c_stableOutBuffer, value); + CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value; + return CCtxParams->outBufferMode; + + case ZSTD_c_blockDelimiters: + BOUNDCHECK(ZSTD_c_blockDelimiters, value); + CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value; + return CCtxParams->blockDelimiters; + + case ZSTD_c_validateSequences: + BOUNDCHECK(ZSTD_c_validateSequences, value); + CCtxParams->validateSequences = value; + return CCtxParams->validateSequences; + + case ZSTD_c_splitBlocks: + BOUNDCHECK(ZSTD_c_splitBlocks, value); + CCtxParams->splitBlocks = value; + return CCtxParams->splitBlocks; + + case ZSTD_c_useRowMatchFinder: + BOUNDCHECK(ZSTD_c_useRowMatchFinder, value); + CCtxParams->useRowMatchFinder = (ZSTD_useRowMatchFinderMode_e)value; + return CCtxParams->useRowMatchFinder; + + case ZSTD_c_deterministicRefPrefix: + BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value); + CCtxParams->deterministicRefPrefix = !!value; + return CCtxParams->deterministicRefPrefix; + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } } -size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value) +size_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value) { return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value); } size_t ZSTD_CCtxParams_getParameter( - ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value) + ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value) { switch(param) { @@ -794,6 +996,9 @@ size_t ZSTD_CCtxParams_getParameter( *value = CCtxParams->rsyncable; break; #endif + case ZSTD_c_enableDedicatedDictSearch : + *value = CCtxParams->enableDedicatedDictSearch; + break; case ZSTD_c_enableLongDistanceMatching : *value = CCtxParams->ldmParams.enableLdm; break; @@ -815,6 +1020,27 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_srcSizeHint : *value = (int)CCtxParams->srcSizeHint; break; + case ZSTD_c_stableInBuffer : + *value = (int)CCtxParams->inBufferMode; + break; + case ZSTD_c_stableOutBuffer : + *value = (int)CCtxParams->outBufferMode; + break; + case ZSTD_c_blockDelimiters : + *value = (int)CCtxParams->blockDelimiters; + break; + case ZSTD_c_validateSequences : + *value = (int)CCtxParams->validateSequences; + break; + case ZSTD_c_splitBlocks : + *value = (int)CCtxParams->splitBlocks; + break; + case ZSTD_c_useRowMatchFinder : + *value = (int)CCtxParams->useRowMatchFinder; + break; + case ZSTD_c_deterministicRefPrefix: + *value = (int)CCtxParams->deterministicRefPrefix; + break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } return 0; @@ -850,6 +1076,14 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo return 0; } +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( + int const compressionLevel, + size_t const dictSize); +static int ZSTD_dedicatedDictSearch_isSupported( + const ZSTD_compressionParameters* cParams); +static void ZSTD_dedicatedDictSearch_revertCParams( + ZSTD_compressionParameters* cParams); + /** * Initializes the local dict using the requested parameters. * NOTE: This does not use the pledged src size, because it may be used for more @@ -858,8 +1092,6 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) { ZSTD_localDict* const dl = &cctx->localDict; - ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize); if (dl->dict == NULL) { /* No local dictionary. */ assert(dl->dictBuffer == NULL); @@ -876,12 +1108,12 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) assert(cctx->cdict == NULL); assert(cctx->prefixDict.dict == NULL); - dl->cdict = ZSTD_createCDict_advanced( + dl->cdict = ZSTD_createCDict_advanced2( dl->dict, dl->dictSize, ZSTD_dlm_byRef, dl->dictContentType, - cParams, + &cctx->requestedParams, cctx->customMem); RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed"); cctx->cdict = dl->cdict; @@ -894,8 +1126,6 @@ size_t ZSTD_CCtx_loadDictionary_advanced( { RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, "Can't load a dictionary when ctx is not in init stage."); - RETURN_ERROR_IF(cctx->staticSize, memory_allocation, - "no malloc for static CCtx"); DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); ZSTD_clearAllDicts(cctx); /* in case one already exists */ if (dict == NULL || dictSize == 0) /* no dictionary mode */ @@ -903,9 +1133,12 @@ size_t ZSTD_CCtx_loadDictionary_advanced( if (dictLoadMethod == ZSTD_dlm_byRef) { cctx->localDict.dict = dict; } else { - void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem); + void* dictBuffer; + RETURN_ERROR_IF(cctx->staticSize, memory_allocation, + "no malloc for static CCtx"); + dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem); RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!"); - memcpy(dictBuffer, dict, dictSize); + ZSTD_memcpy(dictBuffer, dict, dictSize); cctx->localDict.dictBuffer = dictBuffer; cctx->localDict.dict = dictBuffer; } @@ -938,6 +1171,14 @@ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) return 0; } +size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool) +{ + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a pool when ctx not in init stage."); + cctx->pool = pool; + return 0; +} + size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize) { return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent); @@ -1022,23 +1263,83 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) return hashLog - btScale; } +/** ZSTD_dictAndWindowLog() : + * Returns an adjusted window log that is large enough to fit the source and the dictionary. + * The zstd format says that the entire dictionary is valid if one byte of the dictionary + * is within the window. So the hashLog and chainLog should be large enough to reference both + * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing + * the hashLog and windowLog. + * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN. + */ +static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize) +{ + const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX; + /* No dictionary ==> No change */ + if (dictSize == 0) { + return windowLog; + } + assert(windowLog <= ZSTD_WINDOWLOG_MAX); + assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ + { + U64 const windowSize = 1ULL << windowLog; + U64 const dictAndWindowSize = dictSize + windowSize; + /* If the window size is already large enough to fit both the source and the dictionary + * then just use the window size. Otherwise adjust so that it fits the dictionary and + * the window. + */ + if (windowSize >= dictSize + srcSize) { + return windowLog; /* Window size large enough already */ + } else if (dictAndWindowSize >= maxWindowSize) { + return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */ + } else { + return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1; + } + } +} + /** ZSTD_adjustCParams_internal() : * optimize `cPar` for a specified input (`srcSize` and `dictSize`). * mostly downsize to reduce memory consumption and initialization latency. * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known. + * `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`. * note : `srcSize==0` means 0! * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ static ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, - size_t dictSize) + size_t dictSize, + ZSTD_cParamMode_e mode) { - static const U64 minSrcSize = 513; /* (1<<9) + 1 */ - static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); + const U64 minSrcSize = 513; /* (1<<9) + 1 */ + const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); assert(ZSTD_checkCParams(cPar)==0); - if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN) - srcSize = minSrcSize; + switch (mode) { + case ZSTD_cpm_unknown: + case ZSTD_cpm_noAttachDict: + /* If we don't know the source size, don't make any + * assumptions about it. We will already have selected + * smaller parameters if a dictionary is in use. + */ + break; + case ZSTD_cpm_createCDict: + /* Assume a small source size when creating a dictionary + * with an unkown source size. + */ + if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN) + srcSize = minSrcSize; + break; + case ZSTD_cpm_attachDict: + /* Dictionary has its own dedicated parameters which have + * already been selected. We are selecting parameters + * for only the source. + */ + dictSize = 0; + break; + default: + assert(0); + break; + } /* resize windowLog if input is small enough, to use less memory */ if ( (srcSize < maxWindowResize) @@ -1049,10 +1350,12 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, ZSTD_highbit32(tSize-1) + 1; if (cPar.windowLog > srcLog) cPar.windowLog = srcLog; } - if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1; - { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); - if (cycleLog > cPar.windowLog) - cPar.chainLog -= (cycleLog - cPar.windowLog); + if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) { + U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize); + U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); + if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1; + if (cycleLog > dictAndWindowLog) + cPar.chainLog -= (cycleLog - dictAndWindowLog); } if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) @@ -1068,38 +1371,50 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, { cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); + return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown); } -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); + +static void ZSTD_overrideCParams( + ZSTD_compressionParameters* cParams, + const ZSTD_compressionParameters* overrides) +{ + if (overrides->windowLog) cParams->windowLog = overrides->windowLog; + if (overrides->hashLog) cParams->hashLog = overrides->hashLog; + if (overrides->chainLog) cParams->chainLog = overrides->chainLog; + if (overrides->searchLog) cParams->searchLog = overrides->searchLog; + if (overrides->minMatch) cParams->minMatch = overrides->minMatch; + if (overrides->targetLength) cParams->targetLength = overrides->targetLength; + if (overrides->strategy) cParams->strategy = overrides->strategy; +} ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize) + const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { ZSTD_compressionParameters cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { srcSizeHint = CCtxParams->srcSizeHint; } - cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize); + cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; - if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog; - if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog; - if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog; - if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog; - if (CCtxParams->cParams.minMatch) cParams.minMatch = CCtxParams->cParams.minMatch; - if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength; - if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy; + ZSTD_overrideCParams(&cParams, &CCtxParams->cParams); assert(!ZSTD_checkCParams(cParams)); /* srcSizeHint == 0 means 0 */ - return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize); + return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode); } static size_t ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, + const ZSTD_useRowMatchFinderMode_e useRowMatchFinder, + const U32 enableDedicatedDictSearch, const U32 forCCtx) { - size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); + /* chain table size should be 0 for fast or row-hash strategies */ + size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, enableDedicatedDictSearch && !forCCtx) + ? ((size_t)1 << cParams->chainLog) + : 0; size_t const hSize = ((size_t)1) << cParams->hashLog; U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0; @@ -1109,71 +1424,117 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, + hSize * sizeof(U32) + h3Size * sizeof(U32); size_t const optPotentialSpace = - ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((1<<Litbits) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t)) - + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t)); + ZSTD_cwksp_aligned_alloc_size((MaxML+1) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((1<<Litbits) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t)) + + ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t)); + size_t const lazyAdditionalSpace = ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder) + ? ZSTD_cwksp_aligned_alloc_size(hSize*sizeof(U16)) + : 0; size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt)) ? optPotentialSpace : 0; + size_t const slackSpace = ZSTD_cwksp_slack_space_required(); + + /* tables are guaranteed to be sized in multiples of 64 bytes (or 16 uint32_t) */ + ZSTD_STATIC_ASSERT(ZSTD_HASHLOG_MIN >= 4 && ZSTD_WINDOWLOG_MIN >= 4 && ZSTD_CHAINLOG_MIN >= 4); + assert(useRowMatchFinder != ZSTD_urm_auto); + DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u", (U32)chainSize, (U32)hSize, (U32)h3Size); - return tableSpace + optSpace; + return tableSpace + optSpace + slackSpace + lazyAdditionalSpace; +} + +static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( + const ZSTD_compressionParameters* cParams, + const ldmParams_t* ldmParams, + const int isStatic, + const ZSTD_useRowMatchFinderMode_e useRowMatchFinder, + const size_t buffInSize, + const size_t buffOutSize, + const U64 pledgedSrcSize) +{ + size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize)); + size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); + U32 const divider = (cParams->minMatch==3) ? 3 : 4; + size_t const maxNbSeq = blockSize / divider; + size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) + + ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef)) + + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); + size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE); + size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); + size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); + + size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams); + size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize); + size_t const ldmSeqSpace = ldmParams->enableLdm ? + ZSTD_cwksp_aligned_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; + + + size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + + ZSTD_cwksp_alloc_size(buffOutSize); + + size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; + + size_t const neededSpace = + cctxSpace + + entropySpace + + blockStateSpace + + ldmSpace + + ldmSeqSpace + + matchStateSize + + tokenSpace + + bufferSpace; + + DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); + return neededSpace; } size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) { - RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - U32 const divider = (cParams.minMatch==3) ? 3 : 4; - size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) - + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE); - size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1); + ZSTD_compressionParameters const cParams = + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, + &cParams); - size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams); - size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq)); - - /* estimateCCtxSize is for one-shot compression. So no buffers should - * be needed. However, we still allocate two 0-sized buffers, which can - * take space under ASAN. */ - size_t const bufferSpace = ZSTD_cwksp_alloc_size(0) - + ZSTD_cwksp_alloc_size(0); - - size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)); - - size_t const neededSpace = - cctxSpace + - entropySpace + - blockStateSpace + - ldmSpace + - ldmSeqSpace + - matchStateSize + - tokenSpace + - bufferSpace; - - DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); - return neededSpace; - } + RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); + /* estimateCCtxSize is for one-shot compression. So no buffers should + * be needed. However, we still allocate two 0-sized buffers, which can + * take space under ASAN. */ + return ZSTD_estimateCCtxSize_usingCCtxParams_internal( + &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN); } size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) { - ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams); - return ZSTD_estimateCCtxSize_usingCCtxParams(¶ms); + ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); + if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { + /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */ + size_t noRowCCtxSize; + size_t rowCCtxSize; + initialParams.useRowMatchFinder = ZSTD_urm_disableRowMatchFinder; + noRowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams); + initialParams.useRowMatchFinder = ZSTD_urm_enableRowMatchFinder; + rowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams); + return MAX(noRowCCtxSize, rowCCtxSize); + } else { + return ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams); + } } static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); - return ZSTD_estimateCCtxSize_usingCParams(cParams); + int tier = 0; + size_t largestSize = 0; + static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN}; + for (; tier < 4; ++tier) { + /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */ + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); + largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize); + } + return largestSize; } size_t ZSTD_estimateCCtxSize(int compressionLevel) @@ -1181,6 +1542,7 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel) int level; size_t memBudget = 0; for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) { + /* Ensure monotonically increasing memory usage as compression level increases */ size_t const newMB = ZSTD_estimateCCtxSize_internal(level); if (newMB > memBudget) memBudget = newMB; } @@ -1191,27 +1553,42 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) { RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize; - size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; - size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize) - + ZSTD_cwksp_alloc_size(outBuffSize); - - return CCtxSize + streamingSize; + size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) + ? ((size_t)1 << cParams.windowLog) + blockSize + : 0; + size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered) + ? ZSTD_compressBound(blockSize) + 1 + : 0; + ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, ¶ms->cParams); + + return ZSTD_estimateCCtxSize_usingCCtxParams_internal( + &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize, + ZSTD_CONTENTSIZE_UNKNOWN); } } size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) { - ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams); - return ZSTD_estimateCStreamSize_usingCCtxParams(¶ms); + ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); + if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { + /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */ + size_t noRowCCtxSize; + size_t rowCCtxSize; + initialParams.useRowMatchFinder = ZSTD_urm_disableRowMatchFinder; + noRowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams); + initialParams.useRowMatchFinder = ZSTD_urm_enableRowMatchFinder; + rowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams); + return MAX(noRowCCtxSize, rowCCtxSize); + } else { + return ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams); + } } static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); return ZSTD_estimateCStreamSize_usingCParams(cParams); } @@ -1304,16 +1681,6 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) ms->dictMatchState = NULL; } -/** - * Indicates whether this compression proceeds directly from user-provided - * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or - * whether the context needs to buffer the input/output (ZSTDb_buffered). - */ -typedef enum { - ZSTDb_not_buffered, - ZSTDb_buffered -} ZSTD_buffered_policy_e; - /** * Controls, for this matchState reset, whether the tables need to be cleared / * prepared for the coming compression (ZSTDcrp_makeClean), or whether the @@ -1341,20 +1708,27 @@ typedef enum { ZSTD_resetTarget_CCtx } ZSTD_resetTarget_e; + static size_t ZSTD_reset_matchState(ZSTD_matchState_t* ms, ZSTD_cwksp* ws, const ZSTD_compressionParameters* cParams, + const ZSTD_useRowMatchFinderMode_e useRowMatchFinder, const ZSTD_compResetPolicy_e crp, const ZSTD_indexResetPolicy_e forceResetIndex, const ZSTD_resetTarget_e forWho) { - size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); + /* disable chain table allocation for fast or row-based strategies */ + size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, + ms->dedicatedDictSearch && (forWho == ZSTD_resetTarget_CDict)) + ? ((size_t)1 << cParams->chainLog) + : 0; size_t const hSize = ((size_t)1) << cParams->hashLog; U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0; DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset); + assert(useRowMatchFinder != ZSTD_urm_auto); if (forceResetIndex == ZSTDirp_reset) { ZSTD_window_init(&ms->window); ZSTD_cwksp_mark_tables_dirty(ws); @@ -1393,11 +1767,23 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t)); } + if (ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)) { + { /* Row match finder needs an additional table of hashes ("tags") */ + size_t const tagTableSize = hSize*sizeof(U16); + ms->tagTable = (U16*)ZSTD_cwksp_reserve_aligned(ws, tagTableSize); + if (ms->tagTable) ZSTD_memset(ms->tagTable, 0, tagTableSize); + } + { /* Switch to 32-entry rows if searchLog is 5 (or more) */ + U32 const rowLog = cParams->searchLog < 5 ? 4 : 5; + assert(cParams->hashLog > rowLog); + ms->rowHashLog = cParams->hashLog - rowLog; + } + } + ms->cParams = *cParams; RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation, "failed a workspace allocation in ZSTD_reset_matchState"); - return 0; } @@ -1414,75 +1800,85 @@ static int ZSTD_indexTooCloseToMax(ZSTD_window_t w) return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN); } +/** ZSTD_dictTooBig(): + * When dictionaries are larger than ZSTD_CHUNKSIZE_MAX they can't be loaded in + * one go generically. So we ensure that in that case we reset the tables to zero, + * so that we can load as much of the dictionary as possible. + */ +static int ZSTD_dictTooBig(size_t const loadedDictSize) +{ + return loadedDictSize > ZSTD_CHUNKSIZE_MAX; +} + /*! ZSTD_resetCCtx_internal() : - note : `params` are assumed fully validated at this stage */ + * @param loadedDictSize The size of the dictionary to be loaded + * into the context, if any. If no dictionary is used, or the + * dictionary is being attached / copied, then pass 0. + * note : `params` are assumed fully validated at this stage. + */ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, - ZSTD_CCtx_params params, + ZSTD_CCtx_params const* params, U64 const pledgedSrcSize, + size_t const loadedDictSize, ZSTD_compResetPolicy_e const crp, ZSTD_buffered_policy_e const zbuff) { ZSTD_cwksp* const ws = &zc->workspace; - DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u", - (U32)pledgedSrcSize, params.cParams.windowLog); - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d", + (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder); + assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); zc->isFirstBlock = 1; - if (params.ldmParams.enableLdm) { + /* Set applied params early so we can modify them for LDM, + * and point params at the applied params. + */ + zc->appliedParams = *params; + params = &zc->appliedParams; + + assert(params->useRowMatchFinder != ZSTD_urm_auto); + if (params->ldmParams.enableLdm) { /* Adjust long distance matching parameters */ - ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); - assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); - assert(params.ldmParams.hashRateLog < 32); - zc->ldmState.hashPower = ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength); + ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, ¶ms->cParams); + assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog); + assert(params->ldmParams.hashRateLog < 32); } - { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize)); + { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize)); size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); - U32 const divider = (params.cParams.minMatch==3) ? 3 : 4; + U32 const divider = (params->cParams.minMatch==3) ? 3 : 4; size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) - + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0; - size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0; - size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms.cParams, /* forCCtx */ 1); - size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize); - - ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset; - - if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) { - needsIndexReset = ZSTDirp_reset; - } + size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered) + ? ZSTD_compressBound(blockSize) + 1 + : 0; + size_t const buffInSize = (zbuff == ZSTDb_buffered && params->inBufferMode == ZSTD_bm_buffered) + ? windowSize + blockSize + : 0; + size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize); + + int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window); + int const dictTooBig = ZSTD_dictTooBig(loadedDictSize); + ZSTD_indexResetPolicy_e needsIndexReset = + (indexTooClose || dictTooBig || !zc->initialized) ? ZSTDirp_reset : ZSTDirp_continue; - if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0); + size_t const neededSpace = + ZSTD_estimateCCtxSize_usingCCtxParams_internal( + ¶ms->cParams, ¶ms->ldmParams, zc->staticSize != 0, params->useRowMatchFinder, + buffInSize, buffOutSize, pledgedSrcSize); + int resizeWorkspace; - /* Check if workspace is large enough, alloc a new one if needed */ - { size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; - size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE); - size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + ZSTD_cwksp_alloc_size(buffOutSize); - size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams); - size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)); - - size_t const neededSpace = - cctxSpace + - entropySpace + - blockStateSpace + - ldmSpace + - ldmSeqSpace + - matchStateSize + - tokenSpace + - bufferSpace; + FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!"); + if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0); + + { /* Check if workspace is large enough, alloc a new one if needed */ int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace; int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace); - - DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers", - neededSpace>>10, matchStateSize>>10, bufferSpace>>10); + resizeWorkspace = workspaceTooSmall || workspaceWasteful; + DEBUGLOG(4, "Need %zu B workspace", neededSpace); DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize); - if (workspaceTooSmall || workspaceWasteful) { + if (resizeWorkspace) { DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB", ZSTD_cwksp_sizeof(ws) >> 10, neededSpace >> 10); @@ -1503,15 +1899,14 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, HUF_WORKSPACE_SIZE); + zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace"); } } ZSTD_cwksp_clear(ws); /* init params */ - zc->appliedParams = params; - zc->blockState.matchState.cParams = params.cParams; + zc->blockState.matchState.cParams = params->cParams; zc->pledgedSrcSizePlusOne = pledgedSrcSize+1; zc->consumedSrcSize = 0; zc->producedCSize = 0; @@ -1524,6 +1919,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, XXH64_reset(&zc->xxhState, 0); zc->stage = ZSTDcs_init; zc->dictID = 0; + zc->dictContentSize = 0; ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock); @@ -1534,19 +1930,20 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, zc->seqStore.maxNbLit = blockSize; /* buffers */ + zc->bufferedPolicy = zbuff; zc->inBuffSize = buffInSize; zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize); zc->outBuffSize = buffOutSize; zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize); /* ldm bucketOffsets table */ - if (params.ldmParams.enableLdm) { + if (params->ldmParams.enableLdm) { /* TODO: avoid memset? */ - size_t const ldmBucketSize = - ((size_t)1) << (params.ldmParams.hashLog - - params.ldmParams.bucketSizeLog); - zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize); - memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize); + size_t const numBuckets = + ((size_t)1) << (params->ldmParams.hashLog - + params->ldmParams.bucketSizeLog); + zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets); + ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets); } /* sequences storage */ @@ -1560,26 +1957,28 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, FORWARD_IF_ERROR(ZSTD_reset_matchState( &zc->blockState.matchState, ws, - ¶ms.cParams, + ¶ms->cParams, + params->useRowMatchFinder, crp, needsIndexReset, ZSTD_resetTarget_CCtx), ""); /* ldm hash table */ - if (params.ldmParams.enableLdm) { + if (params->ldmParams.enableLdm) { /* TODO: avoid memset? */ - size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog; + size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog; zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t)); - memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); + ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); zc->maxNbLdmSequences = maxNbLdmSeq; ZSTD_window_init(&zc->ldmState.window); - ZSTD_window_clear(&zc->ldmState.window); zc->ldmState.loadedDictEnd = 0; } + assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace, resizeWorkspace)); DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws)); + zc->initialized = 1; return 0; @@ -1618,12 +2017,14 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict, U64 pledgedSrcSize) { size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy]; - return ( pledgedSrcSize <= cutoff - || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || params->attachDictPref == ZSTD_dictForceAttach ) - && params->attachDictPref != ZSTD_dictForceCopy - && !params->forceWindow; /* dictMatchState isn't correctly - * handled in _enforceMaxDist */ + int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch; + return dedicatedDictSearch + || ( ( pledgedSrcSize <= cutoff + || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN + || params->attachDictPref == ZSTD_dictForceAttach ) + && params->attachDictPref != ZSTD_dictForceCopy + && !params->forceWindow ); /* dictMatchState isn't correctly + * handled in _enforceMaxDist */ } static size_t @@ -1633,17 +2034,28 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams; + DEBUGLOG(4, "ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu", + (unsigned long long)pledgedSrcSize); + { + ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams; unsigned const windowLog = params.cParams.windowLog; assert(windowLog != 0); /* Resize working context table params for input only, since the dict * has its own tables. */ - /* pledgeSrcSize == 0 means 0! */ - params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0); + /* pledgedSrcSize == 0 means 0! */ + + if (cdict->matchState.dedicatedDictSearch) { + ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams); + } + + params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize, + cdict->dictContentSize, ZSTD_cpm_attachDict); params.cParams.windowLog = windowLog; - FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, + params.useRowMatchFinder = cdict->useRowMatchFinder; /* cdict overrides */ + FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, + /* loadedDictSize */ 0, ZSTDcrp_makeClean, zbuff), ""); - assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); + assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy); } { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc @@ -1668,9 +2080,10 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, } } cctx->dictID = cdict->dictID; + cctx->dictContentSize = cdict->dictContentSize; /* copy block state */ - memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); + ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); return 0; } @@ -1683,14 +2096,18 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, { const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams; - DEBUGLOG(4, "copying dictionary into context"); + assert(!cdict->matchState.dedicatedDictSearch); + DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu", + (unsigned long long)pledgedSrcSize); { unsigned const windowLog = params.cParams.windowLog; assert(windowLog != 0); /* Copy only compression parameters related to tables. */ params.cParams = *cdict_cParams; params.cParams.windowLog = windowLog; - FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, + params.useRowMatchFinder = cdict->useRowMatchFinder; + FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, + /* loadedDictSize */ 0, ZSTDcrp_leaveDirty, zbuff), ""); assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog); @@ -1698,24 +2115,37 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, } ZSTD_cwksp_mark_tables_dirty(&cctx->workspace); + assert(params.useRowMatchFinder != ZSTD_urm_auto); /* copy tables */ - { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog); + { size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */) + ? ((size_t)1 << cdict_cParams->chainLog) + : 0; size_t const hSize = (size_t)1 << cdict_cParams->hashLog; - memcpy(cctx->blockState.matchState.hashTable, + ZSTD_memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, hSize * sizeof(U32)); - memcpy(cctx->blockState.matchState.chainTable, + /* Do not copy cdict's chainTable if cctx has parameters such that it would not use chainTable */ + if (ZSTD_allocateChainTable(cctx->appliedParams.cParams.strategy, cctx->appliedParams.useRowMatchFinder, 0 /* forDDSDict */)) { + ZSTD_memcpy(cctx->blockState.matchState.chainTable, cdict->matchState.chainTable, chainSize * sizeof(U32)); + } + /* copy tag table */ + if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) { + size_t const tagTableSize = hSize*sizeof(U16); + ZSTD_memcpy(cctx->blockState.matchState.tagTable, + cdict->matchState.tagTable, + tagTableSize); + } } /* Zero the hashTable3, since the cdict never fills it */ { int const h3log = cctx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; assert(cdict->matchState.hashLog3 == 0); - memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); + ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); } ZSTD_cwksp_mark_tables_clean(&cctx->workspace); @@ -1729,9 +2159,10 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, } cctx->dictID = cdict->dictID; + cctx->dictContentSize = cdict->dictContentSize; /* copy block state */ - memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); + ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); return 0; } @@ -1771,16 +2202,18 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - DEBUGLOG(5, "ZSTD_copyCCtx_internal"); RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, "Can't copy a ctx that's not in init stage."); - - memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); + DEBUGLOG(5, "ZSTD_copyCCtx_internal"); + ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); { ZSTD_CCtx_params params = dstCCtx->requestedParams; /* Copy only compression parameters related to tables. */ params.cParams = srcCCtx->appliedParams.cParams; + assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_urm_auto); + params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder; params.fParams = fParams; - ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize, + ZSTD_resetCCtx_internal(dstCCtx, ¶ms, pledgedSrcSize, + /* loadedDictSize */ 0, ZSTDcrp_leaveDirty, zbuff); assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog); assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy); @@ -1792,18 +2225,22 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace); /* copy tables */ - { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog); + { size_t const chainSize = ZSTD_allocateChainTable(srcCCtx->appliedParams.cParams.strategy, + srcCCtx->appliedParams.useRowMatchFinder, + 0 /* forDDSDict */) + ? ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog) + : 0; size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog; int const h3log = srcCCtx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; - memcpy(dstCCtx->blockState.matchState.hashTable, + ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, hSize * sizeof(U32)); - memcpy(dstCCtx->blockState.matchState.chainTable, + ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable, srcCCtx->blockState.matchState.chainTable, chainSize * sizeof(U32)); - memcpy(dstCCtx->blockState.matchState.hashTable3, + ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3, srcCCtx->blockState.matchState.hashTable3, h3Size * sizeof(U32)); } @@ -1819,9 +2256,10 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; } dstCCtx->dictID = srcCCtx->dictID; + dstCCtx->dictContentSize = srcCCtx->dictContentSize; /* copy block state */ - memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock)); + ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock)); return 0; } @@ -1834,7 +2272,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize) { ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0); + ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy; ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1); if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN); @@ -1861,7 +2299,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */ assert(size < (1U<<31)); /* can be casted to int */ -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the table re-use logic is sound, and that we don't * access table space that we haven't cleaned, we re-"poison" the table * space every time we mark it dirty. @@ -1905,7 +2343,7 @@ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* par ZSTD_reduceTable(ms->hashTable, hSize, reducerValue); } - if (params->cParams.strategy != ZSTD_fast) { + if (ZSTD_allocateChainTable(params->cParams.strategy, params->useRowMatchFinder, (U32)ms->dedicatedDictSearch)) { U32 const chainSize = (U32)1 << params->cParams.chainLog; if (params->cParams.strategy == ZSTD_btlazy2) ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue); @@ -1942,9 +2380,9 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr) ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset); mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv); } - if (seqStorePtr->longLengthID==1) + if (seqStorePtr->longLengthType==ZSTD_llt_literalLength) llCodeTable[seqStorePtr->longLengthPos] = MaxLL; - if (seqStorePtr->longLengthID==2) + if (seqStorePtr->longLengthType==ZSTD_llt_matchLength) mlCodeTable[seqStorePtr->longLengthPos] = MaxML; } @@ -1958,10 +2396,158 @@ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams) return (cctxParams->targetCBlockSize != 0); } -/* ZSTD_compressSequences_internal(): - * actually compresses both literals and sequences */ +/* ZSTD_blockSplitterEnabled(): + * Returns if block splitting param is being used + * If used, compression will do best effort to split a block in order to improve compression ratio. + * Returns 1 if true, 0 otherwise. */ +static int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams) +{ + DEBUGLOG(5, "ZSTD_blockSplitterEnabled(splitBlocks=%d)", cctxParams->splitBlocks); + return (cctxParams->splitBlocks != 0); +} + +/* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types + * and size of the sequences statistics + */ +typedef struct { + U32 LLtype; + U32 Offtype; + U32 MLtype; + size_t size; + size_t lastCountSize; /* Accounts for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */ +} ZSTD_symbolEncodingTypeStats_t; + +/* ZSTD_buildSequencesStatistics(): + * Returns a ZSTD_symbolEncodingTypeStats_t, or a zstd error code in the `size` field. + * Modifies `nextEntropy` to have the appropriate values as a side effect. + * nbSeq must be greater than 0. + * + * entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32) + */ +static ZSTD_symbolEncodingTypeStats_t +ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq, + const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy, + BYTE* dst, const BYTE* const dstEnd, + ZSTD_strategy strategy, unsigned* countWorkspace, + void* entropyWorkspace, size_t entropyWkspSize) { + BYTE* const ostart = dst; + const BYTE* const oend = dstEnd; + BYTE* op = ostart; + FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable; + FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable; + FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable; + const BYTE* const ofCodeTable = seqStorePtr->ofCode; + const BYTE* const llCodeTable = seqStorePtr->llCode; + const BYTE* const mlCodeTable = seqStorePtr->mlCode; + ZSTD_symbolEncodingTypeStats_t stats; + + stats.lastCountSize = 0; + /* convert length/distances into codes */ + ZSTD_seqToCodes(seqStorePtr); + assert(op <= oend); + assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */ + /* build CTable for Literal Lengths */ + { unsigned max = MaxLL; + size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ + DEBUGLOG(5, "Building LL table"); + nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode; + stats.LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, + countWorkspace, max, mostFrequent, nbSeq, + LLFSELog, prevEntropy->litlengthCTable, + LL_defaultNorm, LL_defaultNormLog, + ZSTD_defaultAllowed, strategy); + assert(set_basic < set_compressed && set_rle < set_compressed); + assert(!(stats.LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ + { size_t const countSize = ZSTD_buildCTable( + op, (size_t)(oend - op), + CTable_LitLength, LLFSELog, (symbolEncodingType_e)stats.LLtype, + countWorkspace, max, llCodeTable, nbSeq, + LL_defaultNorm, LL_defaultNormLog, MaxLL, + prevEntropy->litlengthCTable, + sizeof(prevEntropy->litlengthCTable), + entropyWorkspace, entropyWkspSize); + if (ZSTD_isError(countSize)) { + DEBUGLOG(3, "ZSTD_buildCTable for LitLens failed"); + stats.size = countSize; + return stats; + } + if (stats.LLtype == set_compressed) + stats.lastCountSize = countSize; + op += countSize; + assert(op <= oend); + } } + /* build CTable for Offsets */ + { unsigned max = MaxOff; + size_t const mostFrequent = HIST_countFast_wksp( + countWorkspace, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ + /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ + ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; + DEBUGLOG(5, "Building OF table"); + nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode; + stats.Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, + countWorkspace, max, mostFrequent, nbSeq, + OffFSELog, prevEntropy->offcodeCTable, + OF_defaultNorm, OF_defaultNormLog, + defaultPolicy, strategy); + assert(!(stats.Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ + { size_t const countSize = ZSTD_buildCTable( + op, (size_t)(oend - op), + CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)stats.Offtype, + countWorkspace, max, ofCodeTable, nbSeq, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, + prevEntropy->offcodeCTable, + sizeof(prevEntropy->offcodeCTable), + entropyWorkspace, entropyWkspSize); + if (ZSTD_isError(countSize)) { + DEBUGLOG(3, "ZSTD_buildCTable for Offsets failed"); + stats.size = countSize; + return stats; + } + if (stats.Offtype == set_compressed) + stats.lastCountSize = countSize; + op += countSize; + assert(op <= oend); + } } + /* build CTable for MatchLengths */ + { unsigned max = MaxML; + size_t const mostFrequent = HIST_countFast_wksp( + countWorkspace, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ + DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); + nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode; + stats.MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, + countWorkspace, max, mostFrequent, nbSeq, + MLFSELog, prevEntropy->matchlengthCTable, + ML_defaultNorm, ML_defaultNormLog, + ZSTD_defaultAllowed, strategy); + assert(!(stats.MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ + { size_t const countSize = ZSTD_buildCTable( + op, (size_t)(oend - op), + CTable_MatchLength, MLFSELog, (symbolEncodingType_e)stats.MLtype, + countWorkspace, max, mlCodeTable, nbSeq, + ML_defaultNorm, ML_defaultNormLog, MaxML, + prevEntropy->matchlengthCTable, + sizeof(prevEntropy->matchlengthCTable), + entropyWorkspace, entropyWkspSize); + if (ZSTD_isError(countSize)) { + DEBUGLOG(3, "ZSTD_buildCTable for MatchLengths failed"); + stats.size = countSize; + return stats; + } + if (stats.MLtype == set_compressed) + stats.lastCountSize = countSize; + op += countSize; + assert(op <= oend); + } } + stats.size = (size_t)(op-ostart); + return stats; +} + +/* ZSTD_entropyCompressSeqStore_internal(): + * compresses both literals and sequences + * Returns compressed size of block, or a zstd error. + */ MEM_STATIC size_t -ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, +ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -1971,24 +2557,26 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, { const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; ZSTD_strategy const strategy = cctxParams->cParams.strategy; - unsigned count[MaxSeq+1]; + unsigned* count = (unsigned*)entropyWorkspace; FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable; FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable; FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable; - U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ const seqDef* const sequences = seqStorePtr->sequencesStart; + const size_t nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; const BYTE* const ofCodeTable = seqStorePtr->ofCode; const BYTE* const llCodeTable = seqStorePtr->llCode; const BYTE* const mlCodeTable = seqStorePtr->mlCode; BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstCapacity; BYTE* op = ostart; - size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - BYTE* seqHead; - BYTE* lastNCount = NULL; + size_t lastCountSize; - DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq); + entropyWorkspace = count + (MaxSeq + 1); + entropyWkspSize -= (MaxSeq + 1) * sizeof(*count); + + DEBUGLOG(4, "ZSTD_entropyCompressSeqStore_internal (nbSeq=%zu)", nbSeq); ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog))); + assert(entropyWkspSize >= HUF_WORKSPACE_SIZE); /* Compress literals */ { const BYTE* const literals = seqStorePtr->litStart; @@ -2023,132 +2611,57 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, assert(op <= oend); if (nbSeq==0) { /* Copy the old tables over as if we repeated them */ - memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); + ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); return (size_t)(op - ostart); } + { + ZSTD_symbolEncodingTypeStats_t stats; + BYTE* seqHead = op++; + /* build stats for sequences */ + stats = ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq, + &prevEntropy->fse, &nextEntropy->fse, + op, oend, + strategy, count, + entropyWorkspace, entropyWkspSize); + FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!"); + *seqHead = (BYTE)((stats.LLtype<<6) + (stats.Offtype<<4) + (stats.MLtype<<2)); + lastCountSize = stats.lastCountSize; + op += stats.size; + } - /* seqHead : flags for FSE encoding type */ - seqHead = op++; - assert(op <= oend); - - /* convert length/distances into codes */ - ZSTD_seqToCodes(seqStorePtr); - /* build CTable for Literal Lengths */ - { unsigned max = MaxLL; - size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ - DEBUGLOG(5, "Building LL table"); - nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode; - LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode, - count, max, mostFrequent, nbSeq, - LLFSELog, prevEntropy->fse.litlengthCTable, - LL_defaultNorm, LL_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(set_basic < set_compressed && set_rle < set_compressed); - assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable( - op, (size_t)(oend - op), - CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype, - count, max, llCodeTable, nbSeq, - LL_defaultNorm, LL_defaultNormLog, MaxLL, - prevEntropy->fse.litlengthCTable, - sizeof(prevEntropy->fse.litlengthCTable), - entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed"); - if (LLtype == set_compressed) - lastNCount = op; - op += countSize; - assert(op <= oend); - } } - /* build CTable for Offsets */ - { unsigned max = MaxOff; - size_t const mostFrequent = HIST_countFast_wksp( - count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ - /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ - ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; - DEBUGLOG(5, "Building OF table"); - nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode; - Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode, - count, max, mostFrequent, nbSeq, - OffFSELog, prevEntropy->fse.offcodeCTable, - OF_defaultNorm, OF_defaultNormLog, - defaultPolicy, strategy); - assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable( - op, (size_t)(oend - op), - CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype, - count, max, ofCodeTable, nbSeq, - OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, - prevEntropy->fse.offcodeCTable, - sizeof(prevEntropy->fse.offcodeCTable), - entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed"); - if (Offtype == set_compressed) - lastNCount = op; - op += countSize; - assert(op <= oend); - } } - /* build CTable for MatchLengths */ - { unsigned max = MaxML; - size_t const mostFrequent = HIST_countFast_wksp( - count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ - DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); - nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode; - MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode, - count, max, mostFrequent, nbSeq, - MLFSELog, prevEntropy->fse.matchlengthCTable, - ML_defaultNorm, ML_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable( - op, (size_t)(oend - op), - CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype, - count, max, mlCodeTable, nbSeq, - ML_defaultNorm, ML_defaultNormLog, MaxML, - prevEntropy->fse.matchlengthCTable, - sizeof(prevEntropy->fse.matchlengthCTable), - entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed"); - if (MLtype == set_compressed) - lastNCount = op; - op += countSize; - assert(op <= oend); - } } - - *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); - - { size_t const bitstreamSize = ZSTD_encodeSequences( - op, (size_t)(oend - op), - CTable_MatchLength, mlCodeTable, - CTable_OffsetBits, ofCodeTable, - CTable_LitLength, llCodeTable, - sequences, nbSeq, - longOffsets, bmi2); - FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); - op += bitstreamSize; - assert(op <= oend); - /* zstd versions <= 1.3.4 mistakenly report corruption when - * FSE_readNCount() receives a buffer < 4 bytes. - * Fixed by https://github.com/facebook/zstd/pull/1146. - * This can happen when the last set_compressed table present is 2 - * bytes and the bitstream is only one byte. - * In this exceedingly rare case, we will simply emit an uncompressed - * block, since it isn't worth optimizing. - */ - if (lastNCount && (op - lastNCount) < 4) { - /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ - assert(op - lastNCount == 3); - DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by " - "emitting an uncompressed block."); - return 0; - } - } + { size_t const bitstreamSize = ZSTD_encodeSequences( + op, (size_t)(oend - op), + CTable_MatchLength, mlCodeTable, + CTable_OffsetBits, ofCodeTable, + CTable_LitLength, llCodeTable, + sequences, nbSeq, + longOffsets, bmi2); + FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); + op += bitstreamSize; + assert(op <= oend); + /* zstd versions <= 1.3.4 mistakenly report corruption when + * FSE_readNCount() receives a buffer < 4 bytes. + * Fixed by https://github.com/facebook/zstd/pull/1146. + * This can happen when the last set_compressed table present is 2 + * bytes and the bitstream is only one byte. + * In this exceedingly rare case, we will simply emit an uncompressed + * block, since it isn't worth optimizing. + */ + if (lastCountSize && (lastCountSize + bitstreamSize) < 4) { + /* lastCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ + assert(lastCountSize + bitstreamSize == 3); + DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by " + "emitting an uncompressed block."); + return 0; + } + } DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart)); return (size_t)(op - ostart); } MEM_STATIC size_t -ZSTD_compressSequences(seqStore_t* seqStorePtr, +ZSTD_entropyCompressSeqStore(seqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -2157,7 +2670,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr, void* entropyWorkspace, size_t entropyWkspSize, int bmi2) { - size_t const cSize = ZSTD_compressSequences_internal( + size_t const cSize = ZSTD_entropyCompressSeqStore_internal( seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity, entropyWorkspace, entropyWkspSize, bmi2); @@ -2167,22 +2680,22 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr, */ if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) return 0; /* block not compressed */ - FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed"); + FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSeqStore_internal failed"); /* Check compressibility */ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); if (cSize >= maxCSize) return 0; /* block not compressed */ } - + DEBUGLOG(4, "ZSTD_entropyCompressSeqStore() cSize: %zu", cSize); return cSize; } /* ZSTD_selectBlockCompressor() : * Not static, but internal use only (used by long distance matcher) * assumption : strat is a valid strategy */ -ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode) +ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e useRowMatchFinder, ZSTD_dictMode_e dictMode) { - static const ZSTD_blockCompressor blockCompressor[3][ZSTD_STRATEGY_MAX+1] = { + static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { { ZSTD_compressBlock_fast /* default for 0 */, ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, @@ -2212,13 +2725,44 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo ZSTD_compressBlock_btlazy2_dictMatchState, ZSTD_compressBlock_btopt_dictMatchState, ZSTD_compressBlock_btultra_dictMatchState, - ZSTD_compressBlock_btultra_dictMatchState } + ZSTD_compressBlock_btultra_dictMatchState }, + { NULL /* default for 0 */, + NULL, + NULL, + ZSTD_compressBlock_greedy_dedicatedDictSearch, + ZSTD_compressBlock_lazy_dedicatedDictSearch, + ZSTD_compressBlock_lazy2_dedicatedDictSearch, + NULL, + NULL, + NULL, + NULL } }; ZSTD_blockCompressor selectedCompressor; ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat)); - selectedCompressor = blockCompressor[(int)dictMode][(int)strat]; + DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder); + if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) { + static const ZSTD_blockCompressor rowBasedBlockCompressors[4][3] = { + { ZSTD_compressBlock_greedy_row, + ZSTD_compressBlock_lazy_row, + ZSTD_compressBlock_lazy2_row }, + { ZSTD_compressBlock_greedy_extDict_row, + ZSTD_compressBlock_lazy_extDict_row, + ZSTD_compressBlock_lazy2_extDict_row }, + { ZSTD_compressBlock_greedy_dictMatchState_row, + ZSTD_compressBlock_lazy_dictMatchState_row, + ZSTD_compressBlock_lazy2_dictMatchState_row }, + { ZSTD_compressBlock_greedy_dedicatedDictSearch_row, + ZSTD_compressBlock_lazy_dedicatedDictSearch_row, + ZSTD_compressBlock_lazy2_dedicatedDictSearch_row } + }; + DEBUGLOG(4, "Selecting a row-based matchfinder"); + assert(useRowMatchFinder != ZSTD_urm_auto); + selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy]; + } else { + selectedCompressor = blockCompressor[(int)dictMode][(int)strat]; + } assert(selectedCompressor != NULL); return selectedCompressor; } @@ -2226,7 +2770,7 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr, const BYTE* anchor, size_t lastLLSize) { - memcpy(seqStorePtr->lit, anchor, lastLLSize); + ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize); seqStorePtr->lit += lastLLSize; } @@ -2234,7 +2778,7 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr) { ssPtr->lit = ssPtr->litStart; ssPtr->sequences = ssPtr->sequencesStart; - ssPtr->longLengthID = 0; + ssPtr->longLengthType = ZSTD_llt_none; } typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e; @@ -2247,7 +2791,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) /* Assert that we have correctly flushed the ctx params into the ms's copy */ ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { - ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); + if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) { + ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize); + } else { + ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); + } return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */ } ZSTD_resetSeqStore(&(zc->seqStore)); @@ -2263,10 +2811,10 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) /* limited update after a very long match */ { const BYTE* const base = ms->window.base; const BYTE* const istart = (const BYTE*)src; - const U32 current = (U32)(istart-base); + const U32 curr = (U32)(istart-base); if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */ - if (current > ms->nextToUpdate + 384) - ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384)); + if (curr > ms->nextToUpdate + 384) + ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384)); } /* select and store sequences */ @@ -2283,10 +2831,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) ZSTD_ldm_blockCompress(&zc->externSeqStore, ms, &zc->seqStore, zc->blockState.nextCBlock->rep, + zc->appliedParams.useRowMatchFinder, src, srcSize); assert(zc->externSeqStore.pos <= zc->externSeqStore.size); } else if (zc->appliedParams.ldmParams.enableLdm) { - rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0}; + rawSeqStore_t ldmSeqStore = kNullRawSeqStore; ldmSeqStore.seq = zc->ldmSequences; ldmSeqStore.capacity = zc->maxNbLdmSequences; @@ -2299,10 +2848,14 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) ZSTD_ldm_blockCompress(&ldmSeqStore, ms, &zc->seqStore, zc->blockState.nextCBlock->rep, + zc->appliedParams.useRowMatchFinder, src, srcSize); assert(ldmSeqStore.pos == ldmSeqStore.size); } else { /* not long range mode */ - ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode); + ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, + zc->appliedParams.useRowMatchFinder, + dictMode); + ms->ldmSeqStore = NULL; lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); } { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; @@ -2314,59 +2867,72 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) { const seqStore_t* seqStore = ZSTD_getSeqStore(zc); - const seqDef* seqs = seqStore->sequencesStart; - size_t seqsSize = seqStore->sequences - seqs; + const seqDef* seqStoreSeqs = seqStore->sequencesStart; + size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs; + size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart); + size_t literalsRead = 0; + size_t lastLLSize; ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex]; - size_t i; size_t position; int repIdx; + size_t i; + repcodes_t updatedRepcodes; assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences); - for (i = 0, position = 0; i < seqsSize; ++i) { - outSeqs[i].offset = seqs[i].offset; - outSeqs[i].litLength = seqs[i].litLength; - outSeqs[i].matchLength = seqs[i].matchLength + MINMATCH; + /* Ensure we have enough space for last literals "sequence" */ + assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1); + ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + for (i = 0; i < seqStoreSeqSize; ++i) { + U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM; + outSeqs[i].litLength = seqStoreSeqs[i].litLength; + outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH; + outSeqs[i].rep = 0; if (i == seqStore->longLengthPos) { - if (seqStore->longLengthID == 1) { + if (seqStore->longLengthType == ZSTD_llt_literalLength) { outSeqs[i].litLength += 0x10000; - } else if (seqStore->longLengthID == 2) { + } else if (seqStore->longLengthType == ZSTD_llt_matchLength) { outSeqs[i].matchLength += 0x10000; } } - if (outSeqs[i].offset <= ZSTD_REP_NUM) { - outSeqs[i].rep = outSeqs[i].offset; - repIdx = (unsigned int)i - outSeqs[i].offset; - - if (outSeqs[i].litLength == 0) { - if (outSeqs[i].offset < 3) { - --repIdx; + if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) { + /* Derive the correct offset corresponding to a repcode */ + outSeqs[i].rep = seqStoreSeqs[i].offset; + if (outSeqs[i].litLength != 0) { + rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1]; + } else { + if (outSeqs[i].rep == 3) { + rawOffset = updatedRepcodes.rep[0] - 1; } else { - repIdx = (unsigned int)i - 1; + rawOffset = updatedRepcodes.rep[outSeqs[i].rep]; } - ++outSeqs[i].rep; - } - assert(repIdx >= -3); - outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : repStartValue[-repIdx - 1]; - if (outSeqs[i].rep == 4) { - --outSeqs[i].offset; } - } else { - outSeqs[i].offset -= ZSTD_REP_NUM; } - - position += outSeqs[i].litLength; - outSeqs[i].matchPos = (unsigned int)position; - position += outSeqs[i].matchLength; + outSeqs[i].offset = rawOffset; + /* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode + so we provide seqStoreSeqs[i].offset - 1 */ + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, + seqStoreSeqs[i].offset - 1, + seqStoreSeqs[i].litLength == 0); + literalsRead += outSeqs[i].litLength; } - zc->seqCollector.seqIndex += seqsSize; + /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0. + * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker + * for the block boundary, according to the API. + */ + assert(seqStoreLiteralsSize >= literalsRead); + lastLLSize = seqStoreLiteralsSize - literalsRead; + outSeqs[i].litLength = (U32)lastLLSize; + outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0; + seqStoreSeqSize++; + zc->seqCollector.seqIndex += seqStoreSeqSize; } -size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize) +size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, + size_t outSeqsSize, const void* src, size_t srcSize) { const size_t dstCapacity = ZSTD_compressBound(srcSize); - void* dst = ZSTD_malloc(dstCapacity, ZSTD_defaultCMem); + void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem); SeqCollector seqCollector; RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!"); @@ -2378,16 +2944,47 @@ size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, zc->seqCollector = seqCollector; ZSTD_compress2(zc, dst, dstCapacity, src, srcSize); - ZSTD_free(dst, ZSTD_defaultCMem); + ZSTD_customFree(dst, ZSTD_defaultCMem); return zc->seqCollector.seqIndex; } -/* Returns true if the given block is a RLE block */ -static int ZSTD_isRLE(const BYTE *ip, size_t length) { +size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) { + size_t in = 0; + size_t out = 0; + for (; in < seqsSize; ++in) { + if (sequences[in].offset == 0 && sequences[in].matchLength == 0) { + if (in != seqsSize - 1) { + sequences[in+1].litLength += sequences[in].litLength; + } + } else { + sequences[out] = sequences[in]; + ++out; + } + } + return out; +} + +/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */ +static int ZSTD_isRLE(const BYTE* src, size_t length) { + const BYTE* ip = src; + const BYTE value = ip[0]; + const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL); + const size_t unrollSize = sizeof(size_t) * 4; + const size_t unrollMask = unrollSize - 1; + const size_t prefixLength = length & unrollMask; size_t i; - if (length < 2) return 1; - for (i = 1; i < length; ++i) { - if (ip[0] != ip[i]) return 0; + size_t u; + if (length == 1) return 1; + /* Check if prefix is RLE first before using unrolled loop */ + if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) { + return 0; + } + for (i = prefixLength; i != length; i += unrollSize) { + for (u = 0; u < unrollSize; u += sizeof(size_t)) { + if (MEM_readST(ip + i + u) != valueST) { + return 0; + } + } } return 1; } @@ -2404,11 +3001,713 @@ static int ZSTD_maybeRLE(seqStore_t const* seqStore) return nbSeqs < 4 && nbLits < 10; } -static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) +static void ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs) +{ + ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock; + bs->prevCBlock = bs->nextCBlock; + bs->nextCBlock = tmp; +} + +/* Writes the block header */ +static void writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock) { + U32 const cBlockHeader = cSize == 1 ? + lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : + lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24(op, cBlockHeader); + DEBUGLOG(3, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock); +} + +/** ZSTD_buildBlockEntropyStats_literals() : + * Builds entropy for the literals. + * Stores literals block type (raw, rle, compressed, repeat) and + * huffman description table to hufMetadata. + * Requires ENTROPY_WORKSPACE_SIZE workspace + * @return : size of huffman description table or error code */ +static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize, + const ZSTD_hufCTables_t* prevHuf, + ZSTD_hufCTables_t* nextHuf, + ZSTD_hufCTablesMetadata_t* hufMetadata, + const int disableLiteralsCompression, + void* workspace, size_t wkspSize) +{ + BYTE* const wkspStart = (BYTE*)workspace; + BYTE* const wkspEnd = wkspStart + wkspSize; + BYTE* const countWkspStart = wkspStart; + unsigned* const countWksp = (unsigned*)workspace; + const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned); + BYTE* const nodeWksp = countWkspStart + countWkspSize; + const size_t nodeWkspSize = wkspEnd-nodeWksp; + unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX; + unsigned huffLog = HUF_TABLELOG_DEFAULT; + HUF_repeat repeat = prevHuf->repeatMode; + DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_literals (srcSize=%zu)", srcSize); + + /* Prepare nextEntropy assuming reusing the existing table */ + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + + if (disableLiteralsCompression) { + DEBUGLOG(5, "set_basic - disabled"); + hufMetadata->hType = set_basic; + return 0; + } + + /* small ? don't even attempt compression (speed opt) */ +#ifndef COMPRESS_LITERALS_SIZE_MIN +#define COMPRESS_LITERALS_SIZE_MIN 63 +#endif + { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; + if (srcSize <= minLitSize) { + DEBUGLOG(5, "set_basic - too small"); + hufMetadata->hType = set_basic; + return 0; + } + } + + /* Scan input and build symbol stats */ + { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize); + FORWARD_IF_ERROR(largest, "HIST_count_wksp failed"); + if (largest == srcSize) { + DEBUGLOG(5, "set_rle"); + hufMetadata->hType = set_rle; + return 0; + } + if (largest <= (srcSize >> 7)+4) { + DEBUGLOG(5, "set_basic - no gain"); + hufMetadata->hType = set_basic; + return 0; + } + } + + /* Validate the previous Huffman table */ + if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) { + repeat = HUF_repeat_none; + } + + /* Build Huffman Tree */ + ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); + huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); + { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp, + maxSymbolValue, huffLog, + nodeWksp, nodeWkspSize); + FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp"); + huffLog = (U32)maxBits; + { /* Build and write the CTable */ + size_t const newCSize = HUF_estimateCompressedSize( + (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue); + size_t const hSize = HUF_writeCTable_wksp( + hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer), + (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog, + nodeWksp, nodeWkspSize); + /* Check against repeating the previous CTable */ + if (repeat != HUF_repeat_none) { + size_t const oldCSize = HUF_estimateCompressedSize( + (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue); + if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) { + DEBUGLOG(5, "set_repeat - smaller"); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + hufMetadata->hType = set_repeat; + return 0; + } + } + if (newCSize + hSize >= srcSize) { + DEBUGLOG(5, "set_basic - no gains"); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + hufMetadata->hType = set_basic; + return 0; + } + DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize); + hufMetadata->hType = set_compressed; + nextHuf->repeatMode = HUF_repeat_check; + return hSize; + } + } +} + + +/* ZSTD_buildDummySequencesStatistics(): + * Returns a ZSTD_symbolEncodingTypeStats_t with all encoding types as set_basic, + * and updates nextEntropy to the appropriate repeatMode. + */ +static ZSTD_symbolEncodingTypeStats_t +ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) { + ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0}; + nextEntropy->litlength_repeatMode = FSE_repeat_none; + nextEntropy->offcode_repeatMode = FSE_repeat_none; + nextEntropy->matchlength_repeatMode = FSE_repeat_none; + return stats; +} + +/** ZSTD_buildBlockEntropyStats_sequences() : + * Builds entropy for the sequences. + * Stores symbol compression modes and fse table to fseMetadata. + * Requires ENTROPY_WORKSPACE_SIZE wksp. + * @return : size of fse tables or error code */ +static size_t ZSTD_buildBlockEntropyStats_sequences(seqStore_t* seqStorePtr, + const ZSTD_fseCTables_t* prevEntropy, + ZSTD_fseCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + ZSTD_fseCTablesMetadata_t* fseMetadata, + void* workspace, size_t wkspSize) { - ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; - zc->blockState.prevCBlock = zc->blockState.nextCBlock; - zc->blockState.nextCBlock = tmp; + ZSTD_strategy const strategy = cctxParams->cParams.strategy; + size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; + BYTE* const ostart = fseMetadata->fseTablesBuffer; + BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer); + BYTE* op = ostart; + unsigned* countWorkspace = (unsigned*)workspace; + unsigned* entropyWorkspace = countWorkspace + (MaxSeq + 1); + size_t entropyWorkspaceSize = wkspSize - (MaxSeq + 1) * sizeof(*countWorkspace); + ZSTD_symbolEncodingTypeStats_t stats; + + DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)", nbSeq); + stats = nbSeq != 0 ? ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq, + prevEntropy, nextEntropy, op, oend, + strategy, countWorkspace, + entropyWorkspace, entropyWorkspaceSize) + : ZSTD_buildDummySequencesStatistics(nextEntropy); + FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!"); + fseMetadata->llType = (symbolEncodingType_e) stats.LLtype; + fseMetadata->ofType = (symbolEncodingType_e) stats.Offtype; + fseMetadata->mlType = (symbolEncodingType_e) stats.MLtype; + fseMetadata->lastCountSize = stats.lastCountSize; + return stats.size; +} + + +/** ZSTD_buildBlockEntropyStats() : + * Builds entropy for the block. + * Requires workspace size ENTROPY_WORKSPACE_SIZE + * + * @return : 0 on success or error code + */ +size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize) +{ + size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart; + entropyMetadata->hufMetadata.hufDesSize = + ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize, + &prevEntropy->huf, &nextEntropy->huf, + &entropyMetadata->hufMetadata, + ZSTD_disableLiteralsCompression(cctxParams), + workspace, wkspSize); + FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildBlockEntropyStats_literals failed"); + entropyMetadata->fseMetadata.fseTablesSize = + ZSTD_buildBlockEntropyStats_sequences(seqStorePtr, + &prevEntropy->fse, &nextEntropy->fse, + cctxParams, + &entropyMetadata->fseMetadata, + workspace, wkspSize); + FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildBlockEntropyStats_sequences failed"); + return 0; +} + +/* Returns the size estimate for the literals section (header + content) of a block */ +static size_t ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize, + const ZSTD_hufCTables_t* huf, + const ZSTD_hufCTablesMetadata_t* hufMetadata, + void* workspace, size_t wkspSize, + int writeEntropy) +{ + unsigned* const countWksp = (unsigned*)workspace; + unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX; + size_t literalSectionHeaderSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB); + U32 singleStream = litSize < 256; + + if (hufMetadata->hType == set_basic) return litSize; + else if (hufMetadata->hType == set_rle) return 1; + else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) { + size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize); + if (ZSTD_isError(largest)) return litSize; + { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue); + if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize; + if (!singleStream) cLitSizeEstimate += 6; /* multi-stream huffman uses 6-byte jump table */ + return cLitSizeEstimate + literalSectionHeaderSize; + } } + assert(0); /* impossible */ + return 0; +} + +/* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */ +static size_t ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type, + const BYTE* codeTable, size_t nbSeq, unsigned maxCode, + const FSE_CTable* fseCTable, + const U32* additionalBits, + short const* defaultNorm, U32 defaultNormLog, U32 defaultMax, + void* workspace, size_t wkspSize) +{ + unsigned* const countWksp = (unsigned*)workspace; + const BYTE* ctp = codeTable; + const BYTE* const ctStart = ctp; + const BYTE* const ctEnd = ctStart + nbSeq; + size_t cSymbolTypeSizeEstimateInBits = 0; + unsigned max = maxCode; + + HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */ + if (type == set_basic) { + /* We selected this encoding type, so it must be valid. */ + assert(max <= defaultMax); + (void)defaultMax; + cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max); + } else if (type == set_rle) { + cSymbolTypeSizeEstimateInBits = 0; + } else if (type == set_compressed || type == set_repeat) { + cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max); + } + if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) { + return nbSeq * 10; + } + while (ctp < ctEnd) { + if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp]; + else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */ + ctp++; + } + return cSymbolTypeSizeEstimateInBits >> 3; +} + +/* Returns the size estimate for the sequences section (header + content) of a block */ +static size_t ZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable, + const BYTE* llCodeTable, + const BYTE* mlCodeTable, + size_t nbSeq, + const ZSTD_fseCTables_t* fseTables, + const ZSTD_fseCTablesMetadata_t* fseMetadata, + void* workspace, size_t wkspSize, + int writeEntropy) +{ + size_t sequencesSectionHeaderSize = 1 /* seqHead */ + 1 /* min seqSize size */ + (nbSeq >= 128) + (nbSeq >= LONGNBSEQ); + size_t cSeqSizeEstimate = 0; + cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, nbSeq, MaxOff, + fseTables->offcodeCTable, NULL, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, + workspace, wkspSize); + cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->llType, llCodeTable, nbSeq, MaxLL, + fseTables->litlengthCTable, LL_bits, + LL_defaultNorm, LL_defaultNormLog, MaxLL, + workspace, wkspSize); + cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, nbSeq, MaxML, + fseTables->matchlengthCTable, ML_bits, + ML_defaultNorm, ML_defaultNormLog, MaxML, + workspace, wkspSize); + if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize; + return cSeqSizeEstimate + sequencesSectionHeaderSize; +} + +/* Returns the size estimate for a given stream of literals, of, ll, ml */ +static size_t ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize, + const BYTE* ofCodeTable, + const BYTE* llCodeTable, + const BYTE* mlCodeTable, + size_t nbSeq, + const ZSTD_entropyCTables_t* entropy, + const ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize, + int writeLitEntropy, int writeSeqEntropy) { + size_t const literalsSize = ZSTD_estimateBlockSize_literal(literals, litSize, + &entropy->huf, &entropyMetadata->hufMetadata, + workspace, wkspSize, writeLitEntropy); + size_t const seqSize = ZSTD_estimateBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable, + nbSeq, &entropy->fse, &entropyMetadata->fseMetadata, + workspace, wkspSize, writeSeqEntropy); + return seqSize + literalsSize + ZSTD_blockHeaderSize; +} + +/* Builds entropy statistics and uses them for blocksize estimation. + * + * Returns the estimated compressed size of the seqStore, or a zstd error. + */ +static size_t ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, const ZSTD_CCtx* zc) { + ZSTD_entropyCTablesMetadata_t entropyMetadata; + FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore, + &zc->blockState.prevCBlock->entropy, + &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, + &entropyMetadata, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); + return ZSTD_estimateBlockSize(seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart), + seqStore->ofCode, seqStore->llCode, seqStore->mlCode, + (size_t)(seqStore->sequences - seqStore->sequencesStart), + &zc->blockState.nextCBlock->entropy, &entropyMetadata, zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE, + (int)(entropyMetadata.hufMetadata.hType == set_compressed), 1); +} + +/* Returns literals bytes represented in a seqStore */ +static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) { + size_t literalsBytes = 0; + size_t const nbSeqs = seqStore->sequences - seqStore->sequencesStart; + size_t i; + for (i = 0; i < nbSeqs; ++i) { + seqDef seq = seqStore->sequencesStart[i]; + literalsBytes += seq.litLength; + if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) { + literalsBytes += 0x10000; + } + } + return literalsBytes; +} + +/* Returns match bytes represented in a seqStore */ +static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) { + size_t matchBytes = 0; + size_t const nbSeqs = seqStore->sequences - seqStore->sequencesStart; + size_t i; + for (i = 0; i < nbSeqs; ++i) { + seqDef seq = seqStore->sequencesStart[i]; + matchBytes += seq.matchLength + MINMATCH; + if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) { + matchBytes += 0x10000; + } + } + return matchBytes; +} + +/* Derives the seqStore that is a chunk of the originalSeqStore from [startIdx, endIdx). + * Stores the result in resultSeqStore. + */ +static void ZSTD_deriveSeqStoreChunk(seqStore_t* resultSeqStore, + const seqStore_t* originalSeqStore, + size_t startIdx, size_t endIdx) { + BYTE* const litEnd = originalSeqStore->lit; + size_t literalsBytes; + size_t literalsBytesPreceding = 0; + + *resultSeqStore = *originalSeqStore; + if (startIdx > 0) { + resultSeqStore->sequences = originalSeqStore->sequencesStart + startIdx; + literalsBytesPreceding = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore); + } + + /* Move longLengthPos into the correct position if necessary */ + if (originalSeqStore->longLengthType != ZSTD_llt_none) { + if (originalSeqStore->longLengthPos < startIdx || originalSeqStore->longLengthPos > endIdx) { + resultSeqStore->longLengthType = ZSTD_llt_none; + } else { + resultSeqStore->longLengthPos -= (U32)startIdx; + } + } + resultSeqStore->sequencesStart = originalSeqStore->sequencesStart + startIdx; + resultSeqStore->sequences = originalSeqStore->sequencesStart + endIdx; + literalsBytes = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore); + resultSeqStore->litStart += literalsBytesPreceding; + if (endIdx == (size_t)(originalSeqStore->sequences - originalSeqStore->sequencesStart)) { + /* This accounts for possible last literals if the derived chunk reaches the end of the block */ + resultSeqStore->lit = litEnd; + } else { + resultSeqStore->lit = resultSeqStore->litStart+literalsBytes; + } + resultSeqStore->llCode += startIdx; + resultSeqStore->mlCode += startIdx; + resultSeqStore->ofCode += startIdx; +} + +/** + * Returns the raw offset represented by the combination of offCode, ll0, and repcode history. + * offCode must be an offCode representing a repcode, therefore in the range of [0, 2]. + */ +static U32 ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offCode, const U32 ll0) { + U32 const adjustedOffCode = offCode + ll0; + assert(offCode < ZSTD_REP_NUM); + if (adjustedOffCode == ZSTD_REP_NUM) { + /* litlength == 0 and offCode == 2 implies selection of first repcode - 1 */ + assert(rep[0] > 0); + return rep[0] - 1; + } + return rep[adjustedOffCode]; +} + +/** + * ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise + * due to emission of RLE/raw blocks that disturb the offset history, and replaces any repcodes within + * the seqStore that may be invalid. + * + * dRepcodes are updated as would be on the decompression side. cRepcodes are updated exactly in + * accordance with the seqStore. + */ +static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes, + seqStore_t* const seqStore, U32 const nbSeq) { + U32 idx = 0; + for (; idx < nbSeq; ++idx) { + seqDef* const seq = seqStore->sequencesStart + idx; + U32 const ll0 = (seq->litLength == 0); + U32 offCode = seq->offset - 1; + assert(seq->offset > 0); + if (offCode <= ZSTD_REP_MOVE) { + U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offCode, ll0); + U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offCode, ll0); + /* Adjust simulated decompression repcode history if we come across a mismatch. Replace + * the repcode with the offset it actually references, determined by the compression + * repcode history. + */ + if (dRawOffset != cRawOffset) { + seq->offset = cRawOffset + ZSTD_REP_NUM; + } + } + /* Compression repcode history is always updated with values directly from the unmodified seqStore. + * Decompression repcode history may use modified seq->offset value taken from compression repcode history. + */ + *dRepcodes = ZSTD_updateRep(dRepcodes->rep, seq->offset - 1, ll0); + *cRepcodes = ZSTD_updateRep(cRepcodes->rep, offCode, ll0); + } +} + +/* ZSTD_compressSeqStore_singleBlock(): + * Compresses a seqStore into a block with a block header, into the buffer dst. + * + * Returns the total size of that block (including header) or a ZSTD error code. + */ +static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore, + repcodes_t* const dRep, repcodes_t* const cRep, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 lastBlock, U32 isPartition) { + const U32 rleMaxLength = 25; + BYTE* op = (BYTE*)dst; + const BYTE* ip = (const BYTE*)src; + size_t cSize; + size_t cSeqsSize; + + /* In case of an RLE or raw block, the simulated decompression repcode history must be reset */ + repcodes_t const dRepOriginal = *dRep; + if (isPartition) + ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart)); + + cSeqsSize = ZSTD_entropyCompressSeqStore(seqStore, + &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, + op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize, + srcSize, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->bmi2); + FORWARD_IF_ERROR(cSeqsSize, "ZSTD_entropyCompressSeqStore failed!"); + + if (!zc->isFirstBlock && + cSeqsSize < rleMaxLength && + ZSTD_isRLE((BYTE const*)src, srcSize)) { + /* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + cSeqsSize = 1; + } + + if (zc->seqCollector.collectSequences) { + ZSTD_copyBlockSequences(zc); + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + return 0; + } + + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + if (cSeqsSize == 0) { + cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize, "Nocompress block failed"); + DEBUGLOG(4, "Writing out nocompress block, size: %zu", cSize); + *dRep = dRepOriginal; /* reset simulated decompression repcode history */ + } else if (cSeqsSize == 1) { + cSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize, "RLE compress block failed"); + DEBUGLOG(4, "Writing out RLE block, size: %zu", cSize); + *dRep = dRepOriginal; /* reset simulated decompression repcode history */ + } else { + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + writeBlockHeader(op, cSeqsSize, srcSize, lastBlock); + cSize = ZSTD_blockHeaderSize + cSeqsSize; + DEBUGLOG(4, "Writing out compressed block, size: %zu", cSize); + } + return cSize; +} + +/* Struct to keep track of where we are in our recursive calls. */ +typedef struct { + U32* splitLocations; /* Array of split indices */ + size_t idx; /* The current index within splitLocations being worked on */ +} seqStoreSplits; + +#define MIN_SEQUENCES_BLOCK_SPLITTING 300 +#define MAX_NB_SPLITS 196 + +/* Helper function to perform the recursive search for block splits. + * Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half. + * If advantageous to split, then we recurse down the two sub-blocks. If not, or if an error occurred in estimation, then + * we do not recurse. + * + * Note: The recursion depth is capped by a heuristic minimum number of sequences, defined by MIN_SEQUENCES_BLOCK_SPLITTING. + * In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING). + * In practice, recursion depth usually doesn't go beyond 4. + * + * Furthermore, the number of splits is capped by MAX_NB_SPLITS. At MAX_NB_SPLITS == 196 with the current existing blockSize + * maximum of 128 KB, this value is actually impossible to reach. + */ +static void ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx, + const ZSTD_CCtx* zc, const seqStore_t* origSeqStore) { + seqStore_t fullSeqStoreChunk; + seqStore_t firstHalfSeqStore; + seqStore_t secondHalfSeqStore; + size_t estimatedOriginalSize; + size_t estimatedFirstHalfSize; + size_t estimatedSecondHalfSize; + size_t midIdx = (startIdx + endIdx)/2; + + if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= MAX_NB_SPLITS) { + return; + } + ZSTD_deriveSeqStoreChunk(&fullSeqStoreChunk, origSeqStore, startIdx, endIdx); + ZSTD_deriveSeqStoreChunk(&firstHalfSeqStore, origSeqStore, startIdx, midIdx); + ZSTD_deriveSeqStoreChunk(&secondHalfSeqStore, origSeqStore, midIdx, endIdx); + estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&fullSeqStoreChunk, zc); + estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&firstHalfSeqStore, zc); + estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&secondHalfSeqStore, zc); + DEBUGLOG(5, "Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu", + estimatedOriginalSize, estimatedFirstHalfSize, estimatedSecondHalfSize); + if (ZSTD_isError(estimatedOriginalSize) || ZSTD_isError(estimatedFirstHalfSize) || ZSTD_isError(estimatedSecondHalfSize)) { + return; + } + if (estimatedFirstHalfSize + estimatedSecondHalfSize < estimatedOriginalSize) { + ZSTD_deriveBlockSplitsHelper(splits, startIdx, midIdx, zc, origSeqStore); + splits->splitLocations[splits->idx] = (U32)midIdx; + splits->idx++; + ZSTD_deriveBlockSplitsHelper(splits, midIdx, endIdx, zc, origSeqStore); + } +} + +/* Base recursive function. Populates a table with intra-block partition indices that can improve compression ratio. + * + * Returns the number of splits made (which equals the size of the partition table - 1). + */ +static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq) { + seqStoreSplits splits = {partitions, 0}; + if (nbSeq <= 4) { + DEBUGLOG(4, "ZSTD_deriveBlockSplits: Too few sequences to split"); + /* Refuse to try and split anything with less than 4 sequences */ + return 0; + } + ZSTD_deriveBlockSplitsHelper(&splits, 0, nbSeq, zc, &zc->seqStore); + splits.splitLocations[splits.idx] = nbSeq; + DEBUGLOG(5, "ZSTD_deriveBlockSplits: final nb partitions: %zu", splits.idx+1); + return splits.idx; +} + +/* ZSTD_compressBlock_splitBlock(): + * Attempts to split a given block into multiple blocks to improve compression ratio. + * + * Returns combined size of all blocks (which includes headers), or a ZSTD error code. + */ +static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, + const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq) { + size_t cSize = 0; + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + U32 partitions[MAX_NB_SPLITS]; + size_t i = 0; + size_t srcBytesTotal = 0; + size_t numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq); + seqStore_t nextSeqStore; + seqStore_t currSeqStore; + + /* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history + * may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two + * separate repcode histories that simulate repcode history on compression and decompression side, + * and use the histories to determine whether we must replace a particular repcode with its raw offset. + * + * 1) cRep gets updated for each partition, regardless of whether the block was emitted as uncompressed + * or RLE. This allows us to retrieve the offset value that an invalid repcode references within + * a nocompress/RLE block. + * 2) dRep gets updated only for compressed partitions, and when a repcode gets replaced, will use + * the replacement offset value rather than the original repcode to update the repcode history. + * dRep also will be the final repcode history sent to the next block. + * + * See ZSTD_seqStore_resolveOffCodes() for more details. + */ + repcodes_t dRep; + repcodes_t cRep; + ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + + DEBUGLOG(4, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", + (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, + (unsigned)zc->blockState.matchState.nextToUpdate); + + if (numSplits == 0) { + size_t cSizeSingleBlock = ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore, + &dRep, &cRep, + op, dstCapacity, + ip, blockSize, + lastBlock, 0 /* isPartition */); + FORWARD_IF_ERROR(cSizeSingleBlock, "Compressing single block from splitBlock_internal() failed!"); + DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal: No splits"); + assert(cSizeSingleBlock <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize); + return cSizeSingleBlock; + } + + ZSTD_deriveSeqStoreChunk(&currSeqStore, &zc->seqStore, 0, partitions[0]); + for (i = 0; i <= numSplits; ++i) { + size_t srcBytes; + size_t cSizeChunk; + U32 const lastPartition = (i == numSplits); + U32 lastBlockEntireSrc = 0; + + srcBytes = ZSTD_countSeqStoreLiteralsBytes(&currSeqStore) + ZSTD_countSeqStoreMatchBytes(&currSeqStore); + srcBytesTotal += srcBytes; + if (lastPartition) { + /* This is the final partition, need to account for possible last literals */ + srcBytes += blockSize - srcBytesTotal; + lastBlockEntireSrc = lastBlock; + } else { + ZSTD_deriveSeqStoreChunk(&nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]); + } + + cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, &currSeqStore, + &dRep, &cRep, + op, dstCapacity, + ip, srcBytes, + lastBlockEntireSrc, 1 /* isPartition */); + DEBUGLOG(5, "Estimated size: %zu actual size: %zu", ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&currSeqStore, zc), cSizeChunk); + FORWARD_IF_ERROR(cSizeChunk, "Compressing chunk failed!"); + + ip += srcBytes; + op += cSizeChunk; + dstCapacity -= cSizeChunk; + cSize += cSizeChunk; + currSeqStore = nextSeqStore; + assert(cSizeChunk <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize); + } + /* cRep and dRep may have diverged during the compression. If so, we use the dRep repcodes + * for the next block. + */ + ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(repcodes_t)); + return cSize; +} + +static size_t ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, U32 lastBlock) { + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + U32 nbSeq; + size_t cSize; + DEBUGLOG(4, "ZSTD_compressBlock_splitBlock"); + + { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); + if (bss == ZSTDbss_noCompress) { + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); + DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block"); + return cSize; + } + nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart); + } + + assert(zc->appliedParams.splitBlocks == 1); + cSize = ZSTD_compressBlock_splitBlock_internal(zc, dst, dstCapacity, src, srcSize, lastBlock, nbSeq); + FORWARD_IF_ERROR(cSize, "Splitting blocks failed!"); + return cSize; } static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, @@ -2434,18 +3733,25 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, if (zc->seqCollector.collectSequences) { ZSTD_copyBlockSequences(zc); + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); return 0; } /* encode sequences and literals */ - cSize = ZSTD_compressSequences(&zc->seqStore, + cSize = ZSTD_entropyCompressSeqStore(&zc->seqStore, &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, dst, dstCapacity, srcSize, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, zc->bmi2); + if (zc->seqCollector.collectSequences) { + ZSTD_copyBlockSequences(zc); + return 0; + } + + if (frame && /* We don't want to emit our first block as a RLE even if it qualifies because * doing so will cause the decoder (cli only) to throw a "should consume all input error." @@ -2461,7 +3767,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, out: if (!ZSTD_isError(cSize) && cSize > 1) { - ZSTD_confirmRepcodesAndEntropyTables(zc); + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); } /* We check that dictionaries have offset codes available for the first * block. After the first block, the offcode table might not have large @@ -2514,7 +3820,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy); FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed"); if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) { - ZSTD_confirmRepcodesAndEntropyTables(zc); + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); return cSize; } } @@ -2554,9 +3860,9 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, void const* ip, void const* iend) { - if (ZSTD_window_needOverflowCorrection(ms->window, iend)) { - U32 const maxDist = (U32)1 << params->cParams.windowLog; - U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); + U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); + U32 const maxDist = (U32)1 << params->cParams.windowLog; + if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) { U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); @@ -2579,7 +3885,7 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, * Frame is supposed already started (header already produced) * @return : compressed size, or an error code */ -static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, +static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastFrameChunk) @@ -2593,7 +3899,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); + DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); if (cctx->appliedParams.fParams.checksumFlag && srcSize) XXH64_update(&cctx->xxhState, src, srcSize); @@ -2619,6 +3925,10 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed"); assert(cSize > 0); assert(cSize <= blockSize + ZSTD_blockHeaderSize); + } else if (ZSTD_blockSplitterEnabled(&cctx->appliedParams)) { + cSize = ZSTD_compressBlock_splitBlock(cctx, op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_splitBlock failed"); + assert(cSize > 0 || cctx->seqCollector.collectSequences == 1); } else { cSize = ZSTD_compressBlock_internal(cctx, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, @@ -2673,7 +3983,6 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, "dst buf is too small to fit worst-case frame header size."); DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); - if (params->format == ZSTD_f_zstd1) { MEM_writeLE32(dst, ZSTD_MAGICNUMBER); pos = 4; @@ -2699,6 +4008,26 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, return pos; } +/* ZSTD_writeSkippableFrame_advanced() : + * Writes out a skippable frame with the specified magic number variant (16 are supported), + * from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data. + * + * Returns the total number of bytes written, or a ZSTD error code. + */ +size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, unsigned magicVariant) { + BYTE* op = (BYTE*)dst; + RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */, + dstSize_tooSmall, "Not enough room for skippable frame"); + RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, "Src size too large for skippable frame"); + RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, "Skippable frame magic number variant not supported"); + + MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant)); + MEM_writeLE32(op+4, (U32)srcSize); + ZSTD_memcpy(op+8, src, srcSize); + return srcSize + ZSTD_SKIPPABLEHEADERSIZE; +} + /* ZSTD_writeLastEmptyBlock() : * output an empty Block with end-of-frame mark to complete a frame * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h)) @@ -2725,6 +4054,7 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe cctx->externSeqStore.size = nbSeq; cctx->externSeqStore.capacity = nbSeq; cctx->externSeqStore.pos = 0; + cctx->externSeqStore.posInSequence = 0; return 0; } @@ -2754,11 +4084,12 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, if (!srcSize) return fhSize; /* do not generate an empty block if no input */ - if (!ZSTD_window_update(&ms->window, src, srcSize)) { + if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) { + ms->forceNonContiguous = 0; ms->nextToUpdate = ms->window.dictLimit; } if (cctx->appliedParams.ldmParams.enableLdm) { - ZSTD_window_update(&cctx->ldmState.window, src, srcSize); + ZSTD_window_update(&cctx->ldmState.window, src, srcSize, /* forceNonContiguous */ 0); } if (!frame) { @@ -2826,59 +4157,86 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, { const BYTE* ip = (const BYTE*) src; const BYTE* const iend = ip + srcSize; - - ZSTD_window_update(&ms->window, src, srcSize); - ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); - - if (params->ldmParams.enableLdm && ls != NULL) { - ZSTD_window_update(&ls->window, src, srcSize); - ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base); - } + int const loadLdmDict = params->ldmParams.enableLdm && ls != NULL; /* Assert that we the ms params match the params we're being given */ ZSTD_assertEqualCParams(params->cParams, ms->cParams); - if (srcSize <= HASH_READ_SIZE) return 0; + if (srcSize > ZSTD_CHUNKSIZE_MAX) { + /* Allow the dictionary to set indices up to exactly ZSTD_CURRENT_MAX. + * Dictionaries right at the edge will immediately trigger overflow + * correction, but I don't want to insert extra constraints here. + */ + U32 const maxDictSize = ZSTD_CURRENT_MAX - 1; + /* We must have cleared our windows when our source is this large. */ + assert(ZSTD_window_isEmpty(ms->window)); + if (loadLdmDict) + assert(ZSTD_window_isEmpty(ls->window)); + /* If the dictionary is too large, only load the suffix of the dictionary. */ + if (srcSize > maxDictSize) { + ip = iend - maxDictSize; + src = ip; + srcSize = maxDictSize; + } + } - while (iend - ip > HASH_READ_SIZE) { - size_t const remaining = (size_t)(iend - ip); - size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX); - const BYTE* const ichunk = ip + chunk; + DEBUGLOG(4, "ZSTD_loadDictionaryContent(): useRowMatchFinder=%d", (int)params->useRowMatchFinder); + ZSTD_window_update(&ms->window, src, srcSize, /* forceNonContiguous */ 0); + ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); + ms->forceNonContiguous = params->deterministicRefPrefix; - ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk); + if (loadLdmDict) { + ZSTD_window_update(&ls->window, src, srcSize, /* forceNonContiguous */ 0); + ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base); + } - if (params->ldmParams.enableLdm && ls != NULL) - ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams); + if (srcSize <= HASH_READ_SIZE) return 0; - switch(params->cParams.strategy) - { - case ZSTD_fast: - ZSTD_fillHashTable(ms, ichunk, dtlm); - break; - case ZSTD_dfast: - ZSTD_fillDoubleHashTable(ms, ichunk, dtlm); - break; + ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, iend); - case ZSTD_greedy: - case ZSTD_lazy: - case ZSTD_lazy2: - if (chunk >= HASH_READ_SIZE) - ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE); - break; + if (loadLdmDict) + ZSTD_ldm_fillHashTable(ls, ip, iend, ¶ms->ldmParams); - case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ - case ZSTD_btopt: - case ZSTD_btultra: - case ZSTD_btultra2: - if (chunk >= HASH_READ_SIZE) - ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk); - break; + switch(params->cParams.strategy) + { + case ZSTD_fast: + ZSTD_fillHashTable(ms, iend, dtlm); + break; + case ZSTD_dfast: + ZSTD_fillDoubleHashTable(ms, iend, dtlm); + break; - default: - assert(0); /* not possible : not a valid strategy id */ + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + assert(srcSize >= HASH_READ_SIZE); + if (ms->dedicatedDictSearch) { + assert(ms->chainTable != NULL); + ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, iend-HASH_READ_SIZE); + } else { + assert(params->useRowMatchFinder != ZSTD_urm_auto); + if (params->useRowMatchFinder == ZSTD_urm_enableRowMatchFinder) { + size_t const tagTableSize = ((size_t)1 << params->cParams.hashLog) * sizeof(U16); + ZSTD_memset(ms->tagTable, 0, tagTableSize); + ZSTD_row_update(ms, iend-HASH_READ_SIZE); + DEBUGLOG(4, "Using row-based hash table for lazy dict"); + } else { + ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE); + DEBUGLOG(4, "Using chain-based hash table for lazy dict"); + } } + break; + + case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + assert(srcSize >= HASH_READ_SIZE); + ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend); + break; - ip = ichunk; + default: + assert(0); /* not possible : not a valid strategy id */ } ms->nextToUpdate = (U32)(iend - ms->window.base); @@ -2887,22 +4245,28 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, /* Dictionaries that assign zero probability to symbols that show up causes problems - when FSE encoding. Refuse dictionaries that assign zero probability to symbols - that we may encounter during compression. - NOTE: This behavior is not standard and could be improved in the future. */ -static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) { + * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check + * and only dictionaries with 100% valid symbols can be assumed valid. + */ +static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) +{ U32 s; - RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols"); + if (dictMaxSymbolValue < maxSymbolValue) { + return FSE_repeat_check; + } for (s = 0; s <= maxSymbolValue; ++s) { - RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols"); + if (normalizedCounter[s] == 0) { + return FSE_repeat_check; + } } - return 0; + return FSE_repeat_valid; } size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, - short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize) { + short offcodeNCount[MaxOff+1]; + unsigned offcodeMaxValue = MaxOff; const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; dictPtr += 8; @@ -2924,16 +4288,16 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, } { unsigned offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); - /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ /* fill all offset symbols to avoid garbage at end of table */ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.offcodeCTable, offcodeNCount, MaxOff, offcodeLog, workspace, HUF_WORKSPACE_SIZE)), dictionary_corrupted, ""); + /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ dictPtr += offcodeHeaderSize; } @@ -2942,13 +4306,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); - /* Every match length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE)), dictionary_corrupted, ""); + bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML); dictPtr += matchlengthHeaderSize; } @@ -2957,13 +4320,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); - /* Every literal length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE)), dictionary_corrupted, ""); + bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL); dictPtr += litlengthHeaderSize; } @@ -2973,12 +4335,28 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, bs->rep[2] = MEM_readLE32(dictPtr+8); dictPtr += 12; + { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); + U32 offcodeMax = MaxOff; + if (dictContentSize <= ((U32)-1) - 128 KB) { + U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ + offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ + } + /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */ + bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)); + + /* All repCodes must be <= dictContentSize and != 0 */ + { U32 u; + for (u=0; u<3; u++) { + RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); + RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); + } } } + return dictPtr - (const BYTE*)dict; } /* Dictionary format : * See : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format + * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format */ /*! ZSTD_loadZstdDictionary() : * @return : dictID, or an error code @@ -2995,42 +4373,23 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, { const BYTE* dictPtr = (const BYTE*)dict; const BYTE* const dictEnd = dictPtr + dictSize; - short offcodeNCount[MaxOff+1]; - unsigned offcodeMaxValue = MaxOff; size_t dictID; size_t eSize; - ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog))); assert(dictSize >= 8); assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); - eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); + eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize); FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed"); dictPtr += eSize; - { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); - U32 offcodeMax = MaxOff; - if (dictContentSize <= ((U32)-1) - 128 KB) { - U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ - offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ - } - /* All offset values <= dictContentSize + 128 KB must be representable */ - FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), ""); - /* All repCodes must be <= dictContentSize and != 0*/ - { U32 u; - for (u=0; u<3; u++) { - RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); - RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); - } } - - bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; - bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; - bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; + { + size_t const dictContentSize = (size_t)(dictEnd - dictPtr); FORWARD_IF_ERROR(ZSTD_loadDictionaryContent( ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), ""); - return dictID; } + return dictID; } /** ZSTD_compress_insertDictionary() : @@ -3074,7 +4433,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, } #define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB) -#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6) +#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL) /*! ZSTD_compressBegin_internal() : * @return : 0, or an error code */ @@ -3086,6 +4445,10 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { + size_t const dictContentSize = cdict ? cdict->dictContentSize : dictSize; +#if ZSTD_TRACE + cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0; +#endif DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog); /* params are supposed to be fully validated at this point */ assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); @@ -3100,13 +4463,14 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); } - FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize, + FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, + dictContentSize, ZSTDcrp_makeClean, zbuff) , ""); { size_t const dictID = cdict ? ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, - cdict->dictContentSize, dictContentType, dtlm, + cdict->dictContentSize, cdict->dictContentType, dtlm, cctx->entropyWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, @@ -3115,6 +4479,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); assert(dictID <= UINT_MAX); cctx->dictID = (U32)dictID; + cctx->dictContentSize = dictContentSize; } return 0; } @@ -3143,8 +4508,8 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize) { - ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); + ZSTD_CCtx_params cctxParams; + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL); return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL /*cdict*/, @@ -3153,9 +4518,11 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); + ZSTD_CCtx_params cctxParams; + { + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel); + } DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered); @@ -3209,6 +4576,30 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) return op-ostart; } +void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize) +{ +#if ZSTD_TRACE + if (cctx->traceCtx && ZSTD_trace_compress_end != NULL) { + int const streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0 || cctx->appliedParams.nbWorkers > 0; + ZSTD_Trace trace; + ZSTD_memset(&trace, 0, sizeof(trace)); + trace.version = ZSTD_VERSION_NUMBER; + trace.streaming = streaming; + trace.dictionaryID = cctx->dictID; + trace.dictionarySize = cctx->dictContentSize; + trace.uncompressedSize = cctx->consumedSrcSize; + trace.compressedSize = cctx->producedCSize + extraCSize; + trace.params = &cctx->appliedParams; + trace.cctx = cctx; + ZSTD_trace_compress_end(cctx->traceCtx, &trace); + } + cctx->traceCtx = 0; +#else + (void)cctx; + (void)extraCSize; +#endif +} + size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) @@ -3231,26 +4622,10 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, (unsigned)cctx->pledgedSrcSizePlusOne-1, (unsigned)cctx->consumedSrcSize); } + ZSTD_CCtx_trace(cctx, endResult); return cSize + endResult; } - -static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - const ZSTD_parameters* params) -{ - ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params); - DEBUGLOG(4, "ZSTD_compress_internal"); - return ZSTD_compress_advanced_internal(cctx, - dst, dstCapacity, - src, srcSize, - dict, dictSize, - &cctxParams); -} - size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -3259,11 +4634,12 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, { DEBUGLOG(4, "ZSTD_compress_advanced"); FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); - return ZSTD_compress_internal(cctx, - dst, dstCapacity, - src, srcSize, - dict, dictSize, - ¶ms); + ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, ZSTD_NO_CLEVEL); + return ZSTD_compress_advanced_internal(cctx, + dst, dstCapacity, + src, srcSize, + dict, dictSize, + &cctx->simpleApiParams); } /* Internal */ @@ -3287,11 +4663,13 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0); - ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); + { + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); + assert(params.fParams.contentSizeFlag == 1); + ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel); + } DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize); - assert(params.fParams.contentSizeFlag == 1); - return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams); + return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctx->simpleApiParams); } size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, @@ -3309,10 +4687,17 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, int compressionLevel) { size_t result; +#if ZSTD_COMPRESS_HEAPMODE + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed"); + result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel); + ZSTD_freeCCtx(cctx); +#else ZSTD_CCtx ctxBody; ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem); result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel); ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */ +#endif return result; } @@ -3328,14 +4713,17 @@ size_t ZSTD_estimateCDictSize_advanced( DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict)); return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) - + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) + /* enableDedicatedDictSearch == 1 ensures that CDict estimation will not be too small + * in case we are using DDS with row-hash. */ + + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_urm_auto, &cParams), + /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *)))); } size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); } @@ -3353,20 +4741,22 @@ static size_t ZSTD_initCDict_internal( const void* dictBuffer, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams) + ZSTD_CCtx_params params) { DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); - assert(!ZSTD_checkCParams(cParams)); - cdict->matchState.cParams = cParams; + assert(!ZSTD_checkCParams(params.cParams)); + cdict->matchState.cParams = params.cParams; + cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch; if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { cdict->dictContent = dictBuffer; } else { void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*))); RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!"); cdict->dictContent = internalBuffer; - memcpy(internalBuffer, dictBuffer, dictSize); + ZSTD_memcpy(internalBuffer, dictBuffer, dictSize); } cdict->dictContentSize = dictSize; + cdict->dictContentType = dictContentType; cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE); @@ -3376,18 +4766,16 @@ static size_t ZSTD_initCDict_internal( FORWARD_IF_ERROR(ZSTD_reset_matchState( &cdict->matchState, &cdict->workspace, - &cParams, + ¶ms.cParams, + params.useRowMatchFinder, ZSTDcrp_makeClean, ZSTDirp_reset, ZSTD_resetTarget_CDict), ""); /* (Maybe) load the dictionary * Skips loading the dictionary if it is < 8 bytes. */ - { ZSTD_CCtx_params params; - memset(¶ms, 0, sizeof(params)); - params.compressionLevel = ZSTD_CLEVEL_DEFAULT; + { params.compressionLevel = ZSTD_CLEVEL_DEFAULT; params.fParams.contentSizeFlag = 1; - params.cParams = cParams; { size_t const dictID = ZSTD_compress_insertDictionary( &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace, ¶ms, cdict->dictContent, cdict->dictContentSize, @@ -3401,66 +4789,129 @@ static size_t ZSTD_initCDict_internal( return 0; } -ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, +static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams, ZSTD_customMem customMem) + ZSTD_compressionParameters cParams, + ZSTD_useRowMatchFinderMode_e useRowMatchFinder, + U32 enableDedicatedDictSearch, + ZSTD_customMem customMem) { - DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType); - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; { size_t const workspaceSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + - ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) + + ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, enableDedicatedDictSearch, /* forCCtx */ 0) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))); - void* const workspace = ZSTD_malloc(workspaceSize, customMem); + void* const workspace = ZSTD_customMalloc(workspaceSize, customMem); ZSTD_cwksp ws; ZSTD_CDict* cdict; if (!workspace) { - ZSTD_free(workspace, customMem); + ZSTD_customFree(workspace, customMem); return NULL; } - ZSTD_cwksp_init(&ws, workspace, workspaceSize); + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc); cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); assert(cdict != NULL); ZSTD_cwksp_move(&cdict->workspace, &ws); cdict->customMem = customMem; - cdict->compressionLevel = 0; /* signals advanced API usage */ + cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ + cdict->useRowMatchFinder = useRowMatchFinder; + return cdict; + } +} + +ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params cctxParams; + ZSTD_memset(&cctxParams, 0, sizeof(cctxParams)); + ZSTD_CCtxParams_init(&cctxParams, 0); + cctxParams.cParams = cParams; + cctxParams.customMem = customMem; + return ZSTD_createCDict_advanced2( + dictBuffer, dictSize, + dictLoadMethod, dictContentType, + &cctxParams, customMem); +} + +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* originalCctxParams, + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params cctxParams = *originalCctxParams; + ZSTD_compressionParameters cParams; + ZSTD_CDict* cdict; + + DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType); + if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + + if (cctxParams.enableDedicatedDictSearch) { + cParams = ZSTD_dedicatedDictSearch_getCParams( + cctxParams.compressionLevel, dictSize); + ZSTD_overrideCParams(&cParams, &cctxParams.cParams); + } else { + cParams = ZSTD_getCParamsFromCCtxParams( + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + } - if (ZSTD_isError( ZSTD_initCDict_internal(cdict, - dictBuffer, dictSize, - dictLoadMethod, dictContentType, - cParams) )) { - ZSTD_freeCDict(cdict); - return NULL; - } + if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) { + /* Fall back to non-DDSS params */ + cctxParams.enableDedicatedDictSearch = 0; + cParams = ZSTD_getCParamsFromCCtxParams( + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + } - return cdict; + DEBUGLOG(3, "ZSTD_createCDict_advanced2: DDS: %u", cctxParams.enableDedicatedDictSearch); + cctxParams.cParams = cParams; + cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); + + cdict = ZSTD_createCDict_advanced_internal(dictSize, + dictLoadMethod, cctxParams.cParams, + cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch, + customMem); + + if (ZSTD_isError( ZSTD_initCDict_internal(cdict, + dict, dictSize, + dictLoadMethod, dictContentType, + cctxParams) )) { + ZSTD_freeCDict(cdict); + return NULL; } + + return cdict; } ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); if (cdict) - cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; } ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - return ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); + if (cdict) + cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + return cdict; } size_t ZSTD_freeCDict(ZSTD_CDict* cdict) @@ -3470,7 +4921,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict) int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict); ZSTD_cwksp_free(&cdict->workspace, cMem); if (!cdictInWorkspace) { - ZSTD_free(cdict, cMem); + ZSTD_customFree(cdict, cMem); } return 0; } @@ -3496,19 +4947,22 @@ const ZSTD_CDict* ZSTD_initStaticCDict( ZSTD_dictContentType_e dictContentType, ZSTD_compressionParameters cParams) { - size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0); + ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_urm_auto, &cParams); + /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */ + size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0); size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))) + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + matchStateSize; ZSTD_CDict* cdict; + ZSTD_CCtx_params params; if ((size_t)workspace & 7) return NULL; /* 8-aligned */ { ZSTD_cwksp ws; - ZSTD_cwksp_init(&ws, workspace, workspaceSize); + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc); cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); if (cdict == NULL) return NULL; ZSTD_cwksp_move(&cdict->workspace, &ws); @@ -3518,10 +4972,15 @@ const ZSTD_CDict* ZSTD_initStaticCDict( (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize)); if (workspaceSize < neededSize) return NULL; + ZSTD_CCtxParams_init(¶ms, 0); + params.cParams = cParams; + params.useRowMatchFinder = useRowMatchFinder; + cdict->useRowMatchFinder = useRowMatchFinder; + if (ZSTD_isError( ZSTD_initCDict_internal(cdict, dict, dictSize, dictLoadMethod, dictContentType, - cParams) )) + params) )) return NULL; return cdict; @@ -3533,61 +4992,98 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) return cdict->matchState.cParams; } -/* ZSTD_compressBegin_usingCDict_advanced() : - * cdict must be != NULL */ -size_t ZSTD_compressBegin_usingCDict_advanced( +/*! ZSTD_getDictID_fromCDict() : + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict) +{ + if (cdict==NULL) return 0; + return cdict->dictID; +} + +/* ZSTD_compressBegin_usingCDict_internal() : + * Implementation of various ZSTD_compressBegin_usingCDict* functions. + */ +static size_t ZSTD_compressBegin_usingCDict_internal( ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) { - DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced"); + ZSTD_CCtx_params cctxParams; + DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_internal"); RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); - { ZSTD_CCtx_params params = cctx->requestedParams; + /* Initialize the cctxParams from the cdict */ + { + ZSTD_parameters params; + params.fParams = fParams; params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0 ) - && (params.attachDictPref != ZSTD_dictForceLoad) ? + || cdict->compressionLevel == 0 ) ? ZSTD_getCParamsFromCDict(cdict) : ZSTD_getCParams(cdict->compressionLevel, pledgedSrcSize, cdict->dictContentSize); - /* Increase window log to fit the entire dictionary and source if the - * source size is known. Limit the increase to 19, which is the - * window log for compression level 1 with the largest source size. - */ - if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { - U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); - U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; - params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog); - } - params.fParams = fParams; - return ZSTD_compressBegin_internal(cctx, - NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, - cdict, - ¶ms, pledgedSrcSize, - ZSTDb_not_buffered); + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel); } + /* Increase window log to fit the entire dictionary and source if the + * source size is known. Limit the increase to 19, which is the + * window log for compression level 1 with the largest source size. + */ + if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { + U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); + U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; + cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog); + } + return ZSTD_compressBegin_internal(cctx, + NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, + cdict, + &cctxParams, pledgedSrcSize, + ZSTDb_not_buffered); +} + + +/* ZSTD_compressBegin_usingCDict_advanced() : + * This function is DEPRECATED. + * cdict must be != NULL */ +size_t ZSTD_compressBegin_usingCDict_advanced( + ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, + ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) +{ + return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, pledgedSrcSize); } /* ZSTD_compressBegin_usingCDict() : - * pledgedSrcSize=0 means "unknown" - * if pledgedSrcSize>0, it will enable contentSizeFlag */ + * cdict must be != NULL */ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) { ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag); - return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); + return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); } -size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, +/*! ZSTD_compress_usingCDict_internal(): + * Implementation of various ZSTD_compress_usingCDict* functions. + */ +static size_t ZSTD_compress_usingCDict_internal(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) { - FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */ + FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */ return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); } +/*! ZSTD_compress_usingCDict_advanced(): + * This function is DEPRECATED. + */ +size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) +{ + return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams); +} + /*! ZSTD_compress_usingCDict() : * Compression using a digested Dictionary. * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. @@ -3599,7 +5095,7 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) { ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams); + return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams); } @@ -3640,32 +5136,12 @@ size_t ZSTD_CStreamOutSize(void) return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; } -static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx, - const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType, - const ZSTD_CDict* const cdict, - ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize) +static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize) { - DEBUGLOG(4, "ZSTD_resetCStream_internal"); - /* Finalize the compression parameters */ - params.cParams = ZSTD_getCParamsFromCCtxParams(¶ms, pledgedSrcSize, dictSize); - /* params are supposed to be fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); - assert(!((dict) && (cdict))); /* either dict or cdict, not both */ - - FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, - dict, dictSize, dictContentType, ZSTD_dtlm_fast, - cdict, - ¶ms, pledgedSrcSize, - ZSTDb_buffered) , ""); - - cctx->inToCompress = 0; - cctx->inBuffPos = 0; - cctx->inBuffTarget = cctx->blockSize - + (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */ - cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0; - cctx->streamStage = zcss_load; - cctx->frameEnded = 0; - return 0; /* ready to go */ + if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) + return ZSTD_cpm_attachDict; + else + return ZSTD_cpm_noAttachDict; } /* ZSTD_resetCStream(): @@ -3749,7 +5225,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); - zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, ¶ms); + ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms); FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); return 0; } @@ -3815,12 +5291,17 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, /* check expectations */ DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode); - assert(zcs->inBuff != NULL); - assert(zcs->inBuffSize > 0); - assert(zcs->outBuff != NULL); - assert(zcs->outBuffSize > 0); + if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) { + assert(zcs->inBuff != NULL); + assert(zcs->inBuffSize > 0); + } + if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) { + assert(zcs->outBuff != NULL); + assert(zcs->outBuffSize > 0); + } assert(output->pos <= output->size); assert(input->pos <= input->size); + assert((U32)flushMode <= (U32)ZSTD_e_end); while (someMoreWork) { switch(zcs->streamStage) @@ -3830,7 +5311,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, case zcss_load: if ( (flushMode == ZSTD_e_end) - && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */ + && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip) /* Enough output space */ + || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) /* OR we are allowed to return dstSizeTooSmall */ && (zcs->inBuffPos == 0) ) { /* shortcut to compression pass directly into output buffer */ size_t const cSize = ZSTD_compressEnd(zcs, @@ -3843,8 +5325,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); someMoreWork = 0; break; } - /* complete loading into inBuffer */ - { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; + /* complete loading into inBuffer in buffered mode */ + if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) { + size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; size_t const loaded = ZSTD_limitCopy( zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip); @@ -3864,31 +5347,49 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, } /* compress current block (note : this stage cannot be stopped in the middle) */ DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode); - { void* cDst; + { int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered); + void* cDst; size_t cSize; - size_t const iSize = zcs->inBuffPos - zcs->inToCompress; size_t oSize = oend-op; - unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend); - if (oSize >= ZSTD_compressBound(iSize)) + size_t const iSize = inputBuffered + ? zcs->inBuffPos - zcs->inToCompress + : MIN((size_t)(iend - ip), zcs->blockSize); + if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) cDst = op; /* compress into output buffer, to skip flush stage */ else cDst = zcs->outBuff, oSize = zcs->outBuffSize; - cSize = lastBlock ? - ZSTD_compressEnd(zcs, cDst, oSize, - zcs->inBuff + zcs->inToCompress, iSize) : - ZSTD_compressContinue(zcs, cDst, oSize, - zcs->inBuff + zcs->inToCompress, iSize); - FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); - zcs->frameEnded = lastBlock; - /* prepare next block */ - zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; - if (zcs->inBuffTarget > zcs->inBuffSize) - zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; - DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", - (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); - if (!lastBlock) - assert(zcs->inBuffTarget <= zcs->inBuffSize); - zcs->inToCompress = zcs->inBuffPos; + if (inputBuffered) { + unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend); + cSize = lastBlock ? + ZSTD_compressEnd(zcs, cDst, oSize, + zcs->inBuff + zcs->inToCompress, iSize) : + ZSTD_compressContinue(zcs, cDst, oSize, + zcs->inBuff + zcs->inToCompress, iSize); + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + zcs->frameEnded = lastBlock; + /* prepare next block */ + zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; + if (zcs->inBuffTarget > zcs->inBuffSize) + zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; + DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", + (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); + if (!lastBlock) + assert(zcs->inBuffTarget <= zcs->inBuffSize); + zcs->inToCompress = zcs->inBuffPos; + } else { + unsigned const lastBlock = (ip + iSize == iend); + assert(flushMode == ZSTD_e_end /* Already validated */); + cSize = lastBlock ? + ZSTD_compressEnd(zcs, cDst, oSize, ip, iSize) : + ZSTD_compressContinue(zcs, cDst, oSize, ip, iSize); + /* Consume the input prior to error checking to mirror buffered mode. */ + if (iSize > 0) + ip += iSize; + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + zcs->frameEnded = lastBlock; + if (lastBlock) + assert(ip == iend); + } if (cDst == op) { /* no need to flush */ op += cSize; if (zcs->frameEnded) { @@ -3905,6 +5406,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, /* fall-through */ case zcss_flush: DEBUGLOG(5, "flush stage"); + assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered); { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op), zcs->outBuff + zcs->outBuffFlushedSize, toFlush); @@ -3959,6 +5461,135 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf return ZSTD_nextInputSizeHint_MTorST(zcs); } +/* After a compression call set the expected input/output buffer. + * This is validated at the start of the next compression call. + */ +static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input) +{ + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + cctx->expectedInBuffer = *input; + } + if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) { + cctx->expectedOutBufferSize = output->size - output->pos; + } +} + +/* Validate that the input/output buffers match the expectations set by + * ZSTD_setBufferExpectations. + */ +static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx, + ZSTD_outBuffer const* output, + ZSTD_inBuffer const* input, + ZSTD_EndDirective endOp) +{ + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + ZSTD_inBuffer const expect = cctx->expectedInBuffer; + if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size) + RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!"); + if (endOp != ZSTD_e_end) + RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!"); + } + if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) { + size_t const outBufferSize = output->size - output->pos; + if (cctx->expectedOutBufferSize != outBufferSize) + RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!"); + } + return 0; +} + +static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, + ZSTD_EndDirective endOp, + size_t inSize) { + ZSTD_CCtx_params params = cctx->requestedParams; + ZSTD_prefixDict const prefixDict = cctx->prefixDict; + FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ + ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ + assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ + if (cctx->cdict && !cctx->localDict.cdict) { + /* Let the cdict's compression level take priority over the requested params. + * But do not take the cdict's compression level if the "cdict" is actually a localDict + * generated from ZSTD_initLocalDict(). + */ + params.compressionLevel = cctx->cdict->compressionLevel; + } + DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); + if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-fix pledgedSrcSize */ + { + size_t const dictSize = prefixDict.dict + ? prefixDict.dictSize + : (cctx->cdict ? cctx->cdict->dictContentSize : 0); + ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1); + params.cParams = ZSTD_getCParamsFromCCtxParams( + ¶ms, cctx->pledgedSrcSizePlusOne-1, + dictSize, mode); + } + + if (ZSTD_CParams_shouldEnableLdm(¶ms.cParams)) { + /* Enable LDM by default for optimal parser and window size >= 128MB */ + DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)"); + params.ldmParams.enableLdm = 1; + } + + if (ZSTD_CParams_useBlockSplitter(¶ms.cParams)) { + DEBUGLOG(4, "Block splitter enabled by default (window size >= 128K, strategy >= btopt)"); + params.splitBlocks = 1; + } + + params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, ¶ms.cParams); + +#ifdef ZSTD_MULTITHREAD + if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { + params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ + } + if (params.nbWorkers > 0) { +#if ZSTD_TRACE + cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0; +#endif + /* mt context creation */ + if (cctx->mtctx == NULL) { + DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", + params.nbWorkers); + cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool); + RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); + } + /* mt compression */ + DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); + FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( + cctx->mtctx, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, + cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); + cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0; + cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize; + cctx->consumedSrcSize = 0; + cctx->producedCSize = 0; + cctx->streamStage = zcss_load; + cctx->appliedParams = params; + } else +#endif + { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1; + assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast, + cctx->cdict, + ¶ms, pledgedSrcSize, + ZSTDb_buffered) , ""); + assert(cctx->appliedParams.nbWorkers == 0); + cctx->inToCompress = 0; + cctx->inBuffPos = 0; + if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) { + /* for small input: avoid automatic flush on reaching end of block, since + * it would require to add a 3-bytes null block to end frame + */ + cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize); + } else { + cctx->inBuffTarget = 0; + } + cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0; + cctx->streamStage = zcss_load; + cctx->frameEnded = 0; + } + return 0; +} size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, ZSTD_outBuffer* output, @@ -3967,82 +5598,69 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, { DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); /* check conditions */ - RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer"); - RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer"); - assert(cctx!=NULL); + RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer"); + RETURN_ERROR_IF(input->pos > input->size, srcSize_wrong, "invalid input buffer"); + RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective"); + assert(cctx != NULL); /* transparent initialization stage */ if (cctx->streamStage == zcss_init) { - ZSTD_CCtx_params params = cctx->requestedParams; - ZSTD_prefixDict const prefixDict = cctx->prefixDict; - FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ - memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ - assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ - DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); - if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */ - params.cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/); - - -#ifdef ZSTD_MULTITHREAD - if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { - params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ - } - if (params.nbWorkers > 0) { - /* mt context creation */ - if (cctx->mtctx == NULL) { - DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", - params.nbWorkers); - cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem); - RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); - } - /* mt compression */ - DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); - FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( - cctx->mtctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); - cctx->streamStage = zcss_load; - cctx->appliedParams.nbWorkers = params.nbWorkers; - } else -#endif - { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, - params, cctx->pledgedSrcSizePlusOne-1) , ""); - assert(cctx->streamStage == zcss_load); - assert(cctx->appliedParams.nbWorkers == 0); - } } + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, input->size), "CompressStream2 initialization failed"); + ZSTD_setBufferExpectations(cctx, output, input); /* Set initial buffer expectations now that we've initialized */ + } /* end of transparent initialization stage */ + FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers"); /* compression stage */ #ifdef ZSTD_MULTITHREAD if (cctx->appliedParams.nbWorkers > 0) { - int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end); size_t flushMin; - assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */); if (cctx->cParamsChanged) { ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams); cctx->cParamsChanged = 0; } - do { + for (;;) { + size_t const ipos = input->pos; + size_t const opos = output->pos; flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); + cctx->consumedSrcSize += (U64)(input->pos - ipos); + cctx->producedCSize += (U64)(output->pos - opos); if ( ZSTD_isError(flushMin) || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ + if (flushMin == 0) + ZSTD_CCtx_trace(cctx, 0); ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); } FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed"); - } while (forceMaxProgress && flushMin != 0 && output->pos < output->size); + + if (endOp == ZSTD_e_continue) { + /* We only require some progress with ZSTD_e_continue, not maximal progress. + * We're done if we've consumed or produced any bytes, or either buffer is + * full. + */ + if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size) + break; + } else { + assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end); + /* We require maximal progress. We're done when the flush is complete or the + * output buffer is full. + */ + if (flushMin == 0 || output->pos == output->size) + break; + } + } DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); /* Either we don't require maximum forward progress, we've finished the * flush, or we are out of output space. */ - assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size); + assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size); + ZSTD_setBufferExpectations(cctx, output, input); return flushMin; } #endif FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , ""); DEBUGLOG(5, "completed ZSTD_compressStream2"); + ZSTD_setBufferExpectations(cctx, output, input); return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ } @@ -4065,14 +5683,22 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) { + ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode; + ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode; DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize); ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); + /* Enable stable input/output buffers. */ + cctx->requestedParams.inBufferMode = ZSTD_bm_stable; + cctx->requestedParams.outBufferMode = ZSTD_bm_stable; { size_t oPos = 0; size_t iPos = 0; size_t const result = ZSTD_compressStream2_simpleArgs(cctx, dst, dstCapacity, &oPos, src, srcSize, &iPos, ZSTD_e_end); + /* Reset to the original values. */ + cctx->requestedParams.inBufferMode = originalInBufferMode; + cctx->requestedParams.outBufferMode = originalOutBufferMode; FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed"); if (result != 0) { /* compression not completed, due to lack of output space */ assert(oPos == dstCapacity); @@ -4083,6 +5709,409 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, } } +typedef struct { + U32 idx; /* Index in array of ZSTD_Sequence */ + U32 posInSequence; /* Position within sequence at idx */ + size_t posInSrc; /* Number of bytes given by sequences provided so far */ +} ZSTD_sequencePosition; + +/* Returns a ZSTD error code if sequence is not valid */ +static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength, + size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) { + size_t offsetBound; + U32 windowSize = 1 << windowLog; + /* posInSrc represents the amount of data the the decoder would decode up to this point. + * As long as the amount of data decoded is less than or equal to window size, offsets may be + * larger than the total length of output decoded in order to reference the dict, even larger than + * window size. After output surpasses windowSize, we're limited to windowSize offsets again. + */ + offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize; + RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!"); + RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small"); + return 0; +} + +/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */ +static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) { + U32 offCode = rawOffset + ZSTD_REP_MOVE; + U32 repCode = 0; + + if (!ll0 && rawOffset == rep[0]) { + repCode = 1; + } else if (rawOffset == rep[1]) { + repCode = 2 - ll0; + } else if (rawOffset == rep[2]) { + repCode = 3 - ll0; + } else if (ll0 && rawOffset == rep[0] - 1) { + repCode = 3; + } + if (repCode) { + /* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */ + offCode = repCode - 1; + } + return offCode; +} + +/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of + * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter. + */ +static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize) { + U32 idx = seqPos->idx; + BYTE const* ip = (BYTE const*)(src); + const BYTE* const iend = ip + blockSize; + repcodes_t updatedRepcodes; + U32 dictSize; + U32 litLength; + U32 matchLength; + U32 ll0; + U32 offCode; + + if (cctx->cdict) { + dictSize = (U32)cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = (U32)cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) { + litLength = inSeqs[idx].litLength; + matchLength = inSeqs[idx].matchLength; + ll0 = litLength == 0; + offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0); + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0); + + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength); + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; + FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, + cctx->appliedParams.cParams.minMatch), + "Sequence validation failed"); + } + RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH); + ip += matchLength + litLength; + } + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + + if (inSeqs[idx].litLength) { + DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength); + ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength); + ip += inSeqs[idx].litLength; + seqPos->posInSrc += inSeqs[idx].litLength; + } + RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!"); + seqPos->idx = idx+1; + return 0; +} + +/* Returns the number of bytes to move the current read position back by. Only non-zero + * if we ended up splitting a sequence. Otherwise, it may return a ZSTD error if something + * went wrong. + * + * This function will attempt to scan through blockSize bytes represented by the sequences + * in inSeqs, storing any (partial) sequences. + * + * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to + * avoid splitting a match, or to avoid splitting a match such that it would produce a match + * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block. + */ +static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize) { + U32 idx = seqPos->idx; + U32 startPosInSequence = seqPos->posInSequence; + U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize; + size_t dictSize; + BYTE const* ip = (BYTE const*)(src); + BYTE const* iend = ip + blockSize; /* May be adjusted if we decide to process fewer than blockSize bytes */ + repcodes_t updatedRepcodes; + U32 bytesAdjustment = 0; + U32 finalMatchSplit = 0; + U32 litLength; + U32 matchLength; + U32 rawOffset; + U32 offCode; + + if (cctx->cdict) { + dictSize = cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + DEBUGLOG(5, "ZSTD_copySequencesToSeqStore: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize); + DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) { + const ZSTD_Sequence currSeq = inSeqs[idx]; + litLength = currSeq.litLength; + matchLength = currSeq.matchLength; + rawOffset = currSeq.offset; + + /* Modify the sequence depending on where endPosInSequence lies */ + if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) { + if (startPosInSequence >= litLength) { + startPosInSequence -= litLength; + litLength = 0; + matchLength -= startPosInSequence; + } else { + litLength -= startPosInSequence; + } + /* Move to the next sequence */ + endPosInSequence -= currSeq.litLength + currSeq.matchLength; + startPosInSequence = 0; + idx++; + } else { + /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence + does not reach the end of the match. So, we have to split the sequence */ + DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u", + currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence); + if (endPosInSequence > litLength) { + U32 firstHalfMatchLength; + litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence; + firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength; + if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) { + /* Only ever split the match if it is larger than the block size */ + U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence; + if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) { + /* Move the endPosInSequence backward so that it creates match of minMatch length */ + endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength; + bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength; + firstHalfMatchLength -= bytesAdjustment; + } + matchLength = firstHalfMatchLength; + /* Flag that we split the last match - after storing the sequence, exit the loop, + but keep the value of endPosInSequence */ + finalMatchSplit = 1; + } else { + /* Move the position in sequence backwards so that we don't split match, and break to store + * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence + * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so + * would cause the first half of the match to be too small + */ + bytesAdjustment = endPosInSequence - currSeq.litLength; + endPosInSequence = currSeq.litLength; + break; + } + } else { + /* This sequence ends inside the literals, break to store the last literals */ + break; + } + } + /* Check if this offset can be represented with a repcode */ + { U32 ll0 = (litLength == 0); + offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0); + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0); + } + + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; + FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, + cctx->appliedParams.cParams.minMatch), + "Sequence validation failed"); + } + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength); + RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH); + ip += matchLength + litLength; + } + DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); + assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength); + seqPos->idx = idx; + seqPos->posInSequence = endPosInSequence; + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + + iend -= bytesAdjustment; + if (ip != iend) { + /* Store any last literals */ + U32 lastLLSize = (U32)(iend - ip); + assert(ip <= iend); + DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize); + ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize); + seqPos->posInSrc += lastLLSize; + } + + return bytesAdjustment; +} + +typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize); +static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) { + ZSTD_sequenceCopier sequenceCopier = NULL; + assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode)); + if (mode == ZSTD_sf_explicitBlockDelimiters) { + return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; + } else if (mode == ZSTD_sf_noBlockDelimiters) { + return ZSTD_copySequencesToSeqStoreNoBlockDelim; + } + assert(sequenceCopier != NULL); + return sequenceCopier; +} + +/* Compress, block-by-block, all of the sequences given. + * + * Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error. + */ +static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize) { + size_t cSize = 0; + U32 lastBlock; + size_t blockSize; + size_t compressedSeqsSize; + size_t remaining = srcSize; + ZSTD_sequencePosition seqPos = {0, 0, 0}; + + BYTE const* ip = (BYTE const*)src; + BYTE* op = (BYTE*)dst; + ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters); + + DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize); + /* Special case: empty frame */ + if (remaining == 0) { + U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header"); + MEM_writeLE32(op, cBlockHeader24); + op += ZSTD_blockHeaderSize; + dstCapacity -= ZSTD_blockHeaderSize; + cSize += ZSTD_blockHeaderSize; + } + + while (remaining) { + size_t cBlockSize; + size_t additionalByteAdjustment; + lastBlock = remaining <= cctx->blockSize; + blockSize = lastBlock ? (U32)remaining : (U32)cctx->blockSize; + ZSTD_resetSeqStore(&cctx->seqStore); + DEBUGLOG(4, "Working on new block. Blocksize: %zu", blockSize); + + additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize); + FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy"); + blockSize -= additionalByteAdjustment; + + /* If blocks are too small, emit as a nocompress block */ + if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { + cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed"); + DEBUGLOG(4, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize); + cSize += cBlockSize; + ip += blockSize; + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + continue; + } + + compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore, + &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, + &cctx->appliedParams, + op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, + blockSize, + cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + cctx->bmi2); + FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); + DEBUGLOG(4, "Compressed sequences size: %zu", compressedSeqsSize); + + if (!cctx->isFirstBlock && + ZSTD_maybeRLE(&cctx->seqStore) && + ZSTD_isRLE((BYTE const*)src, srcSize)) { + /* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + compressedSeqsSize = 1; + } + + if (compressedSeqsSize == 0) { + /* ZSTD_noCompressBlock writes the block header as well */ + cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed"); + DEBUGLOG(4, "Writing out nocompress block, size: %zu", cBlockSize); + } else if (compressedSeqsSize == 1) { + cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "RLE compress block failed"); + DEBUGLOG(4, "Writing out RLE block, size: %zu", cBlockSize); + } else { + U32 cBlockHeader; + /* Error checking and repcodes update */ + ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState); + if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + /* Write block header into beginning of block*/ + cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3); + MEM_writeLE24(op, cBlockHeader); + cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize; + DEBUGLOG(4, "Writing out compressed block, size: %zu", cBlockSize); + } + + cSize += cBlockSize; + DEBUGLOG(4, "cSize running total: %zu", cSize); + + if (lastBlock) { + break; + } else { + ip += blockSize; + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + cctx->isFirstBlock = 0; + } + } + + return cSize; +} + +size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize) { + BYTE* op = (BYTE*)dst; + size_t cSize = 0; + size_t compressedBlocksSize = 0; + size_t frameHeaderSize = 0; + + /* Transparent initialization stage, same as compressStream2() */ + DEBUGLOG(3, "ZSTD_compressSequences()"); + assert(cctx != NULL); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); + /* Begin writing output, starting with frame header */ + frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID); + op += frameHeaderSize; + dstCapacity -= frameHeaderSize; + cSize += frameHeaderSize; + if (cctx->appliedParams.fParams.checksumFlag && srcSize) { + XXH64_update(&cctx->xxhState, src, srcSize); + } + /* cSize includes block header size and compressed sequences size */ + compressedBlocksSize = ZSTD_compressSequences_internal(cctx, + op, dstCapacity, + inSeqs, inSeqsSize, + src, srcSize); + FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!"); + cSize += compressedBlocksSize; + dstCapacity -= compressedBlocksSize; + + if (cctx->appliedParams.fParams.checksumFlag) { + U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum"); + DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum); + MEM_writeLE32((char*)dst + cSize, checksum); + cSize += 4; + } + + DEBUGLOG(3, "Final compressed size: %zu", cSize); + return cSize; +} + /*====== Finalize ======*/ /*! ZSTD_flushStream() : @@ -4115,6 +6144,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) #define ZSTD_MAX_CLEVEL 22 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } +int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; } static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { { /* "default" - for any srcSize > 256 KB */ @@ -4223,25 +6253,110 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV }, }; +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) +{ + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); + switch (cParams.strategy) { + case ZSTD_fast: + case ZSTD_dfast: + break; + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG; + break; + case ZSTD_btlazy2: + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + break; + } + return cParams; +} + +static int ZSTD_dedicatedDictSearch_isSupported( + ZSTD_compressionParameters const* cParams) +{ + return (cParams->strategy >= ZSTD_greedy) + && (cParams->strategy <= ZSTD_lazy2) + && (cParams->hashLog > cParams->chainLog) + && (cParams->chainLog <= 24); +} + +/** + * Reverses the adjustment applied to cparams when enabling dedicated dict + * search. This is used to recover the params set to be used in the working + * context. (Otherwise, those tables would also grow.) + */ +static void ZSTD_dedicatedDictSearch_revertCParams( + ZSTD_compressionParameters* cParams) { + switch (cParams->strategy) { + case ZSTD_fast: + case ZSTD_dfast: + break; + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG; + if (cParams->hashLog < ZSTD_HASHLOG_MIN) { + cParams->hashLog = ZSTD_HASHLOG_MIN; + } + break; + case ZSTD_btlazy2: + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + break; + } +} + +static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) +{ + switch (mode) { + case ZSTD_cpm_unknown: + case ZSTD_cpm_noAttachDict: + case ZSTD_cpm_createCDict: + break; + case ZSTD_cpm_attachDict: + dictSize = 0; + break; + default: + assert(0); + break; + } + { int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; + size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; + return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; + } +} + /*! ZSTD_getCParams_internal() : * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. - * Use dictSize == 0 for unknown or unused. */ -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) + * Use dictSize == 0 for unknown or unused. + * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */ +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { - int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; - size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; - U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; + U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode); U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); - int row = compressionLevel; + int row; DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel); + + /* row */ if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ - if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ - if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; + else if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ + else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; + else row = compressionLevel; + { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; - if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */ + DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)cp.strategy); + /* acceleration factor */ + if (compressionLevel < 0) { + int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel); + cp.targetLength = (unsigned)(-clampedCompressionLevel); + } /* refine parameters based on srcSize & dictSize */ - return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); + return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode); } } @@ -4251,18 +6366,18 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); + return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); } /*! ZSTD_getParams() : * same idea as ZSTD_getCParams() * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). * Fields of `ZSTD_frameParameters` are set to default values */ -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { ZSTD_parameters params; - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); - memset(¶ms, 0, sizeof(params)); + ZSTD_memset(¶ms, 0, sizeof(params)); params.cParams = cParams; params.fParams.contentSizeFlag = 1; return params; @@ -4274,5 +6389,5 @@ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned lo * Fields of `ZSTD_frameParameters` are set to default values */ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize); + return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); } diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index db73f6ce21f..3b04fd09f64 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -28,7 +28,6 @@ extern "C" { #endif - /*-************************************* * Constants ***************************************/ @@ -64,7 +63,7 @@ typedef struct { } ZSTD_localDict; typedef struct { - U32 CTable[HUF_CTABLE_SIZE_U32(255)]; + HUF_CElt CTable[HUF_CTABLE_SIZE_U32(255)]; HUF_repeat repeatMode; } ZSTD_hufCTables_t; @@ -82,11 +81,75 @@ typedef struct { ZSTD_fseCTables_t fse; } ZSTD_entropyCTables_t; +/*********************************************** +* Entropy buffer statistics structs and funcs * +***********************************************/ +/** ZSTD_hufCTablesMetadata_t : + * Stores Literals Block Type for a super-block in hType, and + * huffman tree description in hufDesBuffer. + * hufDesSize refers to the size of huffman tree description in bytes. + * This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */ typedef struct { - U32 off; - U32 len; + symbolEncodingType_e hType; + BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE]; + size_t hufDesSize; +} ZSTD_hufCTablesMetadata_t; + +/** ZSTD_fseCTablesMetadata_t : + * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and + * fse tables in fseTablesBuffer. + * fseTablesSize refers to the size of fse tables in bytes. + * This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */ +typedef struct { + symbolEncodingType_e llType; + symbolEncodingType_e ofType; + symbolEncodingType_e mlType; + BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE]; + size_t fseTablesSize; + size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */ +} ZSTD_fseCTablesMetadata_t; + +typedef struct { + ZSTD_hufCTablesMetadata_t hufMetadata; + ZSTD_fseCTablesMetadata_t fseMetadata; +} ZSTD_entropyCTablesMetadata_t; + +/** ZSTD_buildBlockEntropyStats() : + * Builds entropy for the block. + * @return : 0 on success or error code */ +size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize); + +/********************************* +* Compression internals structs * +*********************************/ + +typedef struct { + U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */ + U32 len; /* Raw length of match */ } ZSTD_match_t; +typedef struct { + U32 offset; /* Offset of sequence */ + U32 litLength; /* Length of literals prior to match */ + U32 matchLength; /* Raw length of match */ +} rawSeq; + +typedef struct { + rawSeq* seq; /* The start of the sequences */ + size_t pos; /* The index in seq where reading stopped. pos <= size. */ + size_t posInSequence; /* The position within the sequence at seq[pos] where reading + stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */ + size_t size; /* The number of sequences. <= capacity. */ + size_t capacity; /* The capacity starting from `seq` pointer */ +} rawSeqStore_t; + +UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0}; + typedef struct { int price; U32 off; @@ -125,14 +188,21 @@ typedef struct { } ZSTD_compressedBlockState_t; typedef struct { - BYTE const* nextSrc; /* next block here to continue on current prefix */ - BYTE const* base; /* All regular indexes relative to this position */ - BYTE const* dictBase; /* extDict indexes relative to this position */ - U32 dictLimit; /* below that point, need extDict */ - U32 lowLimit; /* below that point, no more valid data */ + BYTE const* nextSrc; /* next block here to continue on current prefix */ + BYTE const* base; /* All regular indexes relative to this position */ + BYTE const* dictBase; /* extDict indexes relative to this position */ + U32 dictLimit; /* below that point, need extDict */ + U32 lowLimit; /* below that point, no more valid data */ + U32 nbOverflowCorrections; /* Number of times overflow correction has run since + * ZSTD_window_init(). Useful for debugging coredumps + * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY. + */ } ZSTD_window_t; typedef struct ZSTD_matchState_t ZSTD_matchState_t; + +#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */ + struct ZSTD_matchState_t { ZSTD_window_t window; /* State for window round buffer management */ U32 loadedDictEnd; /* index of end of dictionary, within context's referential. @@ -144,12 +214,24 @@ struct ZSTD_matchState_t { */ U32 nextToUpdate; /* index from which to continue table update */ U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */ + + U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/ + U16* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */ + U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */ + U32* hashTable; U32* hashTable3; U32* chainTable; + + U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */ + + int dedicatedDictSearch; /* Indicates whether this matchState is using the + * dedicated dictionary search structure. + */ optState_t opt; /* optimal parser state */ const ZSTD_matchState_t* dictMatchState; ZSTD_compressionParameters cParams; + const rawSeqStore_t* ldmSeqStore; }; typedef struct { @@ -163,13 +245,22 @@ typedef struct { U32 checksum; } ldmEntry_t; +typedef struct { + BYTE const* split; + U32 hash; + U32 checksum; + ldmEntry_t* bucket; +} ldmMatchCandidate_t; + +#define LDM_BATCH_SIZE 64 + typedef struct { ZSTD_window_t window; /* State for the window round buffer management */ ldmEntry_t* hashTable; U32 loadedDictEnd; BYTE* bucketOffsets; /* Next position in bucket to insert entry */ - U64 hashPower; /* Used to compute the rolling hash. - * Depends on ldmParams.minMatchLength */ + size_t splitIndices[LDM_BATCH_SIZE]; + ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE]; } ldmState_t; typedef struct { @@ -181,19 +272,6 @@ typedef struct { U32 windowLog; /* Window log for the LDM */ } ldmParams_t; -typedef struct { - U32 offset; - U32 litLength; - U32 matchLength; -} rawSeq; - -typedef struct { - rawSeq* seq; /* The start of the sequences */ - size_t pos; /* The position where reading stopped. <= size. */ - size_t size; /* The number of sequences. <= capacity. */ - size_t capacity; /* The capacity starting from `seq` pointer */ -} rawSeqStore_t; - typedef struct { int collectSequences; ZSTD_Sequence* seqStart; @@ -228,17 +306,52 @@ struct ZSTD_CCtx_params_s { /* Long distance matching parameters */ ldmParams_t ldmParams; + /* Dedicated dict search algorithm trigger */ + int enableDedicatedDictSearch; + + /* Input/output buffer modes */ + ZSTD_bufferMode_e inBufferMode; + ZSTD_bufferMode_e outBufferMode; + + /* Sequence compression API */ + ZSTD_sequenceFormat_e blockDelimiters; + int validateSequences; + + /* Block splitting */ + int splitBlocks; + + /* Param for deciding whether to use row-based matchfinder */ + ZSTD_useRowMatchFinderMode_e useRowMatchFinder; + + /* Always load a dictionary in ext-dict mode (not prefix mode)? */ + int deterministicRefPrefix; + /* Internal use, for createCCtxParams() and freeCCtxParams() only */ ZSTD_customMem customMem; }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */ +#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2)) +#define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE) + +/** + * Indicates whether this compression proceeds directly from user-provided + * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or + * whether the context needs to buffer the input/output (ZSTDb_buffered). + */ +typedef enum { + ZSTDb_not_buffered, + ZSTDb_buffered +} ZSTD_buffered_policy_e; + struct ZSTD_CCtx_s { ZSTD_compressionStage_e stage; int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */ ZSTD_CCtx_params requestedParams; ZSTD_CCtx_params appliedParams; + ZSTD_CCtx_params simpleApiParams; /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */ U32 dictID; + size_t dictContentSize; ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */ size_t blockSize; @@ -247,6 +360,7 @@ struct ZSTD_CCtx_s { unsigned long long producedCSize; XXH64_state_t xxhState; ZSTD_customMem customMem; + ZSTD_threadPool* pool; size_t staticSize; SeqCollector seqCollector; int isFirstBlock; @@ -258,7 +372,10 @@ struct ZSTD_CCtx_s { size_t maxNbLdmSequences; rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ ZSTD_blockState_t blockState; - U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ + U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */ + + /* Wether we are streaming or not */ + ZSTD_buffered_policy_e bufferedPolicy; /* streaming */ char* inBuff; @@ -273,6 +390,10 @@ struct ZSTD_CCtx_s { ZSTD_cStreamStage streamStage; U32 frameEnded; + /* Stable in/out buffer verification */ + ZSTD_inBuffer expectedInBuffer; + size_t expectedOutBufferSize; + /* Dictionary */ ZSTD_localDict localDict; const ZSTD_CDict* cdict; @@ -282,17 +403,46 @@ struct ZSTD_CCtx_s { #ifdef ZSTD_MULTITHREAD ZSTDMT_CCtx* mtctx; #endif + + /* Tracing */ +#if ZSTD_TRACE + ZSTD_TraceCtx traceCtx; +#endif }; typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e; -typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e; - +typedef enum { + ZSTD_noDict = 0, + ZSTD_extDict = 1, + ZSTD_dictMatchState = 2, + ZSTD_dedicatedDictSearch = 3 +} ZSTD_dictMode_e; + +typedef enum { + ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict. + * In this mode we use both the srcSize and the dictSize + * when selecting and adjusting parameters. + */ + ZSTD_cpm_attachDict = 1, /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch. + * In this mode we only take the srcSize into account when selecting + * and adjusting parameters. + */ + ZSTD_cpm_createCDict = 2, /* Creating a CDict. + * In this mode we take both the source size and the dictionary size + * into account when selecting and adjusting the parameters. + */ + ZSTD_cpm_unknown = 3, /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams. + * We don't know what these parameters are for. We default to the legacy + * behavior of taking both the source size and the dict size into account + * when selecting and adjusting parameters. + */ +} ZSTD_cParamMode_e; typedef size_t (*ZSTD_blockCompressor) ( ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode); +ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); MEM_STATIC U32 ZSTD_LLcode(U32 litLength) @@ -345,7 +495,7 @@ MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 con newReps.rep[1] = rep[0]; newReps.rep[0] = currentOffset; } else { /* repCode == 0 */ - memcpy(&newReps, rep, sizeof(newReps)); + ZSTD_memcpy(&newReps, rep, sizeof(newReps)); } } return newReps; @@ -372,7 +522,7 @@ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const voi RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity, dstSize_tooSmall, "dst buf too small for uncompressed block"); MEM_writeLE24(dst, cBlockHeader24); - memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); + ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); return ZSTD_blockHeaderSize + srcSize; } @@ -469,8 +619,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera /* literal Length */ if (litLength>0xFFFF) { - assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */ - seqStorePtr->longLengthID = 1; + assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */ + seqStorePtr->longLengthType = ZSTD_llt_literalLength; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); } seqStorePtr->sequences[0].litLength = (U16)litLength; @@ -480,8 +630,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera /* match Length */ if (mlBase>0xFFFF) { - assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */ - seqStorePtr->longLengthID = 2; + assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */ + seqStorePtr->longLengthType = ZSTD_llt_matchLength; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); } seqStorePtr->sequences[0].matchLength = (U16)mlBase; @@ -498,8 +648,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val) if (MEM_isLittleEndian()) { if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0; +# if STATIC_BMI2 + return _tzcnt_u64(val) >> 3; +# else + unsigned long r = 0; + return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_ctzll((U64)val) >> 3); # else @@ -530,8 +684,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* Big Endian CPU */ if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - return _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0; +# if STATIC_BMI2 + return _lzcnt_u64(val) >> 3; +# else + unsigned long r = 0; + return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_clzll(val) >> 3); # else @@ -626,7 +784,8 @@ static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; } static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } -MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) +MEM_STATIC FORCE_INLINE_ATTR +size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) { switch(mls) { @@ -723,6 +882,13 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window) window->dictLimit = end; } +MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window) +{ + return window.dictLimit == 1 && + window.lowLimit == 1 && + (window.nextSrc - window.base) == 1; +} + /** * ZSTD_window_hasExtDict(): * Returns non-zero if the window has a non-empty extDict. @@ -742,20 +908,74 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms) return ZSTD_window_hasExtDict(ms->window) ? ZSTD_extDict : ms->dictMatchState != NULL ? - ZSTD_dictMatchState : + (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) : ZSTD_noDict; } +/* Defining this macro to non-zero tells zstd to run the overflow correction + * code much more frequently. This is very inefficient, and should only be + * used for tests and fuzzers. + */ +#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY +# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1 +# else +# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0 +# endif +#endif + +/** + * ZSTD_window_canOverflowCorrect(): + * Returns non-zero if the indices are large enough for overflow correction + * to work correctly without impacting compression ratio. + */ +MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window, + U32 cycleLog, + U32 maxDist, + U32 loadedDictEnd, + void const* src) +{ + U32 const cycleSize = 1u << cycleLog; + U32 const curr = (U32)((BYTE const*)src - window.base); + U32 const minIndexToOverflowCorrect = cycleSize + MAX(maxDist, cycleSize); + + /* Adjust the min index to backoff the overflow correction frequency, + * so we don't waste too much CPU in overflow correction. If this + * computation overflows we don't really care, we just need to make + * sure it is at least minIndexToOverflowCorrect. + */ + U32 const adjustment = window.nbOverflowCorrections + 1; + U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment, + minIndexToOverflowCorrect); + U32 const indexLargeEnough = curr > adjustedIndex; + + /* Only overflow correct early if the dictionary is invalidated already, + * so we don't hurt compression ratio. + */ + U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd; + + return indexLargeEnough && dictionaryInvalidated; +} + /** * ZSTD_window_needOverflowCorrection(): * Returns non-zero if the indices are getting too large and need overflow * protection. */ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window, + U32 cycleLog, + U32 maxDist, + U32 loadedDictEnd, + void const* src, void const* srcEnd) { - U32 const current = (U32)((BYTE const*)srcEnd - window.base); - return current > ZSTD_CURRENT_MAX; + U32 const curr = (U32)((BYTE const*)srcEnd - window.base); + if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) { + if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) { + return 1; + } + } + return curr > ZSTD_CURRENT_MAX; } /** @@ -766,7 +986,6 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window, * * The least significant cycleLog bits of the indices must remain the same, * which may be 0. Every index up to maxDist in the past must be valid. - * NOTE: (maxDist & cycleMask) must be zero. */ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, U32 maxDist, void const* src) @@ -790,17 +1009,25 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32: * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32. */ - U32 const cycleMask = (1U << cycleLog) - 1; - U32 const current = (U32)((BYTE const*)src - window->base); - U32 const currentCycle0 = current & cycleMask; + U32 const cycleSize = 1u << cycleLog; + U32 const cycleMask = cycleSize - 1; + U32 const curr = (U32)((BYTE const*)src - window->base); + U32 const currentCycle0 = curr & cycleMask; /* Exclude zero so that newCurrent - maxDist >= 1. */ - U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0; - U32 const newCurrent = currentCycle1 + maxDist; - U32 const correction = current - newCurrent; - assert((maxDist & cycleMask) == 0); - assert(current > newCurrent); - /* Loose bound, should be around 1<<29 (see above) */ - assert(correction > 1<<28); + U32 const currentCycle1 = currentCycle0 == 0 ? cycleSize : currentCycle0; + U32 const newCurrent = currentCycle1 + MAX(maxDist, cycleSize); + U32 const correction = curr - newCurrent; + /* maxDist must be a power of two so that: + * (newCurrent & cycleMask) == (curr & cycleMask) + * This is required to not corrupt the chains / binary tree. + */ + assert((maxDist & (maxDist - 1)) == 0); + assert((curr & cycleMask) == (newCurrent & cycleMask)); + assert(curr > newCurrent); + if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) { + /* Loose bound, should be around 1<<29 (see above) */ + assert(correction > 1<<28); + } window->base += correction; window->dictBase += correction; @@ -816,6 +1043,8 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, assert(window->lowLimit <= newCurrent); assert(window->dictLimit <= newCurrent); + ++window->nbOverflowCorrections; + DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction, window->lowLimit); return correction; @@ -919,12 +1148,13 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window, } MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { - memset(window, 0, sizeof(*window)); + ZSTD_memset(window, 0, sizeof(*window)); window->base = (BYTE const*)""; window->dictBase = (BYTE const*)""; window->dictLimit = 1; /* start from 1, so that 1st position is valid */ window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */ window->nextSrc = window->base + 1; /* see issue #1241 */ + window->nbOverflowCorrections = 0; } /** @@ -935,7 +1165,8 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { * Returns non-zero if the segment is contiguous. */ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, - void const* src, size_t srcSize) + void const* src, size_t srcSize, + int forceNonContiguous) { BYTE const* const ip = (BYTE const*)src; U32 contiguous = 1; @@ -945,7 +1176,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, assert(window->base != NULL); assert(window->dictBase != NULL); /* Check if blocks follow each other */ - if (src != window->nextSrc) { + if (src != window->nextSrc || forceNonContiguous) { /* not contiguous */ size_t const distanceFromBase = (size_t)(window->nextSrc - window->base); DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit); @@ -973,12 +1204,16 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, /** * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix. */ -MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.lowLimit; - U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); + /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary + * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't + * valid for the entire block. So this check is sufficient to find the lowest valid match index. + */ U32 const matchLowest = isDictionary ? lowestValid : withinWindow; return matchLowest; } @@ -986,12 +1221,15 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current /** * Returns the lowest allowed match index in the prefix. */ -MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.dictLimit; - U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); + /* When computing the lowest prefix index we need to take the dictionary into account to handle + * the edge case where the dictionary and the source are contiguous in memory. + */ U32 const matchLowest = isDictionary ? lowestValid : withinWindow; return matchLowest; } @@ -1045,7 +1283,6 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) * assumptions : magic number supposed already checked * and dictSize >= 8 */ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, - short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize); void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); @@ -1061,7 +1298,7 @@ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); * Note: srcSizeHint == 0 means 0! */ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize); + const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); /*! ZSTD_initCStream_internal() : * Private use only. Init streaming operation. @@ -1122,4 +1359,9 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe * condition for correct operation : hashLog > 1 */ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat); +/** ZSTD_CCtx_trace() : + * Trace the end of a compression call. + */ +void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize); + #endif /* ZSTD_COMPRESS_H */ diff --git a/lib/compress/zstd_compress_literals.c b/lib/compress/zstd_compress_literals.c index 17e7168d893..008337bb1b3 100644 --- a/lib/compress/zstd_compress_literals.c +++ b/lib/compress/zstd_compress_literals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,7 +15,7 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize) { - BYTE* const ostart = (BYTE* const)dst; + BYTE* const ostart = (BYTE*)dst; U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, ""); @@ -35,14 +35,14 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, assert(0); } - memcpy(ostart + flSize, src, srcSize); + ZSTD_memcpy(ostart + flSize, src, srcSize); DEBUGLOG(5, "Raw literals: %u -> %u", (U32)srcSize, (U32)(srcSize + flSize)); return srcSize + flSize; } size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize) { - BYTE* const ostart = (BYTE* const)dst; + BYTE* const ostart = (BYTE*)dst; U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */ @@ -86,7 +86,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, disableLiteralCompression, (U32)srcSize); /* Prepare nextEntropy assuming reusing the existing table */ - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); if (disableLiteralCompression) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); @@ -117,12 +117,12 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, } } - if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) { - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) { + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); } if (cLitSize==1) { - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); } diff --git a/lib/compress/zstd_compress_literals.h b/lib/compress/zstd_compress_literals.h index 8b087057432..9904c0cd30a 100644 --- a/lib/compress/zstd_compress_literals.h +++ b/lib/compress/zstd_compress_literals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index f9f8097c839..611eabdcbbb 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -50,6 +50,19 @@ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) { return maxSymbolValue; } +/** + * Returns true if we should use ncount=-1 else we should + * use ncount=1 for low probability symbols instead. + */ +static unsigned ZSTD_useLowProbCount(size_t const nbSeq) +{ + /* Heuristic: This should cover most blocks <= 16K and + * start to fade out after 16K to about 32K depending on + * comprssibility. + */ + return nbSeq >= 2048; +} + /** * Returns the cost in bytes of encoding the normalized count header. * Returns an error if any of the helper functions return an error. @@ -60,7 +73,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max, BYTE wksp[FSE_NCOUNTBOUND]; S16 norm[MaxSeq + 1]; const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), ""); + FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), ""); return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog); } @@ -72,6 +85,8 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t { unsigned cost = 0; unsigned s; + + assert(total > 0); for (s = 0; s <= max; ++s) { unsigned norm = (unsigned)((256 * count[s]) / total); if (count[s] != 0 && norm == 0) @@ -219,6 +234,11 @@ ZSTD_selectEncodingType( return set_compressed; } +typedef struct { + S16 norm[MaxSeq + 1]; + U32 wksp[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(MaxSeq, MaxFSELog)]; +} ZSTD_BuildCTableWksp; + size_t ZSTD_buildCTable(void* dst, size_t dstCapacity, FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type, @@ -239,13 +259,13 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, *op = codeTable[0]; return 1; case set_repeat: - memcpy(nextCTable, prevCTable, prevCTableSize); + ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize); return 0; case set_basic: FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */ return 0; case set_compressed: { - S16 norm[MaxSeq + 1]; + ZSTD_BuildCTableWksp* wksp = (ZSTD_BuildCTableWksp*)entropyWorkspace; size_t nbSeq_1 = nbSeq; const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); if (count[codeTable[nbSeq-1]] > 1) { @@ -253,10 +273,12 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, nbSeq_1--; } assert(nbSeq_1 > 1); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max), ""); - { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ + assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp)); + (void)entropyWorkspaceSize; + FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), ""); + { size_t const NCountSize = FSE_writeNCount(op, oend - op, wksp->norm, max, tableLog); /* overflow protected */ FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed"); - FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), ""); + FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), ""); return NCountSize; } } diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index 68c6f9a5acd..7991364c2f7 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index b693866c0ac..e4e45069bc1 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,288 +15,10 @@ #include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */ #include "hist.h" /* HIST_countFast_wksp */ -#include "zstd_compress_internal.h" +#include "zstd_compress_internal.h" /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */ #include "zstd_compress_sequences.h" #include "zstd_compress_literals.h" -/*-************************************* -* Superblock entropy buffer structs -***************************************/ -/** ZSTD_hufCTablesMetadata_t : - * Stores Literals Block Type for a super-block in hType, and - * huffman tree description in hufDesBuffer. - * hufDesSize refers to the size of huffman tree description in bytes. - * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */ -typedef struct { - symbolEncodingType_e hType; - BYTE hufDesBuffer[500]; /* TODO give name to this value */ - size_t hufDesSize; -} ZSTD_hufCTablesMetadata_t; - -/** ZSTD_fseCTablesMetadata_t : - * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and - * fse tables in fseTablesBuffer. - * fseTablesSize refers to the size of fse tables in bytes. - * This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */ -typedef struct { - symbolEncodingType_e llType; - symbolEncodingType_e ofType; - symbolEncodingType_e mlType; - BYTE fseTablesBuffer[500]; /* TODO give name to this value */ - size_t fseTablesSize; - size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */ -} ZSTD_fseCTablesMetadata_t; - -typedef struct { - ZSTD_hufCTablesMetadata_t hufMetadata; - ZSTD_fseCTablesMetadata_t fseMetadata; -} ZSTD_entropyCTablesMetadata_t; - - -/** ZSTD_buildSuperBlockEntropy_literal() : - * Builds entropy for the super-block literals. - * Stores literals block type (raw, rle, compressed, repeat) and - * huffman description table to hufMetadata. - * @return : size of huffman description table or error code */ -static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize, - const ZSTD_hufCTables_t* prevHuf, - ZSTD_hufCTables_t* nextHuf, - ZSTD_hufCTablesMetadata_t* hufMetadata, - const int disableLiteralsCompression, - void* workspace, size_t wkspSize) -{ - BYTE* const wkspStart = (BYTE*)workspace; - BYTE* const wkspEnd = wkspStart + wkspSize; - BYTE* const countWkspStart = wkspStart; - unsigned* const countWksp = (unsigned*)workspace; - const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned); - BYTE* const nodeWksp = countWkspStart + countWkspSize; - const size_t nodeWkspSize = wkspEnd-nodeWksp; - unsigned maxSymbolValue = 255; - unsigned huffLog = HUF_TABLELOG_DEFAULT; - HUF_repeat repeat = prevHuf->repeatMode; - - DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize); - - /* Prepare nextEntropy assuming reusing the existing table */ - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - - if (disableLiteralsCompression) { - DEBUGLOG(5, "set_basic - disabled"); - hufMetadata->hType = set_basic; - return 0; - } - - /* small ? don't even attempt compression (speed opt) */ -# define COMPRESS_LITERALS_SIZE_MIN 63 - { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; - if (srcSize <= minLitSize) { - DEBUGLOG(5, "set_basic - too small"); - hufMetadata->hType = set_basic; - return 0; - } - } - - /* Scan input and build symbol stats */ - { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize); - FORWARD_IF_ERROR(largest, "HIST_count_wksp failed"); - if (largest == srcSize) { - DEBUGLOG(5, "set_rle"); - hufMetadata->hType = set_rle; - return 0; - } - if (largest <= (srcSize >> 7)+4) { - DEBUGLOG(5, "set_basic - no gain"); - hufMetadata->hType = set_basic; - return 0; - } - } - - /* Validate the previous Huffman table */ - if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) { - repeat = HUF_repeat_none; - } - - /* Build Huffman Tree */ - memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); - huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); - { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp, - maxSymbolValue, huffLog, - nodeWksp, nodeWkspSize); - FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp"); - huffLog = (U32)maxBits; - { /* Build and write the CTable */ - size_t const newCSize = HUF_estimateCompressedSize( - (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue); - size_t const hSize = HUF_writeCTable( - hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer), - (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog); - /* Check against repeating the previous CTable */ - if (repeat != HUF_repeat_none) { - size_t const oldCSize = HUF_estimateCompressedSize( - (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue); - if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) { - DEBUGLOG(5, "set_repeat - smaller"); - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - hufMetadata->hType = set_repeat; - return 0; - } - } - if (newCSize + hSize >= srcSize) { - DEBUGLOG(5, "set_basic - no gains"); - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - hufMetadata->hType = set_basic; - return 0; - } - DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize); - hufMetadata->hType = set_compressed; - nextHuf->repeatMode = HUF_repeat_check; - return hSize; - } - } -} - -/** ZSTD_buildSuperBlockEntropy_sequences() : - * Builds entropy for the super-block sequences. - * Stores symbol compression modes and fse table to fseMetadata. - * @return : size of fse tables or error code */ -static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr, - const ZSTD_fseCTables_t* prevEntropy, - ZSTD_fseCTables_t* nextEntropy, - const ZSTD_CCtx_params* cctxParams, - ZSTD_fseCTablesMetadata_t* fseMetadata, - void* workspace, size_t wkspSize) -{ - BYTE* const wkspStart = (BYTE*)workspace; - BYTE* const wkspEnd = wkspStart + wkspSize; - BYTE* const countWkspStart = wkspStart; - unsigned* const countWksp = (unsigned*)workspace; - const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned); - BYTE* const cTableWksp = countWkspStart + countWkspSize; - const size_t cTableWkspSize = wkspEnd-cTableWksp; - ZSTD_strategy const strategy = cctxParams->cParams.strategy; - FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable; - FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable; - FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable; - const BYTE* const ofCodeTable = seqStorePtr->ofCode; - const BYTE* const llCodeTable = seqStorePtr->llCode; - const BYTE* const mlCodeTable = seqStorePtr->mlCode; - size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; - BYTE* const ostart = fseMetadata->fseTablesBuffer; - BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer); - BYTE* op = ostart; - - assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE)); - DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq); - memset(workspace, 0, wkspSize); - - fseMetadata->lastCountSize = 0; - /* convert length/distances into codes */ - ZSTD_seqToCodes(seqStorePtr); - /* build CTable for Literal Lengths */ - { U32 LLtype; - unsigned max = MaxLL; - size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ - DEBUGLOG(5, "Building LL table"); - nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode; - LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, - countWksp, max, mostFrequent, nbSeq, - LLFSELog, prevEntropy->litlengthCTable, - LL_defaultNorm, LL_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(set_basic < set_compressed && set_rle < set_compressed); - assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype, - countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL, - prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable), - cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed"); - if (LLtype == set_compressed) - fseMetadata->lastCountSize = countSize; - op += countSize; - fseMetadata->llType = (symbolEncodingType_e) LLtype; - } } - /* build CTable for Offsets */ - { U32 Offtype; - unsigned max = MaxOff; - size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ - /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ - ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; - DEBUGLOG(5, "Building OF table"); - nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode; - Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, - countWksp, max, mostFrequent, nbSeq, - OffFSELog, prevEntropy->offcodeCTable, - OF_defaultNorm, OF_defaultNormLog, - defaultPolicy, strategy); - assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype, - countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, - prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable), - cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed"); - if (Offtype == set_compressed) - fseMetadata->lastCountSize = countSize; - op += countSize; - fseMetadata->ofType = (symbolEncodingType_e) Offtype; - } } - /* build CTable for MatchLengths */ - { U32 MLtype; - unsigned max = MaxML; - size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ - DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); - nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode; - MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, - countWksp, max, mostFrequent, nbSeq, - MLFSELog, prevEntropy->matchlengthCTable, - ML_defaultNorm, ML_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype, - countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML, - prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable), - cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed"); - if (MLtype == set_compressed) - fseMetadata->lastCountSize = countSize; - op += countSize; - fseMetadata->mlType = (symbolEncodingType_e) MLtype; - } } - assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer)); - return op-ostart; -} - - -/** ZSTD_buildSuperBlockEntropy() : - * Builds entropy for the super-block. - * @return : 0 on success or error code */ -static size_t -ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr, - const ZSTD_entropyCTables_t* prevEntropy, - ZSTD_entropyCTables_t* nextEntropy, - const ZSTD_CCtx_params* cctxParams, - ZSTD_entropyCTablesMetadata_t* entropyMetadata, - void* workspace, size_t wkspSize) -{ - size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart; - DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy"); - entropyMetadata->hufMetadata.hufDesSize = - ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize, - &prevEntropy->huf, &nextEntropy->huf, - &entropyMetadata->hufMetadata, - ZSTD_disableLiteralsCompression(cctxParams), - workspace, wkspSize); - FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed"); - entropyMetadata->fseMetadata.fseTablesSize = - ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr, - &prevEntropy->fse, &nextEntropy->fse, - cctxParams, - &entropyMetadata->fseMetadata, - workspace, wkspSize); - FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed"); - return 0; -} - /** ZSTD_compressSubBlock_literal() : * Compresses literals section for a sub-block. * When we have to write the Huffman table we will sometimes choose a header @@ -304,7 +26,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr, * before we know the table size + compressed size, so we have a bound on the * table size. If we guessed incorrectly, we fall back to uncompressed literals. * - * We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded + * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded * in writing the header, otherwise it is set to 0. * * hufMetadata->hType has literals block type info. @@ -348,7 +70,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat); if (writeEntropy && hufMetadata->hType == set_compressed) { - memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); + ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); op += hufMetadata->hufDesSize; cLitSize += hufMetadata->hufDesSize; DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize); @@ -474,7 +196,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables const U32 MLtype = fseMetadata->mlType; DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize); *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); - memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize); + ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize); op += fseMetadata->fseTablesSize; } else { const U32 repeat = set_repeat; @@ -603,7 +325,7 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, const BYTE* codeTable, unsigned maxCode, size_t nbSeq, const FSE_CTable* fseCTable, const U32* additionalBits, - short const* defaultNorm, U32 defaultNormLog, + short const* defaultNorm, U32 defaultNormLog, U32 defaultMax, void* workspace, size_t wkspSize) { unsigned* const countWksp = (unsigned*)workspace; @@ -615,7 +337,11 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */ if (type == set_basic) { - cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max); + /* We selected this encoding type, so it must be valid. */ + assert(max <= defaultMax); + cSymbolTypeSizeEstimateInBits = max <= defaultMax + ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max) + : ERROR(GENERIC); } else if (type == set_rle) { cSymbolTypeSizeEstimateInBits = 0; } else if (type == set_compressed || type == set_repeat) { @@ -639,19 +365,20 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable, void* workspace, size_t wkspSize, int writeEntropy) { - size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */ + size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */ size_t cSeqSizeEstimate = 0; + if (nbSeq == 0) return sequencesSectionHeaderSize; cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff, nbSeq, fseTables->offcodeCTable, NULL, - OF_defaultNorm, OF_defaultNormLog, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, workspace, wkspSize); cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL, nbSeq, fseTables->litlengthCTable, LL_bits, - LL_defaultNorm, LL_defaultNormLog, + LL_defaultNorm, LL_defaultNormLog, MaxLL, workspace, wkspSize); cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML, nbSeq, fseTables->matchlengthCTable, ML_bits, - ML_defaultNorm, ML_defaultNormLog, + ML_defaultNorm, ML_defaultNormLog, MaxML, workspace, wkspSize); if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize; return cSeqSizeEstimate + sequencesSectionHeaderSize; @@ -790,7 +517,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, } while (!lastSequence); if (writeLitEntropy) { DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten"); - memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); + ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); } if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) { /* If we haven't written our entropy tables, then we've violated our contract and @@ -809,11 +536,11 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, if (sp < send) { seqDef const* seq; repcodes_t rep; - memcpy(&rep, prevCBlock->rep, sizeof(rep)); + ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep)); for (seq = sstart; seq < sp; ++seq) { rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0); } - memcpy(nextCBlock->rep, &rep, sizeof(rep)); + ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep)); } } DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed"); @@ -826,12 +553,12 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, unsigned lastBlock) { ZSTD_entropyCTablesMetadata_t entropyMetadata; - FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore, + FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore, &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, &entropyMetadata, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); return ZSTD_compressSubBlock_multi(&zc->seqStore, zc->blockState.prevCBlock, @@ -841,5 +568,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, dst, dstCapacity, src, srcSize, zc->bmi2, lastBlock, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */); + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */); } diff --git a/lib/compress/zstd_compress_superblock.h b/lib/compress/zstd_compress_superblock.h index 07f4cb1dc64..176f9b106f3 100644 --- a/lib/compress/zstd_compress_superblock.h +++ b/lib/compress/zstd_compress_superblock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index a25c9263b7d..2656d26ca2e 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -35,6 +35,10 @@ extern "C" { #define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128 #endif + +/* Set our tables and aligneds to align by 64 bytes */ +#define ZSTD_CWKSP_ALIGNMENT_BYTES 64 + /*-************************************* * Structures ***************************************/ @@ -44,6 +48,16 @@ typedef enum { ZSTD_cwksp_alloc_aligned } ZSTD_cwksp_alloc_phase_e; +/** + * Used to describe whether the workspace is statically allocated (and will not + * necessarily ever be freed), or if it's dynamically allocated and we can + * expect a well-formed caller to free this. + */ +typedef enum { + ZSTD_cwksp_dynamic_alloc, + ZSTD_cwksp_static_alloc +} ZSTD_cwksp_static_alloc_e; + /** * Zstd fits all its internal datastructures into a single continuous buffer, * so that it only needs to perform a single OS allocation (or so that a buffer @@ -92,7 +106,7 @@ typedef enum { * * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict, * so that literally everything fits in a single buffer. Note: if present, - * this must be the first object in the workspace, since ZSTD_free{CCtx, + * this must be the first object in the workspace, since ZSTD_customFree{CCtx, * CDict}() rely on a pointer comparison to see whether one or two frees are * required. * @@ -107,10 +121,11 @@ typedef enum { * - Tables: these are any of several different datastructures (hash tables, * chain tables, binary trees) that all respect a common format: they are * uint32_t arrays, all of whose values are between 0 and (nextSrc - base). - * Their sizes depend on the cparams. + * Their sizes depend on the cparams. These tables are 64-byte aligned. * * - Aligned: these buffers are used for various purposes that require 4 byte - * alignment, but don't require any initialization before they're used. + * alignment, but don't require any initialization before they're used. These + * buffers are each aligned to 64 bytes. * * - Buffers: these buffers are used for various purposes that don't require * any alignment or initialization before they're used. This means they can @@ -123,8 +138,7 @@ typedef enum { * * 1. Objects * 2. Buffers - * 3. Aligned - * 4. Tables + * 3. Aligned/Tables * * Attempts to reserve objects of different types out of order will fail. */ @@ -137,9 +151,10 @@ typedef struct { void* tableValidEnd; void* allocStart; - int allocFailed; + BYTE allocFailed; int workspaceOversizedDuration; ZSTD_cwksp_alloc_phase_e phase; + ZSTD_cwksp_static_alloc_e isStatic; } ZSTD_cwksp; /*-************************************* @@ -176,39 +191,123 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { * Since tables aren't currently redzoned, you don't need to call through this * to figure out how much space you need for the matchState tables. Everything * else is though. + * + * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size(). */ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + if (size == 0) + return 0; +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; #else return size; #endif } -MEM_STATIC void ZSTD_cwksp_internal_advance_phase( +/** + * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes. + * Used to determine the number of bytes required for a given "aligned". + */ +MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) { + return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES)); +} + +/** + * Returns the amount of additional space the cwksp must allocate + * for internal purposes (currently only alignment). + */ +MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) { + /* For alignment, the wksp will always allocate an additional n_1=[1, 64] bytes + * to align the beginning of tables section, as well as another n_2=[0, 63] bytes + * to align the beginning of the aligned secion. + * + * n_1 + n_2 == 64 bytes if the cwksp is freshly allocated, due to tables and + * aligneds being sized in multiples of 64 bytes. + */ + size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES; + return slackSpace; +} + + +/** + * Return the number of additional bytes required to align a pointer to the given number of bytes. + * alignBytes must be a power of two. + */ +MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) { + size_t const alignBytesMask = alignBytes - 1; + size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask; + assert((alignBytes & alignBytesMask) == 0); + assert(bytes != ZSTD_CWKSP_ALIGNMENT_BYTES); + return bytes; +} + +/** + * Internal function. Do not use directly. + * Reserves the given number of bytes within the aligned/buffer segment of the wksp, which + * counts from the end of the wksp. (as opposed to the object/table segment) + * + * Returns a pointer to the beginning of that space. + */ +MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) { + void* const alloc = (BYTE*)ws->allocStart - bytes; + void* const bottom = ws->tableEnd; + DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining", + alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); + ZSTD_cwksp_assert_internal_consistency(ws); + assert(alloc >= bottom); + if (alloc < bottom) { + DEBUGLOG(4, "cwksp: alloc failed!"); + ws->allocFailed = 1; + return NULL; + } + if (alloc < ws->tableValidEnd) { + ws->tableValidEnd = alloc; + } + ws->allocStart = alloc; + return alloc; +} + +/** + * Moves the cwksp to the next phase, and does any necessary allocations. + * Returns a 0 on success, or zstd error + */ +MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase( ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) { assert(phase >= ws->phase); if (phase > ws->phase) { + /* Going from allocating objects to allocating buffers */ if (ws->phase < ZSTD_cwksp_alloc_buffers && phase >= ZSTD_cwksp_alloc_buffers) { ws->tableValidEnd = ws->objectEnd; } + + /* Going from allocating buffers to allocating aligneds/tables */ if (ws->phase < ZSTD_cwksp_alloc_aligned && phase >= ZSTD_cwksp_alloc_aligned) { - /* If unaligned allocations down from a too-large top have left us - * unaligned, we need to realign our alloc ptr. Technically, this - * can consume space that is unaccounted for in the neededSpace - * calculation. However, I believe this can only happen when the - * workspace is too large, and specifically when it is too large - * by a larger margin than the space that will be consumed. */ - /* TODO: cleaner, compiler warning friendly way to do this??? */ - ws->allocStart = (BYTE*)ws->allocStart - ((size_t)ws->allocStart & (sizeof(U32)-1)); - if (ws->allocStart < ws->tableValidEnd) { - ws->tableValidEnd = ws->allocStart; + { /* Align the start of the "aligned" to 64 bytes. Use [1, 64] bytes. */ + size_t const bytesToAlign = + ZSTD_CWKSP_ALIGNMENT_BYTES - ZSTD_cwksp_bytes_to_align_ptr(ws->allocStart, ZSTD_CWKSP_ALIGNMENT_BYTES); + DEBUGLOG(5, "reserving aligned alignment addtl space: %zu", bytesToAlign); + ZSTD_STATIC_ASSERT((ZSTD_CWKSP_ALIGNMENT_BYTES & (ZSTD_CWKSP_ALIGNMENT_BYTES - 1)) == 0); /* power of 2 */ + RETURN_ERROR_IF(!ZSTD_cwksp_reserve_internal_buffer_space(ws, bytesToAlign), + memory_allocation, "aligned phase - alignment initial allocation failed!"); + } + { /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */ + void* const alloc = ws->objectEnd; + size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES); + void* const end = (BYTE*)alloc + bytesToAlign; + DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign); + RETURN_ERROR_IF(end > ws->workspaceEnd, memory_allocation, + "table phase - alignment initial allocation failed!"); + ws->objectEnd = end; + ws->tableEnd = end; + ws->tableValidEnd = end; } } ws->phase = phase; + ZSTD_cwksp_assert_internal_consistency(ws); } + return 0; } /** @@ -224,34 +323,26 @@ MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) { MEM_STATIC void* ZSTD_cwksp_reserve_internal( ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) { void* alloc; - void* bottom = ws->tableEnd; - ZSTD_cwksp_internal_advance_phase(ws, phase); - alloc = (BYTE *)ws->allocStart - bytes; + if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) { + return NULL; + } -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* over-reserve space */ - alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; + bytes += 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; #endif - DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining", - alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); - ZSTD_cwksp_assert_internal_consistency(ws); - assert(alloc >= bottom); - if (alloc < bottom) { - DEBUGLOG(4, "cwksp: alloc failed!"); - ws->allocFailed = 1; - return NULL; - } - if (alloc < ws->tableValidEnd) { - ws->tableValidEnd = alloc; - } - ws->allocStart = alloc; + alloc = ZSTD_cwksp_reserve_internal_buffer_space(ws, bytes); -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on * either size. */ - alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; - __asan_unpoison_memory_region(alloc, bytes); + if (alloc) { + alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } + } #endif return alloc; @@ -265,28 +356,36 @@ MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) { } /** - * Reserves and returns memory sized on and aligned on sizeof(unsigned). + * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes). */ MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) { - assert((bytes & (sizeof(U32)-1)) == 0); - return ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, sizeof(U32)), ZSTD_cwksp_alloc_aligned); + void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), + ZSTD_cwksp_alloc_aligned); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + return ptr; } /** - * Aligned on sizeof(unsigned). These buffers have the special property that + * Aligned on 64 bytes. These buffers have the special property that * their values remain constrained, allowing us to re-use them without * memset()-ing them. */ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) { const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned; - void* alloc = ws->tableEnd; - void* end = (BYTE *)alloc + bytes; - void* top = ws->allocStart; + void* alloc; + void* end; + void* top; + + if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) { + return NULL; + } + alloc = ws->tableEnd; + end = (BYTE *)alloc + bytes; + top = ws->allocStart; DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining", alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); assert((bytes & (sizeof(U32)-1)) == 0); - ZSTD_cwksp_internal_advance_phase(ws, phase); ZSTD_cwksp_assert_internal_consistency(ws); assert(end <= top); if (end > top) { @@ -296,10 +395,14 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) { } ws->tableEnd = end; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - __asan_unpoison_memory_region(alloc, bytes); +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } #endif + assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); + assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); return alloc; } @@ -311,7 +414,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { void* alloc = ws->objectEnd; void* end = (BYTE*)alloc + roundedBytes; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* over-reserve space */ end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; #endif @@ -332,11 +435,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { ws->tableEnd = end; ws->tableValidEnd = end; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on * either size. */ alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; - __asan_unpoison_memory_region(alloc, bytes); + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } #endif return alloc; @@ -345,7 +450,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty"); -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the table re-use logic is sound, and that we don't * access table space that we haven't cleaned, we re-"poison" the table * space every time we mark it dirty. */ @@ -380,7 +485,7 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { assert(ws->tableValidEnd >= ws->objectEnd); assert(ws->tableValidEnd <= ws->allocStart); if (ws->tableValidEnd < ws->tableEnd) { - memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd); + ZSTD_memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd); } ZSTD_cwksp_mark_tables_clean(ws); } @@ -392,8 +497,12 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: clearing tables!"); -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - { +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* We don't do this when the workspace is statically allocated, because + * when that is the case, we have no capability to hook into the end of the + * workspace's lifecycle to unpoison the memory. + */ + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd; __asan_poison_memory_region(ws->objectEnd, size); } @@ -410,7 +519,7 @@ MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: clearing!"); -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the context re-use logic is sound, and that we don't * access stuff that this compression hasn't initialized, we re-"poison" * the workspace (or at least the non-static, non-table parts of it) @@ -421,8 +530,12 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { } #endif -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - { +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* We don't do this when the workspace is statically allocated, because + * when that is the case, we have no capability to hook into the end of the + * workspace's lifecycle to unpoison the memory. + */ + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd; __asan_poison_memory_region(ws->objectEnd, size); } @@ -442,7 +555,7 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { * Any existing values in the workspace are ignored (the previously managed * buffer, if present, must be separately freed). */ -MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) { +MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) { DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size); assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */ ws->workspace = start; @@ -450,39 +563,45 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) { ws->objectEnd = ws->workspace; ws->tableValidEnd = ws->objectEnd; ws->phase = ZSTD_cwksp_alloc_objects; + ws->isStatic = isStatic; ZSTD_cwksp_clear(ws); ws->workspaceOversizedDuration = 0; ZSTD_cwksp_assert_internal_consistency(ws); } MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) { - void* workspace = ZSTD_malloc(size, customMem); + void* workspace = ZSTD_customMalloc(size, customMem); DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size); RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!"); - ZSTD_cwksp_init(ws, workspace, size); + ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc); return 0; } MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) { void *ptr = ws->workspace; DEBUGLOG(4, "cwksp: freeing workspace"); - memset(ws, 0, sizeof(ZSTD_cwksp)); - ZSTD_free(ptr, customMem); + ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp)); + ZSTD_customFree(ptr, customMem); } /** * Moves the management of a workspace from one cwksp to another. The src cwksp - * is left in an invalid state (src must be re-init()'ed before its used again). + * is left in an invalid state (src must be re-init()'ed before it's used again). */ MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) { *dst = *src; - memset(src, 0, sizeof(ZSTD_cwksp)); + ZSTD_memset(src, 0, sizeof(ZSTD_cwksp)); } MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) { return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace); } +MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) { + return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace) + + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart); +} + MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) { return ws->allocFailed; } @@ -491,6 +610,24 @@ MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) { * Functions Checking Free Space ***************************************/ +/* ZSTD_alignmentSpaceWithinBounds() : + * Returns if the estimated space needed for a wksp is within an acceptable limit of the + * actual amount of space used. + */ +MEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp* const ws, + size_t const estimatedSpace, int resizedWorkspace) { + if (resizedWorkspace) { + /* Resized/newly allocated wksp should have exact bounds */ + return ZSTD_cwksp_used(ws) == estimatedSpace; + } else { + /* Due to alignment, when reusing a workspace, we can actually consume 63 fewer or more bytes + * than estimatedSpace. See the comments in zstd_cwksp.h for details. + */ + return (ZSTD_cwksp_used(ws) >= estimatedSpace - 63) && (ZSTD_cwksp_used(ws) <= estimatedSpace + 63); + } +} + + MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) { return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd); } diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 27eed66cfed..d0d3a784dd2 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -31,15 +31,15 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, * is empty. */ for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) { - U32 const current = (U32)(ip - base); + U32 const curr = (U32)(ip - base); U32 i; for (i = 0; i < fastHashFillStep; ++i) { size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls); size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8); if (i == 0) - hashSmall[smHash] = current + i; + hashSmall[smHash] = curr + i; if (i == 0 || hashLarge[lgHash] == 0) - hashLarge[lgHash] = current + i; + hashLarge[lgHash] = curr + i; /* Only load extra positions for ZSTD_dtlm_full */ if (dtlm == ZSTD_dtlm_fast) break; @@ -108,9 +108,9 @@ size_t ZSTD_compressBlock_doubleFast_generic( /* init */ ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { - U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); - U32 const maxRep = current - windowLow; + U32 const curr = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); + U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; } @@ -129,17 +129,17 @@ size_t ZSTD_compressBlock_doubleFast_generic( size_t const h = ZSTD_hashPtr(ip, hBitsS, mls); size_t const dictHL = ZSTD_hashPtr(ip, dictHBitsL, 8); size_t const dictHS = ZSTD_hashPtr(ip, dictHBitsS, mls); - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const matchIndexL = hashLong[h2]; U32 matchIndexS = hashSmall[h]; const BYTE* matchLong = base + matchIndexL; const BYTE* match = base + matchIndexS; - const U32 repIndex = current + 1 - offset_1; + const U32 repIndex = curr + 1 - offset_1; const BYTE* repMatch = (dictMode == ZSTD_dictMatchState && repIndex < prefixLowestIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - hashLong[h2] = hashSmall[h] = current; /* update hash tables */ + hashLong[h2] = hashSmall[h] = curr; /* update hash tables */ /* check dictMatchState repcode */ if (dictMode == ZSTD_dictMatchState @@ -177,7 +177,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) { mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8; - offset = (U32)(current - dictMatchIndexL - dictIndexDelta); + offset = (U32)(curr - dictMatchIndexL - dictIndexDelta); while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */ goto _match_found; } } @@ -209,7 +209,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8); U32 const matchIndexL3 = hashLong[hl3]; const BYTE* matchL3 = base + matchIndexL3; - hashLong[hl3] = current + 1; + hashLong[hl3] = curr + 1; /* check prefix long +1 match */ if (matchIndexL3 > prefixLowestIndex) { @@ -228,7 +228,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) { mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8; ip++; - offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta); + offset = (U32)(curr + 1 - dictMatchIndexL3 - dictIndexDelta); while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */ goto _match_found; } } } @@ -236,7 +236,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( /* if no long +1 match, explore the short match we found */ if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) { mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4; - offset = (U32)(current - matchIndexS); + offset = (U32)(curr - matchIndexS); while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ } else { mLength = ZSTD_count(ip+4, match+4, iend) + 4; @@ -260,7 +260,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( if (ip <= ilimit) { /* Complementary insertion */ /* done after iLimit test, as candidates could be > iend-8 */ - { U32 const indexToInsert = current+2; + { U32 const indexToInsert = curr+2; hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; @@ -401,15 +401,15 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base; const BYTE* matchLong = matchLongBase + matchLongIndex; - const U32 current = (U32)(ip-base); - const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */ + const U32 curr = (U32)(ip-base); + const U32 repIndex = curr + 1 - offset_1; /* offset_1 expected <= curr +1 */ const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; size_t mLength; - hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */ + hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */ if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */ - & (repIndex > dictStartIndex)) + & (offset_1 < curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; @@ -421,7 +421,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart; U32 offset; mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8; - offset = current - matchLongIndex; + offset = curr - matchLongIndex; while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; @@ -433,19 +433,19 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base; const BYTE* match3 = match3Base + matchIndex3; U32 offset; - hashLong[h3] = current + 1; + hashLong[h3] = curr + 1; if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) { const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend; const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart; mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8; ip++; - offset = current+1 - matchIndex3; + offset = curr+1 - matchIndex3; while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */ } else { const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; - offset = current - matchIndex; + offset = curr - matchIndex; while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ } offset_2 = offset_1; @@ -464,7 +464,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( if (ip <= ilimit) { /* Complementary insertion */ /* done after iLimit test, as candidates could be > iend-8 */ - { U32 const indexToInsert = current+2; + { U32 const indexToInsert = curr+2; hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; @@ -477,7 +477,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( U32 const repIndex2 = current2 - offset_2; const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */ - & (repIndex2 > dictStartIndex)) + & (offset_2 < current2 - dictStartIndex)) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h index 14d944d69bc..e16b7b03a32 100644 --- a/lib/compress/zstd_double_fast.h +++ b/lib/compress/zstd_double_fast.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 85a3a7a91e4..4edc04dccdf 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -29,16 +29,16 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, * Insert the other positions if their hash entry is empty. */ for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) { - U32 const current = (U32)(ip - base); + U32 const curr = (U32)(ip - base); size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls); - hashTable[hash0] = current; + hashTable[hash0] = curr; if (dtlm == ZSTD_dtlm_fast) continue; /* Only load extra positions for ZSTD_dtlm_full */ { U32 p; for (p = 1; p < fastHashFillStep; ++p) { size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls); if (hashTable[hash] == 0) { /* not yet filled */ - hashTable[hash] = current + p; + hashTable[hash] = curr + p; } } } } } @@ -72,9 +72,9 @@ ZSTD_compressBlock_fast_generic( DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); ip1 = ip0 + 1; - { U32 const current = (U32)(ip0 - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); - U32 const maxRep = current - windowLow; + { U32 const curr = (U32)(ip0 - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); + U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; } @@ -242,7 +242,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( assert(endIndex - prefixStartIndex <= maxDistance); (void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */ - /* ensure there will be no no underflow + /* ensure there will be no underflow * when translating a dict index into a local index */ assert(prefixStartIndex >= (U32)(dictEnd - dictBase)); @@ -258,14 +258,14 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ size_t mLength; size_t const h = ZSTD_hashPtr(ip, hlog, mls); - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const matchIndex = hashTable[h]; const BYTE* match = base + matchIndex; - const U32 repIndex = current + 1 - offset_1; + const U32 repIndex = curr + 1 - offset_1; const BYTE* repMatch = (repIndex < prefixStartIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - hashTable[h] = current; /* update hash table */ + hashTable[h] = curr; /* update hash table */ if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { @@ -284,7 +284,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( continue; } else { /* found a dict match */ - U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta); + U32 const offset = (U32)(curr-dictMatchIndex-dictIndexDelta); mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4; while (((ip>anchor) & (dictMatch>dictStart)) && (ip[-1] == dictMatch[-1])) { @@ -316,8 +316,8 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( if (ip <= ilimit) { /* Fill Table */ - assert(base+current+2 > istart); /* check base overflow */ - hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; /* here because current+2 could be > iend-8 */ + assert(base+curr+2 > istart); /* check base overflow */ + hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2; /* here because curr+2 could be > iend-8 */ hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); /* check immediate repcode */ @@ -410,15 +410,15 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( const U32 matchIndex = hashTable[h]; const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base; const BYTE* match = matchBase + matchIndex; - const U32 current = (U32)(ip-base); - const U32 repIndex = current + 1 - offset_1; + const U32 curr = (U32)(ip-base); + const U32 repIndex = curr + 1 - offset_1; const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - hashTable[h] = current; /* update hash table */ - DEBUGLOG(7, "offset_1 = %u , current = %u", offset_1, current); - assert(offset_1 <= current +1); /* check repIndex */ + hashTable[h] = curr; /* update hash table */ + DEBUGLOG(7, "offset_1 = %u , curr = %u", offset_1, curr); - if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex)) + if ( ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ + & (offset_1 < curr+1 - dictStartIndex) ) /* note: we are searching at curr+1 */ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4; @@ -435,7 +435,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( } { const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; - U32 const offset = current - matchIndex; + U32 const offset = curr - matchIndex; size_t mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; /* update offset history */ @@ -446,14 +446,14 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( if (ip <= ilimit) { /* Fill Table */ - hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; + hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2; hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); /* check immediate repcode */ while (ip <= ilimit) { U32 const current2 = (U32)(ip-base); U32 const repIndex2 = current2 - offset_2; const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; - if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (repIndex2 > dictStartIndex)) /* intentional overflow */ + if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 < curr - dictStartIndex)) /* intentional overflow */ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h index cf6aaa8e675..0d4a0c1090f 100644 --- a/lib/compress/zstd_fast.h +++ b/lib/compress/zstd_fast.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 4cf5c88b532..3d523e8472f 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -58,11 +58,11 @@ ZSTD_updateDUBT(ZSTD_matchState_t* ms, /** ZSTD_insertDUBT1() : * sort one already inserted but unsorted position - * assumption : current >= btlow == (current - btmask) + * assumption : curr >= btlow == (curr - btmask) * doesn't fail */ static void ZSTD_insertDUBT1(ZSTD_matchState_t* ms, - U32 current, const BYTE* inputEnd, + U32 curr, const BYTE* inputEnd, U32 nbCompares, U32 btLow, const ZSTD_dictMode_e dictMode) { @@ -74,41 +74,41 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms, const BYTE* const base = ms->window.base; const BYTE* const dictBase = ms->window.dictBase; const U32 dictLimit = ms->window.dictLimit; - const BYTE* const ip = (current>=dictLimit) ? base + current : dictBase + current; - const BYTE* const iend = (current>=dictLimit) ? inputEnd : dictBase + dictLimit; + const BYTE* const ip = (curr>=dictLimit) ? base + curr : dictBase + curr; + const BYTE* const iend = (curr>=dictLimit) ? inputEnd : dictBase + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* match; - U32* smallerPtr = bt + 2*(current&btMask); + U32* smallerPtr = bt + 2*(curr&btMask); U32* largerPtr = smallerPtr + 1; U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ U32 dummy32; /* to be nullified at the end */ U32 const windowValid = ms->window.lowLimit; U32 const maxDistance = 1U << cParams->windowLog; - U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid; + U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid; DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)", - current, dictLimit, windowLow); - assert(current >= btLow); + curr, dictLimit, windowLow); + assert(curr >= btLow); assert(ip < iend); /* condition for ZSTD_count */ while (nbCompares-- && (matchIndex > windowLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(matchIndex < current); + assert(matchIndex < curr); /* note : all candidates are now supposed sorted, * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */ if ( (dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit) /* both in current segment*/ - || (current < dictLimit) /* both in extDict */) { + || (curr < dictLimit) /* both in extDict */) { const BYTE* const mBase = ( (dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) ? base : dictBase; assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */ - || (current < dictLimit) ); + || (curr < dictLimit) ); match = mBase + matchIndex; matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); } else { @@ -119,7 +119,7 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms, } DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ", - current, matchIndex, (U32)matchLength); + curr, matchIndex, (U32)matchLength); if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */ @@ -168,7 +168,7 @@ ZSTD_DUBT_findBetterDictMatch ( const BYTE* const base = ms->window.base; const BYTE* const prefixStart = base + ms->window.dictLimit; - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); const BYTE* const dictBase = dms->window.base; const BYTE* const dictEnd = dms->window.nextSrc; U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base); @@ -195,10 +195,10 @@ ZSTD_DUBT_findBetterDictMatch ( if (matchLength > bestLength) { U32 matchIndex = dictMatchIndex + dictIndexDelta; - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) { + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) { DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)", - current, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + current - matchIndex, dictMatchIndex, matchIndex); - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; + curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + curr - matchIndex, dictMatchIndex, matchIndex); + bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex; } if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */ break; /* drop, to guarantee consistency (miss a little bit of compression) */ @@ -218,9 +218,9 @@ ZSTD_DUBT_findBetterDictMatch ( } if (bestLength >= MINMATCH) { - U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; + U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)", - current, (U32)bestLength, (U32)*offsetPtr, mIndex); + curr, (U32)bestLength, (U32)*offsetPtr, mIndex); } return bestLength; @@ -241,13 +241,13 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, U32 matchIndex = hashTable[h]; const BYTE* const base = ms->window.base; - U32 const current = (U32)(ip-base); - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog); + U32 const curr = (U32)(ip-base); + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; U32 const btMask = (1 << btLog) - 1; - U32 const btLow = (btMask >= current) ? 0 : current - btMask; + U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; U32 const unsortLimit = MAX(btLow, windowLow); U32* nextCandidate = bt + 2*(matchIndex&btMask); @@ -256,8 +256,9 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, U32 nbCandidates = nbCompares; U32 previousCandidate = 0; - DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", current); + DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", curr); assert(ip <= iend-8); /* required for h calculation */ + assert(dictMode != ZSTD_dedicatedDictSearch); /* reach end of unsorted candidates list */ while ( (matchIndex > unsortLimit) @@ -299,14 +300,14 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, const U32 dictLimit = ms->window.dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 matchEndIdx = current + 8 + 1; + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = bt + 2*(curr&btMask) + 1; + U32 matchEndIdx = curr + 8 + 1; U32 dummy32; /* to be nullified at the end */ size_t bestLength = 0; matchIndex = hashTable[h]; - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ while (nbCompares-- && (matchIndex > windowLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); @@ -326,8 +327,8 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, if (matchLength > bestLength) { if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) + bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex; if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ if (dictMode == ZSTD_dictMatchState) { nbCompares = 0; /* in addition to avoiding checking any @@ -363,12 +364,12 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, mls, dictMode); } - assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */ + assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */ ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ if (bestLength >= MINMATCH) { - U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; + U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)", - current, (U32)bestLength, (U32)*offsetPtr, mIndex); + curr, (U32)bestLength, (U32)*offsetPtr, mIndex); } return bestLength; } @@ -437,6 +438,220 @@ static size_t ZSTD_BtFindBestMatch_extDict_selectMLS ( } } +/*********************************** +* Dedicated dict search +***********************************/ + +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip) +{ + const BYTE* const base = ms->window.base; + U32 const target = (U32)(ip - base); + U32* const hashTable = ms->hashTable; + U32* const chainTable = ms->chainTable; + U32 const chainSize = 1 << ms->cParams.chainLog; + U32 idx = ms->nextToUpdate; + U32 const minChain = chainSize < target ? target - chainSize : idx; + U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const cacheSize = bucketSize - 1; + U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize; + U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts; + + /* We know the hashtable is oversized by a factor of `bucketSize`. + * We are going to temporarily pretend `bucketSize == 1`, keeping only a + * single entry. We will use the rest of the space to construct a temporary + * chaintable. + */ + U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + U32* const tmpHashTable = hashTable; + U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog); + U32 const tmpChainSize = ((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog; + U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx; + U32 hashIdx; + + assert(ms->cParams.chainLog <= 24); + assert(ms->cParams.hashLog > ms->cParams.chainLog); + assert(idx != 0); + assert(tmpMinChain <= minChain); + + /* fill conventional hash table and conventional chain table */ + for ( ; idx < target; idx++) { + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch); + if (idx >= tmpMinChain) { + tmpChainTable[idx - tmpMinChain] = hashTable[h]; + } + tmpHashTable[h] = idx; + } + + /* sort chains into ddss chain table */ + { + U32 chainPos = 0; + for (hashIdx = 0; hashIdx < (1U << hashLog); hashIdx++) { + U32 count; + U32 countBeyondMinChain = 0; + U32 i = tmpHashTable[hashIdx]; + for (count = 0; i >= tmpMinChain && count < cacheSize; count++) { + /* skip through the chain to the first position that won't be + * in the hash cache bucket */ + if (i < minChain) { + countBeyondMinChain++; + } + i = tmpChainTable[i - tmpMinChain]; + } + if (count == cacheSize) { + for (count = 0; count < chainLimit;) { + if (i < minChain) { + if (!i || ++countBeyondMinChain > cacheSize) { + /* only allow pulling `cacheSize` number of entries + * into the cache or chainTable beyond `minChain`, + * to replace the entries pulled out of the + * chainTable into the cache. This lets us reach + * back further without increasing the total number + * of entries in the chainTable, guaranteeing the + * DDSS chain table will fit into the space + * allocated for the regular one. */ + break; + } + } + chainTable[chainPos++] = i; + count++; + if (i < tmpMinChain) { + break; + } + i = tmpChainTable[i - tmpMinChain]; + } + } else { + count = 0; + } + if (count) { + tmpHashTable[hashIdx] = ((chainPos - count) << 8) + count; + } else { + tmpHashTable[hashIdx] = 0; + } + } + assert(chainPos <= chainSize); /* I believe this is guaranteed... */ + } + + /* move chain pointers into the last entry of each hash bucket */ + for (hashIdx = (1 << hashLog); hashIdx; ) { + U32 const bucketIdx = --hashIdx << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const chainPackedPointer = tmpHashTable[hashIdx]; + U32 i; + for (i = 0; i < cacheSize; i++) { + hashTable[bucketIdx + i] = 0; + } + hashTable[bucketIdx + bucketSize - 1] = chainPackedPointer; + } + + /* fill the buckets of the hash table */ + for (idx = ms->nextToUpdate; idx < target; idx++) { + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch) + << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 i; + /* Shift hash cache down 1. */ + for (i = cacheSize - 1; i; i--) + hashTable[h + i] = hashTable[h + i - 1]; + hashTable[h] = idx; + } + + ms->nextToUpdate = target; +} + +/* Returns the longest match length found in the dedicated dict search structure. + * If none are longer than the argument ml, then ml will be returned. + */ +FORCE_INLINE_TEMPLATE +size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nbAttempts, + const ZSTD_matchState_t* const dms, + const BYTE* const ip, const BYTE* const iLimit, + const BYTE* const prefixStart, const U32 curr, + const U32 dictLimit, const size_t ddsIdx) { + const U32 ddsLowestIndex = dms->window.dictLimit; + const BYTE* const ddsBase = dms->window.base; + const BYTE* const ddsEnd = dms->window.nextSrc; + const U32 ddsSize = (U32)(ddsEnd - ddsBase); + const U32 ddsIndexDelta = dictLimit - ddsSize; + const U32 bucketSize = (1 << ZSTD_LAZY_DDSS_BUCKET_LOG); + const U32 bucketLimit = nbAttempts < bucketSize - 1 ? nbAttempts : bucketSize - 1; + U32 ddsAttempt; + U32 matchIndex; + + for (ddsAttempt = 0; ddsAttempt < bucketSize - 1; ddsAttempt++) { + PREFETCH_L1(ddsBase + dms->hashTable[ddsIdx + ddsAttempt]); + } + + { + U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1]; + U32 const chainIndex = chainPackedPointer >> 8; + + PREFETCH_L1(&dms->chainTable[chainIndex]); + } + + for (ddsAttempt = 0; ddsAttempt < bucketLimit; ddsAttempt++) { + size_t currentMl=0; + const BYTE* match; + matchIndex = dms->hashTable[ddsIdx + ddsAttempt]; + match = ddsBase + matchIndex; + + if (!matchIndex) { + return ml; + } + + /* guaranteed by table construction */ + (void)ddsLowestIndex; + assert(matchIndex >= ddsLowestIndex); + assert(match+4 <= ddsEnd); + if (MEM_read32(match) == MEM_read32(ip)) { + /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE; + if (ip+currentMl == iLimit) { + /* best possible, avoids read overflow on next attempt */ + return ml; + } + } + } + + { + U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1]; + U32 chainIndex = chainPackedPointer >> 8; + U32 const chainLength = chainPackedPointer & 0xFF; + U32 const chainAttempts = nbAttempts - ddsAttempt; + U32 const chainLimit = chainAttempts > chainLength ? chainLength : chainAttempts; + U32 chainAttempt; + + for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++) { + PREFETCH_L1(ddsBase + dms->chainTable[chainIndex + chainAttempt]); + } + + for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++, chainIndex++) { + size_t currentMl=0; + const BYTE* match; + matchIndex = dms->chainTable[chainIndex]; + match = ddsBase + matchIndex; + + /* guaranteed by table construction */ + assert(matchIndex >= ddsLowestIndex); + assert(match+4 <= ddsEnd); + if (MEM_read32(match) == MEM_read32(ip)) { + /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE; + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + } + } + return ml; +} /* ********************************* @@ -446,7 +661,7 @@ static size_t ZSTD_BtFindBestMatch_extDict_selectMLS ( /* Update chains up to ip (excluded) Assumption : always within prefix (i.e. not within extDict) */ -static U32 ZSTD_insertAndFindFirstIndex_internal( +FORCE_INLINE_TEMPLATE U32 ZSTD_insertAndFindFirstIndex_internal( ZSTD_matchState_t* ms, const ZSTD_compressionParameters* const cParams, const BYTE* ip, U32 const mls) @@ -475,7 +690,6 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) { return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch); } - /* inlining is important to hardwire a hot branch (template emulation) */ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_generic ( @@ -493,20 +707,33 @@ size_t ZSTD_HcFindBestMatch_generic ( const U32 dictLimit = ms->window.dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; - const U32 current = (U32)(ip-base); + const U32 curr = (U32)(ip-base); const U32 maxDistance = 1U << cParams->windowLog; const U32 lowestValid = ms->window.lowLimit; - const U32 withinMaxDistance = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; const U32 isDictionary = (ms->loadedDictEnd != 0); const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance; - const U32 minChain = current > chainSize ? current - chainSize : 0; + const U32 minChain = curr > chainSize ? curr - chainSize : 0; U32 nbAttempts = 1U << cParams->searchLog; size_t ml=4-1; + const ZSTD_matchState_t* const dms = ms->dictMatchState; + const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch + ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch + ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + + U32 matchIndex; + + if (dictMode == ZSTD_dedicatedDictSearch) { + const U32* entry = &dms->hashTable[ddsIdx]; + PREFETCH_L1(entry); + } + /* HC4 match finder */ - U32 matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls); + matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls); - for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) { + for ( ; (matchIndex>=lowLimit) & (nbAttempts>0) ; nbAttempts--) { size_t currentMl=0; if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { const BYTE* const match = base + matchIndex; @@ -523,7 +750,7 @@ size_t ZSTD_HcFindBestMatch_generic ( /* save best solution */ if (currentMl > ml) { ml = currentMl; - *offsetPtr = current - matchIndex + ZSTD_REP_MOVE; + *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE; if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ } @@ -531,8 +758,10 @@ size_t ZSTD_HcFindBestMatch_generic ( matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); } - if (dictMode == ZSTD_dictMatchState) { - const ZSTD_matchState_t* const dms = ms->dictMatchState; + if (dictMode == ZSTD_dedicatedDictSearch) { + ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms, + ip, iLimit, prefixStart, curr, dictLimit, ddsIdx); + } else if (dictMode == ZSTD_dictMatchState) { const U32* const dmsChainTable = dms->chainTable; const U32 dmsChainSize = (1 << dms->cParams.chainLog); const U32 dmsChainMask = dmsChainSize - 1; @@ -545,7 +774,7 @@ size_t ZSTD_HcFindBestMatch_generic ( matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)]; - for ( ; (matchIndex>dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { + for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { size_t currentMl=0; const BYTE* const match = dmsBase + matchIndex; assert(match+4 <= dmsEnd); @@ -555,11 +784,12 @@ size_t ZSTD_HcFindBestMatch_generic ( /* save best solution */ if (currentMl > ml) { ml = currentMl; - *offsetPtr = current - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE; + *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE; if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ } if (matchIndex <= dmsMinChain) break; + matchIndex = dmsChainTable[matchIndex & dmsChainMask]; } } @@ -600,6 +830,22 @@ static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS ( } +static size_t ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS ( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr) +{ + switch(ms->cParams.minMatch) + { + default : /* includes case 3 */ + case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dedicatedDictSearch); + case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dedicatedDictSearch); + case 7 : + case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dedicatedDictSearch); + } +} + + FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS ( ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* const iLimit, @@ -615,11 +861,657 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS ( } } +/* ********************************* +* (SIMD) Row-based matchfinder +***********************************/ +/* Constants for row-based hash */ +#define ZSTD_ROW_HASH_TAG_OFFSET 1 /* byte offset of hashes in the match state's tagTable from the beginning of a row */ +#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */ +#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1) + +#define ZSTD_ROW_HASH_CACHE_MASK (ZSTD_ROW_HASH_CACHE_SIZE - 1) + +typedef U32 ZSTD_VecMask; /* Clarifies when we are interacting with a U32 representing a mask of matches */ + +#if !defined(ZSTD_NO_INTRINSICS) && defined(__SSE2__) /* SIMD SSE version */ + +#include <emmintrin.h> +typedef __m128i ZSTD_Vec128; + +/* Returns a 128-bit container with 128-bits from src */ +static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) { + return _mm_loadu_si128((ZSTD_Vec128 const*)src); +} + +/* Returns a ZSTD_Vec128 with the byte "val" packed 16 times */ +static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) { + return _mm_set1_epi8((char)val); +} + +/* Do byte-by-byte comparison result of x and y. Then collapse 128-bit resultant mask + * into a 32-bit mask that is the MSB of each byte. + * */ +static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) { + return (ZSTD_VecMask)_mm_movemask_epi8(_mm_cmpeq_epi8(x, y)); +} + +typedef struct { + __m128i fst; + __m128i snd; +} ZSTD_Vec256; + +static ZSTD_Vec256 ZSTD_Vec256_read(const void* const ptr) { + ZSTD_Vec256 v; + v.fst = ZSTD_Vec128_read(ptr); + v.snd = ZSTD_Vec128_read((ZSTD_Vec128 const*)ptr + 1); + return v; +} + +static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) { + ZSTD_Vec256 v; + v.fst = ZSTD_Vec128_set8(val); + v.snd = ZSTD_Vec128_set8(val); + return v; +} + +static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) { + ZSTD_VecMask fstMask; + ZSTD_VecMask sndMask; + fstMask = ZSTD_Vec128_cmpMask8(x.fst, y.fst); + sndMask = ZSTD_Vec128_cmpMask8(x.snd, y.snd); + return fstMask | (sndMask << 16); +} + +#elif !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) /* SIMD ARM NEON Version */ + +#include <arm_neon.h> +typedef uint8x16_t ZSTD_Vec128; + +static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) { + return vld1q_u8((const BYTE* const)src); +} + +static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) { + return vdupq_n_u8(val); +} + +/* Mimics '_mm_movemask_epi8()' from SSE */ +static U32 ZSTD_vmovmaskq_u8(ZSTD_Vec128 val) { + /* Shift out everything but the MSB bits in each byte */ + uint16x8_t highBits = vreinterpretq_u16_u8(vshrq_n_u8(val, 7)); + /* Merge the even lanes together with vsra (right shift and add) */ + uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(highBits, highBits, 7)); + uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); + uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); + /* Extract the low 8 bits from each lane, merge */ + return vgetq_lane_u8(paired64, 0) | ((U32)vgetq_lane_u8(paired64, 8) << 8); +} + +static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) { + return (ZSTD_VecMask)ZSTD_vmovmaskq_u8(vceqq_u8(x, y)); +} + +typedef struct { + uint8x16_t fst; + uint8x16_t snd; +} ZSTD_Vec256; + +static ZSTD_Vec256 ZSTD_Vec256_read(const void* const ptr) { + ZSTD_Vec256 v; + v.fst = ZSTD_Vec128_read(ptr); + v.snd = ZSTD_Vec128_read((ZSTD_Vec128 const*)ptr + 1); + return v; +} + +static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) { + ZSTD_Vec256 v; + v.fst = ZSTD_Vec128_set8(val); + v.snd = ZSTD_Vec128_set8(val); + return v; +} + +static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) { + ZSTD_VecMask fstMask; + ZSTD_VecMask sndMask; + fstMask = ZSTD_Vec128_cmpMask8(x.fst, y.fst); + sndMask = ZSTD_Vec128_cmpMask8(x.snd, y.snd); + return fstMask | (sndMask << 16); +} + +#else /* Scalar fallback version */ + +#define VEC128_NB_SIZE_T (16 / sizeof(size_t)) +typedef struct { + size_t vec[VEC128_NB_SIZE_T]; +} ZSTD_Vec128; + +static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) { + ZSTD_Vec128 ret; + ZSTD_memcpy(ret.vec, src, VEC128_NB_SIZE_T*sizeof(size_t)); + return ret; +} + +static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) { + ZSTD_Vec128 ret = { {0} }; + int startBit = sizeof(size_t) * 8 - 8; + for (;startBit >= 0; startBit -= 8) { + unsigned j = 0; + for (;j < VEC128_NB_SIZE_T; ++j) { + ret.vec[j] |= ((size_t)val << startBit); + } + } + return ret; +} + +/* Compare x to y, byte by byte, generating a "matches" bitfield */ +static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) { + ZSTD_VecMask res = 0; + unsigned i = 0; + unsigned l = 0; + for (; i < VEC128_NB_SIZE_T; ++i) { + const size_t cmp1 = x.vec[i]; + const size_t cmp2 = y.vec[i]; + unsigned j = 0; + for (; j < sizeof(size_t); ++j, ++l) { + if (((cmp1 >> j*8) & 0xFF) == ((cmp2 >> j*8) & 0xFF)) { + res |= ((U32)1 << (j+i*sizeof(size_t))); + } + } + } + return res; +} + +#define VEC256_NB_SIZE_T 2*VEC128_NB_SIZE_T +typedef struct { + size_t vec[VEC256_NB_SIZE_T]; +} ZSTD_Vec256; + +static ZSTD_Vec256 ZSTD_Vec256_read(const void* const src) { + ZSTD_Vec256 ret; + ZSTD_memcpy(ret.vec, src, VEC256_NB_SIZE_T*sizeof(size_t)); + return ret; +} + +static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) { + ZSTD_Vec256 ret = { {0} }; + int startBit = sizeof(size_t) * 8 - 8; + for (;startBit >= 0; startBit -= 8) { + unsigned j = 0; + for (;j < VEC256_NB_SIZE_T; ++j) { + ret.vec[j] |= ((size_t)val << startBit); + } + } + return ret; +} + +/* Compare x to y, byte by byte, generating a "matches" bitfield */ +static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) { + ZSTD_VecMask res = 0; + unsigned i = 0; + unsigned l = 0; + for (; i < VEC256_NB_SIZE_T; ++i) { + const size_t cmp1 = x.vec[i]; + const size_t cmp2 = y.vec[i]; + unsigned j = 0; + for (; j < sizeof(size_t); ++j, ++l) { + if (((cmp1 >> j*8) & 0xFF) == ((cmp2 >> j*8) & 0xFF)) { + res |= ((U32)1 << (j+i*sizeof(size_t))); + } + } + } + return res; +} + +#endif /* !defined(ZSTD_NO_INTRINSICS) && defined(__SSE2__) */ + +/* ZSTD_VecMask_next(): + * Starting from the LSB, returns the idx of the next non-zero bit. + * Basically counting the nb of trailing zeroes. + */ +static U32 ZSTD_VecMask_next(ZSTD_VecMask val) { +# if defined(_MSC_VER) /* Visual */ + unsigned long r=0; + return _BitScanForward(&r, val) ? (U32)r : 0; +# elif defined(__GNUC__) && (__GNUC__ >= 3) + return (U32)__builtin_ctz(val); +# else + /* Software ctz version: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */ + static const U32 multiplyDeBruijnBitPosition[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + return multiplyDeBruijnBitPosition[((U32)((v & -(int)v) * 0x077CB531U)) >> 27]; +# endif +} + +/* ZSTD_VecMask_rotateRight(): + * Rotates a bitfield to the right by "rotation" bits. + * If the rotation is greater than totalBits, the returned mask is 0. + */ +FORCE_INLINE_TEMPLATE ZSTD_VecMask +ZSTD_VecMask_rotateRight(ZSTD_VecMask mask, U32 const rotation, U32 const totalBits) { + if (rotation == 0) + return mask; + switch (totalBits) { + default: + assert(0); + case 16: + return (mask >> rotation) | (U16)(mask << (16 - rotation)); + case 32: + return (mask >> rotation) | (U32)(mask << (32 - rotation)); + } +} + +/* ZSTD_row_nextIndex(): + * Returns the next index to insert at within a tagTable row, and updates the "head" + * value to reflect the update. Essentially cycles backwards from [0, {entries per row}) + */ +FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextIndex(BYTE* const tagRow, U32 const rowMask) { + U32 const next = (*tagRow - 1) & rowMask; + *tagRow = (BYTE)next; + return next; +} + +/* ZSTD_isAligned(): + * Checks that a pointer is aligned to "align" bytes which must be a power of 2. + */ +MEM_STATIC int ZSTD_isAligned(void const* ptr, size_t align) { + assert((align & (align - 1)) == 0); + return (((size_t)ptr) & (align - 1)) == 0; +} + +/* ZSTD_row_prefetch(): + * Performs prefetching for the hashTable and tagTable at a given row. + */ +FORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, U16 const* tagTable, U32 const relRow, U32 const rowLog) { + PREFETCH_L1(hashTable + relRow); + if (rowLog == 5) { + PREFETCH_L1(hashTable + relRow + 16); + } + PREFETCH_L1(tagTable + relRow); + assert(rowLog == 4 || rowLog == 5); + assert(ZSTD_isAligned(hashTable + relRow, 64)); /* prefetched hash row always 64-byte aligned */ + assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on a multiple of 32 or 64 bytes */ +} + +/* ZSTD_row_fillHashCache(): + * Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries, + * but not beyond iLimit. + */ +static void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base, + U32 const rowLog, U32 const mls, + U32 idx, const BYTE* const iLimit) +{ + U32 const* const hashTable = ms->hashTable; + U16 const* const tagTable = ms->tagTable; + U32 const hashLog = ms->rowHashLog; + U32 const maxElemsToPrefetch = (base + idx) > iLimit ? 0 : (U32)(iLimit - (base + idx) + 1); + U32 const lim = idx + MIN(ZSTD_ROW_HASH_CACHE_SIZE, maxElemsToPrefetch); + + for (; idx < lim; ++idx) { + U32 const hash = (U32)ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls); + U32 const row = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + ZSTD_row_prefetch(hashTable, tagTable, row, rowLog); + ms->hashCache[idx & ZSTD_ROW_HASH_CACHE_MASK] = hash; + } + + DEBUGLOG(6, "ZSTD_row_fillHashCache(): [%u %u %u %u %u %u %u %u]", ms->hashCache[0], ms->hashCache[1], + ms->hashCache[2], ms->hashCache[3], ms->hashCache[4], + ms->hashCache[5], ms->hashCache[6], ms->hashCache[7]); +} + +/* ZSTD_row_nextCachedHash(): + * Returns the hash of base + idx, and replaces the hash in the hash cache with the byte at + * base + idx + ZSTD_ROW_HASH_CACHE_SIZE. Also prefetches the appropriate rows from hashTable and tagTable. + */ +FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable, + U16 const* tagTable, BYTE const* base, + U32 idx, U32 const hashLog, + U32 const rowLog, U32 const mls) +{ + U32 const newHash = (U32)ZSTD_hashPtr(base+idx+ZSTD_ROW_HASH_CACHE_SIZE, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls); + U32 const row = (newHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + ZSTD_row_prefetch(hashTable, tagTable, row, rowLog); + { U32 const hash = cache[idx & ZSTD_ROW_HASH_CACHE_MASK]; + cache[idx & ZSTD_ROW_HASH_CACHE_MASK] = newHash; + return hash; + } +} + +/* ZSTD_row_update_internal(): + * Inserts the byte at ip into the appropriate position in the hash table. + * Determines the relative row, and the position within the {16, 32} entry row to insert at. + */ +FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip, + U32 const mls, U32 const rowLog, + U32 const rowMask, U32 const useCache) +{ + U32* const hashTable = ms->hashTable; + U16* const tagTable = ms->tagTable; + U32 const hashLog = ms->rowHashLog; + const BYTE* const base = ms->window.base; + const U32 target = (U32)(ip - base); + U32 idx = ms->nextToUpdate; + + DEBUGLOG(6, "ZSTD_row_update_internal(): nextToUpdate=%u, current=%u", idx, target); + for (; idx < target; ++idx) { + U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, idx, hashLog, rowLog, mls) + : (U32)ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls); + U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + U32* const row = hashTable + relRow; + BYTE* tagRow = (BYTE*)(tagTable + relRow); /* Though tagTable is laid out as a table of U16, each tag is only 1 byte. + Explicit cast allows us to get exact desired position within each row */ + U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask); + + assert(hash == ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls)); + ((BYTE*)tagRow)[pos + ZSTD_ROW_HASH_TAG_OFFSET] = hash & ZSTD_ROW_HASH_TAG_MASK; + row[pos] = idx; + } + ms->nextToUpdate = target; +} + +/* ZSTD_row_update(): + * External wrapper for ZSTD_row_update_internal(). Used for filling the hashtable during dictionary + * processing. + */ +void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) { + const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5; + const U32 rowMask = (1u << rowLog) - 1; + const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */); + + DEBUGLOG(5, "ZSTD_row_update(), rowLog=%u", rowLog); + ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* dont use cache */); +} + +/* Returns a ZSTD_VecMask (U32) that has the nth bit set to 1 if the newly-computed "tag" matches + * the hash at the nth position in a row of the tagTable. + */ +FORCE_INLINE_TEMPLATE +ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 head, const U32 rowEntries) { + ZSTD_VecMask matches = 0; + if (rowEntries == 16) { + ZSTD_Vec128 hashes = ZSTD_Vec128_read(tagRow + ZSTD_ROW_HASH_TAG_OFFSET); + ZSTD_Vec128 expandedTags = ZSTD_Vec128_set8(tag); + matches = ZSTD_Vec128_cmpMask8(hashes, expandedTags); + } else if (rowEntries == 32) { + ZSTD_Vec256 hashes = ZSTD_Vec256_read(tagRow + ZSTD_ROW_HASH_TAG_OFFSET); + ZSTD_Vec256 expandedTags = ZSTD_Vec256_set8(tag); + matches = ZSTD_Vec256_cmpMask8(hashes, expandedTags); + } else { + assert(0); + } + /* Each row is a circular buffer beginning at the value of "head". So we must rotate the "matches" bitfield + to match up with the actual layout of the entries within the hashTable */ + return ZSTD_VecMask_rotateRight(matches, head, rowEntries); +} + +/* The high-level approach of the SIMD row based match finder is as follows: + * - Figure out where to insert the new entry: + * - Generate a hash from a byte along with an additional 1-byte "short hash". The additional byte is our "tag" + * - The hashTable is effectively split into groups or "rows" of 16 or 32 entries of U32, and the hash determines + * which row to insert into. + * - Determine the correct position within the row to insert the entry into. Each row of 16 or 32 can + * be considered as a circular buffer with a "head" index that resides in the tagTable. + * - Also insert the "tag" into the equivalent row and position in the tagTable. + * - Note: The tagTable has 17 or 33 1-byte entries per row, due to 16 or 32 tags, and 1 "head" entry. + * The 17 or 33 entry rows are spaced out to occur every 32 or 64 bytes, respectively, + * for alignment/performance reasons, leaving some bytes unused. + * - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte "short hash" and + * generate a bitfield that we can cycle through to check the collisions in the hash table. + * - Pick the longest match. + */ +FORCE_INLINE_TEMPLATE +size_t ZSTD_RowFindBestMatch_generic ( + ZSTD_matchState_t* ms, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 mls, const ZSTD_dictMode_e dictMode, + const U32 rowLog) +{ + U32* const hashTable = ms->hashTable; + U16* const tagTable = ms->tagTable; + U32* const hashCache = ms->hashCache; + const U32 hashLog = ms->rowHashLog; + const ZSTD_compressionParameters* const cParams = &ms->cParams; + const BYTE* const base = ms->window.base; + const BYTE* const dictBase = ms->window.dictBase; + const U32 dictLimit = ms->window.dictLimit; + const BYTE* const prefixStart = base + dictLimit; + const BYTE* const dictEnd = dictBase + dictLimit; + const U32 curr = (U32)(ip-base); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 lowestValid = ms->window.lowLimit; + const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; + const U32 isDictionary = (ms->loadedDictEnd != 0); + const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance; + const U32 rowEntries = (1U << rowLog); + const U32 rowMask = rowEntries - 1; + const U32 cappedSearchLog = MIN(cParams->searchLog, rowLog); /* nb of searches is capped at nb entries per row */ + U32 nbAttempts = 1U << cappedSearchLog; + size_t ml=4-1; + + /* DMS/DDS variables that may be referenced laster */ + const ZSTD_matchState_t* const dms = ms->dictMatchState; + size_t ddsIdx; + U32 ddsExtraAttempts; /* cctx hash tables are limited in searches, but allow extra searches into DDS */ + U32 dmsTag; + U32* dmsRow; + BYTE* dmsTagRow; + + if (dictMode == ZSTD_dedicatedDictSearch) { + const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + { /* Prefetch DDS hashtable entry */ + ddsIdx = ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG; + PREFETCH_L1(&dms->hashTable[ddsIdx]); + } + ddsExtraAttempts = cParams->searchLog > rowLog ? 1U << (cParams->searchLog - rowLog) : 0; + } + + if (dictMode == ZSTD_dictMatchState) { + /* Prefetch DMS rows */ + U32* const dmsHashTable = dms->hashTable; + U16* const dmsTagTable = dms->tagTable; + U32 const dmsHash = (U32)ZSTD_hashPtr(ip, dms->rowHashLog + ZSTD_ROW_HASH_TAG_BITS, mls); + U32 const dmsRelRow = (dmsHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + dmsTag = dmsHash & ZSTD_ROW_HASH_TAG_MASK; + dmsTagRow = (BYTE*)(dmsTagTable + dmsRelRow); + dmsRow = dmsHashTable + dmsRelRow; + ZSTD_row_prefetch(dmsHashTable, dmsTagTable, dmsRelRow, rowLog); + } + + /* Update the hashTable and tagTable up to (but not including) ip */ + ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 1 /* useCache */); + { /* Get the hash for ip, compute the appropriate row */ + U32 const hash = ZSTD_row_nextCachedHash(hashCache, hashTable, tagTable, base, curr, hashLog, rowLog, mls); + U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + U32 const tag = hash & ZSTD_ROW_HASH_TAG_MASK; + U32* const row = hashTable + relRow; + BYTE* tagRow = (BYTE*)(tagTable + relRow); + U32 const head = *tagRow & rowMask; + U32 matchBuffer[32 /* maximum nb entries per row */]; + size_t numMatches = 0; + size_t currMatch = 0; + ZSTD_VecMask matches = ZSTD_row_getMatchMask(tagRow, (BYTE)tag, head, rowEntries); + + /* Cycle through the matches and prefetch */ + for (; (matches > 0) && (nbAttempts > 0); --nbAttempts, matches &= (matches - 1)) { + U32 const matchPos = (head + ZSTD_VecMask_next(matches)) & rowMask; + U32 const matchIndex = row[matchPos]; + assert(numMatches < rowEntries); + if (matchIndex < lowLimit) + break; + if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { + PREFETCH_L1(base + matchIndex); + } else { + PREFETCH_L1(dictBase + matchIndex); + } + matchBuffer[numMatches++] = matchIndex; + } + + /* Speed opt: insert current byte into hashtable too. This allows us to avoid one iteration of the loop + in ZSTD_row_update_internal() at the next search. */ + { + U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask); + tagRow[pos + ZSTD_ROW_HASH_TAG_OFFSET] = (BYTE)tag; + row[pos] = ms->nextToUpdate++; + } + + /* Return the longest match */ + for (; currMatch < numMatches; ++currMatch) { + U32 const matchIndex = matchBuffer[currMatch]; + size_t currentMl=0; + assert(matchIndex < curr); + assert(matchIndex >= lowLimit); + + if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { + const BYTE* const match = base + matchIndex; + assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */ + if (match[ml] == ip[ml]) /* potentially better */ + currentMl = ZSTD_count(ip, match, iLimit); + } else { + const BYTE* const match = dictBase + matchIndex; + assert(match+4 <= dictEnd); + if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4; + } + + /* Save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE; + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + } + } + + if (dictMode == ZSTD_dedicatedDictSearch) { + ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms, + ip, iLimit, prefixStart, curr, dictLimit, ddsIdx); + } else if (dictMode == ZSTD_dictMatchState) { + /* TODO: Measure and potentially add prefetching to DMS */ + const U32 dmsLowestIndex = dms->window.dictLimit; + const BYTE* const dmsBase = dms->window.base; + const BYTE* const dmsEnd = dms->window.nextSrc; + const U32 dmsSize = (U32)(dmsEnd - dmsBase); + const U32 dmsIndexDelta = dictLimit - dmsSize; + + { U32 const head = *dmsTagRow & rowMask; + U32 matchBuffer[32 /* maximum nb row entries */]; + size_t numMatches = 0; + size_t currMatch = 0; + ZSTD_VecMask matches = ZSTD_row_getMatchMask(dmsTagRow, (BYTE)dmsTag, head, rowEntries); + + for (; (matches > 0) && (nbAttempts > 0); --nbAttempts, matches &= (matches - 1)) { + U32 const matchPos = (head + ZSTD_VecMask_next(matches)) & rowMask; + U32 const matchIndex = dmsRow[matchPos]; + if (matchIndex < dmsLowestIndex) + break; + PREFETCH_L1(dmsBase + matchIndex); + matchBuffer[numMatches++] = matchIndex; + } + + /* Return the longest match */ + for (; currMatch < numMatches; ++currMatch) { + U32 const matchIndex = matchBuffer[currMatch]; + size_t currentMl=0; + assert(matchIndex >= dmsLowestIndex); + assert(matchIndex < curr); + + { const BYTE* const match = dmsBase + matchIndex; + assert(match+4 <= dmsEnd); + if (MEM_read32(match) == MEM_read32(ip)) + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4; + } + + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE; + if (ip+currentMl == iLimit) break; + } + } + } + } + return ml; +} + +/* Inlining is important to hardwire a hot branch (template emulation) */ +FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectMLS ( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + const ZSTD_dictMode_e dictMode, size_t* offsetPtr, const U32 rowLog) +{ + switch(ms->cParams.minMatch) + { + default : /* includes case 3 */ + case 4 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, dictMode, rowLog); + case 5 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, dictMode, rowLog); + case 7 : + case 6 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, dictMode, rowLog); + } +} + +FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectRowLog ( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr) +{ + const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5); + switch(cappedSearchLog) + { + default : + case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 4); + case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 5); + } +} + +FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dictMatchState_selectRowLog( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr) +{ + const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5); + switch(cappedSearchLog) + { + default : + case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 4); + case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 5); + } +} + +FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr) +{ + const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5); + switch(cappedSearchLog) + { + default : + case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 4); + case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 5); + } +} + +FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_extDict_selectRowLog ( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr) +{ + const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5); + switch(cappedSearchLog) + { + default : + case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 4); + case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 5); + } +} + /* ******************************* * Common parser - lazy strategy *********************************/ -typedef enum { search_hashChain, search_binaryTree } searchMethod_e; +typedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e; FORCE_INLINE_TEMPLATE size_t ZSTD_compressBlock_lazy_generic( @@ -633,53 +1525,85 @@ ZSTD_compressBlock_lazy_generic( const BYTE* ip = istart; const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; + const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8; const BYTE* const base = ms->window.base; const U32 prefixLowestIndex = ms->window.dictLimit; const BYTE* const prefixLowest = base + prefixLowestIndex; + const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5; typedef size_t (*searchMax_f)( ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr); - searchMax_f const searchMax = dictMode == ZSTD_dictMatchState ? - (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_dictMatchState_selectMLS - : ZSTD_HcFindBestMatch_dictMatchState_selectMLS) : - (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_selectMLS - : ZSTD_HcFindBestMatch_selectMLS); + + /** + * This table is indexed first by the four ZSTD_dictMode_e values, and then + * by the two searchMethod_e values. NULLs are placed for configurations + * that should never occur (extDict modes go to the other implementation + * below and there is no DDSS for binary tree search yet). + */ + const searchMax_f searchFuncs[4][3] = { + { + ZSTD_HcFindBestMatch_selectMLS, + ZSTD_BtFindBestMatch_selectMLS, + ZSTD_RowFindBestMatch_selectRowLog + }, + { + NULL, + NULL, + NULL + }, + { + ZSTD_HcFindBestMatch_dictMatchState_selectMLS, + ZSTD_BtFindBestMatch_dictMatchState_selectMLS, + ZSTD_RowFindBestMatch_dictMatchState_selectRowLog + }, + { + ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS, + NULL, + ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog + } + }; + + searchMax_f const searchMax = searchFuncs[dictMode][(int)searchMethod]; U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0; + const int isDMS = dictMode == ZSTD_dictMatchState; + const int isDDS = dictMode == ZSTD_dedicatedDictSearch; + const int isDxS = isDMS || isDDS; const ZSTD_matchState_t* const dms = ms->dictMatchState; - const U32 dictLowestIndex = dictMode == ZSTD_dictMatchState ? - dms->window.dictLimit : 0; - const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ? - dms->window.base : NULL; - const BYTE* const dictLowest = dictMode == ZSTD_dictMatchState ? - dictBase + dictLowestIndex : NULL; - const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ? - dms->window.nextSrc : NULL; - const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ? + const U32 dictLowestIndex = isDxS ? dms->window.dictLimit : 0; + const BYTE* const dictBase = isDxS ? dms->window.base : NULL; + const BYTE* const dictLowest = isDxS ? dictBase + dictLowestIndex : NULL; + const BYTE* const dictEnd = isDxS ? dms->window.nextSrc : NULL; + const U32 dictIndexDelta = isDxS ? prefixLowestIndex - (U32)(dictEnd - dictBase) : 0; const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest)); - DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u)", (U32)dictMode); + assert(searchMax != NULL); - /* init */ + DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u) (searchFunc=%u)", (U32)dictMode, (U32)searchMethod); ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { - U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, ms->cParams.windowLog); - U32 const maxRep = current - windowLow; + U32 const curr = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog); + U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0; if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0; } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { /* dictMatchState repCode checks don't currently handle repCode == 0 * disabling. */ assert(offset_1 <= dictAndPrefixLength); assert(offset_2 <= dictAndPrefixLength); } + if (searchMethod == search_rowHash) { + ZSTD_row_fillHashCache(ms, base, rowLog, + MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */), + ms->nextToUpdate, ilimit); + } + /* Match Loop */ #if defined(__GNUC__) && defined(__x86_64__) /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the @@ -693,9 +1617,9 @@ ZSTD_compressBlock_lazy_generic( const BYTE* start=ip+1; /* check repCode */ - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { const U32 repIndex = (U32)(ip - base) + 1 - offset_1; - const BYTE* repMatch = (dictMode == ZSTD_dictMatchState + const BYTE* repMatch = ((dictMode == ZSTD_dictMatchState || dictMode == ZSTD_dedicatedDictSearch) && repIndex < prefixLowestIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; @@ -736,7 +1660,7 @@ ZSTD_compressBlock_lazy_generic( if ((mlRep >= 4) && (gain2 > gain1)) matchLength = mlRep, offset = 0, start = ip; } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { const U32 repIndex = (U32)(ip - base) - offset_1; const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase + (repIndex - dictIndexDelta) : @@ -771,7 +1695,7 @@ ZSTD_compressBlock_lazy_generic( if ((mlRep >= 4) && (gain2 > gain1)) matchLength = mlRep, offset = 0, start = ip; } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { const U32 repIndex = (U32)(ip - base) - offset_1; const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase + (repIndex - dictIndexDelta) : @@ -809,7 +1733,7 @@ ZSTD_compressBlock_lazy_generic( && (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */ { start--; matchLength++; } } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE)); const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex; const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest; @@ -825,12 +1749,11 @@ ZSTD_compressBlock_lazy_generic( } /* check immediate repcode */ - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { while (ip <= ilimit) { U32 const current2 = (U32)(ip-base); U32 const repIndex = current2 - offset_2; - const BYTE* repMatch = dictMode == ZSTD_dictMatchState - && repIndex < prefixLowestIndex ? + const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase - dictIndexDelta + repIndex : base + repIndex; if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */) @@ -925,6 +1848,92 @@ size_t ZSTD_compressBlock_greedy_dictMatchState( } +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch); +} + +/* Row-based matchfinder */ +size_t ZSTD_compressBlock_lazy2_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_lazy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_greedy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_lazy2_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_lazy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_greedy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState); +} + + +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch); +} + FORCE_INLINE_TEMPLATE size_t ZSTD_compressBlock_lazy_extDict_generic( ZSTD_matchState_t* ms, seqStore_t* seqStore, @@ -936,7 +1945,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const BYTE* ip = istart; const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; + const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8; const BYTE* const base = ms->window.base; const U32 dictLimit = ms->window.dictLimit; const BYTE* const prefixStart = base + dictLimit; @@ -944,18 +1953,28 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const dictStart = dictBase + ms->window.lowLimit; const U32 windowLog = ms->cParams.windowLog; + const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5; typedef size_t (*searchMax_f)( ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr); - searchMax_f searchMax = searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_extDict_selectMLS : ZSTD_HcFindBestMatch_extDict_selectMLS; - + const searchMax_f searchFuncs[3] = { + ZSTD_HcFindBestMatch_extDict_selectMLS, + ZSTD_BtFindBestMatch_extDict_selectMLS, + ZSTD_RowFindBestMatch_extDict_selectRowLog + }; + searchMax_f searchMax = searchFuncs[(int)searchMethod]; U32 offset_1 = rep[0], offset_2 = rep[1]; - DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic"); + DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)", (U32)searchMethod); /* init */ ip += (ip == prefixStart); + if (searchMethod == search_rowHash) { + ZSTD_row_fillHashCache(ms, base, rowLog, + MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */), + ms->nextToUpdate, ilimit); + } /* Match Loop */ #if defined(__GNUC__) && defined(__x86_64__) @@ -968,14 +1987,15 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( size_t matchLength=0; size_t offset=0; const BYTE* start=ip+1; - U32 current = (U32)(ip-base); + U32 curr = (U32)(ip-base); /* check repCode */ - { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current+1, windowLog); - const U32 repIndex = (U32)(current+1 - offset_1); + { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog); + const U32 repIndex = (U32)(curr+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ + if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ + & (offset_1 < curr+1 - windowLow) ) /* note: we are searching at curr+1 */ if (MEM_read32(ip+1) == MEM_read32(repMatch)) { /* repcode detected we should take it */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -999,14 +2019,15 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( if (depth>=1) while (ip<ilimit) { ip ++; - current++; + curr++; /* check repCode */ if (offset) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); - const U32 repIndex = (U32)(current - offset_1); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog); + const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ + if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (offset_1 < curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -1030,14 +2051,15 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( /* let's find an even better one */ if ((depth==2) && (ip<ilimit)) { ip ++; - current++; + curr++; /* check repCode */ if (offset) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); - const U32 repIndex = (U32)(current - offset_1); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog); + const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ + if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (offset_1 < curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -1083,7 +2105,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const U32 repIndex = repCurrent - offset_2; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ + if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (offset_2 < repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected we should take it */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -1136,3 +2159,26 @@ size_t ZSTD_compressBlock_btlazy2_extDict( { return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2); } + +size_t ZSTD_compressBlock_greedy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0); +} + +size_t ZSTD_compressBlock_lazy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) + +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1); +} + +size_t ZSTD_compressBlock_lazy2_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) + +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2); +} diff --git a/lib/compress/zstd_lazy.h b/lib/compress/zstd_lazy.h index 581936f03bd..150f7b390b8 100644 --- a/lib/compress/zstd_lazy.h +++ b/lib/compress/zstd_lazy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -17,7 +17,18 @@ extern "C" { #include "zstd_compress_internal.h" +/** + * Dedicated Dictionary Search Structure bucket log. In the + * ZSTD_dedicatedDictSearch mode, the hashTable has + * 2 ** ZSTD_LAZY_DDSS_BUCKET_LOG entries in each bucket, rather than just + * one. + */ +#define ZSTD_LAZY_DDSS_BUCKET_LOG 2 + U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip); +void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip); + +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip); void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */ @@ -33,6 +44,15 @@ size_t ZSTD_compressBlock_lazy( size_t ZSTD_compressBlock_greedy( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); size_t ZSTD_compressBlock_btlazy2_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], @@ -46,6 +66,34 @@ size_t ZSTD_compressBlock_lazy_dictMatchState( size_t ZSTD_compressBlock_greedy_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); size_t ZSTD_compressBlock_greedy_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], @@ -56,9 +104,19 @@ size_t ZSTD_compressBlock_lazy_extDict( size_t ZSTD_compressBlock_lazy2_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); size_t ZSTD_compressBlock_btlazy2_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); + #if defined (__cplusplus) } diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 8c479483581..fa4ebeabd70 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,13 +11,126 @@ #include "zstd_ldm.h" #include "../common/debug.h" +#include "../common/xxhash.h" #include "zstd_fast.h" /* ZSTD_fillHashTable() */ #include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */ +#include "zstd_ldm_geartab.h" #define LDM_BUCKET_SIZE_LOG 3 #define LDM_MIN_MATCH_LENGTH 64 #define LDM_HASH_RLOG 7 -#define LDM_HASH_CHAR_OFFSET 10 + +typedef struct { + U64 rolling; + U64 stopMask; +} ldmRollingHashState_t; + +/** ZSTD_ldm_gear_init(): + * + * Initializes the rolling hash state such that it will honor the + * settings in params. */ +static void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params) +{ + unsigned maxBitsInMask = MIN(params->minMatchLength, 64); + unsigned hashRateLog = params->hashRateLog; + + state->rolling = ~(U32)0; + + /* The choice of the splitting criterion is subject to two conditions: + * 1. it has to trigger on average every 2^(hashRateLog) bytes; + * 2. ideally, it has to depend on a window of minMatchLength bytes. + * + * In the gear hash algorithm, bit n depends on the last n bytes; + * so in order to obtain a good quality splitting criterion it is + * preferable to use bits with high weight. + * + * To match condition 1 we use a mask with hashRateLog bits set + * and, because of the previous remark, we make sure these bits + * have the highest possible weight while still respecting + * condition 2. + */ + if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) { + state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog); + } else { + /* In this degenerate case we simply honor the hash rate. */ + state->stopMask = ((U64)1 << hashRateLog) - 1; + } +} + +/** ZSTD_ldm_gear_reset() + * Feeds [data, data + minMatchLength) into the hash without registering any + * splits. This effectively resets the hash state. This is used when skipping + * over data, either at the beginning of a block, or skipping sections. + */ +static void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state, + BYTE const* data, size_t minMatchLength) +{ + U64 hash = state->rolling; + size_t n = 0; + +#define GEAR_ITER_ONCE() do { \ + hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \ + n += 1; \ + } while (0) + while (n + 3 < minMatchLength) { + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + } + while (n < minMatchLength) { + GEAR_ITER_ONCE(); + } +#undef GEAR_ITER_ONCE +} + +/** ZSTD_ldm_gear_feed(): + * + * Registers in the splits array all the split points found in the first + * size bytes following the data pointer. This function terminates when + * either all the data has been processed or LDM_BATCH_SIZE splits are + * present in the splits array. + * + * Precondition: The splits array must not be full. + * Returns: The number of bytes processed. */ +static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state, + BYTE const* data, size_t size, + size_t* splits, unsigned* numSplits) +{ + size_t n; + U64 hash, mask; + + hash = state->rolling; + mask = state->stopMask; + n = 0; + +#define GEAR_ITER_ONCE() do { \ + hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \ + n += 1; \ + if (UNLIKELY((hash & mask) == 0)) { \ + splits[*numSplits] = n; \ + *numSplits += 1; \ + if (*numSplits == LDM_BATCH_SIZE) \ + goto done; \ + } \ + } while (0) + + while (n + 3 < size) { + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + } + while (n < size) { + GEAR_ITER_ONCE(); + } + +#undef GEAR_ITER_ONCE + +done: + state->rolling = hash; + return n; +} void ZSTD_ldm_adjustParameters(ldmParams_t* params, ZSTD_compressionParameters const* cParams) @@ -27,13 +140,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH; - if (cParams->strategy >= ZSTD_btopt) { - /* Get out of the way of the optimal parser */ - U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength); - assert(minMatch >= ZSTD_LDM_MINMATCH_MIN); - assert(minMatch <= ZSTD_LDM_MINMATCH_MAX); - params->minMatchLength = minMatch; - } if (params->hashLog == 0) { params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG); assert(params->hashLog <= ZSTD_HASHLOG_MAX); @@ -61,41 +167,6 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize) return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0; } -/** ZSTD_ldm_getSmallHash() : - * numBits should be <= 32 - * If numBits==0, returns 0. - * @return : the most significant numBits of value. */ -static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits) -{ - assert(numBits <= 32); - return numBits == 0 ? 0 : (U32)(value >> (64 - numBits)); -} - -/** ZSTD_ldm_getChecksum() : - * numBitsToDiscard should be <= 32 - * @return : the next most significant 32 bits after numBitsToDiscard */ -static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard) -{ - assert(numBitsToDiscard <= 32); - return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF; -} - -/** ZSTD_ldm_getTag() ; - * Given the hash, returns the most significant numTagBits bits - * after (32 + hbits) bits. - * - * If there are not enough bits remaining, return the last - * numTagBits bits. */ -static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits) -{ - assert(numTagBits < 32 && hbits <= 32); - if (32 - hbits < numTagBits) { - return hash & (((U32)1 << numTagBits) - 1); - } else { - return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1); - } -} - /** ZSTD_ldm_getBucket() : * Returns a pointer to the start of the bucket associated with hash. */ static ldmEntry_t* ZSTD_ldm_getBucket( @@ -110,38 +181,12 @@ static void ZSTD_ldm_insertEntry(ldmState_t* ldmState, size_t const hash, const ldmEntry_t entry, ldmParams_t const ldmParams) { - BYTE* const bucketOffsets = ldmState->bucketOffsets; - *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + bucketOffsets[hash]) = entry; - bucketOffsets[hash]++; - bucketOffsets[hash] &= ((U32)1 << ldmParams.bucketSizeLog) - 1; -} + BYTE* const pOffset = ldmState->bucketOffsets + hash; + unsigned const offset = *pOffset; + + *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + offset) = entry; + *pOffset = (BYTE)((offset + 1) & ((1u << ldmParams.bucketSizeLog) - 1)); -/** ZSTD_ldm_makeEntryAndInsertByTag() : - * - * Gets the small hash, checksum, and tag from the rollingHash. - * - * If the tag matches (1 << ldmParams.hashRateLog)-1, then - * creates an ldmEntry from the offset, and inserts it into the hash table. - * - * hBits is the length of the small hash, which is the most significant hBits - * of rollingHash. The checksum is the next 32 most significant bits, followed - * by ldmParams.hashRateLog bits that make up the tag. */ -static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState, - U64 const rollingHash, - U32 const hBits, - U32 const offset, - ldmParams_t const ldmParams) -{ - U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashRateLog); - U32 const tagMask = ((U32)1 << ldmParams.hashRateLog) - 1; - if (tag == tagMask) { - U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits); - U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits); - ldmEntry_t entry; - entry.offset = offset; - entry.checksum = checksum; - ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams); - } } /** ZSTD_ldm_countBackwardsMatch() : @@ -150,10 +195,10 @@ static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState, * We count only bytes where pMatch >= pBase and pIn >= pAnchor. */ static size_t ZSTD_ldm_countBackwardsMatch( const BYTE* pIn, const BYTE* pAnchor, - const BYTE* pMatch, const BYTE* pBase) + const BYTE* pMatch, const BYTE* pMatchBase) { size_t matchLength = 0; - while (pIn > pAnchor && pMatch > pBase && pIn[-1] == pMatch[-1]) { + while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) { pIn--; pMatch--; matchLength++; @@ -161,6 +206,27 @@ static size_t ZSTD_ldm_countBackwardsMatch( return matchLength; } +/** ZSTD_ldm_countBackwardsMatch_2segments() : + * Returns the number of bytes that match backwards from pMatch, + * even with the backwards match spanning 2 different segments. + * + * On reaching `pMatchBase`, start counting from mEnd */ +static size_t ZSTD_ldm_countBackwardsMatch_2segments( + const BYTE* pIn, const BYTE* pAnchor, + const BYTE* pMatch, const BYTE* pMatchBase, + const BYTE* pExtDictStart, const BYTE* pExtDictEnd) +{ + size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase); + if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) { + /* If backwards match is entirely in the extDict or prefix, immediately return */ + return matchLength; + } + DEBUGLOG(7, "ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)", matchLength); + matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart); + DEBUGLOG(7, "final backwards match length = %zu", matchLength); + return matchLength; +} + /** ZSTD_ldm_fillFastTables() : * * Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies. @@ -198,43 +264,42 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms, return 0; } -/** ZSTD_ldm_fillLdmHashTable() : - * - * Fills hashTable from (lastHashed + 1) to iend (non-inclusive). - * lastHash is the rolling hash that corresponds to lastHashed. - * - * Returns the rolling hash corresponding to position iend-1. */ -static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state, - U64 lastHash, const BYTE* lastHashed, - const BYTE* iend, const BYTE* base, - U32 hBits, ldmParams_t const ldmParams) -{ - U64 rollingHash = lastHash; - const BYTE* cur = lastHashed + 1; - - while (cur < iend) { - rollingHash = ZSTD_rollingHash_rotate(rollingHash, cur[-1], - cur[ldmParams.minMatchLength-1], - state->hashPower); - ZSTD_ldm_makeEntryAndInsertByTag(state, - rollingHash, hBits, - (U32)(cur - base), ldmParams); - ++cur; - } - return rollingHash; -} - void ZSTD_ldm_fillHashTable( - ldmState_t* state, const BYTE* ip, + ldmState_t* ldmState, const BYTE* ip, const BYTE* iend, ldmParams_t const* params) { + U32 const minMatchLength = params->minMatchLength; + U32 const hBits = params->hashLog - params->bucketSizeLog; + BYTE const* const base = ldmState->window.base; + BYTE const* const istart = ip; + ldmRollingHashState_t hashState; + size_t* const splits = ldmState->splitIndices; + unsigned numSplits; + DEBUGLOG(5, "ZSTD_ldm_fillHashTable"); - if ((size_t)(iend - ip) >= params->minMatchLength) { - U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength); - ZSTD_ldm_fillLdmHashTable( - state, startingHash, ip, iend - params->minMatchLength, state->window.base, - params->hashLog - params->bucketSizeLog, - *params); + + ZSTD_ldm_gear_init(&hashState, params); + while (ip < iend) { + size_t hashed; + unsigned n; + + numSplits = 0; + hashed = ZSTD_ldm_gear_feed(&hashState, ip, iend - ip, splits, &numSplits); + + for (n = 0; n < numSplits; n++) { + if (ip + splits[n] >= istart + minMatchLength) { + BYTE const* const split = ip + splits[n] - minMatchLength; + U64 const xxhash = XXH64(split, minMatchLength, 0); + U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1)); + ldmEntry_t entry; + + entry.offset = (U32)(split - base); + entry.checksum = (U32)(xxhash >> 32); + ZSTD_ldm_insertEntry(ldmState, hash, entry, *params); + } + } + + ip += hashed; } } @@ -246,10 +311,10 @@ void ZSTD_ldm_fillHashTable( * (after a long match, only update tables a limited amount). */ static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor) { - U32 const current = (U32)(anchor - ms->window.base); - if (current > ms->nextToUpdate + 1024) { + U32 const curr = (U32)(anchor - ms->window.base); + if (curr > ms->nextToUpdate + 1024) { ms->nextToUpdate = - current - MIN(512, current - ms->nextToUpdate - 1024); + curr - MIN(512, curr - ms->nextToUpdate - 1024); } } @@ -260,11 +325,8 @@ static size_t ZSTD_ldm_generateSequences_internal( /* LDM parameters */ int const extDict = ZSTD_window_hasExtDict(ldmState->window); U32 const minMatchLength = params->minMatchLength; - U64 const hashPower = ldmState->hashPower; + U32 const entsPerBucket = 1U << params->bucketSizeLog; U32 const hBits = params->hashLog - params->bucketSizeLog; - U32 const ldmBucketSize = 1U << params->bucketSizeLog; - U32 const hashRateLog = params->hashRateLog; - U32 const ldmTagMask = (1U << params->hashRateLog) - 1; /* Prefix and extDict parameters */ U32 const dictLimit = ldmState->window.dictLimit; U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit; @@ -276,45 +338,69 @@ static size_t ZSTD_ldm_generateSequences_internal( /* Input bounds */ BYTE const* const istart = (BYTE const*)src; BYTE const* const iend = istart + srcSize; - BYTE const* const ilimit = iend - MAX(minMatchLength, HASH_READ_SIZE); + BYTE const* const ilimit = iend - HASH_READ_SIZE; /* Input positions */ BYTE const* anchor = istart; BYTE const* ip = istart; - /* Rolling hash */ - BYTE const* lastHashed = NULL; - U64 rollingHash = 0; - - while (ip <= ilimit) { - size_t mLength; - U32 const current = (U32)(ip - base); - size_t forwardMatchLength = 0, backwardMatchLength = 0; - ldmEntry_t* bestEntry = NULL; - if (ip != istart) { - rollingHash = ZSTD_rollingHash_rotate(rollingHash, lastHashed[0], - lastHashed[minMatchLength], - hashPower); - } else { - rollingHash = ZSTD_rollingHash_compute(ip, minMatchLength); + /* Rolling hash state */ + ldmRollingHashState_t hashState; + /* Arrays for staged-processing */ + size_t* const splits = ldmState->splitIndices; + ldmMatchCandidate_t* const candidates = ldmState->matchCandidates; + unsigned numSplits; + + if (srcSize < minMatchLength) + return iend - anchor; + + /* Initialize the rolling hash state with the first minMatchLength bytes */ + ZSTD_ldm_gear_init(&hashState, params); + ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength); + ip += minMatchLength; + + while (ip < ilimit) { + size_t hashed; + unsigned n; + + numSplits = 0; + hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip, + splits, &numSplits); + + for (n = 0; n < numSplits; n++) { + BYTE const* const split = ip + splits[n] - minMatchLength; + U64 const xxhash = XXH64(split, minMatchLength, 0); + U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1)); + + candidates[n].split = split; + candidates[n].hash = hash; + candidates[n].checksum = (U32)(xxhash >> 32); + candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *params); + PREFETCH_L1(candidates[n].bucket); } - lastHashed = ip; - /* Do not insert and do not look for a match */ - if (ZSTD_ldm_getTag(rollingHash, hBits, hashRateLog) != ldmTagMask) { - ip++; - continue; - } + for (n = 0; n < numSplits; n++) { + size_t forwardMatchLength = 0, backwardMatchLength = 0, + bestMatchLength = 0, mLength; + U32 offset; + BYTE const* const split = candidates[n].split; + U32 const checksum = candidates[n].checksum; + U32 const hash = candidates[n].hash; + ldmEntry_t* const bucket = candidates[n].bucket; + ldmEntry_t const* cur; + ldmEntry_t const* bestEntry = NULL; + ldmEntry_t newEntry; + + newEntry.offset = (U32)(split - base); + newEntry.checksum = checksum; + + /* If a split point would generate a sequence overlapping with + * the previous one, we merely register it in the hash table and + * move on */ + if (split < anchor) { + ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params); + continue; + } - /* Get the best entry and compute the match lengths */ - { - ldmEntry_t* const bucket = - ZSTD_ldm_getBucket(ldmState, - ZSTD_ldm_getSmallHash(rollingHash, hBits), - *params); - ldmEntry_t* cur; - size_t bestMatchLength = 0; - U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits); - - for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) { + for (cur = bucket; cur < bucket + entsPerBucket; cur++) { size_t curForwardMatchLength, curBackwardMatchLength, curTotalMatchLength; if (cur->checksum != checksum || cur->offset <= lowestIndex) { @@ -328,30 +414,23 @@ static size_t ZSTD_ldm_generateSequences_internal( cur->offset < dictLimit ? dictEnd : iend; BYTE const* const lowMatchPtr = cur->offset < dictLimit ? dictStart : lowPrefixPtr; - - curForwardMatchLength = ZSTD_count_2segments( - ip, pMatch, iend, - matchEnd, lowPrefixPtr); + curForwardMatchLength = + ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr); if (curForwardMatchLength < minMatchLength) { continue; } - curBackwardMatchLength = - ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch, - lowMatchPtr); - curTotalMatchLength = curForwardMatchLength + - curBackwardMatchLength; + curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments( + split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd); } else { /* !extDict */ BYTE const* const pMatch = base + cur->offset; - curForwardMatchLength = ZSTD_count(ip, pMatch, iend); + curForwardMatchLength = ZSTD_count(split, pMatch, iend); if (curForwardMatchLength < minMatchLength) { continue; } curBackwardMatchLength = - ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch, - lowPrefixPtr); - curTotalMatchLength = curForwardMatchLength + - curBackwardMatchLength; + ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr); } + curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength; if (curTotalMatchLength > bestMatchLength) { bestMatchLength = curTotalMatchLength; @@ -360,57 +439,54 @@ static size_t ZSTD_ldm_generateSequences_internal( bestEntry = cur; } } - } - - /* No match found -- continue searching */ - if (bestEntry == NULL) { - ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, - hBits, current, - *params); - ip++; - continue; - } - /* Match found */ - mLength = forwardMatchLength + backwardMatchLength; - ip -= backwardMatchLength; + /* No match found -- insert an entry into the hash table + * and process the next candidate match */ + if (bestEntry == NULL) { + ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params); + continue; + } - { - /* Store the sequence: - * ip = current - backwardMatchLength - * The match is at (bestEntry->offset - backwardMatchLength) - */ - U32 const matchIndex = bestEntry->offset; - U32 const offset = current - matchIndex; - rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size; - - /* Out of sequence storage */ - if (rawSeqStore->size == rawSeqStore->capacity) - return ERROR(dstSize_tooSmall); - seq->litLength = (U32)(ip - anchor); - seq->matchLength = (U32)mLength; - seq->offset = offset; - rawSeqStore->size++; - } + /* Match found */ + offset = (U32)(split - base) - bestEntry->offset; + mLength = forwardMatchLength + backwardMatchLength; + { + rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size; + + /* Out of sequence storage */ + if (rawSeqStore->size == rawSeqStore->capacity) + return ERROR(dstSize_tooSmall); + seq->litLength = (U32)(split - backwardMatchLength - anchor); + seq->matchLength = (U32)mLength; + seq->offset = offset; + rawSeqStore->size++; + } - /* Insert the current entry into the hash table */ - ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits, - (U32)(lastHashed - base), - *params); + /* Insert the current entry into the hash table --- it must be + * done after the previous block to avoid clobbering bestEntry */ + ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params); - assert(ip + backwardMatchLength == lastHashed); + anchor = split + forwardMatchLength; - /* Fill the hash table from lastHashed+1 to ip+mLength*/ - /* Heuristic: don't need to fill the entire table at end of block */ - if (ip + mLength <= ilimit) { - rollingHash = ZSTD_ldm_fillLdmHashTable( - ldmState, rollingHash, lastHashed, - ip + mLength, base, hBits, *params); - lastHashed = ip + mLength - 1; + /* If we find a match that ends after the data that we've hashed + * then we have a repeating, overlapping, pattern. E.g. all zeros. + * If one repetition of the pattern matches our `stopMask` then all + * repetitions will. We don't need to insert them all into out table, + * only the first one. So skip over overlapping matches. + * This is a major speed boost (20x) for compressing a single byte + * repeated, when that byte ends up in the table. + */ + if (anchor > ip + hashed) { + ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength); + /* Continue the outter loop at anchor (ip + hashed == anchor). */ + ip = anchor - hashed; + break; + } } - ip += mLength; - anchor = ip; + + ip += hashed; } + return iend - anchor; } @@ -459,7 +535,7 @@ size_t ZSTD_ldm_generateSequences( assert(chunkStart < iend); /* 1. Perform overflow correction if necessary. */ - if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) { + if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) { U32 const ldmHSize = 1U << params->hashLog; U32 const correction = ZSTD_window_correctOverflow( &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart); @@ -562,14 +638,32 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore, return sequence; } +void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { + U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); + while (currPos && rawSeqStore->pos < rawSeqStore->size) { + rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; + if (currPos >= currSeq.litLength + currSeq.matchLength) { + currPos -= currSeq.litLength + currSeq.matchLength; + rawSeqStore->pos++; + } else { + rawSeqStore->posInSequence = currPos; + break; + } + } + if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { + rawSeqStore->posInSequence = 0; + } +} + size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_useRowMatchFinderMode_e useRowMatchFinder, void const* src, size_t srcSize) { const ZSTD_compressionParameters* const cParams = &ms->cParams; unsigned const minMatch = cParams->minMatch; ZSTD_blockCompressor const blockCompressor = - ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms)); + ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms)); /* Input bounds */ BYTE const* const istart = (BYTE const*)src; BYTE const* const iend = istart + srcSize; @@ -577,9 +671,18 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, BYTE const* ip = istart; DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize); + /* If using opt parser, use LDMs only as candidates rather than always accepting them */ + if (cParams->strategy >= ZSTD_btopt) { + size_t lastLLSize; + ms->ldmSeqStore = rawSeqStore; + lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize); + ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize); + return lastLLSize; + } + assert(rawSeqStore->pos <= rawSeqStore->size); assert(rawSeqStore->size <= rawSeqStore->capacity); - /* Loop through each sequence and apply the block compressor to the lits */ + /* Loop through each sequence and apply the block compressor to the literals */ while (rawSeqStore->pos < rawSeqStore->size && ip < iend) { /* maybeSplitSequence updates rawSeqStore->pos */ rawSeq const sequence = maybeSplitSequence(rawSeqStore, diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index 229ea05a9e1..393466fa9f5 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -66,6 +66,7 @@ size_t ZSTD_ldm_generateSequences( */ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_useRowMatchFinderMode_e useRowMatchFinder, void const* src, size_t srcSize); /** @@ -73,11 +74,17 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, * * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`. * Avoids emitting matches less than `minMatch` bytes. - * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). + * Must be called for data that is not passed to ZSTD_ldm_blockCompress(). */ void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch); +/* ZSTD_ldm_skipRawSeqStoreBytes(): + * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'. + * Not to be used in conjunction with ZSTD_ldm_skipSequences(). + * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). + */ +void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes); /** ZSTD_ldm_getTableSize() : * Estimate the space needed for long distance matching tables or 0 if LDM is diff --git a/lib/compress/zstd_ldm_geartab.h b/lib/compress/zstd_ldm_geartab.h new file mode 100644 index 00000000000..e5c24d856b0 --- /dev/null +++ b/lib/compress/zstd_ldm_geartab.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_LDM_GEARTAB_H +#define ZSTD_LDM_GEARTAB_H + +static U64 ZSTD_ldm_gearTab[256] = { + 0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc, + 0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05, + 0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e, + 0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889, + 0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e, + 0x37b628620b628, 0x49a8d455d88caf5, 0x8556d711e6958140, + 0x4f7ae74fc605c1f, 0x829f0c3468bd3a20, 0x4ffdc885c625179e, + 0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f, + 0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391, + 0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210, + 0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be, + 0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a, + 0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b, + 0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4, + 0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb, + 0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312, + 0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01, + 0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc, + 0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967, + 0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553, + 0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f, + 0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2, + 0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d, + 0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a, + 0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74, + 0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3, + 0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1, + 0xff452823dbb010a, 0x9d42ed614f3dd267, 0x5b9313c06257c57b, + 0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568, + 0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a, + 0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1, + 0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9, + 0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463, + 0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba, + 0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9, + 0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61, + 0x24a5483879c453e3, 0x88026889192b4b9, 0x28da96671782dbec, + 0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6, + 0xbc135a0a704b70ba, 0x69cd868f7622ada, 0xbc37ba89e0b9c0ab, + 0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5, + 0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59, + 0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7, + 0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc, + 0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb, + 0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be, + 0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312, + 0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1, + 0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc, + 0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d, + 0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445, + 0x820d471e20b348e, 0x1874383cb83d46dc, 0x97edeec7a1efe11c, + 0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5, + 0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5, + 0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28, + 0xaf846af6ab7d0bf4, 0xe5af208eb666e49, 0x5e6622f73534cd6a, + 0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9, + 0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15, + 0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef, + 0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2, + 0x9f90e4c5fd508d8, 0xa34e5956fbaf3385, 0x2e2f8e151d3ef375, + 0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3, + 0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595, + 0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389, + 0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4, + 0x4228e364c5b5ed7, 0x9d7a3edf0da43911, 0x8edcfeda24686756, + 0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc, + 0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45, + 0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea, + 0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f, + 0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc, + 0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c, + 0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a, + 0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17, + 0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3, + 0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4, + 0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91, + 0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40, + 0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741, + 0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f, + 0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4, + 0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad, + 0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047, + 0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2, + 0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e, + 0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b, + 0x2b4da14f2613d8f4 +}; + +#endif /* ZSTD_LDM_GEARTAB_H */ diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 36fff050cf5..402a7e5c76b 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -386,32 +386,32 @@ static U32 ZSTD_insertBt1( const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* match; - const U32 current = (U32)(ip-base); - const U32 btLow = btMask >= current ? 0 : current - btMask; - U32* smallerPtr = bt + 2*(current&btMask); + const U32 curr = (U32)(ip-base); + const U32 btLow = btMask >= curr ? 0 : curr - btMask; + U32* smallerPtr = bt + 2*(curr&btMask); U32* largerPtr = smallerPtr + 1; U32 dummy32; /* to be nullified at the end */ U32 const windowLow = ms->window.lowLimit; - U32 matchEndIdx = current+8+1; + U32 matchEndIdx = curr+8+1; size_t bestLength = 8; U32 nbCompares = 1U << cParams->searchLog; #ifdef ZSTD_C_PREDICT - U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0); - U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1); + U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0); + U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1); predictedSmall += (predictedSmall>0); predictedLarge += (predictedLarge>0); #endif /* ZSTD_C_PREDICT */ - DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current); + DEBUGLOG(8, "ZSTD_insertBt1 (%u)", curr); assert(ip <= iend-8); /* required for h calculation */ - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ assert(windowLow > 0); while (nbCompares-- && (matchIndex >= windowLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(matchIndex < current); + assert(matchIndex < curr); #ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */ @@ -474,8 +474,8 @@ static U32 ZSTD_insertBt1( *smallerPtr = *largerPtr = 0; { U32 positions = 0; if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */ - assert(matchEndIdx > current + 8); - return MAX(positions, matchEndIdx - (current + 8)); + assert(matchEndIdx > curr + 8); + return MAX(positions, matchEndIdx - (curr + 8)); } } @@ -519,7 +519,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( const ZSTD_compressionParameters* const cParams = &ms->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); const BYTE* const base = ms->window.base; - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const hashLog = cParams->hashLog; U32 const minMatch = (mls==3) ? 3 : 4; U32* const hashTable = ms->hashTable; @@ -533,12 +533,12 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dictLimit = ms->window.dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; - U32 const btLow = (btMask >= current) ? 0 : current - btMask; - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog); + U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); U32 const matchLow = windowLow ? windowLow : 1; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */ + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = bt + 2*(curr&btMask) + 1; + U32 matchEndIdx = curr+8+1; /* farthest referenced position of any match => detects repetitive patterns */ U32 dummy32; /* to be nullified at the end */ U32 mnum = 0; U32 nbCompares = 1U << cParams->searchLog; @@ -557,7 +557,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit; size_t bestLength = lengthToBeat-1; - DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current); + DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", curr); /* check repCode */ assert(ll0 <= 1); /* necessarily 1 or 0 */ @@ -565,29 +565,29 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 repCode; for (repCode = ll0; repCode < lastR; repCode++) { U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; - U32 const repIndex = current - repOffset; + U32 const repIndex = curr - repOffset; U32 repLen = 0; - assert(current >= dictLimit); - if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */ + assert(curr >= dictLimit); + if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) { /* equivalent to `curr > repIndex >= dictLimit` */ /* We must validate the repcode offset because when we're using a dictionary the * valid offset range shrinks when the dictionary goes out of bounds. */ if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) { repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch; } - } else { /* repIndex < dictLimit || repIndex >= current */ + } else { /* repIndex < dictLimit || repIndex >= curr */ const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ? dmsBase + repIndex - dmsIndexDelta : dictBase + repIndex; - assert(current >= windowLow); + assert(curr >= windowLow); if ( dictMode == ZSTD_extDict - && ( ((repOffset-1) /*intentional overflow*/ < current - windowLow) /* equivalent to `current > repIndex >= windowLow` */ + && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow) /* equivalent to `curr > repIndex >= windowLow` */ & (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */) && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch; } if (dictMode == ZSTD_dictMatchState - && ( ((repOffset-1) /*intentional overflow*/ < current - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `current > repIndex >= dmsLowLimit` */ + && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `curr > repIndex >= dmsLowLimit` */ & ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch; @@ -609,7 +609,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( if ((mls == 3) /*static*/ && (bestLength < mls)) { U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip); if ((matchIndex3 >= matchLow) - & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { + & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { size_t mlen; if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) { const BYTE* const match = base + matchIndex3; @@ -624,26 +624,26 @@ U32 ZSTD_insertBtAndGetAllMatches ( DEBUGLOG(8, "found small match with hlog3, of length %u", (U32)mlen); bestLength = mlen; - assert(current > matchIndex3); + assert(curr > matchIndex3); assert(mnum==0); /* no prior solution */ - matches[0].off = (current - matchIndex3) + ZSTD_REP_MOVE; + matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE; matches[0].len = (U32)mlen; mnum = 1; if ( (mlen > sufficient_len) | (ip+mlen == iLimit) ) { /* best possible length */ - ms->nextToUpdate = current+1; /* skip insertion */ + ms->nextToUpdate = curr+1; /* skip insertion */ return 1; } } } /* no dictMatchState lookup: dicts don't have a populated HC3 table */ } - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ while (nbCompares-- && (matchIndex >= matchLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); const BYTE* match; size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(current > matchIndex); + assert(curr > matchIndex); if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) { assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */ @@ -660,12 +660,12 @@ U32 ZSTD_insertBtAndGetAllMatches ( if (matchLength > bestLength) { DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)", - (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE); + (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE); assert(matchEndIdx > matchIndex); if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; bestLength = matchLength; - matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE; + matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE; matches[mnum].len = (U32)matchLength; mnum++; if ( (matchLength > ZSTD_OPT_NUM) @@ -708,11 +708,11 @@ U32 ZSTD_insertBtAndGetAllMatches ( if (matchLength > bestLength) { matchIndex = dictMatchIndex + dmsIndexDelta; DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)", - (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE); + (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE); if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; bestLength = matchLength; - matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE; + matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE; matches[mnum].len = (U32)matchLength; mnum++; if ( (matchLength > ZSTD_OPT_NUM) @@ -733,7 +733,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( } } - assert(matchEndIdx > current+8); + assert(matchEndIdx > curr+8); ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ return mnum; } @@ -764,6 +764,140 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( } } +/************************* +* LDM helper functions * +*************************/ + +/* Struct containing info needed to make decision about ldm inclusion */ +typedef struct { + rawSeqStore_t seqStore; /* External match candidates store for this block */ + U32 startPosInBlock; /* Start position of the current match candidate */ + U32 endPosInBlock; /* End position of the current match candidate */ + U32 offset; /* Offset of the match candidate */ +} ZSTD_optLdm_t; + +/* ZSTD_optLdm_skipRawSeqStoreBytes(): + * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'. + */ +static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { + U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); + while (currPos && rawSeqStore->pos < rawSeqStore->size) { + rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; + if (currPos >= currSeq.litLength + currSeq.matchLength) { + currPos -= currSeq.litLength + currSeq.matchLength; + rawSeqStore->pos++; + } else { + rawSeqStore->posInSequence = currPos; + break; + } + } + if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { + rawSeqStore->posInSequence = 0; + } +} + +/* ZSTD_opt_getNextMatchAndUpdateSeqStore(): + * Calculates the beginning and end of the next match in the current block. + * Updates 'pos' and 'posInSequence' of the ldmSeqStore. + */ +static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock, + U32 blockBytesRemaining) { + rawSeq currSeq; + U32 currBlockEndPos; + U32 literalsBytesRemaining; + U32 matchBytesRemaining; + + /* Setting match end position to MAX to ensure we never use an LDM during this block */ + if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { + optLdm->startPosInBlock = UINT_MAX; + optLdm->endPosInBlock = UINT_MAX; + return; + } + /* Calculate appropriate bytes left in matchLength and litLength after adjusting + based on ldmSeqStore->posInSequence */ + currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos]; + assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength); + currBlockEndPos = currPosInBlock + blockBytesRemaining; + literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ? + currSeq.litLength - (U32)optLdm->seqStore.posInSequence : + 0; + matchBytesRemaining = (literalsBytesRemaining == 0) ? + currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) : + currSeq.matchLength; + + /* If there are more literal bytes than bytes remaining in block, no ldm is possible */ + if (literalsBytesRemaining >= blockBytesRemaining) { + optLdm->startPosInBlock = UINT_MAX; + optLdm->endPosInBlock = UINT_MAX; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining); + return; + } + + /* Matches may be < MINMATCH by this process. In that case, we will reject them + when we are deciding whether or not to add the ldm */ + optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining; + optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining; + optLdm->offset = currSeq.offset; + + if (optLdm->endPosInBlock > currBlockEndPos) { + /* Match ends after the block ends, we can't use the whole match */ + optLdm->endPosInBlock = currBlockEndPos; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock); + } else { + /* Consume nb of bytes equal to size of sequence left */ + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining); + } +} + +/* ZSTD_optLdm_maybeAddMatch(): + * Adds a match if it's long enough, based on it's 'matchStartPosInBlock' + * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches' + */ +static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches, + ZSTD_optLdm_t* optLdm, U32 currPosInBlock) { + U32 posDiff = currPosInBlock - optLdm->startPosInBlock; + /* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */ + U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff; + U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE; + + /* Ensure that current block position is not outside of the match */ + if (currPosInBlock < optLdm->startPosInBlock + || currPosInBlock >= optLdm->endPosInBlock + || candidateMatchLength < MINMATCH) { + return; + } + + if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) { + DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u", + candidateOffCode, candidateMatchLength, currPosInBlock); + matches[*nbMatches].len = candidateMatchLength; + matches[*nbMatches].off = candidateOffCode; + (*nbMatches)++; + } +} + +/* ZSTD_optLdm_processMatchCandidate(): + * Wrapper function to update ldm seq store and call ldm functions as necessary. + */ +static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches, + U32 currPosInBlock, U32 remainingBytes) { + if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { + return; + } + + if (currPosInBlock >= optLdm->endPosInBlock) { + if (currPosInBlock > optLdm->endPosInBlock) { + /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily + * at the end of a match from the ldm seq store, and will often be some bytes + * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots" + */ + U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot); + } + ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes); + } + ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock); +} /*-******************************* * Optimal parser @@ -817,6 +951,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, ZSTD_optimal_t* const opt = optStatePtr->priceTable; ZSTD_match_t* const matches = optStatePtr->matchTable; ZSTD_optimal_t lastSequence; + ZSTD_optLdm_t optLdm; + + optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore; + optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0; + ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip)); /* init */ DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u", @@ -832,7 +971,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* find first match */ { U32 const litlen = (U32)(ip - anchor); U32 const ll0 = !litlen; - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch); + U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch); + ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, + (U32)(ip-istart), (U32)(iend - ip)); if (!nbMatches) { ip++; continue; } /* initialize opt[0] */ @@ -925,9 +1066,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, if (opt[cur].mlen != 0) { U32 const prev = cur - opt[cur].mlen; repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0); - memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); + ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); } else { - memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t)); + ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t)); } /* last match must start at a minimum distance of 8 from oend */ @@ -945,8 +1086,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0; U32 const previousPrice = opt[cur].price; U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel); - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); + U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); U32 matchNb; + + ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, + (U32)(inr-istart), (U32)(iend-inr)); + if (!nbMatches) { DEBUGLOG(7, "rPos:%u : no match found", cur); continue; @@ -1010,9 +1155,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, */ if (lastSequence.mlen != 0) { repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0); - memcpy(rep, &reps, sizeof(reps)); + ZSTD_memcpy(rep, &reps, sizeof(reps)); } else { - memcpy(rep, opt[cur].rep, sizeof(repcodes_t)); + ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t)); } { U32 const storeEnd = cur + 1; @@ -1110,7 +1255,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms, const void* src, size_t srcSize) { U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */ - memcpy(tmpRep, rep, sizeof(tmpRep)); + ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep)); DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize); assert(ms->opt.litLengthSum == 0); /* first block */ @@ -1143,7 +1288,7 @@ size_t ZSTD_compressBlock_btultra2( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - U32 const current = (U32)((const BYTE*)src - ms->window.base); + U32 const curr = (U32)((const BYTE*)src - ms->window.base); DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize); /* 2-pass strategy: @@ -1158,7 +1303,7 @@ size_t ZSTD_compressBlock_btultra2( if ( (ms->opt.litLengthSum==0) /* first block */ && (seqStore->sequences == seqStore->sequencesStart) /* no ldm */ && (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */ - && (current == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */ + && (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */ && (srcSize > ZSTD_PREDEF_THRESHOLD) ) { ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize); diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h index 9aba8a9018c..627255f53de 100644 --- a/lib/compress/zstd_opt.h +++ b/lib/compress/zstd_opt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 1e3c8fdbee2..22aa3e1245a 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -20,8 +20,7 @@ /* ====== Dependencies ====== */ -#include <string.h> /* memcpy, memset */ -#include <limits.h> /* INT_MAX, UINT_MAX */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */ #include "../common/mem.h" /* MEM_STATIC */ #include "../common/pool.h" /* threadpool */ #include "../common/threading.h" /* mutex */ @@ -106,11 +105,11 @@ typedef struct ZSTDMT_bufferPool_s { static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem) { unsigned const maxNbBuffers = 2*nbWorkers + 3; - ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc( + ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc( sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem); if (bufPool==NULL) return NULL; if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) { - ZSTD_free(bufPool, cMem); + ZSTD_customFree(bufPool, cMem); return NULL; } bufPool->bufferSize = 64 KB; @@ -127,10 +126,10 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool) if (!bufPool) return; /* compatibility with free on NULL */ for (u=0; u<bufPool->totalBuffers; u++) { DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start); - ZSTD_free(bufPool->bTable[u].start, bufPool->cMem); + ZSTD_customFree(bufPool->bTable[u].start, bufPool->cMem); } ZSTD_pthread_mutex_destroy(&bufPool->poolMutex); - ZSTD_free(bufPool, bufPool->cMem); + ZSTD_customFree(bufPool, bufPool->cMem); } /* only works at initialization, not during compression */ @@ -201,13 +200,13 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) } /* size conditions not respected : scratch this buffer, create new one */ DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing"); - ZSTD_free(buf.start, bufPool->cMem); + ZSTD_customFree(buf.start, bufPool->cMem); } ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); /* create new buffer */ DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer"); { buffer_t buffer; - void* const start = ZSTD_malloc(bSize, bufPool->cMem); + void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); buffer.start = start; /* note : start can be NULL if malloc fails ! */ buffer.capacity = (start==NULL) ? 0 : bSize; if (start==NULL) { @@ -229,13 +228,13 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer) { size_t const bSize = bufPool->bufferSize; if (buffer.capacity < bSize) { - void* const start = ZSTD_malloc(bSize, bufPool->cMem); + void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); buffer_t newBuffer; newBuffer.start = start; newBuffer.capacity = start == NULL ? 0 : bSize; if (start != NULL) { assert(newBuffer.capacity >= buffer.capacity); - memcpy(newBuffer.start, buffer.start, buffer.capacity); + ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity); DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize); return newBuffer; } @@ -261,14 +260,12 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf) ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); /* Reached bufferPool capacity (should not happen) */ DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing "); - ZSTD_free(buf.start, bufPool->cMem); + ZSTD_customFree(buf.start, bufPool->cMem); } /* ===== Seq Pool Wrapper ====== */ -static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0}; - typedef ZSTDMT_bufferPool ZSTDMT_seqPool; static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) @@ -278,7 +275,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) static rawSeqStore_t bufferToSeq(buffer_t buffer) { - rawSeqStore_t seq = {NULL, 0, 0, 0}; + rawSeqStore_t seq = kNullRawSeqStore; seq.seq = (rawSeq*)buffer.start; seq.capacity = buffer.capacity / sizeof(rawSeq); return seq; @@ -354,7 +351,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool) for (cid=0; cid<pool->totalCCtx; cid++) ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */ ZSTD_pthread_mutex_destroy(&pool->poolMutex); - ZSTD_free(pool, pool->cMem); + ZSTD_customFree(pool, pool->cMem); } /* ZSTDMT_createCCtxPool() : @@ -362,12 +359,12 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool) static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers, ZSTD_customMem cMem) { - ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc( + ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_customCalloc( sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem); assert(nbWorkers > 0); if (!cctxPool) return NULL; if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) { - ZSTD_free(cctxPool, cMem); + ZSTD_customFree(cctxPool, cMem); return NULL; } cctxPool->cMem = cMem; @@ -475,10 +472,8 @@ ZSTDMT_serialState_reset(serialState_t* serialState, ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); assert(params.ldmParams.hashRateLog < 32); - serialState->ldmState.hashPower = - ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength); } else { - memset(¶ms.ldmParams, 0, sizeof(params.ldmParams)); + ZSTD_memset(¶ms.ldmParams, 0, sizeof(params.ldmParams)); } serialState->nextJobID = 0; if (params.fParams.checksumFlag) @@ -489,35 +484,35 @@ ZSTDMT_serialState_reset(serialState_t* serialState, size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t); unsigned const bucketLog = params.ldmParams.hashLog - params.ldmParams.bucketSizeLog; - size_t const bucketSize = (size_t)1 << bucketLog; unsigned const prevBucketLog = serialState->params.ldmParams.hashLog - serialState->params.ldmParams.bucketSizeLog; + size_t const numBuckets = (size_t)1 << bucketLog; /* Size the seq pool tables */ ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize)); /* Reset the window */ ZSTD_window_init(&serialState->ldmState.window); /* Resize tables and output space if necessary. */ if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) { - ZSTD_free(serialState->ldmState.hashTable, cMem); - serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_malloc(hashSize, cMem); + ZSTD_customFree(serialState->ldmState.hashTable, cMem); + serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem); } if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) { - ZSTD_free(serialState->ldmState.bucketOffsets, cMem); - serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_malloc(bucketSize, cMem); + ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); + serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem); } if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets) return 1; /* Zero the tables */ - memset(serialState->ldmState.hashTable, 0, hashSize); - memset(serialState->ldmState.bucketOffsets, 0, bucketSize); + ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize); + ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets); /* Update window state and fill hash table with dict */ serialState->ldmState.loadedDictEnd = 0; if (dictSize > 0) { if (dictContentType == ZSTD_dct_rawContent) { BYTE const* const dictEnd = (const BYTE*)dict + dictSize; - ZSTD_window_update(&serialState->ldmState.window, dict, dictSize); + ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0); ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams); serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base); } else { @@ -537,7 +532,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState, static int ZSTDMT_serialState_init(serialState_t* serialState) { int initError = 0; - memset(serialState, 0, sizeof(*serialState)); + ZSTD_memset(serialState, 0, sizeof(*serialState)); initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL); initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL); initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL); @@ -552,8 +547,8 @@ static void ZSTDMT_serialState_free(serialState_t* serialState) ZSTD_pthread_cond_destroy(&serialState->cond); ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex); ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond); - ZSTD_free(serialState->ldmState.hashTable, cMem); - ZSTD_free(serialState->ldmState.bucketOffsets, cMem); + ZSTD_customFree(serialState->ldmState.hashTable, cMem); + ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); } static void ZSTDMT_serialState_update(serialState_t* serialState, @@ -574,7 +569,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState, assert(seqStore.seq != NULL && seqStore.pos == 0 && seqStore.size == 0 && seqStore.capacity > 0); assert(src.size <= serialState->params.jobSize); - ZSTD_window_update(&serialState->ldmState.window, src.start, src.size); + ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0); error = ZSTD_ldm_generateSequences( &serialState->ldmState, &seqStore, &serialState->params.ldmParams, src.start, src.size); @@ -686,6 +681,8 @@ static void ZSTDMT_compressionJob(void* jobDescription) if (job->jobID != 0) jobParams.fParams.checksumFlag = 0; /* Don't run LDM for the chunks, since we handle it externally */ jobParams.ldmParams.enableLdm = 0; + /* Correct nbWorkers to 0. */ + jobParams.nbWorkers = 0; /* init */ @@ -698,6 +695,10 @@ static void ZSTDMT_compressionJob(void* jobDescription) { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob); if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError); } + if (!job->firstJob) { + size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0); + if (ZSTD_isError(err)) JOB_ERROR(err); + } { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */ ZSTD_dtlm_fast, @@ -753,6 +754,13 @@ static void ZSTDMT_compressionJob(void* jobDescription) if (ZSTD_isError(cSize)) JOB_ERROR(cSize); lastCBlockSize = cSize; } } + if (!job->firstJob) { + /* Double check that we don't have an ext-dict, because then our + * repcode invalidation doesn't work. + */ + assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window)); + } + ZSTD_CCtx_trace(cctx, 0); _endJob: ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize); @@ -820,7 +828,6 @@ struct ZSTDMT_CCtx_s { roundBuff_t roundBuff; serialState_t serial; rsyncState_t rsync; - unsigned singleBlockingThread; unsigned jobIDMask; unsigned doneJobID; unsigned nextJobID; @@ -832,6 +839,7 @@ struct ZSTDMT_CCtx_s { ZSTD_customMem cMem; ZSTD_CDict* cdictLocal; const ZSTD_CDict* cdict; + unsigned providedFactory: 1; }; static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem) @@ -842,7 +850,7 @@ static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZS ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex); ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond); } - ZSTD_free(jobTable, cMem); + ZSTD_customFree(jobTable, cMem); } /* ZSTDMT_allocJobsTable() @@ -854,7 +862,7 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom U32 const nbJobs = 1 << nbJobsLog2; U32 jobNb; ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*) - ZSTD_calloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem); + ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem); int initError = 0; if (jobTable==NULL) return NULL; *nbJobsPtr = nbJobs; @@ -885,12 +893,12 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) { /* ZSTDMT_CCtxParam_setNbWorkers(): * Internal use only */ -size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers) +static size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers) { return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers); } -MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem) +MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool) { ZSTDMT_CCtx* mtctx; U32 nbJobs = nbWorkers + 2; @@ -903,12 +911,19 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, /* invalid custom allocator */ return NULL; - mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem); + mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem); if (!mtctx) return NULL; ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers); mtctx->cMem = cMem; mtctx->allJobsCompleted = 1; - mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem); + if (pool != NULL) { + mtctx->factory = pool; + mtctx->providedFactory = 1; + } + else { + mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem); + mtctx->providedFactory = 0; + } mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem); assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */ mtctx->jobIDMask = nbJobs - 1; @@ -925,22 +940,18 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, return mtctx; } -ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem) +ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool) { #ifdef ZSTD_MULTITHREAD - return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem); + return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool); #else (void)nbWorkers; (void)cMem; + (void)pool; return NULL; #endif } -ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers) -{ - return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem); -} - /* ZSTDMT_releaseAllJobResources() : * note : ensure all workers are killed first ! */ @@ -957,7 +968,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx) ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff); /* Clear the job description, but keep the mutex/cond */ - memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID])); + ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID])); mtctx->jobs[jobID].job_mutex = mutex; mtctx->jobs[jobID].job_cond = cond; } @@ -984,7 +995,8 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx) size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx) { if (mtctx==NULL) return 0; /* compatible with free on NULL */ - POOL_free(mtctx->factory); /* stop and free worker threads */ + if (!mtctx->providedFactory) + POOL_free(mtctx->factory); /* stop and free worker threads */ ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */ ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem); ZSTDMT_freeBufferPool(mtctx->bufPool); @@ -993,8 +1005,8 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx) ZSTDMT_serialState_free(&mtctx->serial); ZSTD_freeCDict(mtctx->cdictLocal); if (mtctx->roundBuff.buffer) - ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem); - ZSTD_free(mtctx, mtctx->cMem); + ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem); + ZSTD_customFree(mtctx, mtctx->cMem); return 0; } @@ -1011,65 +1023,6 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx) + mtctx->roundBuff.capacity; } -/* Internal only */ -size_t -ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, - ZSTDMT_parameter parameter, - int value) -{ - DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter"); - switch(parameter) - { - case ZSTDMT_p_jobSize : - DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value); - return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value); - case ZSTDMT_p_overlapLog : - DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value); - return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value); - case ZSTDMT_p_rsyncable : - DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value); - return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value); - default : - return ERROR(parameter_unsupported); - } -} - -size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value) -{ - DEBUGLOG(4, "ZSTDMT_setMTCtxParameter"); - return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value); -} - -size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value) -{ - switch (parameter) { - case ZSTDMT_p_jobSize: - return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value); - case ZSTDMT_p_overlapLog: - return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value); - case ZSTDMT_p_rsyncable: - return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value); - default: - return ERROR(parameter_unsupported); - } -} - -/* Sets parameters relevant to the compression job, - * initializing others to default values. */ -static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params) -{ - ZSTD_CCtx_params jobParams = *params; - /* Clear parameters related to multithreading */ - jobParams.forceWindow = 0; - jobParams.nbWorkers = 0; - jobParams.jobSize = 0; - jobParams.overlapLog = 0; - jobParams.rsyncable = 0; - memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t)); - memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem)); - return jobParams; -} - /* ZSTDMT_resize() : * @return : error code if fails, 0 on success */ @@ -1098,7 +1051,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; - { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0); + { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); cParams.windowLog = saved_wlog; mtctx->params.cParams = cParams; } @@ -1185,8 +1138,8 @@ static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params) if (params->ldmParams.enableLdm) { /* In Long Range Mode, the windowLog is typically oversized. * In which case, it's preferable to determine the jobSize - * based on chainLog instead. */ - jobLog = MAX(21, params->cParams.chainLog + 4); + * based on cycleLog instead. */ + jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3); } else { jobLog = MAX(20, params->cParams.windowLog + 2); } @@ -1240,174 +1193,6 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params) return (ovLog==0) ? 0 : (size_t)1 << ovLog; } -static unsigned -ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nbWorkers) -{ - assert(nbWorkers>0); - { size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params); - size_t const jobMaxSize = jobSizeTarget << 2; - size_t const passSizeMax = jobMaxSize * nbWorkers; - unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1; - unsigned const nbJobsLarge = multiplier * nbWorkers; - unsigned const nbJobsMax = (unsigned)(srcSize / jobSizeTarget) + 1; - unsigned const nbJobsSmall = MIN(nbJobsMax, nbWorkers); - return (multiplier>1) ? nbJobsLarge : nbJobsSmall; -} } - -/* ZSTDMT_compress_advanced_internal() : - * This is a blocking function : it will only give back control to caller after finishing its compression job. - */ -static size_t -ZSTDMT_compress_advanced_internal( - ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params) -{ - ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(¶ms); - size_t const overlapSize = ZSTDMT_computeOverlapSize(¶ms); - unsigned const nbJobs = ZSTDMT_computeNbJobs(¶ms, srcSize, params.nbWorkers); - size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs; - size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */ - const char* const srcStart = (const char*)src; - size_t remainingSrcSize = srcSize; - unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbJobs : (unsigned)(dstCapacity / ZSTD_compressBound(avgJobSize)); /* presumes avgJobSize >= 256 KB, which should be the case */ - size_t frameStartPos = 0, dstBufferPos = 0; - assert(jobParams.nbWorkers == 0); - assert(mtctx->cctxPool->totalCCtx == params.nbWorkers); - - params.jobSize = (U32)avgJobSize; - DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbJobs=%2u (rawSize=%u bytes; fixedSize=%u) ", - nbJobs, (U32)proposedJobSize, (U32)avgJobSize); - - if ((nbJobs==1) | (params.nbWorkers<=1)) { /* fallback to single-thread mode : this is a blocking invocation anyway */ - ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0]; - DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode"); - if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams); - return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, &jobParams); - } - - assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */ - ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) ); - /* LDM doesn't even try to load the dictionary in single-ingestion mode */ - if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0, ZSTD_dct_auto)) - return ERROR(memory_allocation); - - FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , ""); /* only expands if necessary */ - - { unsigned u; - for (u=0; u<nbJobs; u++) { - size_t const jobSize = MIN(remainingSrcSize, avgJobSize); - size_t const dstBufferCapacity = ZSTD_compressBound(jobSize); - buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity }; - buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : g_nullBuffer; - size_t dictSize = u ? overlapSize : 0; - - mtctx->jobs[u].prefix.start = srcStart + frameStartPos - dictSize; - mtctx->jobs[u].prefix.size = dictSize; - mtctx->jobs[u].src.start = srcStart + frameStartPos; - mtctx->jobs[u].src.size = jobSize; assert(jobSize > 0); /* avoid job.src.size == 0 */ - mtctx->jobs[u].consumed = 0; - mtctx->jobs[u].cSize = 0; - mtctx->jobs[u].cdict = (u==0) ? cdict : NULL; - mtctx->jobs[u].fullFrameSize = srcSize; - mtctx->jobs[u].params = jobParams; - /* do not calculate checksum within sections, but write it in header for first section */ - mtctx->jobs[u].dstBuff = dstBuffer; - mtctx->jobs[u].cctxPool = mtctx->cctxPool; - mtctx->jobs[u].bufPool = mtctx->bufPool; - mtctx->jobs[u].seqPool = mtctx->seqPool; - mtctx->jobs[u].serial = &mtctx->serial; - mtctx->jobs[u].jobID = u; - mtctx->jobs[u].firstJob = (u==0); - mtctx->jobs[u].lastJob = (u==nbJobs-1); - - DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)jobSize); - DEBUG_PRINTHEX(6, mtctx->jobs[u].prefix.start, 12); - POOL_add(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[u]); - - frameStartPos += jobSize; - dstBufferPos += dstBufferCapacity; - remainingSrcSize -= jobSize; - } } - - /* collect result */ - { size_t error = 0, dstPos = 0; - unsigned jobID; - for (jobID=0; jobID<nbJobs; jobID++) { - DEBUGLOG(5, "waiting for job %u ", jobID); - ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex); - while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) { - DEBUGLOG(5, "waiting for jobCompleted signal from job %u", jobID); - ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex); - } - ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex); - DEBUGLOG(5, "ready to write job %u ", jobID); - - { size_t const cSize = mtctx->jobs[jobID].cSize; - if (ZSTD_isError(cSize)) error = cSize; - if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall); - if (jobID) { /* note : job 0 is written directly at dst, which is correct position */ - if (!error) - memmove((char*)dst + dstPos, mtctx->jobs[jobID].dstBuff.start, cSize); /* may overlap when job compressed within dst */ - if (jobID >= compressWithinDst) { /* job compressed into its own buffer, which must be released */ - DEBUGLOG(5, "releasing buffer %u>=%u", jobID, compressWithinDst); - ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff); - } } - mtctx->jobs[jobID].dstBuff = g_nullBuffer; - mtctx->jobs[jobID].cSize = 0; - dstPos += cSize ; - } - } /* for (jobID=0; jobID<nbJobs; jobID++) */ - - DEBUGLOG(4, "checksumFlag : %u ", params.fParams.checksumFlag); - if (params.fParams.checksumFlag) { - U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState); - if (dstPos + 4 > dstCapacity) { - error = ERROR(dstSize_tooSmall); - } else { - DEBUGLOG(4, "writing checksum : %08X \n", checksum); - MEM_writeLE32((char*)dst + dstPos, checksum); - dstPos += 4; - } } - - if (!error) DEBUGLOG(4, "compressed size : %u ", (U32)dstPos); - return error ? error : dstPos; - } -} - -size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_parameters params, - int overlapLog) -{ - ZSTD_CCtx_params cctxParams = mtctx->params; - cctxParams.cParams = params.cParams; - cctxParams.fParams = params.fParams; - assert(ZSTD_OVERLAPLOG_MIN <= overlapLog && overlapLog <= ZSTD_OVERLAPLOG_MAX); - cctxParams.overlapLog = overlapLog; - return ZSTDMT_compress_advanced_internal(mtctx, - dst, dstCapacity, - src, srcSize, - cdict, cctxParams); -} - - -size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel) -{ - ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0); - int const overlapLog = ZSTDMT_overlapLog_default(params.cParams.strategy); - params.fParams.contentSizeFlag = 1; - return ZSTDMT_compress_advanced(mtctx, dst, dstCapacity, src, srcSize, NULL, params, overlapLog); -} - - /* ====================================== */ /* ======= Streaming API ======= */ /* ====================================== */ @@ -1432,16 +1217,6 @@ size_t ZSTDMT_initCStream_internal( if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX; - mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */ - if (mtctx->singleBlockingThread) { - ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(¶ms); - DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode"); - assert(singleThreadParams.nbWorkers == 0); - return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0], - dict, dictSize, cdict, - &singleThreadParams, pledgedSrcSize); - } - DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers); if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */ @@ -1475,9 +1250,8 @@ size_t ZSTDMT_initCStream_internal( if (params.rsyncable) { /* Aim for the targetsectionSize as the average job size. */ - U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20); - U32 const rsyncBits = ZSTD_highbit32(jobSizeMB) + 20; - assert(jobSizeMB >= 1); + U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10); + U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10); DEBUGLOG(4, "rsyncLog = %u", rsyncBits); mtctx->rsync.hash = 0; mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1; @@ -1504,8 +1278,8 @@ size_t ZSTDMT_initCStream_internal( size_t const capacity = MAX(windowSize, sectionsSize) + slackSize; if (mtctx->roundBuff.capacity < capacity) { if (mtctx->roundBuff.buffer) - ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem); - mtctx->roundBuff.buffer = (BYTE*)ZSTD_malloc(capacity, mtctx->cMem); + ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem); + mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem); if (mtctx->roundBuff.buffer == NULL) { mtctx->roundBuff.capacity = 0; return ERROR(memory_allocation); @@ -1530,53 +1304,6 @@ size_t ZSTDMT_initCStream_internal( return 0; } -size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, - ZSTD_parameters params, - unsigned long long pledgedSrcSize) -{ - ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */ - DEBUGLOG(4, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize); - cctxParams.cParams = params.cParams; - cctxParams.fParams = params.fParams; - return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dct_auto, NULL, - cctxParams, pledgedSrcSize); -} - -size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams, - unsigned long long pledgedSrcSize) -{ - ZSTD_CCtx_params cctxParams = mtctx->params; - if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */ - cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict); - cctxParams.fParams = fParams; - return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dct_auto, cdict, - cctxParams, pledgedSrcSize); -} - - -/* ZSTDMT_resetCStream() : - * pledgedSrcSize can be zero == unknown (for the time being) - * prefer using ZSTD_CONTENTSIZE_UNKNOWN, - * as `0` might mean "empty" in the future */ -size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize) -{ - if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, 0, mtctx->params, - pledgedSrcSize); -} - -size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); - ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */ - DEBUGLOG(4, "ZSTDMT_initCStream (cLevel=%i)", compressionLevel); - cctxParams.cParams = params.cParams; - cctxParams.fParams = params.fParams; - return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN); -} - /* ZSTDMT_writeLastEmptyBlock() * Write a single empty block with an end-of-frame to finish a frame. @@ -1740,7 +1467,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u assert(cSize >= mtctx->jobs[wJobID].dstFlushed); assert(mtctx->jobs[wJobID].dstBuff.start != NULL); if (toFlush > 0) { - memcpy((char*)output->dst + output->pos, + ZSTD_memcpy((char*)output->dst + output->pos, (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed, toFlush); } @@ -1894,7 +1621,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) return 0; } ZSTDMT_waitForLdmComplete(mtctx, buffer); - memmove(start, mtctx->inBuff.prefix.start, prefixSize); + ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize); mtctx->inBuff.prefix.start = start; mtctx->roundBuff.pos = prefixSize; } @@ -1968,6 +1695,16 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input) pos = 0; prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH; hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH); + if ((hash & hitMask) == hitMask) { + /* We're already at a sync point so don't load any more until + * we're able to flush this sync point. + * This likely happened because the job table was full so we + * couldn't add our job. + */ + syncPoint.toLoad = 0; + syncPoint.flush = 1; + return syncPoint; + } } else { /* We don't have enough bytes buffered to initialize the hash, but * we know we have at least RSYNC_LENGTH bytes total. @@ -2022,34 +1759,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, assert(output->pos <= output->size); assert(input->pos <= input->size); - if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */ - return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp); - } - if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) { /* current frame being ended. Only flush/end are allowed */ return ERROR(stage_wrong); } - /* single-pass shortcut (note : synchronous-mode) */ - if ( (!mtctx->params.rsyncable) /* rsyncable mode is disabled */ - && (mtctx->nextJobID == 0) /* just started */ - && (mtctx->inBuff.filled == 0) /* nothing buffered */ - && (!mtctx->jobReady) /* no job already created */ - && (endOp == ZSTD_e_end) /* end order */ - && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough space in dst */ - size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx, - (char*)output->dst + output->pos, output->size - output->pos, - (const char*)input->src + input->pos, input->size - input->pos, - mtctx->cdict, mtctx->params); - if (ZSTD_isError(cSize)) return cSize; - input->pos = input->size; - output->pos += cSize; - mtctx->allJobsCompleted = 1; - mtctx->frameEnded = 1; - return 0; - } - /* fill input buffer */ if ( (!mtctx->jobReady) && (input->size > input->pos) ) { /* support NULL input */ @@ -2072,13 +1786,21 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize); DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u", (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize); - memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad); + ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad); input->pos += syncPoint.toLoad; mtctx->inBuff.filled += syncPoint.toLoad; forwardInputProgress = syncPoint.toLoad>0; } - if ((input->pos < input->size) && (endOp == ZSTD_e_end)) - endOp = ZSTD_e_flush; /* can't end now : not all input consumed */ + } + if ((input->pos < input->size) && (endOp == ZSTD_e_end)) { + /* Can't end yet because the input is not fully consumed. + * We are in one of these cases: + * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job. + * - We filled the input buffer: flush this job but don't end the frame. + * - We hit a synchronization point: flush this job but don't end the frame. + */ + assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable); + endOp = ZSTD_e_flush; } if ( (mtctx->jobReady) @@ -2097,47 +1819,3 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, return remainingToFlush; } } - - -size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input) -{ - FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) , ""); - - /* recommended next input size : fill current input buffer */ - return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */ -} - - -static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_EndDirective endFrame) -{ - size_t const srcSize = mtctx->inBuff.filled; - DEBUGLOG(5, "ZSTDMT_flushStream_internal"); - - if ( mtctx->jobReady /* one job ready for a worker to pick up */ - || (srcSize > 0) /* still some data within input buffer */ - || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */ - DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)", - (U32)srcSize, (U32)endFrame); - FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) , ""); - } - - /* check if there is any data available to flush */ - return ZSTDMT_flushProduced(mtctx, output, 1 /* blockToFlush */, endFrame); -} - - -size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output) -{ - DEBUGLOG(5, "ZSTDMT_flushStream"); - if (mtctx->singleBlockingThread) - return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output); - return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_flush); -} - -size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output) -{ - DEBUGLOG(4, "ZSTDMT_endStream"); - if (mtctx->singleBlockingThread) - return ZSTD_endStream(mtctx->cctxPool->cctx[0], output); - return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_end); -} diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index 89914eb7f88..2fee2ec7455 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -19,113 +19,57 @@ /* Note : This is an internal API. * These APIs used to be exposed with ZSTDLIB_API, * because it used to be the only way to invoke MT compression. - * Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2() - * instead. - * - * If you depend on these APIs and can't switch, then define - * ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library. - * However, we may completely remove these functions in a future - * release, so please switch soon. + * Now, you must use ZSTD_compress2 and ZSTD_compressStream2() instead. * * This API requires ZSTD_MULTITHREAD to be defined during compilation, * otherwise ZSTDMT_createCCtx*() will fail. */ -#ifdef ZSTD_LEGACY_MULTITHREADED_API -# define ZSTDMT_API ZSTDLIB_API -#else -# define ZSTDMT_API -#endif - /* === Dependencies === */ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */ #include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */ /* === Constants === */ -#ifndef ZSTDMT_NBWORKERS_MAX -# define ZSTDMT_NBWORKERS_MAX 200 +#ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */ +# define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256) #endif -#ifndef ZSTDMT_JOBSIZE_MIN -# define ZSTDMT_JOBSIZE_MIN (1 MB) +#ifndef ZSTDMT_JOBSIZE_MIN /* a different value can be selected at compile time */ +# define ZSTDMT_JOBSIZE_MIN (512 KB) #endif #define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30) #define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB)) +/* ======================================================== + * === Private interface, for use by ZSTD_compress.c === + * === Not exposed in libzstd. Never invoke directly === + * ======================================================== */ + /* === Memory management === */ typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx; /* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */ -ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers); -/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */ -ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, - ZSTD_customMem cMem); -ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx); - -ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx); - - -/* === Simple one-pass compression function === */ - -ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); - +ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, + ZSTD_customMem cMem, + ZSTD_threadPool *pool); +size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx); +size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx); /* === Streaming functions === */ -ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel); -ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */ - -ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); -ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input); - -ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */ -ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */ - - -/* === Advanced functions and parameters === */ - -ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_parameters params, - int overlapLog); - -ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */ - ZSTD_parameters params, - unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */ - -ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fparams, - unsigned long long pledgedSrcSize); /* note : zero means empty */ - -/* ZSTDMT_parameter : - * List of parameters that can be set using ZSTDMT_setMTCtxParameter() */ -typedef enum { - ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */ - ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */ - ZSTDMT_p_rsyncable /* Enables rsyncable mode. */ -} ZSTDMT_parameter; - -/* ZSTDMT_setMTCtxParameter() : - * allow setting individual parameters, one at a time, among a list of enums defined in ZSTDMT_parameter. - * The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__ - * Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions. - * @return : 0, or an error code (which can be tested using ZSTD_isError()) */ -ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value); - -/* ZSTDMT_getMTCtxParameter() : - * Query the ZSTDMT_CCtx for a parameter value. - * @return : 0, or an error code (which can be tested using ZSTD_isError()) */ -ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value); +size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); +/*! ZSTDMT_initCStream_internal() : + * Private use only. Init streaming operation. + * expects params to be valid. + * must receive dict, or cdict, or none, but not both. + * @return : 0, or an error code */ +size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, + const ZSTD_CDict* cdict, + ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); /*! ZSTDMT_compressStream_generic() : * Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream() @@ -134,16 +78,10 @@ ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter * 0 if fully flushed * or an error code * note : needs to be init using any ZSTD_initCStream*() variant */ -ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, - ZSTD_outBuffer* output, - ZSTD_inBuffer* input, - ZSTD_EndDirective endOp); - - -/* ======================================================== - * === Private interface, for use by ZSTD_compress.c === - * === Not exposed in libzstd. Never invoke directly === - * ======================================================== */ +size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); /*! ZSTDMT_toFlushNow() * Tell how many bytes are ready to be flushed immediately. @@ -153,15 +91,6 @@ ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, * therefore flushing is limited by speed of oldest job. */ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx); -/*! ZSTDMT_CCtxParam_setMTCtxParameter() - * like ZSTDMT_setMTCtxParameter(), but into a ZSTD_CCtx_Params */ -size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, int value); - -/*! ZSTDMT_CCtxParam_setNbWorkers() - * Set nbWorkers, and clamp it. - * Also reset jobSize and overlapLog */ -size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers); - /*! ZSTDMT_updateCParams_whileCompressing() : * Updates only a selected set of compression parameters, to remain compatible with current frame. * New parameters will be applied to next compression job. */ @@ -174,17 +103,6 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx); -/*! ZSTDMT_initCStream_internal() : - * Private use only. Init streaming operation. - * expects params to be valid. - * must receive dict, or cdict, or none, but not both. - * @return : 0, or an error code */ -size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs, - const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); - - #if defined (__cplusplus) } #endif diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 68293a13096..b93c9a003b4 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -1,7 +1,7 @@ /* ****************************************************************** * huff0 huffman decoder, * part of Finite State Entropy library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * * You can contact the author at : * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -15,7 +15,7 @@ /* ************************************************************** * Dependencies ****************************************************************/ -#include <string.h> /* memcpy, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */ #include "../common/compiler.h" #include "../common/bitstream.h" /* BIT_* */ #include "../common/fse.h" /* to compress headers */ @@ -103,7 +103,7 @@ typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) { DTableDesc dtd; - memcpy(&dtd, table, sizeof(dtd)); + ZSTD_memcpy(&dtd, table, sizeof(dtd)); return dtd; } @@ -115,29 +115,51 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) /*-***************************/ typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */ +/** + * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at + * a time. + */ +static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) { + U64 D4; + if (MEM_isLittleEndian()) { + D4 = symbol + (nbBits << 8); + } else { + D4 = (symbol << 8) + nbBits; + } + D4 *= 0x0001000100010001ULL; + return D4; +} + +typedef struct { + U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; + U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1]; + U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; + BYTE symbols[HUF_SYMBOLVALUE_MAX + 1]; + BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; +} HUF_ReadDTableX1_Workspace; + + size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize) +{ + return HUF_readDTableX1_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0); +} + +size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2) { U32 tableLog = 0; U32 nbSymbols = 0; size_t iSize; void* const dtPtr = DTable + 1; HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr; + HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace; - U32* rankVal; - BYTE* huffWeight; - size_t spaceUsed32 = 0; - - rankVal = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1; - huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; - - if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); + DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp)); + if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge); DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable)); - /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ + /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ - iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); + iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2); if (HUF_isError(iSize)) return iSize; /* Table header */ @@ -145,52 +167,117 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */ dtd.tableType = 0; dtd.tableLog = (BYTE)tableLog; - memcpy(DTable, &dtd, sizeof(dtd)); + ZSTD_memcpy(DTable, &dtd, sizeof(dtd)); } - /* Calculate starting value for each rank */ - { U32 n, nextRankStart = 0; - for (n=1; n<tableLog+1; n++) { - U32 const current = nextRankStart; - nextRankStart += (rankVal[n] << (n-1)); - rankVal[n] = current; - } } + /* Compute symbols and rankStart given rankVal: + * + * rankVal already contains the number of values of each weight. + * + * symbols contains the symbols ordered by weight. First are the rankVal[0] + * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on. + * symbols[0] is filled (but unused) to avoid a branch. + * + * rankStart contains the offset where each rank belongs in the DTable. + * rankStart[0] is not filled because there are no entries in the table for + * weight 0. + */ + { + int n; + int nextRankStart = 0; + int const unroll = 4; + int const nLimit = (int)nbSymbols - unroll + 1; + for (n=0; n<(int)tableLog+1; n++) { + U32 const curr = nextRankStart; + nextRankStart += wksp->rankVal[n]; + wksp->rankStart[n] = curr; + } + for (n=0; n < nLimit; n += unroll) { + int u; + for (u=0; u < unroll; ++u) { + size_t const w = wksp->huffWeight[n+u]; + wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u); + } + } + for (; n < (int)nbSymbols; ++n) { + size_t const w = wksp->huffWeight[n]; + wksp->symbols[wksp->rankStart[w]++] = (BYTE)n; + } + } - /* fill DTable */ - { U32 n; - size_t const nEnd = nbSymbols; - for (n=0; n<nEnd; n++) { - size_t const w = huffWeight[n]; - size_t const length = (1 << w) >> 1; - size_t const uStart = rankVal[w]; - size_t const uEnd = uStart + length; - size_t u; - HUF_DEltX1 D; - D.byte = (BYTE)n; - D.nbBits = (BYTE)(tableLog + 1 - w); - rankVal[w] = (U32)uEnd; - if (length < 4) { - /* Use length in the loop bound so the compiler knows it is short. */ - for (u = 0; u < length; ++u) - dt[uStart + u] = D; - } else { - /* Unroll the loop 4 times, we know it is a power of 2. */ - for (u = uStart; u < uEnd; u += 4) { - dt[u + 0] = D; - dt[u + 1] = D; - dt[u + 2] = D; - dt[u + 3] = D; - } } } } + /* fill DTable + * We fill all entries of each weight in order. + * That way length is a constant for each iteration of the outter loop. + * We can switch based on the length to a different inner loop which is + * optimized for that particular case. + */ + { + U32 w; + int symbol=wksp->rankVal[0]; + int rankStart=0; + for (w=1; w<tableLog+1; ++w) { + int const symbolCount = wksp->rankVal[w]; + int const length = (1 << w) >> 1; + int uStart = rankStart; + BYTE const nbBits = (BYTE)(tableLog + 1 - w); + int s; + int u; + switch (length) { + case 1: + for (s=0; s<symbolCount; ++s) { + HUF_DEltX1 D; + D.byte = wksp->symbols[symbol + s]; + D.nbBits = nbBits; + dt[uStart] = D; + uStart += 1; + } + break; + case 2: + for (s=0; s<symbolCount; ++s) { + HUF_DEltX1 D; + D.byte = wksp->symbols[symbol + s]; + D.nbBits = nbBits; + dt[uStart+0] = D; + dt[uStart+1] = D; + uStart += 2; + } + break; + case 4: + for (s=0; s<symbolCount; ++s) { + U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits); + MEM_write64(dt + uStart, D4); + uStart += 4; + } + break; + case 8: + for (s=0; s<symbolCount; ++s) { + U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits); + MEM_write64(dt + uStart, D4); + MEM_write64(dt + uStart + 4, D4); + uStart += 8; + } + break; + default: + for (s=0; s<symbolCount; ++s) { + U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits); + for (u=0; u < length; u += 16) { + MEM_write64(dt + uStart + u + 0, D4); + MEM_write64(dt + uStart + u + 4, D4); + MEM_write64(dt + uStart + u + 8, D4); + MEM_write64(dt + uStart + u + 12, D4); + } + assert(u == length); + uStart += length; + } + break; + } + symbol += symbolCount; + rankStart += symbolCount * length; + } + } return iSize; } -size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_readDTableX1_wksp(DTable, src, srcSize, - workSpace, sizeof(workSpace)); -} - FORCE_INLINE_TEMPLATE BYTE HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog) { @@ -389,20 +476,6 @@ size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, } -size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize); -} - size_t HUF_decompress4X1_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, @@ -419,8 +492,7 @@ static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size { const BYTE* ip = (const BYTE*) cSrc; - size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize, - workSpace, wkspSize); + size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; cSrcSize -= hSize; @@ -436,18 +508,6 @@ size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, } -size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} -size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - #endif /* HUF_FORCE_DECOMPRESS_X2 */ @@ -468,13 +528,15 @@ typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX]; static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed, const U32* rankValOrigin, const int minWeight, const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, - U32 nbBitsBaseline, U16 baseSeq) + U32 nbBitsBaseline, U16 baseSeq, U32* wksp, size_t wkspSize) { HUF_DEltX2 DElt; - U32 rankVal[HUF_TABLELOG_MAX + 1]; + U32* rankVal = wksp; + assert(wkspSize >= HUF_TABLELOG_MAX + 1); + (void)wkspSize; /* get pre-calculated rankVal */ - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1)); /* fill skipped values */ if (minWeight>1) { @@ -509,14 +571,18 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 co static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, const sortedSymbol_t* sortedList, const U32 sortedListSize, const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, - const U32 nbBitsBaseline) + const U32 nbBitsBaseline, U32* wksp, size_t wkspSize) { - U32 rankVal[HUF_TABLELOG_MAX + 1]; + U32* rankVal = wksp; const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ const U32 minBits = nbBitsBaseline - maxWeight; U32 s; - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + assert(wkspSize >= HUF_TABLELOG_MAX + 1); + wksp += HUF_TABLELOG_MAX + 1; + wkspSize -= HUF_TABLELOG_MAX + 1; + + ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1)); /* fill DTable */ for (s=0; s<sortedListSize; s++) { @@ -534,7 +600,7 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits, rankValOrigin[nbBits], minWeight, sortedList+sortedRank, sortedListSize-sortedRank, - nbBitsBaseline, symbol); + nbBitsBaseline, symbol, wksp, wkspSize); } else { HUF_DEltX2 DElt; MEM_writeLE16(&(DElt.sequence), symbol); @@ -548,6 +614,15 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, } } +typedef struct { + rankValCol_t rankVal[HUF_TABLELOG_MAX]; + U32 rankStats[HUF_TABLELOG_MAX + 1]; + U32 rankStart0[HUF_TABLELOG_MAX + 2]; + sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1]; + BYTE weightList[HUF_SYMBOLVALUE_MAX + 1]; + U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; +} HUF_ReadDTableX2_Workspace; + size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize) @@ -560,48 +635,33 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr; U32 *rankStart; - rankValCol_t* rankVal; - U32* rankStats; - U32* rankStart0; - sortedSymbol_t* sortedSymbol; - BYTE* weightList; - size_t spaceUsed32 = 0; - - rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2; - rankStats = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_MAX + 1; - rankStart0 = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_MAX + 2; - sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t); - spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2; - weightList = (BYTE *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; - - if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); - - rankStart = rankStart0 + 1; - memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1)); + HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace; + + if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC); + + rankStart = wksp->rankStart0 + 1; + ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats)); + ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0)); DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */ if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); - /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ + /* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ - iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); + iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), /* bmi2 */ 0); if (HUF_isError(iSize)) return iSize; /* check result */ if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ /* find maxWeight */ - for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */ + for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */ /* Get start index of each weight */ { U32 w, nextRankStart = 0; for (w=1; w<maxW+1; w++) { - U32 current = nextRankStart; - nextRankStart += rankStats[w]; - rankStart[w] = current; + U32 curr = nextRankStart; + nextRankStart += wksp->rankStats[w]; + rankStart[w] = curr; } rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ sizeOfSort = nextRankStart; @@ -610,57 +670,51 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, /* sort symbols by weight */ { U32 s; for (s=0; s<nbSymbols; s++) { - U32 const w = weightList[s]; + U32 const w = wksp->weightList[s]; U32 const r = rankStart[w]++; - sortedSymbol[r].symbol = (BYTE)s; - sortedSymbol[r].weight = (BYTE)w; + wksp->sortedSymbol[r].symbol = (BYTE)s; + wksp->sortedSymbol[r].weight = (BYTE)w; } rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */ } /* Build rankVal */ - { U32* const rankVal0 = rankVal[0]; + { U32* const rankVal0 = wksp->rankVal[0]; { int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */ U32 nextRankVal = 0; U32 w; for (w=1; w<maxW+1; w++) { - U32 current = nextRankVal; - nextRankVal += rankStats[w] << (w+rescale); - rankVal0[w] = current; + U32 curr = nextRankVal; + nextRankVal += wksp->rankStats[w] << (w+rescale); + rankVal0[w] = curr; } } { U32 const minBits = tableLog+1 - maxW; U32 consumed; for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) { - U32* const rankValPtr = rankVal[consumed]; + U32* const rankValPtr = wksp->rankVal[consumed]; U32 w; for (w = 1; w < maxW+1; w++) { rankValPtr[w] = rankVal0[w] >> consumed; } } } } HUF_fillDTableX2(dt, maxTableLog, - sortedSymbol, sizeOfSort, - rankStart0, rankVal, maxW, - tableLog+1); + wksp->sortedSymbol, sizeOfSort, + wksp->rankStart0, wksp->rankVal, maxW, + tableLog+1, + wksp->calleeWksp, sizeof(wksp->calleeWksp) / sizeof(U32)); dtd.tableLog = (BYTE)maxTableLog; dtd.tableType = 1; - memcpy(DTable, &dtd, sizeof(dtd)); + ZSTD_memcpy(DTable, &dtd, sizeof(dtd)); return iSize; } -size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_readDTableX2_wksp(DTable, src, srcSize, - workSpace, sizeof(workSpace)); -} - FORCE_INLINE_TEMPLATE U32 HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) { size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt+val, 2); + ZSTD_memcpy(op, dt+val, 2); BIT_skipBits(DStream, dt[val].nbBits); return dt[val].length; } @@ -669,7 +723,7 @@ FORCE_INLINE_TEMPLATE U32 HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) { size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt+val, 1); + ZSTD_memcpy(op, dt+val, 1); if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); else { if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { @@ -890,20 +944,6 @@ size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, } -size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - size_t HUF_decompress4X2_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, @@ -937,20 +977,6 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, } -size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - #endif /* HUF_FORCE_DECOMPRESS_X1 */ @@ -1051,67 +1077,6 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize) } -typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); - -size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ -#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) - static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 }; -#endif - - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); -#else - return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); -#endif - } -} - -size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); -#else - return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : - HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ; -#endif - } -} - -size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - - size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, @@ -1145,8 +1110,8 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, /* validation checks */ if (dstSize == 0) return ERROR(dstSize_tooSmall); if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); #if defined(HUF_FORCE_DECOMPRESS_X1) @@ -1168,14 +1133,6 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, } } -size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2) { @@ -1199,7 +1156,7 @@ size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstS { const BYTE* ip = (const BYTE*) cSrc; - size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize); + size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; cSrcSize -= hSize; @@ -1246,3 +1203,149 @@ size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t ds #endif } } + +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_readDTableX1_wksp(DTable, src, srcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); + return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +#ifndef HUF_FORCE_DECOMPRESS_X1 +size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_readDTableX2_wksp(DTable, src, srcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); + return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} +size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); + return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +#ifndef HUF_FORCE_DECOMPRESS_X1 +size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); + return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); + +size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ +#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) + static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 }; +#endif + + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)algoNb; + assert(algoNb == 0); + return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)algoNb; + assert(algoNb == 1); + return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); +#else + return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); +#endif + } +} + +size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)algoNb; + assert(algoNb == 0); + return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)algoNb; + assert(algoNb == 1); + return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); +#else + return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : + HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ; +#endif + } +} + +size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} +#endif diff --git a/lib/decompress/zstd_ddict.c b/lib/decompress/zstd_ddict.c index c8cb8ecc952..ce335477b32 100644 --- a/lib/decompress/zstd_ddict.c +++ b/lib/decompress/zstd_ddict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -14,7 +14,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <string.h> /* memcpy, memmove, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ #include "../common/cpu.h" /* bmi2 */ #include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY @@ -127,11 +127,11 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, ddict->dictContent = dict; if (!dict) dictSize = 0; } else { - void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem); + void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem); ddict->dictBuffer = internalBuffer; ddict->dictContent = internalBuffer; if (!internalBuffer) return ERROR(memory_allocation); - memcpy(internalBuffer, dict, dictSize); + ZSTD_memcpy(internalBuffer, dict, dictSize); } ddict->dictSize = dictSize; ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ @@ -147,9 +147,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_customMem customMem) { - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; - { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem); + { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem); if (ddict == NULL) return NULL; ddict->cMem = customMem; { size_t const initResult = ZSTD_initDDict_internal(ddict, @@ -198,7 +198,7 @@ const ZSTD_DDict* ZSTD_initStaticDDict( if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */ if (sBufferSize < neededSpace) return NULL; if (dictLoadMethod == ZSTD_dlm_byCopy) { - memcpy(ddict+1, dict, dictSize); /* local copy */ + ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */ dict = ddict+1; } if (ZSTD_isError( ZSTD_initDDict_internal(ddict, @@ -213,8 +213,8 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict) { if (ddict==NULL) return 0; /* support free on NULL */ { ZSTD_customMem const cMem = ddict->cMem; - ZSTD_free(ddict->dictBuffer, cMem); - ZSTD_free(ddict, cMem); + ZSTD_customFree(ddict->dictBuffer, cMem); + ZSTD_customFree(ddict, cMem); return 0; } } diff --git a/lib/decompress/zstd_ddict.h b/lib/decompress/zstd_ddict.h index af307efd3d7..bd03268b508 100644 --- a/lib/decompress/zstd_ddict.h +++ b/lib/decompress/zstd_ddict.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,7 +15,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ #include "../zstd.h" /* ZSTD_DDict, and several public functions */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index be5c7cfc334..910bc034c00 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -55,13 +55,14 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <string.h> /* memcpy, memmove, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ #include "../common/cpu.h" /* bmi2 */ #include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY #include "../common/fse.h" #define HUF_STATIC_LINKING_ONLY #include "../common/huf.h" +#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */ #include "../common/zstd_internal.h" /* blockProperties_t */ #include "zstd_decompress_internal.h" /* ZSTD_DCtx */ #include "zstd_ddict.h" /* ZSTD_DDictDictContent */ @@ -72,6 +73,144 @@ #endif + +/************************************* + * Multiple DDicts Hashset internals * + *************************************/ + +#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4 +#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float. + * Currently, that means a 0.75 load factor. + * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded + * the load factor of the ddict hash set. + */ + +#define DDICT_HASHSET_TABLE_BASE_SIZE 64 +#define DDICT_HASHSET_RESIZE_FACTOR 2 + +/* Hash function to determine starting position of dict insertion within the table + * Returns an index between [0, hashSet->ddictPtrTableSize] + */ +static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) { + const U64 hash = XXH64(&dictID, sizeof(U32), 0); + /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */ + return hash & (hashSet->ddictPtrTableSize - 1); +} + +/* Adds DDict to a hashset without resizing it. + * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set. + * Returns 0 if successful, or a zstd error code if something went wrong. + */ +static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) { + const U32 dictID = ZSTD_getDictID_fromDDict(ddict); + size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID); + const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1; + RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!"); + DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx); + while (hashSet->ddictPtrTable[idx] != NULL) { + /* Replace existing ddict if inserting ddict with same dictID */ + if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) { + DEBUGLOG(4, "DictID already exists, replacing rather than adding"); + hashSet->ddictPtrTable[idx] = ddict; + return 0; + } + idx &= idxRangeMask; + idx++; + } + DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx); + hashSet->ddictPtrTable[idx] = ddict; + hashSet->ddictPtrCount++; + return 0; +} + +/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and + * rehashes all values, allocates new table, frees old table. + * Returns 0 on success, otherwise a zstd error code. + */ +static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) { + size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR; + const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem); + const ZSTD_DDict** oldTable = hashSet->ddictPtrTable; + size_t oldTableSize = hashSet->ddictPtrTableSize; + size_t i; + + DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize); + RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!"); + hashSet->ddictPtrTable = newTable; + hashSet->ddictPtrTableSize = newTableSize; + hashSet->ddictPtrCount = 0; + for (i = 0; i < oldTableSize; ++i) { + if (oldTable[i] != NULL) { + FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), ""); + } + } + ZSTD_customFree((void*)oldTable, customMem); + DEBUGLOG(4, "Finished re-hash"); + return 0; +} + +/* Fetches a DDict with the given dictID + * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL. + */ +static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) { + size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID); + const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1; + DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx); + for (;;) { + size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]); + if (currDictID == dictID || currDictID == 0) { + /* currDictID == 0 implies a NULL ddict entry */ + break; + } else { + idx &= idxRangeMask; /* Goes to start of table when we reach the end */ + idx++; + } + } + DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx); + return hashSet->ddictPtrTable[idx]; +} + +/* Allocates space for and returns a ddict hash set + * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with. + * Returns NULL if allocation failed. + */ +static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) { + ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem); + DEBUGLOG(4, "Allocating new hash set"); + ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem); + ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE; + ret->ddictPtrCount = 0; + if (!ret || !ret->ddictPtrTable) { + return NULL; + } + return ret; +} + +/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself. + * Note: The ZSTD_DDict* within the table are NOT freed. + */ +static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) { + DEBUGLOG(4, "Freeing ddict hash set"); + if (hashSet && hashSet->ddictPtrTable) { + ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem); + } + if (hashSet) { + ZSTD_customFree(hashSet, customMem); + } +} + +/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set. + * Returns 0 on success, or a ZSTD error. + */ +static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) { + DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize); + if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) { + FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), ""); + } + FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), ""); + return 0; +} + /*-************************************************************* * Context management ***************************************************************/ @@ -94,11 +233,19 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format) return startingInputLength; } +static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx) +{ + assert(dctx->streamStage == zdss_init); + dctx->format = ZSTD_f_zstd1; + dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + dctx->outBufferMode = ZSTD_bm_buffered; + dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum; + dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict; +} + static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) { - dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */ dctx->staticSize = 0; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; dctx->ddict = NULL; dctx->ddictLocal = NULL; dctx->dictEnd = NULL; @@ -113,7 +260,8 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->noForwardProgress = 0; dctx->oversizedDuration = 0; dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); - dctx->outBufferMode = ZSTD_obm_buffered; + dctx->ddictSet = NULL; + ZSTD_DCtx_resetParameters(dctx); #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION dctx->dictContentEndForFuzzing = NULL; #endif @@ -134,9 +282,9 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize) ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem) { - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; - { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem); + { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem); if (!dctx) return NULL; dctx->customMem = customMem; ZSTD_initDCtx_internal(dctx); @@ -164,13 +312,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx"); { ZSTD_customMem const cMem = dctx->customMem; ZSTD_clearDict(dctx); - ZSTD_free(dctx->inBuff, cMem); + ZSTD_customFree(dctx->inBuff, cMem); dctx->inBuff = NULL; #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) if (dctx->legacyContext) ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion); #endif - ZSTD_free(dctx, cMem); + if (dctx->ddictSet) { + ZSTD_freeDDictHashSet(dctx->ddictSet, cMem); + dctx->ddictSet = NULL; + } + ZSTD_customFree(dctx, cMem); return 0; } } @@ -179,7 +331,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) { size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx); - memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ + ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ +} + +/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on + * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then + * accordingly sets the ddict to be used to decompress the frame. + * + * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is. + * + * ZSTD_d_refMultipleDDicts must be enabled for this function to be called. + */ +static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) { + assert(dctx->refMultipleDDicts && dctx->ddictSet); + DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame"); + if (dctx->ddict) { + const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID); + if (frameDDict) { + DEBUGLOG(4, "DDict found!"); + ZSTD_clearDict(dctx); + dctx->dictID = dctx->fParams.dictID; + dctx->ddict = frameDDict; + dctx->dictUses = ZSTD_use_indefinitely; + } + } } @@ -246,7 +421,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s const BYTE* ip = (const BYTE*)src; size_t const minInputSize = ZSTD_startingInputLength(format); - memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ + ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ if (srcSize < minInputSize) return minInputSize; RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter"); @@ -256,7 +431,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s /* skippable frame */ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */ - memset(zfhPtr, 0, sizeof(*zfhPtr)); + ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); zfhPtr->frameType = ZSTD_skippableFrame; return 0; @@ -433,12 +608,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize) /** ZSTD_decodeFrameHeader() : * `headerSize` must be the size provided by ZSTD_frameHeaderSize(). + * If multiple DDict references are enabled, also will choose the correct DDict to use. * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize) { size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format); if (ZSTD_isError(result)) return result; /* invalid header */ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small"); + + /* Reference DDict requested by frame if dctx references multiple ddicts */ + if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) { + ZSTD_DCtx_selectFrameDDict(dctx); + } + #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* Skip the dictID check in fuzzing mode, because it makes the search * harder. @@ -446,7 +628,9 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID), dictionary_wrong, ""); #endif - if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); + dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0; + if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0); + dctx->processedCSize += headerSize; return 0; } @@ -461,7 +645,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret) static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize) { ZSTD_frameSizeInfo frameSizeInfo; - memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); + ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) if (ZSTD_isLegacy(src, srcSize)) @@ -516,7 +700,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize ip += 4; } - frameSizeInfo.compressedSize = ip - ipstart; + frameSizeInfo.compressedSize = (size_t)(ip - ipstart); frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) ? zfh.frameContentSize : nbBlocks * zfh.blockSizeMax; @@ -569,7 +753,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize) size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize) { DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize); - ZSTD_checkContinuity(dctx, blockStart); + ZSTD_checkContinuity(dctx, blockStart, blockSize); dctx->previousDstEnd = (const char*)blockStart + blockSize; return blockSize; } @@ -579,12 +763,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_copyRawBlock"); + RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); if (dst == NULL) { if (srcSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); - memcpy(dst, src, srcSize); + ZSTD_memcpy(dst, src, srcSize); return srcSize; } @@ -592,15 +776,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, BYTE b, size_t regenSize) { + RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); if (dst == NULL) { if (regenSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); - memset(dst, b, regenSize); + ZSTD_memset(dst, b, regenSize); return regenSize; } +static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming) +{ +#if ZSTD_TRACE + if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) { + ZSTD_Trace trace; + ZSTD_memset(&trace, 0, sizeof(trace)); + trace.version = ZSTD_VERSION_NUMBER; + trace.streaming = streaming; + if (dctx->ddict) { + trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict); + trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict); + trace.dictionaryIsCold = dctx->ddictIsCold; + } + trace.uncompressedSize = (size_t)uncompressedSize; + trace.compressedSize = (size_t)compressedSize; + trace.dctx = dctx; + ZSTD_trace_decompress_end(dctx->traceCtx, &trace); + } +#else + (void)dctx; + (void)uncompressedSize; + (void)compressedSize; + (void)streaming; +#endif +} + /*! ZSTD_decompressFrame() : * @dctx must be properly initialized @@ -610,8 +820,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void** srcPtr, size_t *srcSizePtr) { - const BYTE* ip = (const BYTE*)(*srcPtr); - BYTE* const ostart = (BYTE* const)dst; + const BYTE* const istart = (const BYTE*)(*srcPtr); + const BYTE* ip = istart; + BYTE* const ostart = (BYTE*)dst; BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart; BYTE* op = ostart; size_t remainingSrcSize = *srcSizePtr; @@ -647,13 +858,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, switch(blockProperties.blockType) { case bt_compressed: - decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1); + decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1); break; case bt_raw : - decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize); + decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize); break; case bt_rle : - decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize); + decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize); break; case bt_reserved : default: @@ -661,7 +872,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, } if (ZSTD_isError(decodedSize)) return decodedSize; - if (dctx->fParams.checksumFlag) + if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, op, decodedSize); if (decodedSize != 0) op += decodedSize; @@ -676,19 +887,21 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, corruption_detected, ""); } if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ - U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); - U32 checkRead; RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, ""); - checkRead = MEM_readLE32(ip); - RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); + if (!dctx->forceIgnoreChecksum) { + U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); + U32 checkRead; + checkRead = MEM_readLE32(ip); + RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); + } ip += 4; remainingSrcSize -= 4; } - + ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0); /* Allow caller to get size read */ *srcPtr = ip; *srcSizePtr = remainingSrcSize; - return op-ostart; + return (size_t)(op-ostart); } static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, @@ -721,7 +934,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize); if (ZSTD_isError(decodedSize)) return decodedSize; - assert(decodedSize <=- dstCapacity); + assert(decodedSize <= dstCapacity); dst = (BYTE*)dst + decodedSize; dstCapacity -= decodedSize; @@ -753,7 +966,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, * use this in all cases but ddict */ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), ""); } - ZSTD_checkContinuity(dctx, dst); + ZSTD_checkContinuity(dctx, dst, dstCapacity); { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &src, &srcSize); @@ -761,15 +974,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown) && (moreThan1Frame==1), srcSize_wrong, - "at least one frame successfully completed, but following " - "bytes are garbage: it's more likely to be a srcSize error, " - "specifying more bytes than compressed size of frame(s). This " - "error message replaces ERROR(prefix_unknown), which would be " - "confusing, as the first header is actually correct. Note that " - "one could be unlucky, it might be a corruption error instead, " - "happening right at the place where we expect zstd magic " - "bytes. But this is _much_ less likely than a srcSize field " - "error."); + "At least one frame successfully completed, " + "but following bytes are garbage: " + "it's more likely to be a srcSize error, " + "specifying more input bytes than size of frame(s). " + "Note: one could be unlucky, it might be a corruption error instead, " + "happening right at the place where we expect zstd magic bytes. " + "But this is _much_ less likely than a srcSize field error."); if (ZSTD_isError(res)) return res; assert(res <= dstCapacity); if (res != 0) @@ -781,7 +992,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed"); - return (BYTE*)dst - (BYTE*)dststart; + return (size_t)((BYTE*)dst - (BYTE*)dststart); } size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, @@ -890,7 +1101,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize); /* Sanity check */ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed"); - if (dstCapacity) ZSTD_checkContinuity(dctx, dst); + ZSTD_checkContinuity(dctx, dst, dstCapacity); + + dctx->processedCSize += srcSize; switch (dctx->stage) { @@ -899,21 +1112,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c if (dctx->format == ZSTD_f_zstd1) { /* allows header */ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ - memcpy(dctx->headerBuffer, src, srcSize); + ZSTD_memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */ dctx->stage = ZSTDds_decodeSkippableHeader; return 0; } } dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format); if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize; - memcpy(dctx->headerBuffer, src, srcSize); + ZSTD_memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = dctx->headerSize - srcSize; dctx->stage = ZSTDds_decodeFrameHeader; return 0; case ZSTDds_decodeFrameHeader: assert(src != NULL); - memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); + ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), ""); dctx->expected = ZSTD_blockHeaderSize; dctx->stage = ZSTDds_decodeBlockHeader; @@ -977,7 +1190,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum"); DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize); dctx->decodedSize += rSize; - if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize); dctx->previousDstEnd = (char*)dst + rSize; /* Stay on the same stage until we are finished streaming the block. */ @@ -995,6 +1208,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c dctx->expected = 4; dctx->stage = ZSTDds_checkChecksum; } else { + ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1); dctx->expected = 0; /* ends here */ dctx->stage = ZSTDds_getFrameHeaderSize; } @@ -1007,10 +1221,14 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case ZSTDds_checkChecksum: assert(srcSize == 4); /* guaranteed by dctx->expected */ - { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); - U32 const check32 = MEM_readLE32(src); - DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); - RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); + { + if (dctx->validateChecksum) { + U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); + U32 const check32 = MEM_readLE32(src); + DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); + RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); + } + ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1); dctx->expected = 0; dctx->stage = ZSTDds_getFrameHeaderSize; return 0; @@ -1019,7 +1237,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case ZSTDds_decodeSkippableHeader: assert(src != NULL); assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE); - memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */ + ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */ dctx->stage = ZSTDds_skipFrame; return 0; @@ -1075,7 +1293,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, workspace, workspaceSize); #else size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable, - dictPtr, dictEnd - dictPtr, + dictPtr, (size_t)(dictEnd - dictPtr), workspace, workspaceSize); #endif RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, ""); @@ -1084,40 +1302,46 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, { short offcodeNCount[MaxOff+1]; unsigned offcodeMaxValue = MaxOff, offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->OFTable, offcodeNCount, offcodeMaxValue, OF_base, OF_bits, - offcodeLog); + offcodeLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */0); dictPtr += offcodeHeaderSize; } { short matchlengthNCount[MaxML+1]; unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); + size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->MLTable, matchlengthNCount, matchlengthMaxValue, ML_base, ML_bits, - matchlengthLog); + matchlengthLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */ 0); dictPtr += matchlengthHeaderSize; } { short litlengthNCount[MaxLL+1]; unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); + size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->LLTable, litlengthNCount, litlengthMaxValue, LL_base, LL_bits, - litlengthLog); + litlengthLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */ 0); dictPtr += litlengthHeaderSize; } @@ -1131,7 +1355,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, entropy->rep[i] = rep; } } - return dictPtr - (const BYTE*)dict; + return (size_t)(dictPtr - (const BYTE*)dict); } static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) @@ -1158,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) { assert(dctx != NULL); +#if ZSTD_TRACE + dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0; +#endif dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */ dctx->stage = ZSTDds_getFrameHeaderSize; + dctx->processedCSize = 0; dctx->decodedSize = 0; dctx->previousDstEnd = NULL; dctx->prefixStart = NULL; @@ -1170,7 +1398,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) dctx->dictID = 0; dctx->bType = bt_reserved; ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); - memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ + ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ dctx->LLTptr = dctx->entropy.LLTable; dctx->MLTptr = dctx->entropy.MLTable; dctx->OFTptr = dctx->entropy.OFTable; @@ -1373,6 +1601,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) if (ddict) { dctx->ddict = ddict; dctx->dictUses = ZSTD_use_indefinitely; + if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) { + if (dctx->ddictSet == NULL) { + dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem); + if (!dctx->ddictSet) { + RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!"); + } + } + assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */ + FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), ""); + } } return 0; } @@ -1394,7 +1632,7 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize) size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format) { - return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format); + return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format); } ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) @@ -1411,8 +1649,16 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless); return bounds; case ZSTD_d_stableOutBuffer: - bounds.lowerBound = (int)ZSTD_obm_buffered; - bounds.upperBound = (int)ZSTD_obm_stable; + bounds.lowerBound = (int)ZSTD_bm_buffered; + bounds.upperBound = (int)ZSTD_bm_stable; + return bounds; + case ZSTD_d_forceIgnoreChecksum: + bounds.lowerBound = (int)ZSTD_d_validateChecksum; + bounds.upperBound = (int)ZSTD_d_ignoreChecksum; + return bounds; + case ZSTD_d_refMultipleDDicts: + bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict; + bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts; return bounds; default:; } @@ -1436,6 +1682,29 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value) RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \ } +size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value) +{ + switch (param) { + case ZSTD_d_windowLogMax: + *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize); + return 0; + case ZSTD_d_format: + *value = (int)dctx->format; + return 0; + case ZSTD_d_stableOutBuffer: + *value = (int)dctx->outBufferMode; + return 0; + case ZSTD_d_forceIgnoreChecksum: + *value = (int)dctx->forceIgnoreChecksum; + return 0; + case ZSTD_d_refMultipleDDicts: + *value = (int)dctx->refMultipleDDicts; + return 0; + default:; + } + RETURN_ERROR(parameter_unsupported, ""); +} + size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); @@ -1451,7 +1720,18 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value return 0; case ZSTD_d_stableOutBuffer: CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value); - dctx->outBufferMode = (ZSTD_outBufferMode_e)value; + dctx->outBufferMode = (ZSTD_bufferMode_e)value; + return 0; + case ZSTD_d_forceIgnoreChecksum: + CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value); + dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value; + return 0; + case ZSTD_d_refMultipleDDicts: + CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value); + if (dctx->staticSize != 0) { + RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!"); + } + dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value; return 0; default:; } @@ -1469,8 +1749,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) || (reset == ZSTD_reset_session_and_parameters) ) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); - dctx->format = ZSTD_f_zstd1; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + ZSTD_DCtx_resetParameters(dctx); } return 0; } @@ -1524,7 +1803,7 @@ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const ne { if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize)) zds->oversizedDuration++; - else + else zds->oversizedDuration = 0; } @@ -1538,7 +1817,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* { ZSTD_outBuffer const expect = zds->expectedOutBuffer; /* No requirement when ZSTD_obm_stable is not enabled. */ - if (zds->outBufferMode != ZSTD_obm_stable) + if (zds->outBufferMode != ZSTD_bm_stable) return 0; /* Any buffer is allowed in zdss_init, this must be the same for every other call until * the context is reset. @@ -1548,7 +1827,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* /* The buffer must match our expectation exactly. */ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size) return 0; - RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!"); + RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!"); } /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream() @@ -1560,7 +1839,7 @@ static size_t ZSTD_decompressContinueStream( ZSTD_DStream* zds, char** op, char* oend, void const* src, size_t srcSize) { int const isSkipFrame = ZSTD_isSkipFrame(zds); - if (zds->outBufferMode == ZSTD_obm_buffered) { + if (zds->outBufferMode == ZSTD_bm_buffered) { size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart; size_t const decodedSize = ZSTD_decompressContinue(zds, zds->outBuff + zds->outStart, dstSize, src, srcSize); @@ -1573,14 +1852,14 @@ static size_t ZSTD_decompressContinueStream( } } else { /* Write directly into the output buffer */ - size_t const dstSize = isSkipFrame ? 0 : oend - *op; + size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op); size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize); FORWARD_IF_ERROR(decodedSize, ""); *op += decodedSize; /* Flushing is not needed. */ zds->streamStage = zdss_read; assert(*op <= oend); - assert(zds->outBufferMode == ZSTD_obm_stable); + assert(zds->outBufferMode == ZSTD_bm_stable); } return 0; } @@ -1635,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } } #endif { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format); + if (zds->refMultipleDDicts && zds->ddictSet) { + ZSTD_DCtx_selectFrameDDict(zds); + } DEBUGLOG(5, "header size : %u", (U32)hSize); if (ZSTD_isError(hSize)) { #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) @@ -1663,14 +1945,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB assert(iend >= ip); if (toLoad > remainingInput) { /* not enough input to load full header */ if (remainingInput > 0) { - memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); + ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); zds->lhSize += remainingInput; } input->pos = input->size; return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ } assert(ip != NULL); - memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; + ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; break; } } @@ -1678,10 +1960,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && zds->fParams.frameType != ZSTD_skippableFrame && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) { - size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart); + size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart)); if (cSize <= (size_t)(iend-istart)) { /* shortcut : using single-pass mode */ - size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds)); + size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds)); if (ZSTD_isError(decompressedSize)) return decompressedSize; DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()") ip = istart + cSize; @@ -1693,7 +1975,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } } /* Check output buffer is large enough for ZSTD_odm_stable. */ - if (zds->outBufferMode == ZSTD_obm_stable + if (zds->outBufferMode == ZSTD_bm_stable && zds->fParams.frameType != ZSTD_skippableFrame && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) { @@ -1723,7 +2005,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); - size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered + size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize) : 0; @@ -1731,7 +2013,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize); int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds); - + if (tooSmall || tooLarge) { size_t const bufferSize = neededInBuffSize + neededOutBuffSize; DEBUGLOG(4, "inBuff : from %u to %u", @@ -1745,10 +2027,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), memory_allocation, ""); } else { - ZSTD_free(zds->inBuff, zds->customMem); + ZSTD_customFree(zds->inBuff, zds->customMem); zds->inBuffSize = 0; zds->outBuffSize = 0; - zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); + zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem); RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, ""); } zds->inBuffSize = neededInBuffSize; @@ -1760,7 +2042,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB case zdss_read: DEBUGLOG(5, "stage zdss_read"); - { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip); + { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)); DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize); if (neededInSize==0) { /* end of frame */ zds->streamStage = zdss_init; @@ -1790,7 +2072,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos, corruption_detected, "should never happen"); - loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip); + loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip)); } ip += loadedSize; zds->inPos += loadedSize; @@ -1804,7 +2086,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } case zdss_flush: { size_t const toFlushSize = zds->outEnd - zds->outStart; - size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize); + size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize); op += flushedSize; zds->outStart += flushedSize; if (flushedSize == toFlushSize) { /* flush completed */ diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index ad3b3d8dbd0..349dcdc3336 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -14,7 +14,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <string.h> /* memcpy, memmove, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ #include "../common/compiler.h" /* prefetch */ #include "../common/cpu.h" /* bmi2 */ #include "../common/mem.h" /* low level memory routines */ @@ -44,7 +44,7 @@ /*_******************************************************* * Memory operations **********************************************************/ -static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } +static void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); } /*-************************************************************* @@ -166,7 +166,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, dctx->litSize = litSize; dctx->litEntropy = 1; if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); + ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); return litCSize + lhSize; } @@ -191,10 +191,10 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, ""); - memcpy(dctx->litBuffer, istart+lhSize, litSize); + ZSTD_memcpy(dctx->litBuffer, istart+lhSize, litSize); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); + ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); return lhSize+litSize; } /* direct reference into compressed stream */ @@ -223,7 +223,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, break; } RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); - memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); + ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; return lhSize+1; @@ -236,7 +236,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, /* Default FSE distribution tables. * These are pre-calculated FSE decoding tables using default distributions as defined in specification : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions + * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions * They were generated programmatically with following method : * - start from default distributions, present in /lib/common/zstd_internal.h * - generate tables normally, using ZSTD_buildFSETable() @@ -364,23 +364,26 @@ static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddB * generate FSE decoding table for one symbol (ll, ml or off) * cannot fail if input is valid => * all inputs are presumed validated at this stage */ -void -ZSTD_buildFSETable(ZSTD_seqSymbol* dt, +FORCE_INLINE_TEMPLATE +void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt, const short* normalizedCounter, unsigned maxSymbolValue, const U32* baseValue, const U32* nbAdditionalBits, - unsigned tableLog) + unsigned tableLog, void* wksp, size_t wkspSize) { ZSTD_seqSymbol* const tableDecode = dt+1; - U16 symbolNext[MaxSeq+1]; - U32 const maxSV1 = maxSymbolValue + 1; U32 const tableSize = 1 << tableLog; - U32 highThreshold = tableSize-1; + + U16* symbolNext = (U16*)wksp; + BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1); + U32 highThreshold = tableSize - 1; + /* Sanity Checks */ assert(maxSymbolValue <= MaxSeq); assert(tableLog <= MaxFSELog); - + assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE); + (void)wkspSize; /* Init, lay down lowprob symbols */ { ZSTD_seqSymbol_header DTableH; DTableH.tableLog = tableLog; @@ -396,16 +399,69 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt, assert(normalizedCounter[s]>=0); symbolNext[s] = (U16)normalizedCounter[s]; } } } - memcpy(dt, &DTableH, sizeof(DTableH)); + ZSTD_memcpy(dt, &DTableH, sizeof(DTableH)); } /* Spread symbols */ - { U32 const tableMask = tableSize-1; + assert(tableSize <= 512); + /* Specialized symbol spreading for the case when there are + * no low probability (-1 count) symbols. When compressing + * small blocks we avoid low probability symbols to hit this + * case, since header decoding speed matters more. + */ + if (highThreshold == tableSize - 1) { + size_t const tableMask = tableSize-1; + size_t const step = FSE_TABLESTEP(tableSize); + /* First lay down the symbols in order. + * We use a uint64_t to lay down 8 bytes at a time. This reduces branch + * misses since small blocks generally have small table logs, so nearly + * all symbols have counts <= 8. We ensure we have 8 bytes at the end of + * our buffer to handle the over-write. + */ + { + U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s<maxSV1; ++s, sv += add) { + int i; + int const n = normalizedCounter[s]; + MEM_write64(spread + pos, sv); + for (i = 8; i < n; i += 8) { + MEM_write64(spread + pos + i, sv); + } + pos += n; + } + } + /* Now we spread those positions across the table. + * The benefit of doing it in two stages is that we avoid the the + * variable size inner loop, which caused lots of branch misses. + * Now we can run through all the positions without any branch misses. + * We unroll the loop twice, since that is what emperically worked best. + */ + { + size_t position = 0; + size_t s; + size_t const unroll = 2; + assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */ + for (s = 0; s < (size_t)tableSize; s += unroll) { + size_t u; + for (u = 0; u < unroll; ++u) { + size_t const uPosition = (position + (u * step)) & tableMask; + tableDecode[uPosition].baseValue = spread[s + u]; + } + position = (position + (unroll * step)) & tableMask; + } + assert(position == 0); + } + } else { + U32 const tableMask = tableSize-1; U32 const step = FSE_TABLESTEP(tableSize); U32 s, position = 0; for (s=0; s<maxSV1; s++) { int i; - for (i=0; i<normalizedCounter[s]; i++) { + int const n = normalizedCounter[s]; + for (i=0; i<n; i++) { tableDecode[position].baseValue = s; position = (position + step) & tableMask; while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */ @@ -414,7 +470,8 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt, } /* Build Decoding table */ - { U32 u; + { + U32 u; for (u=0; u<tableSize; u++) { U32 const symbol = tableDecode[u].baseValue; U32 const nextState = symbolNext[symbol]++; @@ -423,7 +480,46 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt, assert(nbAdditionalBits[symbol] < 255); tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol]; tableDecode[u].baseValue = baseValue[symbol]; - } } + } + } +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize) +{ + ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); +} + +#if DYNAMIC_BMI2 +TARGET_ATTRIBUTE("bmi2") static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize) +{ + ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); +} +#endif + +void ZSTD_buildFSETable(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); + return; + } +#endif + (void)bmi2; + ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); } @@ -435,7 +531,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb const void* src, size_t srcSize, const U32* baseValue, const U32* nbAdditionalBits, const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable, - int ddictIsCold, int nbSeq) + int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize, + int bmi2) { switch(type) { @@ -467,7 +564,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, ""); RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, ""); - ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog); + ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2); *DTablePtr = DTableSpace; return headerSize; } @@ -480,7 +577,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, const void* src, size_t srcSize) { - const BYTE* const istart = (const BYTE* const)src; + const BYTE* const istart = (const BYTE*)src; const BYTE* const iend = istart + srcSize; const BYTE* ip = istart; int nbSeq; @@ -499,7 +596,8 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, if (nbSeq > 0x7F) { if (nbSeq == 0xFF) { RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, ""); - nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2; + nbSeq = MEM_readLE16(ip) + LONGNBSEQ; + ip+=2; } else { RETURN_ERROR_IF(ip >= iend, srcSize_wrong, ""); nbSeq = ((nbSeq-0x80)<<8) + *ip++; @@ -520,7 +618,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ip, iend-ip, LL_base, LL_bits, LL_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + dctx->bmi2); RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += llhSize; } @@ -530,7 +630,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ip, iend-ip, OF_base, OF_bits, OF_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + dctx->bmi2); RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += ofhSize; } @@ -540,7 +642,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ip, iend-ip, ML_base, ML_bits, ML_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + dctx->bmi2); RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += mlhSize; } @@ -554,7 +658,6 @@ typedef struct { size_t litLength; size_t matchLength; size_t offset; - const BYTE* match; } seq_t; typedef struct { @@ -568,9 +671,6 @@ typedef struct { ZSTD_fseState stateOffb; ZSTD_fseState stateML; size_t prevOffset[ZSTD_REP_NUM]; - const BYTE* prefixStart; - const BYTE* dictEnd; - size_t pos; } seqState_t; /*! ZSTD_overlapCopy8() : @@ -686,12 +786,12 @@ size_t ZSTD_execSequenceEnd(BYTE* op, RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, ""); match = dictEnd - (prefixStart-match); if (match + sequence.matchLength <= dictEnd) { - memmove(oLitEnd, match, sequence.matchLength); + ZSTD_memmove(oLitEnd, match, sequence.matchLength); return sequenceLength; } /* span extDict & currentPrefixSegment */ { size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); + ZSTD_memmove(oLitEnd, match, length1); op = oLitEnd + length1; sequence.matchLength -= length1; match = prefixStart; @@ -752,12 +852,12 @@ size_t ZSTD_execSequence(BYTE* op, RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, ""); match = dictEnd + (match - prefixStart); if (match + sequence.matchLength <= dictEnd) { - memmove(oLitEnd, match, sequence.matchLength); + ZSTD_memmove(oLitEnd, match, sequence.matchLength); return sequenceLength; } /* span extDict & currentPrefixSegment */ { size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); + ZSTD_memmove(oLitEnd, match, length1); op = oLitEnd + length1; sequence.matchLength -= length1; match = prefixStart; @@ -832,10 +932,9 @@ ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD : 0) typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e; -typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e; FORCE_INLINE_TEMPLATE seq_t -ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch) +ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets) { seq_t seq; ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state]; @@ -910,14 +1009,6 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u", (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); - if (prefetch == ZSTD_p_prefetch) { - size_t const pos = seqState->pos + seq.litLength; - const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart; - seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. - * No consequence though : no memory access will occur, offset is only used for prefetching */ - seqState->pos = pos + seq.matchLength; - } - /* ANS state update * gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo(). * clang-9.2.0 does 7% worse with ZSTD_updateFseState(). @@ -948,7 +1039,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c } #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) +MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) { size_t const windowSize = dctx->fParams.windowSize; /* No dictionary used. */ @@ -969,6 +1060,7 @@ MEM_STATIC void ZSTD_assertValidSequence( seq_t const seq, BYTE const* prefixStart, BYTE const* virtualStart) { +#if DEBUGLEVEL >= 1 size_t const windowSize = dctx->fParams.windowSize; size_t const sequenceSize = seq.litLength + seq.matchLength; BYTE const* const oLitEnd = op + seq.litLength; @@ -986,6 +1078,9 @@ MEM_STATIC void ZSTD_assertValidSequence( /* Offset must be within our window. */ assert(seq.offset <= windowSize); } +#else + (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart; +#endif } #endif @@ -1000,7 +1095,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, { const BYTE* ip = (const BYTE*)seqStart; const BYTE* const iend = ip + seqSize; - BYTE* const ostart = (BYTE* const)dst; + BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + maxDstSize; BYTE* op = ostart; const BYTE* litPtr = dctx->litPtr; @@ -1014,7 +1109,6 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, /* Regen sequences */ if (nbSeq) { seqState_t seqState; - size_t error = 0; dctx->fseEntropy = 1; { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; } RETURN_ERROR_IF( @@ -1048,13 +1142,14 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, * If you see most cycles served out of the DSB you've hit the good case. * If it is pretty even then you may be in an okay case. * - * I've been able to reproduce this issue on the following CPUs: + * This issue has been reproduced on the following CPUs: * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9 * Use Instruments->Counters to get DSB/MITE cycles. * I never got performance swings, but I was able to * go from the good case of mostly DSB to half of the * cycles served from MITE. * - Coffeelake: Intel i9-9900k + * - Coffeelake: Intel i7-9700k * * I haven't been able to reproduce the instability or DSB misses on any * of the following CPUS: @@ -1067,33 +1162,35 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, * * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4 */ + __asm__(".p2align 6"); + __asm__("nop"); __asm__(".p2align 5"); __asm__("nop"); +# if __GNUC__ >= 9 + /* better for gcc-9 and gcc-10, worse for clang and gcc-8 */ + __asm__(".p2align 3"); +# else __asm__(".p2align 4"); +# endif #endif for ( ; ; ) { - seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch); + seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset); size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) assert(!ZSTD_isError(oneSeqSize)); if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); #endif + if (UNLIKELY(ZSTD_isError(oneSeqSize))) + return oneSeqSize; DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + op += oneSeqSize; + if (UNLIKELY(!--nbSeq)) + break; BIT_reloadDStream(&(seqState.DStream)); - /* gcc and clang both don't like early returns in this loop. - * gcc doesn't like early breaks either. - * Instead save an error and report it at the end. - * When there is an error, don't increment op, so we don't - * overwrite. - */ - if (UNLIKELY(ZSTD_isError(oneSeqSize))) error = oneSeqSize; - else op += oneSeqSize; - if (UNLIKELY(!--nbSeq)) break; } /* check if reached exact end */ DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq); - if (ZSTD_isError(error)) return error; RETURN_ERROR_IF(nbSeq, corruption_detected, ""); RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, ""); /* save reps for next block */ @@ -1104,7 +1201,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, { size_t const lastLLSize = litEnd - litPtr; RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); if (op != NULL) { - memcpy(op, litPtr, lastLLSize); + ZSTD_memcpy(op, litPtr, lastLLSize); op += lastLLSize; } } @@ -1124,6 +1221,24 @@ ZSTD_decompressSequences_default(ZSTD_DCtx* dctx, #endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT + +FORCE_INLINE_TEMPLATE size_t +ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence, + const BYTE* const prefixStart, const BYTE* const dictEnd) +{ + prefetchPos += sequence.litLength; + { const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart; + const BYTE* const match = matchBase + prefetchPos - sequence.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. + * No consequence though : memory address is only used for prefetching, not for dereferencing */ + PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ + } + return prefetchPos + sequence.matchLength; +} + +/* This decoding function employs prefetching + * to reduce latency impact of cache misses. + * It's generally employed when block contains a significant portion of long-distance matches + * or when coupled with a "cold" dictionary */ FORCE_INLINE_TEMPLATE size_t ZSTD_decompressSequencesLong_body( ZSTD_DCtx* dctx, @@ -1134,7 +1249,7 @@ ZSTD_decompressSequencesLong_body( { const BYTE* ip = (const BYTE*)seqStart; const BYTE* const iend = ip + seqSize; - BYTE* const ostart = (BYTE* const)dst; + BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + maxDstSize; BYTE* op = ostart; const BYTE* litPtr = dctx->litPtr; @@ -1146,18 +1261,17 @@ ZSTD_decompressSequencesLong_body( /* Regen sequences */ if (nbSeq) { -#define STORED_SEQS 4 +#define STORED_SEQS 8 #define STORED_SEQS_MASK (STORED_SEQS-1) -#define ADVANCED_SEQS 4 +#define ADVANCED_SEQS STORED_SEQS seq_t sequences[STORED_SEQS]; int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS); seqState_t seqState; int seqNb; + size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */ + dctx->fseEntropy = 1; { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; } - seqState.prefixStart = prefixStart; - seqState.pos = (size_t)(op-prefixStart); - seqState.dictEnd = dictEnd; assert(dst != NULL); assert(iend >= ip); RETURN_ERROR_IF( @@ -1169,21 +1283,23 @@ ZSTD_decompressSequencesLong_body( /* prepare in advance */ for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) { - sequences[seqNb] = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch); - PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ + seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset); + prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd); + sequences[seqNb] = sequence; } RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, ""); /* decode and decompress */ for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) { - seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch); + seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset); size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd); #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) assert(!ZSTD_isError(oneSeqSize)); if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart); #endif if (ZSTD_isError(oneSeqSize)) return oneSeqSize; - PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ + + prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd); sequences[seqNb & STORED_SEQS_MASK] = sequence; op += oneSeqSize; } @@ -1209,7 +1325,7 @@ ZSTD_decompressSequencesLong_body( { size_t const lastLLSize = litEnd - litPtr; RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); if (op != NULL) { - memcpy(op, litPtr, lastLLSize); + ZSTD_memcpy(op, litPtr, lastLLSize); op += lastLLSize; } } @@ -1409,9 +1525,9 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, } -void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst) +void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize) { - if (dst != dctx->previousDstEnd) { /* not contiguous */ + if (dst != dctx->previousDstEnd && dstSize > 0) { /* not contiguous */ dctx->dictEnd = dctx->previousDstEnd; dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); dctx->prefixStart = dst; @@ -1425,7 +1541,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, const void* src, size_t srcSize) { size_t dSize; - ZSTD_checkContinuity(dctx, dst); + ZSTD_checkContinuity(dctx, dst, dstCapacity); dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0); dctx->previousDstEnd = (char*)dst + dSize; return dSize; diff --git a/lib/decompress/zstd_decompress_block.h b/lib/decompress/zstd_decompress_block.h index bf39b7350cf..049a0cd84c7 100644 --- a/lib/decompress/zstd_decompress_block.h +++ b/lib/decompress/zstd_decompress_block.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,7 +15,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ #include "../zstd.h" /* DCtx, and some public functions */ #include "../common/zstd_internal.h" /* blockProperties_t, and some public functions */ #include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */ @@ -48,12 +48,15 @@ size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, * this function must be called with valid parameters only * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.) * in which case it cannot fail. + * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is + * defined in zstd_decompress_internal.h. * Internal use only. */ void ZSTD_buildFSETable(ZSTD_seqSymbol* dt, const short* normalizedCounter, unsigned maxSymbolValue, const U32* baseValue, const U32* nbAdditionalBits, - unsigned tableLog); + unsigned tableLog, void* wksp, size_t wkspSize, + int bmi2); #endif /* ZSTD_DEC_BLOCK_H */ diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 9ad96c55488..ebda0c9031d 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -27,26 +27,26 @@ /*-******************************************************* * Constants *********************************************************/ -static const U32 LL_base[MaxLL+1] = { +static UNUSED_ATTR const U32 LL_base[MaxLL+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000 }; -static const U32 OF_base[MaxOff+1] = { +static UNUSED_ATTR const U32 OF_base[MaxOff+1] = { 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD }; -static const U32 OF_bits[MaxOff+1] = { +static UNUSED_ATTR const U32 OF_bits[MaxOff+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; -static const U32 ML_base[MaxML+1] = { +static UNUSED_ATTR const U32 ML_base[MaxML+1] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, @@ -73,12 +73,16 @@ static const U32 ML_base[MaxML+1] = { #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) +#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64)) +#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32)) + typedef struct { ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ U32 rep[ZSTD_REP_NUM]; + U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32]; } ZSTD_entropyDTables_t; typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, @@ -95,10 +99,12 @@ typedef enum { ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */ } ZSTD_dictUses_e; -typedef enum { - ZSTD_obm_buffered = 0, /* Buffer the output */ - ZSTD_obm_stable = 1 /* ZSTD_outBuffer is stable */ -} ZSTD_outBufferMode_e; +/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */ +typedef struct { + const ZSTD_DDict** ddictPtrTable; + size_t ddictPtrTableSize; + size_t ddictPtrCount; +} ZSTD_DDictHashSet; struct ZSTD_DCtx_s { @@ -114,6 +120,7 @@ struct ZSTD_DCtx_s const void* dictEnd; /* end of previous segment */ size_t expected; ZSTD_frameHeader fParams; + U64 processedCSize; U64 decodedSize; blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */ ZSTD_dStage stage; @@ -122,6 +129,8 @@ struct ZSTD_DCtx_s XXH64_state_t xxhState; size_t headerSize; ZSTD_format_e format; + ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum; /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */ + U32 validateChecksum; /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */ const BYTE* litPtr; ZSTD_customMem customMem; size_t litSize; @@ -135,6 +144,8 @@ struct ZSTD_DCtx_s U32 dictID; int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */ ZSTD_dictUses_e dictUses; + ZSTD_DDictHashSet* ddictSet; /* Hash set for multiple ddicts */ + ZSTD_refMultipleDDicts_e refMultipleDDicts; /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */ /* streaming */ ZSTD_dStreamStage streamStage; @@ -152,7 +163,7 @@ struct ZSTD_DCtx_s U32 legacyVersion; U32 hostageByte; int noForwardProgress; - ZSTD_outBufferMode_e outBufferMode; + ZSTD_bufferMode_e outBufferMode; ZSTD_outBuffer expectedOutBuffer; /* workspace */ @@ -165,6 +176,11 @@ struct ZSTD_DCtx_s void const* dictContentBeginForFuzzing; void const* dictContentEndForFuzzing; #endif + + /* Tracing */ +#if ZSTD_TRACE + ZSTD_TraceCtx traceCtx; +#endif }; /* typedef'd to ZSTD_DCtx within "zstd.h" */ @@ -183,7 +199,7 @@ size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, * If yes, do nothing (continue on current segment). * If not, classify previous segment as "external dictionary", and start a new segment. * This function cannot fail. */ -void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst); +void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize); #endif /* ZSTD_DECOMPRESS_INTERNAL_H */ diff --git a/lib/deprecated/zbuff.h b/lib/deprecated/zbuff.h index 03cb14a039d..b83ea0fed58 100644 --- a/lib/deprecated/zbuff.h +++ b/lib/deprecated/zbuff.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff_common.c b/lib/deprecated/zbuff_common.c index 579bc4df14a..e7d01a08180 100644 --- a/lib/deprecated/zbuff_common.c +++ b/lib/deprecated/zbuff_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff_compress.c b/lib/deprecated/zbuff_compress.c index 2d20b137759..2e722673568 100644 --- a/lib/deprecated/zbuff_compress.c +++ b/lib/deprecated/zbuff_compress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff_decompress.c b/lib/deprecated/zbuff_decompress.c index d3c49e84b81..d73c0f35fac 100644 --- a/lib/deprecated/zbuff_decompress.c +++ b/lib/deprecated/zbuff_decompress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index da54ef15f2b..8364444d159 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -26,47 +26,57 @@ #include <string.h> /* memset */ #include <time.h> /* clock */ +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + #include "../common/mem.h" /* read */ #include "../common/pool.h" #include "../common/threading.h" -#include "cover.h" #include "../common/zstd_internal.h" /* includes zstd.h */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" +#include "../zdict.h" +#include "cover.h" /*-************************************* * Constants ***************************************/ #define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB)) -#define DEFAULT_SPLITPOINT 1.0 +#define COVER_DEFAULT_SPLITPOINT 1.0 /*-************************************* * Console display ***************************************/ +#ifndef LOCALDISPLAYLEVEL static int g_displayLevel = 2; +#endif +#undef DISPLAY #define DISPLAY(...) \ { \ fprintf(stderr, __VA_ARGS__); \ fflush(stderr); \ } +#undef LOCALDISPLAYLEVEL #define LOCALDISPLAYLEVEL(displayLevel, l, ...) \ if (displayLevel >= l) { \ DISPLAY(__VA_ARGS__); \ } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ +#undef DISPLAYLEVEL #define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__) +#ifndef LOCALDISPLAYUPDATE +static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100; +static clock_t g_time = 0; +#endif +#undef LOCALDISPLAYUPDATE #define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ if (displayLevel >= l) { \ - if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \ + if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \ g_time = clock(); \ DISPLAY(__VA_ARGS__); \ } \ } +#undef DISPLAYUPDATE #define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__) -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; /*-************************************* * Hash table @@ -120,9 +130,9 @@ static int COVER_map_init(COVER_map_t *map, U32 size) { /** * Internal hash function */ -static const U32 prime4bytes = 2654435761U; +static const U32 COVER_prime4bytes = 2654435761U; static U32 COVER_map_hash(COVER_map_t *map, U32 key) { - return (key * prime4bytes) >> (32 - map->sizeLog); + return (key * COVER_prime4bytes) >> (32 - map->sizeLog); } /** @@ -215,7 +225,7 @@ typedef struct { } COVER_ctx_t; /* We need a global context for qsort... */ -static COVER_ctx_t *g_ctx = NULL; +static COVER_ctx_t *g_coverCtx = NULL; /*-************************************* * Helper functions @@ -258,11 +268,11 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) { /** * Same as COVER_cmp() except ties are broken by pointer value - * NOTE: g_ctx must be set to call this function. A global is required because + * NOTE: g_coverCtx must be set to call this function. A global is required because * qsort doesn't take an opaque pointer. */ -static int COVER_strict_cmp(const void *lp, const void *rp) { - int result = COVER_cmp(g_ctx, lp, rp); +static int WIN_CDECL COVER_strict_cmp(const void *lp, const void *rp) { + int result = COVER_cmp(g_coverCtx, lp, rp); if (result == 0) { result = lp < rp ? -1 : 1; } @@ -271,8 +281,8 @@ static int COVER_strict_cmp(const void *lp, const void *rp) { /** * Faster version for d <= 8. */ -static int COVER_strict_cmp8(const void *lp, const void *rp) { - int result = COVER_cmp8(g_ctx, lp, rp); +static int WIN_CDECL COVER_strict_cmp8(const void *lp, const void *rp) { + int result = COVER_cmp8(g_coverCtx, lp, rp); if (result == 0) { result = lp < rp ? -1 : 1; } @@ -603,7 +613,7 @@ static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer, /* qsort doesn't take an opaque pointer, so pass as a global. * On OpenBSD qsort() is not guaranteed to be stable, their mergesort() is. */ - g_ctx = ctx; + g_coverCtx = ctx; #if defined(__OpenBSD__) mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32), (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); @@ -946,7 +956,7 @@ void COVER_dictSelectionFree(COVER_dictSelection_t selection){ free(selection.dictContent); } -COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, +COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity, size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples, size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize) { @@ -954,8 +964,8 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t largestCompressed = 0; BYTE* customDictContentEnd = customDictContent + dictContentSize; - BYTE * largestDictbuffer = (BYTE *)malloc(dictContentSize); - BYTE * candidateDictBuffer = (BYTE *)malloc(dictContentSize); + BYTE * largestDictbuffer = (BYTE *)malloc(dictBufferCapacity); + BYTE * candidateDictBuffer = (BYTE *)malloc(dictBufferCapacity); double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00; if (!largestDictbuffer || !candidateDictBuffer) { @@ -967,7 +977,7 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, /* Initial dictionary size and compressed size */ memcpy(largestDictbuffer, customDictContent, dictContentSize); dictContentSize = ZDICT_finalizeDictionary( - largestDictbuffer, dictContentSize, customDictContent, dictContentSize, + largestDictbuffer, dictBufferCapacity, customDictContent, dictContentSize, samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams); if (ZDICT_isError(dictContentSize)) { @@ -1001,7 +1011,7 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, while (dictContentSize < largestDict) { memcpy(candidateDictBuffer, largestDictbuffer, largestDict); dictContentSize = ZDICT_finalizeDictionary( - candidateDictBuffer, dictContentSize, customDictContentEnd - dictContentSize, dictContentSize, + candidateDictBuffer, dictBufferCapacity, customDictContentEnd - dictContentSize, dictContentSize, samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams); if (ZDICT_isError(dictContentSize)) { @@ -1053,18 +1063,19 @@ typedef struct COVER_tryParameters_data_s { * This function is thread safe if zstd is compiled with multithreaded support. * It takes its parameters as an *OWNING* opaque pointer to support threading. */ -static void COVER_tryParameters(void *opaque) { +static void COVER_tryParameters(void *opaque) +{ /* Save parameters as local variables */ - COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t *)opaque; + COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t*)opaque; const COVER_ctx_t *const ctx = data->ctx; const ZDICT_cover_params_t parameters = data->parameters; size_t dictBufferCapacity = data->dictBufferCapacity; size_t totalCompressedSize = ERROR(GENERIC); /* Allocate space for hash table, dict, and freqs */ COVER_map_t activeDmers; - BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity); + BYTE* const dict = (BYTE*)malloc(dictBufferCapacity); COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC)); - U32 *freqs = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); + U32* const freqs = (U32*)malloc(ctx->suffixSize * sizeof(U32)); if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) { DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); goto _cleanup; @@ -1079,7 +1090,7 @@ static void COVER_tryParameters(void *opaque) { { const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict, dictBufferCapacity, parameters); - selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail, + selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail, ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets, totalCompressedSize); @@ -1094,19 +1105,18 @@ static void COVER_tryParameters(void *opaque) { free(data); COVER_map_destroy(&activeDmers); COVER_dictSelectionFree(selection); - if (freqs) { - free(freqs); - } + free(freqs); } ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover( - void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, - ZDICT_cover_params_t *parameters) { + void* dictBuffer, size_t dictBufferCapacity, const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples, + ZDICT_cover_params_t* parameters) +{ /* constants */ const unsigned nbThreads = parameters->nbThreads; const double splitPoint = - parameters->splitPoint <= 0.0 ? DEFAULT_SPLITPOINT : parameters->splitPoint; + parameters->splitPoint <= 0.0 ? COVER_DEFAULT_SPLITPOINT : parameters->splitPoint; const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d; const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k; diff --git a/lib/dictBuilder/cover.h b/lib/dictBuilder/cover.h index f2aa0e35e3a..1aacdddd6fe 100644 --- a/lib/dictBuilder/cover.h +++ b/lib/dictBuilder/cover.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, Facebook, Inc. + * Copyright (c) Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -8,6 +8,10 @@ * You may select, at your option, one of the above-listed licenses. */ +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + #include <stdio.h> /* fprintf */ #include <stdlib.h> /* malloc, free, qsort */ #include <string.h> /* memset */ @@ -16,10 +20,7 @@ #include "../common/pool.h" #include "../common/threading.h" #include "../common/zstd_internal.h" /* includes zstd.h */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" +#include "../zdict.h" /** * COVER_best_t is used for two purposes: @@ -152,6 +153,6 @@ void COVER_dictSelectionFree(COVER_dictSelection_t selection); * smallest dictionary within a specified regression of the compressed size * from the largest dictionary. */ - COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, + COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity, size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples, size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize); diff --git a/lib/dictBuilder/divsufsort.c b/lib/dictBuilder/divsufsort.c index ead9220442b..a2870fb3ba3 100644 --- a/lib/dictBuilder/divsufsort.c +++ b/lib/dictBuilder/divsufsort.c @@ -1576,7 +1576,7 @@ sort_typeBstar(const unsigned char *T, int *SA, /* Construct the inverse suffix array of type B* suffixes using trsort. */ trsort(ISAb, SA, m, 1); - /* Set the sorted order of tyoe B* suffixes. */ + /* Set the sorted order of type B* suffixes. */ for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) { for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { } if(0 <= i) { diff --git a/lib/dictBuilder/fastcover.c b/lib/dictBuilder/fastcover.c index 485c333b54a..ed789f92f48 100644 --- a/lib/dictBuilder/fastcover.c +++ b/lib/dictBuilder/fastcover.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Facebook, Inc. + * Copyright (c) Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -16,15 +16,17 @@ #include <string.h> /* memset */ #include <time.h> /* clock */ +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + #include "../common/mem.h" /* read */ #include "../common/pool.h" #include "../common/threading.h" -#include "cover.h" #include "../common/zstd_internal.h" /* includes zstd.h */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" +#include "../compress/zstd_compress_internal.h" /* ZSTD_hash*() */ +#include "../zdict.h" +#include "cover.h" /*-************************************* @@ -33,7 +35,7 @@ #define FASTCOVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB)) #define FASTCOVER_MAX_F 31 #define FASTCOVER_MAX_ACCEL 10 -#define DEFAULT_SPLITPOINT 0.75 +#define FASTCOVER_DEFAULT_SPLITPOINT 0.75 #define DEFAULT_F 20 #define DEFAULT_ACCEL 1 @@ -41,50 +43,50 @@ /*-************************************* * Console display ***************************************/ +#ifndef LOCALDISPLAYLEVEL static int g_displayLevel = 2; +#endif +#undef DISPLAY #define DISPLAY(...) \ { \ fprintf(stderr, __VA_ARGS__); \ fflush(stderr); \ } +#undef LOCALDISPLAYLEVEL #define LOCALDISPLAYLEVEL(displayLevel, l, ...) \ if (displayLevel >= l) { \ DISPLAY(__VA_ARGS__); \ } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ +#undef DISPLAYLEVEL #define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__) +#ifndef LOCALDISPLAYUPDATE +static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100; +static clock_t g_time = 0; +#endif +#undef LOCALDISPLAYUPDATE #define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ if (displayLevel >= l) { \ - if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \ + if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \ g_time = clock(); \ DISPLAY(__VA_ARGS__); \ } \ } +#undef DISPLAYUPDATE #define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__) -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; /*-************************************* * Hash Functions ***************************************/ -static const U64 prime6bytes = 227718039650203ULL; -static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; } -static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); } - -static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; -static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; } -static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } - - /** - * Hash the d-byte value pointed to by p and mod 2^f + * Hash the d-byte value pointed to by p and mod 2^f into the frequency vector */ -static size_t FASTCOVER_hashPtrToIndex(const void* p, U32 h, unsigned d) { +static size_t FASTCOVER_hashPtrToIndex(const void* p, U32 f, unsigned d) { if (d == 6) { - return ZSTD_hash6Ptr(p, h) & ((1 << h) - 1); + return ZSTD_hash6Ptr(p, f); } - return ZSTD_hash8Ptr(p, h) & ((1 << h) - 1); + return ZSTD_hash8Ptr(p, f); } @@ -461,20 +463,20 @@ typedef struct FASTCOVER_tryParameters_data_s { * This function is thread safe if zstd is compiled with multithreaded support. * It takes its parameters as an *OWNING* opaque pointer to support threading. */ -static void FASTCOVER_tryParameters(void *opaque) +static void FASTCOVER_tryParameters(void* opaque) { /* Save parameters as local variables */ - FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t *)opaque; + FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t*)opaque; const FASTCOVER_ctx_t *const ctx = data->ctx; const ZDICT_cover_params_t parameters = data->parameters; size_t dictBufferCapacity = data->dictBufferCapacity; size_t totalCompressedSize = ERROR(GENERIC); /* Initialize array to keep track of frequency of dmer within activeSegment */ - U16* segmentFreqs = (U16 *)calloc(((U64)1 << ctx->f), sizeof(U16)); + U16* segmentFreqs = (U16*)calloc(((U64)1 << ctx->f), sizeof(U16)); /* Allocate space for hash table, dict, and freqs */ - BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity); + BYTE *const dict = (BYTE*)malloc(dictBufferCapacity); COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC)); - U32 *freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32)); + U32* freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32)); if (!segmentFreqs || !dict || !freqs) { DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n"); goto _cleanup; @@ -486,7 +488,7 @@ static void FASTCOVER_tryParameters(void *opaque) parameters, segmentFreqs); const unsigned nbFinalizeSamples = (unsigned)(ctx->nbTrainSamples * ctx->accelParams.finalize / 100); - selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail, + selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail, ctx->samples, ctx->samplesSizes, nbFinalizeSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets, totalCompressedSize); @@ -617,7 +619,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover( /* constants */ const unsigned nbThreads = parameters->nbThreads; const double splitPoint = - parameters->splitPoint <= 0.0 ? DEFAULT_SPLITPOINT : parameters->splitPoint; + parameters->splitPoint <= 0.0 ? FASTCOVER_DEFAULT_SPLITPOINT : parameters->splitPoint; const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d; const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k; diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 6d0b04231bb..459cbe4d19b 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -23,9 +23,13 @@ /* Unix Large Files support (>4GB) */ #define _FILE_OFFSET_BITS 64 #if (defined(__sun__) && (!defined(__LP64__))) /* Sun Solaris 32-bits requires specific definitions */ +# ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE +# endif #elif ! defined(__LP64__) /* No point defining Large file for 64 bit */ +# ifndef _LARGEFILE64_SOURCE # define _LARGEFILE64_SOURCE +# endif #endif @@ -37,18 +41,19 @@ #include <stdio.h> /* fprintf, fopen, ftello64 */ #include <time.h> /* clock */ +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif +#define HUF_STATIC_LINKING_ONLY + #include "../common/mem.h" /* read */ #include "../common/fse.h" /* FSE_normalizeCount, FSE_writeNCount */ -#define HUF_STATIC_LINKING_ONLY #include "../common/huf.h" /* HUF_buildCTable, HUF_writeCTable */ #include "../common/zstd_internal.h" /* includes zstd.h */ #include "../common/xxhash.h" /* XXH64 */ -#include "divsufsort.h" -#ifndef ZDICT_STATIC_LINKING_ONLY -# define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" #include "../compress/zstd_compress_internal.h" /* ZSTD_loadCEntropy() */ +#include "../zdict.h" +#include "divsufsort.h" /*-************************************* @@ -62,14 +67,15 @@ #define NOISELENGTH 32 -static const int g_compressionLevel_default = 3; static const U32 g_selectivity_default = 9; /*-************************************* * Console display ***************************************/ +#undef DISPLAY #define DISPLAY(...) { fprintf(stderr, __VA_ARGS__); fflush( stderr ); } +#undef DISPLAYLEVEL #define DISPLAYLEVEL(l, ...) if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ static clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; } @@ -105,20 +111,17 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) size_t headerSize; if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return ERROR(dictionary_corrupted); - { unsigned offcodeMaxValue = MaxOff; - ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); + { ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); - short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short)); - if (!bs || !wksp || !offcodeNCount) { + if (!bs || !wksp) { headerSize = ERROR(memory_allocation); } else { ZSTD_reset_compressedBlockState(bs); - headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); + headerSize = ZSTD_loadCEntropy(bs, wksp, dictBuffer, dictSize); } free(bs); free(wksp); - free(offcodeNCount); } return headerSize; @@ -532,6 +535,7 @@ static size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize, clock_t displayClock = 0; clock_t const refreshRate = CLOCKS_PER_SEC * 3 / 10; +# undef DISPLAYUPDATE # define DISPLAYUPDATE(l, ...) if (notificationLevel>=l) { \ if (ZDICT_clockSpan(displayClock) > refreshRate) \ { displayClock = clock(); DISPLAY(__VA_ARGS__); \ @@ -706,7 +710,7 @@ static void ZDICT_flatLit(unsigned* countLit) #define OFFCODE_MAX 30 /* only applicable to first block */ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, - unsigned compressionLevel, + int compressionLevel, const void* srcBuffer, const size_t* fileSizes, unsigned nbFiles, const void* dictBuffer, size_t dictBufferSize, unsigned notificationLevel) @@ -741,7 +745,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, memset(repOffset, 0, sizeof(repOffset)); repOffset[1] = repOffset[4] = repOffset[8] = 1; memset(bestRepOffset, 0, sizeof(bestRepOffset)); - if (compressionLevel==0) compressionLevel = g_compressionLevel_default; + if (compressionLevel==0) compressionLevel = ZSTD_CLEVEL_DEFAULT; params = ZSTD_getParams(compressionLevel, averageSampleSize, dictBufferSize); esr.dict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, params.cParams, ZSTD_defaultCMem); @@ -786,7 +790,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, /* note : the result of this phase should be used to better appreciate the impact on statistics */ total=0; for (u=0; u<=offcodeMax; u++) total+=offcodeCount[u]; - errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax); + errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax, /* useLowProbCount */ 1); if (FSE_isError(errorCode)) { eSize = errorCode; DISPLAYLEVEL(1, "FSE_normalizeCount error with offcodeCount \n"); @@ -795,7 +799,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, Offlog = (U32)errorCode; total=0; for (u=0; u<=MaxML; u++) total+=matchLengthCount[u]; - errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML); + errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML, /* useLowProbCount */ 1); if (FSE_isError(errorCode)) { eSize = errorCode; DISPLAYLEVEL(1, "FSE_normalizeCount error with matchLengthCount \n"); @@ -804,7 +808,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, mlLog = (U32)errorCode; total=0; for (u=0; u<=MaxLL; u++) total+=litLengthCount[u]; - errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL); + errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL, /* useLowProbCount */ 1); if (FSE_isError(errorCode)) { eSize = errorCode; DISPLAYLEVEL(1, "FSE_normalizeCount error with litLengthCount \n"); @@ -893,7 +897,7 @@ size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity, size_t hSize; #define HBUFFSIZE 256 /* should prove large enough for all entropy headers */ BYTE header[HBUFFSIZE]; - int const compressionLevel = (params.compressionLevel == 0) ? g_compressionLevel_default : params.compressionLevel; + int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel; U32 const notificationLevel = params.notificationLevel; /* check conditions */ @@ -939,7 +943,7 @@ static size_t ZDICT_addEntropyTablesFromBuffer_advanced( const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, ZDICT_params_t params) { - int const compressionLevel = (params.compressionLevel == 0) ? g_compressionLevel_default : params.compressionLevel; + int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel; U32 const notificationLevel = params.notificationLevel; size_t hSize = 8; @@ -968,16 +972,11 @@ static size_t ZDICT_addEntropyTablesFromBuffer_advanced( return MIN(dictBufferCapacity, hSize+dictContentSize); } -/* Hidden declaration for dbio.c */ -size_t ZDICT_trainFromBuffer_unsafe_legacy( - void* dictBuffer, size_t maxDictSize, - const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, - ZDICT_legacy_params_t params); /*! ZDICT_trainFromBuffer_unsafe_legacy() : -* Warning : `samplesBuffer` must be followed by noisy guard band. +* Warning : `samplesBuffer` must be followed by noisy guard band !!! * @return : size of dictionary, or an error code which can be tested with ZDICT_isError() */ -size_t ZDICT_trainFromBuffer_unsafe_legacy( +static size_t ZDICT_trainFromBuffer_unsafe_legacy( void* dictBuffer, size_t maxDictSize, const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, ZDICT_legacy_params_t params) @@ -1114,8 +1113,8 @@ size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity, memset(¶ms, 0, sizeof(params)); params.d = 8; params.steps = 4; - /* Default to level 6 since no compression level information is available */ - params.zParams.compressionLevel = 3; + /* Use default level since no compression level information is available */ + params.zParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; #if defined(DEBUGLEVEL) && (DEBUGLEVEL>=1) params.zParams.notificationLevel = DEBUGLEVEL; #endif diff --git a/lib/dictBuilder/zdict.h b/lib/zdict.h similarity index 70% rename from lib/dictBuilder/zdict.h rename to lib/zdict.h index ff2e77faf77..75b05dbf43e 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/zdict.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -36,6 +36,145 @@ extern "C" { # define ZDICTLIB_API ZDICTLIB_VISIBILITY #endif +/******************************************************************************* + * Zstd dictionary builder + * + * FAQ + * === + * Why should I use a dictionary? + * ------------------------------ + * + * Zstd can use dictionaries to improve compression ratio of small data. + * Traditionally small files don't compress well because there is very little + * repetion in a single sample, since it is small. But, if you are compressing + * many similar files, like a bunch of JSON records that share the same + * structure, you can train a dictionary on ahead of time on some samples of + * these files. Then, zstd can use the dictionary to find repetitions that are + * present across samples. This can vastly improve compression ratio. + * + * When is a dictionary useful? + * ---------------------------- + * + * Dictionaries are useful when compressing many small files that are similar. + * The larger a file is, the less benefit a dictionary will have. Generally, + * we don't expect dictionary compression to be effective past 100KB. And the + * smaller a file is, the more we would expect the dictionary to help. + * + * How do I use a dictionary? + * -------------------------- + * + * Simply pass the dictionary to the zstd compressor with + * `ZSTD_CCtx_loadDictionary()`. The same dictionary must then be passed to + * the decompressor, using `ZSTD_DCtx_loadDictionary()`. There are other + * more advanced functions that allow selecting some options, see zstd.h for + * complete documentation. + * + * What is a zstd dictionary? + * -------------------------- + * + * A zstd dictionary has two pieces: Its header, and its content. The header + * contains a magic number, the dictionary ID, and entropy tables. These + * entropy tables allow zstd to save on header costs in the compressed file, + * which really matters for small data. The content is just bytes, which are + * repeated content that is common across many samples. + * + * What is a raw content dictionary? + * --------------------------------- + * + * A raw content dictionary is just bytes. It doesn't have a zstd dictionary + * header, a dictionary ID, or entropy tables. Any buffer is a valid raw + * content dictionary. + * + * How do I train a dictionary? + * ---------------------------- + * + * Gather samples from your use case. These samples should be similar to each + * other. If you have several use cases, you could try to train one dictionary + * per use case. + * + * Pass those samples to `ZDICT_trainFromBuffer()` and that will train your + * dictionary. There are a few advanced versions of this function, but this + * is a great starting point. If you want to further tune your dictionary + * you could try `ZDICT_optimizeTrainFromBuffer_cover()`. If that is too slow + * you can try `ZDICT_optimizeTrainFromBuffer_fastCover()`. + * + * If the dictionary training function fails, that is likely because you + * either passed too few samples, or a dictionary would not be effective + * for your data. Look at the messages that the dictionary trainer printed, + * if it doesn't say too few samples, then a dictionary would not be effective. + * + * How large should my dictionary be? + * ---------------------------------- + * + * A reasonable dictionary size, the `dictBufferCapacity`, is about 100KB. + * The zstd CLI defaults to a 110KB dictionary. You likely don't need a + * dictionary larger than that. But, most use cases can get away with a + * smaller dictionary. The advanced dictionary builders can automatically + * shrink the dictionary for you, and select a the smallest size that + * doesn't hurt compression ratio too much. See the `shrinkDict` parameter. + * A smaller dictionary can save memory, and potentially speed up + * compression. + * + * How many samples should I provide to the dictionary builder? + * ------------------------------------------------------------ + * + * We generally recommend passing ~100x the size of the dictionary + * in samples. A few thousand should suffice. Having too few samples + * can hurt the dictionaries effectiveness. Having more samples will + * only improve the dictionaries effectiveness. But having too many + * samples can slow down the dictionary builder. + * + * How do I determine if a dictionary will be effective? + * ----------------------------------------------------- + * + * Simply train a dictionary and try it out. You can use zstd's built in + * benchmarking tool to test the dictionary effectiveness. + * + * # Benchmark levels 1-3 without a dictionary + * zstd -b1e3 -r /path/to/my/files + * # Benchmark levels 1-3 with a dictioanry + * zstd -b1e3 -r /path/to/my/files -D /path/to/my/dictionary + * + * When should I retrain a dictionary? + * ----------------------------------- + * + * You should retrain a dictionary when its effectiveness drops. Dictionary + * effectiveness drops as the data you are compressing changes. Generally, we do + * expect dictionaries to "decay" over time, as your data changes, but the rate + * at which they decay depends on your use case. Internally, we regularly + * retrain dictionaries, and if the new dictionary performs significantly + * better than the old dictionary, we will ship the new dictionary. + * + * I have a raw content dictionary, how do I turn it into a zstd dictionary? + * ------------------------------------------------------------------------- + * + * If you have a raw content dictionary, e.g. by manually constructing it, or + * using a third-party dictionary builder, you can turn it into a zstd + * dictionary by using `ZDICT_finalizeDictionary()`. You'll also have to + * provide some samples of the data. It will add the zstd header to the + * raw content, which contains a dictionary ID and entropy tables, which + * will improve compression ratio, and allow zstd to write the dictionary ID + * into the frame, if you so choose. + * + * Do I have to use zstd's dictionary builder? + * ------------------------------------------- + * + * No! You can construct dictionary content however you please, it is just + * bytes. It will always be valid as a raw content dictionary. If you want + * a zstd dictionary, which can improve compression ratio, use + * `ZDICT_finalizeDictionary()`. + * + * What is the attack surface of a zstd dictionary? + * ------------------------------------------------ + * + * Zstd is heavily fuzz tested, including loading fuzzed dictionaries, so + * zstd should never crash, or access out-of-bounds memory no matter what + * the dictionary is. However, if an attacker can control the dictionary + * during decompression, they can cause zstd to generate arbitrary bytes, + * just like if they controlled the compressed data. + * + ******************************************************************************/ + /*! ZDICT_trainFromBuffer(): * Train a dictionary from an array of samples. @@ -64,7 +203,14 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap typedef struct { int compressionLevel; /*< optimize for a specific zstd compression level; 0 means default */ unsigned notificationLevel; /*< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ - unsigned dictID; /*< force dictID value; 0 means auto mode (32-bits random value) */ + unsigned dictID; /*< force dictID value; 0 means auto mode (32-bits random value) + * NOTE: The zstd format reserves some dictionary IDs for future use. + * You may use them in private settings, but be warned that they + * may be used by zstd in a public dictionary registry in the future. + * These dictionary IDs are: + * - low range : <= 32767 + * - high range : >= (2^31) + */ } ZDICT_params_t; /*! ZDICT_finalizeDictionary(): @@ -264,10 +410,11 @@ typedef struct { * Note: ZDICT_trainFromBuffer_legacy() will send notifications into stderr if instructed to, using notificationLevel>0. */ ZDICTLIB_API size_t ZDICT_trainFromBuffer_legacy( - void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, + void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, ZDICT_legacy_params_t parameters); + /* Deprecation warnings */ /* It is generally possible to disable deprecation warnings from compiler, for example with -Wno-deprecated-declarations for gcc @@ -279,7 +426,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_legacy( # define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) # if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ # define ZDICT_DEPRECATED(message) [[deprecated(message)]] ZDICTLIB_API -# elif (ZDICT_GCC_VERSION >= 405) || defined(__clang__) +# elif defined(__clang__) || (ZDICT_GCC_VERSION >= 405) # define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated(message))) # elif (ZDICT_GCC_VERSION >= 301) # define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated)) diff --git a/lib/zstd.h b/lib/zstd.h index 8c6fc6ae90e..4651e6c4dc7 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -71,17 +71,22 @@ extern "C" { /*------ Version ------*/ #define ZSTD_VERSION_MAJOR 1 -#define ZSTD_VERSION_MINOR 4 -#define ZSTD_VERSION_RELEASE 5 - +#define ZSTD_VERSION_MINOR 5 +#define ZSTD_VERSION_RELEASE 0 #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) -ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ + +/*! ZSTD_versionNumber() : + * Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */ +ZSTDLIB_API unsigned ZSTD_versionNumber(void); #define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE #define ZSTD_QUOTE(str) #str #define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) #define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) -ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ + +/*! ZSTD_versionString() : + * Return runtime library version, like "1.4.5". Requires v1.3.0+. */ +ZSTDLIB_API const char* ZSTD_versionString(void); /* ************************************* * Default constant @@ -104,7 +109,6 @@ ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ #define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX) - /*************************************** * Simple API ***************************************/ @@ -161,7 +165,7 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); -/*! ZSTD_findFrameCompressedSize() : +/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+ * `src` should point to the start of a ZSTD frame or skippable frame. * `srcSize` must be >= first frame size * @return : the compressed size of the first frame starting at `src`, @@ -175,8 +179,9 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize) ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ -ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */ +ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ +ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */ /*************************************** @@ -194,7 +199,7 @@ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compres */ typedef struct ZSTD_CCtx_s ZSTD_CCtx; ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); -ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer */ /*! ZSTD_compressCCtx() : * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. @@ -217,7 +222,7 @@ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, * Use one context per thread for parallel execution. */ typedef struct ZSTD_DCtx_s ZSTD_DCtx; ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); -ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */ /*! ZSTD_decompressDCtx() : * Same as ZSTD_decompress(), @@ -229,9 +234,9 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, const void* src, size_t srcSize); -/*************************************** -* Advanced compression API -***************************************/ +/********************************************* +* Advanced compression API (Requires v1.4.0+) +**********************************************/ /* API design : * Parameters are pushed one by one into an existing context, @@ -261,7 +266,6 @@ typedef enum { ZSTD_fast=1, Only the order (from fast to strong) is guaranteed */ } ZSTD_strategy; - typedef enum { /* compression parameters @@ -327,14 +331,15 @@ typedef enum { * The higher the value of selected strategy, the more complex it is, * resulting in stronger and slower compression. * Special: value 0 means "use default strategy". */ - /* LDM mode parameters */ ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching. * This parameter is designed to improve compression ratio * for large inputs, by finding large matches at long distance. * It increases memory usage and window size. * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB - * except when expressly set to a different value. */ + * except when expressly set to a different value. + * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and + * compression strategy >= ZSTD_btopt (== compression level 16+) */ ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. * Larger values increase memory usage and compression ratio, * but decrease compression speed. @@ -365,20 +370,24 @@ typedef enum { ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ /* multi-threading parameters */ - /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). - * They return an error otherwise. */ + /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). + * Otherwise, trying to set any other value than default (0) will be a no-op and return an error. + * In a situation where it's unknown if the linked library supports multi-threading or not, + * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property. + */ ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. - * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() : + * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() : * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, - * while compression work is performed in parallel, within worker threads. + * while compression is performed in parallel, within worker thread(s). * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). * More workers improve speed, but also increase memory usage. - * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */ + * Default value is `0`, aka "single-threaded mode" : no worker is spawned, + * compression is performed inside Caller's thread, and all invocations are blocking */ ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. * 0 means default, which is dynamically determined based on compression parameters. - * Job size must be a minimum of overlap size, or 1 MB, whichever is largest. + * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest. * The minimum size is automatically and transparently enforced. */ ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size. * The overlap size is an amount of data reloaded from previous job at the beginning of a new job. @@ -403,6 +412,13 @@ typedef enum { * ZSTD_c_literalCompressionMode * ZSTD_c_targetCBlockSize * ZSTD_c_srcSizeHint + * ZSTD_c_enableDedicatedDictSearch + * ZSTD_c_stableInBuffer + * ZSTD_c_stableOutBuffer + * ZSTD_c_blockDelimiters + * ZSTD_c_validateSequences + * ZSTD_c_splitBlocks + * ZSTD_c_useRowMatchFinder * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly; * also, the enums values themselves are unstable and can still change. @@ -413,7 +429,15 @@ typedef enum { ZSTD_c_experimentalParam4=1001, ZSTD_c_experimentalParam5=1002, ZSTD_c_experimentalParam6=1003, - ZSTD_c_experimentalParam7=1004 + ZSTD_c_experimentalParam7=1004, + ZSTD_c_experimentalParam8=1005, + ZSTD_c_experimentalParam9=1006, + ZSTD_c_experimentalParam10=1007, + ZSTD_c_experimentalParam11=1008, + ZSTD_c_experimentalParam12=1009, + ZSTD_c_experimentalParam13=1010, + ZSTD_c_experimentalParam14=1011, + ZSTD_c_experimentalParam15=1012 } ZSTD_cParameter; typedef struct { @@ -498,9 +522,9 @@ ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, const void* src, size_t srcSize); -/*************************************** -* Advanced decompression API -***************************************/ +/*********************************************** +* Advanced decompression API (Requires v1.4.0+) +************************************************/ /* The advanced API pushes parameters one by one into an existing DCtx context. * Parameters are sticky, and remain valid for all following frames @@ -524,11 +548,15 @@ typedef enum { * At the time of this writing, they include : * ZSTD_d_format * ZSTD_d_stableOutBuffer + * ZSTD_d_forceIgnoreChecksum + * ZSTD_d_refMultipleDDicts * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly */ ZSTD_d_experimentalParam1=1000, - ZSTD_d_experimentalParam2=1001 + ZSTD_d_experimentalParam2=1001, + ZSTD_d_experimentalParam3=1002, + ZSTD_d_experimentalParam4=1003 } ZSTD_dParameter; @@ -642,7 +670,7 @@ typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ /*===== ZSTD_CStream management functions =====*/ ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); -ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); +ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */ /*===== Streaming compression functions =====*/ typedef enum { @@ -658,14 +686,15 @@ typedef enum { : note : multithreaded compression will block to flush as much output as possible. */ } ZSTD_EndDirective; -/*! ZSTD_compressStream2() : +/*! ZSTD_compressStream2() : Requires v1.4.0+ * Behaves about the same as ZSTD_compressStream, with additional control on end directive. * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) * - output->pos must be <= dstCapacity, input->pos must be <= srcSize * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. + * - endOp must be a valid directive * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. - * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available, + * - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available, * and then immediately returns, just indicating that there is some data remaining to be flushed. * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking. @@ -703,11 +732,11 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output /* ***************************************************************************** - * This following is a legacy streaming API. + * This following is a legacy streaming API, available since v1.0+ . * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). * It is redundant, but remains fully supported. - * Advanced parameters and dictionary compression can only be used through the - * new API. + * Streaming in combination with advanced parameters and dictionary compression + * can only be used through the new API. ******************************************************************************/ /*! @@ -762,7 +791,7 @@ typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ /*===== ZSTD_DStream management functions =====*/ ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); -ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */ /*===== Streaming decompression functions =====*/ @@ -785,7 +814,7 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output /*! ZSTD_compress_usingDict() : * Compression at an explicit compression level using a Dictionary. * A dictionary can be any arbitrary data segment (also called a prefix), - * or a buffer with specified information (see dictBuilder/zdict.h). + * or a buffer with specified information (see zdict.h). * Note : This function loads the dictionary, resulting in significant startup delay. * It's intended for a dictionary used only once. * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ @@ -828,7 +857,8 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize int compressionLevel); /*! ZSTD_freeCDict() : - * Function frees memory allocated by ZSTD_createCDict(). */ + * Function frees memory allocated by ZSTD_createCDict(). + * If a NULL pointer is passed, no operation is performed. */ ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); /*! ZSTD_compress_usingCDict() : @@ -850,7 +880,8 @@ typedef struct ZSTD_DDict_s ZSTD_DDict; ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); /*! ZSTD_freeDDict() : - * Function frees memory allocated with ZSTD_createDDict() */ + * Function frees memory allocated with ZSTD_createDDict() + * If a NULL pointer is passed, no operation is performed. */ ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); /*! ZSTD_decompress_usingDDict() : @@ -866,19 +897,25 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, * Dictionary helper functions *******************************/ -/*! ZSTD_getDictID_fromDict() : +/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+ * Provides the dictID stored within dictionary. * if @return == 0, the dictionary is not conformant with Zstandard specification. * It can still be loaded, but as a content-only dictionary. */ ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); -/*! ZSTD_getDictID_fromDDict() : +/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+ + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict); + +/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+ * Provides the dictID of the dictionary loaded into `ddict`. * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); -/*! ZSTD_getDictID_fromFrame() : +/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+ * Provides the dictID required to decompressed the frame stored within `src`. * If @return == 0, the dictID could not be decoded. * This could for one of the following reasons : @@ -892,7 +929,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); /******************************************************************************* - * Advanced dictionary and prefix API + * Advanced dictionary and prefix API (Requires v1.4.0+) * * This API allows dictionaries to be used with ZSTD_compress2(), * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and @@ -901,7 +938,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); ******************************************************************************/ -/*! ZSTD_CCtx_loadDictionary() : +/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+ * Create an internal CDict from `dict` buffer. * Decompression will have to use same dictionary. * @result : 0, or an error code (which can be tested with ZSTD_isError()). @@ -920,11 +957,11 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); * to precisely select how dictionary content must be interpreted. */ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); -/*! ZSTD_CCtx_refCDict() : +/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+ * Reference a prepared dictionary, to be used for all next compressed frames. * Note that compression parameters are enforced from within CDict, * and supersede any compression parameter previously set within CCtx. - * The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. + * The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode. * The dictionary will remain valid for future compressed frames using same CCtx. * @result : 0, or an error code (which can be tested with ZSTD_isError()). @@ -934,7 +971,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); -/*! ZSTD_CCtx_refPrefix() : +/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+ * Reference a prefix (single-usage dictionary) for next compressed frame. * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end). * Decompression will need same prefix to properly regenerate data. @@ -955,7 +992,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize); -/*! ZSTD_DCtx_loadDictionary() : +/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+ * Create an internal DDict from dict buffer, * to be used to decompress next frames. * The dictionary remains valid for all future frames, until explicitly invalidated. @@ -972,9 +1009,16 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, */ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); -/*! ZSTD_DCtx_refDDict() : +/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+ * Reference a prepared dictionary, to be used to decompress next frames. * The dictionary remains active for decompression of future frames using same DCtx. + * + * If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function + * will store the DDict references in a table, and the DDict used for decompression + * will be determined at decompression time, as per the dict ID in the frame. + * The memory for the table is allocated on the first call to refDDict, and can be + * freed with ZSTD_freeDCtx(). + * * @result : 0, or an error code (which can be tested with ZSTD_isError()). * Note 1 : Currently, only one dictionary can be managed. * Referencing a new dictionary effectively "discards" any previous one. @@ -983,7 +1027,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, s */ ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); -/*! ZSTD_DCtx_refPrefix() : +/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+ * Reference a prefix (single-usage dictionary) to decompress next frame. * This is the reverse operation of ZSTD_CCtx_refPrefix(), * and must use the same prefix as the one used during compression. @@ -1004,7 +1048,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, /* === Memory management === */ -/*! ZSTD_sizeof_*() : +/*! ZSTD_sizeof_*() : Requires v1.4.0+ * These functions give the _current_ memory usage of selected object. * Note that object memory usage can evolve (increase or decrease) over time. */ ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); @@ -1029,6 +1073,28 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); #if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) #define ZSTD_H_ZSTD_STATIC_LINKING_ONLY +/* Deprecation warnings : + * Should these warnings be a problem, it is generally possible to disable them, + * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual. + * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS. + */ +#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS +# define ZSTD_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */ +#else +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API +# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) +# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message))) +# elif defined(__GNUC__) && (__GNUC__ >= 3) +# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define ZSTD_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler") +# define ZSTD_DEPRECATED(message) ZSTDLIB_API +# endif +#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */ + /**************************************************************************************** * experimental API (static linking only) **************************************************************************************** @@ -1100,21 +1166,40 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params; typedef struct { - unsigned int matchPos; /* Match pos in dst */ - /* If seqDef.offset > 3, then this is seqDef.offset - 3 - * If seqDef.offset < 3, then this is the corresponding repeat offset - * But if seqDef.offset < 3 and litLength == 0, this is the - * repeat offset before the corresponding repeat offset - * And if seqDef.offset == 3 and litLength == 0, this is the - * most recent repeat offset - 1 - */ - unsigned int offset; - unsigned int litLength; /* Literal length */ - unsigned int matchLength; /* Match length */ - /* 0 when seq not rep and seqDef.offset otherwise - * when litLength == 0 this will be <= 4, otherwise <= 3 like normal - */ - unsigned int rep; + unsigned int offset; /* The offset of the match. (NOT the same as the offset code) + * If offset == 0 and matchLength == 0, this sequence represents the last + * literals in the block of litLength size. + */ + + unsigned int litLength; /* Literal length of the sequence. */ + unsigned int matchLength; /* Match length of the sequence. */ + + /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0. + * In this case, we will treat the sequence as a marker for a block boundary. + */ + + unsigned int rep; /* Represents which repeat offset is represented by the field 'offset'. + * Ranges from [0, 3]. + * + * Repeat offsets are essentially previous offsets from previous sequences sorted in + * recency order. For more detail, see doc/zstd_compression_format.md + * + * If rep == 0, then 'offset' does not contain a repeat offset. + * If rep > 0: + * If litLength != 0: + * rep == 1 --> offset == repeat_offset_1 + * rep == 2 --> offset == repeat_offset_2 + * rep == 3 --> offset == repeat_offset_3 + * If litLength == 0: + * rep == 1 --> offset == repeat_offset_2 + * rep == 2 --> offset == repeat_offset_3 + * rep == 3 --> offset == repeat_offset_1 - 1 + * + * Note: This field is optional. ZSTD_generateSequences() will calculate the value of + * 'rep', but repeat offsets do not necessarily need to be calculated from an external + * sequence provider's perspective. For example, ZSTD_compressSequences() does not + * use this 'rep' field at all (as of now). + */ } ZSTD_Sequence; typedef struct { @@ -1156,6 +1241,18 @@ typedef enum { * Decoder cannot recognise automatically this format, requiring this instruction. */ } ZSTD_format_e; +typedef enum { + /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */ + ZSTD_d_validateChecksum = 0, + ZSTD_d_ignoreChecksum = 1 +} ZSTD_forceIgnoreChecksum_e; + +typedef enum { + /* Note: this enum controls ZSTD_d_refMultipleDDicts */ + ZSTD_rmd_refSingleDDict = 0, + ZSTD_rmd_refMultipleDDicts = 1 +} ZSTD_refMultipleDDicts_e; + typedef enum { /* Note: this enum and the behavior it controls are effectively internal * implementation details of the compressor. They are expected to continue @@ -1204,6 +1301,11 @@ typedef enum { ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ } ZSTD_literalCompressionMode_e; +typedef enum { + ZSTD_urm_auto = 0, /* Automatically determine whether or not we use row matchfinder */ + ZSTD_urm_disableRowMatchFinder = 1, /* Never use row matchfinder */ + ZSTD_urm_enableRowMatchFinder = 2 /* Always use row matchfinder when applicable */ +} ZSTD_useRowMatchFinderMode_e; /*************************************** * Frame size functions @@ -1237,7 +1339,7 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t * `srcSize` must be the _exact_ size of this series * (i.e. there should be a frame boundary at `src + srcSize`) * @return : - upper-bound for the decompressed size of all data in all successive frames - * - if an error occured: ZSTD_CONTENTSIZE_ERROR + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR * * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame. * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`. @@ -1253,14 +1355,91 @@ ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcS * or an error code (if srcSize is too small) */ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); -/*! ZSTD_getSequences() : - * Extract sequences from the sequence store +typedef enum { + ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */ + ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */ +} ZSTD_sequenceFormat_e; + +/*! ZSTD_generateSequences() : + * Generate sequences using ZSTD_compress2, given a source buffer. + * + * Each block will end with a dummy sequence + * with offset == 0, matchLength == 0, and litLength == length of last literals. + * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0) + * simply acts as a block delimiter. + * * zc can be used to insert custom compression params. * This function invokes ZSTD_compress2 - * @return : number of sequences extracted + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters + * @return : number of sequences generated + */ + +ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, + size_t outSeqsSize, const void* src, size_t srcSize); + +/*! ZSTD_mergeBlockDelimiters() : + * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals + * by merging them into into the literals of the next sequence. + * + * As such, the final generated result has no explicit representation of block boundaries, + * and the final last literals segment is not represented in the sequences. + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters + * @return : number of sequences left after merging + */ +ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize); + +/*! ZSTD_compressSequences() : + * Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst. + * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.) + * The entire source is compressed into a single frame. + * + * The compression behavior changes based on cctx params. In particular: + * If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on + * the block size derived from the cctx, and sequences may be split. This is the default setting. + * + * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. + * + * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined + * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and return an error. + * + * In addition to the two adjustable experimental params, there are other important cctx params. + * - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN. + * - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression. + * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset + * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md + * + * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused. + * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly, + * and cannot emit an RLE block that disagrees with the repcode history + * @return : final compressed size or a ZSTD error. */ -ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize); + + +/*! ZSTD_writeSkippableFrame() : + * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer. + * + * Skippable frames begin with a a 4-byte magic number. There are 16 possible choices of magic number, + * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15. + * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so + * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant. + * + * Returns an error if destination buffer is not large enough, if the source size is not representable + * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid). + * + * @return : number of bytes written or a ZSTD error. + */ +ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, unsigned magicVariant); /*************************************** @@ -1372,7 +1551,11 @@ ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict( typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); typedef void (*ZSTD_freeFunction) (void* opaque, void* address); typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; -static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ +static +#ifdef __GNUC__ +__attribute__((__unused__)) +#endif +ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); @@ -1385,12 +1568,38 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictS ZSTD_compressionParameters cParams, ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_customMem customMem); +/* ! Thread pool : + * These prototypes make it possible to share a thread pool among multiple compression contexts. + * This can limit resources for applications with multiple threads where each one uses + * a threaded compression mode (via ZSTD_c_nbWorkers parameter). + * ZSTD_createThreadPool creates a new thread pool with a given number of threads. + * Note that the lifetime of such pool must exist while being used. + * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value + * to use an internal thread pool). + * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer. + */ +typedef struct POOL_ctx_s ZSTD_threadPool; +ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads); +ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */ +ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool); +/* + * This API is temporary and is expected to change or disappear in the future! + */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* cctxParams, + ZSTD_customMem customMem); + +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_customMem customMem); + /*************************************** * Advanced compression functions @@ -1430,18 +1639,20 @@ ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParame /*! ZSTD_compress_advanced() : * Note : this function is now DEPRECATED. * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters. - * This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */ -ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, + * This prototype will generate compilation warnings. */ +ZSTD_DEPRECATED("use ZSTD_compress2") +size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict,size_t dictSize, ZSTD_parameters params); /*! ZSTD_compress_usingCDict_advanced() : - * Note : this function is now REDUNDANT. + * Note : this function is now DEPRECATED. * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters. - * This prototype will be marked as deprecated and generate compilation warning in some future version */ -ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + * This prototype will generate compilation warnings. */ +ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary") +size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const ZSTD_CDict* cdict, @@ -1503,7 +1714,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre /* Controls how the literals are compressed (default is auto). * The value must be of type ZSTD_literalCompressionMode_e. - * See ZSTD_literalCompressionMode_t enum definition for details. + * See ZSTD_literalCompressionMode_e enum definition for details. */ #define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5 @@ -1518,12 +1729,189 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre * but compression ratio may regress significantly if guess considerably underestimates */ #define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 +/* Controls whether the new and experimental "dedicated dictionary search + * structure" can be used. This feature is still rough around the edges, be + * prepared for surprising behavior! + * + * How to use it: + * + * When using a CDict, whether to use this feature or not is controlled at + * CDict creation, and it must be set in a CCtxParams set passed into that + * construction (via ZSTD_createCDict_advanced2()). A compression will then + * use the feature or not based on how the CDict was constructed; the value of + * this param, set in the CCtx, will have no effect. + * + * However, when a dictionary buffer is passed into a CCtx, such as via + * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control + * whether the CDict that is created internally can use the feature or not. + * + * What it does: + * + * Normally, the internal data structures of the CDict are analogous to what + * would be stored in a CCtx after compressing the contents of a dictionary. + * To an approximation, a compression using a dictionary can then use those + * data structures to simply continue what is effectively a streaming + * compression where the simulated compression of the dictionary left off. + * Which is to say, the search structures in the CDict are normally the same + * format as in the CCtx. + * + * It is possible to do better, since the CDict is not like a CCtx: the search + * structures are written once during CDict creation, and then are only read + * after that, while the search structures in the CCtx are both read and + * written as the compression goes along. This means we can choose a search + * structure for the dictionary that is read-optimized. + * + * This feature enables the use of that different structure. + * + * Note that some of the members of the ZSTD_compressionParameters struct have + * different semantics and constraints in the dedicated search structure. It is + * highly recommended that you simply set a compression level in the CCtxParams + * you pass into the CDict creation call, and avoid messing with the cParams + * directly. + * + * Effects: + * + * This will only have any effect when the selected ZSTD_strategy + * implementation supports this feature. Currently, that's limited to + * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2. + * + * Note that this means that the CDict tables can no longer be copied into the + * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be + * useable. The dictionary can only be attached or reloaded. + * + * In general, you should expect compression to be faster--sometimes very much + * so--and CDict creation to be slightly slower. Eventually, we will probably + * make this mode the default. + */ +#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8 + +/* ZSTD_c_stableInBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the compressor that the ZSTD_inBuffer will ALWAYS be the same + * between calls, except for the modifications that zstd makes to pos (the + * caller must not modify pos). This is checked by the compressor, and + * compression will fail if it ever changes. This means the only flush + * mode that makes sense is ZSTD_e_end, so zstd will error if ZSTD_e_end + * is not used. The data in the ZSTD_inBuffer in the range [src, src + pos) + * MUST not be modified during compression or you will get data corruption. + * + * When this flag is enabled zstd won't allocate an input window buffer, + * because the user guarantees it can reference the ZSTD_inBuffer until + * the frame is complete. But, it will still allocate an output buffer + * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also + * avoid the memcpy() from the input buffer to the input window buffer. + * + * NOTE: ZSTD_compressStream2() will error if ZSTD_e_end is not used. + * That means this flag cannot be used with ZSTD_compressStream(). + * + * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, compression WILL fail if you violate the preconditions. + * + * WARNING: The data in the ZSTD_inBuffer in the range [dst, dst + pos) MUST + * not be modified during compression or you will get data corruption. This + * is because zstd needs to reference data in the ZSTD_inBuffer to find + * matches. Normally zstd maintains its own window buffer for this purpose, + * but passing this flag tells zstd to use the user provided buffer. + */ +#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9 + +/* ZSTD_c_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells he compressor that the ZSTD_outBuffer will not be resized between + * calls. Specifically: (out.size - out.pos) will never grow. This gives the + * compressor the freedom to say: If the compressed data doesn't fit in the + * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to + * always decompress directly into the output buffer, instead of decompressing + * into an internal buffer and copying to the output buffer. + * + * When this flag is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer. It will still allocate the + * input window buffer (see ZSTD_c_stableInBuffer). + * + * Zstd will check that (out.size - out.pos) never grows and return an error + * if it does. While not strictly necessary, this should prevent surprises. + */ +#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10 + +/* ZSTD_c_blockDelimiters + * Default is 0 == ZSTD_sf_noBlockDelimiters. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * + * Designates whether or not the given array of ZSTD_Sequence contains block delimiters + * and last literals, which are defined as sequences with offset == 0 and matchLength == 0. + * See the definition of ZSTD_Sequence for more specifics. + */ +#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11 + +/* ZSTD_c_validateSequences + * Default is 0 == disabled. Set to 1 to enable sequence validation. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * Designates whether or not we validate sequences provided to ZSTD_compressSequences() + * during function execution. + * + * Without validation, providing a sequence that does not conform to the zstd spec will cause + * undefined behavior, and may produce a corrupted block. + * + * With validation enabled, a if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and + * return an error. + * + */ +#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12 + +/* ZSTD_c_splitBlocks + * Default is 0 == disabled. Set to 1 to enable block splitting. + * + * Will attempt to split blocks in order to improve compression ratio at the cost of speed. + */ +#define ZSTD_c_splitBlocks ZSTD_c_experimentalParam13 + +/* ZSTD_c_useRowMatchFinder + * Default is ZSTD_urm_auto. + * Controlled with ZSTD_useRowMatchFinderMode_e enum. + * + * By default, in ZSTD_urm_auto, when finalizing the compression parameters, the library + * will decide at runtime whether to use the row-based matchfinder based on support for SIMD + * instructions as well as the windowLog. + * + * Set to ZSTD_urm_disableRowMatchFinder to never use row-based matchfinder. + * Set to ZSTD_urm_enableRowMatchFinder to force usage of row-based matchfinder. + */ +#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14 + +/* ZSTD_c_deterministicRefPrefix + * Default is 0 == disabled. Set to 1 to enable. + * + * Zstd produces different results for prefix compression when the prefix is + * directly adjacent to the data about to be compressed vs. when it isn't. + * This is because zstd detects that the two buffers are contiguous and it can + * use a more efficient match finding algorithm. However, this produces different + * results than when the two buffers are non-contiguous. This flag forces zstd + * to always load the prefix in non-contiguous mode, even if it happens to be + * adjacent to the data, to guarantee determinism. + * + * If you really care about determinism when using a dictionary or prefix, + * like when doing delta compression, you should select this option. It comes + * at a speed penalty of about ~2.5% if the dictionary and data happened to be + * contiguous, and is free if they weren't contiguous. We don't expect that + * intentionally making the dictionary and data contiguous will be worth the + * cost to memcpy() the data. + */ +#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15 + /*! ZSTD_CCtx_getParameter() : * Get the requested compression parameter value, selected by enum ZSTD_cParameter, * and store it into int* value. * @return : 0, or an error code (which can be tested with ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); +ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); /*! ZSTD_CCtx_params : @@ -1538,13 +1926,13 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param * These parameters will be applied to * all subsequent frames. * - ZSTD_compressStream2() : Do compression using the CCtx. - * - ZSTD_freeCCtxParams() : Free the memory. + * - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer. * * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() * for static allocation of CCtx for single-threaded compression. */ ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); -ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); +ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */ /*! ZSTD_CCtxParams_reset() : * Reset params to default values. @@ -1563,11 +1951,13 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compre */ ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); -/*! ZSTD_CCtxParams_setParameter() : +/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+ * Similar to ZSTD_CCtx_setParameter. * Set one compression parameter, selected by enum ZSTD_cParameter. - * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). - * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Parameters must be applied to a ZSTD_CCtx using + * ZSTD_CCtx_setParametersUsingCCtxParams(). + * @result : a code representing success or failure (which can be tested with + * ZSTD_isError()). */ ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); @@ -1576,7 +1966,7 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_c * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. * @result : 0, or an error code (which can be tested with ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); +ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); /*! ZSTD_CCtx_setParametersUsingCCtxParams() : * Apply a set of ZSTD_CCtx_params to the compression context. @@ -1647,6 +2037,13 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* pre */ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); +/*! ZSTD_DCtx_getParameter() : + * Get the requested decompression parameter value, selected by enum ZSTD_dParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value); + /* ZSTD_d_format * experimental parameter, * allowing selection between ZSTD_format_e input compression formats @@ -1684,12 +2081,49 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS */ #define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 +/* ZSTD_d_forceIgnoreChecksum + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * Tells the decompressor to skip checksum validation during decompression, regardless + * of whether checksumming was specified during compression. This offers some + * slight performance benefits, and may be useful for debugging. + * Param has values of type ZSTD_forceIgnoreChecksum_e + */ +#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3 + +/* ZSTD_d_refMultipleDDicts + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * If enabled and dctx is allocated on the heap, then additional memory will be allocated + * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict() + * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead + * store all references. At decompression time, the appropriate dictID is selected + * from the set of DDicts based on the dictID in the frame. + * + * Usage is simply calling ZSTD_refDDict() on multiple dict buffers. + * + * Param has values of byte ZSTD_refMultipleDDicts_e + * + * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory + * allocation for the hash table. ZSTD_freeDCtx() also frees this memory. + * Memory is allocated as per ZSTD_DCtx::customMem. + * + * Although this function allocates memory for the table, the user is still responsible for + * memory management of the underlying ZSTD_DDict* themselves. + */ +#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4 + + /*! ZSTD_DCtx_setFormat() : + * This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter(). * Instruct the decoder context about what kind of data to decode next. * This instruction is mandatory to decode data without a fully-formed header, * such ZSTD_f_zstd1_magicless for example. * @return : 0, or an error code (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); +ZSTD_DEPRECATED("use ZSTD_DCtx_setParameter() instead") +size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); /*! ZSTD_decompressStream_simpleArgs() : * Same as ZSTD_decompressStream(), @@ -1711,8 +2145,9 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs ( ********************************************************************/ /*===== Advanced Streaming compression functions =====*/ -/**! ZSTD_initCStream_srcSize() : - * This function is deprecated, and equivalent to: + +/*! ZSTD_initCStream_srcSize() : + * This function is DEPRECATED, and equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); @@ -1721,15 +2156,15 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs ( * pledgedSrcSize must be correct. If it is not known at init time, use * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, * "0" also disables frame content size field. It may be enabled in the future. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + * This prototype will generate compilation warnings. */ -ZSTDLIB_API size_t -ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); -/**! ZSTD_initCStream_usingDict() : - * This function is deprecated, and is equivalent to: +/*! ZSTD_initCStream_usingDict() : + * This function is DEPRECATED, and is equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); @@ -1738,15 +2173,15 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, * dict == NULL or dictSize < 8, in which case no dict is used. * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + * This prototype will generate compilation warnings. */ -ZSTDLIB_API size_t -ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); -/**! ZSTD_initCStream_advanced() : - * This function is deprecated, and is approximately equivalent to: +/*! ZSTD_initCStream_advanced() : + * This function is DEPRECATED, and is approximately equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * // Pseudocode: Set each zstd parameter and leave the rest as-is. * for ((param, value) : params) { @@ -1758,25 +2193,26 @@ ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy. * pledgedSrcSize must be correct. * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + * This prototype will generate compilation warnings. */ -ZSTDLIB_API size_t -ZSTD_initCStream_advanced(ZSTD_CStream* zcs, +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); -/**! ZSTD_initCStream_usingCDict() : - * This function is deprecated, and equivalent to: +/*! ZSTD_initCStream_usingCDict() : + * This function is DEPRECATED, and equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_refCDict(zcs, cdict); - * + * * note : cdict will just be referenced, and must outlive compression session - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + * This prototype will generate compilation warnings. */ -ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); +ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions") +size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); -/**! ZSTD_initCStream_usingCDict_advanced() : +/*! ZSTD_initCStream_usingCDict_advanced() : * This function is DEPRECATED, and is approximately equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * // Pseudocode: Set each zstd frame parameter and leave the rest as-is. @@ -1789,18 +2225,21 @@ ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDi * same as ZSTD_initCStream_usingCDict(), with control over frame parameters. * pledgedSrcSize must be correct. If srcSize is not known at init time, use * value ZSTD_CONTENTSIZE_UNKNOWN. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + * This prototype will generate compilation warnings. */ -ZSTDLIB_API size_t -ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, +ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions") +size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /*! ZSTD_resetCStream() : - * This function is deprecated, and is equivalent to: + * This function is DEPRECATED, and is equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but + * ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be + * explicitly specified. * * start a new frame, using same parameters from previous frame. * This is typically useful to skip dictionary loading stage, since it will re-use it in-place. @@ -1810,9 +2249,10 @@ ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. * @return : 0, or an error code (which can be tested using ZSTD_isError()) - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + * This prototype will generate compilation warnings. */ -ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); typedef struct { @@ -1849,7 +2289,8 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); /*===== Advanced Streaming decompression functions =====*/ -/** + +/*! * This function is deprecated, and is equivalent to: * * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); @@ -1860,7 +2301,7 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); */ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); -/** +/*! * This function is deprecated, and is equivalent to: * * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); @@ -1871,7 +2312,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dic */ ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); -/** +/*! * This function is deprecated, and is equivalent to: * * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); @@ -1898,8 +2339,7 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); ZSTD_CCtx object can be re-used multiple times within successive compression operations. Start by initializing a context. - Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression, - or ZSTD_compressBegin_advanced(), for finer parameter control. + Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression. It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx() Then, consume your input using ZSTD_compressContinue(). @@ -1924,16 +2364,18 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /*===== Buffer-less streaming compression functions =====*/ ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); -ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ -ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); - -/*- +/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */ +ZSTD_DEPRECATED("use advanced API to access custom parameters") +size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ +ZSTD_DEPRECATED("use advanced API to access custom parameters") +size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ +/** Buffer-less streaming decompression (synchronous mode) A ZSTD_DCtx object is required to track streaming operations. diff --git a/lib/common/zstd_errors.h b/lib/zstd_errors.h similarity index 97% rename from lib/common/zstd_errors.h rename to lib/zstd_errors.h index 998398e7e57..fa3686b7724 100644 --- a/lib/common/zstd_errors.h +++ b/lib/zstd_errors.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -77,6 +77,7 @@ typedef enum { ZSTD_error_frameIndex_tooLarge = 100, ZSTD_error_seekableIO = 102, ZSTD_error_dstBuffer_wrong = 104, + ZSTD_error_srcBuffer_wrong = 105, ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ } ZSTD_ErrorCode; From ffb54e2350035b7d1cb7f11f89a998307ee3d8bf Mon Sep 17 00:00:00 2001 From: Deniz Bahadir <deniz@code.bahadir.email> Date: Tue, 12 Oct 2021 18:01:50 +0200 Subject: [PATCH 1396/1519] Help: Add more documentation for CMAKE_<LANG>_SIMULATE_ID Signed-off-by: Deniz Bahadir <deniz@code.bahadir.email> --- Help/variable/CMAKE_LANG_SIMULATE_ID.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Help/variable/CMAKE_LANG_SIMULATE_ID.rst b/Help/variable/CMAKE_LANG_SIMULATE_ID.rst index 15c87a186fd..3226352a293 100644 --- a/Help/variable/CMAKE_LANG_SIMULATE_ID.rst +++ b/Help/variable/CMAKE_LANG_SIMULATE_ID.rst @@ -1,9 +1,13 @@ CMAKE_<LANG>_SIMULATE_ID ------------------------ -Identification string of "simulated" compiler. +Identification string of the "simulated" compiler. Some compilers simulate other compilers to serve as drop-in replacements. When CMake detects such a compiler it sets this variable to what would have been the :variable:`CMAKE_<LANG>_COMPILER_ID` for the simulated compiler. + +.. note:: + In other words, this variable describes the ABI compatibility + of the generated code. From f2262fab51d6d7625303bb2ba2a4c617046b3ca0 Mon Sep 17 00:00:00 2001 From: Deniz Bahadir <deniz@code.bahadir.email> Date: Tue, 12 Oct 2021 18:22:21 +0200 Subject: [PATCH 1397/1519] Help: Add documentation for CMAKE_<LANG>_COMPILER_FRONTEND_VARIANT Signed-off-by: Deniz Bahadir <deniz@code.bahadir.email> --- Help/manual/cmake-variables.7.rst | 1 + .../CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 17f04ab53f1..a2103f72bf9 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -71,6 +71,7 @@ Variables that Provide Information /variable/CMAKE_JOB_POOL_PRECOMPILE_HEADER /variable/CMAKE_JOB_POOLS /variable/CMAKE_LANG_COMPILER_AR + /variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT /variable/CMAKE_LANG_COMPILER_RANLIB /variable/CMAKE_LANG_LINK_LIBRARY_SUFFIX /variable/CMAKE_LINK_LIBRARY_SUFFIX diff --git a/Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst b/Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst new file mode 100644 index 00000000000..128b1fbbebe --- /dev/null +++ b/Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst @@ -0,0 +1,18 @@ +CMAKE_<LANG>_COMPILER_FRONTEND_VARIANT +-------------------------------------- + +.. versionadded:: 3.14 + +Identification string of the compiler frontend variant. + +Some compilers have multiple, different frontends for accepting command +line options. (For example ``Clang`` originally only had a frontend +compatible with the ``GNU`` compiler but since its port to Windows +(``Clang-Cl``) it now also supports a frontend compatible with ``MSVC``.) +When CMake detects such a compiler it sets this +variable to what would have been the :variable:`CMAKE_<LANG>_COMPILER_ID` for +the compiler whose frontend it resembles. + +.. note:: + In other words, this variable describes what command line options + and language extensions the compiler frontend expects. From 67f8d20a8e13033818fe3ddcbe6f9beada0b2b16 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Tue, 12 Oct 2021 13:43:53 -0400 Subject: [PATCH 1398/1519] Help: clarify list(POP_* <in_out> <in_out>) behavior --- Help/command/list.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Help/command/list.rst b/Help/command/list.rst index f46641f0b6a..9b49cb493ac 100644 --- a/Help/command/list.rst +++ b/Help/command/list.rst @@ -161,8 +161,9 @@ Inserts elements to the list to the specified location. .. versionadded:: 3.15 If no variable name is given, removes exactly one element. Otherwise, -assign the last element's value to the given variable and removes it, -up to the last variable name given. +with `N` variable names provided, assign the last `N` elements' values +to the given variables and then remove the last `N` values from +``<list>``. .. _POP_FRONT: @@ -173,8 +174,9 @@ up to the last variable name given. .. versionadded:: 3.15 If no variable name is given, removes exactly one element. Otherwise, -assign the first element's value to the given variable and removes it, -up to the last variable name given. +with `N` variable names provided, assign the first `N` elements' values +to the given variables and then remove the first `N` values from +``<list>``. .. _PREPEND: From ee98d9378fe83c442ee8e66f8eddc222add4880c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 05:09:11 -0400 Subject: [PATCH 1399/1519] zstd: Fix ZSTD_VecMask_next compilation of software ctz implementation --- Utilities/cmzstd/lib/compress/zstd_lazy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Utilities/cmzstd/lib/compress/zstd_lazy.c b/Utilities/cmzstd/lib/compress/zstd_lazy.c index 3d523e8472f..6ce897dc89a 100644 --- a/Utilities/cmzstd/lib/compress/zstd_lazy.c +++ b/Utilities/cmzstd/lib/compress/zstd_lazy.c @@ -1081,7 +1081,8 @@ static U32 ZSTD_VecMask_next(ZSTD_VecMask val) { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; - return multiplyDeBruijnBitPosition[((U32)((v & -(int)v) * 0x077CB531U)) >> 27]; + return multiplyDeBruijnBitPosition[((U32)((val & -(int)val) * 0x077CB531U)) >> 27]; + # endif } From ddced0c6b6e6d0e2f1bbbcc6daf6cb5a42cee9bc Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 05:53:03 -0400 Subject: [PATCH 1400/1519] zstd: Fix trace compilation on AIX Since zstd commit `6cee3c2c` ([trace] Remove default definitions of weak symbols, 2021-04-26, v1.5.0^2~53^2), the weak symbol trace implementation does not compile on AIX. Disable it. --- Utilities/cmzstd/lib/common/zstd_trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/cmzstd/lib/common/zstd_trace.h b/Utilities/cmzstd/lib/common/zstd_trace.h index 2da5640771d..485cadf7c4c 100644 --- a/Utilities/cmzstd/lib/common/zstd_trace.h +++ b/Utilities/cmzstd/lib/common/zstd_trace.h @@ -20,7 +20,7 @@ extern "C" { /* weak symbol support */ #if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && defined(__GNUC__) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \ - !defined(__CYGWIN__) + !defined(__CYGWIN__) && !defined(_AIX) # define ZSTD_HAVE_WEAK_SYMBOLS 1 #else # define ZSTD_HAVE_WEAK_SYMBOLS 0 From 167060303b6d9ffb56b2785cec0f7e363f0876c6 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 08:03:54 -0400 Subject: [PATCH 1401/1519] CMake 3.22.0-rc1 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index beb43a83eec..0c01b0039ad 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 22) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 0) +set(CMake_VERSION_RC 1) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From e4e4c59180fca93da5713c076c2dd00a199554ac Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 10:35:52 -0400 Subject: [PATCH 1402/1519] zstd: Backport fix for SIGBUS on armv6 from zstd 1.5.0 Backport zstd commit `28d0120b` (Avoid SIGBUS on armv6, 2021-05-11, `v1.5.0^2~11^2`) to our bundled copy of zstd 1.4.5. Fixes: #22754 --- Utilities/cmzstd/lib/common/mem.h | 4 +--- Utilities/cmzstd/lib/common/xxhash.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Utilities/cmzstd/lib/common/mem.h b/Utilities/cmzstd/lib/common/mem.h index 89c8aea7d22..c3f98fcd09a 100644 --- a/Utilities/cmzstd/lib/common/mem.h +++ b/Utilities/cmzstd/lib/common/mem.h @@ -173,9 +173,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); * Prefer these methods in priority order (0 > 1 > 2) */ #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define MEM_FORCE_MEMORY_ACCESS 2 -# elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__) +# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__) # define MEM_FORCE_MEMORY_ACCESS 1 # endif #endif diff --git a/Utilities/cmzstd/lib/common/xxhash.c b/Utilities/cmzstd/lib/common/xxhash.c index 597de18fc89..3d7655eba9c 100644 --- a/Utilities/cmzstd/lib/common/xxhash.c +++ b/Utilities/cmzstd/lib/common/xxhash.c @@ -30,9 +30,7 @@ * Prefer these methods in priority order (0 > 1 > 2) */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define XXH_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ +# if (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \ defined(__ICCARM__) # define XXH_FORCE_MEMORY_ACCESS 1 From 787ab7ff20ca74b57cfd3c18b0e92be1844ba244 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 12:36:51 -0400 Subject: [PATCH 1403/1519] IRSL: Fix discovery of VS 2022 v143 toolset redistributables for preview 5 VS 2022 Preview 5 renamed the redist directories from `Microsoft.VC142.*` to `Microsoft.VC143.*` in order to match the `v143` toolset name. Fixes: #22586 --- Modules/InstallRequiredSystemLibraries.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index 331623fa449..a2672784d23 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -225,7 +225,7 @@ if(MSVC) elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 144) message(WARNING "MSVC toolset v${MSVC_TOOLSET_VERSION} not yet supported.") elseif(MSVC_TOOLSET_VERSION EQUAL 143) - set(MSVC_REDIST_NAME VC142) + set(MSVC_REDIST_NAME VC143) set(_MSVC_DLL_VERSION 140) set(_MSVC_IDE_VERSION 17) elseif(MSVC_TOOLSET_VERSION EQUAL 142) From a8414190da56606ef103c04842598b0d303f8f4c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 13:38:44 -0400 Subject: [PATCH 1404/1519] VS: Update Visual Studio 17 2022 generator for Preview 5 --- Help/generator/Visual Studio 17 2022.rst | 4 ++-- Help/release/3.21.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index 708909ef91d..1f76d2fdb83 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -7,7 +7,7 @@ Generates Visual Studio 17 (VS 2022) project files. .. warning:: - This is experimental and based on "Visual Studio 2022 Preview 4". + This is experimental and based on "Visual Studio 2022 Preview 5". As of this version of CMake, VS 2022 has not been released. Project Types @@ -51,7 +51,7 @@ name (architecture). For example: Toolset Selection ^^^^^^^^^^^^^^^^^ -The ``v143`` toolset that comes with VS 17 2022 Preview 4 is selected by +The ``v143`` toolset that comes with VS 17 2022 Preview 5 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index a468817f0b7..2a676faf388 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -27,7 +27,7 @@ Generators ---------- * The :generator:`Visual Studio 17 2022` generator was added. This is - experimental and based on "Visual Studio 2022 Preview 4" because this + experimental and based on "Visual Studio 2022 Preview 5" because this version of VS has not been released. * The :ref:`Makefile Generators` and the :generator:`Ninja` generator From 6fde60a4c81b81f142cbad3e54f23c00fc963a5c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 14 Oct 2021 13:45:03 -0400 Subject: [PATCH 1405/1519] Help: Add 3.22 release note about the update for VS 2022 Preview 5 --- Help/release/3.22.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst index fcb655d196b..14b392916e8 100644 --- a/Help/release/3.22.rst +++ b/Help/release/3.22.rst @@ -142,3 +142,7 @@ Other Changes This became available as of VS 16.10 (toolchain version 14.29.30037). * The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. + +* The :generator:`Visual Studio 17 2022` generator was updated. This is + experimental and based on "Visual Studio 2022 Preview 5" because this + version of VS has not been released. From 40e73c5ac4849fdbeb58850bf93de7f2c581f26e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 15 Oct 2021 11:33:00 -0400 Subject: [PATCH 1406/1519] Source: Fix typo in _WIN32 preprocessor checks Since CMake's default compiler flags with MSVC include `-DWIN32` for historical reasons, a few preprocessor conditions were accidentally checking for `WIN32` instead of `_WIN32`. The corresponding blocks were left out when compiling official binaries for `cmake.org` because we hard-code compiler flags without `-DWIN32`. Fixes: #22764 --- Source/CPack/cmCPackDebGenerator.cxx | 2 +- Source/cmFileCopier.cxx | 2 +- Source/cmLocalNinjaGenerator.cxx | 2 +- Source/cmcmd.cxx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 560e5c1dc50..7515d3332bf 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -211,7 +211,7 @@ bool DebGenerator::generateDataTar() const cmCPackLogger(cmCPackLog::LOG_DEBUG, "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl); -#ifdef WIN32 +#ifdef _WIN32 std::string mode_t_adt_filename = file + ":cmake_mode_t"; cmsys::ifstream permissionStream(mode_t_adt_filename.c_str()); diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 48fc2868296..237d234f808 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -72,7 +72,7 @@ bool cmFileCopier::SetPermissions(const std::string& toFile, mode_t permissions) { if (permissions) { -#ifdef WIN32 +#ifdef _WIN32 if (Makefile->IsOn("CMAKE_CROSSCOMPILING")) { // Store the mode in an NTFS alternate stream. std::string mode_t_adt_filename = toFile + ":cmake_mode_t"; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index ad782ee3922..3540579311d 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -85,7 +85,7 @@ void cmLocalNinjaGenerator::Generate() cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(), "localized /showIncludes string"); this->GetRulesFileStream() << "msvc_deps_prefix = "; -#ifdef WIN32 +#ifdef _WIN32 // Ninja uses the ANSI Windows APIs, so strings in the rules file // typically need to be ANSI encoded. However, in this case the compiler // is being invoked using the UTF-8 codepage so the /showIncludes prefix diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index e2ff8b75358..613593a5b5d 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1334,7 +1334,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, cmSystemTools::Error("Problem extracting tar: " + outFile); return 1; } -#ifdef WIN32 +#ifdef _WIN32 // OK, on windows 7 after we untar some files, // sometimes we can not rename the directory after // the untar is done. This breaks the external project From 7123c8fdbfc8effd0b085e26cef982cc4cd88097 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Sun, 17 Oct 2021 20:18:00 +0300 Subject: [PATCH 1407/1519] CheckLanguage: Don't pass CMAKE_CUDA_HOST_COMPILER for Visual Studio Visual Studio doesn't support specifying it and if we do we get a warning. Fixes: #22712 --- Modules/CheckLanguage.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake index 559c103e8b7..52f707c002f 100644 --- a/Modules/CheckLanguage.cmake +++ b/Modules/CheckLanguage.cmake @@ -46,7 +46,7 @@ macro(check_language lang) file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}) set(extra_compiler_variables) - if(${lang} STREQUAL CUDA) + if(${lang} STREQUAL CUDA AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") set(extra_compiler_variables "set(CMAKE_CUDA_HOST_COMPILER \\\"\${CMAKE_CUDA_HOST_COMPILER}\\\")") endif() From ec9470679142605c95988bd34a6045d94d16d179 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Mon, 18 Oct 2021 11:49:40 -0400 Subject: [PATCH 1408/1519] Help: gen expr: note that CONFIG is comma-separated --- Help/manual/cmake-generator-expressions.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 5d508cb0dd7..62608e243e0 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -134,8 +134,8 @@ Variable Queries .. genex:: $<CONFIG:cfgs> - ``1`` if config is any one of the entries in ``cfgs``, else ``0``. This is a - case-insensitive comparison. The mapping in + ``1`` if config is any one of the entries in comma-separated list + ``cfgs``, else ``0``. This is a case-insensitive comparison. The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by this expression when it is evaluated on a property on an :prop_tgt:`IMPORTED` target. From 3d9d75b0bea439e3e9957733964668030e849dfe Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 19 Oct 2021 09:27:37 -0400 Subject: [PATCH 1409/1519] VS: Update Visual Studio 17 2022 generator for the Release Candidate --- Help/generator/Visual Studio 17 2022.rst | 4 ++-- Help/release/3.21.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index 1f76d2fdb83..eeff05eed74 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -7,7 +7,7 @@ Generates Visual Studio 17 (VS 2022) project files. .. warning:: - This is experimental and based on "Visual Studio 2022 Preview 5". + This is experimental and based on "Visual Studio 2022 Release Candidate". As of this version of CMake, VS 2022 has not been released. Project Types @@ -51,7 +51,7 @@ name (architecture). For example: Toolset Selection ^^^^^^^^^^^^^^^^^ -The ``v143`` toolset that comes with VS 17 2022 Preview 5 is selected by +The ``v143`` toolset that comes with VS 17 2022 Release Candidate is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 2a676faf388..4b0d68c0db2 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -27,8 +27,8 @@ Generators ---------- * The :generator:`Visual Studio 17 2022` generator was added. This is - experimental and based on "Visual Studio 2022 Preview 5" because this - version of VS has not been released. + experimental and based on "Visual Studio 2022 Release Candidate" because + this version of VS has not been released. * The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to add linker launcher tools along with the linker for ``C``, From f117c7d11eab19d6469ec03c43e24e2d1f2752ea Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 19 Oct 2021 09:37:05 -0400 Subject: [PATCH 1410/1519] Help: Update 3.22 release notes for the VS 2022 Release Candidate --- Help/release/3.22.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst index 14b392916e8..b65c0eaca45 100644 --- a/Help/release/3.22.rst +++ b/Help/release/3.22.rst @@ -144,5 +144,5 @@ Other Changes * The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. * The :generator:`Visual Studio 17 2022` generator was updated. This is - experimental and based on "Visual Studio 2022 Preview 5" because this - version of VS has not been released. + experimental and based on "Visual Studio 2022 Release Candidate" because + this version of VS has not been released. From 1560265e7d3af90fbdd991dc8fe35d918e907d7b Mon Sep 17 00:00:00 2001 From: Arcturus Arcturus <arcturus98@outlook.com> Date: Wed, 20 Oct 2021 16:58:00 +0100 Subject: [PATCH 1411/1519] Help: Fix file(INSTALL) docs w.r.t. CMAKE_INSTALL_MESSAGE In commit c9568de52c (install: Add CMAKE_INSTALL_MESSAGE variable (#13761), 2014-06-24, v3.1.0-rc1~370^2~1) we incorrectly documented that `CMAKE_INSTALL_MESSAGE` controls the status message for `file(INSTALL)`. Revert that. Fixes: #17162 --- Help/command/file.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/command/file.rst b/Help/command/file.rst index 5a3fd883bc1..799b6ff106f 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -838,8 +838,8 @@ of their content even if options are used to select a subset of files. The ``INSTALL`` signature differs slightly from ``COPY``: it prints -status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable), -and ``NO_SOURCE_PERMISSIONS`` is default. +status messages, and ``NO_SOURCE_PERMISSIONS`` is default. + Installation scripts generated by the :command:`install` command use this signature (with some undocumented options for internal use). From 6511654164dd483b4ff0c3eb5775d5fdb2c53564 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 11:56:42 -0400 Subject: [PATCH 1412/1519] cmGlobalVisualStudio10Generator: Allow subclasses to reset MSBuild search While at it, convert to inline initialization. --- Source/cmGlobalVisualStudio10Generator.cxx | 1 - Source/cmGlobalVisualStudio10Generator.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 488ff2e9c7a..499efbbf411 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -139,7 +139,6 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); this->CudaEnabled = false; - this->MSBuildCommandInitialized = false; { std::string envPlatformToolset; if (cmSystemTools::GetEnv("PlatformToolset", envPlatformToolset) && diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index b7ae1eecfd8..6c8e5f7e8c2 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -222,6 +222,7 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator bool SystemIsWindowsPhone = false; bool SystemIsWindowsStore = false; bool SystemIsAndroid = false; + bool MSBuildCommandInitialized = false; private: class Factory; @@ -243,7 +244,6 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator LongestSourcePath LongestSource; std::string MSBuildCommand; - bool MSBuildCommandInitialized; std::set<std::string> AndroidExecutableWarnings; virtual std::string FindMSBuildCommand(); std::string FindDevEnvCommand() override; From 8917b8512f20147b22ac8a7bf78245ab0162acaf Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 11:58:39 -0400 Subject: [PATCH 1413/1519] cmGlobalVisualStudioVersionedGenerator: Allow repeating SetGeneratorInstance --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 6 ++++++ Source/cmGlobalVisualStudioVersionedGenerator.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 3ecf32e2451..b6219a69580 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -436,6 +436,9 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( std::string const& i, cmMakefile* mf) { + if (this->GeneratorInstance && i == *(this->GeneratorInstance)) { + return true; + } if (!i.empty()) { if (!this->vsSetupAPIHelper.SetVSInstance(i)) { std::ostringstream e; @@ -472,6 +475,9 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( cmStateEnums::INTERNAL); } + // The selected instance may have a different MSBuild than previously found. + this->MSBuildCommandInitialized = false; + return true; } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index f07492dff52..691651fe2c0 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -8,6 +8,8 @@ #include <memory> #include <string> +#include <cm/optional> + #include "cmGlobalVisualStudio14Generator.h" #include "cmVSSetupHelper.h" @@ -72,4 +74,5 @@ class cmGlobalVisualStudioVersionedGenerator class Factory17; friend class Factory17; mutable cmVSSetupAPIHelper vsSetupAPIHelper; + cm::optional<std::string> GeneratorInstance; }; From 7f730464be485862ba89c85248306c893117a595 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 11:59:44 -0400 Subject: [PATCH 1414/1519] cmGlobalGenerator: Add method to check if generator is at least VS 10 --- Source/cmGlobalGenerator.h | 2 ++ Source/cmGlobalVisualStudio10Generator.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 23c5700de31..074da4ed12a 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -444,6 +444,8 @@ class cmGlobalGenerator virtual bool IsVisualStudio() const { return false; } + virtual bool IsVisualStudioAtLeast10() const { return false; } + virtual bool IsNinja() const { return false; } /** Return true if we know the exact location of object files. diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 6c8e5f7e8c2..a5ee284465a 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -20,6 +20,8 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator public: static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); + bool IsVisualStudioAtLeast10() const override { return true; } + bool MatchesGeneratorName(const std::string& name) const override; bool SetSystemName(std::string const& s, cmMakefile* mf) override; From 6999b871335c26d9d39b05023559254b1437bcf5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 12:01:53 -0400 Subject: [PATCH 1415/1519] cmGlobalVisualStudio10Generator: Add method to find MSBuild early Add a way to find MSBuild before the main `FindMakeProgram` code path has executed. --- Source/cmGlobalVisualStudio10Generator.cxx | 6 ++++++ Source/cmGlobalVisualStudio10Generator.h | 2 ++ Source/cmGlobalVisualStudioVersionedGenerator.cxx | 11 +++++++++++ Source/cmGlobalVisualStudioVersionedGenerator.h | 2 ++ 4 files changed, 21 insertions(+) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 499efbbf411..c11516ddb52 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -856,6 +856,12 @@ std::string const& cmGlobalVisualStudio10Generator::GetMSBuildCommand() return this->MSBuildCommand; } +cm::optional<std::string> +cmGlobalVisualStudio10Generator::FindMSBuildCommandEarly(cmMakefile*) +{ + return this->GetMSBuildCommand(); +} + std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand() { std::string msbuild; diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index a5ee284465a..6e6239065b8 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -134,6 +134,8 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; } + virtual cm::optional<std::string> FindMSBuildCommandEarly(cmMakefile* mf); + bool FindMakeProgram(cmMakefile* mf) override; bool IsIPOSupported() const override { return true; } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index b6219a69580..ec2e74fd935 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -718,6 +718,17 @@ cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersionDefault( return std::string(); } +cm::optional<std::string> +cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommandEarly(cmMakefile* mf) +{ + std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); + if (!this->SetGeneratorInstance(instance, mf)) { + cmSystemTools::SetFatalErrorOccured(); + return {}; + } + return this->cmGlobalVisualStudio14Generator::FindMSBuildCommandEarly(mf); +} + std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() { std::string msbuild; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 691651fe2c0..b7760ac72b8 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -31,6 +31,8 @@ class cmGlobalVisualStudioVersionedGenerator bool GetVSInstance(std::string& dir) const; + cm::optional<std::string> FindMSBuildCommandEarly(cmMakefile* mf) override; + cm::optional<std::string> GetVSInstanceVersion() const override; AuxToolset FindAuxToolset(std::string& version, From 44a86d0b3890848e2df702dc87d625a19216641e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 12:05:24 -0400 Subject: [PATCH 1416/1519] cmake_host_system_information: Add undocumented VS_MSBUILD_COMMAND key When using the Visual Studio generator for VS 10 or above, offer this key to get the location of the MSBuild command before the first `project()` or `enable_language()` command has finished running. This will be needed only by one of our own modules, so leave it undocumented for now. --- Source/cmCMakeHostSystemInformationCommand.cxx | 7 +++++++ .../cmake_host_system_information/RunCMakeTest.cmake | 6 ++++++ .../RunCMake/cmake_host_system_information/VsMSBuild.cmake | 4 ++++ .../VsMSBuildMissing-result.txt | 1 + .../VsMSBuildMissing-stderr.txt | 4 ++++ .../cmake_host_system_information/VsMSBuildMissing.cmake | 1 + 6 files changed, 23 insertions(+) create mode 100644 Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake create mode 100644 Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 74071ff4f29..3922c565aeb 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -27,6 +27,7 @@ #ifdef _WIN32 # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" +# include "cmGlobalVisualStudio10Generator.h" # include "cmGlobalVisualStudioVersionedGenerator.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER @@ -434,6 +435,12 @@ cm::optional<std::string> GetValue(cmExecutionStatus& status, } } + if (key == "VS_MSBUILD_COMMAND"_s && gg->IsVisualStudioAtLeast10()) { + cmGlobalVisualStudio10Generator* vs10gen = + static_cast<cmGlobalVisualStudio10Generator*>(gg); + return vs10gen->FindMSBuildCommandEarly(&status.GetMakefile()); + } + return {}; } #endif diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index 189013f84f6..87b6944dcbc 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -15,3 +15,9 @@ run_cmake(CentOS6) run_cmake(Debian6) run_cmake(UserFallbackScript) + +if(RunCMake_GENERATOR MATCHES "^Visual Studio " AND NOT RunCMake_GENERATOR STREQUAL "Visual Studio 9 2008") + run_cmake(VsMSBuild) +else() + run_cmake(VsMSBuildMissing) +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake b/Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake new file mode 100644 index 00000000000..30e616eb067 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake @@ -0,0 +1,4 @@ +cmake_host_system_information(RESULT msbuild QUERY VS_MSBUILD_COMMAND) +if(NOT EXISTS "${msbuild}") + message(FATAL_ERROR "VS_MSBUILD_COMMAND returned path that does not exist:\n ${msbuild}") +endif() diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt new file mode 100644 index 00000000000..3a7dfef6da4 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at VsMSBuildMissing.cmake:[0-9]+ \(cmake_host_system_information\): + cmake_host_system_information does not recognize <key> VS_MSBUILD_COMMAND +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake new file mode 100644 index 00000000000..23c03642965 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT msbuild QUERY VS_MSBUILD_COMMAND) From 42418b02f769858d68ce21a58dab3025d30f31a2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 12:07:59 -0400 Subject: [PATCH 1417/1519] Android: Refactor sysroot detection under Visual Studio Since commit 6051a49c78 (Visual Studio: Add Android support, 2020-06-12, v3.19.0-rc1~619^2) we run MSBuild to build a sample project to detect the sysroot. Previously we relied on `CMAKE_VS_MSBUILD_COMMAND` being available. That required commit d5b5c19278 (cmGlobalGenerator: FindMakeProgram() before CMakeDetermineSystem, 2020-06-15, v3.19.0-rc1~619^2~3) to make it available early enough. However, that ordering broke `CMAKE_GENERATOR_INSTANCE` so we need to prepare to revert it. Use `cmake_host_system_information` to get the location of MSBuild under a VS generator instead. --- Modules/Platform/Android-Determine.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index 7b67f839ecc..a4e9574955d 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -52,14 +52,16 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio") endif() configure_file(${CMAKE_ROOT}/Modules/Platform/Android/VCXProjInspect.vcxproj.in ${CMAKE_PLATFORM_INFO_DIR}/VCXProjInspect.vcxproj @ONLY) + cmake_host_system_information(RESULT _msbuild QUERY VS_MSBUILD_COMMAND) # undocumented query execute_process( - COMMAND "${CMAKE_VS_MSBUILD_COMMAND}" "VCXProjInspect.vcxproj" + COMMAND "${_msbuild}" "VCXProjInspect.vcxproj" "/p:Configuration=Debug" "/p:Platform=${vcx_platform}" WORKING_DIRECTORY ${CMAKE_PLATFORM_INFO_DIR} OUTPUT_VARIABLE VCXPROJ_INSPECT_OUTPUT ERROR_VARIABLE VCXPROJ_INSPECT_OUTPUT RESULT_VARIABLE VCXPROJ_INSPECT_RESULT ) + unset(_msbuild) if(NOT CMAKE_SYSROOT AND VCXPROJ_INSPECT_OUTPUT MATCHES "CMAKE_SYSROOT=([^%\r\n]+)[\r\n]") # Strip VS diagnostic output from the end of the line. string(REGEX REPLACE " \\(TaskId:[0-9]*\\)$" "" _sysroot "${CMAKE_MATCH_1}") From 46e9ff57298b58b3a4669adcb913429b691ce5bb Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 20 Oct 2021 12:12:35 -0400 Subject: [PATCH 1418/1519] Restore honoring CMAKE_GENERATOR_INSTANCE in toolchain file Revert the changes from commit d5b5c19278 (cmGlobalGenerator: FindMakeProgram() before CMakeDetermineSystem, 2020-06-15, v3.19.0-rc1~619^2~3) and commit ef91fb02f3 (cmGlobalGenerator: FindMakeProgram() at a generator-specific time, 2020-11-23, v3.19.1~2^2). We must delay selecting the location of MSBuild until after an instance of Visual Studio has been selected. It is now safe to revert the ordering because the motivating use case (sysroot detection in Platform/Android-Determine) has been implemented another way. Fixes: #22782 --- Source/cmGlobalGenerator.cxx | 13 +------------ Source/cmGlobalGenerator.h | 11 ----------- Source/cmGlobalVisualStudioGenerator.h | 5 ----- Source/cmGlobalXCodeGenerator.h | 5 ----- 4 files changed, 1 insertion(+), 33 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 6dabf63744f..ac283ab4a1c 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -593,16 +593,6 @@ void cmGlobalGenerator::EnableLanguage( } } - if (readCMakeSystem) { - // Find the native build tool for this generator. - // This has to be done early so that MSBuild can be used to examine the - // cross-compilation environment. - if (this->GetFindMakeProgramStage() == FindMakeProgramStage::Early && - !this->FindMakeProgram(mf)) { - return; - } - } - // Load the CMakeDetermineSystem.cmake file and find out // what platform we are running on if (!mf->GetDefinition("CMAKE_SYSTEM")) { @@ -676,8 +666,7 @@ void cmGlobalGenerator::EnableLanguage( } // Find the native build tool for this generator. - if (this->GetFindMakeProgramStage() == FindMakeProgramStage::Late && - !this->FindMakeProgram(mf)) { + if (!this->FindMakeProgram(mf)) { return; } } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 074da4ed12a..cc0ad29d27d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -625,17 +625,6 @@ class cmGlobalGenerator std::string GetPredefinedTargetsFolder() const; - enum class FindMakeProgramStage - { - Early, - Late, - }; - - virtual FindMakeProgramStage GetFindMakeProgramStage() const - { - return FindMakeProgramStage::Late; - } - private: using TargetMap = std::unordered_map<std::string, cmTarget*>; using GeneratorTargetMap = diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index d1bd6b118d5..23c8a029081 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -167,11 +167,6 @@ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator void WriteSLNHeader(std::ostream& fout); - FindMakeProgramStage GetFindMakeProgramStage() const override - { - return FindMakeProgramStage::Early; - } - bool ComputeTargetDepends() override; class VSDependSet : public std::set<std::string> { diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 72af4a40adc..4d7ee9010bb 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -138,11 +138,6 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator void AddExtraIDETargets() override; void Generate() override; - FindMakeProgramStage GetFindMakeProgramStage() const override - { - return FindMakeProgramStage::Early; - } - private: enum EmbedActionFlags { From 5dd981539f6b81ad5697df974f309d9a6d4e78c6 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 22 Oct 2021 09:14:51 -0400 Subject: [PATCH 1419/1519] BinUtils: Avoid llvm-strip versions older than Clang 11 Since commit cf82300a63 (BinUtils: Clarify search logic and make it more consistent, 2021-05-27, v3.21.0-rc1~119^2~2) we correctly prefer the more-specific name `llvm-strip` over `strip` when using Clang. However, `llvm-strip` from Clang versions prior to 11 require extra flags to strip everything. Until our `install(TARGETS)` logic learns to add those flags, avoid using older versions of `llvm-strip` by default. Fixes: #22785 --- Modules/CMakeFindBinUtils.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 27d9131c837..8e9237a870d 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -174,7 +174,10 @@ else() endif() list(PREPEND _CMAKE_AR_NAMES "llvm-ar") list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") - list(PREPEND _CMAKE_STRIP_NAMES "llvm-strip") + if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}" VERSION_GREATER_EQUAL 11) + # llvm-strip versions prior to 11 require additional flags we do not yet add. + list(PREPEND _CMAKE_STRIP_NAMES "llvm-strip") + endif() list(PREPEND _CMAKE_NM_NAMES "llvm-nm") if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}" VERSION_GREATER_EQUAL 9) # llvm-objdump versions prior to 9 did not support everything we need. From f6177f05dacfa8ce790c65812a6a3528969c0291 Mon Sep 17 00:00:00 2001 From: Michael Hirsch <scivision@users.noreply.gitlab.kitware.com> Date: Sun, 24 Oct 2021 16:01:07 -0400 Subject: [PATCH 1420/1519] Help: Clarify ENVIRONMENT_MODIFICATION case sensitivity --- Help/prop_test/ENVIRONMENT_MODIFICATION.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst index 00312100cf2..0b3cd83a4a1 100644 --- a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst +++ b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst @@ -8,8 +8,9 @@ that the operations performed by this property are performed after the :prop_test:`ENVIRONMENT` property is already applied. If set to a list of environment variables and values of the form -``MYVAR=OP:VALUE``. Entries are considered in the order specified in the -property's value. The ``OP`` may be one of: +``MYVAR=OP:VALUE``, where ``MYVAR`` is the case-sensitive name of an +environment variable to be modified. Entries are considered in the +order specified in the property's value. The ``OP`` may be one of: - ``reset``: Reset to the unmodified value, ignoring all modifications to ``MYVAR`` prior to this entry. Note that this will reset the variable to From 3d0e2775a554f33d4d0583f232d33057a4d8076c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 26 Oct 2021 10:47:58 -0400 Subject: [PATCH 1421/1519] HIP: Add missing space when appending --cuda-host-only Fixes: #22805 --- Modules/CMakeTestHIPCompiler.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake index 5acd8062404..ecbfa7fc287 100644 --- a/Modules/CMakeTestHIPCompiler.cmake +++ b/Modules/CMakeTestHIPCompiler.cmake @@ -10,7 +10,7 @@ if(CMAKE_HIP_COMPILER_FORCED) endif() set(__CMAKE_HIP_FLAGS "${CMAKE_HIP_FLAGS}") -string(APPEND CMAKE_HIP_FLAGS "--cuda-host-only") +string(APPEND CMAKE_HIP_FLAGS " --cuda-host-only") include(CMakeTestCompilerCommon) From 69f95cf1d93945ace09ee9a87c0185b1ee6e4a47 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Tue, 26 Oct 2021 12:51:44 -0400 Subject: [PATCH 1422/1519] cmCTestRunTest: fix modifying non-existent envvars When appending or modifying to a variable that has not been modified before, the iterator was not valid, but it was used to insert into the map again. Instead, just use indexing into the map since we know it will exist by the end of the function anyways. Fixes: #22796 --- Source/CTest/cmCTestRunTest.cxx | 8 ++------ Tests/Environment/CMakeLists.txt | 18 ++++++++++++++++++ Tests/Environment/check_mod.cmake | 8 +++++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 20f0ed3884c..2d1562a0cfc 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -800,13 +800,9 @@ bool cmCTestRunTest::ForkProcess( auto apply_diff = [&env_application](const std::string& name, std::function<void(std::string&)> const& apply) { - auto entry = env_application.find(name); - std::string output; - if (entry != env_application.end() && entry->second) { - output = *entry->second; - } + std::string output = env_application[name].value_or(std::string{}); apply(output); - entry->second = output; + env_application[name] = output; }; bool err_occurred = false; diff --git a/Tests/Environment/CMakeLists.txt b/Tests/Environment/CMakeLists.txt index 17009bd838c..5f1edbffa8c 100644 --- a/Tests/Environment/CMakeLists.txt +++ b/Tests/Environment/CMakeLists.txt @@ -45,6 +45,12 @@ set_property(TEST EchoEnvironment3 "STRING_MANIP=string_append:suffix" "STRING_MANIP=string_prepend:prefix" + # String manipulation on non-existent. + "STRING_DNE=string_append:post-" + "STRING_DNE=string_prepend:-pre" + "STRING_DNE=string_append:suffix" + "STRING_DNE=string_prepend:prefix" + # Path manipulation. "PATH_MANIP=set:core" "PATH_MANIP=path_list_append:post" @@ -52,10 +58,22 @@ set_property(TEST EchoEnvironment3 "PATH_MANIP=path_list_append:suffix" "PATH_MANIP=path_list_prepend:prefix" + # Path manipulation on non-existent. + "PATH_DNE=path_list_append:post" + "PATH_DNE=path_list_prepend:pre" + "PATH_DNE=path_list_append:suffix" + "PATH_DNE=path_list_prepend:prefix" + # CMake list manipulation. "CMAKE_LIST_MANIP=set:core" "CMAKE_LIST_MANIP=cmake_list_append:post" "CMAKE_LIST_MANIP=cmake_list_prepend:pre" "CMAKE_LIST_MANIP=cmake_list_append:suffix" "CMAKE_LIST_MANIP=cmake_list_prepend:prefix" + + # CMake list manipulation on non-existent. + "CMAKE_LIST_DNE=cmake_list_append:post" + "CMAKE_LIST_DNE=cmake_list_prepend:pre" + "CMAKE_LIST_DNE=cmake_list_append:suffix" + "CMAKE_LIST_DNE=cmake_list_prepend:prefix" ) diff --git a/Tests/Environment/check_mod.cmake b/Tests/Environment/check_mod.cmake index 16d02f26a95..179bd7a237a 100644 --- a/Tests/Environment/check_mod.cmake +++ b/Tests/Environment/check_mod.cmake @@ -20,12 +20,18 @@ set(expect_DIRECT "new") set(expect_STRING_MANIP "prefix-pre-core-post-suffix") set(expect_PATH_MANIP "prefix${path_sep}pre${path_sep}core${path_sep}post${path_sep}suffix") set(expect_CMAKE_LIST_MANIP "prefix;pre;core;post;suffix") +set(expect_STRING_DNE "prefix-prepost-suffix") +set(expect_PATH_DNE "prefix${path_sep}pre${path_sep}post${path_sep}suffix") +set(expect_CMAKE_LIST_DNE "prefix;pre;post;suffix") set(expected_vars DIRECT STRING_MANIP PATH_MANIP - CMAKE_LIST_MANIP) + CMAKE_LIST_MANIP + STRING_DNE + PATH_DNE + CMAKE_LIST_DNE) while (out) string(FIND "${out}" "\n" nl_pos) From 9eaf0932af0cd7881c712fbe4586ec59cb9e0d10 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 26 Oct 2021 13:45:51 -0400 Subject: [PATCH 1423/1519] cmGlobalVisualStudioVersionedGenerator: Fix repeating SetGeneratorInstance Fix logic added by commit 8917b8512f (cmGlobalVisualStudioVersionedGenerator: Allow repeating SetGeneratorInstance, 2021-10-20) to avoid repeating work. --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 6 +++++- Source/cmGlobalVisualStudioVersionedGenerator.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index ec2e74fd935..f27b2c47d3a 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -436,9 +436,11 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( std::string const& i, cmMakefile* mf) { - if (this->GeneratorInstance && i == *(this->GeneratorInstance)) { + if (this->LastGeneratorInstanceString && + i == *(this->LastGeneratorInstanceString)) { return true; } + if (!i.empty()) { if (!this->vsSetupAPIHelper.SetVSInstance(i)) { std::ostringstream e; @@ -478,6 +480,8 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( // The selected instance may have a different MSBuild than previously found. this->MSBuildCommandInitialized = false; + this->LastGeneratorInstanceString = i; + return true; } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index b7760ac72b8..2aed65b87fc 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -76,5 +76,5 @@ class cmGlobalVisualStudioVersionedGenerator class Factory17; friend class Factory17; mutable cmVSSetupAPIHelper vsSetupAPIHelper; - cm::optional<std::string> GeneratorInstance; + cm::optional<std::string> LastGeneratorInstanceString; }; From f3ddc526765b39c75bd3d2086ec8016b47c2f36c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 26 Oct 2021 13:06:57 -0400 Subject: [PATCH 1424/1519] VS: Update Visual Studio 17 2022 generator for the Release Candidates Assume this is close enough to the final release to treat as non-experimental support. --- Help/generator/Visual Studio 17 2022.rst | 9 ++------- Help/release/3.21.rst | 11 ++++++++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index eeff05eed74..b3f49f3dfad 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -5,11 +5,6 @@ Visual Studio 17 2022 Generates Visual Studio 17 (VS 2022) project files. -.. warning:: - - This is experimental and based on "Visual Studio 2022 Release Candidate". - As of this version of CMake, VS 2022 has not been released. - Project Types ^^^^^^^^^^^^^ @@ -51,8 +46,8 @@ name (architecture). For example: Toolset Selection ^^^^^^^^^^^^^^^^^ -The ``v143`` toolset that comes with VS 17 2022 Release Candidate is selected by -default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps +The ``v143`` toolset that comes with VS 17 2022 is selected by default. +The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 4b0d68c0db2..e1c6172b2a4 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -26,9 +26,7 @@ Presets Generators ---------- -* The :generator:`Visual Studio 17 2022` generator was added. This is - experimental and based on "Visual Studio 2022 Release Candidate" because - this version of VS has not been released. +* The :generator:`Visual Studio 17 2022` generator was added. * The :ref:`Makefile Generators` and the :generator:`Ninja` generator learned to add linker launcher tools along with the linker for ``C``, @@ -329,3 +327,10 @@ Changes made since CMake 3.21.0 include the following. * ``hipcc`` may once again be used as a ``CXX`` compiler, and is treated as whatever compiler it selects underneath, as CMake 3.20 and below did. + +3.21.4 +------ + +* The :generator:`Visual Studio 17 2022` generator is now based on the + "Visual Studio 2022" release candidates. Previously it was based on + preview versions. From 8b64fc7dbb4cfd348425453b42fd54f15754ee83 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 26 Oct 2021 13:10:32 -0400 Subject: [PATCH 1425/1519] Help: Drop 3.22 release note for VS 2022 The 3.21.4 release will have full support, so it is not new to the 3.22 series anymore. --- Help/release/3.22.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst index b65c0eaca45..fcb655d196b 100644 --- a/Help/release/3.22.rst +++ b/Help/release/3.22.rst @@ -142,7 +142,3 @@ Other Changes This became available as of VS 16.10 (toolchain version 14.29.30037). * The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later. - -* The :generator:`Visual Studio 17 2022` generator was updated. This is - experimental and based on "Visual Studio 2022 Release Candidate" because - this version of VS has not been released. From 054754359a0b6b5721dea722b7920c954a573451 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Tue, 26 Oct 2021 17:15:46 -0400 Subject: [PATCH 1426/1519] cmRST: support `versionadded` and `versionchanged` directives This makes `versionadded` and `versionchanged` directives show up in `cmake --help-*` output instead of disappearing (and potentially making empty sections). Fixes: #22808 --- Help/dev/documentation.rst | 5 +++++ Source/cmRST.cxx | 5 +++++ Source/cmRST.h | 1 + Tests/CMakeLib/testRST.expect | 6 ++++++ Tests/CMakeLib/testRST.rst | 6 ++++++ 5 files changed, 23 insertions(+) diff --git a/Help/dev/documentation.rst b/Help/dev/documentation.rst index 29fc8803314..4a2a5d963af 100644 --- a/Help/dev/documentation.rst +++ b/Help/dev/documentation.rst @@ -92,6 +92,11 @@ literal block after ``::`` the referenced documents inline as part of the referencing document. +``versionadded``, ``versionchanged`` directives + Specify that something was added or changed by a named CMake version. + The command-line help processor prints the block content as if the lines + were normal paragraph text with interpretation. + Inline markup constructs not listed above are printed literally in the command-line help output. We prefer to use inline markup constructs that look correct in source form, so avoid use of \\-escapes in favor of inline diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index fce6e80bf10..1e4dedde368 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -35,6 +35,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot) , TocTreeDirective("^.. toctree::[ \t]*(.*)$") , ProductionListDirective("^.. productionlist::[ \t]*(.*)$") , NoteDirective("^.. note::[ \t]*(.*)$") + , VersionDirective("^.. version(added|changed)::[ \t]*(.*)$") , ModuleRST(R"(^#\[(=*)\[\.rst:$)") , CMakeRole("(:cmake)?:(" "command|cpack_gen|generator|genex|" @@ -209,6 +210,10 @@ void cmRST::ProcessLine(std::string const& line) } else if (this->NoteDirective.find(line)) { // Output note directives and their content normally. this->NormalLine(line); + } else if (this->VersionDirective.find(line)) { + // Output versionadded and versionchanged directives and their content + // normally. + this->NormalLine(line); } } // An explicit markup start followed nothing but whitespace and a diff --git a/Source/cmRST.h b/Source/cmRST.h index 17cdfe896eb..156b20a1bad 100644 --- a/Source/cmRST.h +++ b/Source/cmRST.h @@ -83,6 +83,7 @@ class cmRST cmsys::RegularExpression TocTreeDirective; cmsys::RegularExpression ProductionListDirective; cmsys::RegularExpression NoteDirective; + cmsys::RegularExpression VersionDirective; cmsys::RegularExpression ModuleRST; cmsys::RegularExpression CMakeRole; cmsys::RegularExpression InlineLink; diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect index 4870f658a73..5e3cdb10450 100644 --- a/Tests/CMakeLib/testRST.expect +++ b/Tests/CMakeLib/testRST.expect @@ -116,6 +116,12 @@ A literal block can be empty:: .. note:: Notes are called out. +.. versionadded:: 1.2 + Version blocks are preserved. + +.. versionchanged:: 2.3 + Version blocks are preserved. + substituted text with multiple lines becomes one line End of first include. diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst index 44931a756b2..4139801833e 100644 --- a/Tests/CMakeLib/testRST.rst +++ b/Tests/CMakeLib/testRST.rst @@ -123,6 +123,12 @@ A literal block can be empty:: .. note:: Notes are called out. +.. versionadded:: 1.2 + Version blocks are preserved. + +.. versionchanged:: 2.3 + Version blocks are preserved. + .. |substitution| replace:: |nested substitution| with multiple lines becomes one line From f65cebf51a2cf3af2017fd9b03c685c77da00c74 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 27 Oct 2021 09:51:39 -0400 Subject: [PATCH 1427/1519] CMake 3.21.4 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 264cb9cd2ea..1becd8a3ee9 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 3) +set(CMake_VERSION_PATCH 4) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From ada9855b781fceebe2f97fcc1a8509130bbc984e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 27 Oct 2021 12:45:12 -0400 Subject: [PATCH 1428/1519] gitlab-ci: Run manual jobs automatically only on scheduled pipelines Previously we ran manual jobs automatically in the `cmake/cmake` project integration branches. Change this to happen only when the pipeline is created by a schedule. Also, start automatic jobs in scheduled pipelines without delay. --- .gitlab/rules.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitlab/rules.yml b/.gitlab/rules.yml index 4846fea7648..a871b8f6f28 100644 --- a/.gitlab/rules.yml +++ b/.gitlab/rules.yml @@ -15,9 +15,10 @@ when: never - if: '$CI_MERGE_REQUEST_ID' when: manual + - if: '$CI_PROJECT_PATH == "cmake/cmake" && $CI_PIPELINE_SOURCE == "schedule"' + when: on_success - if: '$CI_PROJECT_PATH == "cmake/cmake"' - when: delayed - start_in: 5 minutes + when: manual - when: never .run_automatically: @@ -34,6 +35,8 @@ when: never - if: '$CI_MERGE_REQUEST_ID' when: on_success + - if: '$CI_PROJECT_PATH == "cmake/cmake" && $CI_PIPELINE_SOURCE == "schedule"' + when: on_success - if: '$CI_PROJECT_PATH == "cmake/cmake"' when: delayed start_in: 5 minutes From 51a2afe6e7b26052219afb2b9eb8bc6e0c89eefc Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" <erlend.aasland@innova.no> Date: Wed, 27 Oct 2021 20:17:02 +0200 Subject: [PATCH 1429/1519] CPack/IFW: Add support for QtIFW 4.2 --- Modules/CPackIFW.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index 2e68770a54d..85108db4110 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -439,6 +439,7 @@ set(_CPACK_IFW_PREFIXES "QtIFW-") set(_CPACK_IFW_VERSIONS + "4.2" "4.1" "4.0" "3.2" From 28a033cc7de056d1a74857606397bb294ebe27ac Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 28 Oct 2021 09:46:08 -0400 Subject: [PATCH 1430/1519] CMake 3.22.0-rc2 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0c01b0039ad..85791c224fe 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 22) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 1) +set(CMake_VERSION_RC 2) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From 22f804e0ec1f827a11396394206e2cd5834e5522 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 28 Oct 2021 12:10:33 -0400 Subject: [PATCH 1431/1519] MSVC: Refactor C compile features table for C90, C99, and C11 The custom "no modes" `cmake_record_c_compile_features` implementation should only be used in `cl` versions prior to 19.27 because they had no `-std:c*` flags for C standards. For 19.27 we need a different custom implementation to account for partial C11 support. For 19.28 and above we can use the default implementation through the `*__HAS_FULL_SUPPORT` settings. We already use this pattern in the MSVC C++ compile feature table. --- Modules/Compiler/MSVC-C.cmake | 64 +++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index 4ba1eea3f5e..aca79952c2e 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -11,6 +11,20 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27) set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std:c11") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std:c11") + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28) + set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) + else() + # Special case for 19.27 (VS 16.7): C11 has partial support. + macro(cmake_record_c_compile_features) + _has_compiler_features_c(90) + _has_compiler_features_c(99) + list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11) + set(_result 0) # expected by cmake_determine_compile_features + endmacro() + endif() + __compiler_check_default_language_standard(C 19.27 99) else() # MSVC has no specific options to set C language standards, but set them as @@ -25,41 +39,33 @@ else() # There is no meaningful default for this set(CMAKE_C_STANDARD_DEFAULT "") + + # There are no C compiler modes so we hard-code the known compiler supported + # features. Override the default macro for this special case. Pretend that + # all language standards are available so that at least compilation + # can be attempted. + macro(cmake_record_c_compile_features) + list(APPEND CMAKE_C_COMPILE_FEATURES + c_std_90 + c_std_99 + c_std_11 + c_function_prototypes + ) + list(APPEND CMAKE_C90_COMPILE_FEATURES c_std_90 c_function_prototypes) + list(APPEND CMAKE_C99_COMPILE_FEATURES c_std_99) + list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11) + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0) + list(APPEND CMAKE_C_COMPILE_FEATURES c_variadic_macros) + list(APPEND CMAKE_C99_COMPILE_FEATURES c_variadic_macros) + endif() + set(_result 0) # expected by cmake_determine_compile_features + endmacro() endif() set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") -# There are no C compiler modes so we hard-code the known compiler supported -# features. Override the default macro for this special case. Pretend that -# all language standards are available so that at least compilation -# can be attempted. -macro(cmake_record_c_compile_features) - list(APPEND CMAKE_C_COMPILE_FEATURES - c_std_90 - c_std_99 - c_std_11 - c_function_prototypes - ) - list(APPEND CMAKE_C90_COMPILE_FEATURES c_std_90 c_function_prototypes) - list(APPEND CMAKE_C99_COMPILE_FEATURES c_std_99) - list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11) - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0) - list(APPEND CMAKE_C_COMPILE_FEATURES c_variadic_macros) - list(APPEND CMAKE_C99_COMPILE_FEATURES c_variadic_macros) - endif() - if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27) - list(APPEND CMAKE_C_COMPILE_FEATURES c_restrict) - list(APPEND CMAKE_C99_COMPILE_FEATURES c_restrict) - endif() - if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28) - list(APPEND CMAKE_C_COMPILE_FEATURES c_static_assert) - list(APPEND CMAKE_C11_COMPILE_FEATURES c_static_assert) - endif() - set(_result 0) # expected by cmake_determine_compile_features -endmacro() - # /JMC "Just My Code" is only supported by MSVC 19.05 onward. if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) set(CMAKE_C_COMPILE_OPTIONS_JMC "-JMC") From 6561b032bc995a248bc065690f0af6d98288ecea Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 28 Oct 2021 12:18:42 -0400 Subject: [PATCH 1432/1519] MSVC: Tolerate c_std_17 and c_std_23 features on older compiler versions MSVC `cl` versions prior to 19.27 had no `-std:c*` flags for C standards. List the `c_std_{17,23}` features anyway. This allows projects to at least attempt compilation with these compilers since they do not have any modes. --- Modules/Compiler/MSVC-C.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index aca79952c2e..8da0cedd15b 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -49,6 +49,8 @@ else() c_std_90 c_std_99 c_std_11 + c_std_17 + c_std_23 c_function_prototypes ) list(APPEND CMAKE_C90_COMPILE_FEATURES c_std_90 c_function_prototypes) From c5cc4ddac4dfc376844a210b4cd25a01565b024d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 28 Oct 2021 12:21:13 -0400 Subject: [PATCH 1433/1519] MSVC: Add support for C17 C17 support has been available in MSVC since VS 16.8. Fixes: #22816 --- Modules/Compiler/MSVC-C.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index 8da0cedd15b..a53df46648e 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -15,6 +15,8 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27) set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) + set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std:c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std:c17") else() # Special case for 19.27 (VS 16.7): C11 has partial support. macro(cmake_record_c_compile_features) From fa47e9c8f9082f5c75b56e1f8069509f898c9a25 Mon Sep 17 00:00:00 2001 From: Marc Aldorasi <marc@groundctl.com> Date: Wed, 27 Oct 2021 16:46:40 -0400 Subject: [PATCH 1434/1519] Help: Document that configure_file can create directories --- Help/command/configure_file.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst index 086668c16ba..1d814235156 100644 --- a/Help/command/configure_file.rst +++ b/Help/command/configure_file.rst @@ -96,6 +96,7 @@ The arguments are: with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`. If the path names an existing directory the output file is placed in that directory with the same file name as the input file. + If the path contains non-existent directories, they are created. ``NO_SOURCE_PERMISSIONS`` .. versionadded:: 3.19 From 0ad79f7ba840ae08fb67583d51f4ca5aa8d665c2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 29 Oct 2021 09:47:01 -0400 Subject: [PATCH 1435/1519] Help: Fix versionadded for VS 15 2017 instance selection Support for `CMAKE_GENERATOR_INSTANCE` was added in CMake 3.11, but the possibility was mentioned in a comment in older versions, so the wrong versionadded value was used in commit c43e845d09 (Help: Add `.. versionadded` directives to generator docs, 2020-11-11, v3.20.0-rc1~476^2). --- Help/generator/Visual Studio 15 2017.rst | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst index a4f5f98e3cd..b4d6f6d9f68 100644 --- a/Help/generator/Visual Studio 15 2017.rst +++ b/Help/generator/Visual Studio 15 2017.rst @@ -15,20 +15,20 @@ Powershell, Python, etc.) are not supported. Instance Selection ^^^^^^^^^^^^^^^^^^ -.. versionadded:: 3.9 - VS 2017 supports multiple installations on the same machine. - The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a - cache entry containing the absolute path to a Visual Studio instance. - If the value is not specified explicitly by the user or a toolchain file, - CMake queries the Visual Studio Installer to locate VS instances, chooses - one, and sets the variable as a cache entry to hold the value persistently. - .. versionadded:: 3.11 - When CMake first chooses an instance, if the ``VS150COMNTOOLS`` environment - variable is set and points to the ``Common7/Tools`` directory within - one of the instances, that instance will be used. Otherwise, if more - than one instance is installed we do not define which one is chosen - by default. + +VS 2017 supports multiple installations on the same machine. +The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a +cache entry containing the absolute path to a Visual Studio instance. +If the value is not specified explicitly by the user or a toolchain file, +CMake queries the Visual Studio Installer to locate VS instances, chooses +one, and sets the variable as a cache entry to hold the value persistently. + +When CMake first chooses an instance, if the ``VS150COMNTOOLS`` environment +variable is set and points to the ``Common7/Tools`` directory within +one of the instances, that instance will be used. Otherwise, if more +than one instance is installed we do not define which one is chosen +by default. Platform Selection ^^^^^^^^^^^^^^^^^^ From 7d52d48a329d6a1c456b48f63c980cce799f3a9c Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Fri, 29 Oct 2021 09:50:41 -0400 Subject: [PATCH 1436/1519] cmCTestRunTest: get the default value from the environment This only works due to some assumptions about how the `ENVIRONMENT` property is processed. Comments have been added to notify anyone modifying the behavior about where to look. Fixes: #22819 --- Source/CTest/cmCTestRunTest.cxx | 18 +++++++++++++++++- Tests/Environment/CMakeLists.txt | 16 ++++++++++++++++ Tests/Environment/check_mod.cmake | 9 +++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 2d1562a0cfc..9d2cef69fd9 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -782,6 +782,9 @@ bool cmCTestRunTest::ForkProcess( std::ostringstream envMeasurement; if (environment && !environment->empty()) { + // Environment modification works on the assumption that the environment is + // actually modified here. If another strategy is used, there will need to + // be updates below in `apply_diff`. cmSystemTools::AppendEnv(*environment); for (auto const& var : *environment) { envMeasurement << var << std::endl; @@ -800,7 +803,20 @@ bool cmCTestRunTest::ForkProcess( auto apply_diff = [&env_application](const std::string& name, std::function<void(std::string&)> const& apply) { - std::string output = env_application[name].value_or(std::string{}); + cm::optional<std::string> old_value = env_application[name]; + std::string output; + if (old_value) { + output = *old_value; + } else { + // This only works because the environment is actually modified above + // (`AppendEnv`). If CTest ever just creates an environment block + // directly, that block will need to be queried for the subprocess' + // value instead. + const char* curval = cmSystemTools::GetEnv(name); + if (curval) { + output = curval; + } + } apply(output); env_application[name] = output; }; diff --git a/Tests/Environment/CMakeLists.txt b/Tests/Environment/CMakeLists.txt index 5f1edbffa8c..9397bfe0377 100644 --- a/Tests/Environment/CMakeLists.txt +++ b/Tests/Environment/CMakeLists.txt @@ -26,8 +26,24 @@ set_tests_properties(Environment2 EchoEnvironment2 PROPERTIES FAIL_REGULAR_EXPRESSION "CMAKE_ENV.*Happy Thanksgiving" ) +set_property(TEST EchoEnvironment3 + PROPERTY ENVIRONMENT + "SET_FROM_ENVIRONMENT_PROPERTY_unset=base" + "SET_FROM_ENVIRONMENT_PROPERTY_replace=base" + "SET_FROM_ENVIRONMENT_PROPERTY_string=base" + "SET_FROM_ENVIRONMENT_PROPERTY_path=base" + "SET_FROM_ENVIRONMENT_PROPERTY_list=base" +) + set_property(TEST EchoEnvironment3 PROPERTY ENVIRONMENT_MODIFICATION + # Modifying variables set in the `ENVIRONMENT` property. + "SET_FROM_ENVIRONMENT_PROPERTY_unset=unset:" + "SET_FROM_ENVIRONMENT_PROPERTY_replace=set:new" + "SET_FROM_ENVIRONMENT_PROPERTY_string=string_append:new" + "SET_FROM_ENVIRONMENT_PROPERTY_path=path_list_append:new" + "SET_FROM_ENVIRONMENT_PROPERTY_list=cmake_list_append:new" + # Variables expected to be unset. "UNSET_EXPLICIT=set:value" "UNSET_EXPLICIT=unset:" diff --git a/Tests/Environment/check_mod.cmake b/Tests/Environment/check_mod.cmake index 179bd7a237a..0691b17b17d 100644 --- a/Tests/Environment/check_mod.cmake +++ b/Tests/Environment/check_mod.cmake @@ -14,6 +14,7 @@ else () set(path_sep ":") endif () +set(unexpect_SET_FROM_ENVIRONMENT_PROPERTY_unset "") set(unexpect_UNSET_EXPLICIT "") set(unexpect_UNSET_VIA_RESET "") set(expect_DIRECT "new") @@ -23,8 +24,16 @@ set(expect_CMAKE_LIST_MANIP "prefix;pre;core;post;suffix") set(expect_STRING_DNE "prefix-prepost-suffix") set(expect_PATH_DNE "prefix${path_sep}pre${path_sep}post${path_sep}suffix") set(expect_CMAKE_LIST_DNE "prefix;pre;post;suffix") +set(expect_SET_FROM_ENVIRONMENT_PROPERTY_replace "new") +set(expect_SET_FROM_ENVIRONMENT_PROPERTY_string "basenew") +set(expect_SET_FROM_ENVIRONMENT_PROPERTY_path "base${path_sep}new") +set(expect_SET_FROM_ENVIRONMENT_PROPERTY_list "base;new") set(expected_vars + SET_FROM_ENVIRONMENT_PROPERTY_replace + SET_FROM_ENVIRONMENT_PROPERTY_string + SET_FROM_ENVIRONMENT_PROPERTY_path + SET_FROM_ENVIRONMENT_PROPERTY_list DIRECT STRING_MANIP PATH_MANIP From 9c4d6404eb4ac0016d2d107d8c24c8097d4e2359 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Fri, 29 Oct 2021 09:52:02 -0400 Subject: [PATCH 1437/1519] Tests/Environment: also test modifying ambient values --- Tests/CMakeLists.txt | 7 +++++++ Tests/Environment/CMakeLists.txt | 8 ++++++++ Tests/Environment/check_mod.cmake | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index d1f7b6979b8..ecb54c7aed1 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1379,6 +1379,13 @@ if(BUILD_TESTING) --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment") + set_property(TEST Environment APPEND + PROPERTY ENVIRONMENT + "SET_FROM_AMBIENT_unset=base" + "SET_FROM_AMBIENT_replace=base" + "SET_FROM_AMBIENT_string=base" + "SET_FROM_AMBIENT_path=base" + "SET_FROM_AMBIENT_list=base") add_test(QtAutomocNoQt ${CMAKE_CTEST_COMMAND} --build-and-test diff --git a/Tests/Environment/CMakeLists.txt b/Tests/Environment/CMakeLists.txt index 9397bfe0377..abcf33c53b3 100644 --- a/Tests/Environment/CMakeLists.txt +++ b/Tests/Environment/CMakeLists.txt @@ -37,6 +37,14 @@ set_property(TEST EchoEnvironment3 set_property(TEST EchoEnvironment3 PROPERTY ENVIRONMENT_MODIFICATION + # Modifying variables set in the ambient environment (see properties for + # this test in `Tests/CMakeLists.txt`). + "SET_FROM_AMBIENT_unset=unset:" + "SET_FROM_AMBIENT_replace=set:new" + "SET_FROM_AMBIENT_string=string_append:new" + "SET_FROM_AMBIENT_path=path_list_append:new" + "SET_FROM_AMBIENT_list=cmake_list_append:new" + # Modifying variables set in the `ENVIRONMENT` property. "SET_FROM_ENVIRONMENT_PROPERTY_unset=unset:" "SET_FROM_ENVIRONMENT_PROPERTY_replace=set:new" diff --git a/Tests/Environment/check_mod.cmake b/Tests/Environment/check_mod.cmake index 0691b17b17d..0f885f0f154 100644 --- a/Tests/Environment/check_mod.cmake +++ b/Tests/Environment/check_mod.cmake @@ -14,6 +14,7 @@ else () set(path_sep ":") endif () +set(unexpect_SET_FROM_AMBIENT_unset "") set(unexpect_SET_FROM_ENVIRONMENT_PROPERTY_unset "") set(unexpect_UNSET_EXPLICIT "") set(unexpect_UNSET_VIA_RESET "") @@ -24,12 +25,20 @@ set(expect_CMAKE_LIST_MANIP "prefix;pre;core;post;suffix") set(expect_STRING_DNE "prefix-prepost-suffix") set(expect_PATH_DNE "prefix${path_sep}pre${path_sep}post${path_sep}suffix") set(expect_CMAKE_LIST_DNE "prefix;pre;post;suffix") +set(expect_SET_FROM_AMBIENT_replace "new") +set(expect_SET_FROM_AMBIENT_string "basenew") +set(expect_SET_FROM_AMBIENT_path "base${path_sep}new") +set(expect_SET_FROM_AMBIENT_list "base;new") set(expect_SET_FROM_ENVIRONMENT_PROPERTY_replace "new") set(expect_SET_FROM_ENVIRONMENT_PROPERTY_string "basenew") set(expect_SET_FROM_ENVIRONMENT_PROPERTY_path "base${path_sep}new") set(expect_SET_FROM_ENVIRONMENT_PROPERTY_list "base;new") set(expected_vars + SET_FROM_AMBIENT_replace + SET_FROM_AMBIENT_string + SET_FROM_AMBIENT_path + SET_FROM_AMBIENT_list SET_FROM_ENVIRONMENT_PROPERTY_replace SET_FROM_ENVIRONMENT_PROPERTY_string SET_FROM_ENVIRONMENT_PROPERTY_path From 56d949f05f37c65401825a30be0d39bd152cc33c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 1 Nov 2021 08:09:15 -0400 Subject: [PATCH 1438/1519] FindMPI: Fix finding PkgConfg for fallback In commit 0723b2c935 (MPI: Add fallback detection code for MPI when cross compiling, 2021-09-17, v3.22.0-rc1~89^2) the FindPkgConfig module was included directly. This produces warnings like: The package name passed to `find_package_handle_standard_args` (PkgConfig) does not match the name of the calling package (MPI). Use `find_package(PkgConfig)` instead, as other find modules do. Fixes: #22823 --- Modules/FindMPI.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 62412aeec58..c974d338846 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -267,7 +267,7 @@ cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/FindPkgConfig.cmake) +find_package(PkgConfig QUIET) # Generic compiler names set(_MPI_C_GENERIC_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r) @@ -1583,7 +1583,7 @@ foreach(LANG IN ITEMS C CXX Fortran) else() set(_MPI_PKG "") endif() - if(_MPI_PKG) + if(_MPI_PKG AND PKG_CONFIG_FOUND) pkg_check_modules("MPI_${LANG}_PKG" "${_MPI_PKG}") if("${MPI_${LANG}_PKG_FOUND}") set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_${LANG}_PKG_CFLAGS} CACHE STRING "MPI ${LANG} compilation options" FORCE) From 3eefb785124bbe2cdd8cfc442806b942b601165d Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 1 Nov 2021 09:18:57 -0400 Subject: [PATCH 1439/1519] Help: Use lower-case names of sphinx directives --- Help/cpack_gen/rpm.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst index 823594abf1b..b1724af68d5 100644 --- a/Help/cpack_gen/rpm.rst +++ b/Help/cpack_gen/rpm.rst @@ -1027,7 +1027,7 @@ Source RPM packaging has its own set of variables: * Mandatory : YES * Default : "/" -.. VARIABLE:: CPACK_RPM_BUILDREQUIRES +.. variable:: CPACK_RPM_BUILDREQUIRES List of source rpm build dependencies. @@ -1040,7 +1040,7 @@ Source RPM packaging has its own set of variables: set(CPACK_RPM_BUILDREQUIRES "python >= 2.5.0, cmake >= 2.8") -.. VARIABLE:: CPACK_RPM_REQUIRES_EXCLUDE_FROM +.. variable:: CPACK_RPM_REQUIRES_EXCLUDE_FROM * Mandatory : NO * Default : - From a7a499a459591f484a2b8bfbe7905f36edf16892 Mon Sep 17 00:00:00 2001 From: Alex Turbov <i.zaufi@gmail.com> Date: Mon, 1 Nov 2021 15:17:35 +0500 Subject: [PATCH 1440/1519] Help: Add `versionadded` for `CPACK_RPM_REQUIRES_EXCLUDE_FROM` variable --- Help/cpack_gen/rpm.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst index b1724af68d5..0d287fc9122 100644 --- a/Help/cpack_gen/rpm.rst +++ b/Help/cpack_gen/rpm.rst @@ -1042,6 +1042,8 @@ Source RPM packaging has its own set of variables: .. variable:: CPACK_RPM_REQUIRES_EXCLUDE_FROM + .. versionadded:: 3.22 + * Mandatory : NO * Default : - From e9976c882739a0860ae2eae33f318cb0c601c658 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Mon, 1 Nov 2021 22:03:09 +0200 Subject: [PATCH 1441/1519] Help: Better explain CMAKE_<LANG>_EXTENSIONS_DEFAULT Explain that this represents the compiler's default and mustn't be modified by the user. Clarify when it's used as the default. Additionally: * Add a reference to it in cmake-compile-features in text explaining the feature. * Add explanations for the default initialization by `CMAKE_<LANG>_EXTENSIONS_DEFAULT` to all `<LANG>_EXTENSIONS` pages and references to CMP0128. * Slightly reduce the wordiness of the default initialization explanations by removing an unnecessary "it is". Fixes #22828. --- Help/manual/cmake-compile-features.7.rst | 6 +++--- Help/prop_tgt/CUDA_EXTENSIONS.rst | 6 ++++-- Help/prop_tgt/CXX_EXTENSIONS.rst | 6 ++++-- Help/prop_tgt/C_EXTENSIONS.rst | 6 ++++-- Help/prop_tgt/HIP_EXTENSIONS.rst | 6 ++++-- Help/prop_tgt/LANG_EXTENSIONS.rst | 3 ++- Help/prop_tgt/OBJCXX_EXTENSIONS.rst | 6 ++++-- Help/prop_tgt/OBJC_EXTENSIONS.rst | 6 ++++-- Help/variable/CMAKE_LANG_EXTENSIONS.rst | 3 ++- Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst | 7 +++++-- 10 files changed, 36 insertions(+), 19 deletions(-) diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index a0459fac46f..67b0f6ec73e 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -119,9 +119,9 @@ Availability of Compiler Extensions ----------------------------------- The :prop_tgt:`<LANG>_EXTENSIONS` target property defaults to the compiler's -efault. Note that because most compilers enable extensions by default, this -may expose cross-platform bugs in user code or in the headers of third-party -dependencies. +default (see :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`). Note that because +most compilers enable extensions by default, this may expose portability bugs +in user code or in the headers of third-party dependencies. :prop_tgt:`<LANG>_EXTENSIONS` used to default to ``ON``. See :policy:`CMP0128`. diff --git a/Help/prop_tgt/CUDA_EXTENSIONS.rst b/Help/prop_tgt/CUDA_EXTENSIONS.rst index 2ddba0b4198..ab467ac408c 100644 --- a/Help/prop_tgt/CUDA_EXTENSIONS.rst +++ b/Help/prop_tgt/CUDA_EXTENSIONS.rst @@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. This property is initialized by the value of -the :variable:`CMAKE_CUDA_EXTENSIONS` variable if it is set when a target -is created. +the :variable:`CMAKE_CUDA_EXTENSIONS` variable if set when a target is created +and otherwise by the value of +:variable:`CMAKE_CUDA_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` +(see :policy:`CMP0128`). diff --git a/Help/prop_tgt/CXX_EXTENSIONS.rst b/Help/prop_tgt/CXX_EXTENSIONS.rst index bda531ec01c..9b52504efc8 100644 --- a/Help/prop_tgt/CXX_EXTENSIONS.rst +++ b/Help/prop_tgt/CXX_EXTENSIONS.rst @@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. This property is initialized by the value of -the :variable:`CMAKE_CXX_EXTENSIONS` variable if it is set when a target -is created. +the :variable:`CMAKE_CXX_EXTENSIONS` variable if set when a target is created +and otherwise by the value of +:variable:`CMAKE_CXX_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` (see +:policy:`CMP0128`). diff --git a/Help/prop_tgt/C_EXTENSIONS.rst b/Help/prop_tgt/C_EXTENSIONS.rst index b2abb462fc7..a53090c57fd 100644 --- a/Help/prop_tgt/C_EXTENSIONS.rst +++ b/Help/prop_tgt/C_EXTENSIONS.rst @@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. This property is initialized by the value of -the :variable:`CMAKE_C_EXTENSIONS` variable if it is set when a target -is created. +the :variable:`CMAKE_C_EXTENSIONS` variable if set when a target is created and +otherwise by the value of +:variable:`CMAKE_C_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` (see +:policy:`CMP0128`). diff --git a/Help/prop_tgt/HIP_EXTENSIONS.rst b/Help/prop_tgt/HIP_EXTENSIONS.rst index b731753bd03..d1475c96420 100644 --- a/Help/prop_tgt/HIP_EXTENSIONS.rst +++ b/Help/prop_tgt/HIP_EXTENSIONS.rst @@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. This property is initialized by the value of -the :variable:`CMAKE_HIP_EXTENSIONS` variable if it is set when a target -is created. +the :variable:`CMAKE_HIP_EXTENSIONS` variable if set when a target is created +and otherwise by the value of +:variable:`CMAKE_HIP_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` (see +:policy:`CMP0128`). diff --git a/Help/prop_tgt/LANG_EXTENSIONS.rst b/Help/prop_tgt/LANG_EXTENSIONS.rst index 2add21db58b..afc2ad367ec 100644 --- a/Help/prop_tgt/LANG_EXTENSIONS.rst +++ b/Help/prop_tgt/LANG_EXTENSIONS.rst @@ -14,7 +14,8 @@ These properties specify whether compiler-specific extensions are requested. These properties are initialized by the value of the :variable:`CMAKE_<LANG>_EXTENSIONS` variable if it is set when a target is -created. +created and otherwise by the value of +:variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT` (see :policy:`CMP0128`). For supported CMake versions see the respective pages. To control language standard versions see :prop_tgt:`<LANG>_STANDARD`. diff --git a/Help/prop_tgt/OBJCXX_EXTENSIONS.rst b/Help/prop_tgt/OBJCXX_EXTENSIONS.rst index 8a254f20a56..2a15dec9066 100644 --- a/Help/prop_tgt/OBJCXX_EXTENSIONS.rst +++ b/Help/prop_tgt/OBJCXX_EXTENSIONS.rst @@ -18,5 +18,7 @@ If the property is not set, and the project has set the :prop_tgt:`CXX_EXTENSION the value of :prop_tgt:`CXX_EXTENSIONS` is set for :prop_tgt:`OBJCXX_EXTENSIONS`. This property is initialized by the value of -the :variable:`CMAKE_OBJCXX_EXTENSIONS` variable if it is set when a target -is created. +the :variable:`CMAKE_OBJCXX_EXTENSIONS` variable if set when a target is +created and otherwise by the value of +:variable:`CMAKE_OBJCXX_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` +(see :policy:`CMP0128`). diff --git a/Help/prop_tgt/OBJC_EXTENSIONS.rst b/Help/prop_tgt/OBJC_EXTENSIONS.rst index ef1c7543cd9..cd72e5fcca1 100644 --- a/Help/prop_tgt/OBJC_EXTENSIONS.rst +++ b/Help/prop_tgt/OBJC_EXTENSIONS.rst @@ -18,5 +18,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. This property is initialized by the value of -the :variable:`CMAKE_OBJC_EXTENSIONS` variable if it is set when a target -is created. +the :variable:`CMAKE_OBJC_EXTENSIONS` variable if set when a target is created +and otherwise by the value of +:variable:`CMAKE_OBJC_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` +(see :policy:`CMP0128`). diff --git a/Help/variable/CMAKE_LANG_EXTENSIONS.rst b/Help/variable/CMAKE_LANG_EXTENSIONS.rst index 84e5e3ad1b8..3a32002f612 100644 --- a/Help/variable/CMAKE_LANG_EXTENSIONS.rst +++ b/Help/variable/CMAKE_LANG_EXTENSIONS.rst @@ -11,7 +11,8 @@ The variations are: * :variable:`CMAKE_OBJCXX_EXTENSIONS` Default values for :prop_tgt:`<LANG>_EXTENSIONS` target properties if set when -a target is created. +a target is created. For the compiler's default setting see +:variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. For supported CMake versions see the respective pages. diff --git a/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst b/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst index 6783eb5b599..a66453acb1d 100644 --- a/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst +++ b/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst @@ -3,5 +3,8 @@ CMAKE_<LANG>_EXTENSIONS_DEFAULT .. versionadded:: 3.22 -Default value used when the :prop_tgt:`<LANG>_EXTENSIONS` target property is -not set. Initialized during compiler detection to the compiler's default. +Compiler's default extensions mode. Used as the default for the +:prop_tgt:`<LANG>_EXTENSIONS` target property when +:variable:`CMAKE_<LANG>_EXTENSIONS` is not set (see :policy:`CMP0128`). + +This variable is read-only. Modifying it is undefined behavior. From 92624714c4ab99fd14631c7a8b45d5efc02cdff9 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Tue, 2 Nov 2021 09:57:55 -0400 Subject: [PATCH 1442/1519] NVHPC: Support SYSTEM include directories Fixed #22834 --- Modules/Compiler/NVHPC.cmake | 1 + Tests/IncludeDirectories/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake index 70486705c1c..b51bb433929 100644 --- a/Modules/Compiler/NVHPC.cmake +++ b/Modules/Compiler/NVHPC.cmake @@ -12,4 +12,5 @@ include(Compiler/PGI) macro(__compiler_nvhpc lang) # Logic specific to NVHPC. + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") endmacro() diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index 4c488e61591..f00565e563f 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -3,6 +3,7 @@ project(IncludeDirectories) if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4) OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") + OR CMAKE_C_COMPILER_ID STREQUAL NVHPC OR CMAKE_C_COMPILER_ID STREQUAL AppleClang OR ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "19.29.30036.3" AND From bd36735f65b3f2c87f7510a7474ac2cd5f98084c Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 10:06:23 -0400 Subject: [PATCH 1443/1519] cmNinjaTargetGenerator: Replace "their" with "there" in comment --- Source/cmNinjaTargetGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 57fc020abb5..57657b1c7d1 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1749,7 +1749,7 @@ void cmNinjaTargetGenerator::EnsureDirectoryExists( } else { cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator(); std::string fullPath = gg->GetCMakeInstance()->GetHomeOutputDirectory(); - // Also ensures their is a trailing slash. + // Also ensures there is a trailing slash. gg->StripNinjaOutputPathPrefixAsSuffix(fullPath); fullPath += path; cmSystemTools::MakeDirectory(fullPath); From 73b84db62d30c8eaa4cde73de6bcb5da1ef27ae6 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 10:07:02 -0400 Subject: [PATCH 1444/1519] Ninja: Fix creation of Windows import library directory Call `EnsureParentDirectoryExists` with our internal representation of the path, not the representation quoted/encoded for Ninja. Fixes: #22841 --- Source/cmNinjaNormalTargetGenerator.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 596084b7636..517d52955d0 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -902,7 +902,7 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement( const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; - this->EnsureParentDirectoryExists(impLibPath); + this->EnsureParentDirectoryExists(targetOutputImplib); } const std::string objPath = @@ -1211,7 +1211,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; - this->EnsureParentDirectoryExists(impLibPath); + this->EnsureParentDirectoryExists(targetOutputImplib); if (gt->HasImportLibrary(config)) { // Some linkers may update a binary without touching its import lib. byproducts.ExplicitOuts.emplace_back(targetOutputImplib); From 571a795d2fb33e4dfdc401fa824e27b86f8bbed7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 10:31:19 -0400 Subject: [PATCH 1445/1519] GNUtoMS: Add search path for VS 2022 environment scripts Extend the logic from commit 08c5b3eff0 (GNUtoMS: Add search path for VS 2019 environment scripts, 2020-01-09, v3.16.3~15^2) to consider VS 2022 paths too. Fixes: #22847 --- Modules/Platform/Windows-GNU.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index d0003803bde..a04882f5653 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -148,7 +148,7 @@ macro(__windows_compiler_gnu_abi lang) # Query the VS Installer tool for locations of VS 2017 and above. set(_vs_installer_paths "") - foreach(vs RANGE 16 15 -1) # change the first number to the largest supported version + foreach(vs RANGE 17 15 -1) # change the first number to the largest supported version cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR) if(_vs_dir) list(APPEND _vs_installer_paths "${_vs_dir}/VC/Auxiliary/Build") From 9ed1d7bee6f36b489fa3bb5e77add26ea6119f61 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 10:50:54 -0400 Subject: [PATCH 1446/1519] cmScanDepFormat: Accept P1689r4 files with version 1 VS 2022's `cl` 19.30 has a `-scanDependencies` option that produces the P1689r4 format. It reports the "version" field with value "1". --- Source/cmScanDepFormat.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index 6fcbce5f18d..82a374a83bc 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -97,7 +97,7 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, } Json::Value const& version = ppi["version"]; - if (version.asUInt() != 0) { + if (version.asUInt() > 1) { cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, ": version ", version.asString())); return false; From 6f830c5c38abf0deed2ffb7e5d4407faa5656503 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 3 Nov 2021 11:27:53 -0400 Subject: [PATCH 1447/1519] FindHDF5: fix variable name when querying `hdf5_hl`'s implib Introduced in 4150048a3b (FindHDF5: unset some variables, 2017-07-24). --- Modules/FindHDF5.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index e33535513a3..caaf7b70f04 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -560,7 +560,7 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE) set(HDF5_${_lang}_FOUND TRUE) endif() if(HDF5_FIND_HL) - get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} ) + get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} ) if (NOT _hdf5_lang_hl_location) get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf}) if (NOT _hdf5_hl_lang_location) From f56963cf054832995488287af7b8c4abd6c8e4dd Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 3 Nov 2021 13:05:18 -0400 Subject: [PATCH 1448/1519] FindHDF5: clear library output variables at the top of the module This avoids accumulation of `HDF5_LIBRARIES` results when calling `find_package(HDF5)` multiple times within a single scope. --- Modules/FindHDF5.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index e33535513a3..ce08728b235 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -161,6 +161,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) # scope somewhere else. We can't rely on it because different components may # have been requested for this call. set(HDF5_FOUND OFF) +set(HDF5_LIBRARIES) +set(HDF5_HL_LIBRARIES) # List of the valid HDF5 components set(HDF5_VALID_LANGUAGE_BINDINGS C CXX Fortran) From 247f1149e1035f6a9cd95620016364015c34807b Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Wed, 3 Nov 2021 13:24:30 -0400 Subject: [PATCH 1449/1519] FindHDF5: clear language-specific libraries list before discovery --- Modules/FindHDF5.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index ce08728b235..bda392da343 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -588,6 +588,9 @@ if(NOT HDF5_FOUND) set(HDF5_COMPILER_NO_INTERROGATE TRUE) # Only search for languages we've enabled foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + set(HDF5_${_lang}_LIBRARIES) + set(HDF5_${_lang}_HL_LIBRARIES) + # First check to see if our regular compiler is one of wrappers if(_lang STREQUAL "C") _HDF5_test_regular_compiler_C( @@ -813,6 +816,9 @@ if( NOT HDF5_FOUND ) endif() foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + set(HDF5_${_lang}_LIBRARIES) + set(HDF5_${_lang}_HL_LIBRARIES) + # The "main" library. set(_hdf5_main_library "") From 78782cc7dc9f4efa2e3a19c174dca0129d99af2e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 11:58:27 -0400 Subject: [PATCH 1450/1519] cmGlobalVisualStudio8Generator: Refactor SetGeneratorPlatform Re-organize the method to make room for additional `CMAKE_GENERATOR_PLATFORM` processing. --- Source/cmGlobalVisualStudio8Generator.cxx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 092e5b92d9e..439d13e9d5b 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -67,12 +67,19 @@ void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, cmMakefile* mf) { - if (!this->PlatformInGeneratorName) { - this->GeneratorPlatform = p; - return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); - } else { + if (this->PlatformInGeneratorName) { + // This is an old-style generator name that contains the platform name. + // No explicit platform specification is supported, so pass it through + // to our base class implementation, which errors on non-empty platforms. return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform(p, mf); } + + this->GeneratorPlatform = p; + + // The generator name does not contain the platform name, and so supports + // explicit platform specification. We handled that above, so pass an + // empty platform name to our base class implementation so it does not error. + return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); } std::string cmGlobalVisualStudio8Generator::GetGenerateStampList() From 001870d451d965a2cc4a30a89ed23e69bcd70b5e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 15:51:35 -0400 Subject: [PATCH 1451/1519] Help: Clarify TARGET_RUNTIME_DLLS behavior on imported targets This generator expression does not report the locations of `.dll` files on imported targets with the `UNKNWON` type, since their `IMPORTED_LOCATION` refers to the import library and not the DLL. Fixes: #22845 --- Help/command/add_library.rst | 5 ++++- Help/manual/cmake-generator-expressions.7.rst | 11 ++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst index dfc650091a7..1235155deba 100644 --- a/Help/command/add_library.rst +++ b/Help/command/add_library.rst @@ -166,6 +166,8 @@ itself and is not included as a target in the generated buildsystem. call are ``PRIVATE`` to the interface library and do not appear in its :prop_tgt:`INTERFACE_SOURCES` target property. +.. _`add_library imported libraries`: + Imported Libraries ^^^^^^^^^^^^^^^^^^ @@ -205,7 +207,8 @@ The ``<type>`` must be one of: :prop_tgt:`IMPORTED_IMPLIB_<CONFIG>`) specifies the location of the DLL import library file (``.lib`` or ``.dll.a``) on disk, and the ``IMPORTED_LOCATION`` is the location of the ``.dll`` runtime - library (and is optional). + library (and is optional, but needed by the :genex:`TARGET_RUNTIME_DLLS` + generator expression). Additional usage requirements may be specified in ``INTERFACE_*`` properties. diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 5d508cb0dd7..d3cbd491c27 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -1068,7 +1068,7 @@ which is just the string ``tgt``. .. code-block:: cmake - find_package(foo REQUIRED) + find_package(foo CONFIG REQUIRED) # package generated by install(EXPORT) add_executable(exe main.c) target_link_libraries(exe PRIVATE foo::foo foo::bar) @@ -1077,6 +1077,15 @@ which is just the string ``tgt``. COMMAND_EXPAND_LISTS ) + .. note:: + + :ref:`Imported Targets` are supported only if they know the location + of their ``.dll`` files. An imported ``SHARED`` or ``MODULE`` library + must have :prop_tgt:`IMPORTED_LOCATION` set to its ``.dll`` file. See + the :ref:`add_library imported libraries <add_library imported libraries>` + section for details. Many :ref:`Find Modules` produce imported targets + with the ``UNKNOWN`` type and therefore will be ignored. + .. genex:: $<INSTALL_PREFIX> Content of the install prefix when the target is exported via From 16e24748c5092f19d53c80548083826f009aafc7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 4 Nov 2021 11:58:06 -0400 Subject: [PATCH 1452/1519] Ninja Multi-Config: Fix cross-config custom command dependency tracing Process `CMAKE_CROSS_CONFIGS` and friends to properly configure the generator for cross-config behavior before custom command dependency tracing. --- Source/cmGlobalGenerator.cxx | 3 +++ Source/cmGlobalGenerator.h | 2 ++ Source/cmGlobalNinjaGenerator.cxx | 3 --- Source/cmGlobalNinjaGenerator.h | 2 -- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ac283ab4a1c..9914902eff3 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1402,6 +1402,9 @@ bool cmGlobalGenerator::Compute() this->SupportsDefaultConfigs())) { return false; } + if (!this->InspectConfigTypeVariables()) { + return false; + } // Some generators track files replaced during the Generate. // Start with an empty vector: diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index cc0ad29d27d..96696aa8a4b 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -153,6 +153,8 @@ class cmGlobalGenerator */ virtual void Configure(); + virtual bool InspectConfigTypeVariables() { return true; } + bool Compute(); virtual void AddExtraIDETargets() {} diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 3f6f55ee9c6..7122b9f8f26 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -568,9 +568,6 @@ void cmGlobalNinjaGenerator::Generate() msg.str()); return; } - if (!this->InspectConfigTypeVariables()) { - return; - } if (!this->OpenBuildFileStreams()) { return; } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index ec73475db5d..84fc06c1cd3 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -481,8 +481,6 @@ class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator const std::set<std::string>& all, const std::set<std::string>& defaults, const std::vector<std::string>& items); - virtual bool InspectConfigTypeVariables() { return true; } - std::set<std::string> CrossConfigs; std::set<std::string> DefaultConfigs; std::string DefaultFileConfig; From a8833639356204d4e3f0ff180c0ff102644a7bad Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 4 Nov 2021 13:26:48 -0400 Subject: [PATCH 1453/1519] Ninja Multi-Config: Fix internal cross-config target dependency ordering In commit 7abc3d61ac (Ninja Multi-Config: Fix issue with framework dependencies and Autogen, 2020-02-13, v3.17.0-rc2~18^2) the `cmLinkItem` comparison operator was updated to order identical strings by the cross-config boolean. We need to order identical targets that way too in order to represent both a cross and non-cross dependency on the same target. Issue: #22855 --- Source/cmLinkItem.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx index 4e50d7097f9..62e7ef425c5 100644 --- a/Source/cmLinkItem.cxx +++ b/Source/cmLinkItem.cxx @@ -32,7 +32,11 @@ bool operator<(cmLinkItem const& l, cmLinkItem const& r) { // Order among targets. if (l.Target && r.Target) { - return l.Target < r.Target; + if (l.Target != r.Target) { + return l.Target < r.Target; + } + // Order identical targets via cross-config. + return l.Cross < r.Cross; } // Order targets before strings. if (l.Target) { @@ -42,10 +46,10 @@ bool operator<(cmLinkItem const& l, cmLinkItem const& r) return false; } // Order among strings. - if (l.String < r.String) { - return true; + if (l.String != r.String) { + return l.String < r.String; } - // Order among cross-config. + // Order identical strings via cross-config. return l.Cross < r.Cross; } From 95f44e00cd1fd90a68f466b432198ca98456cce7 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 4 Nov 2021 12:02:10 -0400 Subject: [PATCH 1454/1519] Ninja Multi-Config: Fix custom command target dependencies in cross-configs Generator expressions in a non-cross custom command's `COMMAND` arguments are evaluated in the command config. Target-level dependencies implied by `TARGET_FILE` must therefore be cross dependencies. This is important to generate proper target-level dependencies on the cross-config build statements for the target to which the custom command is attached. Fixes: #22855 --- Source/cmCustomCommandGenerator.cxx | 12 ++++++++---- ...nd_target-debug-in-release-graph-ninja-stdout.txt | 2 ++ ...utGenex-echo_depend_target-debug-ninja-stdout.txt | 2 ++ ...Genex-echo_depend_target-release-ninja-stdout.txt | 2 ++ .../NinjaMultiConfig/CustomCommandOutputGenex.cmake | 10 ++++++++++ Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake | 10 ++++++++++ 6 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt create mode 100644 Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 04d09d4d62d..fd0a63c295d 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -91,7 +91,7 @@ std::string EvaluateSplitConfigGenex( // Record targets referenced by the genex. if (utils) { - // FIXME: What is the proper condition for a cross-dependency? + // Use a cross-dependency if we referenced the command config. bool const cross = !useOutputConfig; for (cmGeneratorTarget* gt : cge->GetTargets()) { utils->emplace(BT<std::pair<std::string, bool>>( @@ -176,6 +176,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse( this->Target) }; + bool const distinctConfigs = this->OutputConfig != this->CommandConfig; + const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines(); for (cmCustomCommandLine const& cmdline : cmdlines) { cmCustomCommandLine argv; @@ -191,8 +193,10 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( argv.push_back(std::move(parsed_arg)); } - // For remaining arguments, we default to the OUTPUT_CONFIG. - useOutputConfig = true; + if (distinctConfigs) { + // For remaining arguments, we default to the OUTPUT_CONFIG. + useOutputConfig = true; + } } if (!argv.empty()) { @@ -200,7 +204,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( // collect the target to add a target-level dependency on it. cmGeneratorTarget* gt = this->LG->FindGeneratorTargetToUse(argv.front()); if (gt && gt->GetType() == cmStateEnums::EXECUTABLE) { - // FIXME: What is the proper condition for a cross-dependency? + // GetArgv0Location uses the command config, so use a cross-dependency. bool const cross = true; this->Utilities.emplace(BT<std::pair<std::string, bool>>( { gt->GetName(), cross }, cc.GetBacktrace())); diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt new file mode 100644 index 00000000000..80e9c2ff90d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt @@ -0,0 +1,2 @@ +^\[1/1\] Generating echo_depend_target\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt new file mode 100644 index 00000000000..1a7987786fd --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt @@ -0,0 +1,2 @@ +^\[1/1\] Generating echo_depend_target\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt new file mode 100644 index 00000000000..80e9c2ff90d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt @@ -0,0 +1,2 @@ +^\[1/1\] Generating echo_depend_target\.txt +'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release'$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake index bb68a509e63..2de5a3a7773 100644 --- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake @@ -143,6 +143,16 @@ add_custom_command( PROPERTY SYMBOLIC 1) add_custom_target(echo_dbgx DEPENDS "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>") +# A non-cross-config custom command expresses target dependencies in command config. +add_custom_command( + OUTPUT echo_depend_target.txt + COMMAND ${CMAKE_COMMAND} -E env $<TARGET_FILE:echo> $<CONFIG> + # A real project should do: + # DEPENDS $<TARGET_FILE:echo> + # but here we are testing the target-level dependency implied by TARGET_FILE. + ) +add_custom_target(echo_depend_target DEPENDS echo_depend_target.txt) + add_custom_target(echo_target_raw BYPRODUCTS echo_target_raw_$<CONFIG>.txt COMMENT echo_target_raw diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index c7b876c4b4e..4a0c130a1f5 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -344,6 +344,16 @@ run_ninja(CustomCommandOutputGenex echo_dbgx-release build-Release.ninja echo_db run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) run_ninja(CustomCommandOutputGenex echo_dbgx-debug-in-release-graph build-Release.ninja echo_dbgx:Debug) run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) +# echo_depend_target +run_ninja(CustomCommandOutputGenex echo_depend_target-debug-prep build-Debug.ninja echo:Debug) +run_ninja(CustomCommandOutputGenex echo_depend_target-debug build-Debug.ninja echo_depend_target) +run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean) +run_ninja(CustomCommandOutputGenex echo_depend_target-release-prep build-Release.ninja echo:Release) +run_ninja(CustomCommandOutputGenex echo_depend_target-release build-Release.ninja echo_depend_target) +run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) +run_ninja(CustomCommandOutputGenex echo_depend_target-debug-in-release-graph-prep build-Release.ninja echo:Release) +run_ninja(CustomCommandOutputGenex echo_depend_target-debug-in-release-graph build-Release.ninja echo_depend_target:Debug) +run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean) # echo_target_raw run_ninja(CustomCommandOutputGenex echo_target_raw-debug build-Debug.ninja echo_target_raw:Debug) run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean) From 58c8d649e178ad775012dfdf75a5118cbd2de23a Mon Sep 17 00:00:00 2001 From: Thomas Dickerson <elfprince13@gmail.com> Date: Thu, 4 Nov 2021 10:59:10 -0400 Subject: [PATCH 1455/1519] CheckLinkerFlag: Set policies needed by the implementation The module was added in CMake 3.18 by commit af96c0f4fa (CheckLinkerFlag: Add module to check validity of linker flags, 2020-05-16, v3.18.0-rc1~103^2), but it is still possible for projects to use it without setting policies to the 3.18 version level. --- Modules/CheckLinkerFlag.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/CheckLinkerFlag.cmake b/Modules/CheckLinkerFlag.cmake index 28ac2e32e2e..e85e43e9b68 100644 --- a/Modules/CheckLinkerFlag.cmake +++ b/Modules/CheckLinkerFlag.cmake @@ -41,6 +41,10 @@ include_guard(GLOBAL) include(CMakeCheckCompilerFlagCommonPatterns) +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced +cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST + function(CHECK_LINKER_FLAG _lang _flag _var) get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES) if (NOT _lang IN_LIST _supported_languages) @@ -82,3 +86,5 @@ function(CHECK_LINKER_FLAG _lang _flag _var) endforeach() set(${_var} "${${_var}}" PARENT_SCOPE) endfunction() + +cmake_policy(POP) From e40cedddc0bcdd7d0317592a83fde42fd018f72f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 5 Nov 2021 08:54:14 -0400 Subject: [PATCH 1456/1519] cmVisualStudio10TargetGenerator: Refactor target framework selection Split the selection from the generation of the resulting element(s). --- Source/cmVisualStudio10TargetGenerator.cxx | 88 +++++++++++++--------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1ea0461f5cf..f7656126567 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -6,6 +6,7 @@ #include <set> #include <cm/memory> +#include <cm/optional> #include <cm/string_view> #include <cm/vector> #include <cmext/algorithm> @@ -492,50 +493,67 @@ void cmVisualStudio10TargetGenerator::Generate() cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL"); e1.Element("ProjectName", projLabel ? projLabel : this->Name); { - cmValue targetFramework = - this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK"); + cm::optional<std::string> targetFramework; + cm::optional<std::string> targetFrameworkVersion; + cm::optional<std::string> targetFrameworkIdentifier; + cm::optional<std::string> targetFrameworkTargetsVersion; + if (cmValue tf = + this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK")) { + targetFramework = *tf; + } else if (cmValue vstfVer = this->GeneratorTarget->GetProperty( + "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { + // FIXME: Someday, add a deprecation warning for VS_* property. + targetFrameworkVersion = *vstfVer; + } else if (cmValue tfVer = this->GeneratorTarget->GetProperty( + "DOTNET_TARGET_FRAMEWORK_VERSION")) { + targetFrameworkVersion = *tfVer; + } else if (this->ProjectType == csproj && + this->GlobalGenerator->TargetsWindowsCE() && + this->GlobalGenerator->GetVersion() == + cmGlobalVisualStudioGenerator::VS12) { + // VS12 .NETCF default to .NET framework 3.9 + targetFrameworkVersion = "v3.9"; + } + if (this->ProjectType == vcxproj && + this->GlobalGenerator->TargetsWindowsCE()) { + e1.Element("EnableRedirectPlatform", "true"); + e1.Element("RedirectPlatformValue", this->Platform); + } + if (this->ProjectType == csproj) { + if (this->GlobalGenerator->TargetsWindowsCE()) { + // FIXME: These target VS_TARGET_FRAMEWORK* target properties + // are undocumented settings only ever supported for WinCE. + // We need a better way to control these in general. + if (cmValue tfId = this->GeneratorTarget->GetProperty( + "VS_TARGET_FRAMEWORK_IDENTIFIER")) { + targetFrameworkIdentifier = *tfId; + } else { + targetFrameworkIdentifier = "WindowsEmbeddedCompact"; + } + if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty( + "VS_TARGET_FRAMEWORKS_TARGET_VERSION")) { + targetFrameworkTargetsVersion = *tfTargetsVer; + } else { + targetFrameworkTargetsVersion = "v8.0"; + } + } + } if (targetFramework) { if (targetFramework->find(';') != std::string::npos) { e1.Element("TargetFrameworks", *targetFramework); } else { e1.Element("TargetFramework", *targetFramework); } - } else { - // TODO: add deprecation warning for VS_* property? - cmValue p = this->GeneratorTarget->GetProperty( - "VS_DOTNET_TARGET_FRAMEWORK_VERSION"); - if (!p) { - p = this->GeneratorTarget->GetProperty( - "DOTNET_TARGET_FRAMEWORK_VERSION"); - } - std::string targetFrameworkVersion = p; - if (targetFrameworkVersion.empty() && this->ProjectType == csproj && - this->GlobalGenerator->TargetsWindowsCE() && - this->GlobalGenerator->GetVersion() == - cmGlobalVisualStudioGenerator::VS12) { - // VS12 .NETCF default to .NET framework 3.9 - targetFrameworkVersion = "v3.9"; - } - if (!targetFrameworkVersion.empty()) { - e1.Element("TargetFrameworkVersion", targetFrameworkVersion); - } } - if (this->ProjectType == vcxproj && - this->GlobalGenerator->TargetsWindowsCE()) { - e1.Element("EnableRedirectPlatform", "true"); - e1.Element("RedirectPlatformValue", this->Platform); + if (targetFrameworkVersion) { + e1.Element("TargetFrameworkVersion", *targetFrameworkVersion); } - if (this->ProjectType == csproj && - this->GlobalGenerator->TargetsWindowsCE()) { - cmValue targetFrameworkId = this->GeneratorTarget->GetProperty( - "VS_TARGET_FRAMEWORK_IDENTIFIER"); - e1.Element("TargetFrameworkIdentifier", - targetFrameworkId ? *targetFrameworkId - : "WindowsEmbeddedCompact"); - cmValue targetFrameworkVer = this->GeneratorTarget->GetProperty( - "VS_TARGET_FRAMEWORKS_TARGET_VERSION"); + if (targetFrameworkIdentifier) { + e1.Element("TargetFrameworkIdentifier", *targetFrameworkIdentifier); + } + if (targetFrameworkTargetsVersion) { e1.Element("TargetFrameworkTargetsVersion", - targetFrameworkVer ? *targetFrameworkVer : "v8.0"); + *targetFrameworkTargetsVersion); } if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() .empty()) { From f97f8537f371daa073edce34f54743d1f261c022 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 14:31:04 -0400 Subject: [PATCH 1457/1519] VS: Model a default target framework Add fields to the VS generator to select a target framework. Migrate the existing default for VS 12 .NET CF for Windows CE. Report the values in `CMAKE_VS_*` variables and use them for the CSharp compiler id project too. Issue: #22849 --- Help/manual/cmake-variables.7.rst | 3 ++ .../CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst | 13 +++++++ ...KE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst | 13 +++++++ .../CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst | 17 +++++++++ Modules/CMakeDetermineCompilerId.cmake | 9 +++++ Modules/CompilerId/VS-10.csproj.in | 3 ++ Source/cmGlobalVisualStudio10Generator.cxx | 7 ++++ Source/cmGlobalVisualStudio8Generator.cxx | 36 +++++++++++++++++++ Source/cmGlobalVisualStudio8Generator.h | 10 ++++++ Source/cmVisualStudio10TargetGenerator.cxx | 21 +++++------ 10 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst create mode 100644 Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst create mode 100644 Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index a2103f72bf9..4ed0b2e62a7 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -125,6 +125,9 @@ Variables that Provide Information /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION + /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION + /variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER + /variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM /variable/CMAKE_XCODE_BUILD_SYSTEM diff --git a/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst new file mode 100644 index 00000000000..5ad589719e7 --- /dev/null +++ b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst @@ -0,0 +1,13 @@ +CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER +------------------------------------ + +.. versionadded:: 3.22 + +Visual Studio target framework identifier. + +In some cases, the :ref:`Visual Studio Generators` may use an explicit value +for the MSBuild ``TargetFrameworkIdentifier`` setting in ``.csproj`` files. +CMake provides the chosen value in this variable. + +See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_VERSION` and +:variable:`CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION`. diff --git a/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst new file mode 100644 index 00000000000..8dcb3a72b39 --- /dev/null +++ b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst @@ -0,0 +1,13 @@ +CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION +----------------------------------------- + +.. versionadded:: 3.22 + +Visual Studio target framework targets version. + +In some cases, the :ref:`Visual Studio Generators` may use an explicit value +for the MSBuild ``TargetFrameworkTargetsVersion`` setting in ``.csproj`` files. +CMake provides the chosen value in this variable. + +See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_VERSION` and +:variable:`CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER`. diff --git a/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst new file mode 100644 index 00000000000..5489f791966 --- /dev/null +++ b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst @@ -0,0 +1,17 @@ +CMAKE_VS_TARGET_FRAMEWORK_VERSION +--------------------------------- + +.. versionadded:: 3.22 + +Visual Studio target framework version. + +In some cases, the :ref:`Visual Studio Generators` may use an explicit value +for the MSBuild ``TargetFrameworkVersion`` setting in ``.csproj`` files. +CMake provides the chosen value in this variable. + +See the :variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION` variable +and :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target property to +specify custom ``TargetFrameworkVersion`` values for project targets. + +See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER` and +:variable:`CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION`. diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index fa283fec14c..c62cb7d2494 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -421,6 +421,15 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} if(CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR) set(id_ToolsetVCTargetsDir "<VCTargetsPath>${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}</VCTargetsPath>") endif() + if(CMAKE_VS_TARGET_FRAMEWORK_VERSION) + set(id_TargetFrameworkVersion "<TargetFrameworkVersion>${CMAKE_VS_TARGET_FRAMEWORK_VERSION}</TargetFrameworkVersion>") + endif() + if(CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER) + set(id_TargetFrameworkIdentifier "<TargetFrameworkIdentifier>${CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER}</TargetFrameworkIdentifier>") + endif() + if(CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION) + set(id_TargetFrameworkTargetsVersion "<TargetFrameworkTargetsVersion>${CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION}</TargetFrameworkTargetsVersion>") + endif() set(id_CustomGlobals "") foreach(pair IN LISTS CMAKE_VS_GLOBALS) if("${pair}" MATCHES "([^=]+)=(.*)$") diff --git a/Modules/CompilerId/VS-10.csproj.in b/Modules/CompilerId/VS-10.csproj.in index ed5e8476fad..fba74ff587d 100644 --- a/Modules/CompilerId/VS-10.csproj.in +++ b/Modules/CompilerId/VS-10.csproj.in @@ -6,6 +6,9 @@ <Keyword>Win32Proj</Keyword> @id_system@ @id_system_version@ + @id_TargetFrameworkVersion@ + @id_TargetFrameworkIdentifier@ + @id_TargetFrameworkTargetsVersion@ @id_WindowsTargetPlatformVersion@ @id_WindowsSDKDesktopARMSupport@ </PropertyGroup> diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index c11516ddb52..6cab4926924 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -580,6 +580,13 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf) this->DefaultPlatformToolset = this->SelectWindowsCEToolset(); + if (this->GetVersion() == cmGlobalVisualStudioGenerator::VS12) { + // VS 12 .NET CF defaults to .NET framework 3.9 for Windows CE. + this->DefaultTargetFrameworkVersion = "v3.9"; + this->DefaultTargetFrameworkIdentifier = "WindowsEmbeddedCompact"; + this->DefaultTargetFrameworkTargetsVersion = "v8.0"; + } + return true; } diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 439d13e9d5b..1e45813bb92 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -76,12 +76,48 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, this->GeneratorPlatform = p; + // FIXME: Add CMAKE_GENERATOR_PLATFORM field to set the framework. + // For now, just report the generator's default, if any. + if (cm::optional<std::string> const& targetFrameworkVersion = + this->GetTargetFrameworkVersion()) { + mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_VERSION", + *targetFrameworkVersion); + } + if (cm::optional<std::string> const& targetFrameworkIdentifier = + this->GetTargetFrameworkIdentifier()) { + mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER", + *targetFrameworkIdentifier); + } + if (cm::optional<std::string> const& targetFrameworkTargetsVersion = + this->GetTargetFrameworkTargetsVersion()) { + mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION", + *targetFrameworkTargetsVersion); + } + // The generator name does not contain the platform name, and so supports // explicit platform specification. We handled that above, so pass an // empty platform name to our base class implementation so it does not error. return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); } +cm::optional<std::string> const& +cmGlobalVisualStudio8Generator::GetTargetFrameworkVersion() const +{ + return this->DefaultTargetFrameworkVersion; +} + +cm::optional<std::string> const& +cmGlobalVisualStudio8Generator::GetTargetFrameworkIdentifier() const +{ + return this->DefaultTargetFrameworkIdentifier; +} + +cm::optional<std::string> const& +cmGlobalVisualStudio8Generator::GetTargetFrameworkTargetsVersion() const +{ + return this->DefaultTargetFrameworkTargetsVersion; +} + std::string cmGlobalVisualStudio8Generator::GetGenerateStampList() { return "generate.stamp.list"; diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 96e3553f26a..b6ecdf07f8e 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include <cm/optional> + #include "cmGlobalVisualStudio71Generator.h" /** \class cmGlobalVisualStudio8Generator @@ -24,6 +26,10 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; + cm::optional<std::string> const& GetTargetFrameworkVersion() const; + cm::optional<std::string> const& GetTargetFrameworkIdentifier() const; + cm::optional<std::string> const& GetTargetFrameworkTargetsVersion() const; + /** * Override Configure and Generate to add the build-system check * target. @@ -76,4 +82,8 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator std::string Name; std::string WindowsCEVersion; + + cm::optional<std::string> DefaultTargetFrameworkVersion; + cm::optional<std::string> DefaultTargetFrameworkIdentifier; + cm::optional<std::string> DefaultTargetFrameworkTargetsVersion; }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index f7656126567..d2c49ae36b8 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -507,12 +507,9 @@ void cmVisualStudio10TargetGenerator::Generate() } else if (cmValue tfVer = this->GeneratorTarget->GetProperty( "DOTNET_TARGET_FRAMEWORK_VERSION")) { targetFrameworkVersion = *tfVer; - } else if (this->ProjectType == csproj && - this->GlobalGenerator->TargetsWindowsCE() && - this->GlobalGenerator->GetVersion() == - cmGlobalVisualStudioGenerator::VS12) { - // VS12 .NETCF default to .NET framework 3.9 - targetFrameworkVersion = "v3.9"; + } else if (this->ProjectType == csproj) { + targetFrameworkVersion = + this->GlobalGenerator->GetTargetFrameworkVersion(); } if (this->ProjectType == vcxproj && this->GlobalGenerator->TargetsWindowsCE()) { @@ -527,16 +524,20 @@ void cmVisualStudio10TargetGenerator::Generate() if (cmValue tfId = this->GeneratorTarget->GetProperty( "VS_TARGET_FRAMEWORK_IDENTIFIER")) { targetFrameworkIdentifier = *tfId; - } else { - targetFrameworkIdentifier = "WindowsEmbeddedCompact"; } if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty( "VS_TARGET_FRAMEWORKS_TARGET_VERSION")) { targetFrameworkTargetsVersion = *tfTargetsVer; - } else { - targetFrameworkTargetsVersion = "v8.0"; } } + if (!targetFrameworkIdentifier) { + targetFrameworkIdentifier = + this->GlobalGenerator->GetTargetFrameworkIdentifier(); + } + if (!targetFrameworkTargetsVersion) { + targetFrameworkTargetsVersion = + this->GlobalGenerator->GetTargetFrameworkTargetsVersion(); + } } if (targetFramework) { if (targetFramework->find(';') != std::string::npos) { From d51246c6621aa5025e06fcea720930ae00e6f448 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 3 Nov 2021 14:34:58 -0400 Subject: [PATCH 1458/1519] VS: Default TargetFrameworkVersion to v4.7.2 for VS 2022 MSBuild defaults to v4.0 but VS 2022 does not install it anymore. Explicitly specify a newer framework version by default. Use a version that VS 2022 installs without selecting a separate component. Fixes: #22835 --- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index f27b2c47d3a..b5a6b9fdc69 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -401,6 +401,12 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator( this->DefaultPlatformName = VSHostPlatformName(); this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture(); } + if (this->Version >= cmGlobalVisualStudioGenerator::VS17) { + // FIXME: Search for an existing framework? Under '%ProgramFiles(x86)%', + // see 'Reference Assemblies\Microsoft\Framework\.NETFramework'. + // Use a version installed by VS 2022 without a separate component. + this->DefaultTargetFrameworkVersion = "v4.7.2"; + } } bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( From 76c0281421dae544ae7931309dae376a28d5f877 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 7 Nov 2021 16:09:42 +1100 Subject: [PATCH 1459/1519] Help: Clarify how PKG_CONFIG env var initializes cache vars Fixes: #22870 --- Modules/FindPkgConfig.cmake | 49 +++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 4de5331d4ef..ef43a3ae9fa 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -12,13 +12,24 @@ Finds the ``pkg-config`` executable and adds the :command:`pkg_get_variable`, following variables will also be set: ``PKG_CONFIG_FOUND`` - if pkg-config executable was found + True if a pkg-config executable was found. + +``PKG_CONFIG_VERSION_STRING`` + .. versionadded:: 2.8.8 + + The version of pkg-config that was found. + ``PKG_CONFIG_EXECUTABLE`` - pathname of the pkg-config program + The pathname of the pkg-config program. + ``PKG_CONFIG_ARGN`` - list of arguments to pass to pkg-config -``PKG_CONFIG_VERSION_STRING`` - version of pkg-config (since CMake 2.8.8) + .. versionadded:: 3.22 + + A list of arguments to pass to pkg-config. + +Both ``PKG_CONFIG_EXECUTABLE`` and ``PKG_CONFIG_ARGN`` are initialized by the +module, but may be overridden by the user. See `Variables Affecting Behavior`_ +for how these variables are initialized. #]========================================] @@ -923,24 +934,30 @@ Variables Affecting Behavior .. variable:: PKG_CONFIG_EXECUTABLE - This can be set to the path of the pkg-config executable. If not provided, - it will be set by the module as a result of calling :command:`find_program` - internally. + This cache variable can be set to the path of the pkg-config executable. + :command:`find_program` is called internally by the module with this + variable. .. versionadded:: 3.1 - The ``PKG_CONFIG`` environment variable can be used as a hint. + The ``PKG_CONFIG`` environment variable can be used as a hint if + ``PKG_CONFIG_EXECUTABLE`` has not yet been set. + + .. versionchanged:: 3.22 + If the ``PKG_CONFIG`` environment variable is set, only the first + argument is taken from it when using it as a hint. .. variable:: PKG_CONFIG_ARGN .. versionadded:: 3.22 - This can be set to a list of arguments to additionally pass to pkg-config - if needed. If not provided, it will be an empty string, however, if the - environment variable ``PKG_CONFIG`` is provided, this will be set to the - result of splitting the variable. - - The ``PKG_CONFIG`` environment variable can be used to provide both - ``PKG_CONFIG_EXECUTABLE`` and ``PKG_CONFIG_ARGN`` + This cache variable can be set to a list of arguments to additionally pass + to pkg-config if needed. If not provided, it will be initialized from the + ``PKG_CONFIG`` environment variable, if set. The first argument in that + environment variable is assumed to be the pkg-config program, while all + remaining arguments after that are used to initialize ``PKG_CONFIG_ARGN``. + If no such environment variable is defined, ``PKG_CONFIG_ARGN`` is + initialized to an empty string. The module does not update the variable once + it has been set in the cache. .. variable:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH From 84667a6f3c9331eee6737c88f42fb102f8cd33e3 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 7 Nov 2021 21:31:53 +1100 Subject: [PATCH 1460/1519] Help: Clarify valid versus supported values for CUDA_STANDARD CMake 3.18 added the first support for any compiler for 17 and 20, but those were recognized as valid values in earlier CMake versions even though there was no compiler that supported them. Make this distinction clear to avoid creating the impression that these standards could be usefully used before CMake 3.18. While 98 is recognized as a valid value, it also just gets treated as 03 internally. Document this behavior as well. Fixes: #22711 --- Help/prop_tgt/CUDA_STANDARD.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst index 5ef57be70c2..950ba12e657 100644 --- a/Help/prop_tgt/CUDA_STANDARD.rst +++ b/Help/prop_tgt/CUDA_STANDARD.rst @@ -12,21 +12,27 @@ flag such as ``-std=gnu++11`` to the compile line. Supported values are: ``98`` - CUDA C++98 + CUDA C++98. Note that this maps to the same as ``03`` internally. + +``03`` + CUDA C++03 ``11`` CUDA C++11 ``14`` - CUDA C++14 + CUDA C++14. While CMake 3.8 and later *recognize* ``14`` as a valid value, + CMake 3.9 was the first version to include support for any compiler. ``17`` - CUDA C++17 + CUDA C++17. While CMake 3.8 and later *recognize* ``17`` as a valid value, + CMake 3.18 was the first version to include support for any compiler. ``20`` .. versionadded:: 3.12 - CUDA C++20 + CUDA C++20. While CMake 3.12 and later *recognize* ``20`` as a valid value, + CMake 3.18 was the first version to include support for any compiler. ``23`` .. versionadded:: 3.20 @@ -43,7 +49,7 @@ means that using: with a compiler which does not support ``-std=gnu++11`` or an equivalent flag will not result in an error or warning, but will instead add the -``-std=gnu++98`` flag if supported. This "decay" behavior may be controlled +``-std=gnu++03`` flag if supported. This "decay" behavior may be controlled with the :prop_tgt:`CUDA_STANDARD_REQUIRED` target property. Additionally, the :prop_tgt:`CUDA_EXTENSIONS` target property may be used to control whether compiler-specific extensions are enabled on a per-target basis. From 95fa27d94df39fda5463c6644ff78c364dd4e47f Mon Sep 17 00:00:00 2001 From: Cristian Adam <cristian.adam@gmail.com> Date: Mon, 8 Nov 2021 16:35:43 +0100 Subject: [PATCH 1461/1519] PCH: Fix REUSE_FROM when Debug and RelWithDebInfo configs differ If the Debug configuration contains `/ZI` but the RelWithDebInfo doesn't then the copy_pdb_idb.cmake script will cause problems due to the fact that it was common for both configurations but they are incompatible with each other. --- Source/cmLocalGenerator.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 9b6b9abe1da..468ce5c56e5 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2698,8 +2698,8 @@ void cmLocalGenerator::CopyPchCompilePdb( cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/", target->GetName(), ".dir/"); - const std::string copy_script = - cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake"); + const std::string copy_script = cmStrCat( + target_compile_pdb_dir, "copy_idb_pdb_", config.c_str(), ".cmake"); cmGeneratedFileStream file(copy_script); file << "# CMake generated file\n"; From 244550997f83294d8fd1e91665b87ab6185a3033 Mon Sep 17 00:00:00 2001 From: Cristian Adam <cristian.adam@gmail.com> Date: Mon, 8 Nov 2021 18:16:36 +0100 Subject: [PATCH 1462/1519] PCH: Fixed Ninja Multi-Config and REUSE_FROM for MSVC The copy_idb_pdb.cmake script would be executed for every configuration for all configurations. Debug would still want to get the RelWithDebInfo files, and the other way around. --- Source/cmLocalGenerator.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 9b6b9abe1da..8d03c4412b6 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2754,7 +2754,7 @@ void cmLocalGenerator::CopyPchCompilePdb( bool stdPipesUTF8 = true; auto configGenex = [&](cm::string_view expr) -> std::string { - if (this->GetGlobalGenerator()->IsVisualStudio()) { + if (this->GetGlobalGenerator()->IsMultiConfig()) { return cmStrCat("$<$<CONFIG:", config, ">:", expr, ">"); } return std::string(expr); @@ -2773,8 +2773,8 @@ void cmLocalGenerator::CopyPchCompilePdb( std::vector<std::string> no_byproducts; std::vector<std::string> outputs; - outputs.push_back( - cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb")); + outputs.push_back(configGenex( + cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb"))); if (this->GetGlobalGenerator()->IsVisualStudio()) { this->AddCustomCommandToTarget( From 8371056fbb9b24f4967bbdfd95a64e8fcd44ea0c Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Mon, 8 Nov 2021 21:52:27 +1100 Subject: [PATCH 1463/1519] Help: Correct inaccuracies in wording for CMP0128 --- Help/policy/CMP0128.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Help/policy/CMP0128.rst b/Help/policy/CMP0128.rst index f341f24abf7..b894ce1fd7f 100644 --- a/Help/policy/CMP0128.rst +++ b/Help/policy/CMP0128.rst @@ -6,6 +6,7 @@ CMP0128 When this policy is set to ``NEW``: * :prop_tgt:`<LANG>_EXTENSIONS` is initialized to + :variable:`CMAKE_<LANG>_EXTENSIONS` if set, otherwise falling back to :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. * Extensions are correctly disabled/enabled if :prop_tgt:`<LANG>_STANDARD` is @@ -16,7 +17,8 @@ When this policy is set to ``NEW``: The ``OLD`` behavior: -* Initializes :prop_tgt:`<LANG>_EXTENSIONS` to ``ON``. +* Initializes :prop_tgt:`<LANG>_EXTENSIONS` to + :variable:`CMAKE_<LANG>_EXTENSIONS` if set, otherwise falling back to ``ON``. * Always adds a flag if :prop_tgt:`<LANG>_STANDARD` is set and :prop_tgt:`<LANG>_STANDARD_REQUIRED` is ``OFF``. From 6dc64124770a211b46184ee9834dceaceda19d6c Mon Sep 17 00:00:00 2001 From: Yonggang Luo <luoyonggang@gmail.com> Date: Mon, 8 Nov 2021 14:34:55 +0800 Subject: [PATCH 1464/1519] Help: Use stronger wording in rule about preset inheritance --- Help/manual/presets/schema.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index 767e80b6b16..7852550dcfa 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -124,7 +124,7 @@ }, { "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 may not inherit from presets in CMakeUserPresets.json.", + "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.", @@ -446,7 +446,7 @@ }, { "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 may not inherit from presets in CMakeUserPresets.json.", + "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.", @@ -641,7 +641,7 @@ }, { "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 may not inherit from presets in CMakeUserPresets.json.", + "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.", From 48f29b58053be4edfe4864f5cc6fcfbe6c1000f1 Mon Sep 17 00:00:00 2001 From: "William R. Dieter" <william.r.dieter@intel.com> Date: Fri, 24 Sep 2021 17:31:05 -0700 Subject: [PATCH 1465/1519] IntelLLVM: Use MSVC linker with MSVC frontend variant The Intel compiler (pre-LLVM) expected xilink.exe and had special logic to set xilink.exe. The newer LLVM-based compiler does not want xilink.exe. link.exe works better for host code, and is the default, so change the matching condition such that the old compiler matches (and gets xilink.exe) and the new compiler gets the default link.exe it expects. A better solution will be to use the compiler as the linker. A future change will switch to compiler as linker by default, but that fix needs more validation. Signed-off-by: William R. Dieter <william.r.dieter@intel.com> --- Modules/CMakeFindBinUtils.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 8e9237a870d..f3c2345d445 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -85,7 +85,7 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND list(PREPEND _CMAKE_MT_NAMES "llvm-mt") list(PREPEND _CMAKE_LINKER_NAMES "lld-link") list(APPEND _CMAKE_TOOL_VARS NM) - elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIntel") + elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xIntel") list(PREPEND _CMAKE_AR_NAMES "xilib") list(PREPEND _CMAKE_LINKER_NAMES "xilink") endif() From 220f78e2537ee8e3010097c62f05c159a5cdd377 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 6 Nov 2021 15:35:49 +1100 Subject: [PATCH 1466/1519] TI: Recognize invalid compiler option warning during try_compile() Fixes: #22866 --- Modules/CMakeCheckCompilerFlagCommonPatterns.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake index 05174de83be..bda1d711108 100644 --- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake +++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake @@ -32,5 +32,6 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) FAIL_REGEX "Warning: illegal option" # SunStudio 12 FAIL_REGEX "[Ww]arning: Invalid suboption" # Fujitsu FAIL_REGEX "An invalid option .* appears on the command line" # Cray + FAIL_REGEX "WARNING: invalid compiler option" # TI armcl ) endmacro () From b1edd6e7c7c477059d58868158827d8975d88ca8 Mon Sep 17 00:00:00 2001 From: "William R. Dieter" <william.r.dieter@intel.com> Date: Fri, 5 Nov 2021 22:11:35 -0700 Subject: [PATCH 1467/1519] Fortran: Save frontend variant persistently for IntelLLVM Since commit a90d2a9eed (IntelLLVM: Add support for Intel LLVM-based compilers, 2020-11-02, v3.20.0-rc1~89^2~20), our IntelLLVM compiler support populates `CMAKE_Fortran_COMPILER_FRONTEND_VARIANT`. However, the frontend variant was not stored in `CMakeCompilerFortran.cmake`. Signed-off-by: William R. Dieter <william.r.dieter@intel.com> --- Modules/CMakeFortranCompiler.cmake.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 06ee5286d35..d474f964418 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -5,6 +5,7 @@ set(CMAKE_Fortran_COMPILER_VERSION "@CMAKE_Fortran_COMPILER_VERSION@") set(CMAKE_Fortran_COMPILER_WRAPPER "@CMAKE_Fortran_COMPILER_WRAPPER@") set(CMAKE_Fortran_PLATFORM_ID "@CMAKE_Fortran_PLATFORM_ID@") set(CMAKE_Fortran_SIMULATE_ID "@CMAKE_Fortran_SIMULATE_ID@") +set(CMAKE_Fortran_COMPILER_FRONTEND_VARIANT "@CMAKE_Fortran_COMPILER_FRONTEND_VARIANT@") set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@") @_SET_CMAKE_Fortran_XL_CPP@ @_SET_CMAKE_Fortran_COMPILER_ARCHITECTURE_ID@ From ac32794983dbd84f6e0ed6c8a92268f58b3fed88 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 11 Nov 2021 12:06:48 -0500 Subject: [PATCH 1468/1519] gitlab-ci: Re-organize Windows job tags Name the tag groups based on the VS version needed. --- .gitlab-ci.yml | 6 +++--- .gitlab/os-windows.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 708d80ae8ff..e8284759289 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -728,14 +728,14 @@ build:windows-vs2019-x64-ninja: - .windows_vs2019_x64_ninja - .cmake_build_windows - .cmake_build_artifacts - - .windows_builder_tags + - .windows_tags_nonconcurrent_vs2019 - .run_manually test:windows-vs2019-x64-ninja: extends: - .windows_vs2019_x64_ninja - .cmake_test_windows - - .windows_builder_tags + - .windows_tags_nonconcurrent_vs2019 - .cmake_test_artifacts - .run_dependent dependencies: @@ -747,7 +747,7 @@ test:windows-vs2019-x64: extends: - .windows_vs2019_x64 - .cmake_test_windows_external - - .windows_builder_ext_tags + - .windows_tags_concurrent_vs2019 - .cmake_junit_artifacts - .run_dependent dependencies: diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index 8037b33f5bd..91d62ac6486 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -54,7 +54,7 @@ ## Tags -.windows_builder_tags: +.windows_tags_nonconcurrent_vs2019: tags: - cmake # Since this is a bare runner, pin to a project. - windows @@ -63,7 +63,7 @@ - msvc-19.29-16.11 - nonconcurrent -.windows_builder_ext_tags: +.windows_tags_concurrent_vs2019: tags: - cmake # Since this is a bare runner, pin to a project. - windows From 190d2b5d556a7c90be975ff39993d0bcfb6bf9dc Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 11 Nov 2021 12:11:17 -0500 Subject: [PATCH 1469/1519] gitlab-ci: Update Windows jobs to VS 2022 --- .gitlab-ci.yml | 26 ++++++++--------- ...ake => configure_windows_vs2022_x64.cmake} | 0 ... configure_windows_vs2022_x64_ninja.cmake} | 0 .gitlab/ci/download_qt.cmake | 3 +- .gitlab/os-windows.yml | 28 +++++++++---------- 5 files changed, 29 insertions(+), 28 deletions(-) rename .gitlab/ci/{configure_windows_vs2019_x64.cmake => configure_windows_vs2022_x64.cmake} (100%) rename .gitlab/ci/{configure_windows_vs2019_x64_ninja.cmake => configure_windows_vs2022_x64_ninja.cmake} (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8284759289..79e970ba203 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -723,34 +723,34 @@ build:macos10.10-package: # Windows builds -build:windows-vs2019-x64-ninja: +build:windows-vs2022-x64-ninja: extends: - - .windows_vs2019_x64_ninja + - .windows_vs2022_x64_ninja - .cmake_build_windows - .cmake_build_artifacts - - .windows_tags_nonconcurrent_vs2019 + - .windows_tags_nonconcurrent_vs2022 - .run_manually -test:windows-vs2019-x64-ninja: +test:windows-vs2022-x64-ninja: extends: - - .windows_vs2019_x64_ninja + - .windows_vs2022_x64_ninja - .cmake_test_windows - - .windows_tags_nonconcurrent_vs2019 + - .windows_tags_nonconcurrent_vs2022 - .cmake_test_artifacts - .run_dependent dependencies: - - build:windows-vs2019-x64-ninja + - build:windows-vs2022-x64-ninja needs: - - build:windows-vs2019-x64-ninja + - build:windows-vs2022-x64-ninja -test:windows-vs2019-x64: +test:windows-vs2022-x64: extends: - - .windows_vs2019_x64 + - .windows_vs2022_x64 - .cmake_test_windows_external - - .windows_tags_concurrent_vs2019 + - .windows_tags_concurrent_vs2022 - .cmake_junit_artifacts - .run_dependent dependencies: - - test:windows-vs2019-x64-ninja + - test:windows-vs2022-x64-ninja needs: - - test:windows-vs2019-x64-ninja + - test:windows-vs2022-x64-ninja diff --git a/.gitlab/ci/configure_windows_vs2019_x64.cmake b/.gitlab/ci/configure_windows_vs2022_x64.cmake similarity index 100% rename from .gitlab/ci/configure_windows_vs2019_x64.cmake rename to .gitlab/ci/configure_windows_vs2022_x64.cmake diff --git a/.gitlab/ci/configure_windows_vs2019_x64_ninja.cmake b/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake similarity index 100% rename from .gitlab/ci/configure_windows_vs2019_x64_ninja.cmake rename to .gitlab/ci/configure_windows_vs2022_x64_ninja.cmake diff --git a/.gitlab/ci/download_qt.cmake b/.gitlab/ci/download_qt.cmake index 3990430135e..5940a285e7b 100644 --- a/.gitlab/ci/download_qt.cmake +++ b/.gitlab/ci/download_qt.cmake @@ -18,7 +18,8 @@ if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "windows") set(msvc_year "2015") set(qt_abi "win64_msvc${msvc_year}_64") elseif ("$ENV{CMAKE_CONFIGURATION}" MATCHES "vs2017" OR - "$ENV{CMAKE_CONFIGURATION}" MATCHES "vs2019") + "$ENV{CMAKE_CONFIGURATION}" MATCHES "vs2019" OR + "$ENV{CMAKE_CONFIGURATION}" MATCHES "vs2022") set(qt_platform "windows_x86") set(msvc_year "2019") set(qt_abi "win64_msvc${msvc_year}_64") diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index 91d62ac6486..a1194331bf3 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -31,45 +31,45 @@ CMAKE_CI_BUILD_TYPE: Release CTEST_NO_WARNINGS_ALLOWED: 1 -.windows_vs2019_x64_ninja: +.windows_vs2022_x64_ninja: extends: .windows_ninja variables: - CMAKE_CONFIGURATION: windows_vs2019_x64_ninja - VCVARSALL: "${VS160COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat" + CMAKE_CONFIGURATION: windows_vs2022_x64_ninja + VCVARSALL: "${VS170COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat" VCVARSPLATFORM: "x64" - VCVARSVERSION: "14.29.30133" + VCVARSVERSION: "14.30.30705" ### External testing -.windows_vs2019_x64: +.windows_vs2022_x64: extends: .windows variables: - CMAKE_CONFIGURATION: windows_vs2019_x64 - CMAKE_GENERATOR: "Visual Studio 16 2019" + CMAKE_CONFIGURATION: windows_vs2022_x64 + CMAKE_GENERATOR: "Visual Studio 17 2022" CMAKE_GENERATOR_PLATFORM: "x64" - CMAKE_GENERATOR_TOOLSET: "v142,version=14.29.30133" + CMAKE_GENERATOR_TOOLSET: "v143,version=14.30.30705" CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true" ## Tags -.windows_tags_nonconcurrent_vs2019: +.windows_tags_nonconcurrent_vs2022: tags: - cmake # Since this is a bare runner, pin to a project. - windows - shell - - vs2019 - - msvc-19.29-16.11 + - vs2022 + - msvc-19.30 - nonconcurrent -.windows_tags_concurrent_vs2019: +.windows_tags_concurrent_vs2022: tags: - cmake # Since this is a bare runner, pin to a project. - windows - shell - - vs2019 - - msvc-19.29-16.11 + - vs2022 + - msvc-19.30 - concurrent ## Windows-specific scripts From e47dfce75d74de26ac6ee25625a44989312e29c1 Mon Sep 17 00:00:00 2001 From: Raul Tambre <raul@tambre.ee> Date: Tue, 9 Nov 2021 20:34:06 +0200 Subject: [PATCH 1470/1519] CMP0128: Enable/disable extensions if standard same as default This was intended to be part of the initial MR (!6177), but accidentally went missing when debugging nightly failures on less common systems. Noticed during !6711 review as the comment about this behaviour didn't match the code. Documentation for CMP0128 is updated to remove a false case and note the two cases related to this. Fixes #22224. --- Help/policy/CMP0128.rst | 35 +++++++------------ Source/cmStandardLevelResolver.cxx | 3 +- ...xtensionsStandardDefault-build-check.cmake | 12 +++++++ .../ExtensionsStandardDefault.cmake | 9 +++++ ...ExtensionsStandardUnset-build-check.cmake} | 0 ...rd.cmake => ExtensionsStandardUnset.cmake} | 0 .../CompileFeatures/RunCMakeTest.cmake | 16 ++++++--- 7 files changed, 47 insertions(+), 28 deletions(-) create mode 100644 Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake create mode 100644 Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake rename Tests/RunCMake/CompileFeatures/{UnsetStandard-build-check.cmake => ExtensionsStandardUnset-build-check.cmake} (100%) rename Tests/RunCMake/CompileFeatures/{UnsetStandard.cmake => ExtensionsStandardUnset.cmake} (100%) diff --git a/Help/policy/CMP0128.rst b/Help/policy/CMP0128.rst index b894ce1fd7f..604a146a160 100644 --- a/Help/policy/CMP0128.rst +++ b/Help/policy/CMP0128.rst @@ -9,8 +9,8 @@ When this policy is set to ``NEW``: :variable:`CMAKE_<LANG>_EXTENSIONS` if set, otherwise falling back to :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`. -* Extensions are correctly disabled/enabled if :prop_tgt:`<LANG>_STANDARD` is - unset. +* Extensions are correctly enabled/disabled if :prop_tgt:`<LANG>_STANDARD` is + unset or satisfied by the default. * Standard mode-affecting flags aren't added unless necessary to achieve the specified mode. @@ -33,26 +33,6 @@ The ``OLD`` behavior: Code may need to be updated for the ``NEW`` behavior in the following cases: -* If :prop_tgt:`<LANG>_EXTENSIONS` matches - :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT` or is unset and the compiler's - default satisfies :prop_tgt:`<LANG>_STANDARD` but the compiled code requires - the exact standard specified. - Such code should set :prop_tgt:`<LANG>_STANDARD_REQUIRED` to ``ON``. - - For example: - - .. code-block:: cmake - - cmake_minimum_required(VERSION |release|) - project(example C) - - add_executable(exe main.c) - set_property(TARGET exe PROPERTY C_STANDARD 99) - - If the compiler defaults to C11 then the standard specification for C99 is - satisfied and CMake will pass no flags. ``main.c`` will no longer compile if - it is incompatible with C11. - * If a standard mode flag previously overridden by CMake's and not used during compiler detection now takes effect due to CMake no longer adding one as the default detected is appropriate. @@ -64,6 +44,17 @@ Code may need to be updated for the ``NEW`` behavior in the following cases: * Or ensure the manually-specified flags are used during compiler detection. +* If extensions were disabled without :prop_tgt:`<LANG>_STANDARD` being set + CMake previously wouldn't actually disable extensions. + + Such code should be updated to not disable extensions if they are required. + +* If extensions were enabled/disabled when :prop_tgt:`<LANG>_STANDARD` was + satisfied by the compiler's default CMake previously wouldn't actually + enable/disable extensions. + + Such code should be updated to set the correct extensions mode. + If compiler flags affecting the standard mode are used during compiler detection (for example in :manual:`a toolchain file <cmake-toolchains(7)>` using :variable:`CMAKE_<LANG>_FLAGS_INIT`) then they will affect the detected diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 957f4ca2df0..61416e063fa 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -206,7 +206,8 @@ struct StandardLevelComputer // If the standard requested is older than the compiler's default or the // extension mode doesn't match then we need to use a flag. - if (stdIt < defaultStdIt) { + if (stdIt < defaultStdIt || + (cmp0128 == cmPolicies::NEW && ext != defaultExt)) { auto offset = std::distance(cm::cbegin(stds), stdIt); return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type, "_COMPILE_OPTION"); diff --git a/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake new file mode 100644 index 00000000000..4e85397f4a2 --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake @@ -0,0 +1,12 @@ +foreach(flag @flags@) + string(FIND "${actual_stdout}" "${flag}" position) + + if(NOT position EQUAL -1) + set(found TRUE) + break() + endif() +endforeach() + +if(NOT found) + set(RunCMake_TEST_FAILED "No compile flags from \"@flags@\" found for LANG_STANDARD=default and @lang@_EXTENSIONS=@extensions_opposite@.") +endif() diff --git a/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake new file mode 100644 index 00000000000..32578d1f968 --- /dev/null +++ b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake @@ -0,0 +1,9 @@ +enable_language(@lang@) + +# Make sure the compile command is not hidden. +string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}") +string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}") + +set(CMAKE_@lang@_EXTENSIONS @extensions_opposite@) +set(CMAKE_@lang@_STANDARD @standard_default@) +add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@") diff --git a/Tests/RunCMake/CompileFeatures/UnsetStandard-build-check.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset-build-check.cmake similarity index 100% rename from Tests/RunCMake/CompileFeatures/UnsetStandard-build-check.cmake rename to Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset-build-check.cmake diff --git a/Tests/RunCMake/CompileFeatures/UnsetStandard.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset.cmake similarity index 100% rename from Tests/RunCMake/CompileFeatures/UnsetStandard.cmake rename to Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset.cmake diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake index 3bfd2112a1a..ebd981b3d5f 100644 --- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake @@ -36,7 +36,7 @@ endif() configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt" "${RunCMake_BINARY_DIR}/CMakeLists.txt" COPYONLY) -macro(test_build) +function(test_build) set(test ${name}-${lang}) configure_file("${RunCMake_SOURCE_DIR}/${name}.cmake" "${RunCMake_BINARY_DIR}/${test}.cmake" @ONLY) @@ -52,7 +52,7 @@ macro(test_build) run_cmake(${test}) set(RunCMake_TEST_NO_CLEAN 1) run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . ${ARGN}) -endmacro() +endfunction() # Mangle flags such as they're in verbose build output. macro(mangle_flags variable) @@ -68,7 +68,7 @@ macro(mangle_flags variable) list(APPEND flags "${result}") endmacro() -function(test_unset_standard) +function(test_extensions_opposite) if(extensions_opposite) set(flag_ext "_EXT") endif() @@ -81,9 +81,15 @@ function(test_unset_standard) mangle_flags(flag) - set(name UnsetStandard) + # Make sure we enable/disable extensions when: + # 1. LANG_STANDARD is unset. + set(name ExtensionsStandardUnset) set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0128=NEW) test_build(--verbose) + + # 2. LANG_STANDARD matches CMAKE_LANG_STANDARD_DEFAULT. + set(name ExtensionsStandardDefault) + test_build(--verbose) endfunction() function(test_no_unnecessary_flag) @@ -138,7 +144,7 @@ function(test_lang lang ext) set(extensions_opposite ON) endif() - test_unset_standard() + test_extensions_opposite() test_no_unnecessary_flag() test_cmp0128_warn_match() test_cmp0128_warn_unset() From fed67fa40d7b6e34ee7c8565694bd54af61aed73 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 12 Nov 2021 09:15:07 -0500 Subject: [PATCH 1471/1519] CMake 3.22.0-rc3 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 85791c224fe..49033ebbecb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 22) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 2) +set(CMake_VERSION_RC 3) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From a77bdefa3e966fce5eac0a2a9f44b79207937304 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 13 Nov 2021 20:44:05 +1100 Subject: [PATCH 1472/1519] Help: Add missing version details for Additional Test Measurements --- Help/command/ctest_test.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 4e5484f1c80..2ed890aecd6 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -190,9 +190,10 @@ Check the `CDash test measurement documentation <https://github.com/Kitware/CDash/blob/master/docs/test_measurements.md>`_ for more information on the types of test measurements that CDash recognizes. -Starting in version 3.22, CTest can parse custom measurements from tags named -``<CTestMeasurement>`` or ``<CTestMeasurementFile>``. The older names -``<DartMeasurement>`` and ``<DartMeasurementFile>`` are still supported. +.. versionadded: 3.22 + CTest can parse custom measurements from tags named + ``<CTestMeasurement>`` or ``<CTestMeasurementFile>``. The older names + ``<DartMeasurement>`` and ``<DartMeasurementFile>`` are still supported. The following example demonstrates how to output a variety of custom test measurements. @@ -256,6 +257,8 @@ separate from the interactive comparison UI. Attached Files """""""""""""" +.. versionadded:: 3.21 + The following example demonstrates how to upload non-image files to CDash. .. code-block:: c++ @@ -273,6 +276,8 @@ properties instead. Custom Details """""""""""""" +.. versionadded:: 3.21 + The following example demonstrates how to specify a custom value for the ``Test Details`` field displayed on CDash. @@ -284,6 +289,8 @@ The following example demonstrates how to specify a custom value for the Additional Labels """"""""""""""""" +.. versionadded:: 3.22 + The following example demonstrates how to add additional labels to a test at runtime. From 250acbb09962623565457a85de27d480565e59d3 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sat, 13 Nov 2021 20:45:05 +1100 Subject: [PATCH 1473/1519] Help: Improve cross-referencing of test LABELS and related features --- Help/command/ctest_test.rst | 2 ++ Help/manual/ctest.1.rst | 4 ++++ Help/prop_test/LABELS.rst | 8 ++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 2ed890aecd6..6a9a6a04d8a 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -286,6 +286,8 @@ The following example demonstrates how to specify a custom value for the std::cout << "<CTestDetails>My Custom Details Value</CTestDetails>" << std::endl; +.. _`Additional Labels`: + Additional Labels """"""""""""""""" diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 03d8bf6c805..d66c5a9d587 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -464,6 +464,10 @@ CTest prints timing summary information for each ``LABEL`` and subproject associated with the tests run. The label time summary will not include labels that are mapped to subprojects. +.. versionadded:: 3.22 + Labels added dynamically during test execution are also reported in the + timing summary. See :ref:`Additional Labels`. + When the :prop_test:`PROCESSORS` test property is set, CTest will display a weighted test timing result in label and subproject summaries. The time is reported with `sec*proc` instead of just `sec`. diff --git a/Help/prop_test/LABELS.rst b/Help/prop_test/LABELS.rst index 8d755709596..a06f152747c 100644 --- a/Help/prop_test/LABELS.rst +++ b/Help/prop_test/LABELS.rst @@ -1,6 +1,10 @@ LABELS ------ -Specify a list of text labels associated with a test. +Specify a list of text labels associated with a test. The labels are +reported in both the ``ctest`` output summary and in dashboard submissions. +They can also be used to filter the set of tests to be executed (see the +``ctest -L`` and ``ctest -LE`` :ref:`CTest Options`). -The list is reported in dashboard submissions. +See :ref:`Additional Labels` for adding labels to a test dynamically during +test execution. From 1ef54f3163a5c0835a2e214772d7170c9aeab0b1 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 14 Nov 2021 16:49:23 +1100 Subject: [PATCH 1474/1519] Help: Clarify meaning of filter expression in gtest_discover_tests() --- Modules/GoogleTest.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index a483c0356db..efc33e381b3 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -208,8 +208,11 @@ same as the Google Test name (i.e. ``suite.testcase``); see also ``TEST_FILTER expr`` .. versionadded:: 3.22 - Filter expression to pass to ``--gtest_filter`` argument during test - discovery. + Filter expression to pass as a ``--gtest_filter`` argument during test + discovery. Note that the expression is a wildcard-based format that + matches against the original test names as used by gtest. For type or + value-parameterized tests, these names may be different to the potentially + pretty-printed test names that ``ctest`` uses. ``NO_PRETTY_TYPES`` By default, the type index of type-parameterized tests is replaced by the From 715af43124cbd99656c085cef4c37be1ea0cc7b0 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 14 Nov 2021 17:54:57 +1100 Subject: [PATCH 1475/1519] Tests: Fix and update wrongly named GoogleTest stdout file The GoogleTest-skip-test output was never being checked since this test was added due to this file having the wrong name. --- ...p-timeout-stdout.txt => GoogleTest-skip-test-stdout.txt} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename Tests/RunCMake/GoogleTest/{GoogleTest-skip-timeout-stdout.txt => GoogleTest-skip-test-stdout.txt} (51%) diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-skip-timeout-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt similarity index 51% rename from Tests/RunCMake/GoogleTest/GoogleTest-skip-timeout-stdout.txt rename to Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt index eeecb6a7c28..d06cd0a4d6a 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-skip-timeout-stdout.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt @@ -1,10 +1,10 @@ Test project .* - Start 20: skip_test.test1 -1/1 Test #20: skip_test.test1 \.+\*\*\*Skipped +[0-9.]+ sec + Start 36: skip_test.test1 +1/1 Test #36: skip_test.test1 \.+\*\*\*Skipped +[0-9.]+ sec 100% tests passed, 0 tests failed out of 1 Total Test time \(real\) = +[0-9.]+ sec The following tests did not run: -.*20 - skip_test\.test1 \(Skipped\) +.*36 - skip_test\.test1 \(Skipped\) From 1bf6d5979d7fceae8b8a32129b5816bae459fb96 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 14 Nov 2021 17:22:28 +1100 Subject: [PATCH 1476/1519] gtest_discover_tests: Re-run PRE_TEST discovery on any arg change Fixes: #22912 --- Modules/GoogleTest.cmake | 3 +- ...Test-discovery-arg-change-basic-stdout.txt | 7 +++ ...Test-discovery-arg-change-typed-stdout.txt | 5 ++ .../GoogleTestDiscoveryArgChange.cmake | 14 +++++ Tests/RunCMake/GoogleTest/RunCMakeTest.cmake | 51 +++++++++++++++++++ 5 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt create mode 100644 Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt create mode 100644 Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index a483c0356db..fd144537308 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -513,7 +513,8 @@ function(gtest_discover_tests TARGET) string(CONCAT ctest_include_content "if(EXISTS \"$<TARGET_FILE:${TARGET}>\")" "\n" " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n" - " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\")" "\n" + " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\" OR\n" + " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"\${CMAKE_CURRENT_LIST_FILE}\")\n" " include(\"${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}\")" "\n" " gtest_discover_tests_impl(" "\n" " TEST_EXECUTABLE" " [==[" "$<TARGET_FILE:${TARGET}>" "]==]" "\n" diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt new file mode 100644 index 00000000000..385159d65a3 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change + Test #1: basic\.case_foo + Test #2: basic\.case_bar + Test #3: basic\.disabled_case \(Disabled\) + Test #4: basic\.DISABLEDnot_really_case + +Total Tests: 4 diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt new file mode 100644 index 00000000000..095fdcded8a --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt @@ -0,0 +1,5 @@ +Test project .*/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change + Test #1: typed/short\.case + Test #2: typed/float\.case + +Total Tests: 2 diff --git a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake new file mode 100644 index 00000000000..e4e13c5f7ee --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake @@ -0,0 +1,14 @@ +enable_language(CXX) +include(GoogleTest) + +enable_testing() + +include(xcode_sign_adhoc.cmake) + +add_executable(fake_gtest fake_gtest.cpp) +xcode_sign_adhoc(fake_gtest) + +gtest_discover_tests( + fake_gtest + TEST_FILTER "${TEST_FILTER}*" +) diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake index c5c592507f2..33a4b4353da 100644 --- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake @@ -1,5 +1,12 @@ include(RunCMake) +if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR + RunCMake_GENERATOR STREQUAL "Watcom WMake") + set(fs_delay 3) +else() + set(fs_delay 1.125) +endif() + function(run_GoogleTest DISCOVERY_MODE) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-build) @@ -153,6 +160,46 @@ function(run_GoogleTest_discovery_timeout DISCOVERY_MODE) ) endfunction() +function(run_GoogleTest_discovery_arg_change DISCOVERY_MODE) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-arg-change) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake_with_options(GoogleTestDiscoveryArgChange + -DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=${DISCOVERY_MODE} + -DTEST_FILTER=basic + ) + run_cmake_command(GoogleTest-discovery-arg-change-build + ${CMAKE_COMMAND} + --build . + --config Release + --target fake_gtest + ) + run_cmake_command(GoogleTest-discovery-arg-change-basic + ${CMAKE_CTEST_COMMAND} + -C Release + -N + ) + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay}) # handle 1s resolution + run_cmake_with_options(GoogleTestDiscoveryArgChange + -DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=${DISCOVERY_MODE} + -DTEST_FILTER=typed + ) + run_cmake_command(GoogleTest-discovery-arg-change-build + ${CMAKE_COMMAND} + --build . + --config Release + --target fake_gtest + ) + run_cmake_command(GoogleTest-discovery-arg-change-typed + ${CMAKE_CTEST_COMMAND} + -C Release + -N + ) +endfunction() + function(run_GoogleTest_discovery_multi_config) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-multi-config) @@ -195,6 +242,10 @@ foreach(DISCOVERY_MODE POST_BUILD PRE_TEST) run_GoogleTestXML(${DISCOVERY_MODE}) message("Testing ${DISCOVERY_MODE} discovery mode via DISCOVERY_MODE option...") run_GoogleTest_discovery_timeout(${DISCOVERY_MODE}) + if(# VS 9 does not rebuild if POST_BUILD command changes. + NOT "${DISCOVERY_MODE};${RunCMake_GENERATOR}" MATCHES "^POST_BUILD;Visual Studio 9") + run_GoogleTest_discovery_arg_change(${DISCOVERY_MODE}) + endif() endforeach() if(RunCMake_GENERATOR_IS_MULTI_CONFIG) From acc14edd70707ed040a8ea12afd363018df7d2fc Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 16 Nov 2021 11:57:45 -0500 Subject: [PATCH 1477/1519] libuv: Backport MinGW-w64 compilation fix to CMake 3.22 branch Backport libuv commit `3e90bc76` (build: fix build failures with MinGW new headers, 2021-11-03). Fixes: #22916 --- Utilities/cmlibuv/include/uv/win.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Utilities/cmlibuv/include/uv/win.h b/Utilities/cmlibuv/include/uv/win.h index f86357b4edf..9b5d5dc63a6 100644 --- a/Utilities/cmlibuv/include/uv/win.h +++ b/Utilities/cmlibuv/include/uv/win.h @@ -45,7 +45,14 @@ typedef struct pollfd { #endif #include <mswsock.h> +// Disable the typedef in mstcpip.h of MinGW. +#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__AVOID +#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__AVOID +#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__AVOID #include <ws2tcpip.h> +#undef _TCP_INITIAL_RTO_PARAMETERS +#undef TCP_INITIAL_RTO_PARAMETERS +#undef PTCP_INITIAL_RTO_PARAMETERS #include <windows.h> #include <process.h> From 209b896f2c5e7c12e5a75a572469517a298081b2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 17 Nov 2021 10:35:12 -0500 Subject: [PATCH 1478/1519] IntelLLVM: Enable Fortran module rebuild avoidance in Makefile generators The Makefile generators use an internal `cmake -E cmake_copy_f90_mod` tool to avoid rebuilding module consumers when the `.mod` content changes only in a trivial way (e.g. the time it was built). This is done with logic specific to each vendor's module file format. Enable the "Intel" format support when using the IntelLLVM compiler (ifx) too. Issue: #22922 --- Source/cmDependsFortran.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 1a06f317062..74b5ddd3d5e 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -653,7 +653,7 @@ bool cmDependsFortran::ModulesDiffer(const std::string& modFile, return true; } } - } else if (compilerId == "Intel") { + } else if (compilerId == "Intel" || compilerId == "IntelLLVM") { const char seq[2] = { '\n', '\0' }; const int seqlen = 2; From f0eae9292baa9932e6c5eb8d95b7552c291cfeb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antons=20Je=C4=BCkins?= <Antons.Jelkins@bmw.de> Date: Tue, 16 Nov 2021 18:34:48 +0100 Subject: [PATCH 1479/1519] cmTimestamp: Declare component buffer before MinGW-specific code --- Source/cmTimestamp.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index cfea4cff2f9..9125d7eea15 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -192,6 +192,8 @@ std::string cmTimestamp::AddTimestampComponent(char flag, } } + char buffer[16]; + #ifdef __MINGW32__ /* See a bug in MinGW: https://sourceforge.net/p/mingw-w64/bugs/793/. A work * around is to try to use strftime() from ucrtbase.dll. */ @@ -210,8 +212,6 @@ std::string cmTimestamp::AddTimestampComponent(char flag, static T strftime = loadStrftime(); #endif - char buffer[16]; - size_t size = strftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct); From 26c9fbab4618d53f49f92ff3a000951a1d9b9fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antons=20Je=C4=BCkins?= <Antons.Jelkins@bmw.de> Date: Tue, 16 Nov 2021 18:34:48 +0100 Subject: [PATCH 1480/1519] MINGW-w64: Fix string(TIMESTAMP) build on 32bits. Rephrase the string(TIMESTAMP) implementation not to cause gcc-11 ICE on MSYS2/mingw32. Fixes: #22916 --- Source/cmTimestamp.cxx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 9125d7eea15..c8f5a4b2225 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -198,7 +198,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag, /* See a bug in MinGW: https://sourceforge.net/p/mingw-w64/bugs/793/. A work * around is to try to use strftime() from ucrtbase.dll. */ using T = size_t(WINAPI*)(char*, size_t, const char*, const struct tm*); - auto loadStrftime = [] { + auto loadUcrtStrftime = []() -> T { auto handle = LoadLibraryExA("ucrtbase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); if (handle) { @@ -207,9 +207,15 @@ std::string cmTimestamp::AddTimestampComponent(char flag, return reinterpret_cast<T>(GetProcAddress(handle, "strftime")); # pragma GCC diagnostic pop } - return strftime; + return nullptr; }; - static T strftime = loadStrftime(); + static T ucrtStrftime = loadUcrtStrftime(); + + if (ucrtStrftime) { + size_t size = + ucrtStrftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct); + return std::string(buffer, size); + } #endif size_t size = From ff8c3acc0fbe037931680fc74b1a2d3f0af58c79 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 18 Nov 2021 10:51:22 -0500 Subject: [PATCH 1481/1519] CMake 3.22.0 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 49033ebbecb..3d999e7ca18 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,7 +2,7 @@ set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 22) set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 3) +#set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. From fae34ea00717a0d4368b0f1953237e7f7bdba3d5 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 18 Nov 2021 12:54:14 -0500 Subject: [PATCH 1482/1519] ci: add gmock to Debian base images It is already in the Fedora base images. --- .gitlab/ci/docker/debian10-aarch64/install_deps.sh | 1 + .gitlab/ci/docker/debian10/install_deps.sh | 1 + .gitlab/os-linux.yml | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh index d7f4f9c8f85..d5c5e22f544 100755 --- a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh +++ b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh @@ -52,6 +52,7 @@ apt-get install -y \ libgif-dev \ libgl1-mesa-dev \ libglew-dev \ + libgmock-dev \ libgrpc++-dev libgrpc-dev \ libgsl-dev \ libgtest-dev \ diff --git a/.gitlab/ci/docker/debian10/install_deps.sh b/.gitlab/ci/docker/debian10/install_deps.sh index b4d0f8676b5..d3d6b672400 100755 --- a/.gitlab/ci/docker/debian10/install_deps.sh +++ b/.gitlab/ci/docker/debian10/install_deps.sh @@ -52,6 +52,7 @@ apt-get install -y \ libgif-dev \ libgl1-mesa-dev \ libglew-dev \ + libgmock-dev \ libgrpc++-dev libgrpc-dev \ libgsl-dev \ libgtest-dev \ diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 7fce1770daa..ff23ac919b2 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -45,7 +45,7 @@ ### Debian .debian10: - image: "kitware/cmake:ci-debian10-x86_64-2021-10-05" + image: "kitware/cmake:ci-debian10-x86_64-2021-11-18" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -60,7 +60,7 @@ CMake_SKIP_INSTALL: 1 .debian10_aarch64: - image: "kitware/cmake:ci-debian10-aarch64-2021-10-05" + image: "kitware/cmake:ci-debian10-aarch64-2021-11-18" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" From 7224eb5185f6cbd3ce244e8ea5f6ec89d5a517f9 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Fri, 19 Nov 2021 17:42:39 +0100 Subject: [PATCH 1483/1519] UseSWIG: ensure directory for depfile exists When `Visual Studio` and `Xcode` generators are used, directory for depfile is not implicitely created by CMake when OUTFILE_DIR option is used. Fixes: #22932 --- Modules/UseSWIG.cmake | 2 +- Tests/UseSWIG/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 5c8f152bb7e..b48c33ce323 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -676,7 +676,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) ${swig_custom_products} ${swig_cleanup_command} # Let's create the ${outdir} at execution time, in case dir contains $(OutDir) - COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir} + COMMAND "${CMAKE_COMMAND}" -E make_directory "${workingdir}" "${outdir}" "${outfiledir}" ${swig_timestamp_command} COMMAND "${CMAKE_COMMAND}" -E env "SWIG_LIB=${SWIG_DIR}" "${SWIG_EXECUTABLE}" "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" diff --git a/Tests/UseSWIG/CMakeLists.txt b/Tests/UseSWIG/CMakeLists.txt index f1b2f321484..6c0d5e483a2 100644 --- a/Tests/UseSWIG/CMakeLists.txt +++ b/Tests/UseSWIG/CMakeLists.txt @@ -76,6 +76,7 @@ if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2" ${build_generator_args} --build-project TestBasicPython --build-options ${build_options} -DSWIG_USE_SWIG_DEPENDENCIES=ON + "-DSWIG_OUTFILE_DIR=${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPython.Depfile" --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) add_test(NAME UseSWIG.Depfile.BasicPerl COMMAND From 71a2c9d31bd906ef85ef0283a228b64c70707ee6 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 21 Nov 2021 17:50:29 +1100 Subject: [PATCH 1484/1519] Help: ENVIRONMENT_MODIFICATION path_list_... separator is based on host Fixes: #22937 --- Help/prop_test/ENVIRONMENT_MODIFICATION.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst index 0b3cd83a4a1..1e17329344c 100644 --- a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst +++ b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst @@ -21,9 +21,11 @@ order specified in the property's value. The ``OP`` may be one of: - ``string_append``: Appends ``VALUE`` to the current value of ``MYVAR``. - ``string_prepend``: Prepends ``VALUE`` to the current value of ``MYVAR``. - ``path_list_append``: Appends ``VALUE`` to the current value of ``MYVAR`` - using the platform-specific list separator. + using the host platform's path list separator (``;`` on Windows and ``:`` + elsewhere). - ``path_list_prepend``: Prepends ``VALUE`` to the current value of - ``MYVAR`` using the platform-specific list separator. + ``MYVAR`` using the host platform's path list separator (``;`` on Windows + and ``:`` elsewhere). - ``cmake_list_append``: Appends ``VALUE`` to the current value of ``MYVAR`` using ``;`` as the separator. - ``cmake_list_prepend``: Prepends ``VALUE`` to the current value of From 5b1ed2a64650405127d434f6267fb10baf1401d4 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 22 Nov 2021 12:19:03 -0500 Subject: [PATCH 1485/1519] try_compile: Do not use CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES env vars Since: * commit e216b9bbd3 (cmake: Allow CMAKE_BUILD_TYPE to be set by environment variable, 2021-06-29, v3.22.0-rc1~503^2~1) * commit ef56eefc9b (cmake: Allow CMAKE_CONFIGURATION_TYPES to be set by environment variable, 2021-06-29, v3.22.0-rc1~503^2) the environment variables are supposed to provide defaults for settings the user otherwise can control via cache entries. However, they accidentally affect `try_compile` projects too, which are supposed to be programmatically controlled. Fixes: #22935 --- Source/cmGlobalGenerator.cxx | 3 ++- Source/cmMakefile.cxx | 3 ++- Tests/RunCMake/try_compile/EnvConfig.c | 7 +++++++ Tests/RunCMake/try_compile/EnvConfig.cmake | 18 ++++++++++++++++++ Tests/RunCMake/try_compile/RunCMakeTest.cmake | 2 ++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/try_compile/EnvConfig.c create mode 100644 Tests/RunCMake/try_compile/EnvConfig.cmake diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 9914902eff3..97ad7ab553d 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -498,7 +498,8 @@ bool cmGlobalGenerator::CheckLanguages( void cmGlobalGenerator::EnableLanguage( std::vector<std::string> const& languages, cmMakefile* mf, bool optional) { - if (!this->IsMultiConfig()) { + if (!this->IsMultiConfig() && + !this->GetCMakeInstance()->GetIsInTryCompile()) { std::string envBuildType; if (!mf->GetDefinition("CMAKE_BUILD_TYPE") && cmSystemTools::GetEnv("CMAKE_BUILD_TYPE", envBuildType)) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 83984f7a300..88f3cc7b1ff 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3167,7 +3167,8 @@ void cmMakefile::InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault) return; } std::string initConfigs; - if (!cmSystemTools::GetEnv("CMAKE_CONFIGURATION_TYPES", initConfigs)) { + if (this->GetCMakeInstance()->GetIsInTryCompile() || + !cmSystemTools::GetEnv("CMAKE_CONFIGURATION_TYPES", initConfigs)) { initConfigs = genDefault; } this->AddCacheDefinition( diff --git a/Tests/RunCMake/try_compile/EnvConfig.c b/Tests/RunCMake/try_compile/EnvConfig.c new file mode 100644 index 00000000000..5b1d4005200 --- /dev/null +++ b/Tests/RunCMake/try_compile/EnvConfig.c @@ -0,0 +1,7 @@ +#ifdef TC_CONFIG_BAD +# error "Built in 'Bad' config" +#endif +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/try_compile/EnvConfig.cmake b/Tests/RunCMake/try_compile/EnvConfig.cmake new file mode 100644 index 00000000000..4040c593d2b --- /dev/null +++ b/Tests/RunCMake/try_compile/EnvConfig.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +set(ENV{CMAKE_BUILD_TYPE} "Bad") +set(ENV{CMAKE_CONFIGURATION_TYPES} "Bad;Debug") + +add_library(tc_defs INTERFACE IMPORTED) +target_compile_definitions(tc_defs INTERFACE "TC_CONFIG_$<UPPER_CASE:$<CONFIG>>") + +try_compile(ENV_CONFIG_RESULT "${CMAKE_BINARY_DIR}" + SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/EnvConfig.c" + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/EnvConfig.bin" + OUTPUT_VARIABLE tc_output + LINK_LIBRARIES tc_defs + ) +if(NOT ENV_CONFIG_RESULT) + string(REPLACE "\n" "\n " tc_output " ${tc_output}") + message(FATAL_ERROR "try_compile failed:\n${tc_output}") +endif() diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index fffb0381963..b19fd0ee991 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -16,6 +16,8 @@ run_cmake(BadSources2) run_cmake(NonSourceCopyFile) run_cmake(NonSourceCompileDefinitions) +run_cmake(EnvConfig) + set(RunCMake_TEST_OPTIONS --debug-trycompile) run_cmake(PlatformVariables) run_cmake(WarnDeprecated) From c44636a89b93c6c024d8aa318f932beec0453db4 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 22 Nov 2021 14:48:20 -0500 Subject: [PATCH 1486/1519] Help: Document more use cases for CMAKE_POLICY_DEFAULT_CMPNNNN --- .../variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst index 43582be94d0..d643fb8df1b 100644 --- a/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst +++ b/Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst @@ -9,9 +9,16 @@ the given version unset. Set ``CMAKE_POLICY_DEFAULT_CMP<NNNN>`` to ``OLD`` or ``NEW`` to specify the default for policy ``CMP<NNNN>``, where ``<NNNN>`` is the policy number. -This variable should not be set by a project in CMake code; use -:command:`cmake_policy(SET)` instead. Users running CMake may set this -variable in the cache (e.g. ``-DCMAKE_POLICY_DEFAULT_CMP<NNNN>=<OLD|NEW>``) -to set a policy not otherwise set by the project. Set to ``OLD`` to quiet a -policy warning while using old behavior or to ``NEW`` to try building the -project with new behavior. +This variable should not be set by a project in CMake code as a way to +set its own policies; use :command:`cmake_policy(SET)` instead. This +variable is meant to externally set policies for which a project has +not itself been updated: + +* Users running CMake may set this variable in the cache + (e.g. ``-DCMAKE_POLICY_DEFAULT_CMP<NNNN>=<OLD|NEW>``). Set it to ``OLD`` + to quiet a policy warning while using old behavior or to ``NEW`` to + try building the project with new behavior. + +* Projects may set this variable before a call to :command:`add_subdirectory` + that adds a third-party project in order to set its policies without + modifying third-party code. From 5b1c24255f3ca2404134d2fd9270d2edc0801bdd Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 22 Nov 2021 14:48:36 -0500 Subject: [PATCH 1487/1519] Help: Suggest CMAKE_POLICY_DEFAULT_CMP0077 in CMP0077 docs Issue: #20490 --- Help/policy/CMP0077.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Help/policy/CMP0077.rst b/Help/policy/CMP0077.rst index d8744a9458b..482125a7947 100644 --- a/Help/policy/CMP0077.rst +++ b/Help/policy/CMP0077.rst @@ -53,6 +53,8 @@ between the two policies. This policy was introduced in CMake version 3.13. CMake version |release| warns when the policy is not set and uses ``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` -explicitly. +explicitly within a project. Use the :variable:`CMAKE_POLICY_DEFAULT_CMP0077 +<CMAKE_POLICY_DEFAULT_CMP\<NNNN\>>` variable to set the policy for +a third-party project in a subdirectory without modifying it. .. include:: DEPRECATED.txt From 69b70968bd1a90eaf41c55b61604874cfebfd345 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 22 Nov 2021 14:57:04 -0500 Subject: [PATCH 1488/1519] Help: Suggest CMAKE_POLICY_DEFAULT_CMP0126 in CMP0126 docs --- Help/policy/CMP0126.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Help/policy/CMP0126.rst b/Help/policy/CMP0126.rst index ba027b3514d..1b6995762dd 100644 --- a/Help/policy/CMP0126.rst +++ b/Help/policy/CMP0126.rst @@ -22,7 +22,10 @@ will *not* set the cache variable if a non-cache variable of the same name already exists and :policy:`CMP0077` is set to ``NEW``. Policy ``CMP0126`` was introduced in CMake version 3.21. Use the -:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly +within a project. Use the :variable:`CMAKE_POLICY_DEFAULT_CMP0126 +<CMAKE_POLICY_DEFAULT_CMP\<NNNN\>>` variable to set the policy for +a third-party project in a subdirectory without modifying it. Unlike many policies, CMake version |release| does *not* warn when the policy is not set and simply uses ``OLD`` behavior. See documentation of the :variable:`CMAKE_POLICY_WARNING_CMP0126 <CMAKE_POLICY_WARNING_CMP<NNNN>>` From 224d81e804c38d0f1041e20ab9bd9912ba0ec32f Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 22 Nov 2021 18:04:43 -0500 Subject: [PATCH 1489/1519] gitlab-ci: update macOS jobs to use Xcode 13.1 --- .gitlab/os-macos.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab/os-macos.yml b/.gitlab/os-macos.yml index b79d46d7766..c3a1c25d3e1 100644 --- a/.gitlab/os-macos.yml +++ b/.gitlab/os-macos.yml @@ -7,7 +7,7 @@ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci ext/$CI_CONCURRENT_ID" # TODO: Factor this out so that each job selects the Xcode version to # use so that different versions can be tested in a single pipeline. - DEVELOPER_DIR: "/Applications/Xcode-13.0.app/Contents/Developer" + DEVELOPER_DIR: "/Applications/Xcode-13.1.app/Contents/Developer" # Avoid conflicting with other projects running on the same machine. SCCACHE_SERVER_PORT: 4227 @@ -87,7 +87,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-13.0 + - xcode-13.1 - nonconcurrent .macos_x86_64_builder_tags_package: @@ -95,7 +95,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-13.0 + - xcode-13.1 - nonconcurrent - finder @@ -104,7 +104,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos - shell - - xcode-13.0 + - xcode-13.1 - concurrent .macos_arm64_builder_tags: @@ -112,7 +112,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos-arm64 - shell - - xcode-13.0 + - xcode-13.1 - nonconcurrent .macos_arm64_builder_ext_tags: @@ -120,7 +120,7 @@ - cmake # Since this is a bare runner, pin to a project. - macos-arm64 - shell - - xcode-13.0 + - xcode-13.1 - concurrent ## macOS-specific scripts From 0fc8b2f61cf36b7fcc2524028aabc35ba8b8bad9 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 23 Nov 2021 10:00:31 -0500 Subject: [PATCH 1490/1519] CompilerId: Restore support for classic C by avoiding C++ style comments C++ style comments were added by commit fc3a1cbdd8 (CompilerID: Compiler extensions default detection, 2021-05-29, v3.22.0-rc1~52^2~2), but they may not be supported by the default mode of some C compilers. Use C-style comments instead. For consistency, do this for all languages. Fixes: #22942 --- Modules/CMakeCCompilerId.c.in | 2 +- Modules/CMakeCUDACompilerId.cu.in | 2 +- Modules/CMakeCXXCompilerId.cpp.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index 43ede3e8a8d..30ad9824eed 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -60,7 +60,7 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" C_VERSION "]"; const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ #if (defined(__clang__) || defined(__GNUC__) || \ defined(__TI_COMPILER_VERSION__)) && \ !defined(__STRICT_ANSI__) && !defined(_MSC_VER) diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in index bc685a7eb80..becb9b4cb41 100644 --- a/Modules/CMakeCUDACompilerId.cu.in +++ b/Modules/CMakeCUDACompilerId.cu.in @@ -33,7 +33,7 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" "]"; const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ #if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__) && \ !defined(_MSC_VER) "ON" diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index cdf9c1828aa..e7a54874264 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -66,7 +66,7 @@ const char* info_language_standard_default = "INFO" ":" "standard_default[" "]"; const char* info_language_extensions_default = "INFO" ":" "extensions_default[" -// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ #if (defined(__clang__) || defined(__GNUC__) || \ defined(__TI_COMPILER_VERSION__)) && \ !defined(__STRICT_ANSI__) && !defined(_MSC_VER) From cfa478e518049b6297ac874b1cf147d857e6ba7b Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Mon, 22 Nov 2021 12:58:07 -0500 Subject: [PATCH 1491/1519] gitlab-ci: fix comment typo --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 79e970ba203..296013f3a9c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,5 @@ include: - # Metadata shared my many jobs + # Metadata shared by many jobs - local: .gitlab/rules.yml - local: .gitlab/artifacts.yml From 7d5828e2933182e4bcd03fd32ad5cc4403b93694 Mon Sep 17 00:00:00 2001 From: Ben Boeckel <ben.boeckel@kitware.com> Date: Fri, 19 Nov 2021 20:29:13 -0500 Subject: [PATCH 1492/1519] gitlab-ci: shorten job prefixes This helps to maximize the amount of information visible in the GitLab web interface. Also document their meaning in the developer documentation and in the CI configuration file directly. See: https://gitlab.com/gitlab-org/gitlab/-/issues/8496 --- .gitlab-ci.yml | 249 ++++++++++++++++++++++--------------------- .gitlab/os-linux.yml | 8 +- Help/dev/maint.rst | 6 +- Help/dev/review.rst | 13 +++ 4 files changed, 148 insertions(+), 128 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 296013f3a9c..06570d91beb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,9 +34,16 @@ stages: # - dependency/needs jobs for required jobs ################################################################################ +# Job prefixes: +# - `b:` build +# - `l:` lint +# - `p:` prep +# - `t:` test +# - `u:` upload + # Prep jobs -prep:source-package: +p:source-package: extends: - .linux_prep_source - .cmake_prep_source_linux @@ -44,7 +51,7 @@ prep:source-package: - .cmake_release_artifacts - .run_only_for_package -prep:doc-package: +p:doc-package: extends: - .fedora34_sphinx_package - .cmake_prep_doc_linux @@ -52,74 +59,74 @@ prep:doc-package: - .cmake_doc_artifacts - .run_only_for_package -.upload:source-package: +.u:source-package: extends: - .rsync_upload_binary - .run_only_for_package dependencies: - - prep:source-package + - p:source-package needs: - - prep:source-package + - p:source-package variables: RSYNC_DESTINATION: dev # Documentation builds -build:help:master: +b:help:master: extends: - .cmake_org_help - .run_only_for_continuous_master -.upload:help:master: +.u:help:master: extends: - .rsync_upload_help - .run_only_for_continuous_master variables: RSYNC_DESTINATION: git-master dependencies: - - build:help:master + - b:help:master needs: - - build:help:master + - b:help:master -build:help:stage: +b:help:stage: extends: - .cmake_org_help - .run_only_for_continuous_stage -.upload:help:stage: +.u:help:stage: extends: - .rsync_upload_help - .run_only_for_continuous_stage variables: RSYNC_DESTINATION: git-stage dependencies: - - build:help:stage + - b:help:stage needs: - - build:help:stage + - b:help:stage # Lint builds -lint:codespell: +l:codespell: extends: - .cmake_codespell_linux - .linux_builder_tags - .run_automatically -lint:debian10-iwyu: +l:iwyu-debian10: extends: - .debian10_iwyu - .cmake_build_linux - .linux_builder_tags - .run_automatically -lint:fedora34-tidy: +l:tidy-fedora34: extends: - .fedora34_tidy - .cmake_build_linux - .linux_builder_tags_qt - .run_automatically -lint:fedora34-sphinx: +l:sphinx-fedora34: extends: - .fedora34_sphinx - .cmake_build_linux @@ -129,7 +136,7 @@ lint:fedora34-sphinx: CMAKE_CI_JOB_CONTINUOUS: "true" CMAKE_CI_JOB_HELP: "true" -lint:fedora34-clang-analyzer: +l:clang-analyzer-fedora34: extends: - .fedora34_clang_analyzer - .cmake_build_linux @@ -140,7 +147,7 @@ lint:fedora34-clang-analyzer: # Linux builds -build:centos6-x86_64: +b:centos6-x86_64: extends: - .linux_release_x86_64 - .cmake_build_linux_release @@ -148,7 +155,7 @@ build:centos6-x86_64: - .linux_builder_tags - .run_manually -build:centos7-aarch64: +b:centos7-aarch64: extends: - .linux_release_aarch64 - .cmake_build_linux_release @@ -158,7 +165,7 @@ build:centos7-aarch64: variables: CMAKE_CI_NO_MR: "true" -test:debian10-ninja: +t:debian10-ninja: extends: - .debian10_ninja - .cmake_test_linux_release @@ -169,7 +176,7 @@ test:debian10-ninja: variables: CMAKE_CI_JOB_NIGHTLY_NINJA: "true" -test:debian10-aarch64-ninja: +t:debian10-aarch64-ninja: extends: - .debian10_aarch64_ninja - .cmake_test_linux_release @@ -180,7 +187,7 @@ test:debian10-aarch64-ninja: variables: CMAKE_CI_NO_MR: "true" -test:debian10-ninja-clang: +t:debian10-ninja-clang: extends: - .debian10_ninja_clang - .cmake_test_linux_release @@ -190,7 +197,7 @@ test:debian10-ninja-clang: variables: CMAKE_CI_JOB_NIGHTLY: "true" -test:debian10-makefiles-clang: +t:debian10-makefiles-clang: extends: - .debian10_makefiles_clang - .cmake_test_linux_release @@ -200,7 +207,7 @@ test:debian10-makefiles-clang: variables: CMAKE_CI_JOB_NIGHTLY: "true" -test:fedora34-makefiles: +t:fedora34-makefiles: extends: - .fedora34_makefiles - .cmake_test_linux_release @@ -208,7 +215,7 @@ test:fedora34-makefiles: - .run_dependent - .needs_centos6_x86_64 -test:fedora34-makefiles-nospace: +t:fedora34-makefiles-nospace: extends: - .fedora34_makefiles - .cmake_test_linux_release @@ -221,7 +228,7 @@ test:fedora34-makefiles-nospace: CMAKE_CI_BUILD_NAME: fedora34_makefiles_nospace CMAKE_CI_JOB_NIGHTLY: "true" -test:cuda9.2-nvidia: +t:cuda9.2-nvidia: extends: - .cuda9.2_nvidia - .cmake_test_linux_release @@ -231,7 +238,7 @@ test:cuda9.2-nvidia: variables: CMAKE_CI_JOB_NIGHTLY: "true" -test:cuda10.2-nvidia: +t:cuda10.2-nvidia: extends: - .cuda10.2_nvidia - .cmake_test_linux_release @@ -240,7 +247,7 @@ test:cuda10.2-nvidia: - .run_dependent - .needs_centos6_x86_64 -test:cuda10.2-clang: +t:cuda10.2-clang: extends: - .cuda10.2_clang - .cmake_test_linux_release @@ -250,7 +257,7 @@ test:cuda10.2-clang: variables: CMAKE_CI_JOB_NIGHTLY: "true" -test:hip4.2-radeon: +t:hip4.2-radeon: extends: - .hip4.2_radeon - .cmake_test_linux_release @@ -260,7 +267,7 @@ test:hip4.2-radeon: variables: CMAKE_CI_JOB_NIGHTLY: "true" -build:fedora34-ninja: +b:fedora34-ninja: extends: - .fedora34_ninja - .cmake_build_linux @@ -268,7 +275,7 @@ build:fedora34-ninja: - .linux_builder_tags_qt - .run_manually -test:fedora34-ninja: +t:fedora34-ninja: extends: - .fedora34_ninja - .cmake_test_linux @@ -276,11 +283,11 @@ test:fedora34-ninja: - .cmake_test_artifacts - .run_dependent dependencies: - - build:fedora34-ninja + - b:fedora34-ninja needs: - - build:fedora34-ninja + - b:fedora34-ninja -test:fedora34-ninja-multi: +t:fedora34-ninja-multi: extends: - .fedora34_ninja_multi - .cmake_test_linux_external @@ -288,228 +295,228 @@ test:fedora34-ninja-multi: - .cmake_junit_artifacts - .run_dependent dependencies: - - test:fedora34-ninja + - t:fedora34-ninja needs: - - test:fedora34-ninja + - t:fedora34-ninja -test:intel2016-makefiles: +t:intel2016-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2016_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016-el7 -test:intel2016u1-makefiles: +t:intel2016u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2016u1_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u1-el7 -test:intel2016u2-makefiles: +t:intel2016u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2016u2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2016u2-el7 -test:intel2017-makefiles: +t:intel2017-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017-el7 -test:intel2017u1-makefiles: +t:intel2017u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u1_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u1-el7 -test:intel2017u2-makefiles: +t:intel2017u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u2-el7 -test:intel2017u3-makefiles: +t:intel2017u3-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u3_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u3-el7 -test:intel2017u4-makefiles: +t:intel2017u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u4_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u4-el7 -test:intel2017u5-makefiles: +t:intel2017u5-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u5_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u5-el7 -test:intel2017u6-makefiles: +t:intel2017u6-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u6_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u6-el7 -test:intel2017u7-makefiles: +t:intel2017u7-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u7_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u7-el7 -test:intel2017u8-makefiles: +t:intel2017u8-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2017u8_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2017u8-el7 -test:intel2018-makefiles: +t:intel2018-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018-el7 -test:intel2018u1-makefiles: +t:intel2018u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u1_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u1-el7 -test:intel2018u2-makefiles: +t:intel2018u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u2-el7 -test:intel2018u3-makefiles: +t:intel2018u3-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u3_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u3-el7 -test:intel2018u4-makefiles: +t:intel2018u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2018u4_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2018u4-el7 -test:intel2019-makefiles: +t:intel2019-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019-el7 -test:intel2019u1-makefiles: +t:intel2019u1-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u1_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u1-el7 -test:intel2019u2-makefiles: +t:intel2019u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u2-el7 -test:intel2019u3-makefiles: +t:intel2019u3-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u3_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u3-el7 -test:intel2019u4-makefiles: +t:intel2019u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2019u4_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2019u4-el7 -test:intel2020-makefiles: +t:intel2020-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2020_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020-el8 -test:intel2020u2-makefiles: +t:intel2020u2-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2020u2_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u2-el8 -test:intel2020u4-makefiles: +t:intel2020u4-makefiles: extends: - .cmake_test_linux_intelclassic_makefiles variables: CMAKE_CI_BUILD_NAME: intel2020u4_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2020u4-el8 -test:intel2021.1.1-makefiles: +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 -test:intel2021.1.2-makefiles: +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 -test:intel2021.2.0-makefiles: +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 -test:oneapi2021.1.1-makefiles: +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 -test:oneapi2021.1.2-makefiles: +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 -test:oneapi2021.2.0-makefiles: +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 -build:linux-x86_64-package: +b:linux-x86_64-package: extends: - .linux_package - .linux_release_x86_64 @@ -518,22 +525,22 @@ build:linux-x86_64-package: - .linux_builder_tags - .run_only_for_package dependencies: - - prep:doc-package + - p:doc-package needs: - - prep:doc-package + - p:doc-package -.upload:linux-x86_64-package: +.u:linux-x86_64-package: extends: - .rsync_upload_binary - .run_only_for_package dependencies: - - build:linux-x86_64-package + - b:linux-x86_64-package needs: - - build:linux-x86_64-package + - b:linux-x86_64-package variables: RSYNC_DESTINATION: dev -build:linux-aarch64-package: +b:linux-aarch64-package: extends: - .linux_package - .linux_release_aarch64 @@ -542,24 +549,24 @@ build:linux-aarch64-package: - .linux_builder_tags_aarch64 - .run_only_for_package dependencies: - - prep:doc-package + - p:doc-package needs: - - prep:doc-package + - p:doc-package -.upload:linux-aarch64-package: +.u:linux-aarch64-package: extends: - .rsync_upload_binary - .run_only_for_package dependencies: - - build:linux-aarch64-package + - b:linux-aarch64-package needs: - - build:linux-aarch64-package + - b:linux-aarch64-package variables: RSYNC_DESTINATION: dev ## Sanitizer builds -build:fedora34-asan: +b:fedora34-asan: extends: - .fedora34_asan - .cmake_build_linux @@ -569,22 +576,22 @@ build:fedora34-asan: variables: CMAKE_CI_JOB_NIGHTLY: "true" -test:fedora34-asan: +t:fedora34-asan: extends: - .fedora34_asan - .cmake_memcheck_linux - .linux_builder_tags_qt - .run_dependent dependencies: - - build:fedora34-asan + - b:fedora34-asan needs: - - build:fedora34-asan + - b:fedora34-asan variables: CMAKE_CI_JOB_NIGHTLY: "true" # macOS builds -build:macos-x86_64-ninja: +b:macos-x86_64-ninja: extends: - .macos_x86_64_ninja - .cmake_build_macos @@ -592,7 +599,7 @@ build:macos-x86_64-ninja: - .macos_x86_64_builder_tags - .run_manually -build:macos-arm64-ninja: +b:macos-arm64-ninja: extends: - .macos_arm64_ninja - .cmake_build_macos @@ -602,7 +609,7 @@ build:macos-arm64-ninja: variables: CMAKE_CI_NO_MR: "true" -test:macos-x86_64-ninja: +t:macos-x86_64-ninja: extends: - .macos_x86_64_ninja - .cmake_test_macos @@ -610,13 +617,13 @@ test:macos-x86_64-ninja: - .macos_x86_64_builder_tags - .run_dependent dependencies: - - build:macos-x86_64-ninja + - b:macos-x86_64-ninja needs: - - build:macos-x86_64-ninja + - b:macos-x86_64-ninja variables: CMAKE_CI_JOB_NIGHTLY_NINJA: "true" -test:macos-arm64-ninja: +t:macos-arm64-ninja: extends: - .macos_arm64_ninja - .cmake_test_macos @@ -624,13 +631,13 @@ test:macos-arm64-ninja: - .macos_arm64_builder_tags - .run_dependent dependencies: - - build:macos-arm64-ninja + - b:macos-arm64-ninja needs: - - build:macos-arm64-ninja + - b:macos-arm64-ninja variables: CMAKE_CI_NO_MR: "true" -build:macos-x86_64-makefiles: +b:macos-x86_64-makefiles: extends: - .macos_x86_64_makefiles - .cmake_build_macos @@ -638,18 +645,18 @@ build:macos-x86_64-makefiles: - .macos_x86_64_builder_tags - .run_manually -test:macos-x86_64-makefiles: +t:macos-x86_64-makefiles: extends: - .macos_x86_64_makefiles - .cmake_test_macos - .macos_x86_64_builder_tags - .run_dependent dependencies: - - build:macos-x86_64-makefiles + - b:macos-x86_64-makefiles needs: - - build:macos-x86_64-makefiles + - b:macos-x86_64-makefiles -test:macos-x86_64-xcode: +t:macos-x86_64-xcode: extends: - .macos_x86_64_xcode - .cmake_test_macos_external @@ -657,11 +664,11 @@ test:macos-x86_64-xcode: - .cmake_junit_artifacts - .run_dependent dependencies: - - test:macos-x86_64-ninja + - t:macos-x86_64-ninja needs: - - test:macos-x86_64-ninja + - t:macos-x86_64-ninja -test:macos-arm64-xcode: +t:macos-arm64-xcode: extends: - .macos_arm64_xcode - .cmake_test_macos_external @@ -669,13 +676,13 @@ test:macos-arm64-xcode: - .cmake_junit_artifacts - .run_dependent dependencies: - - test:macos-arm64-ninja + - t:macos-arm64-ninja needs: - - test:macos-arm64-ninja + - t:macos-arm64-ninja variables: CMAKE_CI_NO_MR: "true" -build:macos-package: +b:macos-package: extends: - .macos_package - .cmake_build_macos_package @@ -683,22 +690,22 @@ build:macos-package: - .macos_x86_64_builder_tags_package - .run_only_for_package dependencies: - - prep:doc-package + - p:doc-package needs: - - prep:doc-package + - p:doc-package -.upload:macos-package: +.u:macos-package: extends: - .rsync_upload_binary - .run_only_for_package dependencies: - - build:macos-package + - b:macos-package needs: - - build:macos-package + - b:macos-package variables: RSYNC_DESTINATION: dev -build:macos10.10-package: +b:macos10.10-package: extends: - .macos10.10_package - .cmake_build_macos_package @@ -706,24 +713,24 @@ build:macos10.10-package: - .macos_x86_64_builder_tags_package - .run_only_for_package dependencies: - - prep:doc-package + - p:doc-package needs: - - prep:doc-package + - p:doc-package -.upload:macos10.10-package: +.u:macos10.10-package: extends: - .rsync_upload_binary - .run_only_for_package dependencies: - - build:macos10.10-package + - b:macos10.10-package needs: - - build:macos10.10-package + - b:macos10.10-package variables: RSYNC_DESTINATION: dev # Windows builds -build:windows-vs2022-x64-ninja: +b:windows-vs2022-x64-ninja: extends: - .windows_vs2022_x64_ninja - .cmake_build_windows @@ -731,7 +738,7 @@ build:windows-vs2022-x64-ninja: - .windows_tags_nonconcurrent_vs2022 - .run_manually -test:windows-vs2022-x64-ninja: +t:windows-vs2022-x64-ninja: extends: - .windows_vs2022_x64_ninja - .cmake_test_windows @@ -739,11 +746,11 @@ test:windows-vs2022-x64-ninja: - .cmake_test_artifacts - .run_dependent dependencies: - - build:windows-vs2022-x64-ninja + - b:windows-vs2022-x64-ninja needs: - - build:windows-vs2022-x64-ninja + - b:windows-vs2022-x64-ninja -test:windows-vs2022-x64: +t:windows-vs2022-x64: extends: - .windows_vs2022_x64 - .cmake_test_windows_external @@ -751,6 +758,6 @@ test:windows-vs2022-x64: - .cmake_junit_artifacts - .run_dependent dependencies: - - test:windows-vs2022-x64-ninja + - t:windows-vs2022-x64-ninja needs: - - test:windows-vs2022-x64-ninja + - t:windows-vs2022-x64-ninja diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index ff23ac919b2..c8315307019 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -32,15 +32,15 @@ .needs_centos6_x86_64: dependencies: - - build:centos6-x86_64 + - b:centos6-x86_64 needs: - - build:centos6-x86_64 + - b:centos6-x86_64 .needs_centos7_aarch64: dependencies: - - build:centos7-aarch64 + - b:centos7-aarch64 needs: - - build:centos7-aarch64 + - b:centos7-aarch64 ### Debian diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst index 664b7a409f6..54d627dd52d 100644 --- a/Help/dev/maint.rst +++ b/Help/dev/maint.rst @@ -245,12 +245,12 @@ Commit with a message such as:: Release versions do not have the development topic section of the CMake Release Notes index page. -Update ``.gitlab-ci.yml`` to drop the ``upload:`` jobs from the +Update ``.gitlab-ci.yml`` to drop the upload jobs from the packaging pipeline by renaming them to start in ``.``: .. code-block:: shell - sed -i 's/^upload:/.upload:/' .gitlab-ci.yml + sed -i 's/^u:/.u:/' .gitlab-ci.yml Commit with a message such as:: @@ -298,7 +298,7 @@ the version date from ``origin/master``: git checkout origin/master -- \ Source/CMakeVersion.cmake Help/release/dev/0-sample-topic.rst sed -i $'/^Releases/ i\\\n.. include:: dev.txt\\\n' Help/release/index.rst - sed -i 's/^\.upload:/upload:/' .gitlab-ci.yml + sed -i 's/^\.u:/u:/' .gitlab-ci.yml Update ``Source/CMakeVersion.cmake`` to set the version to ``$major.$minor.$date``: diff --git a/Help/dev/review.rst b/Help/dev/review.rst index 198e100a951..34796a1a33e 100644 --- a/Help/dev/review.rst +++ b/Help/dev/review.rst @@ -324,6 +324,19 @@ Heavier jobs require a manual trigger to run: * ``failed``: Restart jobs which have completed, but without success. * ``completed``: Restart all completed jobs. + +In order to keep job names shorter and keep as much information visible on the +GitLab web interface as possible, jobs have a short prefix which indicates +what its main purpose is: + + * ``b:`` jobs build CMake for the purposes of running the + test suite. + * ``l:`` jobs perform "linting" on the CMake source tree such as static + analysis. + * ``p:`` jobs perform preparatory tasks for use in other jobs. + * ``t:`` jobs perform testing of CMake. + * ``u:`` jobs upload other job results to permanent locations. + If the merge request topic branch is updated by a push, a new manual trigger using one of the above methods is needed to start CI again. From 699d4a98e291b48f54b5a1996cda69b78e7c7d4f Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Wed, 24 Nov 2021 08:19:17 +1100 Subject: [PATCH 1493/1519] Help: Use definition list for allowed values of CMAKE_INSTALL_MODE Clean up the wording as well for improved consistency and clarity. --- Help/envvar/CMAKE_INSTALL_MODE.rst | 35 +++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/Help/envvar/CMAKE_INSTALL_MODE.rst b/Help/envvar/CMAKE_INSTALL_MODE.rst index 37db0d71404..be617cc2e2a 100644 --- a/Help/envvar/CMAKE_INSTALL_MODE.rst +++ b/Help/envvar/CMAKE_INSTALL_MODE.rst @@ -19,14 +19,33 @@ symbolic links instead. The following values are allowed for ``CMAKE_INSTALL_MODE``: -* empty, unset or ``COPY``: default behavior, duplicate the file at its destination -* ``ABS_SYMLINK``: create an *absolute* symbolic link to the source file at the destination *or fail* -* ``ABS_SYMLINK_OR_COPY``: like ``ABS_SYMLINK`` but silently copy on error -* ``REL_SYMLINK``: create an *relative* symbolic link to the source file at the destination *or fail* -* ``REL_SYMLINK_OR_COPY``: like ``REL_SYMLINK`` but silently copy on error -* ``SYMLINK``: try as if through ``REL_SYMLINK`` and fall back to ``ABS_SYMLINK`` if the referenced - file cannot be expressed using a relative path. Fail on error. -* ``SYMLINK_OR_COPY``: like ``SYMLINK`` but silently copy on error +``COPY``, empty or unset + Duplicate the file at its destination. This is the default behavior. + +``ABS_SYMLINK`` + Create an *absolute* symbolic link to the source file at the destination. + Halt with an error if the link cannot be created. + +``ABS_SYMLINK_OR_COPY`` + Like ``ABS_SYMLINK`` but fall back to silently copying if the symlink + couldn't be created. + +``REL_SYMLINK`` + Create a *relative* symbolic link to the source file at the destination. + Halt with an error if the link cannot be created. + +``REL_SYMLINK_OR_COPY`` + Like ``REL_SYMLINK`` but fall back to silently copying if the symlink + couldn't be created. + +``SYMLINK`` + Try as if through ``REL_SYMLINK`` and fall back to ``ABS_SYMLINK`` if the + referenced file cannot be expressed using a relative path. + Halt with an error if the link cannot be created. + +``SYMLINK_OR_COPY`` + Like ``SYMLINK`` but fall back to silently copying if the symlink couldn't + be created. Installing symbolic links rather than copying files can help conserve storage space because files do not have to be duplicated on disk. However, modifications applied to the source immediately affects From 3caeee0c86f4bf1922892734a8b3310a34e9bd90 Mon Sep 17 00:00:00 2001 From: Felix Lelchuk <felix.lelchuk@gmx.de> Date: Thu, 18 Nov 2021 04:01:10 +0100 Subject: [PATCH 1494/1519] Help: Clarify CMAKE_INSTALL_MODE documentation Fixes: #22869 Co-Authored-By: Craig Scott <craig.scott@crascit.com> --- Help/envvar/CMAKE_INSTALL_MODE.rst | 80 ++++++++++++++++++++++++++---- Modules/ExternalProject.cmake | 16 ++++++ 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/Help/envvar/CMAKE_INSTALL_MODE.rst b/Help/envvar/CMAKE_INSTALL_MODE.rst index be617cc2e2a..4549ea1498a 100644 --- a/Help/envvar/CMAKE_INSTALL_MODE.rst +++ b/Help/envvar/CMAKE_INSTALL_MODE.rst @@ -13,9 +13,22 @@ source directory into a destination directory. This environment variable however allows the user to override this behavior, causing CMake to create symbolic links instead. -.. note:: - A symbolic link consists of a reference file path rather than contents of its own, - hence there are two ways to express the relation, either by a relative or an absolute path. +Usage Scenarios +^^^^^^^^^^^^^^^ + +Installing symbolic links rather than copying files can help in the following +ways: + +* Conserving storage space because files do not have to be duplicated on disk. +* Changes to the source of the symbolic link are seen at the install + destination without having to re-run the install step. +* Editing through the link at the install destination will modify the source + of the link. This may be useful when dealing with CMake project hierarchies, + i.e. using :module:`ExternalProject` and consistent source navigation and + refactoring is desired across projects. + +Allowed Values +^^^^^^^^^^^^^^ The following values are allowed for ``CMAKE_INSTALL_MODE``: @@ -47,10 +60,57 @@ The following values are allowed for ``CMAKE_INSTALL_MODE``: Like ``SYMLINK`` but fall back to silently copying if the symlink couldn't be created. -Installing symbolic links rather than copying files can help conserve storage space because files do -not have to be duplicated on disk. However, modifications applied to the source immediately affects -the symbolic link and vice versa. *Use with caution*. - -.. note:: ``CMAKE_INSTALL_MODE`` only affects files, *not* directories. - -.. note:: Symbolic links are not available on all platforms. +.. note:: + A symbolic link consists of a reference file path rather than contents of its + own, hence there are two ways to express the relation, either by a *relative* + or an *absolute* path. + +When To Set The Environment Variable +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For the environment variable to take effect, it must be set during the correct +build phase(s). + +* If the project calls :command:`file(INSTALL)` directly, the environment + variable must be set during the configuration phase. +* In order to apply to :command:`install()`, the environment variable must be + set during installation. This could be during a build if using the + ``install`` or ``package`` build targets, or separate from the build when + invoking an install or running :manual:`cpack <cpack(1)>` from the command + line. +* When using :module:`ExternalProject`, it might be required during the build + phase, since the external project's own configure, build and install steps + will execute during the main project's build phase. + +Given the above, it is recommended to set the environment variable consistently +across all phases (configure, build and install). + +Caveats +^^^^^^^ + +Use this environment variable with caution. The following highlights some +points to be considered: + +* ``CMAKE_INSTALL_MODE`` only affects files, not directories. + +* Symbolic links are not available on all platforms. + +* The way this environment variable interacts with the install step of + :module:`ExternalProject` is more complex. For further details, see that + module's documentation. + +* A symbolic link ties the destination to the source in a persistent way. + Writing to either of the two affects both file system objects. + This is in contrast to normal install behavior which only copies files as + they were at the time the install was performed, with no enduring + relationship between the source and destination of the install. + +* Combining ``CMAKE_INSTALL_MODE`` with :prop_tgt:`IOS_INSTALL_COMBINED` is + not supported. + +* Changing ``CMAKE_INSTALL_MODE`` from what it was on a previous run can lead + to unexpected results. Moving from a non-symlinking mode to a symlinking + mode will discard any previous file at the destination, but the reverse is + not true. Once a symlink exists at the destination, even if you switch to a + non-symlink mode, the symlink will continue to exist at the destination and + will not be replaced by an actual file. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index e49faae183e..4004ea443ef 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -637,6 +637,22 @@ External Project Definition supported). Passing an empty string as the ``<cmd>`` makes the install step do nothing. + .. note:: + If the :envvar:`CMAKE_INSTALL_MODE` environment variable is set when the + main project is built, it will only have an effect if the following + conditions are met: + + * The main project's configure step assumed the external project uses + CMake as its build system. + * The external project's install command actually runs. Note that due + to the way ``ExternalProject`` may use timestamps internally, if + nothing the install step depends on needs to be re-executed, the + install command might also not need to run. + + Note also that ``ExternalProject`` does not check whether the + :envvar:`CMAKE_INSTALL_MODE` environment variable changes from one run + to another. + **Test Step Options:** The test step is only defined if at least one of the following ``TEST_...`` options are provided. From 7896991af029d66c9e1692ce18027fafaa0e9bd8 Mon Sep 17 00:00:00 2001 From: Robert Maynard <rmaynard@nvidia.com> Date: Mon, 29 Nov 2021 13:47:16 -0500 Subject: [PATCH 1495/1519] GNUInstallDirs: Prefer system lib64 over conda lib when ambiguous Update logic added by commit ecaca8c129 (GNUInstallDirs now aware of conda lib directory requirements, 2021-09-08, v3.22.0-rc1~142^2). When it is ambiguous if we are doing a conda install or a system install prefer using the system library directory. Fixes: #22962 --- Modules/GNUInstallDirs.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index 6ca424ad5df..01bd63716cf 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -253,7 +253,9 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set elseif(DEFINED ENV{CONDA_PREFIX}) set(conda_prefix "$ENV{CONDA_PREFIX}") cmake_path(ABSOLUTE_PATH conda_prefix NORMALIZE) - if("${CMAKE_INSTALL_PREFIX}" STREQUAL conda_prefix) + if("${CMAKE_INSTALL_PREFIX}" STREQUAL conda_prefix AND + NOT ("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$" OR + "${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")) set(__system_type_for_install "conda") endif() endif() From 992e6d7c5dd3a8cdf330bea9cc988d8974f5e3d5 Mon Sep 17 00:00:00 2001 From: Christoph Reiter <reiter.christoph@gmail.com> Date: Thu, 25 Nov 2021 20:17:10 +0100 Subject: [PATCH 1496/1519] mingw: fix calling convention for strftime() `strftime` uses `__cdecl` and not `__stdcall`. This was exposed by refactoring in commit 26c9fbab46 (MINGW-w64: Fix string(TIMESTAMP) build on 32bits, 2021-11-16, v3.22.0~1^2). This fixes a crash creating a timestamp with clang+mingw-w64 targeting x86. Fixes: #22939 --- Source/cmTimestamp.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index c8f5a4b2225..382657766b9 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -197,7 +197,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag, #ifdef __MINGW32__ /* See a bug in MinGW: https://sourceforge.net/p/mingw-w64/bugs/793/. A work * around is to try to use strftime() from ucrtbase.dll. */ - using T = size_t(WINAPI*)(char*, size_t, const char*, const struct tm*); + using T = size_t(__cdecl*)(char*, size_t, const char*, const struct tm*); auto loadUcrtStrftime = []() -> T { auto handle = LoadLibraryExA("ucrtbase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); From 3a9695557dc68e6520159ec69e21483a1311b420 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Sun, 28 Nov 2021 20:52:42 +1100 Subject: [PATCH 1497/1519] Help: Explicitly state that if(ENV{some_var}) is always false --- Help/command/if.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Help/command/if.rst b/Help/command/if.rst index 6ff8852a381..b4b48979221 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -61,7 +61,9 @@ Basic Expressions ``if(<variable|string>)`` True if given a variable that is defined to a value that is not a false - constant. False otherwise. (Note macro arguments are not variables.) + constant. False otherwise. Note that macro arguments are not variables. + Environment variables also cannot be tested this way, e.g. + ``if(ENV{some_var})`` will always evaluate to false. Logic Operators """"""""""""""" From 294581a4436714367093052151b501d64f6c47f3 Mon Sep 17 00:00:00 2001 From: Craig Scott <craig.scott@crascit.com> Date: Wed, 1 Dec 2021 18:59:23 +1100 Subject: [PATCH 1498/1519] Help: Be more explicit about the behavior of if(<string>) --- Help/command/if.rst | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Help/command/if.rst b/Help/command/if.rst index b4b48979221..5dba13ef3a5 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -56,15 +56,24 @@ Basic Expressions ``NO``, ``FALSE``, ``N``, ``IGNORE``, ``NOTFOUND``, the empty string, or ends in the suffix ``-NOTFOUND``. Named boolean constants are case-insensitive. If the argument is not one of these specific - constants, it is treated as a variable or string and the following - signature is used. + constants, it is treated as a variable or string (see `Variable Expansion`_ + further below) and one of the following two forms applies. -``if(<variable|string>)`` +``if(<variable>)`` True if given a variable that is defined to a value that is not a false - constant. False otherwise. Note that macro arguments are not variables. + constant. False otherwise, including if the variable is undefined. + Note that macro arguments are not variables. Environment variables also cannot be tested this way, e.g. ``if(ENV{some_var})`` will always evaluate to false. +``if(<string>)`` + A quoted string always evaluates to false unless: + + * The string's value is one of the true constants, or + * Policy :policy:`CMP0054` is not set to ``NEW`` and the string's value + happens to be a variable name that is affected by :policy:`CMP0054`'s + behavior. + Logic Operators """"""""""""""" From a35bf772dead925d5761a9be17cc020e6299ac15 Mon Sep 17 00:00:00 2001 From: Marc Chevrier <marc.chevrier@gmail.com> Date: Mon, 29 Nov 2021 12:14:43 +0100 Subject: [PATCH 1499/1519] FindPython: clarify static libraries hint usage Fixes: #22956 --- Modules/FindPython.cmake | 5 +++++ Modules/FindPython2.cmake | 5 +++++ Modules/FindPython3.cmake | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index a4b7a0385c7..375cb702732 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -229,6 +229,11 @@ Hints * If set to TRUE, search **only** for static libraries. * If set to FALSE, search **only** for shared libraries. + .. note:: + + This hint will be ignored on ``Windows`` because static libraries are not + available on this platform. + ``Python_FIND_ABI`` .. versionadded:: 3.16 diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake index bb965b9d3c0..0888fad7eac 100644 --- a/Modules/FindPython2.cmake +++ b/Modules/FindPython2.cmake @@ -215,6 +215,11 @@ Hints * If set to TRUE, search **only** for static libraries. * If set to FALSE, search **only** for shared libraries. + .. note:: + + This hint will be ignored on ``Windows`` because static libraries are not + available on this platform. + ``Python2_FIND_STRATEGY`` .. versionadded:: 3.15 diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index f826fcfe29a..145c95e11cd 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -231,6 +231,11 @@ Hints * If set to TRUE, search **only** for static libraries. * If set to FALSE, search **only** for shared libraries. + .. note:: + + This hint will be ignored on ``Windows`` because static libraries are not + available on this platform. + ``Python3_FIND_ABI`` .. versionadded:: 3.16 From 5596cba7dcb06b0641d4a5499fc046cf0959464e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 1 Dec 2021 12:30:51 -0500 Subject: [PATCH 1500/1519] cmSystemTools: Remove unnecessary mark-as-used casts to void The `CheckRPath` arguments are always used now. --- Source/cmSystemTools.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 75a5a8d8789..6320be84bfe 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -3252,8 +3252,6 @@ bool cmSystemTools::CheckRPath(std::string const& file, return false; } #endif - (void)file; - (void)newRPath; return false; } From 643fc46bdc13dd57584d5d77eee30a99308ba896 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 1 Dec 2021 12:36:07 -0500 Subject: [PATCH 1501/1519] file(RPATH): Restore tolerance of unknown formats if new RPATH is empty Since commit 2e1149874d (cmSystemTools: Support multiple binary formats, 2021-06-14, v3.22.0-rc1~575^2) the `file(RPATH_...)` operations fail on files that are not ELF or XCOFF format. Previously the RPATH operations tolerated files of unknown format if the goal was to produce a file with an empty RPATH. Restore this tolerance in order to support setting an empty RPATH on GNU ld scripts. Fixes: #22963 --- Source/cmSystemTools.cxx | 23 +++++++++++++++++-- Tests/RunCMake/file-RPATH/RunCMakeTest.cmake | 11 +++++++++ .../RunCMake/file-RPATH/TextChange-result.txt | 1 + .../RunCMake/file-RPATH/TextChange-stderr.txt | 12 ++++++++++ Tests/RunCMake/file-RPATH/TextChange.cmake | 3 +++ .../RunCMake/file-RPATH/TextChangeEmpty.cmake | 3 +++ Tests/RunCMake/file-RPATH/TextCheck.cmake | 6 +++++ .../RunCMake/file-RPATH/TextCheckEmpty.cmake | 6 +++++ Tests/RunCMake/file-RPATH/TextRemove.cmake | 3 +++ Tests/RunCMake/file-RPATH/TextSet-result.txt | 1 + Tests/RunCMake/file-RPATH/TextSet-stderr.txt | 12 ++++++++++ Tests/RunCMake/file-RPATH/TextSet.cmake | 3 +++ Tests/RunCMake/file-RPATH/TextSetEmpty.cmake | 3 +++ 13 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/file-RPATH/TextChange-result.txt create mode 100644 Tests/RunCMake/file-RPATH/TextChange-stderr.txt create mode 100644 Tests/RunCMake/file-RPATH/TextChange.cmake create mode 100644 Tests/RunCMake/file-RPATH/TextChangeEmpty.cmake create mode 100644 Tests/RunCMake/file-RPATH/TextCheck.cmake create mode 100644 Tests/RunCMake/file-RPATH/TextCheckEmpty.cmake create mode 100644 Tests/RunCMake/file-RPATH/TextRemove.cmake create mode 100644 Tests/RunCMake/file-RPATH/TextSet-result.txt create mode 100644 Tests/RunCMake/file-RPATH/TextSet-stderr.txt create mode 100644 Tests/RunCMake/file-RPATH/TextSet.cmake create mode 100644 Tests/RunCMake/file-RPATH/TextSetEmpty.cmake diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 6320be84bfe..1934393bb05 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2869,6 +2869,14 @@ bool cmSystemTools::ChangeRPath(std::string const& file, file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) { return result.value(); } + // The file format is not recognized. Assume it has no RPATH. + if (newRPath.empty()) { + // The caller wanted no RPATH anyway. + return true; + } + if (emsg) { + *emsg = "The file format is not recognized."; + } return false; } @@ -2883,6 +2891,14 @@ bool cmSystemTools::SetRPath(std::string const& file, SetRPathXCOFF(file, newRPath, emsg, changed)) { return result.value(); } + // The file format is not recognized. Assume it has no RPATH. + if (newRPath.empty()) { + // The caller wanted no RPATH anyway. + return true; + } + if (emsg) { + *emsg = "The file format is not recognized."; + } return false; } @@ -3212,7 +3228,8 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, if (cm::optional<bool> result = RemoveRPathXCOFF(file, emsg, removed)) { return result.value(); } - return false; + // The file format is not recognized. Assume it has no RPATH. + return true; } bool cmSystemTools::CheckRPath(std::string const& file, @@ -3252,7 +3269,9 @@ bool cmSystemTools::CheckRPath(std::string const& file, return false; } #endif - return false; + // The file format is not recognized. Assume it has no RPATH. + // Therefore we succeed if the new rpath is empty anyway. + return newRPath.empty(); } bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir) diff --git a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake index 1ca2e757a69..525df09c3e2 100644 --- a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake @@ -5,3 +5,14 @@ run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake) if(CMAKE_SYSTEM_NAME STREQUAL "AIX") run_cmake_command(XCOFF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/XCOFF.cmake) endif() + +run_cmake_command(TextCheck ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextCheck.cmake) +run_cmake_command(TextCheckEmpty ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextCheckEmpty.cmake) + +run_cmake_command(TextChange ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextChange.cmake) +run_cmake_command(TextChangeEmpty ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextChangeEmpty.cmake) + +run_cmake_command(TextSet ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextSet.cmake) +run_cmake_command(TextSetEmpty ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextSetEmpty.cmake) + +run_cmake_command(TextRemove ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/TextRemove.cmake) diff --git a/Tests/RunCMake/file-RPATH/TextChange-result.txt b/Tests/RunCMake/file-RPATH/TextChange-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextChange-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-RPATH/TextChange-stderr.txt b/Tests/RunCMake/file-RPATH/TextChange-stderr.txt new file mode 100644 index 00000000000..48a1bf599fa --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextChange-stderr.txt @@ -0,0 +1,12 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file-RPATH/TextChange.cmake:[0-9]+ \(file\): + file RPATH_CHANGE could not write new RPATH: + + /new/rpath + + to the file: + + [^ +]*/Tests/RunCMake/file-RPATH/TextChange-build/not_a_binary.txt + + The file format is not recognized\.$ diff --git a/Tests/RunCMake/file-RPATH/TextChange.cmake b/Tests/RunCMake/file-RPATH/TextChange.cmake new file mode 100644 index 00000000000..5c599eca278 --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextChange.cmake @@ -0,0 +1,3 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_CHANGE FILE "${f}" OLD_RPATH "/old/rpath" NEW_RPATH "/new/rpath") diff --git a/Tests/RunCMake/file-RPATH/TextChangeEmpty.cmake b/Tests/RunCMake/file-RPATH/TextChangeEmpty.cmake new file mode 100644 index 00000000000..8f855d9477b --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextChangeEmpty.cmake @@ -0,0 +1,3 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_CHANGE FILE "${f}" OLD_RPATH "/old/rpath" NEW_RPATH "") diff --git a/Tests/RunCMake/file-RPATH/TextCheck.cmake b/Tests/RunCMake/file-RPATH/TextCheck.cmake new file mode 100644 index 00000000000..1f21ba73cd4 --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextCheck.cmake @@ -0,0 +1,6 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_CHECK FILE "${f}" RPATH "/some/rpath") +if(EXISTS "${f}") + message(FATAL_ERROR "RPATH_CHECK did not remove\n ${f}\nfor non-empty RPATH") +endif() diff --git a/Tests/RunCMake/file-RPATH/TextCheckEmpty.cmake b/Tests/RunCMake/file-RPATH/TextCheckEmpty.cmake new file mode 100644 index 00000000000..806c73dae7a --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextCheckEmpty.cmake @@ -0,0 +1,6 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_CHECK FILE "${f}" RPATH "") +if(NOT EXISTS "${f}") + message(FATAL_ERROR "RPATH_CHECK removed\n ${f}\nfor empty RPATH") +endif() diff --git a/Tests/RunCMake/file-RPATH/TextRemove.cmake b/Tests/RunCMake/file-RPATH/TextRemove.cmake new file mode 100644 index 00000000000..aecaf6f4361 --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextRemove.cmake @@ -0,0 +1,3 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_REMOVE FILE "${f}") diff --git a/Tests/RunCMake/file-RPATH/TextSet-result.txt b/Tests/RunCMake/file-RPATH/TextSet-result.txt new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextSet-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-RPATH/TextSet-stderr.txt b/Tests/RunCMake/file-RPATH/TextSet-stderr.txt new file mode 100644 index 00000000000..811c9a5bfce --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextSet-stderr.txt @@ -0,0 +1,12 @@ +^CMake Error at [^ +]*/Tests/RunCMake/file-RPATH/TextSet.cmake:[0-9]+ \(file\): + file RPATH_SET could not write new RPATH: + + /new/rpath + + to the file: + + [^ +]*/Tests/RunCMake/file-RPATH/TextSet-build/not_a_binary.txt + + The file format is not recognized\.$ diff --git a/Tests/RunCMake/file-RPATH/TextSet.cmake b/Tests/RunCMake/file-RPATH/TextSet.cmake new file mode 100644 index 00000000000..f4b09d248cd --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextSet.cmake @@ -0,0 +1,3 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_SET FILE "${f}" NEW_RPATH "/new/rpath") diff --git a/Tests/RunCMake/file-RPATH/TextSetEmpty.cmake b/Tests/RunCMake/file-RPATH/TextSetEmpty.cmake new file mode 100644 index 00000000000..d9517e08c6f --- /dev/null +++ b/Tests/RunCMake/file-RPATH/TextSetEmpty.cmake @@ -0,0 +1,3 @@ +set(f "${CMAKE_CURRENT_BINARY_DIR}/not_a_binary.txt") +file(WRITE "${f}" "Not a binary.\n") +file(RPATH_SET FILE "${f}" NEW_RPATH "") From 90a49647e963f09badd2b58384b1df38788c1de3 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 2 Dec 2021 12:38:22 -0500 Subject: [PATCH 1502/1519] FindPkgConfig: Restore finding pkg-config before pkgconf Since commit 94a84dc0af (FindPkgConfig: add pkgconf to the search list., 2021-07-02, v3.22.0-rc1~468^2), `pkgconf` is preferred over `pkg-config` if they appear in the same directory. In some environments, `pkg-config` may be a wrapper that adds semantics beyond either `pkgconf` or the normal `pkg-config`. Prefer `pkg-config` over `pkgconf` in order to preserve the prior behavior in such environments. Fixes: #22976 --- Modules/FindPkgConfig.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index ef43a3ae9fa..547bc520da3 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -57,7 +57,7 @@ set(PKG_CONFIG_NAMES "pkg-config") if(CMAKE_HOST_WIN32) list(PREPEND PKG_CONFIG_NAMES "pkg-config.bat") endif() -list(PREPEND PKG_CONFIG_NAMES "pkgconf") +list(APPEND PKG_CONFIG_NAMES "pkgconf") find_program(PKG_CONFIG_EXECUTABLE NAMES ${PKG_CONFIG_NAMES} From 13a7ae2194d44f955712d65fecf0b741049da00e Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 2 Dec 2021 17:41:20 -0500 Subject: [PATCH 1503/1519] VS: Revert "Add missing label in C# project-build events" Revert commit b284a21fee (VS: Add missing label in C# project-build events, 2021-09-03, v3.22.0-rc1~156^2). The change broke cases using multiple successful custom commands. Revert it pending further investigation into the interaction of the generated script code with `Microsoft.Common.CurrentVersion.targets`, and whether this is needed for all managed projects or just C# projects. Also add a test covering the case that was broken. Fixes: #22964 Issue: #21440 --- Source/cmLocalVisualStudio7Generator.cxx | 4 ++-- Source/cmLocalVisualStudioGenerator.cxx | 11 +---------- Source/cmLocalVisualStudioGenerator.h | 6 ------ Source/cmVisualStudio10TargetGenerator.cxx | 10 ++-------- Tests/CMakeLists.txt | 1 + Tests/VSManagedCustomCommand/CMakeLists.txt | 15 +++++++++++++++ Tests/VSManagedCustomCommand/example.txt | 4 ++++ 7 files changed, 25 insertions(+), 26 deletions(-) create mode 100644 Tests/VSManagedCustomCommand/CMakeLists.txt create mode 100644 Tests/VSManagedCustomCommand/example.txt diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 5d3e11a64f1..96dda53939a 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -567,7 +567,7 @@ class cmLocalVisualStudio7Generator::EventWriter } else { this->Stream << this->LG->EscapeForXML("\n"); } - std::string script = this->LG->ConstructScript(ccg, unmanaged); + std::string script = this->LG->ConstructScript(ccg); this->Stream << this->LG->EscapeForXML(script); } @@ -1780,7 +1780,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule( } std::string comment = this->ConstructComment(ccg); - std::string script = this->ConstructScript(ccg, unmanaged); + std::string script = this->ConstructScript(ccg); if (this->FortranProject) { cmSystemTools::ReplaceString(script, "$(Configuration)", config); } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 4ed1dd92bac..03213ef1c9a 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -124,8 +124,7 @@ const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const } std::string cmLocalVisualStudioGenerator::ConstructScript( - cmCustomCommandGenerator const& ccg, IsManaged isManaged, - const std::string& newline_text) + cmCustomCommandGenerator const& ccg, const std::string& newline_text) { bool useLocal = this->CustomCommandUseLocal(); std::string workingDirectory = ccg.GetWorkingDirectory(); @@ -238,14 +237,6 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( script += newline; script += "if %errorlevel% neq 0 goto "; script += this->GetReportErrorLabel(); - if (isManaged == managed) { - // These aren't generated by default for C# projects. - script += newline; - script += this->GetReportErrorLabel(); - script += newline; - script += "exit /b 0"; - script += newline; - } } return script; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 0e7f63ff596..91fb6b06191 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -31,13 +31,7 @@ class cmLocalVisualStudioGenerator : public cmLocalGenerator virtual ~cmLocalVisualStudioGenerator(); /** Construct a script from the given list of command lines. */ - enum IsManaged - { - unmanaged, - managed - }; std::string ConstructScript(cmCustomCommandGenerator const& ccg, - IsManaged isManaged, const std::string& newline = "\n"); /** Label to which to jump in a batch file after a failed step in a diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index d2c49ae36b8..a871e4ce534 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1488,10 +1488,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( cmCustomCommandGenerator ccg(command, c, lg, true); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); - cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed) - ? cmLocalVisualStudioGenerator::managed - : cmLocalVisualStudioGenerator::unmanaged; - std::string script = lg->ConstructScript(ccg, isManaged); + std::string script = lg->ConstructScript(ccg); bool symbolic = false; // input files for custom command std::stringstream additional_inputs; @@ -4241,10 +4238,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent( comment += lg->ConstructComment(ccg); script += pre; pre = "\n"; - cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed) - ? cmLocalVisualStudioGenerator::managed - : cmLocalVisualStudioGenerator::unmanaged; - script += lg->ConstructScript(ccg, isManaged); + script += lg->ConstructScript(ccg); stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8(); } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index ecb54c7aed1..36bbc62efce 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2236,6 +2236,7 @@ if(BUILD_TESTING) if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 " AND NOT CMAKE_GENERATOR_TOOLSET) ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx) + ADD_TEST_MACRO(VSManagedCustomCommand) endif() add_test(VSExternalInclude ${CMAKE_CTEST_COMMAND} diff --git a/Tests/VSManagedCustomCommand/CMakeLists.txt b/Tests/VSManagedCustomCommand/CMakeLists.txt new file mode 100644 index 00000000000..222887511c8 --- /dev/null +++ b/Tests/VSManagedCustomCommand/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.20) +project(VSManagedCustomCommand CXX) + +add_custom_command(OUTPUT middle.txt + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/example.txt ${CMAKE_CURRENT_BINARY_DIR}/middle.txt + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example.txt + ) + +add_custom_command(OUTPUT example.cxx + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/middle.txt ${CMAKE_CURRENT_BINARY_DIR}/example.cxx + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/middle.txt + ) + +add_library(example SHARED example.cxx) +set_property(TARGET example PROPERTY COMMON_LANGUAGE_RUNTIME "") diff --git a/Tests/VSManagedCustomCommand/example.txt b/Tests/VSManagedCustomCommand/example.txt new file mode 100644 index 00000000000..05f95f1af79 --- /dev/null +++ b/Tests/VSManagedCustomCommand/example.txt @@ -0,0 +1,4 @@ +__declspec(dllexport) int example() +{ + return 0; +} From 69419c58709e8a89dbb893295ac09c5f75cd25f3 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 3 Dec 2021 09:09:04 -0500 Subject: [PATCH 1504/1519] ci: Enable more VS tests that use managed code A couple of VS tests were conditioned on `NOT CMAKE_GENERATOR_TOOLSET`, but in CI jobs with VS we always set `CMAKE_GENERATOR_TOOLSET`. Make the condition specific to excluding the `v90` toolset, which was its original intention anyway. --- Tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 36bbc62efce..8b38080fdd3 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2234,7 +2234,7 @@ if(BUILD_TESTING) endif() if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 " - AND NOT CMAKE_GENERATOR_TOOLSET) + AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v90") ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx) ADD_TEST_MACRO(VSManagedCustomCommand) endif() From d4ba945c48a3af674bdd95157d18d6236f7c2472 Mon Sep 17 00:00:00 2001 From: Raphael Gozzo <raphael.rg91@gmail.com> Date: Mon, 6 Dec 2021 15:03:10 -0300 Subject: [PATCH 1505/1519] CMakeParseLibraryArchitecture: Fix parsing /lib/<arch> implicit object path The current regular expression is able to match `/usr/lib/<arch>`, `/usr/usr/lib/<arch>`, `/usr/usr/usr/lib/<arch>`, ... but not `/lib/<arch>`. This behavior ends up causing the detected architecture to be x86_64-pc-linux-gnu when the Clang compiler is installed on a "non-system" location (like /opt/llvm-13) which, in turn, makes almost every 'find_library()' fail because the correct architecture is x86_64-linux-gnu. This is due to a typo in commit 764606e256 (CMakeDetermineCompilerABI: Extract lib arch from implicit object file paths, 2021-04-05, v3.20.1~10^2), which used `+` instead of `?`. --- Modules/CMakeParseLibraryArchitecture.cmake | 2 +- .../linux-custom_clang-C-Clang-13.0.0.input | 56 ++++++++++++++++++ .../linux-custom_clang-CXX-Clang-13.0.0.input | 58 +++++++++++++++++++ .../ParseImplicitIncludeInfo.cmake | 1 + .../linux-custom_clang-C-Clang-13.0.0.output | 1 + ...linux-custom_clang-CXX-Clang-13.0.0.output | 1 + .../ParseImplicitLinkInfo.cmake | 1 + .../linux-custom_clang-C-Clang-13.0.0.output | 3 + ...linux-custom_clang-CXX-Clang-13.0.0.output | 3 + 9 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/ParseImplicitData/linux-custom_clang-C-Clang-13.0.0.input create mode 100644 Tests/RunCMake/ParseImplicitData/linux-custom_clang-CXX-Clang-13.0.0.input create mode 100644 Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-C-Clang-13.0.0.output create mode 100644 Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output create mode 100644 Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-C-Clang-13.0.0.output create mode 100644 Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output diff --git a/Modules/CMakeParseLibraryArchitecture.cmake b/Modules/CMakeParseLibraryArchitecture.cmake index 6fb9c6bfced..f7a4b29c349 100644 --- a/Modules/CMakeParseLibraryArchitecture.cmake +++ b/Modules/CMakeParseLibraryArchitecture.cmake @@ -23,7 +23,7 @@ function(cmake_parse_library_architecture lang implicit_dirs implicit_objs outpu foreach(obj IN LISTS implicit_objs) get_filename_component(dir "${obj}" DIRECTORY) - if("${dir}" MATCHES "(/usr)+/lib/${CMAKE_LIBRARY_ARCHITECTURE_REGEX}$") + if("${dir}" MATCHES "(/usr)?/lib/${CMAKE_LIBRARY_ARCHITECTURE_REGEX}$") get_filename_component(arch "${dir}" NAME) set(library_arch "${arch}") break() diff --git a/Tests/RunCMake/ParseImplicitData/linux-custom_clang-C-Clang-13.0.0.input b/Tests/RunCMake/ParseImplicitData/linux-custom_clang-C-Clang-13.0.0.input new file mode 100644 index 00000000000..a80592c1030 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitData/linux-custom_clang-C-Clang-13.0.0.input @@ -0,0 +1,56 @@ +CMAKE_LANG=C +CMAKE_LINKER=/opt/llvm-13/bin/ld.lld +CMAKE_C_COMPILER_ABI=ELF +CMAKE_C_COMPILER_AR=/opt/llvm-13/bin/llvm-ar +CMAKE_C_COMPILER_ARCHITECTURE_ID= +CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN= +CMAKE_C_COMPILER_ID=Clang +CMAKE_C_COMPILER_LAUNCHER= +CMAKE_C_COMPILER_LOADED=1 +CMAKE_C_COMPILER_RANLIB=/opt/llvm-13/bin/llvm-ranlib +CMAKE_C_COMPILER_TARGET= +CMAKE_C_COMPILER_VERSION=13.0.0 +CMAKE_C_COMPILER_VERSION_INTERAL= +Change Dir: /tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/make -f Makefile cmTC_91833/fast && /usr/bin/make -f CMakeFiles/cmTC_91833.dir/build.make CMakeFiles/cmTC_91833.dir/build +make[1]: Entering directory '/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o +/opt/llvm-13/bin/clang -v -MD -MT CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o -MF CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o.d -o CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o -c /opt/cmake-3.21.3/share/cmake-3.21/Modules/CMakeCCompilerABI.c +clang version 13.0.0 +Target: x86_64-pc-linux-gnu +Thread model: posix +InstalledDir: /opt/llvm-13/bin +Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Candidate multilib: .@m64 +Candidate multilib: 32@m32 +Candidate multilib: x32@mx32 +Selected multilib: .@m64 + (in-process) + "/opt/llvm-13/bin/clang-13" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all --mrelax-relocations -disable-free -main-file-name CMakeCCompilerABI.c -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -v -fcoverage-compilation-dir=/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp -resource-dir /opt/llvm-13/lib/clang/13.0.0 -dependency-file CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o -sys-header-deps -internal-isystem /opt/llvm-13/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp -ferror-limit 19 -fgnuc-version=4.2.1 -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o -x c /opt/cmake-3.21.3/share/cmake-3.21/Modules/CMakeCCompilerABI.c +clang -cc1 version 13.0.0 based upon LLVM 13.0.0 default target x86_64-pc-linux-gnu +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" +ignoring nonexistent directory "/include" +#include "..." search starts here: +#include <...> search starts here: + /opt/llvm-13/lib/clang/13.0.0/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include +End of search list. +Linking C executable cmTC_91833 +/opt/cmake-3.21.3/bin/cmake -E cmake_link_script CMakeFiles/cmTC_91833.dir/link.txt --verbose=1 +/opt/llvm-13/bin/clang -v -rdynamic CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o -o cmTC_91833 +clang version 13.0.0 +Target: x86_64-pc-linux-gnu +Thread model: posix +InstalledDir: /opt/llvm-13/bin +Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Candidate multilib: .@m64 +Candidate multilib: 32@m32 +Candidate multilib: x32@mx32 +Selected multilib: .@m64 + "/opt/llvm-13/bin/ld.lld" -export-dynamic -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_91833 /lib/x86_64-linux-gnu/crt1.o /lib/x86_64-linux-gnu/crti.o /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/clang_rt.crtbegin.o -L/opt/llvm-13/bin/../lib/x86_64-pc-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/opt/llvm-13/bin/../lib -L/lib -L/usr/lib CMakeFiles/cmTC_91833.dir/CMakeCCompilerABI.c.o /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/libclang_rt.builtins.a --as-needed -l:libunwind.so --no-as-needed -lc /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/libclang_rt.builtins.a --as-needed -l:libunwind.so --no-as-needed /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/clang_rt.crtend.o /lib/x86_64-linux-gnu/crtn.o +make[1]: Leaving directory '/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp' diff --git a/Tests/RunCMake/ParseImplicitData/linux-custom_clang-CXX-Clang-13.0.0.input b/Tests/RunCMake/ParseImplicitData/linux-custom_clang-CXX-Clang-13.0.0.input new file mode 100644 index 00000000000..e65639006a9 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitData/linux-custom_clang-CXX-Clang-13.0.0.input @@ -0,0 +1,58 @@ +CMAKE_LANG=CXX +CMAKE_LINKER=/opt/llvm-13/bin/ld.lld +CMAKE_CXX_COMPILER_ABI=ELF +CMAKE_CXX_COMPILER_AR=/opt/llvm-13/bin/llvm-ar +CMAKE_CXX_COMPILER_ARCHITECTURE_ID= +CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN= +CMAKE_CXX_COMPILER_ID=Clang +CMAKE_CXX_COMPILER_LAUNCHER= +CMAKE_CXX_COMPILER_LOADED=1 +CMAKE_CXX_COMPILER_RANLIB=/opt/llvm-13/bin/llvm-ranlib +CMAKE_CXX_COMPILER_TARGET= +CMAKE_CXX_COMPILER_VERSION=13.0.0 +CMAKE_CXX_COMPILER_VERSION_INTERAL= +Change Dir: /tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/make -f Makefile cmTC_5372b/fast && /usr/bin/make -f CMakeFiles/cmTC_5372b.dir/build.make CMakeFiles/cmTC_5372b.dir/build +make[1]: Entering directory '/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o +/opt/llvm-13/bin/clang++ -v -MD -MT CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o -MF CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o.d -o CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o -c /opt/cmake-3.21.3/share/cmake-3.21/Modules/CMakeCXXCompilerABI.cpp +clang version 13.0.0 +Target: x86_64-pc-linux-gnu +Thread model: posix +InstalledDir: /opt/llvm-13/bin +Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Candidate multilib: .@m64 +Candidate multilib: 32@m32 +Candidate multilib: x32@mx32 +Selected multilib: .@m64 + (in-process) + "/opt/llvm-13/bin/clang-13" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all --mrelax-relocations -disable-free -main-file-name CMakeCXXCompilerABI.cpp -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -v -fcoverage-compilation-dir=/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp -resource-dir /opt/llvm-13/lib/clang/13.0.0 -dependency-file CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o.d -MT CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o -sys-header-deps -internal-isystem /opt/llvm-13/bin/../include/x86_64-pc-linux-gnu/c++/v1 -internal-isystem /opt/llvm-13/bin/../include/c++/v1 -internal-isystem /opt/llvm-13/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -fdebug-compilation-dir=/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o -x c++ /opt/cmake-3.21.3/share/cmake-3.21/Modules/CMakeCXXCompilerABI.cpp +clang -cc1 version 13.0.0 based upon LLVM 13.0.0 default target x86_64-pc-linux-gnu +ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" +ignoring nonexistent directory "/include" +#include "..." search starts here: +#include <...> search starts here: + /opt/llvm-13/bin/../include/x86_64-pc-linux-gnu/c++/v1 + /opt/llvm-13/bin/../include/c++/v1 + /opt/llvm-13/lib/clang/13.0.0/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include +End of search list. +Linking CXX executable cmTC_5372b +/opt/cmake-3.21.3/bin/cmake -E cmake_link_script CMakeFiles/cmTC_5372b.dir/link.txt --verbose=1 +/opt/llvm-13/bin/clang++ -v -rdynamic CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_5372b +clang version 13.0.0 +Target: x86_64-pc-linux-gnu +Thread model: posix +InstalledDir: /opt/llvm-13/bin +Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9 +Candidate multilib: .@m64 +Candidate multilib: 32@m32 +Candidate multilib: x32@mx32 +Selected multilib: .@m64 + "/opt/llvm-13/bin/ld.lld" -export-dynamic -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTC_5372b /lib/x86_64-linux-gnu/crt1.o /lib/x86_64-linux-gnu/crti.o /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/clang_rt.crtbegin.o -L/opt/llvm-13/bin/../lib/x86_64-pc-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/opt/llvm-13/bin/../lib -L/lib -L/usr/lib CMakeFiles/cmTC_5372b.dir/CMakeCXXCompilerABI.cpp.o -lc++ -lm /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/libclang_rt.builtins.a -l:libunwind.so -lc /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/libclang_rt.builtins.a -l:libunwind.so /opt/llvm-13/lib/clang/13.0.0/lib/x86_64-pc-linux-gnu/clang_rt.crtend.o /lib/x86_64-linux-gnu/crtn.o +make[1]: Leaving directory '/tmp/cmake/Tests/RunCMake/ParseImplicitData/build/CMakeFiles/CMakeTmp' diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake b/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake index e501f122e5d..75c26a7a17d 100644 --- a/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/ParseImplicitIncludeInfo.cmake @@ -38,6 +38,7 @@ set(targets linux-C-XL-16.1.0.0 linux-CXX-XL-16.1.0.0 linux-CUDA-NVIDIA-10.1.168-CLANG linux-CUDA-NVIDIA-10.1.168-XLClang-v-empty linux-CUDA-NVIDIA-9.2.148-GCC + linux-custom_clang-C-Clang-13.0.0 linux-custom_clang-CXX-Clang-13.0.0 mingw.org-C-GNU-4.9.3 mingw.org-CXX-GNU-4.9.3 netbsd-C-GNU-4.8.5 netbsd-CXX-GNU-4.8.5 netbsd_nostdinc-C-GNU-4.8.5 netbsd_nostdinc-CXX-GNU-4.8.5 diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-C-Clang-13.0.0.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-C-Clang-13.0.0.output new file mode 100644 index 00000000000..2435c62fb84 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-C-Clang-13.0.0.output @@ -0,0 +1 @@ +/opt/llvm-13/lib/clang/13.0.0/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include diff --git a/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output new file mode 100644 index 00000000000..de5a3689c99 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitIncludeInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output @@ -0,0 +1 @@ +/opt/llvm-13/include/x86_64-pc-linux-gnu/c\+\+/v1;/opt/llvm-13/include/c\+\+/v1;/opt/llvm-13/lib/clang/13.0.0/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake index dcdc7f1b96c..51c88325f82 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake +++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake @@ -38,6 +38,7 @@ set(targets linux-C-XL-16.1.0.0 linux-CXX-XL-16.1.0.0 linux-CUDA-NVIDIA-10.1.168-CLANG linux-CUDA-NVIDIA-10.1.168-XLClang-v linux-CUDA-NVIDIA-9.2.148-GCC + linux-custom_clang-C-Clang-13.0.0 linux-custom_clang-CXX-Clang-13.0.0 mingw.org-C-GNU-4.9.3 mingw.org-CXX-GNU-4.9.3 netbsd-C-GNU-4.8.5 netbsd-CXX-GNU-4.8.5 netbsd_nostdinc-C-GNU-4.8.5 netbsd_nostdinc-CXX-GNU-4.8.5 diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-C-Clang-13.0.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-C-Clang-13.0.0.output new file mode 100644 index 00000000000..108712d5653 --- /dev/null +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-C-Clang-13.0.0.output @@ -0,0 +1,3 @@ +libs=-l:libunwind.so;c;-l:libunwind.so +dirs=/opt/llvm-13/lib/x86_64-pc-linux-gnu;/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib64;/lib/x86_64-linux-gnu;/lib64;/usr/lib/x86_64-linux-gnu;/opt/llvm-13/lib;/lib;/usr/lib +library_arch=x86_64-linux-gnu diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output new file mode 100644 index 00000000000..e4a8a70ebcd --- /dev/null +++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-custom_clang-CXX-Clang-13.0.0.output @@ -0,0 +1,3 @@ +libs=c\+\+;m;-l:libunwind.so;c;-l:libunwind.so +dirs=/opt/llvm-13/lib/x86_64-pc-linux-gnu;/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib64;/lib/x86_64-linux-gnu;/lib64;/usr/lib/x86_64-linux-gnu;/opt/llvm-13/lib;/lib;/usr/lib +library_arch=x86_64-linux-gnu From bed4b1583ec29383621f9c81e5c3223c12110cfe Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 3 Dec 2021 11:18:50 -0500 Subject: [PATCH 1506/1519] Utilities/Release: Add script to sign/notarize macOS application bundle We produce macOS binaries for `cmake.org` using GitLab CI jobs. Binaries for official releases are additionally signed and notarized manually by a maintainer with suitable signing certificates and Apple developer account credentials. Add a script to drive these steps. --- Utilities/Release/macos/sign-notarize.bash | 118 +++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100755 Utilities/Release/macos/sign-notarize.bash diff --git a/Utilities/Release/macos/sign-notarize.bash b/Utilities/Release/macos/sign-notarize.bash new file mode 100755 index 00000000000..377eceddea7 --- /dev/null +++ b/Utilities/Release/macos/sign-notarize.bash @@ -0,0 +1,118 @@ +#!/usr/bin/env bash +set -e +readonly usage='usage: sign-notarize.bash -i <id> -d <dev-acct> -k <key-item> [-p <provider>] [--] <package>.dmg + +Sign and notarize the "CMake.app" bundle inside the given "<package>.dmg" disk image. +Also produce a "<package>.tar.gz" tarball containing the same "CMake.app". + +Options: + + -i <id> Signing Identity + -d <dev-acct> Developer account name + -k <key-item> Keychain item containing account credentials + -p <provider> Provider short name +' + +cleanup() { + if test -d "$tmpdir"; then + rm -rf "$tmpdir" + fi + if test -d "$vol_path"; then + hdiutil detach "$vol_path" + fi +} + +trap "cleanup" EXIT + +die() { + echo "$@" 1>&2; exit 1 +} + +id='' +dev_acct='' +key_item='' +provider='' +while test "$#" != 0; do + case "$1" in + -i) shift; id="$1" ;; + -d) shift; dev_acct="$1" ;; + -k) shift; key_item="$1" ;; + -p) shift; provider="$1" ;; + --) shift ; break ;; + -*) die "$usage" ;; + *) break ;; + esac + shift +done +case "$1" in +*.dmg) readonly dmg="$1"; shift ;; +*) die "$usage" ;; +esac +test "$#" = 0 || die "$usage" + +# Verify arguments. +if test -z "$id" -o -z "$dev_acct" -o -z "$key_item"; then + die "$usage" +fi +if test -n "$provider"; then + provider="--provider $provider" +fi + +# Verify environment. +if ! xcnotary="$(type -p xcnotary)"; then + die "'xcnotary' not found in PATH" +fi +readonly xcnotary + +readonly tmpdir="$(mktemp -d)" + +# Prepare entitlements. +readonly entitlements_xml="$tmpdir/entitlements.xml" +echo '<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.cs.allow-dyld-environment-variables</key> + <true/> +</dict> +</plist>' > "$entitlements_xml" + +# Extract SLA +readonly sla_xml="$tmpdir/sla.xml" +hdiutil udifderez -xml "$dmg" > "$sla_xml" +plutil -remove 'blkx' "$sla_xml" +plutil -remove 'plst' "$sla_xml" + +# Convert from read-only original image to read-write. +readonly udrw_dmg="$tmpdir/udrw.dmg" +hdiutil convert "$dmg" -format UDRW -o "${udrw_dmg}" + +# Mount the temporary udrw image. +readonly vol_name="$(basename "${dmg%.dmg}")" +readonly vol_path="/Volumes/$vol_name" +hdiutil attach "${udrw_dmg}" + +codesign --verify --timestamp --options=runtime --verbose --deep \ + -s "$id" \ + --entitlements "$entitlements_xml" \ + "$vol_path/CMake.app/Contents/bin/cmake" \ + "$vol_path/CMake.app/Contents/bin/ccmake" \ + "$vol_path/CMake.app/Contents/bin/ctest" \ + "$vol_path/CMake.app/Contents/bin/cpack" \ + "$vol_path/CMake.app/Contents/share/cmake"*"/Modules/Internal/CPack/CPack.OSXScriptLauncher.in" \ + "$vol_path/CMake.app" + +xcnotary notarize "$vol_path/CMake.app" -d "$dev_acct" -k "$key_item" $provider + +# Create a tarball of the volume next to the original disk image. +readonly tar_gz="${dmg/%.dmg/.tar.gz}" +tar cvzf "$tar_gz" -C /Volumes "$vol_name/CMake.app" + +# Unmount the modified udrw image. +hdiutil detach "$vol_path" + +# Convert back to read-only, compressed image. +hdiutil convert "${udrw_dmg}" -format UDZO -imagekey zlib-level=9 -ov -o "$dmg" + +# Re-insert SLA. +hdiutil udifrez -xml "${sla_xml}" 'FIXME_WHY_IS_THIS_ARGUMENT_NEEDED' "$dmg" From b59f7600c409e08fb872705d795d37f014e02453 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 6 Dec 2021 13:02:16 -0500 Subject: [PATCH 1507/1519] HIP: Enable CMAKE_EXPORT_COMPILE_COMMANDS for HIP Fixes: #22986 --- Source/cmMakefileTargetGenerator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 8edadd31e7c..f5f3727e511 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -888,7 +888,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( bool lang_has_preprocessor = ((lang == "C") || (lang == "CXX") || (lang == "OBJC") || (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA") || - lang == "ISPC" || lang == "ASM"); + lang == "ISPC" || lang == "HIP" || lang == "ASM"); bool const lang_has_assembly = lang_has_preprocessor; bool const lang_can_export_cmds = lang_has_preprocessor; From aa6a33fe54918967f6ffcad30773e01664e8a2b2 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Tue, 7 Dec 2021 10:44:21 -0500 Subject: [PATCH 1508/1519] CMake 3.22.1 --- Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3d999e7ca18..489d2ecc901 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 22) -set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_PATCH 1) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) From 43844c5d82398c443a7f1d4c7aea23d470d1a6e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= <tomas.hrnciar@me.com> Date: Tue, 7 Dec 2021 14:34:24 +0100 Subject: [PATCH 1509/1519] FindPython: Add support for Python 3.11 --- Modules/FindPython/Support.cmake | 2 +- Modules/FindPythonInterp.cmake | 2 +- Modules/FindPythonLibs.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index ce25cfc7093..b7a0ef6bdbf 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -22,7 +22,7 @@ if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) message (FATAL_ERROR "FindPython: INTERNAL ERROR") endif() if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3") - set(_${_PYTHON_PREFIX}_VERSIONS 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) + set(_${_PYTHON_PREFIX}_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2") set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) else() diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake index efe0f11901b..4fc40c89dc8 100644 --- a/Modules/FindPythonInterp.cmake +++ b/Modules/FindPythonInterp.cmake @@ -54,7 +54,7 @@ unset(_Python_NAMES) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonInterp_FIND_VERSION) if(PythonInterp_FIND_VERSION_COUNT GREATER 1) diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake index 396f0d2ed40..c0caf347b69 100644 --- a/Modules/FindPythonLibs.cmake +++ b/Modules/FindPythonLibs.cmake @@ -79,7 +79,7 @@ set(CMAKE_FIND_FRAMEWORK LAST) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonLibs_FIND_VERSION) if(PythonLibs_FIND_VERSION_COUNT GREATER 1) From 38b00f88014a0866e2aa650550977b4bc676b355 Mon Sep 17 00:00:00 2001 From: Ryan Prichard <rprichard@google.com> Date: Fri, 10 Dec 2021 21:23:17 -0800 Subject: [PATCH 1510/1519] Android: Fix linking android_support for pre-21 system STL This typo was introduced in commit 4dca078829 (Android: Link c++abi and android_support when necessary, 2020-10-29, v3.20.0-rc1~541^2). Fixes: #23004 --- Modules/Platform/Android-Common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake index 39da933003e..f1deaca63e0 100644 --- a/Modules/Platform/Android-Common.cmake +++ b/Modules/Platform/Android-Common.cmake @@ -56,7 +56,7 @@ if(CMAKE_ANDROID_STL_TYPE) if(_ANDROID_STL_EXCEPTIONS OR _ANDROID_STL_RTTI) string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -lc++abi") if(CMAKE_SYSTEM_VERSION LESS 21) - list(APPEND CMAKE_${lang}_STANDARD_LIBRARIES "-landroid_support") + string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -landroid_support") endif() endif() endmacro() From d176ff71c03f62d993d2fbad6aa416e64e336453 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 15 Dec 2021 10:16:59 -0500 Subject: [PATCH 1511/1519] FindBoost: Add support for Boost 1.78 Update the list of known versions. Run the command cmake -DBOOST_DIR=/path/to/boost_1_78_0 \ -P Utilities/Scripts/BoostScanDeps.cmake to extract dependencies from the 1.78.0 source tree. The dependencies differ from those of 1.77: * The `log` component no longer depends on `date_time`. Fixes: #23016 --- Modules/FindBoost.cmake | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 38faca24aaf..0ad342f0e6a 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -1350,7 +1350,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - else() + elseif(Boost_VERSION_STRING VERSION_LESS 1.78.0) set(_Boost_CONTRACT_DEPENDENCIES thread chrono) set(_Boost_COROUTINE_DEPENDENCIES context) set(_Boost_FIBER_DEPENDENCIES context) @@ -1365,6 +1365,21 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) + else() + set(_Boost_CONTRACT_DEPENDENCIES thread chrono) + set(_Boost_COROUTINE_DEPENDENCIES context) + set(_Boost_FIBER_DEPENDENCIES context) + set(_Boost_IOSTREAMS_DEPENDENCIES regex) + set(_Boost_JSON_DEPENDENCIES container) + set(_Boost_LOG_DEPENDENCIES log_setup filesystem thread regex chrono atomic) + set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) + set(_Boost_MPI_DEPENDENCIES serialization) + set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) + set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) + set(_Boost_THREAD_DEPENDENCIES chrono atomic) + set(_Boost_TIMER_DEPENDENCIES chrono) + set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic) + set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.78.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() @@ -1638,7 +1653,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" + "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" From 612c0d49f4042303b2c666ec8ca6d02deea637a4 Mon Sep 17 00:00:00 2001 From: "William R. Dieter" <william.r.dieter@intel.com> Date: Wed, 8 Dec 2021 21:33:25 -0800 Subject: [PATCH 1512/1519] VS: Fix detecting icx.exe with Intel Compiler toolsets newer than 2021 The logic added by commit 7808cbd644 (CMakeDetermineCompilerId: support Intel DPC++ compiler toolset for VS gen, 2020-12-06, v3.20.0-rc1~330^2) matches a specific toolset known to be the `icx.exe` compiler, and assumes all other Intel C++ compilers (that are not DPC++) must be `icl.exe`. Since `icx.exe` is officially replacing `icl.exe`, use a regex that matches the now-fixed set of toolsets known to use `icl.exe`. Any other Intel C++ compiler will be assumed to be `icx.exe`. Signed-off-by: William R. Dieter <william.r.dieter@intel.com> --- Modules/CMakeDetermineCompilerId.cmake | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 30b4aec90b6..e564517c0b9 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -319,15 +319,13 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} set(id_cl "$(CLToolExe)") elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") set(id_cl clang.exe) - # Executable names have been chosen according documentation - # URL: (https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-dpcpp-compiler/top.html#top_GUID-A9B4C91D-97AC-450D-9742-9D895BC8AEE1) elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel") if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "DPC\\+\\+ Compiler") set(id_cl dpcpp.exe) - elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler 2021") - set(id_cl icx.exe) - elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler") + elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler ([8-9]\\.|1[0-9]\\.|XE)") set(id_cl icl.exe) + elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler") + set(id_cl icx.exe) endif() else() set(id_cl cl.exe) From 840fa28d3d308828ebc3516e436f2f9c7ee5bfa1 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Thu, 16 Dec 2021 07:46:48 -0500 Subject: [PATCH 1513/1519] ci: Explicitly disable Java tests on Windows Avoid searching for a Java installation on Windows hosts. This will allow some CI hosts to have Java for other projects. We already do this on macOS. While at it, clarify the macOS setting. --- .gitlab/ci/configure_macos_common.cmake | 2 +- .gitlab/ci/configure_windows_common.cmake | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab/ci/configure_macos_common.cmake b/.gitlab/ci/configure_macos_common.cmake index 37cd51c2052..e78c9cec334 100644 --- a/.gitlab/ci/configure_macos_common.cmake +++ b/.gitlab/ci/configure_macos_common.cmake @@ -2,7 +2,7 @@ # detect that Java is available and working, but a test machine then not have a # working Java installed. To work around this, just act as if Java is not # available on any CI machine. -set(CMake_TEST_Java 0 CACHE FILEPATH "") +set(CMake_TEST_Java OFF CACHE BOOL "") # Qt binaries get placed inside the source directory, which causes them to not # be included in the install-time rpath, but we still want them in the diff --git a/.gitlab/ci/configure_windows_common.cmake b/.gitlab/ci/configure_windows_common.cmake index 45250acbe20..112846a9ad8 100644 --- a/.gitlab/ci/configure_windows_common.cmake +++ b/.gitlab/ci/configure_windows_common.cmake @@ -1,4 +1,5 @@ set(BUILD_QtDialog ON CACHE BOOL "") set(CMAKE_PREFIX_PATH "$ENV{CI_PROJECT_DIR}/.gitlab/qt" CACHE STRING "") +set(CMake_TEST_Java OFF CACHE BOOL "") include("${CMAKE_CURRENT_LIST_DIR}/configure_common.cmake") From d4bb6c0c7fe8e3ee5aaa275cf939d074f959119b Mon Sep 17 00:00:00 2001 From: Oleg Sidorkin <osidorkin@gmail.com> Date: Thu, 16 Dec 2021 21:24:00 +0300 Subject: [PATCH 1514/1519] FindBoost: Add support for Python 3.10 Regexps in FindBoost assumed that python's minor version had only one digit. That became not true for 3.10. Fixes: #23025 --- Modules/FindBoost.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 0ad342f0e6a..75cbbf56bc7 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -390,7 +390,7 @@ cmake_policy(SET CMP0102 NEW) # if mark_as_advanced(non_cache_var) function(_boost_get_existing_target component target_var) set(names "${component}") - if(component MATCHES "^([a-z_]*)(python|numpy)([1-9])\\.?([0-9])?$") + if(component MATCHES "^([a-z_]*)(python|numpy)([1-9])\\.?([0-9]+)?$") # handle pythonXY and numpyXY versioned components and also python X.Y, mpi_python etc. list(APPEND names "${CMAKE_MATCH_1}${CMAKE_MATCH_2}" # python @@ -407,7 +407,7 @@ function(_boost_get_existing_target component target_var) if(TARGET "${prefix}::${name}") # The target may be an INTERFACE library that wraps around a single other # target for compatibility. Unwrap this layer so we can extract real info. - if("${name}" MATCHES "^(python|numpy|mpi_python)([1-9])([0-9])$") + if("${name}" MATCHES "^(python|numpy|mpi_python)([1-9])([0-9]+)$") set(name_nv "${CMAKE_MATCH_1}") if(TARGET "${prefix}::${name_nv}") get_property(type TARGET "${prefix}::${name}" PROPERTY TYPE) @@ -430,7 +430,7 @@ endfunction() function(_boost_get_canonical_target_name component target_var) string(TOLOWER "${component}" component) - if(component MATCHES "^([a-z_]*)(python|numpy)([1-9])\\.?([0-9])?$") + if(component MATCHES "^([a-z_]*)(python|numpy)([1-9])\\.?([0-9]+)?$") # handle pythonXY and numpyXY versioned components and also python X.Y, mpi_python etc. set(${target_var} "Boost::${CMAKE_MATCH_1}${CMAKE_MATCH_2}" PARENT_SCOPE) else() @@ -1004,7 +1004,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) # against the new release. # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") + if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9]+)\$") set(component "${CMAKE_MATCH_1}") set(component_python_version "${CMAKE_MATCH_2}") endif() @@ -1408,7 +1408,7 @@ endfunction() # function(_Boost_COMPONENT_HEADERS component _hdrs) # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") + if(component MATCHES "^(python|mpi_python|numpy)([0-9]+|[0-9]\\.[0-9]+)\$") set(component "${CMAKE_MATCH_1}") set(component_python_version "${CMAKE_MATCH_2}") endif() @@ -2165,7 +2165,7 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) if(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\$") set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - elseif(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\\.?([0-9])\$") + elseif(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\\.?([0-9]+)\$") set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") set(COMPONENT_PYTHON_VERSION_MINOR "${CMAKE_MATCH_3}") From ae6b25d920325585f0e7f56d23d2b0f8e0b39af8 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Fri, 17 Dec 2021 12:59:51 -0500 Subject: [PATCH 1515/1519] FindGLUT: Provide legacy GLUT_INCLUDE_DIR result in pkg-config code path Since commit f90d15458a (FindGLUT: Use pkg-config to find flags if available, 2021-06-11, v3.22.0-rc1~469^2) we return early if pkg-config provides the information. During review of that commit, code to populate the legacy `GLUT_INCLUDE_DIR` result variable was removed from that code path. Add code to provide it. Also fix the test case to use `GLUT_INCLUDE_DIR`, the result variable documented officially by the module. Fixes: #23018 --- Modules/FindGLUT.cmake | 2 ++ Tests/FindGLUT/Test/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index dd0975d3951..636f1ea3b14 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -71,6 +71,8 @@ find_package(PkgConfig) if(PKG_CONFIG_FOUND) pkg_check_modules(GLUT glut) if(GLUT_FOUND) + # In the non-pkg-config code path we only provide GLUT_INCLUDE_DIR. + set(GLUT_INCLUDE_DIR "${GLUT_INCLUDE_DIRS}") _add_glut_target_simple() FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_FOUND) return() diff --git a/Tests/FindGLUT/Test/CMakeLists.txt b/Tests/FindGLUT/Test/CMakeLists.txt index 0f4e5367397..f6440b250f3 100644 --- a/Tests/FindGLUT/Test/CMakeLists.txt +++ b/Tests/FindGLUT/Test/CMakeLists.txt @@ -9,7 +9,7 @@ target_link_libraries(testglut_tgt GLUT::GLUT) add_test(NAME testglut_tgt COMMAND testglut_tgt) add_executable(testglut_var main.c) -target_include_directories(testglut_var PRIVATE ${GLUT_INCLUDE_DIRS}) +target_include_directories(testglut_var PRIVATE ${GLUT_INCLUDE_DIR}) target_link_libraries(testglut_var PRIVATE ${GLUT_LIBRARIES}) add_test(NAME testglut_var COMMAND testglut_var) From d45667d45943e1b768b25921f8e481cfafa487a4 Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Mon, 20 Dec 2021 09:03:05 -0500 Subject: [PATCH 1516/1519] FindBoost: Do not warn about now-supported version 1.78 In commit d176ff71c0 (FindBoost: Add support for Boost 1.78, 2021-12-15) we forgot to update the future-version check. Issue: #23016 --- Modules/FindBoost.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 75cbbf56bc7..c3142d66aac 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -1380,7 +1380,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.78.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) + if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.79.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() endif() From 85a07b4b49a88facc04035cb9f4b30f5c4ee28ac Mon Sep 17 00:00:00 2001 From: Brad King <brad.king@kitware.com> Date: Wed, 22 Dec 2021 03:50:01 -0500 Subject: [PATCH 1517/1519] ci: Explicitly disable Java tests on VS builds Extend the change from commit 840fa28d3d (ci: Explicitly disable Java tests on Windows, 2021-12-16) to cover VS builds too. --- .gitlab/ci/configure_windows_vs2022_x64.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab/ci/configure_windows_vs2022_x64.cmake b/.gitlab/ci/configure_windows_vs2022_x64.cmake index f6ece57c884..7c024a8e09b 100644 --- a/.gitlab/ci/configure_windows_vs2022_x64.cmake +++ b/.gitlab/ci/configure_windows_vs2022_x64.cmake @@ -1,3 +1,4 @@ set(CMake_TEST_WIX_NO_VERIFY "ON" CACHE BOOL "") +set(CMake_TEST_Java OFF CACHE BOOL "") include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") From c2777ed00854ce692e4bc83f5c4f5774efd9cd65 Mon Sep 17 00:00:00 2001 From: Jukka Jalkanen <1000jalkanen@gmail.com> Date: Tue, 28 Dec 2021 14:25:04 +0200 Subject: [PATCH 1518/1519] ASM: Fix identification of armasm 6.17+ Spelling of "ARM Compiler" changed to "Arm Compiler". --- Modules/CMakeDetermineASMCompiler.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index a1814b7dd81..d03cbef010f 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -104,7 +104,7 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS ARMCC) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMCC ) - set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)|(Arm Compiler)") list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS NASM) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_NASM "-v") From b0ea75ece2ab2d784a7d8e564da431a6475ca9c5 Mon Sep 17 00:00:00 2001 From: bebenlebricolo <benoittarrade@hotmail.fr> Date: Fri, 21 Jan 2022 14:34:20 +0100 Subject: [PATCH 1519/1519] Adapted AtmelStudio generators code to new CMake cmProp -> cmValue propertie handling Signed-off-by: bebenlebricolo <benoittarrade@hotmail.fr> --- .../cmAtmelStudio7TargetGenerator.cxx | 16 +++++----- .../cmAtmelStudio7TargetGenerator.h | 2 +- .../cmGlobalAtmelStudio7Generator.cxx | 29 +++++++++---------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.cxx b/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.cxx index a9549f790bf..72af05dacf9 100644 --- a/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.cxx +++ b/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.cxx @@ -173,11 +173,11 @@ std::vector<std::string> cmAtmelStudio7TargetGenerator::GetDefines(const std::st return out; } -std::vector<std::string> cmAtmelStudio7TargetGenerator::ConvertStringRange(const cmStringRange& range) const +std::vector<std::string> cmAtmelStudio7TargetGenerator::ConvertBTStringRange(const cmBTStringRange& range) const { std::vector<std::string> out; for (auto& val : range) { - out.push_back(val); + out.push_back(val.Value); } return out; } @@ -214,12 +214,12 @@ std::unordered_map<std::string, std::vector<std::string>> cmAtmelStudio7TargetGe std::string flag_variable_config_name = flag_variable_name + "_" + upConfig; std::string lang_standard_varname = "CMAKE_" + lang + "_STANDARD"; - cmProp lang_flags_base = this->Makefile->GetDefinition(flag_variable_name); - cmProp lang_flags_config = this->Makefile->GetDefinition(flag_variable_config_name); - cmProp lang_standard_def = this->Makefile->GetDefinition(lang_standard_varname); + cmValue lang_flags_base = this->Makefile->GetDefinition(flag_variable_name); + cmValue lang_flags_config = this->Makefile->GetDefinition(flag_variable_config_name); + cmValue lang_standard_def = this->Makefile->GetDefinition(lang_standard_varname); - auto compile_definitions = ConvertStringRange(this->Makefile->GetCompileDefinitionsEntries()); - auto compile_options = ConvertStringRange(this->Makefile->GetCompileOptionsEntries()); + auto compile_definitions = ConvertBTStringRange(this->Makefile->GetCompileDefinitionsEntries()); + auto compile_options = ConvertBTStringRange(this->Makefile->GetCompileOptionsEntries()); std::vector<std::string> base_flags; std::vector<std::string> config_flags; @@ -592,7 +592,7 @@ void cmAtmelStudio7TargetGenerator::BuildProjectReferenceItemGroup(pugi::xml_nod cmLocalGenerator* lg = dependent_target->GetLocalGenerator(); std::string name = dependent_target->GetName(); std::string path; - cmProp p = dependent_target->GetProperty("EXTERNAL_MSPROJECT"); + cmValue p = dependent_target->GetProperty("EXTERNAL_MSPROJECT"); if (p != nullptr) { path = *p; } else { diff --git a/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.h b/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.h index 684e792af91..be160d30c9f 100644 --- a/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.h +++ b/Source/AtmelStudio7Generators/cmAtmelStudio7TargetGenerator.h @@ -233,7 +233,7 @@ class cmAtmelStudio7TargetGenerator * @param range : Cmake's StringRange object * @return a collection of strings */ - std::vector<std::string> ConvertStringRange(const cmStringRange& range) const; + std::vector<std::string> ConvertBTStringRange(const cmBTStringRange& range) const; /** * @brief Builds a configuration group and attaches its xml representation to the parent node. diff --git a/Source/AtmelStudio7Generators/cmGlobalAtmelStudio7Generator.cxx b/Source/AtmelStudio7Generators/cmGlobalAtmelStudio7Generator.cxx index 71da28c45b4..223232957b1 100644 --- a/Source/AtmelStudio7Generators/cmGlobalAtmelStudio7Generator.cxx +++ b/Source/AtmelStudio7Generators/cmGlobalAtmelStudio7Generator.cxx @@ -313,7 +313,7 @@ void cmGlobalAtmelStudio7Generator::OutputATSLNFile( std::string cmGlobalAtmelStudio7Generator::GetStartupProjectName( cmLocalGenerator const* root) const { - cmProp n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); + cmValue n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT"); if (cmNonempty(n)) { std::string startup = *n; if (this->FindTarget(startup)) { @@ -343,7 +343,7 @@ bool cmGlobalAtmelStudio7Generator::FindMakeProgram(cmMakefile*) std::string cmGlobalAtmelStudio7Generator::GetGUID(std::string const& name) { std::string const& guidStoreName = name + "_GUID_CMAKE"; - cmProp storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName); + cmValue storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName); if (nullptr != storedGUID) { return std::string(*storedGUID); @@ -492,7 +492,7 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand> cmGlobalAtmelStudio7Generat // Written by the toolchain file - cmProp compiler; + cmValue compiler; switch (CurrentPlatform) { case AvailablePlatforms::AVR8: @@ -513,7 +513,7 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand> cmGlobalAtmelStudio7Generat } // Select the caller- or user-preferred make program, else MSBuild. - cmProp AtmelStudioPath = this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_ATMEL_STUDIO_EXECUTABLE"); + cmValue AtmelStudioPath = this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_ATMEL_STUDIO_EXECUTABLE"); if (!AtmelStudioPath) { GeneratedMakeCommand makeCommand; makeCommand.Add("Could not find CMAKE_ATMEL_STUDIO_EXECUTABLE in cache !"); @@ -552,11 +552,10 @@ void cmGlobalAtmelStudio7Generator::WriteTargetsToSolution( bool written = false; - cmProp projName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue projName = target->GetProperty("GENERATOR_FILE_NAME"); if (projName) { cmLocalGenerator* lg = target->GetLocalGenerator(); - std::string dir = lg->GetCurrentBinaryDirectory(); - dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir); + std::string dir = root->MaybeRelativeToCurBinDir(rootBinaryDir); if (dir == ".") { dir.clear(); // msbuild cannot handle ".\" prefix } @@ -602,7 +601,7 @@ void cmGlobalAtmelStudio7Generator::WriteProject(std::ostream& fout, const char* project = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""; - cmProp targetExt = target_gen->GetProperty("GENERATOR_FILE_NAME_EXT"); + cmValue targetExt = target_gen->GetProperty("GENERATOR_FILE_NAME_EXT"); if (targetExt) { ext = *targetExt; } @@ -645,17 +644,17 @@ void cmGlobalAtmelStudio7Generator::WriteTargetConfigurations( if (!target->IsInBuildSystem()) { continue; } - cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT"); + cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT"); if (expath) { std::set<std::string> allConfigurations(configs.begin(), configs.end()); - cmProp mapping = target->GetProperty("VS_PLATFORM_MAPPING"); + cmValue mapping = target->GetProperty("VS_PLATFORM_MAPPING"); this->WriteProjectConfigurations(fout, target->GetName(), *target, configs, allConfigurations, mapping ? *mapping : ""); } else { const std::set<std::string>& configsPartOfDefaultBuild = this->IsPartOfDefaultBuild(configs, projectTargets, target); - cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { this->WriteProjectConfigurations(fout, *vcprojName, *target, configs, configsPartOfDefaultBuild); @@ -675,7 +674,7 @@ void cmGlobalAtmelStudio7Generator::WriteProjectConfigurations( std::vector<std::string> mapConfig; const char* dstConfig = i.c_str(); if (target.GetProperty("EXTERNAL_MSPROJECT")) { - if (cmProp m = target.GetProperty("MAP_IMPORTED_CONFIG_" + + if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" + cmSystemTools::UpperCase(i))) { cmExpandList(*m, mapConfig); if (!mapConfig.empty()) { @@ -744,7 +743,7 @@ void cmGlobalAtmelStudio7Generator::WriteATSLNGlobalSections( extensibilityAddInsOverridden = true; } fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; - cmProp p = root->GetMakefile()->GetProperty(it); + cmValue p = root->GetMakefile()->GetProperty(it); std::vector<std::string> keyValuePairs = cmExpandedList(p ? *p : ""); for (std::string const& itPair : keyValuePairs) { const std::string::size_type posEqual = itPair.find('='); @@ -801,7 +800,7 @@ std::set<std::string> cmGlobalAtmelStudio7Generator::IsPartOfDefaultBuild( "CMAKE_VS_INCLUDE_" + t + "_TO_DEFAULT_BUILD"; // inspect CMAKE_VS_INCLUDE_<t>_TO_DEFAULT_BUILD properties for (std::string const& i : configs) { - cmProp propertyValue = + cmValue propertyValue = target->Target->GetMakefile()->GetDefinition(propertyName); if (propertyValue && cmIsOn(cmGeneratorExpression::Evaluate( @@ -867,4 +866,4 @@ bool cmGlobalAtmelStudio7Generator::TargetCompare::operator()( return true; } return l->GetName() < r->GetName(); -} \ No newline at end of file +}